diff options
Diffstat (limited to 'winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/topologycompletion')
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">×</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">×</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">×</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">×</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 + <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 + <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> + |