Add winery source code
[vfc/nfvo/wfengine.git] / winery / org.eclipse.winery.repository / src / main / webapp / jsp / servicetemplates / boundarydefinitions / boundarydefinitions.jsp
1 <%--
2 /*******************************************************************************
3  * Copyright (c) 2013 University of Stuttgart.
4  * All rights reserved. This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License v1.0
6  * and the Apache License 2.0 which both accompany this distribution,
7  * and are available at http://www.eclipse.org/legal/epl-v10.html
8  * and http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Contributors:
11  *    Oliver Kopp - initial API and implementation and/or initial documentation
12  *    Tobias Binz - communication with the nested iframe
13  *******************************************************************************/
14 --%>
15
16 <%@taglib prefix="c"  uri="http://java.sun.com/jsp/jstl/core"%>
17 <%@taglib prefix="w"  tagdir="/WEB-INF/tags"%>
18 <%@taglib prefix="o"  tagdir="/WEB-INF/tags/common/orioneditor"%>
19 <%@taglib prefix="b"  tagdir="/WEB-INF/tags/servicetemplates/boundarydefinitions"%>
20 <%@taglib prefix="pol" tagdir="/WEB-INF/tags/common/policies" %>
21 <%@taglib prefix="wc" uri="http://www.eclipse.org/winery/functions"%>
22 <%@taglib prefix="wr" uri="http://www.eclipse.org/winery/repository/functions"%>
23
24 <%@page import="org.eclipse.winery.common.ModelUtilities"%>
25
26 <pol:policydiag allPolicyTypes="${it.allPolicyTypes}" repositoryURL="${it.repositoryURL}" />
27
28 <b:browseForServiceTemplatePropertyReqOrCap definedPropertiesAsJSONString="${it.definedPropertiesAsJSONString}" />
29
30 <div class="modal fade" id="propertyMappingDiag">
31         <div class="modal-dialog">
32                 <div class="modal-content">
33                         <div class="modal-header">
34                                 <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
35                                 <h4 class="modal-title">Add property mapping</h4>
36                         </div>
37                         <div class="modal-body">
38                                 <form id="propertyMappingForm" enctype="multipart/form-data">
39                                         <fieldset>
40                                                 <div class="form-group">
41                                                         <label for="serviceTemplatePropertyRef">Service Template Property</label>
42                                                         <div class="row">
43                                                                 <div class="col-xs-10">
44                                                                         <input name="serviceTemplatePropertyRef" id="serviceTemplatePropertyRef" class="form-control" type="text" required="required">
45                                                                 </div>
46                                                                 <div class="col-xs-2">
47                                                                         <button type="button" class="btn btn-default btn-sm" onclick="browseForServiceTemplateProperty($('#serviceTemplatePropertyRef'));">Browse</button>
48                                                                 </div>
49                                                         </div>
50                                                 </div>
51
52                                                 <div class="form-group">
53                                                         <label for="targetObjectRef">Target: Node Template, Requirement, Capability, or Relationship Template</label>
54                                                         <div class="row">
55                                                                 <div class="col-xs-4">
56                                                                         <input name="targetObjectRef" id="targetObjectRef" class="form-control" type="text" required="required">
57                                                                 </div>
58                                                                 <div class="col-xs-2">
59                                                                         <button type="button" class="btn btn-default btn-sm" onclick="browseForTemplateAndProperty();">Browse</button>
60                                                                 </div>
61                                                         </div>
62                                                 </div>
63
64                                                 <div class="form-group">
65                                                         <label for="targetPropertyRef">Target Property</label>
66                                                         <input name="targetPropertyRef" id="targetPropertyRef" class="form-control" type="text" required="required"/>
67                                                 </div>
68                                         </fieldset>
69                                 </form>
70                         </div>
71
72                         <div class="modal-footer">
73                                 <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
74                                 <button id="addPropertyMapping"    type="button" class="btn btn-primary" onclick="addPropertyMapping()">Add</button>
75                                 <button id="updatePropertyMapping" type="button" class="btn btn-primary" onclick="updatePropertyMapping()">Update</button>
76                         </div>
77                 </div>
78         </div>
79 </div>
80
81 <div class="modal fade" id="propertyConstraintDiag">
82         <div class="modal-dialog">
83                 <div class="modal-content">
84                         <div class="modal-header">
85                                 <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
86                                 <h4 class="modal-title">Add property constraint</h4>
87                         </div>
88                         <div class="modal-body">
89                                 <form id="propertyMappingForm" enctype="multipart/form-data">
90                                         <fieldset>
91                                                 <div class="form-group">
92                                                         <label for="serviceTemplatePropertyRef">Service Template Property</label>
93                                                         <div class="row">
94                                                                 <div class="col-xs-10">
95                                                                         <input name="serviceTemplatePropertyRef" id="serviceTemplatePropertyRefForConstraint" class="form-control" type="text" />
96                                                                 </div>
97                                                                 <div class="col-xs-2">
98                                                                         <button type="button" class="btn btn-default btn-sm" onclick="browseForServiceTemplateProperty($('#serviceTemplatePropertyRefForConstraint'));">Browse</button>
99                                                                 </div>
100                                                         </div>
101                                                 </div>
102
103                                                 <w:typeswithshortnameasselect label="Constraint Type" selectname="constraintType" type="constrainttype" typesWithShortNames="${it.constraintTypes}"/>
104
105                                                 <div class="form-group">
106                                                         ... constraint fragment ...
107                                                 </div>
108                                         </fieldset>
109                                 </form>
110                         </div>
111
112                         <div class="modal-footer">
113                                 <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
114                                 <button id="addPropertyConstraint"    type="button" class="btn btn-primary" onclick="addPropertyMapping()">Add</button>
115                                 <button id="updatePropertyConstraint" type="button" class="btn btn-primary" onclick="updatePropertyMapping()">Update</button>
116                         </div>
117                 </div>
118         </div>
119 </div>
120
121
122
123 <div id="alltabswithcontent">
124 <ul class="nav nav-tabs" id="myTab">
125         <li class="active"><a href="#properties">Properties</a></li>
126         <li><a href="#propertymappings">Property Mappings</a></li>
127         <li><a href="#propertyconstraints">Property Constraints</a></li>
128         <li><a href="#requirements">Requirements</a></li>
129         <li><a href="#capabilities">Capabilities</a></li>
130         <li><a href="#policies">Policies</a></li>
131         <li><a href="#interfaces">Interfaces</a></li>
132         <li><a href="#xml">XML</a></li>
133 </ul>
134
135 <div class="tab-content">
136
137         <div class="tab-pane active" id="properties">
138                 <%-- reloadAfterSuccess is necessary as the XMLtree has to be changed --%>
139                 <o:orioneditorarea areaid="XMLtextarea" url="boundarydefinitions/properties" reloadAfterSuccess="true">${it.definedPropertiesAsEscapedHTML}</o:orioneditorarea>
140         </div>
141
142         <div class="tab-pane" id="propertymappings">
143                 <c:choose>
144                         <c:when test="${empty it.definedPropertiesAsEscapedHTML}">
145                         <p>No properties available. Thus, no properties can be mapped. Please define properties.</p>
146                         </c:when>
147                         <c:otherwise>
148                                 <button id="deleteRequirement" class="rightbutton btn btn-xs btn-danger" onclick="deleteOnServerAndInTable(propertyMappingsTableInfo, 'Property Mapping', 'boundarydefinitions/propertymappings/');">Remove</button>
149                                 <button class="rightbutton btn btn-xs btn-info" onclick="openAddPropertyMappingDiag();">Add</button>
150                                 <button class="rightbutton btn btn-xs btn-primary" onclick="openUpdatePropertyMappingDiag();">Edit</button>
151                                 <table id="propertyMappingsTable">
152                                         <thead>
153                                                 <tr>
154                                                         <th>Service Template Property</th>
155                                                         <th>Target</th>
156                                                         <th>Target Property</th>
157                                                 </tr>
158                                         </thead>
159                                         <tbody>
160                                                 <c:if test="${not empty it.defs.properties and not empty it.defs.properties.propertyMappings and not empty it.defs.properties.propertyMappings.propertyMapping}">
161                                                         <c:forEach items="${it.defs.properties.propertyMappings.propertyMapping}" var="propertyMapping">
162                                                                 <tr>
163                                                                         <td>${propertyMapping.serviceTemplatePropertyRef}</td>
164                                                                         <td>${propertyMapping.targetObjectRef.id}</td> <%-- .name cannot be used as it is not an Id. Future work: Store the id in a seperate field and show the name to the user --%>
165                                                                         <td>${propertyMapping.targetPropertyRef}</td>
166                                                                 </tr>
167                                                         </c:forEach>
168                                                 </c:if>
169                                         </tbody>
170                                 </table>
171                         </c:otherwise>
172                 </c:choose>
173         </div>
174
175         <%-- TODO: provide this as .tag. The property constraint resource should also be provided as tag --%>
176         <div class="tab-pane" id="propertyconstraints">
177                 <button class="rightbutton btn btn-xs btn-danger" onclick="deleteOnServerAndInTable(propertyConstraintsTableInfo, 'Property Constraint', 'propertyconstraints/');">Remove</button>
178                 <button class="rightbutton btn btn-xs btn-info" onclick="openAddPropertyConstraintDiag();">Add</button>
179                 <button class="rightbutton btn btn-xs btn-primary" onclick="openUpdatePropertyConstraintDiag();">Edit</button>
180                 <table id="propertyconstraintstable">
181                         <thead>
182                                 <tr>
183                                         <th>(internal id)</th>
184                                         <th>Service Template Property</th>
185                                         <th>Constraint Type</th>
186                                         <th>Constraint</th>
187                                 </tr>
188                         </thead>
189                         <tbody>
190                                 <tr>
191                                         <td>example</td>
192                                         <td>/demo</td>
193                                         <td>http://www.example.com/accessrestrictions</td>
194                                         <td>(not yet implemented)</td>
195                                 </tr>
196                         </tbody>
197                 </table>
198         </div>
199
200         <div class="tab-pane" id="requirements">
201                 <button class="rightbutton btn btn-xs btn-danger" onclick="deleteOnServerAndInTable(requirementsTableInfo, 'Requirement', 'boundarydefinitions/requirements/');">Remove</button>
202                 <button class="rightbutton btn btn-xs btn-info" onclick="openReqEditor(false);">Add</button>
203                 <button class="rightbutton btn btn-xs btn-primary" onclick="openReqEditor(true);">Edit</button>
204                 <table id="requirementstable">
205                         <thead>
206                                 <tr>
207                                         <th>(Id)</th><%-- of the boundary requirement, also used as the id of this element--%>
208                                         <th>Name</th>
209                                         <th>Reference</th>
210                                 </tr>
211                         </thead>
212                         <tbody>
213                                 <c:forEach var="item" items="${it.defs.requirements.requirement}">
214                                         <tr>
215                                                 <td>${wr:determineIdUsingHashCode(item)}</td>
216                                                 <td>${item.name}</td>
217                                                 <td>${item.ref.id}</td>
218                                         </tr>
219                                 </c:forEach>
220                         </tbody>
221                 </table>
222         </div>
223
224         <div class="tab-pane" id="capabilities">
225                 <%-- mirrored from requirements --%>
226                 <button class="rightbutton btn btn-xs btn-danger" onclick="deleteOnServerAndInTable(capabilitiesTableInfo, 'Capability', 'boundarydefinitions/capabilities/');">Remove</button>
227                 <button class="rightbutton btn btn-xs btn-info" onclick="openCapEditor(false);">Add</button>
228                 <button class="rightbutton btn btn-xs btn-primary" onclick="openCapEditor(true);">Edit</button>
229                 <table id="capabilitiestable">
230                         <thead>
231                                 <tr>
232                                         <th>(Id)</th><%-- of the boundary requirement, also used as the id of this element--%>
233                                         <th>Name</th>
234                                         <th>Reference</th>
235                                 </tr>
236                         </thead>
237                         <tbody>
238                                 <c:forEach var="item" items="${it.defs.capabilities.capability}">
239                                         <tr>
240                                                 <td>${wr:determineIdUsingHashCode(item)}</td>
241                                                 <td>${item.name}</td>
242                                                 <td>${item.ref.id}</td>
243                                         </tr>
244                                 </c:forEach>
245                         </tbody>
246                 </table>
247         </div>
248
249         <div class="tab-pane" id="policies">
250                 <pol:policies list="${it.defs.policies.policy}" repositoryURL="${it.repositoryURL}" />
251                 <br />
252                 <button class="btn btn-default btn-sm btn-primary" onclick="savePolicies();">Save</button>
253         </div>
254         <script>
255                 // work around for topology modeler's policy usage
256                 $(".addnewpolicy").show();
257
258                 // required for the policy addition dialog
259                 winery.repositoryURL = "${it.repositoryURL}";
260
261                 function savePolicies() {
262                         require(["winery-support-common", "XMLWriter"], function(wsc) {
263                                 var xmlw = new XMLWriter("utf-8");
264                                 xmlw.writeStartDocument();
265
266                                 wsc.writeCollectionDefinedByATextArea(xmlw,
267                                         $("div.policiesContainer").children("div.content").children("div.policy"),
268                                         "Policies");
269
270                                 xmlw.writeEndDocument();
271
272                                 var data = xmlw.flush();
273
274                                 $.ajax({
275                                         url: "boundarydefinitions/policies",
276                                         data: data,
277                                         type: "PUT",
278                                         contentType: "application/xml",
279                                 }).done(function (result) {
280                                         vShowSuccess("Sucessfully saved policies");
281                                 }).fail(function(jqXHR, textStatus, errorThrown) {
282                                         vShowAJAXError("Could not save policies", jqXHR, errorThrown);
283                                 });
284                         });
285                 }
286         </script>
287
288         <b:browseForX XLong="node template" XShort="NodeTemplate"/>
289         <script>
290         /**
291          * called from browseForX
292          */
293         function setNodeTemplateRef() {
294                 var newRef = $("#NodeTemplateReferenceField").val();
295                 $("#nodeTemplateRefForOperation").val(newRef);
296                 storeNewReference(newRef);
297                 updateTargetInterfaceAndOperation(true);
298                 $("#browseForNodeTemplateDiag").modal("hide");
299         }
300
301         function browseForNodeTemplate() {
302                 $("#NodeTemplateReferenceField").val($("#nodeTemplateRefForOperation").val());
303                 $("#browseForNodeTemplateDiag").modal("show");
304         }
305         </script>
306
307         <b:browseForX XLong="relationship template" XShort="RelationshipTemplate"/>
308         <script>
309         /**
310          * called from browseForX
311          */
312         function setRelationshipTemplateRef() {
313                 var newRef = $("#RelationshipTemplateReferenceField").val();
314                 $("#relationshipTemplateRefForOperation").val(newRef);
315                 storeNewReference(newRef);
316                 updateTargetInterfaceAndOperation(false);
317                 $("#browseForRelationshipTemplateDiag").modal("hide");
318         }
319
320         function browseForRelationshipTemplate() {
321                 $("#RelationshipTemplateReferenceField").val($("#relationshipTemplateRefForOperation").val());
322                 $("#browseForRelationshipTemplateDiag").modal("show");
323         }
324         </script>
325
326         <script>
327         function browseForPlan() {
328                 vShowError("not yet implemented.");
329         }
330         </script>
331
332         <div class="tab-pane" id="interfaces">
333                 <h4>Provided Interface and Operation</h4>
334
335                 <form class="form-horizontal">
336                         <div class="form-group">
337                                 <label for="interface" class="col-sm-1 control-label">Interface</label>
338                                 <div class="col-sm-8">
339                                         <input id="interface" class="form-control" placeholder="NCName or URI">
340                                 </div>
341                                 <button type="button" class="btn btn-danger btn-sm col-sm-1" onclick="deleteCurrentlySelectedInterface();">Delete</button>
342                         </div>
343                         <div class="form-group">
344                                 <label for="operation" class="col-sm-1 control-label">Operation</label>
345                                 <div class="col-sm-8">
346                                         <input id="operation" class="form-control" placeholder="NCName">
347                                 </div>
348                                 <button type="button" class="btn btn-danger btn-sm col-sm-1" onclick="deleteCurrentlySelectedOperation();">Delete</button>
349                         </div>
350                 </form>
351
352                 <h4>Target</h4>
353
354                 <form id="reftargettypeForm">
355                         <label>
356                                 <input id="nodeRadio" type="radio" name="reftargettype" value="node" checked="checked">
357                                 Node Template
358                         </label>
359                         <label>
360                                 <input id="relationshipRadio" type="radio" name="reftargettype" value="relationship">
361                                 Relationship Template
362                         </label>
363                         <label>
364                                 <input id="planRadio" type="radio" name="reftargettype" value="plan">
365                                 Plan
366                         </label>
367                 </form>
368
369                 <form class="form-horizontal">
370                         <div class="form-group" id="selectNodeTemplateDiv">
371                                 <label for="nodeTemplateRefForOperation" class="col-sm-1 control-label">Reference</label>
372                                 <div class="col-sm-8">
373                                         <input id="nodeTemplateRefForOperation" class="form-control">
374                                 </div>
375                                 <button type="button" class="btn btn-default btn-sm col-sm-1" onclick="browseForNodeTemplate();">Browse</button>
376                         </div>
377
378                         <div class="form-group" id="selectRelationshipTemplateDiv" style="display:none;">
379                                 <label for="relationshipTemplateRefForOperation" class="col-sm-1 control-label">Reference</label>
380                                 <div class="col-sm-8">
381                                         <input id="relationshipTemplateRefForOperation" class="form-control">
382                                 </div>
383                                 <button type="button" class="btn btn-default btn-sm col-sm-1" onclick="browseForRelationshipTemplate();">Browse</button>
384                         </div>
385
386                         <div class="form-group" id="selectPlanDiv" style="display:none;">
387                                 <label for="planRefForOperation" class="col-sm-1 control-label">Reference</label>
388                                 <div class="col-sm-8">
389                                         <c:choose>
390                                                 <c:when test="${empty it.listOfAllPlans}">
391                                                         <p>No plans available>
392                                                 </c:when>
393                                                 <c:otherwise>
394                                                         <a id="planRefForOperation" href="#"></a>
395                                                 </c:otherwise>
396                                         </c:choose>
397                                 </div>
398                         </div>
399                 </form>
400
401                 <h4>Target Interface and Operation</h4>
402                 <form class="form-horizontal">
403                         <div class="form-group" id="selectInterfaceNameDiv">
404                                 <label for="TargetInterface" class="col-sm-1 control-label">Interface</label>
405                                 <div class="col-sm-8">
406                                         <input id="TargetInterface" class="form-control">
407                                 </div>
408                         </div>
409
410                         <div class="form-group" id="selectOperationNameDiv">
411                                 <label for="TargetOperation" class="col-sm-1 control-label">Operation</label>
412                                 <div class="col-sm-8">
413                                         <input id="TargetOperation" class="form-control">
414                                 </div>
415                         </div>
416                 </form>
417
418                 <div id="notApplicableDiv" style="display:none;">
419                         <p>not applicable in the case of plans</p>
420                 </div>
421
422         </div>
423
424         <script>
425         // initialize interface selection
426         require(["winery-support-common"], function(wsc) {
427                 wsc.fetchSelect2DataAndInitSelect2("interface", "boundarydefinitions/interfaces/?select2", function() {
428                         $("#interface").on("change", function() {
429                                 updateOperationsField();
430                         });
431                         if ($("#interface").select2("val") != "") {
432                                 updateOperationsField();
433                         }
434                 }, true);
435         });
436
437         function getInterfacesAndInterfaceURLs() {
438                 var iface = $("#interface").select2("val");
439                 iface = encodeID(iface);
440
441                 var ifacesURL = "boundarydefinitions/interfaces/";
442                 var ifaceURL = ifacesURL + iface + "/";
443                 return {
444                         ifacesURL: ifacesURL,
445                         ifaceURL: ifaceURL
446                 }
447         }
448
449         function getOperationsAndOperationURLs() {
450                 var ifaceURL = getInterfacesAndInterfaceURLs().ifaceURL;
451                 var operation = $("#operation").select2("val");
452                 operation = encodeID(operation);
453
454                 var operationsURL = ifaceURL + "exportedoperations/";
455                 var operationURL = operationsURL + operation + "/";
456                 return {
457                         operationsURL: operationsURL,
458                         operationURL: operationURL
459                 }
460         }
461
462         /**
463          * Updates the field of the exported operation
464          */
465         function updateOperationsField() {
466                 var iface = $("#interface").select2("val");
467                 var urls = getInterfacesAndInterfaceURLs();
468
469                 $.ajax({
470                         url: urls.ifaceURL,
471                         type: "HEAD",
472                         async: false,
473                         error: function(jqXHR, textStatus, errorThrown) {
474                                 if (jqXHR.status == 404) {
475                                         // everything allright -> user entered a new interface
476                                         $.ajax({
477                                                 url: urls.ifacesURL,
478                                                 async: false,
479                                                 type: "POST",
480                                                 data: JSON.stringify({name: iface}),
481                                                 contentType: "application/json"
482                                         }).done(function (result) {
483                                                 vShowSuccess("Sucessfully created interface");
484                                         }).fail(function(jqXHR, textStatus, errorThrown) {
485                                                 vShowAJAXError("Could not create interface", jqXHR, errorThrown);
486                                         });
487                                 } else {
488                                         vShowAJAXError("Could not check for interface existance", jqXHR, errorThrown);
489                                 }
490                         }
491                 });
492
493                 var url = urls.ifaceURL + "exportedoperations/?select2";
494                 require("winery-support-common").fetchSelect2DataAndInitSelect2("operation", url, function(){
495                         updateTarget();
496                 }, true);
497         }
498
499         $("#operation").on("change", function() {
500                 var operation = $("#operation").select2("val");
501                 var urls = getOperationsAndOperationURLs();
502                 $.ajax({
503                         url: urls.operationURL,
504                         type: "HEAD",
505                         async: false,
506                         error: function(jqXHR, textStatus, errorThrown) {
507                                 if (jqXHR.status == 404) {
508                                         // everything allright -> user entered a new operation
509                                         $.ajax({
510                                                 url: urls.operationsURL,
511                                                 async: false,
512                                                 type: "POST",
513                                                 data: JSON.stringify({name: operation}),
514                                                 contentType: "application/json"
515                                         }).done(function (result) {
516                                                 vShowSuccess("Sucessfully created operation");
517                                         }).fail(function(jqXHR, textStatus, errorThrown) {
518                                                 vShowAJAXError("Could not create interface", jqXHR, errorThrown);
519                                         });
520                                 } else {
521                                         vShowAJAXError("Could not check for interface operation", jqXHR, errorThrown);
522                                 }
523                         }
524                 });
525
526                 updateTarget();
527         })
528
529         /**
530          * Updates the content at "Target": Reference and Target Interface/Operation
531          */
532         function updateTarget() {
533                 var operation = $("#operation").select2("val");
534                 if (operation != "") {
535                         var urls = getOperationsAndOperationURLs();
536                         // At the beginning of the usage, there is no operation selected
537                         // Just fill the data if an operation is chosen
538                         var url = urls.operationURL;
539
540                         // store URL for later use - this avoids global JavaScript variables
541                         $("#operation").data("url", url);
542
543                         $.ajax({
544                                 url: url,
545                                 dataType: "json"
546                         }).done(function (data) {
547                                 if ((data.type == "NodeOperation") || (data.type == "RelationshipOperation")) {
548                                         if (data.type == "NodeOperation") {
549                                                 $("#nodeRadio").prop("checked", true);
550                                                 $("#nodeTemplateRefForOperation").val(data.ref);
551                                                 updateTargetInterfaceAndOperation(true, data.interfacename, data.operationname);
552                                         } else {
553                                                 $("#relationshipRadio").prop("checked", true);
554                                                 $("#relationshipTemplateRefForOperation").val(data.ref);
555                                                 updateTargetInterfaceAndOperation(false, data.interfacename, data.operationname);
556                                         }
557                                 } else if (data.type == "Plan") {
558                                         $("#planRadio").prop("checked", true);
559                                         $("#planRefForOperation").editable("setValue", data.ref);
560                                 } else if (data.type == null) {
561                                         //  nothing set yet; set node as type
562                                         putType("NodeOperation");
563                                         $("#nodeRadio").prop("checked", true);
564                                         // no reference is set if no type is set -> clear field
565                                         $("#nodeTemplateRefForOperation").val("");
566                                 } else {
567                                         vShowError("Unexpected type '" + data.type + "'.");
568                                         return;
569                                 }
570                                 adaptVisibilityOfDivsAccordingToReferenceType();
571                         }).fail(function(jqXHR, textStatus, errorThrown) {
572                                 vShowAJAXError("Could not fetch data of exported operation from " + url, jqXHR, errorThrown);
573                         });
574                 }
575
576         }
577
578         function adaptVisibilityOfDivsAccordingToReferenceType() {
579                 var checked = $('input[name=reftargettype]:checked').val();
580                 if (checked == "node") {
581                         $("#selectNodeTemplateDiv").show();
582                         $("#selectRelationshipTemplateDiv").hide();
583                         $("#selectPlanDiv").hide();
584                         $("#selectInterfaceNameDiv").show();
585                         $("#selectOperationNameDiv").show();
586                         $("#notApplicableDiv").hide();
587                 } else if (checked == "relationship") {
588                         $("#selectNodeTemplateDiv").hide();
589                         $("#selectRelationshipTemplateDiv").show();
590                         $("#selectPlanDiv").hide();
591                         $("#selectInterfaceNameDiv").show();
592                         $("#selectOperationNameDiv").show();
593                         $("#notApplicableDiv").hide();
594                 } else if (checked == "plan") {
595                         $("#selectNodeTemplateDiv").hide();
596                         $("#selectRelationshipTemplateDiv").hide();
597                         $("#selectPlanDiv").show();
598                         $("#selectInterfaceNameDiv").hide();
599                         $("#selectOperationNameDiv").hide();
600                         $("#notApplicableDiv").show();
601                 } else {
602                         vShowError("UI in inconsistent state: wrong branch in adaptVisibilityOfDivsAccordingToReferenceType");
603                 }
604         }
605         </script>
606
607         <div class="tab-pane" id="xml">
608                 <o:orioneditorarea areaid="XML" url="boundarydefinitions/" reloadAfterSuccess="true">${it.boundaryDefinitionsAsXMLStringEncoded}</o:orioneditorarea>
609         </div>
610 </div>
611 </div>
612
613 <script>
614 $('#myTab a').click(function (e) {
615         e.preventDefault();
616         $(this).tab('show');
617 });
618
619 function openPropertyConstraintEditor() {
620         vShowError("not yet implemented");
621         // TODO: fill diag with the values of the table
622         // $('#addPropertyConstraintDiag').modal('show');
623 }
624
625
626 var propertyConstraintsTableInfo = {
627         id: '#propertyconstraintstable'
628 };
629 var requirementsTableInfo = {
630                 id: '#requirementstable'
631 };
632 var capabilitiesTableInfo = {
633                 id: '#capabilitiestable'
634 };
635 var interfacesTableInfo = {
636                 id: '#interfacestable'
637 };
638 var propertyMappingsTableInfo = {
639                 id: '#propertyMappingsTable'
640         };
641
642 require(["winery-support"], function(ws) {
643         var firstColumnIsHidden = {
644                         aoColumnDefs: [
645                                                 { "bSearchable": false, "bVisible": false, "aTargets": [ 0 ] }
646                         ]
647                 };
648
649         ws.initTable(propertyConstraintsTableInfo, firstColumnIsHidden);
650         ws.initTable(requirementsTableInfo, firstColumnIsHidden);
651         ws.initTable(capabilitiesTableInfo, firstColumnIsHidden);
652
653         ws.initTable(interfacesTableInfo);
654         ws.initTable(propertyMappingsTableInfo);
655 });
656
657 <%-- === BEGIN: Property Constraints === --%>
658
659 function openUpdatePropertyConstraintDiag() {
660         if (propertyConstraintsTableInfo.selectedRow) {
661                 require(["winery-support"], function(ws) {
662                         if (ws.isEmptyTable(propertyConstraintsTableInfo)) {
663                                 vShowError("No property constraints available");
664                                 return;
665                         }
666
667                         $("#addPropertyConstraint").hide();
668                         $("#updatePropertyConstraint").show();
669
670                         // put value in fields
671                         var children = $(propertyMappingsTableInfo.selectedRow).children("td");
672                         $("#serviceTemplatePropertyRefForConstraint").val($(children[1]).text());
673                         $("#constraintType").val($(children[2]).text());
674                         // TODO: value of the constraint
675
676                         $('#propertyConstraintDiag').modal('show');
677
678                         vShowError("Not yet implemented.");
679                 });
680         } else {
681                 vShowError("No property constraint selected");
682         }
683 }
684
685 function openAddPropertyConstraintDiag() {
686         $("#addPropertyConstraint").show();
687         $("#updatePropertyConstraint").hide();
688
689         // reset all fields
690         $("#serviceTemplatePropertyRefForConstraint").val("");
691         // TODO: value of the constraint
692
693         $('#propertyConstraintDiag').modal('show');
694
695         vShowError("Not yet implemented.");
696 }
697
698 <%-- === END: Property Constraints === --%>
699
700
701 <%-- === BEGIN: Property Mapping === --%>
702
703 function openUpdatePropertyMappingDiag() {
704         if (propertyMappingsTableInfo.selectedRow) {
705                 require(["winery-support"], function(ws) {
706                         if (ws.isEmptyTable(propertyMappingsTableInfo)) {
707                                 vShowError("No property mappings available");
708                                 return;
709                         }
710
711                         $("#addPropertyMapping").hide();
712                         $("#updatePropertyMapping").show();
713
714                         // put value in fields
715                         var children = $(propertyMappingsTableInfo.selectedRow).children("td");
716                         $("#serviceTemplatePropertyRef").val($(children[0]).text());
717                         $("#targetObjectRef").val($(children[1]).text());
718                         $("#targetPropertyRef").val($(children[2]).text());
719
720                         $('#propertyMappingDiag').modal('show');
721                 });
722         } else {
723                 vShowError("No property mapping selected");
724         }
725 }
726
727 function openAddPropertyMappingDiag() {
728         $("#addPropertyMapping").show();
729         $("#updatePropertyMapping").hide();
730
731         // reset all fields
732         $("#serviceTemplatePropertyRef").val("");
733         $("#targetObjectRef").val("");
734         $("#targetPropertyRef").val("");
735
736         $('#propertyMappingDiag').modal('show');
737 }
738
739 function addOrUpdatePropertyMapping(add) {
740         var serviceTemplatePropertyRef = $("#serviceTemplatePropertyRef").val();
741         var targetObjectRef = $("#targetObjectRef").val();
742         var targetPropertyRef = $("#targetPropertyRef").val();
743
744         $.ajax({
745                 url: "boundarydefinitions/propertymappings",
746                 type: "POST",
747                 async: false,
748                 data: {
749                         serviceTemplatePropertyRef: serviceTemplatePropertyRef,
750                         targetObjectRef: targetObjectRef,
751                         targetPropertyRef: targetPropertyRef
752                 },
753                 error: function(jqXHR, textStatus, errorThrown) {
754                         vShowAJAXError("Could not POST property mapping", jqXHR, errorThrown);
755                 },
756                 success: function(data, textSTatus, jqXHR) {
757                         // put value from fields into table
758                         if (add) {
759                                 propertyMappingsTableInfo.table.fnAddData([serviceTemplatePropertyRef, targetObjectRef, targetPropertyRef]);
760                         } else {
761                                 var children = $(propertyMappingsTableInfo.selectedRow).children("td");
762                                 $(children[0]).text(serviceTemplatePropertyRef);
763                                 $(children[1]).text(targetObjectRef);
764                                 $(children[2]).text(targetPropertyRef);
765                         }
766
767                         $('#propertyMappingDiag').modal('hide');
768
769                         vShowSuccess("Successfully posted property mapping.");
770                 }
771         });
772 }
773
774 function addPropertyMapping() {
775         addOrUpdatePropertyMapping(true);
776 }
777
778 function updatePropertyMapping() {
779         addOrUpdatePropertyMapping(false);
780 }
781
782 <%-- === END: Property Mapping === --%>
783
784
785 //window.addEventListener('message', function(event){var v = document.getElementById('%s');if(v){v=v.firstChild; if(v && v.contentWindow === event.source){%s}}})
786 window.addEventListener('message', function(event) {
787         if (event.data) {
788                 if (event.data.targetObjectRef) {
789                         // current API expects both fields
790                         $(".newObjectRef").val(event.data.targetObjectRef);
791                         $("#newObjectPropertyRef").val(event.data.targetPropertyRef);
792                 } else if (event.data.reqRef) {
793                         $("#ReqReferenceField").val(event.data.reqRef);
794                 } else if (event.data.capRef) {
795                         $("#CapReferenceField").val(event.data.capRef);
796                 } else if (event.data.targetRelationshipTemplateRef) {
797                         $("#RelationshipTemplateReferenceField").val(event.data.targetRelationshipTemplateRef);
798                 }
799         }
800 });
801
802 function storeNewReference(ref) {
803         var url = $("#operation").data("url") + "/ref";
804         $.ajax({
805                 url: url,
806                 data: ref,
807                 type: "PUT",
808                 contentType: "text/plain",
809         }).done(function (result) {
810                 vShowSuccess("Sucessfully saved reference");
811         }).fail(function(jqXHR, textStatus, errorThrown) {
812                 vShowAJAXError("Could not set reference", jqXHR, errorThrown);
813         });
814 }
815
816 <c:if test="${not empty it.listOfAllPlans}">
817 $("#planRefForOperation").editable({
818         type: "select",
819         source: [
820                         <c:forEach var="item" items="${it.listOfAllPlans}">
821                         {value: "${item.id}",
822                           text: "${item.text}"},
823                         </c:forEach>
824                 ]
825 }).on("save", function(e, params) {
826         var newRef = params.newValue;
827         storeNewReference(newRef)
828 });
829 </c:if>
830
831 function putType(type) {
832         var url = $("#operation").data("url") + "/type";
833         $.ajax({
834                 url: url,
835                 data: type,
836                 type: "PUT",
837                 contentType: "text/plain",
838         }).done(function (result) {
839                 vShowSuccess("Sucessfully changed reference type");
840                 adaptVisibilityOfDivsAccordingToReferenceType();
841         }).fail(function(jqXHR, textStatus, errorThrown) {
842                 vShowAJAXError("Could not set new reference type", jqXHR, errorThrown);
843         });
844 }
845
846 function getInterfaceDataFromURL(ifaceURL) {
847         var select2data = null;
848         $.ajax({
849                 url: ifaceURL + "?select2",
850                 async: false,
851                 type: "GET",
852                 dataType: "json",
853                 success: function (data) {
854                         select2data = data;
855                 },
856                 error: function(jqXHR, textStatus, errorThrown) {
857                         vShowAJAXError("Could not get interface data", jqXHR, errorThrown);
858                 }
859         });
860         return select2data;
861 }
862
863 function getDataForUpdateTargetOperation(url, showError) {
864         var select2data = null;
865         $.ajax({
866                 url: url + "?select2",
867                 async: false,
868                 type: "GET",
869                 dataType: "json",
870                 success: function (data) {
871                         select2data = data;
872                 },
873                 error: function(jqXHR, textStatus, errorThrown) {
874                         if (showError) {
875                                 vShowAJAXError("Could not get operation data", jqXHR, errorThrown);
876                         }
877                 }
878         });
879         return select2data;
880 }
881
882 function updateTargetOperation(operationNameToSelect) {
883         var ifaceURL = $("#TargetInterface").data("url2");
884         var select2data = null;
885         var operationsURL;
886
887         // we don't store the interface-URL at #TargetInterface, but do a quick hack here
888         if (ifaceURL != null) {
889                 operationsURL = ifaceURL + "/" + encodeID($("#TargetInterface").val()) + "/operations/";
890                 select2data = getDataForUpdateTargetOperation(operationsURL, false);
891         }
892
893         // either only one URL or nothing found at second URL --> try first URL
894         if (select2data == null) {
895                 ifaceURL = $("#TargetInterface").data("url1");
896                 operationsURL = ifaceURL + "/" + encodeID($("#TargetInterface").val()) + "/operations/";
897                 select2data = getDataForUpdateTargetOperation(operationsURL, true);
898         }
899
900         if (select2data != null) {
901                 $("#TargetOperation").select2({
902                         data:select2data
903                 });
904                 var valueToSelect = null;
905                 if ((typeof operationNameToSelect !== "undefined") && (operationNameToSelect != null)) {
906                         valueToSelect = operationNameToSelect;
907                 } else {
908                         // called without existing data --> insert pseudo data and store it at the backend to ensure consistency
909                         if (select2data.length > 0) {
910                                 valueToSelect = select2data[0].id;
911                                 storeTargetOperation(valueToSelect);
912                         }
913                 }
914                 if (valueToSelect != null) {
915                         $("#TargetOperation").select2('val', valueToSelect);
916                 }
917         }
918
919 }
920
921 function updateTargetInterfaceAndOperationFromInterfaceURL(ifaceURL, interfaceNameToSelect, operationNameToSelect) {
922         var select2data;
923         if (typeof ifaceURL === "string") {
924                 select2data = getInterfaceDataFromURL(ifaceURL);
925                 $("#TargetInterface").data("url1", ifaceURL);
926                 $("#TargetInterface").data("url2", null);
927         } else {
928                 // TODO: instead of hacking with two urls (especially at other places in the code), we should prefix the entries with S| at the source interface and T| at the target interface
929                 select2data = getInterfaceDataFromURL(ifaceURL[0]);
930                 var select2data2 =  getInterfaceDataFromURL(ifaceURL[1]);
931                 $.merge(select2data, select2data2);
932                 $("#TargetInterface").data("url1", ifaceURL[0]);
933                 $("#TargetInterface").data("url2", ifaceURL[1]);
934         }
935         $("#TargetInterface").select2({data:select2data});
936
937         var valueToSelect = null;
938         if ((typeof interfaceNameToSelect !== "undefined") && (interfaceNameToSelect != null)) {
939                 valueToSelect = interfaceNameToSelect;
940         } else {
941                 // called without existing data --> insert pseudo data and store it at the backend to ensure consistency
942                 if (select2data.length > 0) {
943                         valueToSelect = select2data[0].id;
944                         storeTargetInterface(valueToSelect);
945                 }
946         }
947         if (valueToSelect != null) {
948                 $("#TargetInterface").select2('val', valueToSelect);
949         }
950
951         updateTargetOperation(operationNameToSelect);
952 }
953
954 function updateTargetInterfaceAndOperation(isNodeTemplate, interfaceNameToSelect, operationNameToSelect) {
955         var url = "topologytemplate/";
956         url = url + (isNodeTemplate ? "nodetemplates" : "relationshiptemplates" + "/");
957         var templateId = isNodeTemplate ? $("#nodeTemplateRefForOperation").val() : $("#relationshipTemplateRefForOperation").val();
958         if (templateId == "") {
959                 // if no template is provided, we just return
960                 return;
961         }
962         url = url + "/" + templateId + "/type";
963         $.ajax({
964                 url: url,
965                 type: "GET",
966                 dataType: "text"
967         }).done(function (typeQName) {
968                 require(["winery-support-common"], function(wsc) {
969                         var urlDetermination = isNodeTemplate ? wsc.makeNodeTypeURLFromQName : wsc.makeRelationshipTypeURLFromQName;
970                         var typeURL = urlDetermination("${it.repositoryURL}", typeQName)
971                         if (isNodeTemplate) {
972                                 updateTargetInterfaceAndOperationFromInterfaceURL(typeURL + "/interfaces", interfaceNameToSelect, operationNameToSelect);
973                         } else {
974                                 updateTargetInterfaceAndOperationFromInterfaceURL([typeURL + "/sourceinterfaces/", typeURL + "/targetinterfaces/"], interfaceNameToSelect, operationNameToSelect);
975                         }
976                 });
977         }).fail(function(jqXHR, textStatus, errorThrown) {
978                 vShowAJAXError("Could not get type of node / relationship", jqXHR, errorThrown);
979         });
980
981 }
982
983 $("#nodeRadio").on("change", function() {
984         putType("NodeOperation");
985         updateTargetInterfaceAndOperation(true);
986 });
987 $("#relationshipRadio").on("change", function() {
988         putType("RelationshipOperation");
989         updateTargetInterfaceAndOperation(false);
990 });
991 $("#planRadio").on("change", function() {
992         putType("Plan");
993 });
994
995 $("#nodeTemplateRefForOperation").on("change", function() {
996         updateTargetInterfaceAndOperation(true);
997 });
998
999 $("#relationshipTemplateRefForOperation").on("change", function() {
1000         updateTargetInterfaceAndOperation(false);
1001 });
1002
1003 function storeTargetInterface(val) {
1004         val = val || $("#TargetInterface").select2("val");
1005         var url = $("#operation").data("url") + "interfacename";
1006          // when selecting a new operation, both targetinterface and targetoperation are updated; this leads to race conditions at the backend and one chang would be lost. Therefore, we do the calls synchronously
1007         $.ajax({
1008                 url: url,
1009                 data: val,
1010                 type: "PUT",
1011                 contentType: "text/plain",
1012                 async:false
1013         }).done(function (result) {
1014                 vShowSuccess("Sucessfully saved interface name");
1015         }).fail(function(jqXHR, textStatus, errorThrown) {
1016                 vShowAJAXError("Could not set interface name", jqXHR, errorThrown);
1017         });
1018 }
1019
1020 function storeTargetOperation(val) {
1021         val = val || $("#TargetOperation").select2("val");
1022         var url = $("#operation").data("url") + "operationname";
1023         // when selecting a new operation, both targetinterface and targetoperation are updated; this leads to race conditions at the backend and one chang would be lost. Therefore, we do the calls synchronously
1024         $.ajax({
1025                 url: url,
1026                 data: val,
1027                 type: "PUT",
1028                 contentType: "text/plain",
1029                 async:false
1030         }).done(function (result) {
1031                 vShowSuccess("Sucessfully saved operation name");
1032         }).fail(function(jqXHR, textStatus, errorThrown) {
1033                 vShowAJAXError("Could not set operation name", jqXHR, errorThrown);
1034         });
1035 }
1036
1037 $("#TargetInterface").on("change", function() {
1038         storeTargetInterface();
1039         updateTargetOperation();
1040 });
1041
1042 $("#TargetOperation").on("change", function() {
1043         storeTargetOperation();
1044 });
1045
1046 function deleteCurrentlySelectedInterface() {
1047         vConfirmYesNo("Do you really want to delete this interface?", function() {
1048                 var url = getInterfacesAndInterfaceURLs().ifaceURL;
1049                 $.ajax({
1050                         url: url,
1051                         type: "DELETE"
1052                 }).done(function () {
1053                         require(["winery-support-common"], function (wsc) {
1054                                 wsc.removeItemFromSelect2Field($("#interface"), $("#interface").select2("data").id);
1055                                 vShowSuccess("Successfully deleted interface");
1056                         });
1057                 }).fail(function(jqXHR, textStatus, errorThrown) {
1058                         vShowAJAXError("Could not delete interface", jqXHR, errorThrown);
1059                 });
1060         });
1061 }
1062
1063 function deleteCurrentlySelectedOperation() {
1064         vConfirmYesNo("Do you really want to delete this operation?", function() {
1065                 var url = getOperationsAndOperationURLs().operationURL;
1066                 $.ajax({
1067                         url: url,
1068                         type: "DELETE"
1069                 }).done(function () {
1070                         require(["winery-support-common"], function (wsc) {
1071                                 wsc.removeItemFromSelect2Field($("#operation"), $("#operation").select2("data").id);
1072                                 vShowSuccess("Successfully deleted operation");
1073                         });
1074                 }).fail(function(jqXHR, textStatus, errorThrown) {
1075                         vShowAJAXError("Could not delete operation", jqXHR, errorThrown);
1076                 });
1077         });
1078 }
1079
1080 </script>