summaryrefslogtreecommitdiffstats
path: root/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/topologycompletion
diff options
context:
space:
mode:
Diffstat (limited to 'winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/topologycompletion')
-rw-r--r--winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/topologycompletion/nodeTemplateSelector.tag230
-rw-r--r--winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/topologycompletion/relationshipTemplateSelector.tag158
-rw-r--r--winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/topologycompletion/selectionDialogs.tag175
-rw-r--r--winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/topologycompletion/topologyTemplateSelector.tag246
4 files changed, 809 insertions, 0 deletions
diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/topologycompletion/nodeTemplateSelector.tag b/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/topologycompletion/nodeTemplateSelector.tag
new file mode 100644
index 0000000..9d09fd3
--- /dev/null
+++ b/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/topologycompletion/nodeTemplateSelector.tag
@@ -0,0 +1,230 @@
+<%
+/*******************************************************************************
+ * Copyright (c) 2013 Pascal Hirmer.
+ * 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:
+ * Pascal Hirmer - initial API and implementation
+ *******************************************************************************/
+%>
+<%@tag language="java" pageEncoding="UTF-8" description="This tag is used to render Node and Relationship Templates for selection in a dialog."%>
+
+<%-- attributes for the NodeTemplate selection --%>
+<%@attribute name="templateURL" type="java.lang.String"%>
+<%@attribute name="topologyName" type="java.lang.String"%>
+<%@attribute name="topologyNamespace" type="java.lang.String"%>
+<%@attribute name="repositoryURL" type="java.lang.String" %>
+<%@attribute name="stName" type="java.lang.String" %>
+<%@attribute name="choices" type="java.util.Map<org.eclipse.winery.model.tosca.TNodeTemplate, java.util.Map<org.eclipse.winery.model.tosca.TNodeTemplate, java.util.List<org.eclipse.winery.model.tosca.TEntityTemplate>>>"%>
+
+<%@tag import="java.util.ArrayList"%>
+<%@tag import="java.util.HashMap"%>
+<%@tag import="java.util.List"%>
+<%@tag import="java.util.Map"%>
+<%@tag import="java.util.UUID"%>
+<%@tag import="javax.xml.namespace.QName"%>
+<%@tag import="org.eclipse.winery.model.tosca.TEntityTemplate"%>
+<%@tag import="org.eclipse.winery.model.tosca.TNodeTemplate"%>
+<%@tag import="org.eclipse.winery.model.tosca.TRelationshipTemplate"%>
+<%@tag import="org.eclipse.winery.model.tosca.TRelationshipType"%>
+<%@tag import="org.eclipse.winery.repository.client.WineryRepositoryClientFactory"%>
+<%@tag import="org.eclipse.winery.repository.client.IWineryRepositoryClient"%>
+<%@tag import="org.eclipse.winery.common.Util"%>
+
+<%@taglib prefix="ntrq" tagdir="/WEB-INF/tags/common/templates/nodetemplates/reqscaps" %>
+<%@taglib prefix="nt" tagdir="/WEB-INF/tags/common/templates/nodetemplates" %>
+
+<div id="nodeTemplateSelector">
+ <p> There are several possible Node Templates to be inserted. <br> Please select your desired NodeTemplate: </p>
+
+ <%
+ // the pixel distance between the displayed NodeTemplates
+ final int NODE_TEMPLATE_DISTANCE = 150;
+
+ IWineryRepositoryClient client = WineryRepositoryClientFactory.getWineryRepositoryClient();
+ client.addRepository(repositoryURL);
+
+ // instantiate variables
+ Map<String, String> idMap = new HashMap<String, String>();
+ List<TRelationshipTemplate> possibleConnections = new ArrayList<TRelationshipTemplate>();
+ String sourceId = "";
+ String randomId = "";
+ String id = "";
+
+ // a counter used for an ID
+ int counter = 0;
+
+ // used for the position of the NodeTemplate in the EditorArea
+ int topCounter = 0;
+ %>
+ <script>
+ // array to collect the created IDs
+ IDs = new Array();
+
+ // save all created connections in an array to be able to detach them after the selection
+ Connections = new Array();
+ </script>
+ <%
+ // render a topology for every choice to be displayed in the dialog
+ for (TNodeTemplate nt: choices.keySet()) {
+
+ Map<TNodeTemplate, List<TEntityTemplate>> entityTemplates = choices.get(nt);
+
+ for (TNodeTemplate choice: entityTemplates.keySet()) {
+ id = "choice" + Integer.toString(counter);
+
+ %>
+ <div id="proposalEditorArea">
+ <div id="proposaldrawingarea">
+ <%
+
+ topCounter = 0;
+ %>
+ <nt:nodeTemplateRenderer client="<%=client%>" relationshipTypes="<%=client.getAllTypes(TRelationshipType.class)%>" repositoryURL='<%=repositoryURL%>' nodeTemplate="<%=nt%>" top="<%=Integer.toString(topCounter)%>" left='<%="0"%>'/>
+ <script>
+
+ //Map IDs here. ID mapping is necessary to avoid conflict with the modelled NodeTemplates in the background.
+ <%
+ randomId = UUID.randomUUID().toString();
+ %>
+ document.getElementById("<%=nt.getId()%>").id = "<%=randomId%>";
+ IDs.push("<%=randomId%>");
+ <%
+ idMap.put(nt.getId(), randomId);
+ %>
+ </script>
+ <%
+
+ topCounter = topCounter + NODE_TEMPLATE_DISTANCE;
+ %>
+ <!-- use the nodeTemplateRenderer tag to render NodeTemplates-->
+ <nt:nodeTemplateRenderer client="<%=client%>" relationshipTypes="<%=client.getAllTypes(TRelationshipType.class)%>" repositoryURL='<%=repositoryURL%>' nodeTemplate="<%=choice%>" top="<%=Integer.toString(topCounter)%>" left='<%="0"%>'/>
+ <script>
+ //Map IDs here
+ <%
+ randomId = UUID.randomUUID().toString();
+ %>
+ document.getElementById("<%=choice.getId()%>").id = "<%=randomId%>";
+ IDs.push("<%=randomId%>");
+ <%
+ idMap.put(choice.getId(), randomId);
+ %>
+ </script>
+ </div>
+ </div>
+ <% if (entityTemplates.get(choice).size() > 1) { %>
+ <p> There are several possible Relationship Templates to connect the Node Templates <%=nt.getName()%> and <%=choice.getName()%>. Please choose at least one connection: </p>
+ <%}
+ for (TEntityTemplate rtChoice: entityTemplates.get(choice)) {
+
+ TRelationshipTemplate connector = (TRelationshipTemplate) rtChoice;
+ if (entityTemplates.get(choice).size() > 1) {
+ %>
+ <input checked="checked" id="<%=connector.getName()%>" name="<%=connector.getName()%>" type="checkbox" value="<%=connector.getName()%>"> <%=connector.getName()%> <br/>
+ <%
+ }
+ sourceId = ((TNodeTemplate) connector.getSourceElement().getRef()).getId();
+ String targetId = ((TNodeTemplate) connector.getTargetElement().getRef()).getId();
+ QName type = connector.getType();
+ String visualSourceId = idMap.get(sourceId);
+ String visualTargetId = idMap.get(targetId);
+ %>
+ <script>
+ // connect the rendered NodeTemplates
+ require(["winery-common-topologyrendering"], function(wct) {
+ wct.initNodeTemplate(jsPlumb.getSelector(".NodeTemplateShape:not('.hidden')"), true);
+ });
+ var c;
+ require(["jsplumb"], function(_jsPlumb) {
+ _jsPlumb.ready(function() {
+ c = _jsPlumb.connect({
+ source:"<%=visualSourceId%>",
+ target:"<%=visualTargetId%>",
+ endpoint:"Blank",
+ type: "<%=type%>"
+ });
+ Connections.push(c);
+ })
+ });
+
+ </script>
+ <%}
+ %>
+ <br>
+ <button type="button" class="btn btn-primary btn-default" data-dismiss="modal" id="<%=id%>" value='<%=choice.getName()%>' onclick="onSelected<%=choice.getName()%>()">Use Template: <%=choice.getName()%></button>
+ <script>
+
+ /**
+ * Handles a click on the "Select" button.
+ *
+ * This selection handler method is created for every NodeTemplate that can be chosen by the user.
+ * This is realized by inserting the unique names of the NodeTemplate choices in the method name via JSP scriptlet.
+ */
+ function onSelected<%=choice.getName()%>() {
+
+ SelectedRTs = new Array();
+
+ for (var i = 0; i < Connections.length; i++) {
+ jsPlumb.detach(Connections[i]);
+ }
+
+ <%
+ if (entityTemplates.get(choice).size() == 1) {
+ %>
+ SelectedRTs.push("<%=((TRelationshipTemplate) entityTemplates.get(choice).get(0)).getName()%>");
+ <%
+ } else if (entityTemplates.get(choice).size() > 1) {
+ for (TEntityTemplate rtChoice: entityTemplates.get(choice)) {
+ TRelationshipTemplate connector = (TRelationshipTemplate) rtChoice;
+ %>
+ if (document.getElementById("<%=connector.getName()%>").checked) {
+ SelectedRTs.push(document.getElementById("<%=connector.getName()%>").value);
+ }
+ <%
+ }}
+ %>
+ SelectedItems = new Array();
+ SelectedItems.push(document.getElementById("<%=id%>").value);
+
+ if (SelectedItems.length == 0) {
+ vShowError("Please selected at least one Relationship Template.");
+ } else {
+ // add the selected Templates to the topology and restart the completion
+ var selectedNodeTemplates = JSON.stringify(SelectedItems);
+ var selectedRelationshipTemplates = JSON.stringify(SelectedRTs);
+ $.post("jsp/topologyCompletion/selectionHandler.jsp", {topology: topology, allChoices: choices, selectedNodeTemplates: selectedNodeTemplates, selectedRelationshipTemplates: selectedRelationshipTemplates},
+ function(data){
+ require(["winery-topologycompletion"], function(completer) {
+ completer.restartCompletion(data, document.getElementById('overwriteTopology').checked,document.getElementById('openInNewWindow').checked,
+ document.getElementById('topologyName').value, document.getElementById('topologyNamespace').value, true, "<%=stName%>",
+ "<%=templateURL%>", "<%=repositoryURL%>");
+ });
+ }
+ );
+ }
+ }
+ </script>
+ <%
+ counter++;
+ }
+ }%>
+ <br>
+ <br>
+ <br>
+ <button type="button" class="btn btn-primary btn-default" data-dismiss="modal" id="cancel" onclick="onSelectedCancel()">Cancel Automatic Completion</button>
+ <p><i> Press this button if you want to continue the completion manually.</i> </p>
+ <script>
+ // save topology and refresh the page
+ function onSelectedCancel() {
+ $.post("jsp/topologyCompletion/topologySaver.jsp", {topology: topology, templateURL: "<%=templateURL%>", repositoryURL: "<%=repositoryURL%>", topologyName: "<%=topologyName%>", topologyNamespace: "<%=topologyNamespace%>", overwriteTopology: "true"},
+ function(callback){
+ document.location.reload(true);
+ }
+ );
+ }
+ </script>
+</div> \ No newline at end of file
diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/topologycompletion/relationshipTemplateSelector.tag b/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/topologycompletion/relationshipTemplateSelector.tag
new file mode 100644
index 0000000..58e2d85
--- /dev/null
+++ b/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/topologycompletion/relationshipTemplateSelector.tag
@@ -0,0 +1,158 @@
+<%
+/*******************************************************************************
+ * Copyright (c) 2013 Pascal Hirmer.
+ * 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:
+ * Pascal Hirmer - initial API and implementation
+ *******************************************************************************/
+%>
+
+<%@tag language="java" pageEncoding="UTF-8" description="This tag is used to render Relationship Templates for selection in a dialog."%>
+
+<%-- attributes for the topology selection --%>
+<%@attribute name="templateURL" type="java.lang.String"%>
+<%@attribute name="topologyName" type="java.lang.String"%>
+<%@attribute name="topologyNamespace" type="java.lang.String"%>
+<%@attribute name="repositoryURL" type="java.lang.String" %>
+<%@attribute name="stName" type="java.lang.String" %>
+<%@attribute name="choices" type="java.util.List<org.eclipse.winery.model.tosca.TEntityTemplate>"%>
+
+<%@tag import="java.util.ArrayList"%>
+<%@tag import="java.util.HashMap"%>
+<%@tag import="java.util.List"%>
+<%@tag import="java.util.Map"%>
+<%@tag import="java.util.UUID"%>
+<%@tag import="javax.xml.namespace.QName"%>
+<%@tag import="org.eclipse.winery.model.tosca.TEntityTemplate"%>
+<%@tag import="org.eclipse.winery.model.tosca.TNodeTemplate"%>
+<%@tag import="org.eclipse.winery.model.tosca.TRelationshipTemplate"%>
+<%@tag import="org.eclipse.winery.model.tosca.TRelationshipType"%>
+<%@tag import="org.eclipse.winery.repository.client.WineryRepositoryClientFactory"%>
+<%@tag import="org.eclipse.winery.repository.client.IWineryRepositoryClient"%>
+<%@tag import="org.eclipse.winery.common.Util"%>
+
+<%@taglib prefix="ntrq" tagdir="/WEB-INF/tags/common/templates/nodetemplates/reqscaps" %>
+<%@taglib prefix="nt" tagdir="/WEB-INF/tags/common/templates/nodetemplates" %>
+<%@taglib prefix="tc" tagdir="/WEB-INF/tags/common/topologycompletion"%>
+
+<div id="relationshipTemplateSelector">
+<p> There are several possible Relationship Templates for a connection. <br> Please select your desired connection(s): </p>
+<script>
+ // save all created connections in an array to be able to detach them after the selection
+ Connections = new Array();
+</script>
+<%
+ // the pixel distance between the displayed NodeTemplates
+ final int NODE_TEMPLATE_DISTANCE = 150;
+
+ IWineryRepositoryClient client = WineryRepositoryClientFactory.getWineryRepositoryClient();
+ client.addRepository(repositoryURL);
+
+ Map<String, String> idMap = new HashMap<String, String>();
+ String sourceId = "";
+ String id = "choice";
+
+ // used for the position of the NodeTemplate in the EditorArea
+ int topCounter = 0;
+
+ List<TRelationshipTemplate> possibleConnections = new ArrayList<TRelationshipTemplate>();
+
+ for (TEntityTemplate choice: choices) {
+ if (choice instanceof TRelationshipTemplate) {
+ possibleConnections.add((TRelationshipTemplate) choice);
+ }
+ }
+ for (TRelationshipTemplate connector: possibleConnections) { %>
+ <div id="proposalEditorArea">
+ <div id="proposaldrawingarea">
+ <div id="allRelationships">
+ <%
+ topCounter = 0;
+
+ for (TEntityTemplate choice: choices) {
+ if (choice instanceof TNodeTemplate) {
+ TNodeTemplate nodeTemplate = (TNodeTemplate) choice;
+
+ topCounter = topCounter + NODE_TEMPLATE_DISTANCE;
+ %>
+ <nt:nodeTemplateRenderer client="<%=client%>" relationshipTypes="<%=client.getAllTypes(TRelationshipType.class)%>" repositoryURL='<%=repositoryURL%>' nodeTemplate="<%=nodeTemplate%>" top="<%=Integer.toString(topCounter)%>" left='<%="0"%>'/>
+ <script>
+ //Map IDs here
+ <%
+ String randomId = UUID.randomUUID().toString();
+ %>
+ document.getElementById("<%=nodeTemplate.getId()%>").id = "<%=randomId%>";
+ <%
+ idMap.put(nodeTemplate.getId(), randomId);
+ %>
+ </script>
+ <%
+ }
+ }
+
+ sourceId = ((TNodeTemplate) connector.getSourceElement().getRef()).getId();
+ String targetId = ((TNodeTemplate) connector.getTargetElement().getRef()).getId();
+ QName type = connector.getType();
+
+ String visualSourceId = idMap.get(sourceId);
+ String visualTargetId = idMap.get(targetId);
+ %>
+ <script>
+ // connect the rendered NodeTemplates
+ require(["winery-common-topologyrendering"], function(wct) {
+ wct.initNodeTemplate(jsPlumb.getSelector(".NodeTemplateShape:not('.hidden')"), true);
+ });
+ var c;
+ require(["jsplumb"], function(_jsPlumb) {
+ _jsPlumb.ready(function() {
+ c = _jsPlumb.connect({
+ source:"<%=visualSourceId%>",
+ target:"<%=visualTargetId%>",
+ endpoint:"Blank",
+ type: "<%=type%>"
+ });
+ Connections.push(c);
+ })
+ });
+ </script>
+ </div>
+ </div>
+ </div>
+ <input id="<%=id%>" name="<%=id%>" type="checkbox" value="<%=connector.getName()%>"> <%=connector.getName()%> <br>
+
+ <%}%>
+ <button type="button" class="btn btn-primary btn-default" id="btnUseSelection" onclick="useRelationshipTemplateSelection()">Use Selection</button>
+ <script>
+ function useRelationshipTemplateSelection() {
+ // add the selected RelationshipTemplates to the topology and restart the completion
+ SelectedItems = new Array();
+ for (var i= 0; i < document.getElementById("rtchoices").children[0].choice.length; i++) {
+ if (document.getElementById("rtchoices").children[0].choice[i].checked == true) {
+ SelectedItems.push(document.getElementById("rtchoices").children[0].choice[i].value);
+ }
+ }
+
+ if (SelectedItems.length == 0) {
+ vShowError("Please selected at least one Relationship Template.");
+ } else {
+ $('#chooseRelationshipTemplateDiag').modal('hide');
+ var selectedRelationshipTemplates = JSON.stringify(SelectedItems);
+ // add selected RelationshipTemplate(s) to the topology
+ $.post("jsp/topologyCompletion/selectionHandler.jsp", {topology: topology, allChoices: choices, selectedRelationshipTemplates: selectedRelationshipTemplates},
+ function(data) {
+ require(["winery-topologycompletion"], function(completer) {
+ completer.restartCompletion(data, document.getElementById('overwriteTopology').checked,document.getElementById('openInNewWindow').checked,
+ topologyName, topologyNamespace, true, "<%=stName%>",
+ "<%=templateURL%>", "<%=repositoryURL%>");
+ });
+ }
+ );
+ }
+ }
+ </script>
+</div>
diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/topologycompletion/selectionDialogs.tag b/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/topologycompletion/selectionDialogs.tag
new file mode 100644
index 0000000..9edfced
--- /dev/null
+++ b/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/topologycompletion/selectionDialogs.tag
@@ -0,0 +1,175 @@
+<%
+/*******************************************************************************
+ * Copyright (c) 2013 Pascal Hirmer.
+ * 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:
+ * Pascal Hirmer - initial API and implementation
+ *******************************************************************************/
+%>
+<%@tag language="java" pageEncoding="UTF-8" description="This tag is used to create DIVs for the selection dialogs."%>
+
+<%@attribute name="repositoryURL" type="java.lang.String"%>
+<%@attribute name="serviceTemplateName" type="java.lang.String"%>
+<%@attribute name="topologyTemplateURL" type="java.lang.String"%>
+
+<!--
+ Topology Completion: chooseRelationshipTemplateDiag.
+ This dialog serves the user selection of inserted RelationshipTemplates whenever there are several possibilities.
+-->
+<div class="modal fade" id="chooseRelationshipTemplateDiag">
+ <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">Topology Completion - Relationship Template Selection</h4>
+ </div>
+ <div class="modal-body"></div>
+ <div class="modal-footer"></div>
+ </div>
+ </div>
+</div>
+
+<!--
+ Topology Completion: chooseNodeTemplateDiag.
+ This dialog serves the user selection of inserted Node and RelationshipTemplates when the user selects "Complete topology step-by-step".
+-->
+<div class="modal fade" id="chooseNodeTemplateDiag">
+ <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">Topology Completion - Step by Step</h4>
+ </div>
+ <div class="modal-body"></div>
+ <div class="modal-footer">
+ <button type="button" class="btn btn-danger" data-dismiss="modal">Cancel</button>
+ </div>
+ </div>
+ </div>
+</div>
+
+<!--
+ Topology Completion: chooseTopologyDiag.
+ This dialog serves the user selection of completed topologies.
+-->
+<div class="modal fade" id="chooseTopologyDiag">
+ <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">Topology Completion - Choose possible solution </h4>
+ </div>
+ <div class="modal-body"></div>
+ <div class="modal-footer">
+ <button type="button" class="btn btn-danger" data-dismiss="modal">Cancel</button>
+ </div>
+ </div>
+ </div>
+</div>
+
+<!--
+ Topology Completion: enterCompletionInformationDiag.
+ This dialog serves the input of information before completing a topology automatically.
+-->
+<div class="modal fade" id="enterCompletionInformationDiag">
+ <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">Topology Completion</h4>
+ </div>
+ <div class="modal-body">
+ <form id="enterCompletionInformationForm" enctype="multipart/form-data">
+ <fieldset>
+ <p> Select Save Option: </p>
+ <p> <input type="radio" id="overwriteTopology" name="overwriteTopology" onclick="document.getElementById('topologyNamespace').disabled = true; document.getElementById('topologyName').disabled = true; document.getElementById('openInNewWindow').disabled = true;" checked> Overwrite Topology<br>
+ <input type="radio" id="overwriteTopology" name="overwriteTopology" onclick="document.getElementById('topologyNamespace').disabled = false; document.getElementById('topologyName').disabled = false;document.getElementById('openInNewWindow').disabled = false;"> Create new Topology </p> <p> Name: <input id="topologyName" name="topologyName" disabled="disabled" type="text" size="30" maxlength="30"> </p> <p>Namespace: <input id="topologyNamespace" name="topologyNamespace" disabled="disabled" type="text" size="50" maxlength="60"> </p>
+ <input id="openInNewWindow" name="openInNewWindow" type="checkbox" disabled="disabled" /> Open Topology in new Window <br>
+ <input id="completionStyle" name="completionStyle" type="checkbox" /> Complete Topology Step-by-Step
+ </fieldset>
+ </form>
+ </div>
+ <div class="modal-footer">
+ <button type="button" class="btn" data-dismiss="modal">Cancel</button>
+ <button type="button" class="btn btn-primary btn-default" id="btnCompleteTopology" onclick="onClickCompleteTopology()">Complete Topology</button>
+ <script>
+ function onClickCompleteTopology() {
+ var namespace = document.getElementById('topologyNamespace').value;
+ var validURIregexp = new RegExp("([A-Za-z][A-Za-z0-9+\\-.]*):(?:(//)(?:((?:[A-Za-z0-9\\-._~!$&'()*+,;=:]|%[0-9A-Fa-f]{2})*)@)?((?:\\[(?:(?:(?:(?:[0-9A-Fa-f]{1,4}:){6}|::(?:[0-9A-Fa-f]{1,4}:){5}|(?:[0-9A-Fa-f]{1,4})?::(?:[0-9A-Fa-f]{1,4}:){4}|(?:(?:[0-9A-Fa-f]{1,4}:){0,1}[0-9A-Fa-f]{1,4})?::(?:[0-9A-Fa-f]{1,4}:){3}|(?:(?:[0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})?::(?:[0-9A-Fa-f]{1,4}:){2}|(?:(?:[0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})?::[0-9A-Fa-f]{1,4}:|(?:(?:[0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})?::)(?:[0-9A-Fa-f]{1,4}:[0-9A-Fa-f]{1,4}|(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))|(?:(?:[0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})?::[0-9A-Fa-f]{1,4}|(?:(?:[0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})?::)|[Vv][0-9A-Fa-f]+\\.[A-Za-z0-9\\-._~!$&'()*+,;=:]+)\\]|(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)|(?:[A-Za-z0-9\\-._~!$&'()*+,;=]|%[0-9A-Fa-f]{2})*))(?::([0-9]*))?((?:/(?:[A-Za-z0-9\\-._~!$&'()*+,;=:@]|%[0-9A-Fa-f]{2})*)*)|/((?:(?:[A-Za-z0-9\\-._~!$&'()*+,;=:@]|%[0-9A-Fa-f]{2})+(?:/(?:[A-Za-z0-9\\-._~!$&'()*+,;=:@]|%[0-9A-Fa-f]{2})*)*)?)|((?:[A-Za-z0-9\\-._~!$&'()*+,;=:@]|%[0-9A-Fa-f]{2})+(?:/(?:[A-Za-z0-9\\-._~!$&'()*+,;=:@]|%[0-9A-Fa-f]{2})*)*)|)(?:\\?((?:[A-Za-z0-9\\-._~!$&'()*+,;=:@/?]|%[0-9A-Fa-f]{2})*))?(?:\#((?:[A-Za-z0-9\\-._~!$&'()*+,;=:@/?]|%[0-9A-Fa-f]{2})*))?");
+ if (!document.getElementById('overwriteTopology').checked && document.getElementById('topologyName').value == "") {
+ vShowError("Please enter a name for the new topology.");
+ } else if (!document.getElementById('overwriteTopology').checked && (document.getElementById('topologyNamespace').value == "" || !validURIregexp.test(namespace))) {
+ vShowError("Please enter a valid name space for the new topology.");
+ }
+ else {
+ $('#enterCompletionInformationDiag').modal('hide');
+
+ require(["winery-topologycompletion"], function(completer) {
+ completer.complete(document.getElementById('overwriteTopology').checked,document.getElementById('openInNewWindow').checked,document.getElementById('topologyName').value, document.getElementById('topologyNamespace').value, document.getElementById('completionStyle').checked,
+ "<%=repositoryURL%>", "<%=serviceTemplateName%>", "<%=topologyTemplateURL%>");
+ });
+
+ }
+ }
+ </script>
+ </div>
+ </div>
+ </div>
+</div>
+
+<script>
+ $(function() {
+ chooseRelationshipTemplateDiag = $('#chooseRelationshipTemplateDiag');
+
+ chooseRelationshipTemplateDiag.on('show', function() {
+ $(this).find('form')[0].reset();
+ });
+
+ chooseNodeTemplateDiag = $('#chooseNodeTemplateDiag');
+
+ chooseNodeTemplateDiag.on('show', function() {
+ $(this).find('form')[0].reset();
+ });
+
+ chooseNodeTemplateDiag.on('hidden.bs.modal', function () {
+ for (var i = 0; i < Connections.length; i++) {
+ jsPlumb.detach(Connections[i]);
+ }
+ $(document.getElementById("nodeTemplateSelector")).remove();
+ });
+
+ chooseTopologyDiag = $('#chooseTopologyDiag');
+
+ chooseTopologyDiag.on('show', function() {
+ $(this).find('form')[0].reset();
+ });
+
+ chooseTopologyDiag.on('hidden.bs.modal', function () {
+ for (var i = 0; i < Connections.length; i++) {
+ jsPlumb.detach(Connections[i]);
+ }
+ $(document.getElementById("topologyTemplateSelector")).remove();
+ });
+
+ enterCompletionInformationDiag = $('#enterCompletionInformationDiag');
+
+ enterCompletionInformationDiag.on('show', function() {
+ $(this).find('form')[0].reset();
+ });
+ });
+
+ /**
+ * This function is invoked when the button "Complete Topology" is
+ * selected. It will open a dialog to enter necessary information for the
+ * completion.
+ */
+ function completeTopology() {
+ // show the dialog to enter information for the topology completion
+ enterCompletionInformationDiag.modal("show");
+ }
+</script> \ No newline at end of file
diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/topologycompletion/topologyTemplateSelector.tag b/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/topologycompletion/topologyTemplateSelector.tag
new file mode 100644
index 0000000..0d73a57
--- /dev/null
+++ b/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/topologycompletion/topologyTemplateSelector.tag
@@ -0,0 +1,246 @@
+<%
+/*******************************************************************************
+ * Copyright (c) 2013 Pascal Hirmer.
+ * 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:
+ * Pascal Hirmer - initial API and implementation
+ *******************************************************************************/
+%>
+
+<%@tag language="java" pageEncoding="UTF-8" description="This tag is used to render Topology Templates for selection in a dialog."%>
+
+<%-- attributes for the topology selection --%>
+<%@attribute name="templateURL" type="java.lang.String"%>
+<%@attribute name="topologyName" type="java.lang.String"%>
+<%@attribute name="topologyNamespace" type="java.lang.String"%>
+<%@attribute name="repositoryURL" type="java.lang.String" %>
+<%@attribute name="solutionTopologies" type="java.util.List<org.eclipse.winery.model.tosca.TTopologyTemplate>"%>
+
+<%@tag import="java.io.StringWriter"%>
+<%@tag import="java.util.HashMap"%>
+<%@tag import="java.util.Map"%>
+<%@tag import="java.util.List"%>
+<%@tag import="java.util.UUID"%>
+<%@tag import="javax.xml.bind.Marshaller"%>
+<%@tag import="javax.xml.bind.JAXBContext"%>
+<%@tag import="javax.xml.bind.JAXBException"%>
+<%@tag import="javax.xml.namespace.QName"%>
+<%@tag import="org.eclipse.winery.model.tosca.Definitions"%>
+<%@tag import="org.eclipse.winery.model.tosca.TEntityTemplate"%>
+<%@tag import="org.eclipse.winery.model.tosca.TNodeTemplate"%>
+<%@tag import="org.eclipse.winery.model.tosca.TRelationshipTemplate"%>
+<%@tag import="org.eclipse.winery.model.tosca.TRelationshipType"%>
+<%@tag import="org.eclipse.winery.model.tosca.TServiceTemplate"%>
+<%@tag import="org.eclipse.winery.model.tosca.TTopologyTemplate"%>
+<%@tag import="org.eclipse.winery.repository.client.WineryRepositoryClientFactory"%>
+<%@tag import="org.eclipse.winery.repository.client.IWineryRepositoryClient"%>
+<%@tag import="org.eclipse.winery.common.Util"%>
+
+<%@taglib prefix="ntrq" tagdir="/WEB-INF/tags/common/templates/nodetemplates/reqscaps" %>
+<%@taglib prefix="nt" tagdir="/WEB-INF/tags/common/templates/nodetemplates"%>
+
+<div id="topologyTemplateSelector">
+<p> There are several possible topology solutions <br> Please select your desired topology: </p>
+ <script>
+ // array to collect the created IDs
+ IDs = new Array();
+
+ // save all created connections in an array to be able to detach them after the selection
+ Connections = new Array();
+ </script>
+<%
+ // the pixel distance between the displayed NodeTemplates
+ final int NODE_TEMPLATE_DISTANCE = 150;
+
+ List<TTopologyTemplate> topologyTemplateSelector = solutionTopologies;
+ int i = 0;
+ int counter = 0;
+ Map<String, String> idMap;
+ for (TTopologyTemplate choice: topologyTemplateSelector) {
+ Definitions definitions = new Definitions();
+ TServiceTemplate st = new TServiceTemplate();
+ st.setTopologyTemplate(choice);
+ definitions.getServiceTemplateOrNodeTypeOrNodeTypeImplementation().add(st);
+ JAXBContext context = JAXBContext.newInstance(Definitions.class);
+ Marshaller m = context.createMarshaller();
+ StringWriter stringWriter = new StringWriter();
+
+ m.marshal(definitions, stringWriter);
+ int topCounter = 0;
+ IWineryRepositoryClient client = WineryRepositoryClientFactory.getWineryRepositoryClient();
+ client.addRepository(repositoryURL);
+ String id = "solution" + Integer.toString(i);
+
+ String sourceId = null;
+ idMap = new HashMap<String, String>();
+
+ %>
+ <div id="proposalEditorArea">
+ <div id="proposaldrawingarea">
+ <div id="<%=counter%>">
+ <script> IDs.push("<%=id%>"); </script>
+ <%
+ for (TEntityTemplate entity: choice.getNodeTemplateOrRelationshipTemplate()) {
+
+ if (entity instanceof TNodeTemplate) {
+ TNodeTemplate nodeTemplate = (TNodeTemplate) entity;
+
+ %>
+ <nt:nodeTemplateRenderer client="<%=client%>" relationshipTypes="<%=client.getAllTypes(TRelationshipType.class)%>" repositoryURL='<%=repositoryURL%>' nodeTemplate="<%=nodeTemplate%>" top="<%=Integer.toString(topCounter)%>" left='<%="0"%>'/>
+
+ <%
+ String randomId = UUID.randomUUID().toString();
+ %>
+ <script>
+ document.getElementById("<%=nodeTemplate.getId()%>").id = "<%=randomId%>";
+ </script>
+ <%
+ topCounter = topCounter + NODE_TEMPLATE_DISTANCE;
+ idMap.put(nodeTemplate.getId(), randomId);
+ %>
+
+ <%
+ }
+ }
+ for (TEntityTemplate entity: choice.getNodeTemplateOrRelationshipTemplate()) {
+ if (entity instanceof TRelationshipTemplate) {
+ TRelationshipTemplate connector = (TRelationshipTemplate) entity;
+ sourceId = ((TNodeTemplate) connector.getSourceElement().getRef()).getId();
+ String visualSourceId = idMap.get(sourceId);
+ String targetId = ((TNodeTemplate) connector.getTargetElement().getRef()).getId();
+ String visualTargetId = idMap.get(targetId);
+ QName type = connector.getType();
+ %>
+ <script type='text/javascript'>
+ var c;
+ require(["winery-common-topologyrendering"], function(wct) {
+ wct.initNodeTemplate(jsPlumb.getSelector(".NodeTemplateShape:not('.hidden')"), true);
+ require(["jsplumb"], function(_jsPlumb) {
+ _jsPlumb.ready(function() {
+ c = _jsPlumb.connect({
+ source:"<%=visualSourceId%>",
+ target:"<%=visualTargetId%>",
+ endpoint:"Blank",
+ type: "<%=type%>"
+ });
+ Connections.push(c);
+ })
+ });
+ wct.handleConnectionCreated(c);
+ });
+ </script> <%
+ }
+ }
+ %>
+ </div>
+ </div>
+ </div>
+ <br>
+ <input name="<%=id%>" id="<%=id%>" type="checkbox" value='<%=stringWriter.toString()%>' onclick="onClick<%=id%>()"> Save this Topology &nbsp; &nbsp;
+ <script>
+ /**
+ * Handles a click on the "Save this Topology" checkbox.
+ */
+ function onClick<%=id%>() {
+ if (document.getElementById('<%=id%>').checked) {
+ document.getElementById('<%=id + "overwrite"%>').disabled = false;
+ document.getElementById('<%=id + "name"%>').disabled = false;
+ document.getElementById('<%=id + "namespace"%>').disabled = false;
+ document.getElementById('<%=id + "newWindow"%>').disabled = false;
+ }
+ else {
+ document.getElementById('<%=id + "overwrite"%>').disabled = true;
+ document.getElementById('<%=id + "name"%>').disabled = true;
+ document.getElementById('<%=id + "namespace"%>').disabled = true;
+ document.getElementById('<%=id + "newWindow"%>').disabled = true;
+ }
+ }
+ </script>
+ <input disabled="disabled" name='<%=id + "overwrite"%>' id='<%=id + "overwrite"%>' type="checkbox" onclick='onClick<%=id + "overwrite"%>()'> Overwrite current Topology &nbsp; &nbsp;
+ <script>
+ /**
+ * Handles a click on the "Overwrite current Topology" checkbox.
+ */
+ function onClick<%=id + "overwrite"%>() {
+ if (document.getElementById('<%=id + "overwrite"%>').checked) {
+ document.getElementById('<%=id + "name"%>').disabled = true;
+ document.getElementById('<%=id + "namespace"%>').disabled = true;
+ document.getElementById('<%=id + "newWindow"%>').disabled = true;
+ } else {
+ document.getElementById('<%=id + "name"%>').disabled = false;
+ document.getElementById('<%=id + "namespace"%>').disabled = false;
+ document.getElementById('<%=id + "newWindow"%>').disabled = false;
+ }
+ }
+ </script>
+ <input disabled="disabled" name='<%=id + "newWindow"%>' id='<%=id + "newWindow"%>' type="checkbox"> Open in new Window <br> <br>
+ <p>Name: <input disabled="disabled" id='<%=id + "name"%>' name='<%=id + "name"%>' value="<%=topologyName%>" type="text" size="30" maxlength="30"> </p>
+ <p>Namespace: <input disabled="disabled" id='<%=id + "namespace"%>' value="<%=topologyNamespace%>" name='<%=id + "namespace"%>' type="text" size="50" maxlength="60"> </p>
+ <%
+ counter++;
+ i++;
+ }
+%>
+ <button type="button" id="save" class="btn btn-primary btn-default">Save Topologies</button>
+ <script>
+ $('#save').on('click', function() {
+
+ for (var i = 0; i < IDs.length; i++) {
+ if (document.getElementById(IDs[i]).checked) {
+
+ var name = document.getElementById(IDs[i] + 'name').value;
+ var namespace = document.getElementById(IDs[i] + 'namespace').value;
+ var overwrite = document.getElementById(IDs[i] + 'overwrite').checked;
+ var openInNewWindow = document.getElementById(IDs[i] + 'newWindow').checked;
+
+ // check validity of the namespace
+ var validURIregexp = new RegExp("([A-Za-z][A-Za-z0-9+\\-.]*):(?:(//)(?:((?:[A-Za-z0-9\\-._~!$&'()*+,;=:]|%[0-9A-Fa-f]{2})*)@)?((?:\\[(?:(?:(?:(?:[0-9A-Fa-f]{1,4}:){6}|::(?:[0-9A-Fa-f]{1,4}:){5}|(?:[0-9A-Fa-f]{1,4})?::(?:[0-9A-Fa-f]{1,4}:){4}|(?:(?:[0-9A-Fa-f]{1,4}:){0,1}[0-9A-Fa-f]{1,4})?::(?:[0-9A-Fa-f]{1,4}:){3}|(?:(?:[0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})?::(?:[0-9A-Fa-f]{1,4}:){2}|(?:(?:[0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})?::[0-9A-Fa-f]{1,4}:|(?:(?:[0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})?::)(?:[0-9A-Fa-f]{1,4}:[0-9A-Fa-f]{1,4}|(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))|(?:(?:[0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})?::[0-9A-Fa-f]{1,4}|(?:(?:[0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})?::)|[Vv][0-9A-Fa-f]+\\.[A-Za-z0-9\\-._~!$&'()*+,;=:]+)\\]|(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)|(?:[A-Za-z0-9\\-._~!$&'()*+,;=]|%[0-9A-Fa-f]{2})*))(?::([0-9]*))?((?:/(?:[A-Za-z0-9\\-._~!$&'()*+,;=:@]|%[0-9A-Fa-f]{2})*)*)|/((?:(?:[A-Za-z0-9\\-._~!$&'()*+,;=:@]|%[0-9A-Fa-f]{2})+(?:/(?:[A-Za-z0-9\\-._~!$&'()*+,;=:@]|%[0-9A-Fa-f]{2})*)*)?)|((?:[A-Za-z0-9\\-._~!$&'()*+,;=:@]|%[0-9A-Fa-f]{2})+(?:/(?:[A-Za-z0-9\\-._~!$&'()*+,;=:@]|%[0-9A-Fa-f]{2})*)*)|)(?:\\?((?:[A-Za-z0-9\\-._~!$&'()*+,;=:@/?]|%[0-9A-Fa-f]{2})*))?(?:\#((?:[A-Za-z0-9\\-._~!$&'()*+,;=:@/?]|%[0-9A-Fa-f]{2})*))?");
+ if (validURIregexp.test(namespace) || overwrite) {
+
+ if (!overwrite) {
+ // first create a new service template via AJAX call
+ var dataToSend = "name=" + name + "&namespace=" + namespace;
+ var url = "<%=repositoryURL%>" + "/servicetemplates/";
+ $.ajax(
+ {
+ type: "POST",
+ async: false,
+ url: url,
+ "data": dataToSend,
+ dataType: "text",
+ error: function(jqXHR, textStatus, errorThrown) {
+ vShowAJAXError("Could not add Service Template.");
+ }
+ });
+ }
+
+ // now save the topology template
+ $.post("jsp/topologyCompletion/topologySaver.jsp", {topology: document.getElementById(IDs[i]).value, templateURL: "<%=templateURL%>", repositoryURL: "<%=repositoryURL%>", topologyName: name, topologyNamespace: namespace, overwriteTopology: overwrite},
+ function(data){
+ if (openInNewWindow) {
+ // a new topology has been created, open it in a new window
+ var win=window.open('?repositoryURL=' + "<%=repositoryURL%>" + '&ns='+ namespace + '&id=' + name, '_blank');
+ win.focus();
+ } else if (overwrite) {
+ // refresh page
+ document.location.reload(true);
+ }
+ // close the dialog
+ chooseTopologyDiag.modal("hide");
+ vShowSuccess("Successfully Saved Topologies.")
+ }
+ );
+ } else {
+ vShowError("Please enter a valid namespace.");
+ }
+ }
+ }
+ });
+ </script>
+</div>
+