2 /*******************************************************************************
3 * Copyright (c) 2012-2013 University of Stuttgart.
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License v1.0
6 * and the Apache License 2.0 which both accompany this distribution,
7 * and are available at http://www.eclipse.org/legal/epl-v10.html
8 * and http://www.apache.org/licenses/LICENSE-2.0
11 * Oliver Kopp - initial API and implementation and/or initial documentation
12 * Yves Schubert - port to bootstrap 3
13 *******************************************************************************/
15 <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
16 <%@taglib prefix="t" tagdir="/WEB-INF/tags" %>
17 <%@taglib prefix="ct" tagdir="/WEB-INF/tags/common" %>
18 <%@taglib prefix="p" tagdir="/WEB-INF/tags/parameters" %>
19 <%@taglib prefix="w" uri="http://www.eclipse.org/winery/repository/functions"%>
21 <%@page import="org.eclipse.winery.common.Util" %>
22 <%@page import="org.eclipse.winery.repository.Constants" %>
24 <link type="text/css" href="${pageContext.request.contextPath}/components/bootstrap-switch/build/css/bootstrap3/bootstrap-switch.css" rel="stylesheet" />
25 <script type="text/javascript" src="${pageContext.request.contextPath}/components/bootstrap-switch/build/js/bootstrap-switch.js"></script>
27 <%-- include basic parameters support --%>
28 <p:parametersJS afterLoad="interfaceSelectionChanged();"></p:parametersJS>
31 <%final String URI_LIFECYCLE_INTERFACE = "http://www.example.com/interfaces/lifecycle";%>
32 var URI_LIFECYCLE_INTERFACE = "<%=URI_LIFECYCLE_INTERFACE%>";
35 * @param noUpdate if given, then the selection is not updated. This is required when Winery itself creates interfaces without user intervention. For instance, that is the case at the lifecycle interface
37 function afterInterfaceCreation(serializedArray, resData, textStatus, jqXHR, noUpdate) {
38 var text = serializedArray[0].value;
39 if (text == URI_LIFECYCLE_INTERFACE) {
40 // lifecycle interface has been generated
41 // disable button to generate lifecycle interface
42 $("#generatelifecycleifacetn").attr("disabled", "disabled");
44 addSortedSelectionItem($("#interfaces"), text, text);
46 interfaceSelectionChanged();
50 function afterOperationCreation(serializedArray, resData, textStatus, jqXHR) {
51 var text = serializedArray[0].value;
52 addSortedSelectionItem($("#operations"), text, text);
53 operationSelectionChanged();
56 function getIfaceURL() {
57 var iface = $("#interfaces").find(":selected").val();
58 return "${it.urlPrefix}interfaces/" + encodeID(iface) + "/";
61 function getOperationURL() {
62 var op = $("#operations").find(":selected").val();
63 return getIfaceURL() + "operations/" + encodeID(op) + "/";
66 function createInterface() {
67 createResource('Interface', [{'label': 'Name', 'name':'interfaceName'}], '${it.urlPrefix}interfaces/', afterInterfaceCreation);
70 function createOperation() {
71 var url = getIfaceURL() + "operations/";
72 createResource('Operation', [{'label':'Name', 'name':'name'}], url, afterOperationCreation);
75 function disableAllOperationButtons() {
76 $("#addOpBtn").attr("disabled", "disabled");
77 $("#removeOpBtn").attr("disabled", "disabled");
80 function disableAllInputButtons() {
81 $("#addInParBtn").attr("disabled", "disabled");
82 $("#removeInParBtn").attr("disabled", "disabled");
85 function disableAllOutputButtons() {
86 $("#addOutParBtn").attr("disabled", "disabled");
87 $("#removeOutParBtn").attr("disabled", "disabled");
90 function interfaceSelectionChanged(noupdate) {
91 iface = $("#interfaces").find(":selected");
92 if (iface.length == 0) {
94 $("#operations").empty();
95 inputParametersTableInfo.table.fnClearTable();
96 outputParametersTableInfo.table.fnClearTable();
97 disableAllOperationButtons();
98 disableAllInputButtons();
99 disableAllOutputButtons();
100 $("#removeIfBtn").attr("disabled", "disabled");
101 $("#generateiabtn").attr("disabled", "disabled");
104 "url": getIfaceURL() + "operations/",
106 success: function(data, textStatus, jqXHR) {
107 var operations = $("#operations");
109 $.each(data, function(number, item) {
112 selected = ' selected="selected"';
116 operations.append('<option value="' + item + '"' + selected + '>' + item + '</option>');
118 operationSelectionChanged();
119 $("#removeIfBtn").removeAttr("disabled");
120 $("#generateiabtn").removeAttr("disabled");
126 function operationSelectionChanged() {
127 if ($("#operations").find(":selected").length == 0) {
128 inputParametersTableInfo.table.fnClearTable();
129 outputParametersTableInfo.table.fnClearTable();
130 disableAllInputButtons();
131 disableAllOutputButtons();
132 $("#removeOpBtn").attr("disabled", "disabled");
133 if ($("#interfaces").children("option").length == 0) {
134 // no interfaces available
135 $("#addOpBtn").attr("disabled", "disabled");
137 $("#addOpBtn").removeAttr("disabled");
140 updateInputAndOutputParameters(getOperationURL());
141 $("#addOpBtn").removeAttr("disabled");
142 $("#removeOpBtn").removeAttr("disabled");
147 function determineNextItemToSelect(currentItem) {
149 nextToSelect = currentItem.next();
150 if (nextToSelect.length == 0) {
151 nextToSelect = currentItem.prev();
152 // even if nothing found, the following code works:
153 // X.attr("selected", "selected") does not throw any error if X is empty
158 function deleteThing(thingId, thingName, urlDetermination, changedFunction) {
159 var thing = $("#" + thingId).find(":selected");
160 if (thing.length == 0) {
161 vShowError("UI in wrong state");
164 thingName + " " + thing.text(),
167 nextToSelect = determineNextItemToSelect(thing);
169 nextToSelect.attr("selected", "selected");
176 function deleteInterface() {
177 var iface = $("#interfaces").find(":selected").text();
179 // if the lifecycle interface is going to be removed,
180 // enable the button to generate the lifecycle interface again
182 if (iface == URI_LIFECYCLE_INTERFACE) {
183 changedFunction = function() {
184 $("#generatelifecycleifacetn").removeAttr("disabled");
185 interfaceSelectionChanged();
188 changedFunction = interfaceSelectionChanged;
191 deleteThing("interfaces", "Interface", getIfaceURL, changedFunction);
194 function deleteOperation() {
195 deleteThing("operations", "Operation", getOperationURL, operationSelectionChanged);
198 function createArtifactTemplate() {
199 // we use the quick way at implementationartifacts/ to auto-generate an artifact template
200 // see org.eclipse.winery.repository.resources.artifacts.GenericArtifactsResource<ArtifactResource, ArtifactT> for the REST-interface description;
202 var url = getTypeImplementationURL() + "implementationartifacts/";
203 var data = $("#artifactTemplateNS, #artifactTemplateName, #autoCreateArtifactTemplate, #artifactType, #autoGenerateIA, #interfaces, #javapackage").serialize();
205 // we use the artifact template name as artifact name
206 var artifactName = $("#artifactTemplateName").serialize();
207 artifactName = "artifact" + artifactName.substring(16);
208 data = data + "&" + artifactName;
214 }).fail(function(jqXHR, textStatus, errorThrown) {
215 vShowAJAXError("Could not create artifact template", jqXHR, errorThrown);
216 $("#generateiabtn").button("reset");
217 }).done(function(data, textStatus, jqXHR) {
218 var location = jqXHR.getResponseHeader("location");
220 vShowSuccess('Successfully generated IA. It is currently downloaded and available <a href="' + location + '/../../">here</a>');
222 // open the downloaded file
223 window.open(location, "_blank");
225 $("#generateiamodal").modal("hide");
229 function generateIA() {
230 $("#generateiabtn").button("loading");
232 // create type implementation if necessary
233 var typeImplementationHasToBeCreated = $("#nodeTypeImplCreationSwitch").bootstrapSwitch('status'); // "status" instead of "state" (!)
234 if (typeImplementationHasToBeCreated) {
235 var url = "${pageContext.request.contextPath}/${it.relationshipTypeOrNodeTypeURLFragment}implementations/";
236 var data = $("#nodetypeimplementationName, #nodetypeimplementationNS, #qnameOfType").serialize();
241 }).fail(function(jqXHR, textStatus, errorThrown) {
242 vShowAJAXError("Could not create type implementation", jqXHR, errorThrown);
243 $("#generateiabtn").button("reset");
245 createArtifactTemplate();
248 createArtifactTemplate();
253 $("#generateiamodal").on("show.bs.modal", function() {
254 // check whether the required artifact type exists
256 url: "${pageContext.request.contextPath}/artifacttypes/<%=Util.DoubleURLencode(Constants.NAMESPACE_ARTIFACTTYPE_WAR)%>/<%=Util.DoubleURLencode(Constants.LOCALNAME_ARTIFACTTYPE_WAR)%>/",
258 }).fail(function(jqXHR, textStatus, errorThrown) {
259 if (jqXHR.status == 404) {
260 vShowError("WAR artifact type does not exist. Please create artifact type WAR");
261 $("#generateiabtn").attr("disabled", "disabled");
263 vShowAJAXError("Could not check for existance of WAR artifact type", jqXHR, errorThrown);
265 }).success(function() {
266 $("#generateiabtn").removeAttr("disabled");
269 // dialog is reset at each show
270 $("#generateiabtn").button("reset");
273 $("#javapackage").val("${w:namespaceToJavaPackage(it.namespace)}");
275 // set node type implementation name
276 $("#nodetypeimplementationName").val("${it.name}_impl");
278 // reset node type implementation namespace
279 $("#nodetypeimplementationNS").val("${it.namespace}").attr("selected", "selected");
281 // the default type impl could exist
282 checkNodeTypeImplName();
284 // reset artifact template namespace
285 $("#artifactTemplateNS").val("${it.namespace}").attr("selected", "selected");
287 require(["artifacttemplateselection", "winery-support"], function(ats, ws) {
288 // set artifact template name
289 var iface = $("#interfaces").find(":selected");
290 var initialATName = "${it.name}_" + ws.makeNCName(iface.text()) + "_IA";
291 $("#artifactTemplateName").val(initialATName);
293 // check if artifact template is a valid name
294 ats.checkArtifactTemplateName();
298 $("#nodetypeimplementationNS").on("blur", checkNodeTypeImplName).on("change", checkNodeTypeImplName).on("focus", flagNodeTypeImplAsUpdating);
299 $("#nodetypeimplementationName").typing({
300 start: function(event, $elem) {
301 flagNodeTypeImplAsUpdating();
303 stop: function(event, $elem) {
304 checkNodeTypeImplName();
310 <%-- adapted from artifacttemplateselection.tag --%>
312 function getTypeImplementationURL() {
313 var ns = $("#nodetypeimplementationNS").val();
314 var name = $("#nodetypeimplementationName").val();
315 var url = "${pageContext.request.contextPath}/${it.relationshipTypeOrNodeTypeURLFragment}implementations/" + encodeID(ns) + "/" + encodeID(name) + "/";
319 function checkNodeTypeImplName() {
320 var name = $("#nodetypeimplementationName").val();
323 var invalidReason = "No name provided";
324 // TODO: setNodeTypeImplNameValidityStatus(valid, invalidReason);
326 url = getTypeImplementationURL();
330 error: function(jqXHR, textStatus, errorThrown) {
331 if (jqXHR.status == 404) {
332 // node type implementation does not exist
333 $("#nodeTypeImplCreationSwitch").bootstrapSwitch('setState', true);
335 vShowAJAXError("Could not check for type implementation existance", jqXHR, errorThrown);
336 // Alternative: setValidityStatus(false, textStatus);
339 success: function(data, textStatus, jqXHR) {
340 // node type implementation exists
341 $("#nodeTypeImplCreationSwitch").bootstrapSwitch('setState', false);
347 function flagNodeTypeImplAsUpdating() {
348 // not yet implemented
351 function generateLifeCycleInterface() {
352 var data = "interfaceName=" + encodeURIComponent(URI_LIFECYCLE_INTERFACE);
354 url: '${it.urlPrefix}interfaces/',
357 }).fail(function(jqXHR, textStatus, errorThrown) {
358 vShowAJAXError("Could not create interface", jqXHR, errorThrown);
359 }).done(function(data, textStatus, jqXHR) {
360 var serializedArray = [{value:URI_LIFECYCLE_INTERFACE}];
361 afterInterfaceCreation(serializedArray, data, textStatus, jqXHR, true);
363 var operations = ["install", "configure", "start", "stop", "uninstall"];
364 var errorOccurred = false;
366 $(operations).each(function(i, operationName) {
367 // we have to go through one-by-one to keep the order of operations
368 // no parallel creation possible
369 // Therefore also "async: false" at the AJAX call
371 var data = "name=" + operationName;
373 var url = getIfaceURL() + "operations/";
379 }).fail(function(jqXHR, textStatus, errorThrown) {
380 vShowAJAXError("Could not create operation " + operationName, jqXHR, errorThrown);
381 errorOccurred = true;
382 }).done(function(data, textStatus, jqXHR) {
383 serializedArray = [{value:operationName}];
384 afterOperationCreation(serializedArray, data, textStatus, jqXHR);
388 if (!errorOccurred) {
389 vShowSuccess('Successfully generated lifecycle interface');
396 <div id="generateiamodal" class="modal fade">
397 <div class="modal-dialog">
398 <div class="modal-content">
399 <div class="modal-header">
400 <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
401 <h4 class="modal-title">Generate Implementation Artifact</h4>
403 <div class="modal-body">
405 <div class="form-group">
406 <label for="javapackage">Java Package</label>
407 <input class="form-control" id="javapackage" name="javapackage" placeholder="Enter java package name" required="required">
410 <div class="form-group-grouping typeimplementation">
411 <div class="form-group">
412 <label for="nodetypeimplementationName">${it.relationshipTypeOrNodeType} Implementation Name</label>
413 <input required="required" class="form-control" id="nodetypeimplementationName" name="name" placeholder="Enter name for node type implementation" pattern="[\i-[:]][\c-[:]]*"><!-- name is an NCName -->
416 <t:namespaceChooser nameOfInput="namespace" idOfInput="nodetypeimplementationNS" allNamespaces="${w:allNamespaces()}" selected="${it.namespace}"></t:namespaceChooser>
418 <div id="nodeTypeImplCreationSwitch" class="make-switch" data-on-label="will be created" data-off-label="will be reused" style="height:30px; width:250px;">
419 <input type="checkbox" disabled="disabled" checked="checked">
422 <input type="hidden" name="type" id="qnameOfType" value="${it.typeQName}">
425 <p class="text-warning">There is no check for the name of the implementation artifact. The artifact template name will be reused as implementation artifact name without any further check.</p>
427 <ct:artifacttemplateselection repositoryURL="${pageContext.request.contextPath}" defaultNSForArtifactTemplate="${it.namespace}" allNamespaces="${w:allNamespaces()}"></ct:artifacttemplateselection>
428 <input type="hidden" name="autoCreateArtifactTemplate" value="true" id="autoCreateArtifactTemplate">
430 <div class="form-group">
431 <label for="artifacttype">Artifact Type</label>
432 <a class="form-control" target="_blank" href="${pageContext.request.contextPath}/artifacttypes/<%=Util.DoubleURLencode(Constants.NAMESPACE_ARTIFACTTYPE_WAR)%>/<%=Util.DoubleURLencode(Constants.LOCALNAME_ARTIFACTTYPE_WAR)%>/">WAR</a>
433 <input type="hidden" name="artifactType" id="artifactType" value="{<%=Constants.NAMESPACE_ARTIFACTTYPE_WAR%>}<%=Constants.LOCALNAME_ARTIFACTTYPE_WAR%>">
436 <input type="hidden" name="autoGenerateIA" id="autoGenerateIA" value="true">
439 <div class="modal-footer">
440 <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
441 <button type="button" class="btn btn-primary" id="generateiabtn" onclick="generateIA();" data-loading-text="Generating...">Generate</button>
443 </div><!-- /.modal-content -->
444 </div><!-- /.modal-dialog -->
445 </div><!-- /.modal -->
448 <div><!-- we do not use bootstrap's "container" as the container leads to an overflow -->
449 <div class="col-xs-4 bordered">
450 <div class="listheading">
451 <button class="rightbutton btn btn-danger btn-xs" type="button" onclick="deleteInterface();" disabled="disabled" id="removeIfBtn">Remove</button>
452 <button class="rightbutton btn btn-primary btn-xs" type="button" onclick="createInterface();" id="addIfBtn">Add</button>
453 <label>Interfaces</label>
455 <select class="listcontent" id="interfaces" size="18" onchange="interfaceSelectionChanged();" name="interfaceName">
456 <c:set var="generatelifcecycleifactebtnDisabled" value=""></c:set>
457 <c:set var="URI_LIFECYCLE_INTERFACE" value="<%=URI_LIFECYCLE_INTERFACE%>"></c:set>
458 <!-- ${URI_LIFECYCLE_INTERFACE} -->
459 <c:forEach var="iface" varStatus="count" items="${it.listOfAllEntityIdsAsList}">
460 <c:set var="selected" value=""></c:set>
461 <c:if test="${count.index == 0}">
462 <c:set var="selected" value=" selected=\"selected\""></c:set>
464 <c:if test="${iface == URI_LIFECYCLE_INTERFACE}">
465 <c:set var="generatelifcecycleifactebtnDisabled" value=" disabled=\"disabled\""></c:set>
467 <option value="${iface}"${selected}>${iface}</option>
470 <button id="generateiabtn" class="btn btn-default btn-xs" data-toggle="modal" data-target="#generateiamodal">Generate Implementation Artifact</button>
471 <button id="generatelifecycleifacetn" class="btn btn-default btn-xs" onclick="generateLifeCycleInterface();"${generatelifcecycleifactebtnDisabled}>Generate lifecycle interface</button>
474 <div class="col-xs-4 middlebox bordered">
475 <div class="listheading">
476 <button class="rightbutton btn btn-danger btn-xs" type="button" onclick="deleteOperation();" id="removeOpBtn">Remove</button>
477 <button class="rightbutton btn btn-primary btn-xs" type="button" onclick="createOperation();" id="addOpBtn">Add</button>
478 <label>Operations</label>
480 <select class="listcontent" id="operations" size="18" onchange="operationSelectionChanged();">
484 <div class="col-xs-4 bordered">
485 <p:parametersInput baseURL="getOperationURL()"></p:parametersInput>
487 <p:parametersOutput baseURL="getOperationURL()"></p:parametersOutput>