diff options
Diffstat (limited to 'winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF')
33 files changed, 4116 insertions, 0 deletions
diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/common-functions.tld b/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/common-functions.tld new file mode 100644 index 0000000..ffe076d --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/common-functions.tld @@ -0,0 +1,70 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<!-- +/******************************************************************************* + * Copyright (c) 2012-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 + *******************************************************************************/ +--> +<taglib + xmlns="http://java.sun.com/xml/ns/javaee" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd" + version="2.1"> + + <tlib-version>1.0</tlib-version> + <short-name>Winery_Common_Functions</short-name> + <uri>http://www.eclipse.org/winery/functions</uri> + + <!-- from org.eclipse.winery.common.ModelUtilities --> + <function> + <name>winerysPropertiesDefinition</name> + <function-class>org.eclipse.winery.common.ModelUtilities</function-class> + <function-signature>org.eclipse.winery.common.propertydefinitionkv.WinerysPropertiesDefinition getWinerysPropertiesDefinition(org.eclipse.winery.model.tosca.TEntityType)</function-signature> + </function> + + <!-- from org.eclipse.winery.common.Util --> + <function> + <name>convertQNameListToNamespaceToLocalNameList</name> + <function-class>org.eclipse.winery.common.Util</function-class> + <function-signature>java.util.SortedMap convertQNameListToNamespaceToLocalNameList(java.util.List)</function-signature> + </function> + <function> + <name>getType</name> + <function-class>org.eclipse.winery.common.Util</function-class> + <function-signature>org.eclipse.winery.model.tosca.TEntityType getType(org.eclipse.winery.common.interfaces.IWineryRepository, javax.xml.namespace.QName, java.lang.Class)</function-signature> + </function> + <function> + <name>makeCSSName</name> + <function-class>org.eclipse.winery.common.Util</function-class> + <function-signature>java.lang.String makeCSSName(java.lang.String, java.lang.String)</function-signature> + </function> + <function> + <name>XMLAsString</name> + <function-class>org.eclipse.winery.common.Util</function-class> + <function-signature>java.lang.String getXMLAsString(java.lang.Class, java.lang.Object)</function-signature> + </function> + <function> + <name>DOMElementAsString</name> + <function-class>org.eclipse.winery.common.Util</function-class> + <function-signature>java.lang.String getXMLAsString(org.w3c.dom.Element)</function-signature> + </function> + <function> + <name>qname2href</name> + <function-class>org.eclipse.winery.common.Util</function-class> + <function-signature>java.lang.String qname2href(java.lang.String, java.lang.Class, javax.xml.namespace.QName)</function-signature> + </function> + + <!-- from Apache Commons Lang3 --> + <function> + <name>escapeHtml4</name> + <function-class>org.apache.commons.lang3.StringEscapeUtils</function-class> + <function-signature>java.lang.String escapeHtml4(java.lang.String)</function-signature> + </function> +</taglib> diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/functions.tld b/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/functions.tld new file mode 100644 index 0000000..4157f96 --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/functions.tld @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<!-- +/******************************************************************************* + * 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 + *******************************************************************************/ +--> +<taglib + xmlns="http://java.sun.com/xml/ns/javaee" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd" + version="2.1"> + + <tlib-version>1.0</tlib-version> + <short-name>Winery_TopologyModeler_Functions</short-name> + <uri>http://www.eclipse.org/winery/topologymodeler/functions</uri> + + <function> + <name>convertQNameWithNameListToNamespaceToLocalNameNamePairList</name> + <function-class>org.eclipse.winery.topologymodeler.WineryUtil</function-class> + <function-signature>java.util.SortedMap convertQNameWithNameListToNamespaceToLocalNameNamePairList(java.util.List)</function-signature> + </function> + + <function> + <name>escapeHtml4</name> + <function-class>org.apache.commons.lang3.StringEscapeUtils</function-class> + <function-signature>java.lang.String escapeHtml4(java.lang.String)</function-signature> + </function> +</taglib> diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/about.tag b/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/about.tag new file mode 100644 index 0000000..7cb73b2 --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/about.tag @@ -0,0 +1,58 @@ +<%-- +/******************************************************************************* + * 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 + *******************************************************************************/ +--%> + +<%@tag description="About for the repository" pageEncoding="UTF-8"%> + +<div class="modal fade" id="about"> + <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">Winery Topology Modeler ${project.version}</h4> + </div> + <div class="modal-body"> + <p> Supporting <a href="docs.oasis-open.org/tosca/TOSCA/v1.0/os/TOSCA-v1.0-os.html">TOSCA-v1.0 – + Topology and Orchestration Specification for Cloud Applications Version 1.0. 25 November 2013. OASIS Standard.</a><br/> + <br/> + Part of the <a href="http://www.cloudcycle.org">CloudCycle</a> ecosystem.<br/> + <br/> + Code contributions by Oliver Kopp, Uwe Breitenbücher, Kálmán Képes, Yves Schubert, and Tobias Unger. + </p> + <h3>License</h3> + <p>The Eclipse Foundation makes available all content of this software (“Content”). + Unless otherwise indicated below, the Content is provided to you under the terms and conditions of the Eclipse Public License Version 1.0 (“EPL”) and the and the Apache License 2.0. + A copy of the EPL is available at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>. + A copy of the ASL is available at <a href="http://www.apache.org/licenses/LICENSE-2.0.html">http://www.apache.org/licenses/LICENSE-2.0.html</a>. + For purposes of the EPL, “Program” will mean the Content.</p> + <p>If you did not receive this Content directly from the Eclipse Foundation, the Content is being redistributed by another party (“Redistributor”) and different terms and conditions may apply to your use of any object code in the Content. + Check the Redistributor's license that was provided with the Content. + If no such license exists, contact the Redistributor. + Unless otherwise indicated below, the terms and conditions of the EPL still apply to any source code in the Content and such source code may be obtained at <a href="http://www.eclipse.org">http://www.eclipse.org</a>.</p> + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-primary" data-dismiss="modal" id="aboutDiagOKButton">Ok</button> + </div> + </div> + </div> +</div> + +<script> +$("#about").on("shown.bs.modal", function() { + $("#aboutDiagOKButton").focus(); +}); + +function showAbout() { + $("#about").modal("show"); +} +</script>
\ No newline at end of file diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/QNameChooser.tag b/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/QNameChooser.tag new file mode 100644 index 0000000..7a2c067 --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/QNameChooser.tag @@ -0,0 +1,46 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2012-2014 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 + *******************************************************************************/ +--%> +<%@tag description="Dialog parts for choosing a QName" pageEncoding="UTF-8"%> + +<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@taglib prefix="wc" uri="http://www.eclipse.org/winery/functions"%> + +<%@attribute name="allQNames" required="true" type="java.util.Collection" description="Collection<QName> of all available QNames" %> +<%@attribute name="includeNONE" required="false" type="java.lang.Boolean" description="Should (none) be included as option?"%> +<%@attribute name="selected" required="false" description="The initial value to select"%> +<%@attribute name="labelOfSelectField" required="true"%> +<%@attribute name="idOfSelectField" required="true"%> + +<div class="form-group"> + <c:if test="${not empty labelOfSelectField}"><label for="${idOfSelectField}" class="control-label">${labelOfSelectField}:</label></c:if> + <select id="${idOfSelectField}" name="${idOfSelectField}" class="form-control"> + <c:if test="${includeNONE}"><option value="(none)">(none)</option></c:if> + <c:forEach var="namespaceEntry" items="${wc:convertQNameListToNamespaceToLocalNameList(allQNames)}"> + <optgroup label="${namespaceEntry.key}"> + <c:forEach var="localName" items="${namespaceEntry.value}"> + <option value="{${namespaceEntry.key}}${localName}">${localName}</option> + </c:forEach> + </optgroup> + </c:forEach> + </select> +</div> + +<script> +$(function(){ + $("#${idOfSelectField}").select2(); + <c:if test="${not empty selected}"> + $("#${idOfSelectField}").select2("val", "${selected}"); + </c:if> +}); +</script> diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/artifactcreationdialog.tag b/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/artifactcreationdialog.tag new file mode 100644 index 0000000..5e49b04 --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/artifactcreationdialog.tag @@ -0,0 +1,443 @@ +<%-- +/******************************************************************************* + * 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 + *******************************************************************************/ +--%> +<%@tag description="Dialog for adding an implementation / deployment artifact" pageEncoding="UTF-8"%> +<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> +<%@taglib prefix="fup" tagdir="/WEB-INF/tags/common"%> + +<%@attribute name="name" required="true" description="Implementation | Deployment"%> +<%@attribute name="repositoryURL" required="true" description="the URL of Winery's repository"%> +<%@attribute name="onSuccessfulArtifactCreationFunction" required="true" description="javascript code to be executed when the artifact has been successfully created. Parameter: artifactInfo"%> +<%@attribute name="allArtifactTypes" required="true" type="java.util.Collection" description="All available artifact types"%> +<%@attribute name="allNamespaces" required="true" type="java.util.Collection" description="All known namespaces"%> +<%@attribute name="defaultNSForArtifactTemplate" required="true" description="the default namespace of the artifact template"%> + +<%-- either URL or a function to be called for addition --%> +<%@attribute name="URL" required="true" description="the URL of the artifact collection. May also be a function returning the correct URL (used at the topology modeler). I.e., it is an expression being evaluated"%> + +<%@attribute name="isDeploymentArtifact" required="true" type="java.lang.Boolean" description="Is this dialog used to create deployment artifacts?"%> +<%-- required if implementation artifact --%> +<%@attribute name="interfacesOfAssociatedType" type="java.util.List" %> + +<script> +// TODO: check if allArtifactTypes is empty -> then an error message should be shown. Alternative: Add "Manage" button next to "artifact types" + +function addArtifact() { + if (highlightRequiredFields()) { + vShowError("Please fill out required fields."); + return; + } + + var artifactTemplateCreationMode = $("input[name='artifactTemplateCreation']:checked").val(); + var autoCreateArtifactTemplate = (artifactTemplateCreationMode=="createArtifactTemplate"); + + if (autoCreateArtifactTemplate && ($("#artifactTemplateNameIsValid:visible").hasClass("invalid"))) { + vShowError("Please ensure that the artifact template QName is valid."); + return; + } + + + /* begin: form serialization */ + + var theForm = $('#add${name}ArtifactForm'); + + // do not serialze hidden fields + // theForm.find("select:hidden,input:hidden").attr("disabled", "disabled"); + // Because we use "select2", the user-visible select fields are divs. The "real" selects are hidden. + // Therefore, we disable fields manually :) + var disabledFields; + if (artifactTemplateCreationMode == "skipArtifactTemplate") { + disabledFields = ["artifactTemplateName", "artifactTemplateNS", "artifactTemplateToLink"]; + } else if (artifactTemplateCreationMode == "createArtifactTemplate") { + disabledFields = ["artifactTemplateToLink"]; + } else if (artifactTemplateCreationMode == "linkArtifactTemplate") { + disabledFields = ["artifactTemplateName", "artifactTemplateNS", "artifactType"]; + } else { + vShowError("Code not consistent with UI"); + } + + // make a clean form + disabledFields.forEach(function(element) { + $("#"+element).attr("disabled", "disabled"); + }); + $("input[name='artifactTemplateCreation']").attr("disabled", "disabled"); + + // do not serialize choice directly, but ... + // ... append "autoCreateArtifactTemplate=true" in case the artifact template should be auto created + var data = theForm.serialize(); + if (autoCreateArtifactTemplate) { + data = data + "&autoCreateArtifactTemplate=true"; + } + + // enable fields again + disabledFields.forEach(function(element) { + $("#"+element).removeAttr("disabled"); + }); + $("input[name='artifactTemplateCreation']").removeAttr("disabled"); + + /* end: form serialization */ + + <c:if test="${not isDeploymentArtifact}"> + var operationVal = $("#operationName").val(); + if ((operationVal) && (operationVal != "")) { + var operationName = $("#operationName option:selected").text(); + // The operationname is prefixed with the namespace, because of "nextselect" + // we have to undo that effect. + // Therefore, we replace the complete operationName parameter + + var pos = data.indexOf("operationName="); + var posNextParam = data.indexOf("&", pos); + data = data.substr(0, pos) + "operationName=" + operationName + data.substr(posNextParam); + } + </c:if> + + // We assume that the artifact type exists + // i.e., that it was not deleted during loading of the dialog + + // The deployment artifact resource allows auto creation of the artifact template + // We do not need to do that manually using a separate POST call + // TODO: In a future version, this might be better have a clean way to create additional content for an artifact template + + // do the addCall + $.ajax({ + url: ${URL}, + type: "POST", + async: false, + "data": data, + error: function(jqXHR, textStatus, errorThrown) { + vShowAJAXError("Could not create ${name} Artifact", jqXHR, errorThrown); + }, + success: function(data, textStatus, jqXHR) { + // prepare data for onSuccessfulArtifactCreationFunction + // even though interaceName and operationName do not exist at DA, accessing it via jQuery works: then "undefined" is returned, which is OK + var artifactInfo = { + name: $("#artifactName").val(), + interfaceName: $("#interfaceName").val(), + operationName: $("#operationName option:selected").text() + }; + if (artifactTemplateCreationMode == "skipArtifactTemplate") { + // artifactTemplate remains unset as there is not artifactTemplate to be created + artifactInfo.artifactType = $("#artifactType").val(); + } else if (artifactTemplateCreationMode == "createArtifactTemplate") { + artifactInfo.artifactTemplateName = $("#artifactTemplateName").val(); + // FIXME: This is a quick hack - the name could have been changed at the server as it might contain invalid characters for an id + // In other words, $("#artifactTemplateName").val() might not be the localName of the artifactTemplate + artifactInfo.artifactTemplate = "{" + $("#artifactTemplateNS").val() + "}" + $("#artifactTemplateName").val(); + artifactInfo.artifactType = $("#artifactType").val(); + } else if (artifactTemplateCreationMode == "linkArtifactTemplate") { + artifactInfo.artifactTemplateName = $("#artifactTemplateToLink option:selected").text(); + artifactInfo.artifactTemplate = $("#artifactTemplateToLink").val(); + // artifact type is a mandantory field + // we have to ask the artifact template for the QName of its type and then use this data + require(["winery-support-common"], function(wsc) { + var nsAndId = wsc.getNamespaceAndLocalNameFromQName(artifactInfo.artifactTemplate); + var url = makeArtifactTemplateURL("${repositoryURL}", nsAndId.namespace, nsAndId.localname); + $.ajax({ + type: "GET", + async: false, + url: url + "?type", + dataType: "text", + error: function(jqXHR, textStatus, errorThrown) { + vShowAJAXError("Could not get type of artifact template", jqXHR, errorThrown); + return; + }, + success: function(resData, textStatus, jqXHR) { + // QName is directly returned + artifactInfo.artifactType = resData; + } + }); + }); + } else { + vShowError("Code not consistent with UI"); + } + // now, artifactInfo is filled completly + + // the function can be called + ${onSuccessfulArtifactCreationFunction}(artifactInfo); + + $('#add${name}ArtifactDiag').modal('hide'); + vShowSuccess("Artifact added successfully"); + + if (autoCreateArtifactTemplate) { + var aritfactTemplateNS = $("#artifactTemplateNS").val(); + var artifactTemplateName = $("#artifactTemplateName").val(); + var artifactTemplateURL = makeArtifactTemplateURL("${repositoryURL}", aritfactTemplateNS, artifactTemplateName); + $("#artifactTemplateNameAtUploadFiles").text(artifactTemplateName).attr("href", artifactTemplateURL); + var url = artifactTemplateURL + "files/"; + $('#fileupload').fileupload('option', 'url', url); + $("#addFilesToArtifactTemplate").modal('show'); + } + } + }); + +} +</script> + +<c:if test="${not isDeploymentArtifact}"> + <script type="text/javascript" src="${pageContext.request.contextPath}/js/nextselect.js"></script> + <script> + var dependendSelects = {"#interfaceName": "#operationName"}; + var interfaceOpData = { + "": { + label : "(none)", + "options" : [] + }<c:if test="${not empty interfacesOfAssociatedType}">,</c:if> + <c:forEach var="t" items="${interfacesOfAssociatedType}"> + // no label necessary as this list is pre-filled + "${t.name}": { + "options" : [ + "", + <c:forEach var="u" varStatus="loop" items="${t.operationsResouce.listOfAllEntityIdsAsList}"> + "${t.name}:${u}"<c:if test="${!loop.last}">,</c:if> + </c:forEach> + ] + }, + </c:forEach> + <c:forEach var="t" varStatus="outerLoop" items="${interfacesOfAssociatedType}"> + <c:forEach var="u" varStatus="innerLoop" items="${t.operationsResouce.listOfAllEntityIdsAsList}"> + "${t.name}:${u}" : { + "label": "${u}" + }<c:if test="${!innerLoop.last or !outerLoop.last}">,</c:if> + </c:forEach> + </c:forEach> + }; + </script> +</c:if> + +<div class="modal fade" id="add${name}ArtifactDiag"> + <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">Add ${name} Artifact</h4> + </div> + <div class="modal-body"> + <form id="add${name}ArtifactForm" enctype="multipart/form-data"> + <fieldset> + + <div class="form-group"> + <label>Name</label> + <input class="form-control" name="artifactName" id="artifactName" type="text" required="required" autocomplete="on" /> + </div> + + <c:if test="${not isDeploymentArtifact}"> + <div class="form-group"> + <label for="interfaceName">Interface Name</label> + <select name="interfaceName" id="interfaceName" class="form-control" onchange="updateListContent(this.value, '#operationName', dependendSelects, interfaceOpData);"> + <option value="" selected="selected">(none)</option> + <c:forEach var="t" items="${interfacesOfAssociatedType}"> + <option value="${t.name}">${t.name}</option> + </c:forEach> + </select> + </div> + + <div class="form-group"> + <label for="operationName">Operation Name</label> + <select name="operationName" id="operationName" class="form-control"> + <%-- options filled by updateListContent defined by nextselect.js --%> + </select> + </div> + </c:if> + + <h4>Artifact Template Creation</h4> + <div class="radio"> + <label> + <input type="radio" name="artifactTemplateCreation" value="createArtifactTemplate" checked="checked" id="createArtifactTemplateInput">Create Artifact Template</input> + </label> + <p class="help-block">Check if you want to upload <strong>new</strong> files, you do not want to reuse existing files and you do not point to an image library.</p> + </div> + <div class="radio"> + <label> + <input type="radio" name="artifactTemplateCreation" value="linkArtifactTemplate">Link Artifact Template</input> + </label> + <p class="help-block">Check if you want to reuse existing files.</p> + </div> + <div class="radio"> + <label> + <input type="radio" name="artifactTemplateCreation" value="skipArtifactTemplate">Do not create an artifact template</input> + </label> + <p class="help-block">Check if you want to point to an image library.</p> + </div> + </fieldset> + <fieldset id="artifactTypeFieldset"> + <div class="form-group" id="artifactTypeDiv"> + <label for="artifactType">Artifact Type</label> + <select name="artifactType" class="form-control" id="artifactType"> + <c:forEach var="t" items="${allArtifactTypes}"> + <option value="${t.toString()}">${t.localPart}</option> + </c:forEach> + </select> + </div> + </fieldset> + <fieldset> + + <fup:artifacttemplateselection allNamespaces="${allNamespaces}" repositoryURL="${repositoryURL}" defaultNSForArtifactTemplate="${defaultNSForArtifactTemplate}"/> + + <div id="linkArtifactTemplate" class="form-group" style="display:none;"> + <label for="divArtifactTemplateToLink">Artifact Template</label> + <div id="divArtifactTemplateToLink"> + <%-- filled by jQuery at openAdd${name}ArtifactDiag() --%> + <select id=artifactTemplateToLink name="artifactTemplate" class="form-control" style="max-width: 90%"> + </select> + <%-- URL is changed each time the selection is changed --%> + <a href="#" target="_blank" class="btn btn-info btn-sm" id="viewArtifactTemplateToLink">view</a> + </div> + </div> + </fieldset> + </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" onclick="addArtifact();">Add</button> + </div> + </div> + </div> +</div> + + +<script> +function openAdd${name}ArtifactDiag() { + $.ajax({ + url: "${repositoryURL}/artifacttemplates/", + dataType: "json", + async: false, + error: function(jqXHR, textStatus, errorThrown) { + vShowAJAXError("Could not fetch available artifact templates", jqXHR, errorThrown); + }, + success: function(data, textStatus, jqXHR) { + var select = $("#artifactTemplateToLink"); + select.empty(); + $.each(data, function(index, o) { + var qname = "{" + this.namespace + "}" + this.id; + var option = '<option value="' + qname + '">' + this.name + '</option>'; + select.append(option); + if (index==0) { + // first element + // this is the selected element + // we put it as href to the "view" button + $("#viewArtifactTemplateToLink").attr("href", makeArtifactTemplateURL("${repositoryURL}", this.namespace, this.id)); + } + }); + select.trigger("change"); + $('#add${name}ArtifactDiag').modal('show'); + } + }); +} + +requirejs(["select2"], function() { + $("#interfaceName").select2(); + <c:if test="${not isDeploymentArtifact}"> + // the dependend select cannot be a select2 until https://github.com/ivaynberg/select2/issues/1656 is resolved + //$("#operationName").select2(); + </c:if> + $("#artifactType").select2(); + $("#artifactTemplateToLink").select2(); +}); + +requirejs(['tmpl', 'jquery.ui.widget', 'jquery.fileupload', 'jquery.fileupload-ui'], function() { + $('#fileupload').fileupload({ + "autoUpload": true + }); +}); + +$(function(){ + $("input[name='artifactTemplateCreation']").on("change", function(e) { + var choice = $(e.target).attr("value"); + if (choice == "skipArtifactTemplate") { + $(".createArtifactTemplate").hide(); + $("#linkArtifactTemplate").hide(); + $("#artifactTypeFieldset").removeAttr("disabled"); + $("#artifactTypeDiv").show(); + } else if (choice == "createArtifactTemplate") { + $(".createArtifactTemplate").show(); + $("#linkArtifactTemplate").hide(); + $("#artifactTypeFieldset").removeAttr("disabled"); + $("#artifactTypeDiv").show(); + // one might be copy the template name to the artifact template name (if ($("#artifactTemplateName").val() == "")) + } else if (choice == "linkArtifactTemplate") { + $(".createArtifactTemplate").hide(); + $("#linkArtifactTemplate").show(); + $("#artifactTypeFieldset").attr("disabled", "disabled"); + $("#artifactTypeDiv").hide(); + } else { + vShowError("Code not consistent with UI"); + }; + }); + + $("#add${name}ArtifactDiag").on('shown.bs.modal', function() { + $(this).find('form')[0].reset(); + // createArtifactTemplate is the default seeting for the form + // reset the dialog to this choice + $("#createArtifactTemplateInput").trigger("change"); + }); + + $("#artifactName").typing({ + start: function(event, $elem) { + if (syncDAnameWithATname) { + require(["artifacttemplateselection"], function(ats) { + ats.flagArtifactTemplateNameAsUpdating(); + }); + } + }, + stop: function(event, $elem) { + // value is copied at the "change keyup input" event at #artifactName + require(["artifacttemplateselection"], function(ats) { + ats.checkArtifactTemplateName(); + }); + } + }); + + $("#artifactName") + // tip by http://solicitingfame.com/2011/11/09/jquery-keyup-vs-bind/ + .bind("change keyup input", function() { + if (syncDAnameWithATname) { + $("#artifactTemplateName").val(this.value); + } + }) + .on("focus", function() { + syncDAnameWithATname = ($("#artifactTemplateName").is(":visible")) && (this.value == $("#artifactTemplateName").val()); + }); + + $("#artifactTemplateToLink").on("change", function(evt) { + if (evt.val) { + // TODO: possibly use makeArtifactTemplateURL("${repositoryURL}", this.namespace, this.id)) here + require(["winery-support-common"], function(w) { + var fragment = w.getURLFragmentOutOfFullQName(evt.val); + var url = "${repositoryURL}/artifacttemplates/" + fragment + "/"; + $("#viewArtifactTemplateToLink").attr("href", url); + }); + } + }); +}); +</script> + + +<%-- file uploading part --%> + +<div class="modal fade" id="addFilesToArtifactTemplate"> + <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">Add files to artifact template <a id="artifactTemplateNameAtUploadFiles"></a></h4> + </div> + <div class="modal-body"> + <fup:jquery-file-upload-full loadexistingfiles="false"></fup:jquery-file-upload-full> + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default" data-dismiss="modal">Close</button> + </div> + <!-- addFilesToArtifactTemplate --> + </div> + </div> +</div> diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/artifacttemplateselection.tag b/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/artifacttemplateselection.tag new file mode 100644 index 0000000..05c6138 --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/artifacttemplateselection.tag @@ -0,0 +1,41 @@ +<%-- +/******************************************************************************* + * 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 + *******************************************************************************/ +--%> +<%@tag description="dialog for selecting one artifacttemplate" pageEncoding="UTF-8"%> + +<%@attribute name="allNamespaces" required="true" type="java.util.Collection" description="All known namespaces"%> +<%@attribute name="repositoryURL" required="true" description="the URL of Winery's repository"%> +<%@attribute name="defaultNSForArtifactTemplate" required="true" description="the default namespace of the artifact template"%> + +<%@taglib prefix="t" tagdir="/WEB-INF/tags"%> + +<div class="form-group-grouping"> + <!-- createArtifactTemplate class is required for artifactcreationdialog --> + <div class="form-group createArtifactTemplate"> + <label>Artifact Template Name</label> + <!-- name is an NCName --> + <input class="artifactData form-control" id="artifactTemplateName" name="artifactTemplateName" type="text" required="required" autocomplete="on" placeholder="Enter name for artifact template" pattern="[\i-[:]][\c-[:]]*"/> + <div id="artifactTemplateNameIsValid" class="invalid"> + <span id="artifactTemplateNameIsInvalidReason"></span> + </div> + </div> + + <t:namespaceChooser allNamespaces="${allNamespaces}" idOfInput="artifactTemplateNS" selected="${defaultNSForArtifactTemplate}"></t:namespaceChooser> +</div> + +<script> +require(["artifacttemplateselection"], function(ast) { + // configure the plugin + ast.setRepositoryURL("${repositoryURL}"); +}); +</script> diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/id_name_type.tag b/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/id_name_type.tag new file mode 100644 index 0000000..b88a9a9 --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/id_name_type.tag @@ -0,0 +1,36 @@ +<%-- +/******************************************************************************* + * 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 + *******************************************************************************/ +--%> +<%@tag description="Dialog parts for name and type choosing" pageEncoding="UTF-8"%> + +<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@taglib prefix="wc" uri="http://www.eclipse.org/winery/functions"%> +<%@taglib prefix="w" tagdir="/WEB-INF/tags/common"%> + + +<%@attribute name="allTypes" required="true" type="java.util.Collection" description="Collection<QName> of all available types" %> +<%@attribute name="idPrefix" required="true" description="prefix used for name and type field. E.g., 'Req' becomes 'ReqType'."%> +<%@attribute name="hideIdField" required="false" description="if given, id field is not displayed. Quick hack to have this dialog reusable. Future versions might always show the id dialog and provide sync between name and id"%> + + <c:if test="${not hideIdField}"> + <div class="form-group"> + <label for="${idPrefix}Id" class="control-label">Id:</label> + <input id="${idPrefix}Id" class="form-control" name="${shortName}Name" type="text" required="required" disabled="disabled"/> + </div> + </c:if> + <div class="form-group"> + <label for="${idPrefix}Name" class="control-label">Name:</label> + <input id="${idPrefix}Name" class="form-control" name="${shortName}Name" type="text" required="required" /> + </div> + +<w:QNameChooser allQNames="${allTypes}" idOfSelectField="${idPrefix}Type" labelOfSelectField="Type" /> diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/jquery-file-upload-full.tag b/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/jquery-file-upload-full.tag new file mode 100644 index 0000000..5bc1057 --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/jquery-file-upload-full.tag @@ -0,0 +1,181 @@ +<%-- +/******************************************************************************* + * 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 + *******************************************************************************/ +--%> +<%@tag description="HTML + JavaScript enabling the full jQuery file upload as shown at http://blueimp.github.com/jQuery-File-Upload/" pageEncoding="UTF-8"%> + +<%-- Original Source https://raw.github.com/blueimp/jQuery-File-Upload/9.5.4/jquery-ui.html, License: MIT; See also CQ 8006 --%> + +<%@attribute name="action" required="false" description="custom action for the upload"%> +<%@attribute name="loadexistingfiles" type="java.lang.Boolean" required="true" description="load existing files from files/ url. false if that should not happen"%> + +<%-- +!! USES HARD-CODED URL "files/" for data !! +It is OK since it is currently only used in "files.jsp" +If it will be used in other places, there has to be a parameter "url" introduced +(and this jsp updated to a tag file) +--%> + +<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> + +<%-- The File Upload user interface plugin --%> + + <!-- The file upload form used as target for the file upload widget --> + <form id="fileupload" method="POST" enctype="multipart/form-data" <c:if test="${not empty action}">action="${action}"</c:if>> + <!-- The fileupload-buttonbar contains buttons to add/delete files and start/cancel the upload --> + <div class="row fileupload-buttonbar"> + <div class="span7"> <!-- should be col-lg-7, but then the add button does not work any more --> + <!-- The fileinput-button span is used to style the file input field as button --> + <span class="btn btn-success fileinput-button"> + <i class="glyphicon glyphicon-plus"></i> + <span>Add files...</span> + <input type="file" name="files[]" multiple> + </span> + </div> + <!-- The global progress information --> + <div class="span5 fileupload-progress fade"> + <!-- The global progress bar --> + <div class="progress progress-success progress-striped active" role="progressbar" aria-valuemin="0" aria-valuemax="100"> + <div class="bar" style="width:0%;"></div> + </div> + <!-- The extended global progress information --> + <div class="progress-extended"> </div> + </div> + </div> + <!-- The loading indicator is shown during file processing --> + <div class="fileupload-loading"></div> + <br> + <!-- The table listing the files available for upload/download --> + <table role="presentation" class="table table-striped"><tbody class="files" data-toggle="modal-gallery" data-target="#modal-gallery"></tbody></table> + </form> + +<!-- The template to display files available for upload --> +<script id="template-upload" type="text/x-tmpl"> +{% for (var i=0, file; file=o.files[i]; i++) { %} + <tr class="template-upload fade"> + <td> + <span class="preview"></span> + </td> + <td> + <p class="name">{%=file.name%}</p> + <strong class="error text-danger"></strong> + </td> + <td> + <p class="size">Processing...</p> + <div class="progress progress-striped active" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0"><div class="progress-bar progress-bar-success" style="width:0%;"></div></div> + </td> + <td> + {% if (!i && !o.options.autoUpload) { %} + <button class="btn btn-primary start" disabled> + <i class="glyphicon glyphicon-upload"></i> + <span>Start</span> + </button> + {% } %} + {% if (!i) { %} + <button class="btn btn-warning cancel"> + <i class="glyphicon glyphicon-ban-circle"></i> + <span>Cancel</span> + </button> + {% } %} + </td> + </tr> +{% } %} +</script> +<!-- The template to display files available for download --> +<script id="template-download" type="text/x-tmpl"> +{% for (var i=0, file; file=o.files[i]; i++) { %} + <tr class="template-download fade"> + <td> + <span class="preview"> + {% if (file.thumbnailUrl) { %} + <a href="{%=file.url%}" title="{%=file.name%}" download="{%=file.name%}" data-gallery><img src="{%=file.thumbnailUrl%}"></a> + {% } %} + </span> + </td> + <td> + <p class="name"> + {% if (file.url) { %} + <a href="{%=file.url%}" title="{%=file.name%}" download="{%=file.name%}" {%=file.thumbnailUrl?'data-gallery':''%}>{%=file.name%}</a> + {% } else { %} + <span>{%=file.name%}</span> + {% } %} + </p> + {% if (file.error) { %} + <div><span class="label label-danger">Error</span> {%=file.error%}</div> + {% } %} + </td> + <td> + <span class="size">{%=o.formatFileSize(file.size)%}</span> + </td> + <td> + {% if (file.deleteUrl) { %} + <button class="btn btn-danger btn-sm delete" data-type="{%=file.deleteType%}" data-url="{%=file.deleteUrl%}"{% if (file.deleteWithCredentials) { %} data-xhr-fields='{"withCredentials":true}'{% } %}> + <i class="glyphicon glyphicon-trash"></i> + <span>Delete</span> + </button> + {% } else { %} + <button class="btn btn-warning cancel"> + <i class="glyphicon glyphicon-ban-circle"></i> + <span>Cancel</span> + </button> + {% } %} + </td> + </tr> +{% } %} +</script> + +<script> +/* + * Based on jQuery File Upload Plugin JS Example + * https://github.com/blueimp/jQuery-File-Upload + * + * Copyright 2010, Sebastian Tschan + * https://blueimp.net + * + * Licensed under the MIT license: + * http://www.opensource.org/licenses/MIT + */ + +/*jslint nomen: true, unparam: true, regexp: true */ +/*global $, window, document */ + +$(function () { + 'use strict'; + + // jquery.fileupload.process for image resizing capabilities + // has to be included in all cases as jquery.ui.widget depends on it without specifying the depencency explicitly + requirejs(['tmpl', 'jquery.ui.widget', 'jquery.fileupload', 'jquery.fileupload-ui', 'jquery.fileupload-process'], function() { + // Initialize the jQuery File Upload widget: + $('#fileupload').fileupload( { + autoUpload: true, + url: "files/" + }); + + <c:if test="${loadexistingfiles}"> + // Load existing files + $('#fileupload').addClass('fileupload-processing'); + $.ajax({ + url: $('#fileupload').fileupload('option', 'url'), + dataType: 'json', + context: $('#fileupload')[0] + }).always(function () { + $(this).removeClass('fileupload-processing'); + }).done(function (result) { + $(this).fileupload('option', 'done') + .call(this, $.Event('done'), {result: result}); + }).fail(function(jqXHR, textStatus, errorThrown) { + vShowAJAXError("Could not add upload file", jqXHR, errorThrown); + }); + </c:if> + }); +}); +</script> diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/orioneditor/orioneditorarea.tag b/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/orioneditor/orioneditorarea.tag new file mode 100644 index 0000000..70a1cdf --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/orioneditor/orioneditorarea.tag @@ -0,0 +1,110 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2013-2014 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 + *******************************************************************************/ +--%> +<%@tag description="Wrapper for an orion editing area" pageEncoding="UTF-8"%> + +<%@attribute name="areaid" required="true" description="The id of the editing area."%> +<%@attribute name="withoutsavebutton" required="false"%> +<%@attribute name="initialtext" required="false" description="The value to put in the editor. Can be also passed as body of this tag"%> +<%@attribute name="url" required="false"%> +<%@attribute name="hidden" required="false" description="if not empty, the form is hidden"%> +<%@attribute name="method" required="false" description="the method to use. Defaults to PUT"%> + +<%-- QUICK HACK to change the method from POST to PUT after saving an empty documentation the first time --%> +<%@attribute name="reloadAfterSuccess" required="false" description="Trigger a page reload after success (if true)"%> + +<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@taglib prefix="wc" uri="http://www.eclipse.org/winery/functions" %> + +<div> + <div id="${areaid}" class="orionxmleditordiv" <c:if test="{$not empty hidden}">style="display: none;"</c:if>><pre>${wc:escapeHtml4(initialtext)}<jsp:doBody/></pre></div> + <c:if test="${empty withoutsavebutton}"> + <button class="btn btn-primary" type="button" onclick="window.winery.orionareas['${areaid}'].save(this);" data-loading-text="Saving...">Save</button> + </c:if> +</div> + +<script> +if (window.winery === undefined) { + window.winery = {}; +} +if (window.winery.orionareas === undefined) { + window.winery.orionareas = {}; +} +require(["orioneditor"], function(edit) { + var config = { + id: "${areaid}", // used for URL update + reloadAfterSuccess : "${reloadAfterSuccess}", + editor: edit({ + contentType: "application/xml", + parent: "${areaid}" + // todo: we can set the initial text by the parameter "contents" + }), + ajaxOptions : { + contentType: "text/xml" + }, + fixEditorHeight: function() { + // fix the editor + // orion puts "height:0px" -> we remove that + $("#${areaid}").removeAttr("style"); + // due to the CSS style, the height is 300px + // "just" adapt the editor to that size + this.editor.resize(); + }, + save: function(button) { + var btn = $(button); // also works if button is undefined + btn.button("loading"); + + var options = this.ajaxOptions; + options.data = this.editor.getText(); + + // ensure that "config" variable is initialized within the ajax call + var config = this; + // the following code does not use "this" anymore as the "this" in the function references to the jqXHR instead of config + $.ajax(options).done(function( data, textStatus, jqXHR ) { + if (data !== undefined) { + // data contains the new id + url = url.replace(config.id, data); + conifg.id = data; + config.ajaxOptions.url = url; + } + if (config.reloadAfterSuccess) { + location.reload(); + } else { + vShowSuccess("sucessfully saved"); + btn.button("reset"); + } + }).fail(function(jqXHR, textStatus, errorThrown) { + vShowAJAXError("Could not add update XML", jqXHR, errorThrown); + btn.button("reset"); + }); + } + }; + + // now, editor is defined + // we cannot "fix" the appearance as the editor height determination does not work on hidden fields + + // url is an optional parameter to the .tag + if ("${url}" != "") { + config.ajaxOptions.url = "${url}"; + } + // method is an optional parameter to the .tag + if ("${method}" == "") { + config.ajaxOptions.type = "PUT"; + } else { + config.ajaxOptions.type = "${method}"; + } + + // store the config in global variable + window.winery.orionareas["${areaid}"] = config; +}); +</script> diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/policies/policies.tag b/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/policies/policies.tag new file mode 100644 index 0000000..5bd7bd9 --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/policies/policies.tag @@ -0,0 +1,54 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2013-2014 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 + *******************************************************************************/ +--%> + +<%-- This is mostly inspired by the reqscaps handling. Future work: Generalize the dialogs somehow to avoid copy'n'paste of code --%> + +<%@tag import="org.apache.taglibs.standard.lang.jstl.test.PageContextImpl"%> +<%@tag description="Renders the list of policies of a node template" pageEncoding="UTF-8"%> + +<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@taglib prefix="wc" uri="http://www.eclipse.org/winery/functions"%> + +<%@attribute name="list" required="true" type="java.util.List"%> +<%@attribute name="repositoryURL" required="true" type="java.lang.String" %> + +<div class="policiesContainer"> + <div class="header">Policies</div> + <div class="content"> + <div class="row"> + <div class="col-xs-4">Name</div> + <div class="cell col-xs-4">Type</div> + <div class="cell col-xs-4">Template</div> + </div> + <c:forEach var="item" items="${list}" varStatus="loopStatus"><%-- this HTML has to be kept consistent with the tmpl-policy HTML at policydiag.tag --%> + <div class="policy row ${loopStatus.index % 2 == 0 ? 'even' : 'odd'}"> + <div class="col-xs-4 policy name">${item.name}</div> + + <c:set var="clazz" value="<%=org.eclipse.winery.model.tosca.TPolicyType.class%>" /> + <div class="col-xs-4 policy type">${wc:qname2href(repositoryURL, clazz, item.policyType)}</div> + <span class="type">${item.policyType}</span> + + <c:set var="clazz" value="<%=org.eclipse.winery.model.tosca.TPolicyTemplate.class%>" /> + <div class="col-xs-4 policy template">${wc:qname2href(repositoryURL, clazz, item.policyRef)}</div> + <span class="template">${item.policyRef}</span> + + <c:set var="clazz" value="<%=org.eclipse.winery.model.tosca.TPolicy.class%>" /> + <textarea class="policy_xml">${wc:XMLAsString(clazz, item)}</textarea> + </div> + </c:forEach> + <div class="addnewpolicy row" style="display:none;"> + <button class="btn btn-default center-block btn-xs" onclick="showAddDiagForPolicy($(this).parent().parent().parent().parent());">Add new</button> + </div> + </div> +</div> diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/policies/policydiag.tag b/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/policies/policydiag.tag new file mode 100644 index 0000000..2554b8c --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/policies/policydiag.tag @@ -0,0 +1,205 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2012-2014 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 + *******************************************************************************/ +--%> + +<%@tag import="org.eclipse.winery.model.tosca.TPolicyTemplate"%> +<%@tag description="Dialog to add or update a policy. Offers function showUpdateDiagForPolicy(policyElement) / showAddDiagForPolicy(nodeTemplateElement)" 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="w" tagdir="/WEB-INF/tags"%> +<%@taglib prefix="ct" tagdir="/WEB-INF/tags/common"%> +<%@taglib prefix="wc" uri="http://www.eclipse.org/winery/functions"%> + +<%@attribute name="allPolicyTypes" required="true" type="java.util.Collection" description="Collection<QName> of all available policy types" %> +<%@attribute name="repositoryURL" required="true" type="java.lang.String" description="The URL of winery's repository"%> + +<div class="modal fade" id="PolicyDiag"> + <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">Policy</h4> + </div> + <div class="modal-body"> + <ct:id_name_type idPrefix="policy" allTypes="${allPolicyTypes}" hideIdField="true" /> + + <div class="form-group"> + <label for="policyTemplate" class="control-label">Policy Template:</label> + + <input id="policyTemplate" class="form-control" name="policyTemplate"></input> + </div> + + <o:orioneditorarea areaid="OrionpolicyXML" withoutsavebutton="true" /> + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default" data-dismiss="modal">Close</button> + <button type="button" id="deletePolicy" class="btn btn-danger" onclick="deletePolicy();">Delete</button> + <button type="button" id="updatePolicy" class="btn btn-primary" onclick="addOrUpdatePolicy(false);">Update</button> + <button type="button" id="addPolicy" class="btn btn-primary" onclick="addOrUpdatePolicy(true);">Add</button> + </div> + </div> + </div> +</div> + +<c:set var="clazz" value="<%=org.eclipse.winery.model.tosca.TPolicy.class%>" /> +<textarea id="emptyPolicy" class="hidden">${wc:XMLAsString(clazz, null)}</textarea> + +<script> +//global variable set by showUpdateDiagForPolicy and read by addOrUpdatePolicy +var currentPolicyElement; + +// possibly this is a duplicate information as we also have "currentlySelectedNodeTemplate" (or similar) +var currentNodeTemplateElement; + +function updatePolicyTemplateSelect(valueToSelect) { + require(["winery-support-common"], function(w) { + var type = $("#policyType").val(); + var fragment = w.getURLFragmentOutOfFullQName(type); + var url = "${repositoryURL}/policytypes/" + fragment + "/instances/"; + $.ajax(url, { + dataType: 'json' + }).fail(function(jqXHR, textStatus, errorThrown) { + vShowAJAXError("Could not get policy templates", jqXHR, errorThrown); + }).done(function(data) { + // add "(none)" to available items + var none = { + id: "(none)", + text: "(none)" + }; + data.unshift(none); + + if (typeof valueToSelect === "undefined") { + valueToSelect = "(none)"; + } + + $("#policyTemplate") + .select2({data: data}) + .select2("val", valueToSelect); + }); + }); +} + +function showUpdateDiagForPolicy(policyElement) { + currentPolicyElement = policyElement; + + $("#deletePolicy").show(); + $("#updatePolicy").show(); + $("#addPolicy").hide(); + + var name = policyElement.children("div.name").text(); + var type = policyElement.children("span.type").text(); + + $("#policyName").val(name); + $("#policyType").val(type); + + // onchange of type is not called, we have to update the template selection field for ourselves + // we also have to select the current user's choice + updatePolicyTemplateSelect(policyElement.children("span.template").text()); + + var diag = $("#PolicyDiag"); + require(["winery-support-common"], function(w) { + w.replaceDialogShownHookForOrionUpdate(diag, "OrionpolicyXML", currentPolicyElement.children("textarea").val()); + diag.modal("show"); + }); +} + +function showAddDiagForPolicy(nodeTemplateElement) { + currentNodeTemplateElement = nodeTemplateElement; + + $("#deletePolicy").hide(); + $("#updatePolicy").hide(); + $("#addPolicy").show(); + + $("#policyName").val(""); + + // fill policy template select field + updatePolicyTemplateSelect(); + + var diag = $("#PolicyDiag"); + require(["winery-support-common"], function(w) { + w.replaceDialogShownHookForOrionUpdate(diag, "OrionpolicyXML", $("#emptyPolicy").val()); + diag.modal("show"); + }); +} + +function addOrUpdatePolicy(doAdd) { + if (highlightRequiredFields()) { + vShowError("Please fill in all required fields"); + return; + } + + require(["winery-support-common", "tmpl"], function(wsc, tmpl) { + var res = wsc.synchronizeNameAndType("policy", false, [{ + attribute: "policyType", + fieldSuffix: "Type", + }, { + attribute: "policyRef", + fieldSuffix: "Template" + }]); + + if (res) { + var policyTemplate = $("#policyTemplate").select2("data"); + var renderData = { + name: $("#policyName").val(), + + policyTypeText: $("#policyType :selected").text(), + policyTypeVal: $("#policyType").val(), + + policyTemplateText: policyTemplate.text, + policyTemplateVal: policyTemplate.id, + + xml: res.xml + }; + var div = tmpl("tmpl-policy", renderData); + if (doAdd) { + currentNodeTemplateElement.children("div.policiesContainer").children("div.content").children("div.addnewpolicy").before(div); + } else { + currentPolicyElement.replaceWith(div); + } + $("#PolicyDiag").modal("hide"); + } else { + vShowError("Could not synchronize XML fields"); + } + }); +} + + +function deletePolicy() { + // We just have to remove the HTML element: + // The save operation converts the information in the HTML to XML + currentPolicyElement.remove(); + $("#PolicyDiag").modal("hide"); +} + + +$("#policyType") + .select2() + .on("change", updatePolicyTemplateSelect); +</script> + +<%-- parameters: o.id, o.name, o.policyType, o.policyRef, o.xml. Has to be consistent with the HTML generated by policies.tag --%> +<script type="text/x-tmpl" id="tmpl-policy"> + <div class="policy row"> <%-- "even"/"odd" is not set. Could be done by using $.prev() --%> + <div class="col-xs-4 policy name">{%=o.name%}</div> + + <%-- we do not provide a link here. Link is only available at reload. Makes life easier here. makeArtifactTemplateURL at winery-common.js is a first hint of how to generate links --%> + <div class="col-xs-4 policy type">{%=o.policyTypeText%}</div> + <span class="type">{%=o.policyTypeVal%}</span> + + <div class="col-xs-4 policy template">{%=o.policyTemplateText%}</div> + <span class="template">{%=o.policyTemplateVal%}</span> + + <textarea class="policy_xml">{%=o.xml%}</textarea> + </div> +</script> diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/spinnerwithinphty.tag b/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/spinnerwithinphty.tag new file mode 100644 index 0000000..a77c9d9 --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/spinnerwithinphty.tag @@ -0,0 +1,92 @@ +<%-- +/******************************************************************************* + * 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: + * Yves Schubert - initial API and implementation and/or initial documentation + * Oliver Kopp - minor improvements + *******************************************************************************/ +--%> +<%@tag description="A spinner with the possibility to set to inphty via button" pageEncoding="UTF-8"%> +<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> + +<%-- Code copied between repository and topology-modeler --%> + +<%-- +Could also be realized as + * HTML5 Web Component (http://www.ibm.com/developerworks/library/wa-html5components1/) or + * x-tags (http://www.x-tags.org/) +We decided to use JSP tags to avoid an additional JavaScript library +--%> + +<%@attribute name="label" required="true"%> +<%@attribute name="id" required="true"%> +<%@attribute name="min"%> +<%@attribute name="max" required="false" description="Maximum value. Default is 1000. The underlying library does not allow arbitrary high values."%> +<%@attribute name="name" required="false" description="The name of the input field. Defaults to the id"%> +<%@attribute name="withinphty" required="false" description="If set, then an inphty button is provded"%> +<%@attribute name="value"%> +<%@attribute name="width" required="false" description="The Column with according to bootstrap rules. Default is 3 (should not be smaller)."%> +<%@attribute name="changedfunction" required="false" description="Called if value changed"%> + +<%-- Set default name value if required --%> +<c:if test="${empty name}"> + <c:set var="name" value="${id}"></c:set> +</c:if> + +<c:if test="${empty width}"> + <c:set var="width" value="3"></c:set> +</c:if> + +<div class="form-group"> + <label for="${id}">${label}</label> + <div class="row"> + <div class="col-lg-${width}"> + <div class="input-group"> + <input id="${id}" class="spinner form-control" name="${name}" type="text" <c:if test="${not empty changedfunction}">onblur="${changedfunction}();"</c:if>/> + <c:if test="${not empty withinphty}"> + <span class="input-group-addon" style="cursor: pointer; border-left:0" onclick="setToInfin('${id}'<c:if test="${not empty changedfunction}">, ${changedfunction}</c:if>);">∞</span> + </c:if> + </div> + </div> + </div> +</div> + +<script> +<%-- +included multiple times. +Drawback when not using HTML5 components and keeping the JavaScript functions closed to the HTML code +--%> +function setToInfin(id, changedFunction) { + var spinner = $("#" + id); + spinner.val('∞'); // &inphty; - jQuery does not decode that, but places the plain text. Therefore, we directly pass the char we want + if (changedFunction !== undefined) { + changedFunction(); + } +} + +$(function() { + var param = {} + <c:if test="${not empty min}"> + param.minimum = "${min}"; + </c:if> + <c:if test="${empty max}"> + param.maximum = 1000; + </c:if> + + // use bootstrap-spinedit plugin + $("#${id}").spinedit(param); + + <c:if test="${not empty changedfunction}"> + $("#${id}").on('valueChanged', ${changedfunction}); + </c:if> + +}); + +</script> + diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/templates/CSSForTypes.tag b/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/templates/CSSForTypes.tag new file mode 100644 index 0000000..1df2d82 --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/templates/CSSForTypes.tag @@ -0,0 +1,50 @@ +<%-- +/******************************************************************************* + * 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 + *******************************************************************************/ +--%> +<%@tag description="Generates style element for node types and relationship types" pageEncoding="UTF-8" %> + +<%@attribute name="nodeTypes" required="true" type="java.util.Collection" %> +<%@attribute name="relationshipTypes" required="true" type="java.util.Collection" %> + +<%@tag import="java.util.Collection"%> +<%@tag import="javax.xml.namespace.QName"%> +<%@tag import="org.eclipse.winery.common.ModelUtilities"%> +<%@tag import="org.eclipse.winery.common.Util"%> +<%@tag import="org.eclipse.winery.model.tosca.TNodeType"%> +<%@tag import="org.eclipse.winery.model.tosca.TRelationshipType"%> + +<style> +<% + for (TNodeType nt: (Collection<TNodeType>) nodeTypes) { + String borderColor = ModelUtilities.getBorderColor(nt); + String cssName = Util.makeCSSName(nt.getTargetNamespace(), nt.getName()); +%> + div.NodeTemplateShape.<%=cssName%> { + border-color: <%=borderColor%>; + } +<% + } + + // relationship types CSS + for (TRelationshipType rt: (Collection<TRelationshipType>) relationshipTypes) { + String color = ModelUtilities.getColor(rt); + QName qname = new QName(rt.getTargetNamespace(), rt.getName()); + String cssName = Util.makeCSSName(qname) + "_box"; +%> + div.<%=cssName%> { + background: <%=color%>; + } +<% + } +%> +</style> diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/templates/defineCreateConnectorEndpointsFunction.tag b/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/templates/defineCreateConnectorEndpointsFunction.tag new file mode 100644 index 0000000..26f139a --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/templates/defineCreateConnectorEndpointsFunction.tag @@ -0,0 +1,42 @@ +<%-- +/******************************************************************************* + * 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 + *******************************************************************************/ +--%> +<%@tag description="Defines the javascript function createConnectorEndpoints globally. Quick hack to avoid huge hacking at the repository" pageEncoding="UTF-8"%> + +<%@tag import="java.util.Collection"%> +<%@tag import="org.eclipse.winery.model.tosca.TRelationshipType"%> +<%@tag import="org.eclipse.winery.common.Util"%> + +<%@attribute name="relationshipTypes" type="java.util.Collection" required="true" %> + +<script> +function createConnectorEndpoints(nodeTemplateShapeSet) { +<% + for (TRelationshipType relationshipType: (Collection<TRelationshipType>) relationshipTypes) { +%> + nodeTemplateShapeSet.find(".<%=Util.makeCSSName(relationshipType.getTargetNamespace(), relationshipType.getName()) %>").each(function(i,e) { + var p = $(e).parent(); + var grandparent = $(p).parent(); + + jsPlumb.makeSource($(e), { + parent:grandparent, + anchor:"Continuous", + connectionType: "{<%=relationshipType.getTargetNamespace()%>}<%=relationshipType.getName()%>", + endpoint:"Blank" + }); + }); +<% + } +%> +} +</script> diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/templates/nodetemplates/nodeTemplateRenderer.tag b/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/templates/nodetemplates/nodeTemplateRenderer.tag new file mode 100644 index 0000000..16bc737 --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/templates/nodetemplates/nodeTemplateRenderer.tag @@ -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: + * Uwe Breitenbücher - skeletton for node template shapes + * Oliver Kopp - initial API and implementation and/or initial documentation + *******************************************************************************/ +--%> +<%@tag language="java" pageEncoding="UTF-8" description="This tag is used for both real nodeTemplate node rendering and rendering of a 'template' used to create a nodeTemplateShape. The latter is called by palette.jsp. Therefore, this tag has to be more general."%> +<%-- Parameters --%> + +<%-- template and palette --%> +<%@attribute name="client" required="true" description="IWineryRepository" type="org.eclipse.winery.common.interfaces.IWineryRepository"%> +<%@attribute name="repositoryURL" required="true" type="java.lang.String" description="The URL of winery's repository"%> +<%@attribute name="topologyModelerURI" required="false" type="java.lang.String" description="The URL of winery topology modeler's URI - required for images/. Has to end with '/'. Can be left blank."%> +<%@attribute name="relationshipTypes" description="the known relationship types" required="true" type="java.util.Collection"%> + +<%-- only for topology modeler --%> +<%@attribute name="nodeTemplate" type="org.eclipse.winery.model.tosca.TNodeTemplate"%> +<%@attribute name="top"%> +<%@attribute name="left"%> + +<%-- only for palette.jsp --%> +<%@attribute name="nodeType" type="org.eclipse.winery.model.tosca.TNodeType" %> +<%@attribute name="nodeTypeQName" type="javax.xml.namespace.QName"%> + +<%@tag import="org.eclipse.winery.model.tosca.TArtifactTemplate"%> +<%@tag import="org.eclipse.winery.model.tosca.TArtifactType"%> +<%@tag import="org.eclipse.winery.model.tosca.TCapability"%> +<%@tag import="org.eclipse.winery.model.tosca.TDeploymentArtifact"%> +<%@tag import="org.eclipse.winery.model.tosca.TDeploymentArtifacts"%> +<%@tag import="org.eclipse.winery.model.tosca.TEntityType.PropertiesDefinition"%> +<%@tag import="org.eclipse.winery.model.tosca.TNodeTemplate"%> +<%@tag import="org.eclipse.winery.model.tosca.TNodeTemplate.Capabilities"%> +<%@tag import="org.eclipse.winery.model.tosca.TNodeTemplate.Requirements"%> +<%@tag import="org.eclipse.winery.model.tosca.TNodeTemplate.Policies"%> +<%@tag import="org.eclipse.winery.model.tosca.TNodeType"%> +<%@tag import="org.eclipse.winery.model.tosca.TPolicy"%> +<%@tag import="org.eclipse.winery.model.tosca.TRelationshipType"%> +<%@tag import="org.eclipse.winery.model.tosca.TRequirement"%> +<%@tag import="org.eclipse.winery.common.ModelUtilities"%> +<%@tag import="org.eclipse.winery.common.Util"%> +<%@tag import="org.eclipse.winery.common.ids.definitions.ArtifactTemplateId"%> +<%@tag import="org.eclipse.winery.common.ids.definitions.ArtifactTypeId"%> +<%@tag import="org.eclipse.winery.common.interfaces.IWineryRepository"%> +<%@tag import="org.w3c.dom.Element" %> +<%@tag import="org.apache.commons.configuration.Configuration"%> +<%@tag import="org.apache.commons.lang3.StringUtils"%> +<%@tag import="org.apache.commons.lang3.StringEscapeUtils"%> +<%@tag import="java.io.StringWriter" %> +<%@tag import="java.util.Collections"%> +<%@tag import="java.util.Collection"%> +<%@tag import="java.util.Iterator"%> +<%@tag import="java.util.List"%> +<%@tag import="java.util.Map"%> +<%@tag import="java.util.UUID"%> +<%@tag import="javax.xml.namespace.QName"%> +<%@tag import="javax.xml.transform.OutputKeys"%> +<%@tag import="javax.xml.transform.Transformer"%> +<%@tag import="javax.xml.transform.TransformerFactory"%> +<%@tag import="javax.xml.transform.dom.DOMSource"%> +<%@tag import="javax.xml.transform.stream.StreamResult"%> + +<%@taglib prefix="nt" tagdir="/WEB-INF/tags/common/templates/nodetemplates" %> +<%@taglib prefix="ntrq" tagdir="/WEB-INF/tags/common/templates/nodetemplates/reqscaps" %> +<%@taglib prefix="pol" tagdir="/WEB-INF/tags/common/policies" %> +<%@taglib prefix="props" tagdir="/WEB-INF/tags/common/templates" %> + +<% + String visualElementId; + + boolean paletteMode; + if (nodeTemplate == null) { + // we are in palette mode + // --> we render a template to be inserted in the drawing area by drag'n'drop + paletteMode = true; + assert(nodeType != null); + assert(nodeTypeQName != null); + + // these values are only pseudo values, they get all overwritten in drop function of palette.jsp + visualElementId = UUID.randomUUID().toString(); + left = "0"; + top = "0"; + } else { + // we render a real node template + paletteMode = false; + nodeTypeQName = nodeTemplate.getType(); + nodeType = client.getType(nodeTypeQName, TNodeType.class); + if (nodeType == null) { +%> + <script>vShowError("Could not get node type <%=nodeTypeQName%>");</script> +<% + return; + } + + visualElementId = nodeTemplate.getId(); + } + + String nodeTypeCSSName = Util.makeCSSName(nodeTypeQName); +%> + + <div class="NodeTemplateShape unselectable <%=nodeTypeCSSName%> <%if (paletteMode){%> hidden<%}%>" id="<%=visualElementId%>" style="left: <%=left%>px; top: <%=top%>px"> + <div class="headerContainer"> + <img class="icon" onerror="var that=this; require(['winery-common-topologyrendering'], function(wct){wct.imageError(that);});" src="<%=repositoryURL%>/nodetypes/<%=Util.DoubleURLencode(nodeTypeQName)%>/visualappearance/50x50" /> + <% + String name; + if (paletteMode) { + name = ""; // will be changed on drop + } else { + name = nodeTemplate.getName(); + if (StringUtils.isEmpty(name)) { + name = visualElementId; + } + } + %> + <div class="minMaxInstances"> + <span class="minInstances"><% + if (!paletteMode) { + %><%=Util.renderMinInstances(nodeTemplate.getMinInstances())%><% + } + %></span> + <span class="maxInstances"><% + if (!paletteMode) { + %><%=Util.renderMaxInstances(nodeTemplate.getMaxInstances())%><% + } + %></span> + </div> + <div class="id nodetemplate"><%=visualElementId%></div> + <div class="name nodetemplate"><%=name%></div> + <div class="type nodetemplate"><%=Util.qname2hrefWithName(repositoryURL, TNodeType.class, nodeTypeQName, nodeType.getName())%></div> + <span class="typeQName hidden"><%=nodeTypeQName%></span> + <span class="typeNamespace hidden"><%=nodeTypeQName.getNamespaceURI()%></span> + </div> + <div class="endpointContainer"> + <% + for (TRelationshipType relationshipType: (Collection<TRelationshipType>) relationshipTypes) { + %> + <div class="connectorEndpoint <%=Util.makeCSSName(relationshipType.getTargetNamespace(), relationshipType.getName())%>"> + <div class="connectorBox <%=Util.makeCSSName(relationshipType.getTargetNamespace(), relationshipType.getName())%>_box"></div> + <div class="connectorLabel"><%=relationshipType.getName()%></div> + </div> + <% + } + %> + </div> + + <%-- Properties --%> + <props:properties + propertiesDefinition="<%=nodeType.getPropertiesDefinition()%>" + wpd="<%=ModelUtilities.getWinerysPropertiesDefinition(nodeType)%>" + template="<%=paletteMode ? null : nodeTemplate %>" + pathToImages="${topologyModelerURI}images/" /> + + <%-- Deployment Artifacts --%> + + <% + List<TDeploymentArtifact> deploymentArtifacts; + if (paletteMode) { + deploymentArtifacts = Collections.emptyList(); + } else { + TDeploymentArtifacts tDeploymentArtifacts = nodeTemplate.getDeploymentArtifacts(); + if (tDeploymentArtifacts == null) { + deploymentArtifacts = Collections.emptyList(); + } else { + deploymentArtifacts = tDeploymentArtifacts.getDeploymentArtifact(); + } + } + // Render even if (deploymentArtifacts.isEmpty()), because user could add some with drag'n'drop + + // following is required to render artifact specific content + TransformerFactory transFactory = TransformerFactory.newInstance(); + Transformer transformer = transFactory.newTransformer(); + transformer.setOutputProperty(OutputKeys.INDENT, "yes"); + transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); + %> + + <div class="deploymentArtifactsContainer"> + + <div class="header">Deployment Artifacts</div> + <div class="content"> + <% + if (!paletteMode) { + for (TDeploymentArtifact deploymentArtifact : deploymentArtifacts) { + %> + <div class="deploymentArtifact row" onclick="showDeploymentArtifactInformation('<%=visualElementId%>', '<%=deploymentArtifact.getName()%>');"> + <textarea class="hidden"><%=org.eclipse.winery.common.Util.getXMLAsString(org.eclipse.winery.model.tosca.TDeploymentArtifact.class, deploymentArtifact)%></textarea> + <div class="col-xs-4 overflowhidden deploymentArtifact name"><%=deploymentArtifact.getName()%></div> + <div class="col-xs-4 overflowhidden artifactTemplate"><% + QName artifactRef; + if ((artifactRef = deploymentArtifact.getArtifactRef()) != null) { + ArtifactTemplateId atId = new ArtifactTemplateId(artifactRef); + %><%=client.getName(atId)%><% + } + %></div> + <div class="col-xs-4 overflowhidden artifactType"><% + ArtifactTypeId atyId = new ArtifactTypeId(deploymentArtifact.getArtifactType()); + %><%=client.getName(atyId)%></div> + </div> + <% + } + } + %> + + <div class="row addDA"> + <button class="btn btn-default btn-xs center-block addDA">Add new</button> + </div> + + <div class="row addnewartifacttemplate"> + <div class="center-block">Drop to add new deployment artifact. Not yet implemented.</div> + </div> + </div> + </div> + + <%-- Requirements and Capabilities --%> + <% + List<TRequirement> reqList; + if (paletteMode) { + reqList = null; + } else { + Requirements reqs = nodeTemplate.getRequirements(); + if (reqs == null) { + reqList = null; + } else { + reqList = reqs.getRequirement(); + } + } + %> + <ntrq:reqs list="<%=reqList%>" repositoryURL="${repositoryURL}" pathToImages="${topologyModelerURI}images/" client="${client}" /> + + <% + List<TCapability> capList; + if (paletteMode) { + capList = null; + } else { + Capabilities caps = nodeTemplate.getCapabilities(); + if (caps == null) { + capList = null; + } else { + capList = caps.getCapability(); + } + } + %> + <ntrq:caps list="<%=capList%>" repositoryURL="${repositoryURL}" pathToImages="${topologyModelerURI}images/" client="${client}"/> + + <%-- Policies --%> + <% + List<TPolicy> policyList; + if (paletteMode) { + policyList = null; + } else { + Policies policies = nodeTemplate.getPolicies(); + if (policies == null) { + policyList = null; + } else { + policyList = policies.getPolicy(); + } + } + %> + <pol:policies list="<%=policyList%>" repositoryURL="${repositoryURL}" /> +</div> diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/templates/nodetemplates/reqscaps/caps.tag b/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/templates/nodetemplates/reqscaps/caps.tag new file mode 100644 index 0000000..af70ff6 --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/templates/nodetemplates/reqscaps/caps.tag @@ -0,0 +1,33 @@ +<%-- +/******************************************************************************* + * 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 + *******************************************************************************/ +--%> +<%@tag description="Renders the list of requirements or capabilties" pageEncoding="UTF-8"%> +<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@taglib prefix="nt" tagdir="/WEB-INF/tags/common/templates/nodetemplates/reqscaps" %> + +<%@attribute name="client" required="true" description="IWineryRepository" type="org.eclipse.winery.common.interfaces.IWineryRepository"%> +<%@attribute name="list" required="false" type="java.util.List"%> +<%@attribute name="repositoryURL" required="true" %> +<%@attribute name="pathToImages" required="true" description="The path (URI path) to the image/ url, where xml.png is available. Has to end with '/'"%> + +<nt:reqsorcaps + headerLabel="Capabilities" + cssClassPrefix="capabilities" + list="${list}" + shortName="Cap" + TReqOrCapTypeClass="<%=org.eclipse.winery.model.tosca.TCapabilityType.class%>" + repositoryURL="${repositoryURL}" + typeURLFragment="capabilitytypes" + pathToImages="${pathToImages}" + client="${client}" +/> diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/templates/nodetemplates/reqscaps/reqs.tag b/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/templates/nodetemplates/reqscaps/reqs.tag new file mode 100644 index 0000000..473443e --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/templates/nodetemplates/reqscaps/reqs.tag @@ -0,0 +1,33 @@ +<%-- +/******************************************************************************* + * 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 + *******************************************************************************/ +--%> +<%@tag description="Renders the list of requirements or capabilties" pageEncoding="UTF-8"%> +<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@taglib prefix="nt" tagdir="/WEB-INF/tags/common/templates/nodetemplates/reqscaps" %> + +<%@attribute name="client" required="true" description="IWineryRepository" type="org.eclipse.winery.common.interfaces.IWineryRepository"%> +<%@attribute name="list" required="false" type="java.util.List"%> +<%@attribute name="repositoryURL" required="true" %> +<%@attribute name="pathToImages" required="true" description="The path (URI path) to the image/ url, where xml.png is available. Has to end with '/'"%> + +<nt:reqsorcaps + headerLabel="Requirements" + cssClassPrefix="requirements" + list="${list}" + shortName="Req" + TReqOrCapTypeClass="<%=org.eclipse.winery.model.tosca.TRequirementType.class%>" + repositoryURL="${repositoryURL}" + typeURLFragment="requirementtypes" + pathToImages="${pathToImages}" + client="${client}" +/> diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/templates/nodetemplates/reqscaps/reqsorcaps.tag b/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/templates/nodetemplates/reqscaps/reqsorcaps.tag new file mode 100644 index 0000000..6046730 --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/templates/nodetemplates/reqscaps/reqsorcaps.tag @@ -0,0 +1,63 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2012-2014 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 + *******************************************************************************/ +--%> +<%@tag description="Renders the list of requirements or capabilties" pageEncoding="UTF-8"%> + +<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@taglib prefix="wc" uri="http://www.eclipse.org/winery/functions"%> +<%@taglib prefix="nt" tagdir="/WEB-INF/tags/common/templates/nodetemplates/reqscaps" %> +<%@taglib prefix="props" tagdir="/WEB-INF/tags/common/templates" %> + +<%@attribute name="list" required="false" type="java.util.List" %> +<%@attribute name="headerLabel" required="true" description="Used for the heading" %> +<%@attribute name="cssClassPrefix" required="true" %> +<%@attribute name="TReqOrCapTypeClass" required="true" type="java.lang.Class" %> +<%@attribute name="repositoryURL" required="true" %> +<%@attribute name="typeURLFragment" required="true" description="requirementtypes|capabilitytypes"%> +<%@attribute name="shortName" required="true" description="Used for diag id, function name suffix, Req|Cap"%> +<%@attribute name="client" required="true" description="IWineryRepository" type="org.eclipse.winery.common.interfaces.IWineryRepository"%> +<%@attribute name="pathToImages" required="true" description="The path (URI path) to the image/ url, where xml.png is available. Has to end with '/'"%> + +<%@tag import="org.eclipse.winery.common.ModelUtilities"%> + +<div class="${cssClassPrefix}Container"> + <div class="header">${headerLabel}</div> + <div class="content"> + <c:forEach var="item" items="${list}"> + <div class="reqorcap ${cssClassPrefix} row" id="${item.id}"> + <div class="col-xs-4 id reqorcap">${item.id}</div> + <div class="col-xs-4 name reqorcap">${item.name}</div> + <div class="col-xs-4 type reqorcap">${wc:qname2href(repositoryURL, TReqOrCapTypeClass, item.type)}</div> + <c:set var="type" value="${wc:getType(client, item.type, TReqOrCapTypeClass)}" /> + <props:properties + template="${item}" + propertiesDefinition="${type.propertiesDefinition}" + wpd="${wc:winerysPropertiesDefinition(type)}" + pathToImages="${pathToImages}" /> + </div> + </c:forEach> + <div class="addnewreqorcap row" style="display:none;"> + <button class="btn btn-default btn-xs center-block" onclick="showAddOrUpdateDiagFor${shortName}($(this).parent().parent().parent().parent().attr('id'));">Add new</button> + </div> + </div> +</div> + +<%-- parameters: o.id, o.name, o.type, o.xml. Has to be consistent with above HTML --%> +<script type="text/x-tmpl" id="tmpl-${shortName}"> + <div class="reqorcap ${cssClassPrefix}" id="{%=o.id%}"> + <div class="col-xs-4 id reqorcap">{%=o.id%}</div> + <div class="col-xs-4 name reqorcap">{%=o.name%}</div> + <div class="col-xs-4 type reqorcap">{%#require("winery-support-common").qname2href("${repositoryURL}", "${typeURLFragment}", o.type)%}</div> + <div id="toBeReplacedByProperties"></div> + </div> +</script> diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/templates/properties.tag b/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/templates/properties.tag new file mode 100644 index 0000000..4cc6f0a --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/templates/properties.tag @@ -0,0 +1,103 @@ +<%-- +/******************************************************************************* + * 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 + *******************************************************************************/ +--%> +<%@tag description="Rendering for properties. A separate CSS has to be provided to style the content. Thus, this tag is reusable both in the topology modeler and in the management UI. Requires global javaScript function editPropertiesXML(visualElementId)" pageEncoding="UTF-8"%> +<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> + +<%@attribute name="propertiesDefinition" required="true" type="org.eclipse.winery.model.tosca.TEntityType.PropertiesDefinition" description="The TOSCA-conforming properties definition. May be null."%> +<%@attribute name="wpd" required="true" type="org.eclipse.winery.common.propertydefinitionkv.WinerysPropertiesDefinition" description="Winery's K/V properties definition. May be null"%> +<%@attribute name="template" required="true" type="org.eclipse.winery.model.tosca.TEntityTemplate" description="The template to display properties. Has to be null in case of the palette mode of the topology modeler"%> +<%@attribute name="pathToImages" required="true" description="The path (URI path) to the image/ url, where xml.png is available. Has to end with '/'"%> + +<%@tag import="org.eclipse.winery.common.ModelUtilities"%> +<%@tag import="org.eclipse.winery.common.propertydefinitionkv.WinerysPropertiesDefinition"%> +<%@tag import="org.eclipse.winery.common.propertydefinitionkv.PropertyDefinitionKV"%> +<%@tag import="org.eclipse.winery.common.propertydefinitionkv.PropertyDefinitionKVList"%> + +<% +if ((propertiesDefinition != null) || (wpd != null)) { +// properties exist +%> + <div class="propertiesContainer"> + <div class="header">Properties</div> + <div class="content"> + <% + if (wpd == null) { + // no winery's special properties definition, but "normal" TOSCA properties definition + + if (propertiesDefinition.getType() != null) { + %> + <span class="properties_type">XSD Type: <%=propertiesDefinition.getType()%></span> + <% + } else { + %> + <span class="properties_element">XSD Element: <%=propertiesDefinition.getElement()%></span> + <% + } + %> + <textarea class="properties_xml"><% + if (template != null) { + %><%=org.eclipse.winery.common.Util.getXMLAsString(org.eclipse.winery.model.tosca.TEntityTemplate.Properties.class, template.getProperties())%><% + } + %></textarea> + <%-- We have to do use $(this).parent().parent().parent().attr('id') instead of <%=visualElementId%> as on drag'n'drop from the palette, this binding is NOT changed, but the Id changes --> the user does NOT want to edit the properties from the palette entry, but from the node template --%> + <button class="btn btn-default" onclick="editPropertiesXML($(this).parent().parent().parent().attr('id'));"><img src="${pathToImages}xml.png"></img>View</button> + <% + } else { + // Winery special mode + java.util.Properties props; + if (template == null) { + // setting null only because of dump compiler. + // We never read props if in paletteMode + props = null; + } else { + props = ModelUtilities.getPropertiesKV(template); + } + %> + <%-- stores wrapper element name and namespace to ease serialization--%> + <span class="elementName"><%=wpd.getElementName()%></span> + <span class="namespace"><%=wpd.getNamespace()%></span> + <table> + <% + PropertyDefinitionKVList list = wpd.getPropertyDefinitionKVList(); + if (list != null) { + // iterate on all defined properties + for (PropertyDefinitionKV propdef: list) { + String key = propdef.getKey(); + String value; + if (template == null) { + value = ""; + } else { + // assign value, but change "null" to "" if no property is defined + if ((value = props.getProperty(key)) == null) { + value = ""; + } + } + %> + <tr class="KVProperty"> + <td><span class="<%= key %> KVPropertyKey"><%= key %></span></td> + <td><a class="KVPropertyValue" href="#" data-type="text" data-title="Enter <%= key %>"><%=value %></a></td> + </tr> + <% + } + } + %> + </table> + <% + } + %> + </div> + </div> +<% +} +%> diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/templates/propertiesBasic.tag b/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/templates/propertiesBasic.tag new file mode 100644 index 0000000..5e850b1 --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/templates/propertiesBasic.tag @@ -0,0 +1,112 @@ +<%-- +/******************************************************************************* + * 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 + *******************************************************************************/ +--%> +<%@tag description="Has to be included once before ussage of properties.tag. Used in topology modeler and in properties.jsp of entitytemplates" pageEncoding="UTF-8"%> + +<%@tag import="org.eclipse.winery.common.constants.Namespaces" %> + +<%@taglib prefix="o" tagdir="/WEB-INF/tags/common/orioneditor"%> + +<div class="modal fade" id="PropertyXMLDiag"> + <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">Property</h4> + </div> + <div class="modal-body"> + <!-- embed the XML editor without a save button. We provide the save button by ourselves --> + <o:orioneditorarea areaid="PropertyXML" withoutsavebutton="true"/> + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button> + <button type="button" class="btn btn-primary" onclick="savePropertiesXMLChanges();">Save</button> + </div> + </div> + </div> +</div> + +<script> +// global variable set by editPropertiesXML and read by savePropertiesXMLChanges +var nodeTemplateIdsTextAreaPropertiesXMLEditing; + +function editPropertiesXML(nodeTemplateId) { + // code mirror does not update content if field not fully shown + // therefore, we hook in into the "shown" event + $("#PropertyXMLDiag").off("shown.bs.modal"); + $("#PropertyXMLDiag").on("shown.bs.modal", function() { + nodeTemplateIdsTextAreaPropertiesXMLEditing = $("#" + nodeTemplateId).children(".propertiesContainer").children(".content").children("textarea"); + var val = nodeTemplateIdsTextAreaPropertiesXMLEditing.val(); + window.winery.orionareas["PropertyXML"].editor.setText(val); + window.winery.orionareas["PropertyXML"].fixEditorHeight(); + }); + $("#PropertyXMLDiag").modal("show"); + nodeTemplateIdSelectedForPropertiesXMLEditing = nodeTemplateId; +} + +function savePropertiesXMLChanges() { + var val = window.winery.orionareas["PropertyXML"].editor.getText(); + nodeTemplateIdsTextAreaPropertiesXMLEditing.text(val); + $("#PropertyXMLDiag").modal("hide"); +} + +/** + * @param properties - the properties div + * @param w - an XMLWriter + */ +function savePropertiesFromDivToXMLWriter(properties, w, writeNamespaceDeclaration) { + if (properties.length != 0) { + // properties exist + var contentDiv = properties.children("div.content"); + var xmlProperties = contentDiv.children("textarea.properties_xml"); + if (xmlProperties.length == 0) { + // K/V properties -> winery special: XSD defined at node type + + var elementName = contentDiv.children("span.elementName").text(); + var namespace = contentDiv.children("span.namespace").text(); + + w.writeStartElement("Properties"); + if (writeNamespaceDeclaration){ + w.writeAttributeString("xmlns", "<%=Namespaces.TOSCA_NAMESPACE%>"); + } + w.writeStartElement(elementName); + w.writeAttributeString("xmlns", namespace); + properties.children("div.content").children("table").children("tbody").children("tr").each(function() { + var keyEl = $(this).children("td:first-child"); + var key = keyEl.text(); + var valueEl = keyEl.next().children("a"); + var value; + if (valueEl.hasClass("editable-empty")) { + value = ""; + } else { + value = valueEl.text(); + value = value.replace(/\]\]>/g, "]]]]><![CDATA[>"); + value = "<![CDATA[" + value + "]]>"; + } + w.writeStartElement(key); + w.writeString(value); + w.writeEndElement(); + }); + w.writeEndElement(); + // close "Properties" + w.writeEndElement(); + } else { + // just put the content of the XML field as child of the current node template + // The sourrinding tag "properties" is included in the XML field + var data = xmlProperties.text(); + w.writeXML(data); + } + } + +} +</script> diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/templates/registerConnectionTypesAndConnectNodeTemplates.tag b/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/templates/registerConnectionTypesAndConnectNodeTemplates.tag new file mode 100644 index 0000000..fb55f9e --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/templates/registerConnectionTypesAndConnectNodeTemplates.tag @@ -0,0 +1,205 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2012-2014 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 + *******************************************************************************/ +--%> +<%@tag description="Registers the connection types to jsPlumb" pageEncoding="UTF-8"%> + +<%@attribute name="relationshipTypes" description="the known relationship types" required="true" type="java.util.Collection"%> +<%@attribute name="relationshipTemplates" description="the relationship templates to render" required="true" type="java.util.Collection"%> +<%@attribute name="ondone" description="JavaScript code executed when everything has been done" required="false"%> +<%@attribute name="repositoryURL" required="true" %> +<%@attribute name="readOnly" required="false" type="java.lang.Boolean"%> + +<%@tag import="java.util.Collection"%> +<%@tag import="org.eclipse.winery.model.tosca.TRequirement"%> +<%@tag import="org.eclipse.winery.model.tosca.TCapability"%> +<%@tag import="org.eclipse.winery.model.tosca.TNodeTemplate"%> +<%@tag import="org.eclipse.winery.model.tosca.TRelationshipType"%> +<%@tag import="org.eclipse.winery.model.tosca.TRelationshipTemplate"%> +<%@tag import="org.eclipse.winery.model.tosca.TRelationshipTemplate.SourceElement"%> +<%@tag import="org.eclipse.winery.model.tosca.TRelationshipTemplate.TargetElement"%> +<%@tag import="org.eclipse.winery.common.Util"%> + +<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> + +<% +Collection<TRelationshipType> relationshipTypesCasted = (Collection<TRelationshipType>) relationshipTypes; +Collection<TRelationshipTemplate> relationshipTemplatesCasted = (Collection<TRelationshipTemplate>) relationshipTemplates; +%> + +<script> +// we should load jquery and jquery.ui to have it available at jsPlumb +// however, jquery.ui cannot be loaded as it conflicts with bootstrap (when using toogle buttons) +require(["jquery", "jsplumb", "winery-common-topologyrendering"], function(globallyavailablea, jsPlumb, wct) { + jsPlumb.bind("ready", function() { + /** + * Shows error if req or cap does not exist + */ + function getNodeTemplateIdForReqOrCapId(id) { + var reqOrCap = $("#" + id); + if (reqOrCap.length == 0) { + vShowError("Requirement/Capability with id " + id + " not found"); + } + var res = reqOrCap.parent().parent().parent().attr("id"); + return res; + } + + // register the "selected" type to enable selection of arrows + jsPlumb.registerConnectionTypes({ + "selected":{ + paintStyle:{ strokeStyle:"red", lineWidth:5 }, + hoverPaintStyle:{ lineWidth: 7 } + } + }); + +<% + int i=0; + String when = ""; + String whenRes = ""; + if (relationshipTypesCasted.isEmpty()) { +%> + vShowError("No relationship types exist. Please add relationship types to the repository"); +<% + } + for (TRelationshipType relationshipType: relationshipTypesCasted) { + String fnName = "ajaxRTdata" + i; + when = when + fnName + "(), "; + whenRes = whenRes + fnName + ", "; +%> + function <%=fnName%>() { return $.ajax({ + url: "<%=repositoryURL%>/relationshiptypes/<%=Util.DoubleURLencode(relationshipType.getTargetNamespace())%>/<%=Util.DoubleURLencode(relationshipType.getName())%>/visualappearance/", + dataType: "json", + success: function(data, textStatus, jqXHR) { + jsPlumb.registerConnectionType( + "{<%=relationshipType.getTargetNamespace()%>}<%=relationshipType.getName()%>", + data); + }, + error: function(jqXHR, textStatus, errorThrown) { + vShowAJAXError("Could not load relationship type {<%=relationshipType.getTargetNamespace()%>}<%=relationshipType.getName()%>", jqXHR, errorThrown); + } + });}; +<% + i++; + } + + if (!relationshipTypesCasted.isEmpty()) { + // strip last comma + when = when.substring(0, when.length()-2); + whenRes = whenRes.substring(0, whenRes.length()-2); + } +%> + // as soon as all relationship types are registered as jsPlumb object, + // create connection end points and connect the nodes + $.when(<%=when%>).done(function(<%=whenRes%>){ + require(["winery-common-topologyrendering"], function(wct) { + // A NodeTemplateShape also appears in the palette. There, it is hidden. + // These should not be initialized as the template will be initialized later on + + <c:if test="${readOnly}">wct.setReadOnly();</c:if> + + // Quick hack: All node templates are draggable, even in the readonly view + wct.initNodeTemplate(jsPlumb.getSelector(".NodeTemplateShape:not('.hidden')"), true); + + var sourceId; + var targetId; +<% + for (TRelationshipTemplate relationshipTemplate : relationshipTemplatesCasted) { +%> + var req = undefined; + var cap = undefined; +<% + // Source: Either NodeTemplate or Requirement + SourceElement sourceElement = relationshipTemplate.getSourceElement(); + if (sourceElement == null) { + %>vShowError("sourceElement is null for <%=relationshipTemplate.getId()%>");<% + continue; + } + Object source = sourceElement.getRef(); + if (source instanceof TRequirement) { +%> + req = "<%=((TRequirement)source).getId()%>"; + sourceId = getNodeTemplateIdForReqOrCapId(req); +<% + } else { + TNodeTemplate sourceT = (TNodeTemplate) source; + if (sourceT == null) { + %>vShowError("sourceElement.getRef() is null for <%=relationshipTemplate.getId()%>");<% + continue; + } +%> + sourceId = "<%=sourceT.getId()%>"; +<% + } + + // Target: Either NodeTemplate or Requirement + TargetElement targetElement = relationshipTemplate.getTargetElement(); + if (targetElement == null) { + %>vShowError("targetElement is null for <%=relationshipTemplate.getId()%>");<% + continue; + } + Object target = targetElement.getRef(); + if (target instanceof TCapability) { +%> + cap = "<%=((TCapability)target).getId()%>"; + targetId = getNodeTemplateIdForReqOrCapId(cap); +<% + } else { + TNodeTemplate targetT = (TNodeTemplate) target; + if (targetT == null) { + %>vShowError("targetElement.getRef() is null for <%=relationshipTemplate.getId()%>");<% + continue; + } +%> + targetId = "<%=targetT.getId()%>"; +<% + } +%> + var c = jsPlumb.connect({ + source: sourceId, + target: targetId, + type:"<%=relationshipTemplate.getType()%>" + }); + wct.handleConnectionCreated(c); + // we have to store the TOSCA id as jsPlumb does not allow to pass ids from user's side + // we could overwrite c.id, but we are not aware the side effects... + winery.connections[c.id].id = "<%=relationshipTemplate.getId()%>"; + if (req) { + winery.connections[c.id].req = req; + } + if (cap) { + winery.connections[c.id].cap = cap; + } +<% + if (relationshipTemplate.getName() != null) { +%> + winery.connections[c.id].name = "<%=relationshipTemplate.getName()%>"; +<% + } + } +%> + + // all connections are there + // we can register the events now + + jsPlumb.bind("connection", wct.handleConnectionCreated); + + ${ondone} + + // end of the when waiting for all relationship types + }); + // end of require binding + }); + // jsPlumb.ready + }); +// requirejs +}); +</script> diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/templates/toggleButtons.tag b/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/templates/toggleButtons.tag new file mode 100644 index 0000000..05ed289 --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/templates/toggleButtons.tag @@ -0,0 +1,131 @@ +<%-- +/******************************************************************************* + * 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 + *******************************************************************************/ +--%> +<%@tag description="Toggle buttons for visual appearance" pageEncoding="UTF-8"%> +<script> +var JQUERY_ANIMATION_DURATION = 400; + +function doShowOrHide(elements, showThem) { + if (elements.length == 0) { + // e.g., no properties defined + return; + } + if (showThem) { + elements.slideDown(); + } else { + elements.slideUp(); + } + window.setTimeout(function() { + jsPlumb.repaint(elements.parent()); + }, JQUERY_ANIMATION_DURATION); +} + +function showIds(cb) { + var elements; + if ($("div.NodeTemplateShape.selected").size() > 0) { + elements = $("div.NodeTemplateShape.selected div.id.nodetemplate"); + } else { + elements = $("div.NodeTemplateShape:visible div.id.nodetemplate"); + } + + if ($(cb).hasClass("active")) { + elements.fadeOut(); + } else { + elements.fadeIn(); + } + // no repaint required as no nodes are moved + // window.setTimeout(jsPlumb.repaintEverything, JQUERY_ANIMATION_DURATION); +} + +/** + * Toogles visiblity of both node types and relationship types + */ +function showTypes(showThem) { + // types at node templates + var elements; + var typesOfRelationshipTemplates; + if ($("div.NodeTemplateShape.selected").size() > 0) { + elements = $("div.NodeTemplateShape.selected div.type.nodetemplate"); + // TODO: We should put into typesOfRelationshipTemplates all type divs of relationshiptemplates connecting highlighted node templates + // This should be done when doing the multiselect + // And there should be a second if similar to the node templates for relationship templates + typesOfRelationshipTemplates = $(".todo"); + } else { + elements = $("div.NodeTemplateShape:visible div.type.nodetemplate"); + // TODO: we should check for a single relationship template being selected + typesOfRelationshipTemplates = $(".relationshipTypeLabel"); + } + + if (showThem) { + elements.fadeIn(); + typesOfRelationshipTemplates.fadeIn(); + } else { + elements.fadeOut(); + typesOfRelationshipTemplates.fadeOut(); + } + + // no repaint required as no nodes are moved + // window.setTimeout(jsPlumb.repaintEverything, JQUERY_ANIMATION_DURATION); +} + +function showOrHideProperties(showThem) { + var elements; + if ($("div.NodeTemplateShape.selected").size() > 0) { + elements = $("div.NodeTemplateShape.selected > div.propertiesContainer"); + } else { + elements = $("div.NodeTemplateShape:visible > div.propertiesContainer"); + } + doShowOrHide(elements, showThem); +} + + +function showOrHideDeploymentArtifacts(showThem) { + var elements; + if ($("div.NodeTemplateShape.selected").size() > 0) { + elements = $("div.NodeTemplateShape:visible.selected > div.deploymentArtifactsContainer"); + } else { + elements = $("div.NodeTemplateShape:visible > div.deploymentArtifactsContainer"); + } + doShowOrHide(elements, showThem); +} + +function showOrHideReqCaps(showThem) { + var elements; + if ($("div.NodeTemplateShape.selected").size() > 0) { + elements = $("div.NodeTemplateShape:visible.selected > div.requirementsContainer, div.NodeTemplateShape:visible.selected > div.capabilitiesContainer"); + } else { + elements = $("div.NodeTemplateShape:visible > div.requirementsContainer, div.NodeTemplateShape:visible > div.capabilitiesContainer"); + } + doShowOrHide(elements, showThem); +} + +function showOrHidePolicies(showThem) { + var elements; + if ($("div.NodeTemplateShape.selected").size() > 0) { + elements = $("div.NodeTemplateShape:visible.selected > div.policiesContainer"); + } else { + elements = $("div.NodeTemplateShape:visible > div.policiesContainer"); + } + doShowOrHide(elements, showThem); +} +</script> + +<div class="btn-group" data-toggle="buttons-checkbox" id="toggleButtons"> + <button class="btn btn-default" id="toggleIdVisibility" onclick="showIds(this);">Ids</button> + <button class="btn active" id="toggleTypeVisibility" onclick="showTypes(!$(this).hasClass('active'));">Types</button> + <button class="btn btn-default" id="togglePropertiesVisibility" onclick="showOrHideProperties(!$(this).hasClass('active'));">Properties</button> + <button class="btn btn-default" id="toggleDeploymentArtifactsVisibility" onclick="showOrHideDeploymentArtifacts(!$(this).hasClass('active'));">Deployment Artifacts</button> + <button class="btn btn-default" id="toggleReqCapsVisibility" onclick="showOrHideReqCaps(!$(this).hasClass('active'));">Requirements & Capabilities</button> + <button class="btn btn-default" id="PoliciesVisibility" onclick="showOrHidePolicies(!$(this).hasClass('active'));">Policies</button> +</div> + 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> + diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/idInput.tag b/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/idInput.tag new file mode 100644 index 0000000..86dae1c --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/idInput.tag @@ -0,0 +1,43 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2014 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 + *******************************************************************************/ +--%> +<%@tag description="input field for an id unique in the target namespace. Current implementation: Unique in the topology modeler" pageEncoding="UTF-8"%> + +<%@attribute name="inputFieldId" required="true" description="The name and id of the input field"%> + +<div class="form-group" id="${inputFieldId}Group"> + <label for="${inputFieldId}" class="control-label">Id:</label> + <input id="${inputFieldId}" class="form-control" name="${inputFieldId}" type="text" required="required" /> +</div> + +<script> +$("#${inputFieldId}").typing({ + stop: function(evt, elem) { + // check for existinance in the current model + // TODO: global check using the backend + var isSuccess; + try { + var val = elem.val(); + isSuccess = (val != "") && ($("#" + elem.val()).length == 0); + } catch(err) { + // all syntax errors are invalid inputs + isSuccess = false; + } + var newClass = (isSuccess? "has-success" : "has-error"); + var div = elem.parent(); + if (!div.hasClass(newClass)) { + div.removeClass("has-error").removeClass("has-success").addClass(newClass); + } + } +}); +</script>
\ No newline at end of file diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/namespaceChooser.tag b/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/namespaceChooser.tag new file mode 100644 index 0000000..25a19e3 --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/namespaceChooser.tag @@ -0,0 +1,52 @@ +<%-- +/******************************************************************************* + * 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 + *******************************************************************************/ +--%> +<%@tag description="places a bootstrap form control to chooose a namespace. A new namespace can be created" pageEncoding="UTF-8"%> + +<!-- + This tag is shared at repository and topologytemplate. + Both versions differ from each other. + In the repository, ns.decoded is used. + In the topology modeler only "ns" is used: + In other words: The topology modeler passes a Collection<String>, whereas repository passes Collection<Namespace> + --> + +<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> + +<%@attribute name="allNamespaces" required="true" type="java.util.Collection" description="All known namespaces as strings (because the topology modeler currently doesn't provide that as list of winery namespace objects)"%> +<%@attribute name="idOfInput" required="true" description="The id if the input field storing the namespace. Also used as name"%> +<%@attribute name="nameOfInput" required="false" description="The name if the input field storing the namespace. If not provided, ifOfInput is used"%> +<%@attribute name="selected" description="The currently selected namespace (optional)"%> + +<c:if test="${empty nameOfInput}"><c:set var="nameOfInput" value="${idOfInput}"></c:set></c:if> + +<!-- createArtifactTemplate class is required for artifactcreationdialog --> +<div class="form-group createArtifactTemplate"> + <label for="${idOfInput}" class="control-label">Namespace</label> + <input type="hidden" class="form-control" name="${nameOfInput}" id="${idOfInput}"></input> +</div> + +<script> +// we have to use data as select2 does not allow "createSearchChoice" when using <select> as underlying html element +$("#${idOfInput}").select2({ + createSearchChoice: function(term) { + // enables creation of new namespaces + return {id:term, text:term}; + }, + data:[ + <c:forEach var="ns" items="${allNamespaces}" varStatus="loop"> + {id:"${ns}",text:"${ns}"}<c:if test="${!loop.last}">,</c:if> + </c:forEach> + ] +}).select2("val", "${selected}"); +</script> diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/palette.tag b/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/palette.tag new file mode 100644 index 0000000..e6363f6 --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/palette.tag @@ -0,0 +1,207 @@ +<%-- +/******************************************************************************* + * 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: + * Uwe Breitenbücher - initial API and implementation and/or initial documentation + * Oliver Kopp - improvements + *******************************************************************************/ +--%> +<%@tag language="java" pageEncoding="UTF-8" description="Renders the palette on the left"%> + +<%@attribute name="repositoryURL" required="true" type="java.lang.String"%> +<%@attribute name="client" required="true" description="IWineryRepository" type="org.eclipse.winery.common.interfaces.IWineryRepository"%> +<%@attribute name="relationshipTypes" description="the known relationship types" required="true" type="java.util.Collection"%> + +<%@tag import="javax.xml.namespace.QName" %> +<%@tag import="java.util.Collection"%> +<%@tag import="java.util.UUID"%> +<%@tag import="java.util.List"%> +<%@tag import="org.eclipse.winery.common.interfaces.IWineryRepository" %> +<%@tag import="org.eclipse.winery.model.tosca.TNodeType"%> +<%@tag import="org.eclipse.winery.common.Util" %> + +<%@taglib prefix="nt" tagdir="/WEB-INF/tags/common/templates/nodetemplates" %> + +<link rel="stylesheet" href="css/palette.css" /> + +<div id="palette"> + +<div id="paletteLabel"> +Palette +</div> + +<% + Collection<TNodeType> allNodeTypes = client.getAllTypes(TNodeType.class); + if (allNodeTypes.isEmpty()) { +%> + <script> + vShowError("No node types exist. Please add node types in the repository."); + </script> + <% + } + for (TNodeType nodeType: allNodeTypes) { + if (nodeType.getName() == null) { + System.err.println("Invalid nodetype in ns " + nodeType.getTargetNamespace()); + continue; + } +%> + <div class="paletteEntry"> + <div class="iconContainer"> + <img class="icon" onerror="var that=this; require(['winery-common-topologyrendering'], function(wct){wct.imageError(that);});" src="<%= repositoryURL %>/nodetypes/<%= Util.DoubleURLencode(nodeType.getTargetNamespace()) %>/<%=Util.DoubleURLencode(nodeType.getName())%>/visualappearance/50x50" /> + </div> + <div class="typeContainer"> + <div class="typeContainerMiddle"> + <div class="typeContainerInner"> + <%= nodeType.getName() %> + </div> + </div> + </div> + + <div class="hidden"> + <nt:nodeTemplateRenderer + repositoryURL="${repositoryURL}" + client="${client}" + relationshipTypes="${relationshipTypes}" + nodeTypeQName="<%=new QName(nodeType.getTargetNamespace(), nodeType.getName())%>" + nodeType="<%=nodeType%>" /> + </div> + </div> + +<% + } +%> + +</div> + + +<script> + + //$("#palette").css("width","20px"); + //$("div.paletteEntry").hide(); + + $("#palette").click (function() { + showPalette(); + winery.events.fire(winery.events.name.command.UNSELECT_ALL_NODETEMPLATES); + }); + + function showPalette() { + // reset width to original CSS width + $("#palette").removeClass("shrunk"); + // show all palette entries + $("div.paletteEntry").show(); + $("#paletteLabel").hide(); + } + + function hidePalette() { + $("#palette").addClass("shrunk"); + // hide all palette entries + $("div.paletteEntry").hide(); + $("#paletteLabel").show(); + } + + $(function() { + $( "div.paletteEntry" ).draggable({ + cursor: "move", + cursorAt: { top: 40, left: 112 }, + helper: function( event ) { + var newObj = $(this).find("div.NodeTemplateShape").clone(); + newObj.removeClass("hidden"); + newObj.css("z-index", "2000"); + newObj.find ("div.endpointContainer").remove(); + + // Ensure that obj is appended to drawingarea and not to palette + // Consequence: the dragged object is always under the cursor and not paintet with an offset equal to the scrollheight + $("#drawingarea").append(newObj); + + return newObj; + }, + start: function( event, ui ) { + winery.events.fire(winery.events.name.command.UNSELECT_ALL_NODETEMPLATES); + // The palette is kept visible after a drag start, + // therefore no action + // hidePalette(); + }, + appendTo: '#drawingarea' + }); + + + $( "div#drawingarea" ).droppable({ + accept: function(d) { + if (d.hasClass("paletteEntry")) { + return true; + } + }, + drop: function( event, ui ) { + + var palEntry = ui.draggable; + var templateCode = palEntry.find("div.NodeTemplateShape").clone().wrap("<div></div>").parent().html(); + + var newObj = $(templateCode); + + newObj.removeClass("ui-draggable"); + newObj.removeClass("ui-droppable"); + newObj.removeClass("hidden"); + + // generate and set id + var type = newObj.find("div.type.nodetemplate").text(); + var id = type; + // we cannot use the id as the initial name, because we want to preserve special characters in the name, but not in the id. + var name = type; + + // quick hack to make id valid + // currently, only spaces and dots cause problems + id = id.replace(" ", "_"); + id = id.replace(".", "_"); + + if ($("#" + id).length != 0) { + var count = 2; + var idprefix = id + "_"; + do { + id = idprefix + count; + count++; + } while ($("#" + id).length != 0); + // also adjust name + name = name + "_" + count; + } + newObj.attr("id", id); + newObj.children("div.headerContainer").children("div.id").text(id); + + // initial name has been generated based on the id + newObj.children("div.headerContainer").children("div.name").text(name); + + // fix main.css -> #editorArea -> margin-top: 45px; + var top = Math.max(event.pageY-45, 0); + + // drag cursor is at 112/40 + // fix that + top = Math.max(top-40, 0); + var left = Math.max(event.pageX-112, 0); + + newObj.css("top", top); + newObj.css("left", left); + + newObj.addClass("selected"); + + // insert into sheet + newObj.appendTo( $( "div#drawingarea" ) ); + + // initialization works only for displayed objects + require(["winery-common-topologyrendering"], function(wct) { + wct.initNodeTemplate(newObj, true); + + // handle menus + winery.events.fire(winery.events.name.SELECTION_CHANGED); + }); + } + }) + + +}); + +</script> diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/templates/nodetemplates/propertiesOfOneNodeTemplate.tag b/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/templates/nodetemplates/propertiesOfOneNodeTemplate.tag new file mode 100644 index 0000000..238e34a --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/templates/nodetemplates/propertiesOfOneNodeTemplate.tag @@ -0,0 +1,147 @@ +<%-- +/******************************************************************************* + * 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: + * Uwe Breitenbücher - initial API and implementation and/or initial documentation + * Oliver Kopp - improvements to fit updated index.jsp + * Yves Schubert - switch to bootstrap 3 + *******************************************************************************/ +--%> + +<%@tag language="java" pageEncoding="UTF-8" description="Renders the properies of one node tempate on the right"%> + +<%@attribute name="repositoryURL" required="true" type="java.lang.String" description="The repository URL"%> + +<%@taglib prefix="ct" tagdir="/WEB-INF/tags/common" %> + + +<link rel="stylesheet" href="css/propertiesview.css" /> + +<div id="NTPropertiesView" class="propertiesView" style="display: none;"> + + <div id="nodeTemplateInformationSection"> + <%-- + If this is layouted strangely, maybe a <form> wrapper has to be added + Be aware that nested buttons then trigger a submission of the form (-> ct:spinnerwithinphty) + --%> + <fieldset> + <div class="form-group"> + <label for="nodetemplateid">Id</label> + <input id="nodetemplateid" disabled="disabled" class="form-control"></input> + </div> + <div class="form-group"> + <label for="nodetemplatename" class="control-label">Name</label> + <input id="nodetemplatename" name="name" class="form-control"/> + </div> + <div class="form-group"> + <label for="nodetemplateType">Type</label> + <%-- filled by fillInformationSection --%> + <a id="nodetemplateType" target="_blank" href="#" class="form-control"></a> + </div> + <ct:spinnerwithinphty min="0" width="10" changedfunction="minInstancesChanged" label="min" id="minInstances" /> + <ct:spinnerwithinphty min="1" width="10" changedfunction="maxInstancesChanged" label="max" id="maxInstances" withinphty="true" /> + </fieldset> + </div> + +</div> + +<script> + function minInstancesChanged(event, ui) { + var val; + if (ui === undefined) { + val = $("#minInstances").val(); + } else { + val = ui.value; + } + ntMin.html(val); + } + + function maxInstancesChanged(event, ui) { + var val; + if (ui === undefined) { + val = $("#maxInstances").val(); + } else { + val = ui.value; + } + ntMax.html(val); + } + + // the name input field of the properties section + var nameInput = $("#nodetemplatename"); + + // the min/max fields of the currently selected node template + var ntMin; + var ntMax; + + function fillInformationSection(nodeTemplate) { + require(["winery-support-common"], function(wsc) { + // currently doesn't help for a delayed update + //informationSection.slideDown(); + + $("#nodetemplateid").val(nodeTemplate.attr("id")); + + var headerContainer = nodeTemplate.children("div.headerContainer"); + + // copy name + var nameField = headerContainer.children("div.name"); + var name = nameField.text(); + nameInput.val(name); + + // copy type + var typeQName = headerContainer.children("span.typeQName").text(); + var href = wsc.makeNodeTypeURLFromQName("${repositoryURL}", typeQName); + var type = headerContainer.children("div.type").text(); + $("#nodetemplateType").attr("href", href).text(type); + + // we could use jQuery-typing, but it is not possible to replace key events there + nameInput.off("keyup"); + nameInput.on("keyup", function() { + nameField.text($(this).val()); + }); + + // handling of min and max + ntMin = nodeTemplate.children(".headerContainer").children(".minMaxInstances").children(".minInstances"); + $("#minInstances").val(ntMin.text()); + ntMax = nodeTemplate.children(".headerContainer").children(".minMaxInstances").children(".maxInstances"); + $("#maxInstances").val(ntMax.text()); + }); + } + + function showViewOnTheRight() { + $("#NTPropertiesView").fadeIn(); + } + + function hideViewOnTheRight() { + $("#NTPropertiesView").fadeOut(); + } + +$(function() { + winery.events.register( + winery.events.name.SELECTION_CHANGED, + function() { + // min/max instances do not lost focus if other shape is clicked + // workaround + if ($("#minInstances").is(":focus")) { + minInstancesChanged(); + } + if ($("#maxInstances").is(":focus")) { + maxInstancesChanged(); + } + var nodeTemplate = $("div.NodeTemplateShape.selected"); + var numSelected = nodeTemplate.length; + if (numSelected == 1) { + fillInformationSection(nodeTemplate); + showViewOnTheRight(); + } else { + hideViewOnTheRight(); + } + } + ); +}); +</script> diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/templates/nodetemplates/reqscaps/addorupdatereqorcap.tag b/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/templates/nodetemplates/reqscaps/addorupdatereqorcap.tag new file mode 100644 index 0000000..0ec6f5d --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/templates/nodetemplates/reqscaps/addorupdatereqorcap.tag @@ -0,0 +1,248 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2012-2014 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 + *******************************************************************************/ +--%> +<%@tag description="Dialog to change a req or cap. Offers function showEditDiagFor${shortName}(id)" pageEncoding="UTF-8"%> + +<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@taglib prefix="nt" tagdir="/WEB-INF/tags/common/templates/nodetemplates" %> +<%@taglib prefix="o" tagdir="/WEB-INF/tags/common/orioneditor"%> +<%@taglib prefix="w" tagdir="/WEB-INF/tags"%> +<%@taglib prefix="wc" uri="http://www.eclipse.org/winery/functions"%> + +<%@attribute name="headerLabel" required="true"%> +<%@attribute name="shortName" required="true" description="Used for diag id, function name suffix, Req|Cap"%> +<%@attribute name="requirementOrCapability" required="true" description="requirement|capability"%> +<%@attribute name="cssClassPrefix" required="true"%> +<%@attribute name="allTypes" required="true" type="java.util.Collection" description="Collection<QName> of all available types" %> +<%@attribute name="clazz" required="true" type="java.lang.Class" description="TRequirement.class or TCapability.class" %> +<%@attribute name="repositoryURL" required="true" %> + +<div class="modal fade" id="AddOrUpdate${shortName}Diag"> + <div class="modal-dialog"> + <div class="modal-content" style="width:660px;"> + <div class="modal-header"> + <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button> + <h4 class="modal-title"><span id="headerAddOrUpdate"></span> ${headerLabel}</h4> + </div> + <div class="modal-body"> + <form id="add${shortName}Form" enctype="multipart/form-data"> + <fieldset> + <w:idInput inputFieldId="${shortName}Id"/> + + <div class="form-group"> + <label for="${shortName}NameChooser" class="control-label">Definition Name:</label> + <input id="${shortName}NameChooser" class="form-control" type="text" required="required" /> + </div> + + <div class="form-group"> + <label for="${shortName}TypeDisplay" class="control-label">${shortName} Type:</label> + <input id="${shortName}TypeDisplay" class="form-control" type="text" required="required" disabled="disabled"/> + </div> + + <div id="${shortName}PropertiesContainer"> + </div> + </fieldset> + </form> + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button> + <button type="button" id="add${shortName}btn" class="btn btn-primary" onclick="addOrUpdate${shortName}(false);">Add</button> + <button type="button" id="delete${shortName}btn" class="btn btn-danger" onclick="deleteCurrent${shortName}();">Delete</button> + <button type="button" id="update${shortName}btn" class="btn btn-primary" onclick="addOrUpdate${shortName}(true);">Change</button> + </div> + </div> + </div> +</div> + +<script> + +/* + * The following variables are declared twice due to double inclusion of this .tag flie + * Due to JavaScript magic, it works nevertheless + */ +var selectedNodeTemplateForReqCapAddition; + +//global variable set by editPropertiesXML and read by save${shortName}Edits +var nodeTemplateEditedReqOrCap; + + +function deleteCurrent${shortName}() { + nodeTemplateEditedReqOrCap.remove(); + $("#AddOrUpdate${shortName}Diag").modal("hide"); +} + +function update${shortName}PropertiesContainerWithClone(propertiesContainerToClone) { + var clone = propertiesContainerToClone.clone(); + $("#${shortName}PropertiesContainer").empty().append(clone); + clone.find(".KVPropertyValue").editable({mode: "inline"}); +} + +function update${shortName}PropertiesFromSelectedType() { + var data = $("#${shortName}NameChooser").select2("data"); + var name = data.text; + var type = data.id; + + // fill in type + // TODO: use qname2href and store QName in data-qname for later consumption -- possibly qname2href should always store the qname in data-qname + $("#${shortName}TypeDisplay").val(type); + + // fill in properties (derived from type) + var propertiesContainer= $(".skelettonPropertyEditorFor${shortName} > span:contains('" + type + "')").parent().children("div"); + update${shortName}PropertiesContainerWithClone(propertiesContainer); +} + +$("#${shortName}NameChooser").on("change", function(e) { + update${shortName}PropertiesFromSelectedType(); +}); + +/** + * Called when a req/cap should be added or updated + * Update mode is triggered if reqOrCapIdtoUpdate is given + * + * @param nodeTemplateId the node template id to add a req/cap to. undefined in update mode + * @param reqOrCapIdtoUpdate + */ +function showAddOrUpdateDiagFor${shortName}(nodeTemplateId, reqOrCapIdToUpdate) { + var update = (typeof reqOrCapIdToUpdate !== "undefined"); + + if (update) { + nodeTemplateEditedReqOrCap = $("#" + reqOrCapIdToUpdate); + // in update mode, nodeTemplateId is not provided, we have to search for the right shape + selectedNodeTemplateForReqCapAddition = nodeTemplateEditedReqOrCap.closest(".NodeTemplateShape"); + } else { + selectedNodeTemplateForReqCapAddition = $("#" + nodeTemplateId); + } + + require(["winery-support-common"], function(wsc) { + var typeQName = selectedNodeTemplateForReqCapAddition.children("div.headerContainer").children("span.typeQName").text(); + var urlFragment = wsc.getURLFragmentOutOfFullQName(typeQName); + var url = "${repositoryURL}/nodetypes/" + urlFragment + "/${requirementOrCapability}definitions/"; + $.ajax({ + url: url, + dataType: "json" + }).fail(function(jqXHR, textStatus, errorThrown) { + vShowAJAXError("Could not fetch ${requirementOrCapability} definitions", jqXHR, errorThrown); + }).done(function(data) { + // now, we have all available requirement definitions + // we have to ask each of it for the type + // we use the type as key for the option and the name as displayed text + // select2 perfectly handles duplicate keys + + var select2Data = []; + + $.each(data, function(i,e) { + var rqDefURL = url + e + "/type"; + $.ajax({ + url: rqDefURL, + async: false, + dataType: "text" + }).fail(function(jqXHR, textStatus, errorThrown) { + vShowAJAXError("Could not fetch type for " + e, jqXHR, errorThrown); + }).done(function(data) { + var item = { + id: data, + text: e + }; + select2Data.push(item); + }); + }); + + $("#${shortName}NameChooser").select2({ + placeholder: "Select name", + data: select2Data + }); + + if (update) { + $("#add${shortName}btn").hide(); + $("#update${shortName}btn").show(); + $("#delete${shortName}btn").show(); + $("#headerAddOrUpdate").text("Change"); + + // collect existing data in variables + var id = nodeTemplateEditedReqOrCap.children(".id").text(); + var name = nodeTemplateEditedReqOrCap.children(".name").text(); + var type = nodeTemplateEditedReqOrCap.children(".type").children("a").data("qname"); + var propertiesContainer = nodeTemplateEditedReqOrCap.children(".propertiesContainer"); + + // update displays + + // id + $("#${shortName}Id").val(id); + + // name + // we use the type as key at NameChooser. We hope that there are no duplicates. Otherwise, update won't work. + $("#${shortName}NameChooser").select2("val", type); + // make consistency check + var data = $("#${shortName}NameChooser").select2("data"); + if (data == null) { + vShowError("type " + type + " could not be selected.") + } else if (name != (data.text)) { + vShowError("There are two names for different types. That case is not handled in the UI."); + } + + // type + $("#${shortName}TypeDisplay").val(type); + + // properties + update${shortName}PropertiesContainerWithClone(propertiesContainer); + } else { + $("#add${shortName}btn").show(); + $("#update${shortName}btn").hide(); + $("#delete${shortName}btn").hide(); + $("#headerAddOrUpdate").text("Add"); + + // QUICK HACK if dialog has been shown before -> show properties of selected type + if ($("#${shortName}NameChooser").select2("data") != null) { + update${shortName}PropertiesFromSelectedType(); + } + } + + $("#AddOrUpdate${shortName}Diag").modal("show"); + }); + }); +} + +/** + * Called at click on button "Add" or "Change" + */ +function addOrUpdate${shortName}(update) { + if (highlightRequiredFields()) { + vShowError("Please fill in all required fields"); + return; + } + require(["tmpl"], function(tmpl) { + // Generate skeletton div + var sel2data = $("#${shortName}NameChooser").select2("data"); + var data = { + id: $("#${shortName}Id").val(), + name: sel2data.text, + type: sel2data.id + } + // tmpl-${shortName} is defined in reqsorcaps.tag + var div = tmpl("tmpl-${shortName}", data); + + // Add the div to the node template + if (update) { + nodeTemplateEditedReqOrCap.replaceWith(div); + } else { + selectedNodeTemplateForReqCapAddition.children(".${cssClassPrefix}Container").children(".content").children(".addnewreqorcap").before(div); + } + + // Put properties at the right place + $("#toBeReplacedByProperties").replaceWith($("#${shortName}PropertiesContainer").children()); + + $("#AddOrUpdate${shortName}Diag").modal("hide"); + }); +} + +</script> diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/templates/relationshiptemplates/propertiesOfOneRelationshipTemplate.tag b/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/templates/relationshiptemplates/propertiesOfOneRelationshipTemplate.tag new file mode 100644 index 0000000..8c63dca --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/templates/relationshiptemplates/propertiesOfOneRelationshipTemplate.tag @@ -0,0 +1,179 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2012-2014 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 + *******************************************************************************/ +--%> +<%@tag language="java" pageEncoding="UTF-8" description="Renders the properies of one relationship tempate on the right"%> + +<%@attribute name="relationshipTypes" required="true" type="java.util.Collection" %> +<%@attribute name="repositoryURL" required="true" type="java.lang.String" description="The repository URL"%> + +<link rel="stylesheet" href="css/propertiesview.css" /> + +<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> +<%@taglib prefix="props" tagdir="/WEB-INF/tags/common/templates" %> +<%@taglib prefix="wc" uri="http://www.eclipse.org/winery/functions" %> + +<div id="RTPropertiesView" class="propertiesView" style="display: none;"> + + <div id="relationshipTemplateInformationSection"> + <fieldset> + <div class="form-group"> + <label for="relationshiptemplateid">Id</label> + <input id="relationshiptemplateid" disabled="disabled" class="form-control"></input> + </div> + <div class="form-group"> + <label for="relationshiptemplatename" class="control-label">Name</label> + <a href="#" id="relationshiptemplatename" data-title="Name" data-type="text" class="form-control"></a> + </div> + <div class="form-group"> + <label for="relationshipType">Type</label> + <%-- filled by showRTViewOnTheRight --%> + <a id="relationshipType" target="_blank" href="#" class="form-control"></a> + </div> + <div class="form-group"> + <label for="RTreq" class="control-label">Requirement</label> + <select id="RTreq" class="form-control"> + </select> + </div> + <div class="form-group"> + <label for="RTcap" class="control-label">Capability</label> + <select id="RTcap" class="form-control"> + </select> + </div> + </fieldset> + </div> + +</div> + +<script> + + var currentlySelectedConn = null; + + /** + * Fills the requirement and capabilities dropdowns with the available reqs and caps (which are defined at the source/target node template) + * + * @param conn the connection itself + * @param dataField = "req"|"cap" + * @param sourceDivClass = requirementsContainer | capabilitiesContainer + */ + function fillReqOrCap(conn, dataField, nodetemplateId, sourceDivClass, targetSelect) { + var nt = $("#" + nodetemplateId); + var reqsOrCaps = nt.children("." + sourceDivClass).children(".content").children(".reqorcap"); + var connReqCap = winery.connections[conn.id][dataField]; + + targetSelect.empty(); + + var optData = { + value: "__NONE__", + text: "(none)" + }; + if (!connReqCap) { + selected: true + } + require(["tmpl"], function(tmpl) { + var newOption = tmpl("tmpl-option", optData); + targetSelect.append(newOption); + + reqsOrCaps.each(function(i,e) { + optData.value = $(e).children(".id").children("span.id").text(); + optData.text = $(e).children(".name").children("span.name").text(); + optData.selected = (optData.value == connReqCap); + newOption = tmpl("tmpl-option", optData); + targetSelect.append(newOption); + }); + }); + + targetSelect.off("change"); + targetSelect.on("change", function(e) { + var val = targetSelect.val(); + if (val == "__NONE__") { + delete(winery.connections[conn.id][dataField]); + } else { + winery.connections[conn.id][dataField] = val; + } + }); + } + + function fillType(nsAndLocalName) { + require(["winery-support-common"], function(wsc) { + var href = wsc.makeRelationshipTypeURLFromNSAndLocalName("${repositoryURL}", nsAndLocalName); + // localname is always the name of the relationship type because the specification requires a "name" attribute only and does not foresee an "id" attribute + $("#relationshipType").attr("href", href).text(nsAndLocalName.localname); + }) + } + + function displayProperties(connData) { + $("#RTPropertiesView").append(connData.propertiesContainer); + } + + /** + * @param conn the jsPlumb connection + */ + function showRTViewOnTheRight(conn) { + currentlySelectedConn = conn; + + $("#RTPropertiesView").fadeIn(); + + $("#relationshiptemplateid").val(winery.connections[conn.id].id); + $("#relationshiptemplatename").editable('setValue', winery.connections[conn.id].name); + fillReqOrCap(conn, "req", conn.sourceId, "requirementsContainer", $("#RTreq")); + fillReqOrCap(conn, "cap", conn.targetId, "capabilitiesContainer", $("#RTcap")); + fillType(winery.connections[conn.id].nsAndLocalName); + displayProperties(winery.connections[conn.id]); + } + + function hideRTViewOnTheRight() { + if (currentlySelectedConn == null) { + // nothing to do if no relationship template is selected + return; + } + + $("#RTPropertiesView").fadeOut(); + + // user will see some flickering here, but we don't want to set timers -> could lead to race conditions + $("#skelettonContainerForRelationshipTemplates").append(winery.connections[currentlySelectedConn.id].propertiesContainer); + currentlySelectedConn = null; + } + + function storeUpdatedName(newName) { + currentlySelectedConn.name = newName; + } + + $(function() { + $("#relationshiptemplatename").editable({ + success: function(response, newValue) { + currentlySelectedConn.name = newValue; + } + }); + }); + + function unselectAllConnections() { + jsPlumb.select().each(function(connection) { + connection.removeType("selected"); + }); + } + + winery.events.register( + winery.events.name.SELECTION_CHANGED, + function() { + var nodeTemplate = $("div.NodeTemplateShape.selected"); + var numSelected = nodeTemplate.length; + if (numSelected != 0) { + // if node templates are selected, no RT properties should be shown + hideRTViewOnTheRight(); + + unselectAllConnections(); + } + } + ); + +</script> diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/web.xml b/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000..37b6dc9 --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/******************************************************************************* + * 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 + *******************************************************************************/ +--> +<web-app xmlns="http://java.sun.com/xml/ns/javaee" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" + id="winery-topologymodeler" + version="3.0"> + <display-name>Winery Topology Modeler</display-name> +</web-app> |