summaryrefslogtreecommitdiffstats
path: root/winery/org.eclipse.winery.repository/src/main/webapp/jsp/servicetemplates
diff options
context:
space:
mode:
Diffstat (limited to 'winery/org.eclipse.winery.repository/src/main/webapp/jsp/servicetemplates')
-rw-r--r--winery/org.eclipse.winery.repository/src/main/webapp/jsp/servicetemplates/boundarydefinitions/boundarydefinitions.jsp1080
-rw-r--r--winery/org.eclipse.winery.repository/src/main/webapp/jsp/servicetemplates/plans/plans.jsp266
-rw-r--r--winery/org.eclipse.winery.repository/src/main/webapp/jsp/servicetemplates/selfservicemetadata/selfservicemetadata.jsp256
-rw-r--r--winery/org.eclipse.winery.repository/src/main/webapp/jsp/servicetemplates/servicetemplate.jsp43
-rw-r--r--winery/org.eclipse.winery.repository/src/main/webapp/jsp/servicetemplates/topologytemplates/topologytemplate.jsp23
-rw-r--r--winery/org.eclipse.winery.repository/src/main/webapp/jsp/servicetemplates/topologytemplates/topologytemplateview.jsp67
6 files changed, 1735 insertions, 0 deletions
diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/jsp/servicetemplates/boundarydefinitions/boundarydefinitions.jsp b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/servicetemplates/boundarydefinitions/boundarydefinitions.jsp
new file mode 100644
index 0000000..aadec72
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/servicetemplates/boundarydefinitions/boundarydefinitions.jsp
@@ -0,0 +1,1080 @@
+<%--
+/*******************************************************************************
+ * Copyright (c) 2013 University of Stuttgart.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ * Oliver Kopp - initial API and implementation and/or initial documentation
+ * Tobias Binz - communication with the nested iframe
+ *******************************************************************************/
+--%>
+
+<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
+<%@taglib prefix="w" tagdir="/WEB-INF/tags"%>
+<%@taglib prefix="o" tagdir="/WEB-INF/tags/common/orioneditor"%>
+<%@taglib prefix="b" tagdir="/WEB-INF/tags/servicetemplates/boundarydefinitions"%>
+<%@taglib prefix="pol" tagdir="/WEB-INF/tags/common/policies" %>
+<%@taglib prefix="wc" uri="http://www.eclipse.org/winery/functions"%>
+<%@taglib prefix="wr" uri="http://www.eclipse.org/winery/repository/functions"%>
+
+<%@page import="org.eclipse.winery.common.ModelUtilities"%>
+
+<pol:policydiag allPolicyTypes="${it.allPolicyTypes}" repositoryURL="${it.repositoryURL}" />
+
+<b:browseForServiceTemplatePropertyReqOrCap definedPropertiesAsJSONString="${it.definedPropertiesAsJSONString}" />
+
+<div class="modal fade" id="propertyMappingDiag">
+ <div class="modal-dialog">
+ <div class="modal-content">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
+ <h4 class="modal-title">Add property mapping</h4>
+ </div>
+ <div class="modal-body">
+ <form id="propertyMappingForm" enctype="multipart/form-data">
+ <fieldset>
+ <div class="form-group">
+ <label for="serviceTemplatePropertyRef">Service Template Property</label>
+ <div class="row">
+ <div class="col-xs-10">
+ <input name="serviceTemplatePropertyRef" id="serviceTemplatePropertyRef" class="form-control" type="text" required="required">
+ </div>
+ <div class="col-xs-2">
+ <button type="button" class="btn btn-default btn-sm" onclick="browseForServiceTemplateProperty($('#serviceTemplatePropertyRef'));">Browse</button>
+ </div>
+ </div>
+ </div>
+
+ <div class="form-group">
+ <label for="targetObjectRef">Target: Node Template, Requirement, Capability, or Relationship Template</label>
+ <div class="row">
+ <div class="col-xs-4">
+ <input name="targetObjectRef" id="targetObjectRef" class="form-control" type="text" required="required">
+ </div>
+ <div class="col-xs-2">
+ <button type="button" class="btn btn-default btn-sm" onclick="browseForTemplateAndProperty();">Browse</button>
+ </div>
+ </div>
+ </div>
+
+ <div class="form-group">
+ <label for="targetPropertyRef">Target Property</label>
+ <input name="targetPropertyRef" id="targetPropertyRef" class="form-control" type="text" required="required"/>
+ </div>
+ </fieldset>
+ </form>
+ </div>
+
+ <div class="modal-footer">
+ <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
+ <button id="addPropertyMapping" type="button" class="btn btn-primary" onclick="addPropertyMapping()">Add</button>
+ <button id="updatePropertyMapping" type="button" class="btn btn-primary" onclick="updatePropertyMapping()">Update</button>
+ </div>
+ </div>
+ </div>
+</div>
+
+<div class="modal fade" id="propertyConstraintDiag">
+ <div class="modal-dialog">
+ <div class="modal-content">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
+ <h4 class="modal-title">Add property constraint</h4>
+ </div>
+ <div class="modal-body">
+ <form id="propertyMappingForm" enctype="multipart/form-data">
+ <fieldset>
+ <div class="form-group">
+ <label for="serviceTemplatePropertyRef">Service Template Property</label>
+ <div class="row">
+ <div class="col-xs-10">
+ <input name="serviceTemplatePropertyRef" id="serviceTemplatePropertyRefForConstraint" class="form-control" type="text" />
+ </div>
+ <div class="col-xs-2">
+ <button type="button" class="btn btn-default btn-sm" onclick="browseForServiceTemplateProperty($('#serviceTemplatePropertyRefForConstraint'));">Browse</button>
+ </div>
+ </div>
+ </div>
+
+ <w:typeswithshortnameasselect label="Constraint Type" selectname="constraintType" type="constrainttype" typesWithShortNames="${it.constraintTypes}"/>
+
+ <div class="form-group">
+ ... constraint fragment ...
+ </div>
+ </fieldset>
+ </form>
+ </div>
+
+ <div class="modal-footer">
+ <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
+ <button id="addPropertyConstraint" type="button" class="btn btn-primary" onclick="addPropertyMapping()">Add</button>
+ <button id="updatePropertyConstraint" type="button" class="btn btn-primary" onclick="updatePropertyMapping()">Update</button>
+ </div>
+ </div>
+ </div>
+</div>
+
+
+
+<div id="alltabswithcontent">
+<ul class="nav nav-tabs" id="myTab">
+ <li class="active"><a href="#properties">Properties</a></li>
+ <li><a href="#propertymappings">Property Mappings</a></li>
+ <li><a href="#propertyconstraints">Property Constraints</a></li>
+ <li><a href="#requirements">Requirements</a></li>
+ <li><a href="#capabilities">Capabilities</a></li>
+ <li><a href="#policies">Policies</a></li>
+ <li><a href="#interfaces">Interfaces</a></li>
+ <li><a href="#xml">XML</a></li>
+</ul>
+
+<div class="tab-content">
+
+ <div class="tab-pane active" id="properties">
+ <%-- reloadAfterSuccess is necessary as the XMLtree has to be changed --%>
+ <o:orioneditorarea areaid="XMLtextarea" url="boundarydefinitions/properties" reloadAfterSuccess="true">${it.definedPropertiesAsEscapedHTML}</o:orioneditorarea>
+ </div>
+
+ <div class="tab-pane" id="propertymappings">
+ <c:choose>
+ <c:when test="${empty it.definedPropertiesAsEscapedHTML}">
+ <p>No properties available. Thus, no properties can be mapped. Please define properties.</p>
+ </c:when>
+ <c:otherwise>
+ <button id="deleteRequirement" class="rightbutton btn btn-xs btn-danger" onclick="deleteOnServerAndInTable(propertyMappingsTableInfo, 'Property Mapping', 'boundarydefinitions/propertymappings/');">Remove</button>
+ <button class="rightbutton btn btn-xs btn-info" onclick="openAddPropertyMappingDiag();">Add</button>
+ <button class="rightbutton btn btn-xs btn-primary" onclick="openUpdatePropertyMappingDiag();">Edit</button>
+ <table id="propertyMappingsTable">
+ <thead>
+ <tr>
+ <th>Service Template Property</th>
+ <th>Target</th>
+ <th>Target Property</th>
+ </tr>
+ </thead>
+ <tbody>
+ <c:if test="${not empty it.defs.properties and not empty it.defs.properties.propertyMappings and not empty it.defs.properties.propertyMappings.propertyMapping}">
+ <c:forEach items="${it.defs.properties.propertyMappings.propertyMapping}" var="propertyMapping">
+ <tr>
+ <td>${propertyMapping.serviceTemplatePropertyRef}</td>
+ <td>${propertyMapping.targetObjectRef.id}</td> <%-- .name cannot be used as it is not an Id. Future work: Store the id in a seperate field and show the name to the user --%>
+ <td>${propertyMapping.targetPropertyRef}</td>
+ </tr>
+ </c:forEach>
+ </c:if>
+ </tbody>
+ </table>
+ </c:otherwise>
+ </c:choose>
+ </div>
+
+ <%-- TODO: provide this as .tag. The property constraint resource should also be provided as tag --%>
+ <div class="tab-pane" id="propertyconstraints">
+ <button class="rightbutton btn btn-xs btn-danger" onclick="deleteOnServerAndInTable(propertyConstraintsTableInfo, 'Property Constraint', 'propertyconstraints/');">Remove</button>
+ <button class="rightbutton btn btn-xs btn-info" onclick="openAddPropertyConstraintDiag();">Add</button>
+ <button class="rightbutton btn btn-xs btn-primary" onclick="openUpdatePropertyConstraintDiag();">Edit</button>
+ <table id="propertyconstraintstable">
+ <thead>
+ <tr>
+ <th>(internal id)</th>
+ <th>Service Template Property</th>
+ <th>Constraint Type</th>
+ <th>Constraint</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>example</td>
+ <td>/demo</td>
+ <td>http://www.example.com/accessrestrictions</td>
+ <td>(not yet implemented)</td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+
+ <div class="tab-pane" id="requirements">
+ <button class="rightbutton btn btn-xs btn-danger" onclick="deleteOnServerAndInTable(requirementsTableInfo, 'Requirement', 'boundarydefinitions/requirements/');">Remove</button>
+ <button class="rightbutton btn btn-xs btn-info" onclick="openReqEditor(false);">Add</button>
+ <button class="rightbutton btn btn-xs btn-primary" onclick="openReqEditor(true);">Edit</button>
+ <table id="requirementstable">
+ <thead>
+ <tr>
+ <th>(Id)</th><%-- of the boundary requirement, also used as the id of this element--%>
+ <th>Name</th>
+ <th>Reference</th>
+ </tr>
+ </thead>
+ <tbody>
+ <c:forEach var="item" items="${it.defs.requirements.requirement}">
+ <tr>
+ <td>${wr:determineIdUsingHashCode(item)}</td>
+ <td>${item.name}</td>
+ <td>${item.ref.id}</td>
+ </tr>
+ </c:forEach>
+ </tbody>
+ </table>
+ </div>
+
+ <div class="tab-pane" id="capabilities">
+ <%-- mirrored from requirements --%>
+ <button class="rightbutton btn btn-xs btn-danger" onclick="deleteOnServerAndInTable(capabilitiesTableInfo, 'Capability', 'boundarydefinitions/capabilities/');">Remove</button>
+ <button class="rightbutton btn btn-xs btn-info" onclick="openCapEditor(false);">Add</button>
+ <button class="rightbutton btn btn-xs btn-primary" onclick="openCapEditor(true);">Edit</button>
+ <table id="capabilitiestable">
+ <thead>
+ <tr>
+ <th>(Id)</th><%-- of the boundary requirement, also used as the id of this element--%>
+ <th>Name</th>
+ <th>Reference</th>
+ </tr>
+ </thead>
+ <tbody>
+ <c:forEach var="item" items="${it.defs.capabilities.capability}">
+ <tr>
+ <td>${wr:determineIdUsingHashCode(item)}</td>
+ <td>${item.name}</td>
+ <td>${item.ref.id}</td>
+ </tr>
+ </c:forEach>
+ </tbody>
+ </table>
+ </div>
+
+ <div class="tab-pane" id="policies">
+ <pol:policies list="${it.defs.policies.policy}" repositoryURL="${it.repositoryURL}" />
+ <br />
+ <button class="btn btn-default btn-sm btn-primary" onclick="savePolicies();">Save</button>
+ </div>
+ <script>
+ // work around for topology modeler's policy usage
+ $(".addnewpolicy").show();
+
+ // required for the policy addition dialog
+ winery.repositoryURL = "${it.repositoryURL}";
+
+ function savePolicies() {
+ require(["winery-support-common", "XMLWriter"], function(wsc) {
+ var xmlw = new XMLWriter("utf-8");
+ xmlw.writeStartDocument();
+
+ wsc.writeCollectionDefinedByATextArea(xmlw,
+ $("div.policiesContainer").children("div.content").children("div.policy"),
+ "Policies");
+
+ xmlw.writeEndDocument();
+
+ var data = xmlw.flush();
+
+ $.ajax({
+ url: "boundarydefinitions/policies",
+ data: data,
+ type: "PUT",
+ contentType: "application/xml",
+ }).done(function (result) {
+ vShowSuccess("Sucessfully saved policies");
+ }).fail(function(jqXHR, textStatus, errorThrown) {
+ vShowAJAXError("Could not save policies", jqXHR, errorThrown);
+ });
+ });
+ }
+ </script>
+
+ <b:browseForX XLong="node template" XShort="NodeTemplate"/>
+ <script>
+ /**
+ * called from browseForX
+ */
+ function setNodeTemplateRef() {
+ var newRef = $("#NodeTemplateReferenceField").val();
+ $("#nodeTemplateRefForOperation").val(newRef);
+ storeNewReference(newRef);
+ updateTargetInterfaceAndOperation(true);
+ $("#browseForNodeTemplateDiag").modal("hide");
+ }
+
+ function browseForNodeTemplate() {
+ $("#NodeTemplateReferenceField").val($("#nodeTemplateRefForOperation").val());
+ $("#browseForNodeTemplateDiag").modal("show");
+ }
+ </script>
+
+ <b:browseForX XLong="relationship template" XShort="RelationshipTemplate"/>
+ <script>
+ /**
+ * called from browseForX
+ */
+ function setRelationshipTemplateRef() {
+ var newRef = $("#RelationshipTemplateReferenceField").val();
+ $("#relationshipTemplateRefForOperation").val(newRef);
+ storeNewReference(newRef);
+ updateTargetInterfaceAndOperation(false);
+ $("#browseForRelationshipTemplateDiag").modal("hide");
+ }
+
+ function browseForRelationshipTemplate() {
+ $("#RelationshipTemplateReferenceField").val($("#relationshipTemplateRefForOperation").val());
+ $("#browseForRelationshipTemplateDiag").modal("show");
+ }
+ </script>
+
+ <script>
+ function browseForPlan() {
+ vShowError("not yet implemented.");
+ }
+ </script>
+
+ <div class="tab-pane" id="interfaces">
+ <h4>Provided Interface and Operation</h4>
+
+ <form class="form-horizontal">
+ <div class="form-group">
+ <label for="interface" class="col-sm-1 control-label">Interface</label>
+ <div class="col-sm-8">
+ <input id="interface" class="form-control" placeholder="NCName or URI">
+ </div>
+ <button type="button" class="btn btn-danger btn-sm col-sm-1" onclick="deleteCurrentlySelectedInterface();">Delete</button>
+ </div>
+ <div class="form-group">
+ <label for="operation" class="col-sm-1 control-label">Operation</label>
+ <div class="col-sm-8">
+ <input id="operation" class="form-control" placeholder="NCName">
+ </div>
+ <button type="button" class="btn btn-danger btn-sm col-sm-1" onclick="deleteCurrentlySelectedOperation();">Delete</button>
+ </div>
+ </form>
+
+ <h4>Target</h4>
+
+ <form id="reftargettypeForm">
+ <label>
+ <input id="nodeRadio" type="radio" name="reftargettype" value="node" checked="checked">
+ Node Template
+ </label>
+ <label>
+ <input id="relationshipRadio" type="radio" name="reftargettype" value="relationship">
+ Relationship Template
+ </label>
+ <label>
+ <input id="planRadio" type="radio" name="reftargettype" value="plan">
+ Plan
+ </label>
+ </form>
+
+ <form class="form-horizontal">
+ <div class="form-group" id="selectNodeTemplateDiv">
+ <label for="nodeTemplateRefForOperation" class="col-sm-1 control-label">Reference</label>
+ <div class="col-sm-8">
+ <input id="nodeTemplateRefForOperation" class="form-control">
+ </div>
+ <button type="button" class="btn btn-default btn-sm col-sm-1" onclick="browseForNodeTemplate();">Browse</button>
+ </div>
+
+ <div class="form-group" id="selectRelationshipTemplateDiv" style="display:none;">
+ <label for="relationshipTemplateRefForOperation" class="col-sm-1 control-label">Reference</label>
+ <div class="col-sm-8">
+ <input id="relationshipTemplateRefForOperation" class="form-control">
+ </div>
+ <button type="button" class="btn btn-default btn-sm col-sm-1" onclick="browseForRelationshipTemplate();">Browse</button>
+ </div>
+
+ <div class="form-group" id="selectPlanDiv" style="display:none;">
+ <label for="planRefForOperation" class="col-sm-1 control-label">Reference</label>
+ <div class="col-sm-8">
+ <c:choose>
+ <c:when test="${empty it.listOfAllPlans}">
+ <p>No plans available>
+ </c:when>
+ <c:otherwise>
+ <a id="planRefForOperation" href="#"></a>
+ </c:otherwise>
+ </c:choose>
+ </div>
+ </div>
+ </form>
+
+ <h4>Target Interface and Operation</h4>
+ <form class="form-horizontal">
+ <div class="form-group" id="selectInterfaceNameDiv">
+ <label for="TargetInterface" class="col-sm-1 control-label">Interface</label>
+ <div class="col-sm-8">
+ <input id="TargetInterface" class="form-control">
+ </div>
+ </div>
+
+ <div class="form-group" id="selectOperationNameDiv">
+ <label for="TargetOperation" class="col-sm-1 control-label">Operation</label>
+ <div class="col-sm-8">
+ <input id="TargetOperation" class="form-control">
+ </div>
+ </div>
+ </form>
+
+ <div id="notApplicableDiv" style="display:none;">
+ <p>not applicable in the case of plans</p>
+ </div>
+
+ </div>
+
+ <script>
+ // initialize interface selection
+ require(["winery-support-common"], function(wsc) {
+ wsc.fetchSelect2DataAndInitSelect2("interface", "boundarydefinitions/interfaces/?select2", function() {
+ $("#interface").on("change", function() {
+ updateOperationsField();
+ });
+ if ($("#interface").select2("val") != "") {
+ updateOperationsField();
+ }
+ }, true);
+ });
+
+ function getInterfacesAndInterfaceURLs() {
+ var iface = $("#interface").select2("val");
+ iface = encodeID(iface);
+
+ var ifacesURL = "boundarydefinitions/interfaces/";
+ var ifaceURL = ifacesURL + iface + "/";
+ return {
+ ifacesURL: ifacesURL,
+ ifaceURL: ifaceURL
+ }
+ }
+
+ function getOperationsAndOperationURLs() {
+ var ifaceURL = getInterfacesAndInterfaceURLs().ifaceURL;
+ var operation = $("#operation").select2("val");
+ operation = encodeID(operation);
+
+ var operationsURL = ifaceURL + "exportedoperations/";
+ var operationURL = operationsURL + operation + "/";
+ return {
+ operationsURL: operationsURL,
+ operationURL: operationURL
+ }
+ }
+
+ /**
+ * Updates the field of the exported operation
+ */
+ function updateOperationsField() {
+ var iface = $("#interface").select2("val");
+ var urls = getInterfacesAndInterfaceURLs();
+
+ $.ajax({
+ url: urls.ifaceURL,
+ type: "HEAD",
+ async: false,
+ error: function(jqXHR, textStatus, errorThrown) {
+ if (jqXHR.status == 404) {
+ // everything allright -> user entered a new interface
+ $.ajax({
+ url: urls.ifacesURL,
+ async: false,
+ type: "POST",
+ data: JSON.stringify({name: iface}),
+ contentType: "application/json"
+ }).done(function (result) {
+ vShowSuccess("Sucessfully created interface");
+ }).fail(function(jqXHR, textStatus, errorThrown) {
+ vShowAJAXError("Could not create interface", jqXHR, errorThrown);
+ });
+ } else {
+ vShowAJAXError("Could not check for interface existance", jqXHR, errorThrown);
+ }
+ }
+ });
+
+ var url = urls.ifaceURL + "exportedoperations/?select2";
+ require("winery-support-common").fetchSelect2DataAndInitSelect2("operation", url, function(){
+ updateTarget();
+ }, true);
+ }
+
+ $("#operation").on("change", function() {
+ var operation = $("#operation").select2("val");
+ var urls = getOperationsAndOperationURLs();
+ $.ajax({
+ url: urls.operationURL,
+ type: "HEAD",
+ async: false,
+ error: function(jqXHR, textStatus, errorThrown) {
+ if (jqXHR.status == 404) {
+ // everything allright -> user entered a new operation
+ $.ajax({
+ url: urls.operationsURL,
+ async: false,
+ type: "POST",
+ data: JSON.stringify({name: operation}),
+ contentType: "application/json"
+ }).done(function (result) {
+ vShowSuccess("Sucessfully created operation");
+ }).fail(function(jqXHR, textStatus, errorThrown) {
+ vShowAJAXError("Could not create interface", jqXHR, errorThrown);
+ });
+ } else {
+ vShowAJAXError("Could not check for interface operation", jqXHR, errorThrown);
+ }
+ }
+ });
+
+ updateTarget();
+ })
+
+ /**
+ * Updates the content at "Target": Reference and Target Interface/Operation
+ */
+ function updateTarget() {
+ var operation = $("#operation").select2("val");
+ if (operation != "") {
+ var urls = getOperationsAndOperationURLs();
+ // At the beginning of the usage, there is no operation selected
+ // Just fill the data if an operation is chosen
+ var url = urls.operationURL;
+
+ // store URL for later use - this avoids global JavaScript variables
+ $("#operation").data("url", url);
+
+ $.ajax({
+ url: url,
+ dataType: "json"
+ }).done(function (data) {
+ if ((data.type == "NodeOperation") || (data.type == "RelationshipOperation")) {
+ if (data.type == "NodeOperation") {
+ $("#nodeRadio").prop("checked", true);
+ $("#nodeTemplateRefForOperation").val(data.ref);
+ updateTargetInterfaceAndOperation(true, data.interfacename, data.operationname);
+ } else {
+ $("#relationshipRadio").prop("checked", true);
+ $("#relationshipTemplateRefForOperation").val(data.ref);
+ updateTargetInterfaceAndOperation(false, data.interfacename, data.operationname);
+ }
+ } else if (data.type == "Plan") {
+ $("#planRadio").prop("checked", true);
+ $("#planRefForOperation").editable("setValue", data.ref);
+ } else if (data.type == null) {
+ // nothing set yet; set node as type
+ putType("NodeOperation");
+ $("#nodeRadio").prop("checked", true);
+ // no reference is set if no type is set -> clear field
+ $("#nodeTemplateRefForOperation").val("");
+ } else {
+ vShowError("Unexpected type '" + data.type + "'.");
+ return;
+ }
+ adaptVisibilityOfDivsAccordingToReferenceType();
+ }).fail(function(jqXHR, textStatus, errorThrown) {
+ vShowAJAXError("Could not fetch data of exported operation from " + url, jqXHR, errorThrown);
+ });
+ }
+
+ }
+
+ function adaptVisibilityOfDivsAccordingToReferenceType() {
+ var checked = $('input[name=reftargettype]:checked').val();
+ if (checked == "node") {
+ $("#selectNodeTemplateDiv").show();
+ $("#selectRelationshipTemplateDiv").hide();
+ $("#selectPlanDiv").hide();
+ $("#selectInterfaceNameDiv").show();
+ $("#selectOperationNameDiv").show();
+ $("#notApplicableDiv").hide();
+ } else if (checked == "relationship") {
+ $("#selectNodeTemplateDiv").hide();
+ $("#selectRelationshipTemplateDiv").show();
+ $("#selectPlanDiv").hide();
+ $("#selectInterfaceNameDiv").show();
+ $("#selectOperationNameDiv").show();
+ $("#notApplicableDiv").hide();
+ } else if (checked == "plan") {
+ $("#selectNodeTemplateDiv").hide();
+ $("#selectRelationshipTemplateDiv").hide();
+ $("#selectPlanDiv").show();
+ $("#selectInterfaceNameDiv").hide();
+ $("#selectOperationNameDiv").hide();
+ $("#notApplicableDiv").show();
+ } else {
+ vShowError("UI in inconsistent state: wrong branch in adaptVisibilityOfDivsAccordingToReferenceType");
+ }
+ }
+ </script>
+
+ <div class="tab-pane" id="xml">
+ <o:orioneditorarea areaid="XML" url="boundarydefinitions/" reloadAfterSuccess="true">${it.boundaryDefinitionsAsXMLStringEncoded}</o:orioneditorarea>
+ </div>
+</div>
+</div>
+
+<script>
+$('#myTab a').click(function (e) {
+ e.preventDefault();
+ $(this).tab('show');
+});
+
+function openPropertyConstraintEditor() {
+ vShowError("not yet implemented");
+ // TODO: fill diag with the values of the table
+ // $('#addPropertyConstraintDiag').modal('show');
+}
+
+
+var propertyConstraintsTableInfo = {
+ id: '#propertyconstraintstable'
+};
+var requirementsTableInfo = {
+ id: '#requirementstable'
+};
+var capabilitiesTableInfo = {
+ id: '#capabilitiestable'
+};
+var interfacesTableInfo = {
+ id: '#interfacestable'
+};
+var propertyMappingsTableInfo = {
+ id: '#propertyMappingsTable'
+ };
+
+require(["winery-support"], function(ws) {
+ var firstColumnIsHidden = {
+ aoColumnDefs: [
+ { "bSearchable": false, "bVisible": false, "aTargets": [ 0 ] }
+ ]
+ };
+
+ ws.initTable(propertyConstraintsTableInfo, firstColumnIsHidden);
+ ws.initTable(requirementsTableInfo, firstColumnIsHidden);
+ ws.initTable(capabilitiesTableInfo, firstColumnIsHidden);
+
+ ws.initTable(interfacesTableInfo);
+ ws.initTable(propertyMappingsTableInfo);
+});
+
+<%-- === BEGIN: Property Constraints === --%>
+
+function openUpdatePropertyConstraintDiag() {
+ if (propertyConstraintsTableInfo.selectedRow) {
+ require(["winery-support"], function(ws) {
+ if (ws.isEmptyTable(propertyConstraintsTableInfo)) {
+ vShowError("No property constraints available");
+ return;
+ }
+
+ $("#addPropertyConstraint").hide();
+ $("#updatePropertyConstraint").show();
+
+ // put value in fields
+ var children = $(propertyMappingsTableInfo.selectedRow).children("td");
+ $("#serviceTemplatePropertyRefForConstraint").val($(children[1]).text());
+ $("#constraintType").val($(children[2]).text());
+ // TODO: value of the constraint
+
+ $('#propertyConstraintDiag').modal('show');
+
+ vShowError("Not yet implemented.");
+ });
+ } else {
+ vShowError("No property constraint selected");
+ }
+}
+
+function openAddPropertyConstraintDiag() {
+ $("#addPropertyConstraint").show();
+ $("#updatePropertyConstraint").hide();
+
+ // reset all fields
+ $("#serviceTemplatePropertyRefForConstraint").val("");
+ // TODO: value of the constraint
+
+ $('#propertyConstraintDiag').modal('show');
+
+ vShowError("Not yet implemented.");
+}
+
+<%-- === END: Property Constraints === --%>
+
+
+<%-- === BEGIN: Property Mapping === --%>
+
+function openUpdatePropertyMappingDiag() {
+ if (propertyMappingsTableInfo.selectedRow) {
+ require(["winery-support"], function(ws) {
+ if (ws.isEmptyTable(propertyMappingsTableInfo)) {
+ vShowError("No property mappings available");
+ return;
+ }
+
+ $("#addPropertyMapping").hide();
+ $("#updatePropertyMapping").show();
+
+ // put value in fields
+ var children = $(propertyMappingsTableInfo.selectedRow).children("td");
+ $("#serviceTemplatePropertyRef").val($(children[0]).text());
+ $("#targetObjectRef").val($(children[1]).text());
+ $("#targetPropertyRef").val($(children[2]).text());
+
+ $('#propertyMappingDiag').modal('show');
+ });
+ } else {
+ vShowError("No property mapping selected");
+ }
+}
+
+function openAddPropertyMappingDiag() {
+ $("#addPropertyMapping").show();
+ $("#updatePropertyMapping").hide();
+
+ // reset all fields
+ $("#serviceTemplatePropertyRef").val("");
+ $("#targetObjectRef").val("");
+ $("#targetPropertyRef").val("");
+
+ $('#propertyMappingDiag').modal('show');
+}
+
+function addOrUpdatePropertyMapping(add) {
+ var serviceTemplatePropertyRef = $("#serviceTemplatePropertyRef").val();
+ var targetObjectRef = $("#targetObjectRef").val();
+ var targetPropertyRef = $("#targetPropertyRef").val();
+
+ $.ajax({
+ url: "boundarydefinitions/propertymappings",
+ type: "POST",
+ async: false,
+ data: {
+ serviceTemplatePropertyRef: serviceTemplatePropertyRef,
+ targetObjectRef: targetObjectRef,
+ targetPropertyRef: targetPropertyRef
+ },
+ error: function(jqXHR, textStatus, errorThrown) {
+ vShowAJAXError("Could not POST property mapping", jqXHR, errorThrown);
+ },
+ success: function(data, textSTatus, jqXHR) {
+ // put value from fields into table
+ if (add) {
+ propertyMappingsTableInfo.table.fnAddData([serviceTemplatePropertyRef, targetObjectRef, targetPropertyRef]);
+ } else {
+ var children = $(propertyMappingsTableInfo.selectedRow).children("td");
+ $(children[0]).text(serviceTemplatePropertyRef);
+ $(children[1]).text(targetObjectRef);
+ $(children[2]).text(targetPropertyRef);
+ }
+
+ $('#propertyMappingDiag').modal('hide');
+
+ vShowSuccess("Successfully posted property mapping.");
+ }
+ });
+}
+
+function addPropertyMapping() {
+ addOrUpdatePropertyMapping(true);
+}
+
+function updatePropertyMapping() {
+ addOrUpdatePropertyMapping(false);
+}
+
+<%-- === END: Property Mapping === --%>
+
+
+//window.addEventListener('message', function(event){var v = document.getElementById('%s');if(v){v=v.firstChild; if(v && v.contentWindow === event.source){%s}}})
+window.addEventListener('message', function(event) {
+ if (event.data) {
+ if (event.data.targetObjectRef) {
+ // current API expects both fields
+ $(".newObjectRef").val(event.data.targetObjectRef);
+ $("#newObjectPropertyRef").val(event.data.targetPropertyRef);
+ } else if (event.data.reqRef) {
+ $("#ReqReferenceField").val(event.data.reqRef);
+ } else if (event.data.capRef) {
+ $("#CapReferenceField").val(event.data.capRef);
+ } else if (event.data.targetRelationshipTemplateRef) {
+ $("#RelationshipTemplateReferenceField").val(event.data.targetRelationshipTemplateRef);
+ }
+ }
+});
+
+function storeNewReference(ref) {
+ var url = $("#operation").data("url") + "/ref";
+ $.ajax({
+ url: url,
+ data: ref,
+ type: "PUT",
+ contentType: "text/plain",
+ }).done(function (result) {
+ vShowSuccess("Sucessfully saved reference");
+ }).fail(function(jqXHR, textStatus, errorThrown) {
+ vShowAJAXError("Could not set reference", jqXHR, errorThrown);
+ });
+}
+
+<c:if test="${not empty it.listOfAllPlans}">
+$("#planRefForOperation").editable({
+ type: "select",
+ source: [
+ <c:forEach var="item" items="${it.listOfAllPlans}">
+ {value: "${item.id}",
+ text: "${item.text}"},
+ </c:forEach>
+ ]
+}).on("save", function(e, params) {
+ var newRef = params.newValue;
+ storeNewReference(newRef)
+});
+</c:if>
+
+function putType(type) {
+ var url = $("#operation").data("url") + "/type";
+ $.ajax({
+ url: url,
+ data: type,
+ type: "PUT",
+ contentType: "text/plain",
+ }).done(function (result) {
+ vShowSuccess("Sucessfully changed reference type");
+ adaptVisibilityOfDivsAccordingToReferenceType();
+ }).fail(function(jqXHR, textStatus, errorThrown) {
+ vShowAJAXError("Could not set new reference type", jqXHR, errorThrown);
+ });
+}
+
+function getInterfaceDataFromURL(ifaceURL) {
+ var select2data = null;
+ $.ajax({
+ url: ifaceURL + "?select2",
+ async: false,
+ type: "GET",
+ dataType: "json",
+ success: function (data) {
+ select2data = data;
+ },
+ error: function(jqXHR, textStatus, errorThrown) {
+ vShowAJAXError("Could not get interface data", jqXHR, errorThrown);
+ }
+ });
+ return select2data;
+}
+
+function getDataForUpdateTargetOperation(url, showError) {
+ var select2data = null;
+ $.ajax({
+ url: url + "?select2",
+ async: false,
+ type: "GET",
+ dataType: "json",
+ success: function (data) {
+ select2data = data;
+ },
+ error: function(jqXHR, textStatus, errorThrown) {
+ if (showError) {
+ vShowAJAXError("Could not get operation data", jqXHR, errorThrown);
+ }
+ }
+ });
+ return select2data;
+}
+
+function updateTargetOperation(operationNameToSelect) {
+ var ifaceURL = $("#TargetInterface").data("url2");
+ var select2data = null;
+ var operationsURL;
+
+ // we don't store the interface-URL at #TargetInterface, but do a quick hack here
+ if (ifaceURL != null) {
+ operationsURL = ifaceURL + "/" + encodeID($("#TargetInterface").val()) + "/operations/";
+ select2data = getDataForUpdateTargetOperation(operationsURL, false);
+ }
+
+ // either only one URL or nothing found at second URL --> try first URL
+ if (select2data == null) {
+ ifaceURL = $("#TargetInterface").data("url1");
+ operationsURL = ifaceURL + "/" + encodeID($("#TargetInterface").val()) + "/operations/";
+ select2data = getDataForUpdateTargetOperation(operationsURL, true);
+ }
+
+ if (select2data != null) {
+ $("#TargetOperation").select2({
+ data:select2data
+ });
+ var valueToSelect = null;
+ if ((typeof operationNameToSelect !== "undefined") && (operationNameToSelect != null)) {
+ valueToSelect = operationNameToSelect;
+ } else {
+ // called without existing data --> insert pseudo data and store it at the backend to ensure consistency
+ if (select2data.length > 0) {
+ valueToSelect = select2data[0].id;
+ storeTargetOperation(valueToSelect);
+ }
+ }
+ if (valueToSelect != null) {
+ $("#TargetOperation").select2('val', valueToSelect);
+ }
+ }
+
+}
+
+function updateTargetInterfaceAndOperationFromInterfaceURL(ifaceURL, interfaceNameToSelect, operationNameToSelect) {
+ var select2data;
+ if (typeof ifaceURL === "string") {
+ select2data = getInterfaceDataFromURL(ifaceURL);
+ $("#TargetInterface").data("url1", ifaceURL);
+ $("#TargetInterface").data("url2", null);
+ } else {
+ // TODO: instead of hacking with two urls (especially at other places in the code), we should prefix the entries with S| at the source interface and T| at the target interface
+ select2data = getInterfaceDataFromURL(ifaceURL[0]);
+ var select2data2 = getInterfaceDataFromURL(ifaceURL[1]);
+ $.merge(select2data, select2data2);
+ $("#TargetInterface").data("url1", ifaceURL[0]);
+ $("#TargetInterface").data("url2", ifaceURL[1]);
+ }
+ $("#TargetInterface").select2({data:select2data});
+
+ var valueToSelect = null;
+ if ((typeof interfaceNameToSelect !== "undefined") && (interfaceNameToSelect != null)) {
+ valueToSelect = interfaceNameToSelect;
+ } else {
+ // called without existing data --> insert pseudo data and store it at the backend to ensure consistency
+ if (select2data.length > 0) {
+ valueToSelect = select2data[0].id;
+ storeTargetInterface(valueToSelect);
+ }
+ }
+ if (valueToSelect != null) {
+ $("#TargetInterface").select2('val', valueToSelect);
+ }
+
+ updateTargetOperation(operationNameToSelect);
+}
+
+function updateTargetInterfaceAndOperation(isNodeTemplate, interfaceNameToSelect, operationNameToSelect) {
+ var url = "topologytemplate/";
+ url = url + (isNodeTemplate ? "nodetemplates" : "relationshiptemplates" + "/");
+ var templateId = isNodeTemplate ? $("#nodeTemplateRefForOperation").val() : $("#relationshipTemplateRefForOperation").val();
+ if (templateId == "") {
+ // if no template is provided, we just return
+ return;
+ }
+ url = url + "/" + templateId + "/type";
+ $.ajax({
+ url: url,
+ type: "GET",
+ dataType: "text"
+ }).done(function (typeQName) {
+ require(["winery-support-common"], function(wsc) {
+ var urlDetermination = isNodeTemplate ? wsc.makeNodeTypeURLFromQName : wsc.makeRelationshipTypeURLFromQName;
+ var typeURL = urlDetermination("${it.repositoryURL}", typeQName)
+ if (isNodeTemplate) {
+ updateTargetInterfaceAndOperationFromInterfaceURL(typeURL + "/interfaces", interfaceNameToSelect, operationNameToSelect);
+ } else {
+ updateTargetInterfaceAndOperationFromInterfaceURL([typeURL + "/sourceinterfaces/", typeURL + "/targetinterfaces/"], interfaceNameToSelect, operationNameToSelect);
+ }
+ });
+ }).fail(function(jqXHR, textStatus, errorThrown) {
+ vShowAJAXError("Could not get type of node / relationship", jqXHR, errorThrown);
+ });
+
+}
+
+$("#nodeRadio").on("change", function() {
+ putType("NodeOperation");
+ updateTargetInterfaceAndOperation(true);
+});
+$("#relationshipRadio").on("change", function() {
+ putType("RelationshipOperation");
+ updateTargetInterfaceAndOperation(false);
+});
+$("#planRadio").on("change", function() {
+ putType("Plan");
+});
+
+$("#nodeTemplateRefForOperation").on("change", function() {
+ updateTargetInterfaceAndOperation(true);
+});
+
+$("#relationshipTemplateRefForOperation").on("change", function() {
+ updateTargetInterfaceAndOperation(false);
+});
+
+function storeTargetInterface(val) {
+ val = val || $("#TargetInterface").select2("val");
+ var url = $("#operation").data("url") + "interfacename";
+ // when selecting a new operation, both targetinterface and targetoperation are updated; this leads to race conditions at the backend and one chang would be lost. Therefore, we do the calls synchronously
+ $.ajax({
+ url: url,
+ data: val,
+ type: "PUT",
+ contentType: "text/plain",
+ async:false
+ }).done(function (result) {
+ vShowSuccess("Sucessfully saved interface name");
+ }).fail(function(jqXHR, textStatus, errorThrown) {
+ vShowAJAXError("Could not set interface name", jqXHR, errorThrown);
+ });
+}
+
+function storeTargetOperation(val) {
+ val = val || $("#TargetOperation").select2("val");
+ var url = $("#operation").data("url") + "operationname";
+ // when selecting a new operation, both targetinterface and targetoperation are updated; this leads to race conditions at the backend and one chang would be lost. Therefore, we do the calls synchronously
+ $.ajax({
+ url: url,
+ data: val,
+ type: "PUT",
+ contentType: "text/plain",
+ async:false
+ }).done(function (result) {
+ vShowSuccess("Sucessfully saved operation name");
+ }).fail(function(jqXHR, textStatus, errorThrown) {
+ vShowAJAXError("Could not set operation name", jqXHR, errorThrown);
+ });
+}
+
+$("#TargetInterface").on("change", function() {
+ storeTargetInterface();
+ updateTargetOperation();
+});
+
+$("#TargetOperation").on("change", function() {
+ storeTargetOperation();
+});
+
+function deleteCurrentlySelectedInterface() {
+ vConfirmYesNo("Do you really want to delete this interface?", function() {
+ var url = getInterfacesAndInterfaceURLs().ifaceURL;
+ $.ajax({
+ url: url,
+ type: "DELETE"
+ }).done(function () {
+ require(["winery-support-common"], function (wsc) {
+ wsc.removeItemFromSelect2Field($("#interface"), $("#interface").select2("data").id);
+ vShowSuccess("Successfully deleted interface");
+ });
+ }).fail(function(jqXHR, textStatus, errorThrown) {
+ vShowAJAXError("Could not delete interface", jqXHR, errorThrown);
+ });
+ });
+}
+
+function deleteCurrentlySelectedOperation() {
+ vConfirmYesNo("Do you really want to delete this operation?", function() {
+ var url = getOperationsAndOperationURLs().operationURL;
+ $.ajax({
+ url: url,
+ type: "DELETE"
+ }).done(function () {
+ require(["winery-support-common"], function (wsc) {
+ wsc.removeItemFromSelect2Field($("#operation"), $("#operation").select2("data").id);
+ vShowSuccess("Successfully deleted operation");
+ });
+ }).fail(function(jqXHR, textStatus, errorThrown) {
+ vShowAJAXError("Could not delete operation", jqXHR, errorThrown);
+ });
+ });
+}
+
+</script>
diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/jsp/servicetemplates/plans/plans.jsp b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/servicetemplates/plans/plans.jsp
new file mode 100644
index 0000000..ca50be4
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/servicetemplates/plans/plans.jsp
@@ -0,0 +1,266 @@
+<%--
+/*******************************************************************************
+ * Copyright (c) 2012-2013 University of Stuttgart.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ * Oliver Kopp - initial API and implementation and/or initial documentation
+ * Yves Schubert - switch to bootstrap 3
+ *******************************************************************************/
+--%>
+<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
+<%@taglib prefix="p" tagdir="/WEB-INF/tags/parameters" %>
+<%@taglib prefix="t" tagdir="/WEB-INF/tags" %>
+
+<script>
+
+var embeddedPlansTableInfo = {
+ id: '#embeddedPlansTable'
+};
+
+var linkedPlansTableInfo = {
+ id: '#linkedPlansTable'
+};
+
+$(function() {
+ require(["winery-support"], function(ws) {
+ ws.initTable(embeddedPlansTableInfo, {
+ "aoColumns": [
+ { "bVisible": false, "bSearchable": false}, // ID column
+ { "sTitle": "Precondition" },
+ { "sTitle": "Name" },
+ { "sTitle": "Type" },
+ { "sTitle": "Language" }
+ ],
+ "aaData" : ${it.embeddedPlansTableData}
+ });
+
+ ws.initTable(linkedPlansTableInfo, {
+ "aoColumns": [
+ { "bVisible": false, "bSearchable": false}, // ID column
+ { "sTitle": "Precondition" },
+ { "sTitle": "Name" },
+ { "sTitle": "Type" },
+ { "sTitle": "Language" },
+ { "sTitle": "Reference" }
+ ],
+ "aaData" : ${it.linkedPlansTableData}
+ });
+ });
+});
+
+function editIOParameters() {
+ if (embeddedPlansTableInfo.selectedRow) {
+ require(["winery-support"], function(ws) {
+ if (ws.isEmptyTable(embeddedPlansTableInfo)) {
+ vShowError("No plans available");
+ return;
+ }
+ updateInputAndOutputParameters(getPlanURL());
+ $("#editParametersDiag").modal("show");
+ });
+ } else {
+ vShowError("No plan selected");
+ }
+}
+ function createPlan(data) {
+ if (highlightRequiredFields()) {
+ vShowError("Please fill out all required fields");
+ return;
+ }
+ data.submit();
+ }
+
+ function getPlanURL() {
+ var id = embeddedPlansTableInfo.table.fnGetData(embeddedPlansTableInfo.selectedRow, 0);
+ return "plans/" + encodeURIComponent(id) + "/";
+ }
+
+ function openPlanEditor() {
+ if (embeddedPlansTableInfo.selectedRow) {
+ var isEmptyTable = embeddedPlansTableInfo.table.children("tbody").children("tr").first().children("td").hasClass("dataTables_empty");
+ if (isEmptyTable) {
+ vShowError("No plans available");
+ return;
+ }
+ window.open(getPlanURL() + "?edit", "_blank");
+ } else {
+ vShowError("No plan selected");
+ }
+ }
+
+ function letUserChooseAPlan() {
+ $('#planFileInput').trigger('click');
+ $('#planChooseBtn').focus();
+ }
+
+ requirejs(["jquery.fileupload"], function(){
+ $('#addPlanForm').fileupload().bind("fileuploadadd", function(e, data) {
+ $.each(data.files, function (index, file) {
+ $("#planFileText").val(file.name);
+ });
+ $("#addPlanBtnFUP").off("click");
+ $("#addPlanBtnFUP").on("click", function() {
+ createPlan(data);
+ });
+ }).bind("fileuploadstart", function(e) {
+ $("#addPlanBtnFUP").button("loading");
+ }).bind('fileuploadfail', function(e, data) {
+ vShowAJAXError("Could not add plan", data.jqXHR, data.errorThrown);
+ $("#addPlanBtnFUP").button("reset");
+ }).bind('fileuploaddone', function(e, data) {
+ vShowSuccess("Plan created successfully");
+
+ // reset the add button
+ $("#addPlanBtnFUP").button("reset");
+ // do not allow submission of the old files on a click if the dialog is opened another time
+ $("#addPlanBtnFUP").off("click");
+
+ // TODO: if id is already present in table, delete row in table
+
+ embeddedPlansTableInfo.table.fnAddData(data.result.tableData);
+
+ $('#addPlanDiag').modal('hide');
+ });
+ });
+</script>
+
+<div class="modal fade" id="addPlanDiag">
+ <div class="modal-dialog">
+ <div class="modal-content">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
+ <h4 class="modal-title">Add Plan</h4>
+ </div>
+ <div class="modal-body">
+ <form id="addPlanForm" enctype="multipart/form-data" action="plans/" method="post">
+ <div class="form-group">
+ <label class="control-label">Name</label>
+ <input name="planName" id="planName" type="text" class="form-control" required="required">
+ </div>
+
+ <t:typeswithshortnameasselect label="Type" type="plantype" selectname="planType" typesWithShortNames="${it.planTypes}">
+ </t:typeswithshortnameasselect>
+
+ <t:typeswithshortnameasselect label="Language" type="planlanguage" selectname="planLanguage" typesWithShortNames="${it.planLanguages}">
+ </t:typeswithshortnameasselect>
+
+ <div class="form-group" id="fileDiv">
+ <label class="control-label" for="planFileDiv">Archive</label>
+ <div style="display: block; width: 100%" id="planFileDiv">
+ <input id="planFileInput" name="file" type="file" style="display:none">
+ <input name="fileText" id="planFileText" type="text" class="form-control" style="width:300px; display:inline;" onclick="letUserChooseAPlan();" required="required">
+ <button type="button" id="planChooseBtn" class="btn btn-default btn-xs" onclick="letUserChooseAPlan();">Choose</button>
+ </div>
+ </div>
+ </form>
+ </div>
+ <div class="modal-footer">
+ <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
+ <button type="button" class="btn btn-primary" data-loading-text="Uploading..." id="addPlanBtnFUP">Add</button>
+ <button type="button" class="btn btn-primary" style="display:none;" id="addPlanBtnBPMN4TOSCA">Add</button>
+ </div>
+ </div>
+ </div>
+</div>
+
+<script>
+$("#planLanguage").on("change", function(e) {
+ var lang = $("#planLanguage").val();
+ if (lang == "http://www.opentosca.org/bpmn4tosca") {
+ $("#fileDiv").hide();
+ $("#addPlanBtnFUP").hide();
+ $("#addPlanBtnBPMN4TOSCA").show();
+ } else {
+ $("#fileDiv").show();
+ $("#addPlanBtnFUP").show();
+ $("#addPlanBtnBPMN4TOSCA").hide();
+ }
+});
+
+$("#addPlanBtnBPMN4TOSCA").on("click", function() {
+ var data = new FormData();
+ data.append("planName", $("#planName").val());
+ data.append("planType", $("#planType").val());
+ data.append("planLanguage", $("#planLanguage").val());
+
+ $.ajax({
+ url: "plans/",
+ type: "POST",
+ async: false,
+ contentType: false, // jQuery automatically sets multipart/form-data; boundary=...
+ data: data,
+ processData: false,
+ error: function(jqXHR, textStatus, errorThrown) {
+ vShowAJAXError("Could not add BPMN4TOSCSA plan", jqXHR, errorThrown);
+ },
+ success: function(data, textStatus, jqXHR) {
+ //typesTableInfo.table.fnAddData([$('#shortname').val(), $('#type').val()]);
+ $('#addPlanDiag').modal('hide');
+ vShowSuccess("Successfully added plan. Please refresh the page.");
+ }
+ });
+
+});
+</script>
+
+<p:parametersJS></p:parametersJS>
+
+<div class="modal fade" id="editParametersDiag">
+ <div class="modal-dialog">
+ <div class="modal-content">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
+ <h4 class="modal-title">Edit Parameters</h4>
+ </div>
+ <div class="modal-body">
+ <p:parametersInput baseURL="getPlanURL()"></p:parametersInput>
+ <p:parametersOutput baseURL="getPlanURL()"></p:parametersOutput>
+ </div>
+ <div class="modal-footer">
+ <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
+ </div>
+ </div>
+ </div>
+</div>
+
+ <div id="managementPlans">
+ <h4>Embedded Plans</h4>
+ <button class="rightbutton btn btn-xs btn-danger" onclick="deleteOnServerAndInTable(embeddedPlansTableInfo, 'Plan', 'plans/', 0, 2);">Remove</button>
+ <button class="rightbutton btn btn-xs btn-info" onclick="$('#addPlanDiag').modal('show');">Add</button>
+ <button class="rightbutton btn btn-xs btn-default" onclick="editIOParameters();">I/O Parameters</button>
+ <button class="rightbutton btn btn-xs btn-primary" onclick="openPlanEditor();">Edit</button>
+<%
+if (org.eclipse.winery.repository.Prefs.INSTANCE.isPlanBuilderAvailable()) {
+%>
+ <script>
+ function generateBuildPlan() {
+ $("#btnGenerateBuildPlan").button('loading');
+ $.ajax({
+ url: 'topologytemplate/',
+ // targeting method triggerGenerateBuildPlan in TopologyTemplateResource.java
+ dataType: "text"
+ }).fail(function(jqXHR, textStatus, errorThrown) {
+ $("#btnGenerateBuildPlan").button('reset');
+ vShowAJAXError("Could not trigger plan generation.", jqXHR, errorThrown);
+ }).done(function(data, textStatus, jqXHR) {
+ $("#btnGenerateBuildPlan").button('reset');
+ var resultText = "Successfully generated build plan. Please refresh the page.";
+ vShowSuccess(resultText);
+ });
+ }
+ </script>
+ <button id="btnGenerateBuildPlan" class="btn btn-xs btn-default" data-loading-text="Generating..." onclick="generateBuildPlan();">Generate Build Plan</button>
+<%
+}
+%>
+ <table cellpadding="0" cellspacing="0" border="0" class="display" id="embeddedPlansTable"></table>
+
+ <br /><br />
+ <h4>Linked Plans</h4>
+ <table cellpadding="0" cellspacing="0" border="0" class="display" id="linkedPlansTable"></table>
+ </div>
diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/jsp/servicetemplates/selfservicemetadata/selfservicemetadata.jsp b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/servicetemplates/selfservicemetadata/selfservicemetadata.jsp
new file mode 100644
index 0000000..d4d9233
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/servicetemplates/selfservicemetadata/selfservicemetadata.jsp
@@ -0,0 +1,256 @@
+<%--
+/*******************************************************************************
+ * Copyright (c) 2012-2013 University of Stuttgart.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ * Oliver Kopp - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+--%>
+<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
+
+<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
+<%@taglib prefix="o" tagdir="/WEB-INF/tags/common/orioneditor"%>
+<%@taglib prefix="t" tagdir="/WEB-INF/tags" %>
+<%@taglib prefix="w" uri="http://www.eclipse.org/winery/repository/functions"%>
+
+<%-- Upload functionality inspired by plans.jsp. That code could be generalized somehow in a .tag file --%>
+
+<ul class="nav nav-tabs" id="myTab">
+ <li class="active"><a href="#description">Description</a></li>
+ <li><a href="#images">Images</a></li>
+ <li><a href="#options">Options</a></li>
+ <li><a href="#xml" id="showXMLTab">XML</a></li>
+</ul>
+
+<div class="tab-content">
+
+ <div class="tab-pane active" id="description">
+ <div class="form-group">
+ <label class="label-form">Name</label>
+ <a href="#" class="form-control" data-send="always" id="displayName" data-url="selfserviceportal/displayname" data-tile="Enter Display Name">${it.application.displayName}</a>
+ </div>
+
+ <div class="form-group">
+ <label class="label-form">Description</label>
+ <div class="form-control" id="applicationDescriptionDiv">${it.application.description}</div>
+ </div>
+ </div>
+
+ <div class="tab-pane" id="images">
+
+ <t:imageUpload
+ label="Icon"
+ URL="selfserviceportal/icon.jpg"
+ id="upIcon"
+ width="16px"
+ accept="image/*"/>
+
+ <t:imageUpload
+ label="Preview"
+ URL="selfserviceportal/image.jpg"
+ id="upImage"
+ width="100px"
+ accept="image/*"/>
+
+ </div>
+
+ <div class="tab-pane" id="options">
+ <button class="rightbutton btn btn-xs btn-danger" name="remove" onclick="deleteOnServerAndInTable(optionsTableInfo, 'Option', 'selfserviceportal/options/', 0, 1);">Remove</button>
+ <button class="rightbutton btn btn-xs btn-info" name="add" onclick="$('#addOptionDiag').modal('show');">Add</button>
+ <!-- <button class="rightbutton btn btn-xs btn-default" name="edit" onclick="openOptionEditor();">Edit</button> -->
+
+ <table id="optionsTable">
+ <thead>
+ <tr>
+ <th>Id</th>
+ <th>Name</th>
+ <th>Icon</th>
+ <th>Plan Service Name</th>
+ </tr>
+ </thead>
+ <tbody>
+ <c:if test="${not empty it.application}">
+ <c:forEach var="option" items="${it.application.options.option}">
+ <tr>
+ <td>${option.id}</td>
+ <td>${option.name}</td>
+ <td><img src="selfserviceportal/options/${w:URLencode(option.id)}/icon.jpg" style="width:50px;"></td>
+ <td>${option.planServiceName}</td>
+ </tr>
+ </c:forEach>
+ </c:if>
+ </tbody>
+ </table>
+ </div>
+
+ <div class="tab-pane" id="xml">
+ <o:orioneditorarea areaid="XML" url="selfserviceportal/" reloadAfterSuccess="true">${it.applicationAsXMLStringEncoded}</o:orioneditorarea>
+ </div>
+
+</div>
+
+<script>
+function letUserChooseAFile() {
+ $('#fileInput').trigger('click');
+ $('#chooseBtn').focus();
+}
+
+$('#showXMLTab').on('shown.bs.tab', function (e) {
+ window.winery.orionareas['XML'].fixEditorHeight();
+});
+</script>
+
+<div class="modal fade" id="addOptionDiag">
+ <div class="modal-dialog">
+ <div class="modal-content">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
+ <h4 class="modal-title">Add Option</h4>
+ </div>
+ <div class="modal-body">
+ <form id="addOptionForm" enctype="multipart/form-data" action="selfserviceportal/options/" method="post">
+ <div class="form-group">
+ <label class="control-label">Name</label>
+ <input name="name" type="text" class="form-control" required="required">
+ </div>
+
+ <div class="form-group">
+ <label class="control-label">Description</label>
+ <textarea id="optionDescription" name="description" class="form-control" required="required"></textarea>
+ </div>
+
+ <div class="form-group">
+ <label class="control-label" for="fileDiv">Icon</label>
+ <div style="display: block; width: 100%" id="iconDiv">
+ <input id="fileInput" name="file" type="file" style="display:none" accept="image/*">
+ <input name="fileText" id="fileText" type="text" class="form-control" style="width:300px; display:inline;" onclick="letUserChooseAFile();" required="required">
+ <button type="button" id="chooseBtn" class="btn btn-default btn-xs" onclick="letUserChooseAFile();">Choose</button>
+ </div>
+ </div>
+
+ <div class="form-group">
+ <label class="control-label">Plan Service Name</label>
+ <input name="planServiceName" type="text" class="form-control" required="required">
+ </div>
+
+ <div class="form-group">
+ <label class="control-label">Plan Input Message</label>
+ <textarea name="planInputMessage" class="form-control" required="required" rows="20">&lt;soapenv:Envelope xmlns:soapenv=&quot;http://schemas.xmlsoap.org/soap/envelope/&quot;&gt;
+&lt;soapenv:Header/&gt;
+&lt;soapenv:Body&gt;
+&lt;/soapenv:Body&gt;
+&lt;/soapenv:Envelope&gt;</textarea>
+ </div>
+
+ </form>
+ </div>
+ <div class="modal-footer">
+ <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
+ <button type="button" class="btn btn-primary" data-loading-text="Uploading..." id="addOptionBtn">Add</button>
+ </div>
+ </div>
+ </div>
+</div>
+
+
+<script>
+$("#displayName").editable({
+ ajaxOptions: {type: "PUT"},
+ success: function() {
+ vShowSuccess("Successfully updated display name");
+ },
+ error: function(response) {
+ vShowError("Could not update display name: " + response.status + " " + response.responseText);
+ }
+});
+
+$("#applicationDescriptionDiv").editable({
+ type: "wysihtml5",
+ send: "always",
+ url: "selfserviceportal/description",
+ ajaxOptions: {type: "PUT"},
+ success: function() {
+ vShowSuccess("Successfully updated description");
+ },
+ error: function(response) {
+ vShowError("Could not update description: " + response.status + " " + response.responseText);
+ }
+});
+
+$("#optionDescription").wysihtml5();
+
+var optionsTableInfo = {
+ id: '#optionsTable'
+};
+
+$('#myTab a').click(function (e) {
+ e.preventDefault();
+ $(this).tab('show');
+});
+
+$(function() {
+ // initialize table and hide first column
+ require(["winery-support"], function(ws) {
+ ws.initTable(optionsTableInfo, {
+ "aoColumnDefs": [
+ { "bSearchable": false, "bVisible": false, "aTargets": [ 0 ] }
+ ]
+ });
+ });
+
+ $("#addOptionDiag").on("hidden.bs.modal", function() {
+ // we currently do not send data back from the server
+ // we emulate the AJAX refresh by a reaload
+ doTheTabSelection(function() {
+ $('#myTab a[href="#options"]').tab('show');
+ });
+ });
+});
+
+function createOption(data) {
+ if (highlightRequiredFields()) {
+ vShowError("Please fill out all required fields");
+ return;
+ }
+ data.submit();
+}
+
+requirejs(["jquery.fileupload"], function(){
+ $('#addOptionForm').fileupload({
+ // dropping should only be available in the addOptionDialog. This, however, does not work correctly
+ dropZone: $("#addOptionDiag")
+ }).bind("fileuploadadd", function(e, data) {
+ $.each(data.files, function (index, file) {
+ $("#fileText").val(file.name);
+ });
+ $("#addOptionBtn").off("click");
+ $("#addOptionBtn").on("click", function() {
+ createOption(data);
+ });
+ }).bind("fileuploadstart", function(e) {
+ $("#addOptionBtn").button("loading");
+ }).bind('fileuploadfail', function(e, data) {
+ vShowAJAXError("Could not add option", data.jqXHR, data.errorThrown);
+ $("#addOptionBtn").button("reset");
+ }).bind('fileuploaddone', function(e, data) {
+ vShowSuccess("Option created successfully.");
+
+ // reset the add button
+ $("#addOptionBtn").button("reset");
+ // do not allow submission of the old files on a click if the dialog is opened another time
+ $("#addOptionBtn").off("click");
+
+ // TODO: add data
+ //embeddedPlansTableInfo.table.fnAddData(data.result.tableData);
+ // current workaround: event on hidden.bs.modal
+
+ $('#addOptionDiag').modal('hide');
+ });
+});
+
+</script>
diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/jsp/servicetemplates/servicetemplate.jsp b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/servicetemplates/servicetemplate.jsp
new file mode 100644
index 0000000..b5349d6
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/servicetemplates/servicetemplate.jsp
@@ -0,0 +1,43 @@
+<%--
+/*******************************************************************************
+ * Copyright (c) 2012-2013, 2015 University of Stuttgart.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ * Oliver Kopp - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+--%>
+<%@page import="org.eclipse.winery.repository.resources.SubMenuData"%>
+
+<%@taglib prefix="t" tagdir="/WEB-INF/tags" %>
+
+<%-- add submenus after the submenus defined for the type --%>
+<%
+java.util.List<SubMenuData> subMenus = new java.util.ArrayList<SubMenuData>(5);
+
+SubMenuData data;
+
+data = new SubMenuData("#topologytemplate", "Topology Template");
+subMenus.add(data);
+
+data = new SubMenuData("#plans", "Plans");
+subMenus.add(data);
+
+data = new SubMenuData("#selfserviceportal", "Self-service Portal");
+subMenus.add(data);
+
+data = new SubMenuData("#boundarydefinitions", "Boundary Definitions");
+subMenus.add(data);
+
+//Tags are currently not implemented -> Don't confuse users by showing the tab
+//has to be enabled again, when tags are implemented
+//data = new SubMenuData("#tags", "Tags");
+//subMenus.add(data);
+%>
+
+<t:componentinstance cssClass="serviceTemplate" selected="ServiceTemplate" subMenus="<%=subMenus%>">
+</t:componentinstance>
diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/jsp/servicetemplates/topologytemplates/topologytemplate.jsp b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/servicetemplates/topologytemplates/topologytemplate.jsp
new file mode 100644
index 0000000..b5424ae
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/servicetemplates/topologytemplates/topologytemplate.jsp
@@ -0,0 +1,23 @@
+<%--
+/*******************************************************************************
+ * Copyright (c) 2012-2013,2015 University of Stuttgart.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ * Oliver Kopp - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+--%>
+<%@page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
+
+<div>
+ <a class="btn btn-primary" id="newtab" style="cursor:pointer;" href="${it.location}" target="_blank" >Open Editor</a>
+ <a class="btn btn-info" href="topologytemplate/?view" target="_blank" >Open View</a>
+ <br>
+ <br>
+ <div id="loading" class="topologyTemplatePreviewSizing" style="position:absolute; background-color: white; z-index:5;">Loading preview...</div>
+ <iframe id="topologyTemplatePreview" class="topologyTemplatePreviewSizing" src="topologytemplate/?view=small" onload="$('#loading').hide(1000);"></iframe>
+</div>
diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/jsp/servicetemplates/topologytemplates/topologytemplateview.jsp b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/servicetemplates/topologytemplates/topologytemplateview.jsp
new file mode 100644
index 0000000..789c174
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/servicetemplates/topologytemplates/topologytemplateview.jsp
@@ -0,0 +1,67 @@
+<%--
+/*******************************************************************************
+ * Copyright (c) 2013 University of Stuttgart.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ * Oliver Kopp - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+--%>
+<%@page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
+<%@page buffer="none" %>
+
+<%@page import="org.eclipse.winery.common.interfaces.IWineryRepository"%>
+<%@page import="org.eclipse.winery.repository.Prefs" %>
+<%@page import="org.eclipse.winery.repository.client.WineryRepositoryClientFactory"%>
+<%@page import="org.eclipse.winery.repository.client.IWineryRepositoryClient"%>
+<%@page import="org.eclipse.winery.repository.client.WineryRepositoryClient"%>
+
+<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
+<%@taglib prefix="t" tagdir="/WEB-INF/tags" %>
+<%@taglib prefix="w" uri="http://www.eclipse.org/winery/repository/functions"%>
+
+<html>
+<head>
+ <meta name="application-name" content="Winery" />
+ <meta charset="UTF-8">
+ <link rel="icon" href="${w:topologyModelerURI()}/favicon.png" type="image/png">
+
+ <link rel="stylesheet" href="${pageContext.request.contextPath}/components/bootstrap/dist/css/bootstrap.css" />
+ <link rel="stylesheet" href="${pageContext.request.contextPath}/components/bootstrap/dist/css/bootstrap-theme.css" />
+
+ <script type='text/javascript' src='${pageContext.request.contextPath}/components/requirejs/require.js'></script>
+
+ <!-- jquery and jquery UI have to be loaded using the old fashioned way to avoid incompatibilities with bootstrap v3 -->
+ <script type='text/javascript' src='${pageContext.request.contextPath}/components/jquery/jquery.js'></script>
+ <script type='text/javascript' src='${pageContext.request.contextPath}/3rdparty/jquery-ui/js/jquery-ui.js'></script>
+ <script type='text/javascript' src='${pageContext.request.contextPath}/components/bootstrap/dist/js/bootstrap.js'></script>
+ <script>
+ require.config({
+ baseUrl: "${pageContext.request.contextPath}/js",
+ paths: {
+ "datatables": "../components/datatables/media/js/jquery.dataTables",
+ "jquery": "../components/jquery/jquery",
+
+ // required for jsplumb
+ "jquery.ui": "../3rdparty/jquery-ui/js/jquery-ui",
+
+ "jsplumb": "../components/jsPlumb/dist/js/jquery.jsPlumb-1.5.4",
+
+ "winery-sugiyamaLayouter": "${w:topologyModelerURI()}/js/winery-sugiyamaLayouter"
+ }
+ });
+ </script>
+ <c:if test="${not empty it.additionalScript}">
+ <script type='text/javascript' src='${it.additionalScript}'></script>
+ </c:if>
+</head>
+<body>
+
+<t:topologyTemplateRenderer topology="${it.topologyTemplate}" repositoryURL="<%=Prefs.INSTANCE.getResourcePath()%>" client="${it.client}" fullscreen="true" additonalCSS="${it.additonalCSS}" autoLayoutOnLoad="${it.autoLayoutOnLoad}"/>
+
+</body>
+</html>