From fa49e78cc199526a9e33b59c5194f8e3bf0f0952 Mon Sep 17 00:00:00 2001 From: huangjian Date: Wed, 31 Aug 2016 16:47:33 +0800 Subject: Add winery source code Change-Id: I1c5088121d79b71098c3cba1996c6f784737532e Issue-id: TOSCA-49 Signed-off-by: huangjian --- winery/org.eclipse.winery.topologymodeler/.bowerrc | 3 + .../.gitattributes | 1 + .../org.eclipse.winery.topologymodeler/.gitignore | 23 + .../org.eclipse.winery.topologymodeler/README.md | 44 + .../org.eclipse.winery.topologymodeler/about.html | 604 + .../about_files/Apache-LICENSE-2.0.txt | 202 + .../about_files/CDDL-v1.1.txt | 129 + .../about_files/LICENSE-KeyboardJS.txt | 25 + .../about_files/LICENSE-XMLWriter.txt | 27 + .../about_files/LICENSE-biltong.txt | 22 + .../about_files/LICENSE-boostrap.txt | 21 + .../about_files/LICENSE-jQuery-UI.txt | 26 + .../about_files/LICENSE-jQuery.txt | 21 + .../about_files/LICENSE-jsPlumb-MIT.txt | 20 + .../about_files/LICENSE-logback.txt | 15 + .../about_files/LICENSE-requirejs.txt | 58 + .../about_files/LICENSE-slf4j-api.txt | 21 + .../about_files/LICENSE-x-editable.txt | 22 + .../about_files/MPL-v1.1.txt | 470 + .../org.eclipse.winery.topologymodeler/bower.json | 44 + .../package.json | 22 + winery/org.eclipse.winery.topologymodeler/pom.xml | 193 + .../sonar-project.js.properties | 13 + .../sonar-project.web.properties | 13 + .../eclipse/winery/topologymodeler/WineryUtil.java | 87 + .../analyzer/DeferredAnalyzer.java | 60 + .../analyzer/PlaceHolderAnalyzer.java | 52 + .../analyzer/RequirementAnalyzer.java | 117 + .../topologycompleter/analyzer/TOSCAAnalyzer.java | 146 + .../topologycompleter/analyzer/package-info.java | 17 + .../addons/topologycompleter/helper/Constants.java | 89 + .../topologycompleter/helper/JAXBHelper.java | 374 + .../helper/NodeTemplateConnector.java | 86 + .../topologycompleter/helper/RESTHelper.java | 97 + .../addons/topologycompleter/helper/Utils.java | 127 + .../topologycompleter/helper/package-info.java | 17 + .../addons/topologycompleter/package-info.java | 16 + .../placeholderhandling/PlaceHolderHandler.java | 74 + .../topologycompletion/CompletionInterface.java | 257 + .../topologycompletion/CompletionManager.java | 358 + .../completer/DeferredCompleter.java | 218 + .../completer/PlaceHolderCompleter.java | 188 + .../completer/RequirementCompleter.java | 108 + .../completer/StepByStepCompleter.java | 203 + .../topologycompletion/completer/package-info.java | 17 + .../topologycompletion/package-info.java | 17 + .../resources/TopologyCompletionResource.java | 136 + .../topologymodeler/resources/package-info.java | 4 + .../src/main/resources/.gitignore | 1 + .../main/webapp/3rdparty/jquery-ui/js/jquery-ui.js | 14987 +++++++++++++++++++ .../webapp/3rdparty/jquery-ui/js/jquery-ui.min.js | 12 + .../src/main/webapp/WEB-INF/common-functions.tld | 70 + .../src/main/webapp/WEB-INF/functions.tld | 36 + .../src/main/webapp/WEB-INF/tags/about.tag | 58 + .../webapp/WEB-INF/tags/common/QNameChooser.tag | 46 + .../WEB-INF/tags/common/artifactcreationdialog.tag | 443 + .../tags/common/artifacttemplateselection.tag | 41 + .../webapp/WEB-INF/tags/common/id_name_type.tag | 36 + .../tags/common/jquery-file-upload-full.tag | 181 + .../tags/common/orioneditor/orioneditorarea.tag | 110 + .../WEB-INF/tags/common/policies/policies.tag | 54 + .../WEB-INF/tags/common/policies/policydiag.tag | 205 + .../WEB-INF/tags/common/spinnerwithinphty.tag | 92 + .../WEB-INF/tags/common/templates/CSSForTypes.tag | 50 + .../defineCreateConnectorEndpointsFunction.tag | 42 + .../nodetemplates/nodeTemplateRenderer.tag | 266 + .../templates/nodetemplates/reqscaps/caps.tag | 33 + .../templates/nodetemplates/reqscaps/reqs.tag | 33 + .../nodetemplates/reqscaps/reqsorcaps.tag | 63 + .../WEB-INF/tags/common/templates/properties.tag | 103 + .../tags/common/templates/propertiesBasic.tag | 112 + ...isterConnectionTypesAndConnectNodeTemplates.tag | 205 + .../tags/common/templates/toggleButtons.tag | 131 + .../topologycompletion/nodeTemplateSelector.tag | 230 + .../relationshipTemplateSelector.tag | 158 + .../common/topologycompletion/selectionDialogs.tag | 175 + .../topologyTemplateSelector.tag | 246 + .../src/main/webapp/WEB-INF/tags/idInput.tag | 43 + .../main/webapp/WEB-INF/tags/namespaceChooser.tag | 52 + .../src/main/webapp/WEB-INF/tags/palette.tag | 207 + .../nodetemplates/propertiesOfOneNodeTemplate.tag | 147 + .../nodetemplates/reqscaps/addorupdatereqorcap.tag | 248 + .../propertiesOfOneRelationshipTemplate.tag | 179 + .../src/main/webapp/WEB-INF/web.xml | 21 + .../src/main/webapp/css/palette.css | 111 + .../src/main/webapp/css/propertiesview.css | 76 + .../src/main/webapp/css/topologymodeler.css | 286 + .../main/webapp/css/topologytemplatecontent.css | 421 + .../src/main/webapp/css/winery-common.css | 138 + .../src/main/webapp/favicon.png | Bin 0 -> 674 bytes .../src/main/webapp/images/xml.png | Bin 0 -> 475 bytes .../src/main/webapp/index.jsp | 1490 ++ .../main/webapp/js/artifacttemplateselection.js | 82 + .../src/main/webapp/js/jquery.fileupload-audio.js | 13 + .../src/main/webapp/js/jquery.fileupload-image.js | 13 + .../main/webapp/js/jquery.fileupload-validate.js | 13 + .../src/main/webapp/js/jquery.fileupload-video.js | 13 + .../webapp/js/winery-common-topologyrendering.js | 143 + .../src/main/webapp/js/winery-common.js | 265 + .../src/main/webapp/js/winery-sugiyamaLayouter.js | 634 + .../src/main/webapp/js/winery-support-common.js | 330 + .../main/webapp/js/winery-topologycompletion.js | 178 + .../main/webapp/js/winery-topologymodeler-AMD.js | 234 + .../src/main/webapp/js/winery-topologymodeler.js | 308 + .../src/main/webapp/jsp/shared/README.md | 1 + .../src/main/webapp/jsp/shared/dialogs.jsp | 83 + .../jsp/topologyCompletion/selectionHandler.jsp | 25 + .../jsp/topologyCompletion/topologyCompletion.jsp | 175 + .../jsp/topologyCompletion/topologySaver.jsp | 50 + .../src/main/webapp/logback.xml | 15 + .../src/test/java/.gitkeep | 0 111 files changed, 29117 insertions(+) create mode 100644 winery/org.eclipse.winery.topologymodeler/.bowerrc create mode 100644 winery/org.eclipse.winery.topologymodeler/.gitattributes create mode 100644 winery/org.eclipse.winery.topologymodeler/.gitignore create mode 100644 winery/org.eclipse.winery.topologymodeler/README.md create mode 100644 winery/org.eclipse.winery.topologymodeler/about.html create mode 100644 winery/org.eclipse.winery.topologymodeler/about_files/Apache-LICENSE-2.0.txt create mode 100644 winery/org.eclipse.winery.topologymodeler/about_files/CDDL-v1.1.txt create mode 100644 winery/org.eclipse.winery.topologymodeler/about_files/LICENSE-KeyboardJS.txt create mode 100644 winery/org.eclipse.winery.topologymodeler/about_files/LICENSE-XMLWriter.txt create mode 100644 winery/org.eclipse.winery.topologymodeler/about_files/LICENSE-biltong.txt create mode 100644 winery/org.eclipse.winery.topologymodeler/about_files/LICENSE-boostrap.txt create mode 100644 winery/org.eclipse.winery.topologymodeler/about_files/LICENSE-jQuery-UI.txt create mode 100644 winery/org.eclipse.winery.topologymodeler/about_files/LICENSE-jQuery.txt create mode 100644 winery/org.eclipse.winery.topologymodeler/about_files/LICENSE-jsPlumb-MIT.txt create mode 100644 winery/org.eclipse.winery.topologymodeler/about_files/LICENSE-logback.txt create mode 100644 winery/org.eclipse.winery.topologymodeler/about_files/LICENSE-requirejs.txt create mode 100644 winery/org.eclipse.winery.topologymodeler/about_files/LICENSE-slf4j-api.txt create mode 100644 winery/org.eclipse.winery.topologymodeler/about_files/LICENSE-x-editable.txt create mode 100644 winery/org.eclipse.winery.topologymodeler/about_files/MPL-v1.1.txt create mode 100644 winery/org.eclipse.winery.topologymodeler/bower.json create mode 100644 winery/org.eclipse.winery.topologymodeler/package.json create mode 100644 winery/org.eclipse.winery.topologymodeler/pom.xml create mode 100644 winery/org.eclipse.winery.topologymodeler/sonar-project.js.properties create mode 100644 winery/org.eclipse.winery.topologymodeler/sonar-project.web.properties create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/WineryUtil.java create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/analyzer/DeferredAnalyzer.java create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/analyzer/PlaceHolderAnalyzer.java create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/analyzer/RequirementAnalyzer.java create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/analyzer/TOSCAAnalyzer.java create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/analyzer/package-info.java create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/helper/Constants.java create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/helper/JAXBHelper.java create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/helper/NodeTemplateConnector.java create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/helper/RESTHelper.java create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/helper/Utils.java create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/helper/package-info.java create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/package-info.java create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/placeholderhandling/PlaceHolderHandler.java create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/topologycompletion/CompletionInterface.java create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/topologycompletion/CompletionManager.java create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/topologycompletion/completer/DeferredCompleter.java create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/topologycompletion/completer/PlaceHolderCompleter.java create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/topologycompletion/completer/RequirementCompleter.java create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/topologycompletion/completer/StepByStepCompleter.java create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/topologycompletion/completer/package-info.java create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/topologycompletion/package-info.java create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/resources/TopologyCompletionResource.java create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/resources/package-info.java create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/resources/.gitignore create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/webapp/3rdparty/jquery-ui/js/jquery-ui.js create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/webapp/3rdparty/jquery-ui/js/jquery-ui.min.js create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/common-functions.tld create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/functions.tld create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/about.tag create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/QNameChooser.tag create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/artifactcreationdialog.tag create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/artifacttemplateselection.tag create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/id_name_type.tag create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/jquery-file-upload-full.tag create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/orioneditor/orioneditorarea.tag create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/policies/policies.tag create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/policies/policydiag.tag create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/spinnerwithinphty.tag create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/templates/CSSForTypes.tag create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/templates/defineCreateConnectorEndpointsFunction.tag create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/templates/nodetemplates/nodeTemplateRenderer.tag create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/templates/nodetemplates/reqscaps/caps.tag create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/templates/nodetemplates/reqscaps/reqs.tag create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/templates/nodetemplates/reqscaps/reqsorcaps.tag create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/templates/properties.tag create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/templates/propertiesBasic.tag create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/templates/registerConnectionTypesAndConnectNodeTemplates.tag create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/templates/toggleButtons.tag create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/topologycompletion/nodeTemplateSelector.tag create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/topologycompletion/relationshipTemplateSelector.tag create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/topologycompletion/selectionDialogs.tag create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/common/topologycompletion/topologyTemplateSelector.tag create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/idInput.tag create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/namespaceChooser.tag create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/palette.tag create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/templates/nodetemplates/propertiesOfOneNodeTemplate.tag create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/templates/nodetemplates/reqscaps/addorupdatereqorcap.tag create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/tags/templates/relationshiptemplates/propertiesOfOneRelationshipTemplate.tag create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/webapp/WEB-INF/web.xml create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/webapp/css/palette.css create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/webapp/css/propertiesview.css create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/webapp/css/topologymodeler.css create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/webapp/css/topologytemplatecontent.css create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/webapp/css/winery-common.css create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/webapp/favicon.png create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/webapp/images/xml.png create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/webapp/index.jsp create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/webapp/js/artifacttemplateselection.js create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/webapp/js/jquery.fileupload-audio.js create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/webapp/js/jquery.fileupload-image.js create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/webapp/js/jquery.fileupload-validate.js create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/webapp/js/jquery.fileupload-video.js create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/webapp/js/winery-common-topologyrendering.js create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/webapp/js/winery-common.js create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/webapp/js/winery-sugiyamaLayouter.js create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/webapp/js/winery-support-common.js create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/webapp/js/winery-topologycompletion.js create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/webapp/js/winery-topologymodeler-AMD.js create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/webapp/js/winery-topologymodeler.js create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/webapp/jsp/shared/README.md create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/webapp/jsp/shared/dialogs.jsp create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/webapp/jsp/topologyCompletion/selectionHandler.jsp create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/webapp/jsp/topologyCompletion/topologyCompletion.jsp create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/webapp/jsp/topologyCompletion/topologySaver.jsp create mode 100644 winery/org.eclipse.winery.topologymodeler/src/main/webapp/logback.xml create mode 100644 winery/org.eclipse.winery.topologymodeler/src/test/java/.gitkeep (limited to 'winery/org.eclipse.winery.topologymodeler') diff --git a/winery/org.eclipse.winery.topologymodeler/.bowerrc b/winery/org.eclipse.winery.topologymodeler/.bowerrc new file mode 100644 index 0000000..eb92b22 --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/.bowerrc @@ -0,0 +1,3 @@ +{ + "directory" : "src/main/webapp/components" +} \ No newline at end of file diff --git a/winery/org.eclipse.winery.topologymodeler/.gitattributes b/winery/org.eclipse.winery.topologymodeler/.gitattributes new file mode 100644 index 0000000..03b2494 --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/.gitattributes @@ -0,0 +1 @@ +bower.json eol=lf diff --git a/winery/org.eclipse.winery.topologymodeler/.gitignore b/winery/org.eclipse.winery.topologymodeler/.gitignore new file mode 100644 index 0000000..166eaf4 --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/.gitignore @@ -0,0 +1,23 @@ +.classpath +/.gradle +.project +.settings/.jsdtscope +.settings/org.eclipse.core.resources.prefs +.settings/org.eclipse.jdt.core.prefs +.settings/org.eclipse.m2e.core.prefs +.settings/org.eclipse.wst.common.component +.settings/org.eclipse.wst.common.project.facet.core.xml +.settings/org.eclipse.wst.common.project.facet.core.prefs.xml +.settings/org.eclipse.wst.jsdt.ui.superType.container +.settings/org.eclipse.wst.jsdt.ui.superType.name +.settings/org.eclipse.wst.validation.prefs +/.sonar +/bin +/build +sonar-project.properties +/src/main/java/rebel.xml +/src/main/resources/rebel.xml +/target + +#Generated by "bower install" +src/main/webapp/components/ diff --git a/winery/org.eclipse.winery.topologymodeler/README.md b/winery/org.eclipse.winery.topologymodeler/README.md new file mode 100644 index 0000000..f455e42 --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/README.md @@ -0,0 +1,44 @@ +# Winery Topoloy Modeler + +This is the topology modeler component of Winery. + +## Installation + +See [README.md of Winery](../README.md). + +## Implementation hints + +* use `div.NodeTemplateShape` as selector for node templates + +## About the Code + +This code is in a prototypcial status. These are the main issues: +* Instead of using EL, it directly uses Java code in the JSPs. +* Instead of including the libraries using AMD, they are directly included via `script` tags. +* Instead of using [AngularJS] (or a similar framework), we manually do the life update from the properties section to the node +* Saving generates the XML manually (in index.jsp:save()). Therefore the extensibility of TOSCA is not supported here. +* We depend on both bootstrap and jquery UI as jsPlumb does not support a bootstrap binding. + +### Trouble shooting +When the topology modeler does not fully load (i.e., a white background is still there), look at the TOMCAT log file (of the repository). +You'll see something like `TOSCA component id class org.eclipse.winery.common.ids.definitions.NodeTypeId / {http://www.example.org/tosca/nodetypes}VirtualMachine not found`. +This is in indicator that you manually edited a `.definitions` file and did not change the location in the repository. +The directory structure and the namespace and id/name settings in the `.definitions` file have to be in sync. +As quick solution, you can open the type, switch to the XML tab and press "Save". +Then, the namespace and id/name setting in the `.definitions` is changed according to the storage. + +## License +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 v2.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 + + [AngularJS]: http://angularjs.org/ + [Apache License v2.0]: http://www.apache.org/licenses/LICENSE-2.0.html + [Eclipse Public License v1.0]: http://www.eclipse.org/legal/epl-v10.html diff --git a/winery/org.eclipse.winery.topologymodeler/about.html b/winery/org.eclipse.winery.topologymodeler/about.html new file mode 100644 index 0000000..2badd94 --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/about.html @@ -0,0 +1,604 @@ + + + + +About + + +

About This Content

+ +

January 24, 2014

+

License

+ +

The Eclipse Foundation makes available all content in this plug-in (“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 Apache License Version 2.0. +A copy of the EPL is available at http://www.eclipse.org/legal/epl-v10.html +and a copy of the Apache License Version 2.0 is available at http://www.opensource.org/licenses/apache2.0.php. +You may elect to redistribute this code under either of these licenses. +For purposes of the EPL, “Program” will mean the Content. +

+ +

+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 and Apache License 2.0 still apply to any source code +in the Content and such source code may be obtained at http://www.eclipse.org. +

+ +

Third Party Content

+ +

JavaScript libraries

+ +
biltong – Version 0.1
+ + + + + + + + + + + + + +
FilesThe library is completely included in jsPlumb as “jsPlumbGeom v0.1”
URLhttps://github.com/jsplumb/biltong
LicenseMIT. A copy of the license is contained in the file LICENSE-biltong.txt and is also available at github
+ +
Bootstrap – Version 3.1.1
+ + + + + + + + + + + + + +
Filessrc/main/webapp/components/bootstrap
URLhttp://getbootstrap.com/
LicenseMIT. A copy of the license is contained in the file LICENSE-bootstrap.txt and is also available at github
+ +
bootstrap-spinedit – Version 1.0.0
+ + + + + + + + + + + + + +
Filessrc/main/webapp/components/bootstrap-spinedit
URLhttps://github.com/scyv/bootstrap-spinedit
LicenseApache 2.0. A copy of the license is contained in the file Apache-LICENSE-2.0.txt and is also available at github
+ +
JavaScript Canvas to Blob – Version 2.1.0
+ + + + + + + + + + + + + +
Filessrc/main/webapp/components/blueimp-canvas-to-blob
URLhttps://github.com/blueimp/JavaScript-Canvas-to-Blob
LicenseMIT. The authors did not provide a separate variant of the MIT license. The generic MIT license is available at http://opensource.org/licenses/MIT
+ +
JavaScript Load Image – Version 1.11.0
+ + + + + + + + + + + + + +
Filessrc/main/webapp/components/blueimp-load-image
URLhttps://github.com/blueimp/JavaScript-Load-Image
LicenseMIT. The authors did not provide a separate variant of the MIT license. The generic MIT license is available at http://opensource.org/licenses/MIT
+ +
JavaScript Templates – Version 2.5.3
+ + + + + + + + + + + + + +
Filessrc/main/webapp/components/blueimp-tmpl
URLhttps://github.com/blueimp/JavaScript-Templates
LicenseMIT. The authors did not provide a separate variant of the MIT license. The generic MIT license is available at http://opensource.org/licenses/MIT
+ +
jQuery – Version 2.0.3
+ + + + + + + + + + + + + +
Filessrc/main/webapp/components/jquery
URLhttp://jquery.com/
LicenseMIT. A copy of the license is contained in the file LICENSE-jQuery.txt and is also available at https://jquery.org/license/
+ +
jQuery Typing – v0.3.2-2
+ + + + + + + + + + + + + +
Filessrc/main/webapp/components/jquery-typing
URLhttps://github.com/tnajdek/jquery-typing
LicensePublic domain. An explicit license is not provided, only a link to unlicense.org is provided.
+ +
jQuery File Upload Plugin – Version 9.5.3
+ + + + + + + + + + + + + +
Filessrc/main/webapp/components/blueimp-file-upload
URLhttps://github.com/blueimp/jQuery-File-Upload
LicenseMIT. The authors did not provide a separate variant of the MIT license. The generic MIT license is available at http://opensource.org/licenses/MIT
+ +
jQuery UI – Version 1.10.3
+This library is required by jsPlumb only + + + + + + + + + + + + + +
Filessrc/main/webapp/components/jquery-ui
URLhttp://jqueryui.com/
LicenseMIT. A copy of the license is contained in the file LICENSE-jQuery-UI.txt and is also available at https://github.com/jquery/jquery-ui/blob/master/MIT-LICENSE.txt
+ +
jsBezier – Version 0.6
+ + + + + + + + + + + + + +
FilesThe library is completly included in jsPlumb
URLhttps://github.com/jsplumb/jsBezier
LicenseMIT. An explicit license is not provided, only an entry in the header of jsBezier-0.6.js.
+ + +
jsPlumb – Version 1.5.4
+ + + + + + + + + + + + + +
Filessrc/main/webapp/components/jsPlumb
URLhttp://jsplumb.org/
LicenseAll 1.x.x versions of jsPlumb are dual-licensed under both MIT and GPLv2 (http://www.gnu.org/licenses/old-licenses/gpl-2.0). + The Eclipse Foundation elects to include this software in this distribution under the MIT license. + A copy of the license is contained in the file LICENSE-jsPlumb-MIT and is also available at github
+ +
KeyboardJS – Version 0.4.2
+ + + + + + + + + + + + + +
Filessrc/main/webapp/components/KeyboardJS
URLhttps://github.com/RobertWHurst/KeyboardJS/tree/v0.4.2
LicenseBSD (2 clauses). A copy of the license is contained in the file LICENSE-KeyboardJS.txt and is also available at https://github.com/RobertWHurst/KeyboardJS/blob/v0.4.2/license.txt
+ +
Orion – Version 5.0
+ + + + + + + + + + + + + +
URLhttp://eclipse.org/orion/editor/releases/5.0/built-editor.js
URLhttp://www.eclipse.org/orion/
LicenseEclipse Public License v1.0 and Eclipse Distribution License v1.0. + A copy of the licenses is contained in the files LICENSE-EPL.txt and EDL.txt. + A copy of the EPL is available at http://www.eclipse.org/legal/epl-v10.html and a copy of the EDL is available at http://www.eclipse.org/org/documents/edl-v10.html.
+ +
PNotify – Version 1.3.1
+ + + + + + + + + + + + + +
Filessrc/main/webapp/components/pnotify
URLhttp://sciactive.com/pnotify/
LicensePNotify is distributed under the GPL (http://www.gnu.org/licenses/gpl.html), + LGPL (http://www.gnu.org/licenses/lgpl.html), and + MPL (http://www.mozilla.org/MPL/MPL-1.1.html). + The Eclipse Foundation elects to include this software in this distribution under the MPL license. + A copy of the license is contained in the file MPL-v1.1.txt.
+ +
RequireJS – Version 2.1.5
+ + + + + + + + + + + + + +
Filessrc/main/webapp/components/requirejs
URLhttp://requirejs.org/
LicenseBSD and MIT (see https://github.com/jrburke/requirejs/blob/master/LICENSE). + The Eclipse Foundation elects to include this software in this distribution under the MIT license. + A copy of the license is contained in the file LICENSE-requirejs.txt.
+ +
Select2 – Version 3.4.5
+ + + + + + + + + + + + + +
Filessrc/main/webapp/components/select2
URLhttp://ivaynberg.github.io/select2/
LicenseApache 2.0 (http://www.apache.org/licenses/LICENSE-2.0) and GPL2 (http://www.gnu.org/licenses/gpl-2.0.html). + The Eclipse Foundation elects to include this software in this distribution under the Apache 2.0 license. + A copy of the license is contained in the file Apache-LICENSE-2.0.txt.
+ +
X-editable – Version 1.5.1
+ + + + + + + + + + + + + +
Filessrc/main/webapp/components/x-editable
URLhttp://vitalets.github.io/x-editable/
LicenseMIT. A copy of the license is contained in the file LICENSE-x-editable.txt and is also available at github
+ +
XMLWriter – Version v1.0.2
+ + + + + + + + + + + + + +
Filessrc/main/webapp/components/XMLWriter
URLhttps://github.com/flesler/XMLWriter
LicenseBSD. A copy of the license is contained in the file LICENSE-XMLWriter.txt and is also available at github
+ +

Java Libraries

+ +
Apache Commons Configuration – Version 1.9
+ + + + + + + + + +
URLhttp://commons.apache.org/proper/commons-configuration/
LicenseApache 2.0. A copy of the license is contained in the file Apache-LICENSE-2.0.txt and is also available at http://www.apache.org/licenses/LICENSE-2.0
+ +
Apache Commons IO – Version 2.1
+ + + + + + + + + +
URLhttp://commons.apache.org/proper/commons-io/
LicenseApache 2.0. A copy of the license is contained in the file Apache-LICENSE-2.0.txt and is also available at http://www.apache.org/licenses/LICENSE-2.0
+ +
Apache Commons Lang – Version 2.6
+ + + + + + + + + +
URLhttp://commons.apache.org/proper/commons-lang/
LicenseApache 2.0. A copy of the license is contained in the file Apache-LICENSE-2.0.txt and is also available at http://www.apache.org/licenses/LICENSE-2.0
+ +
Apache Commons Lang3 – Version 3.1
+ + + + + + + + + +
URLhttp://commons.apache.org/proper/commons-lang/
LicenseApache 2.0. A copy of the license is contained in the file Apache-LICENSE-2.0.txt and is also available at http://www.apache.org/licenses/LICENSE-2.0
+ +
jackson-annotations – Version 2.2.2
+ + + + + + + + + + + + + +
URLhttps://github.com/FasterXML/jackson-annotations
LicenseApache 2.0. A copy of the license is contained in the file Apache-LICENSE-2.0.txt and is also available at http://www.apache.org/licenses/LICENSE-2.0
NoteThe license was explictily added in version 2.2.3 and 2.3.0. See Issue #14 and LICENSE in the source repository.
+ +
jackson-core – Version 2.2.2
+ + + + + + + + + +
URLhttps://github.com/FasterXML/jackson-core and http://wiki.fasterxml.com/JacksonHome
LicenseApache 2.0. A copy of the license is contained in the file Apache-LICENSE-2.0.txt and is also available at http://www.apache.org/licenses/LICENSE-2.0
+ +
jackson-databind – Version 2.2.2
+ + + + + + + + + +
URLhttps://github.com/FasterXML/jackson-databind
LicenseApache 2.0. A copy of the license is contained in the file Apache-LICENSE-2.0.txt and is also available at http://www.apache.org/licenses/LICENSE-2.0
+ +
jackson-jaxrs-base – Version 2.2.2
+ + + + + + + + + +
URLhttps://github.com/FasterXML/jackson-jaxrs-providers/tree/master/base
LicenseApache 2.0. A copy of the license is contained in the file Apache-LICENSE-2.0.txt and is also available at http://www.apache.org/licenses/LICENSE-2.0
+ +
jackson-jaxrs-json-provider – Version 2.2.2
+ + + + + + + + + +
URLhttps://github.com/FasterXML/jackson-jaxrs-providers/tree/master/json
LicenseApache 2.0. A copy of the license is contained in the file Apache-LICENSE-2.0.txt and is also available at http://www.apache.org/licenses/LICENSE-2.0
+ +
jackson-module-jaxb-annotations – Version 2.3.0
+ + + + + + + + + +
URLhttps://github.com/FasterXML/jackson-module-jaxb-annotations
LicenseApache 2.0. A copy of the license is contained in the file Apache-LICENSE-2.0.txt and is also available at http://www.apache.org/licenses/LICENSE-2.0. + The license is added via the oss-parent project.
+ +
Jersey Client – Version 1.17
+ + + + + + + + + +
URLjersey.java.net/
LicenseCDDL and GPL with classpath exception (https://jersey.java.net/license.html). + The Eclipse Foundation elects to include this software in this distribution under the CDDL license. + A copy of the license is available at CDDL-v1.1.txt.
+ +
Jersey Core – Version 1.17
+ + + + + + + + + +
URLjersey.java.net/
LicenseCDDL and GPL with classpath exception (https://jersey.java.net/license.html). + The Eclipse Foundation elects to include this software in this distribution under the CDDL license. + A copy of the license is available at CDDL-v1.1.txt.
+ +
JSP Standard Tag Library – Version 1.2
+ + + + + + + + + +
URLhttps://jstl.java.net/
LicenseCDDL and GPL with classpath exception (https://jersey.java.net/license.html). + The Eclipse Foundation elects to include this software in this distribution under the CDDL license. + A copy of the license is available at CDDL-v1.1.txt.
+ +
Logback Classic – Version 1.1.1
+ + + + + + + + + +
URLhttp://logback.qos.ch/
LicenseEPL/LGPL dual license. + EPL: http://www.eclipse.org/legal/epl-v10.html. + LGPL v2.1: http://www.gnu.org/licenses/old-licenses/lgpl-2.1. + A copy of the license is contained in the file LICENSE-logback.txt and is also available at http://logback.qos.ch/license.html. + The Eclipse Foundation elects to include this software in this distribution under the EPL license.
+ +
Logback Core – Version 1.1.1
+ + + + + + + + + +
URLhttp://logback.qos.ch/
LicenseEPL/LGPL dual license. + EPL: http://www.eclipse.org/legal/epl-v10.html. + LGPL v2.1: http://www.gnu.org/licenses/old-licenses/lgpl-2.1. + A copy of the license is contained in the file LICENSE-logback.txt and is also available at http://logback.qos.ch/license.html. + The Eclipse Foundation elects to include this software in this distribution under the EPL license.
+ +
SLF4J: slf4j-api – Version 1.7.6
+ + + + + + + + + +
URLhttp://www.slf4j.org/
LicenseMIT. A copy of the license is contained in the file LICENSE-slf4j-api.txt and is also available at http://www.slf4j.org/license.html
+ +
SLF4J: jcl-over-slf4j – Version 1.7.6
+ + + + + + + + + +
URLhttp://www.slf4j.org/legacy.html
LicenseApache 2.0. A copy of the license is contained in the file Apache-LICENSE-2.0.txt and is also available at http://www.apache.org/licenses/LICENSE-2.0
+ +
Winery: org.eclipse.winery.common – ${project.version}
+ + + + + + + + + +
URLhttp://eclipse.org/winery/
LicenseEPL/Apache 2.0. A copy of the licenses is contained in the files LICENSE-ASL.txt and LICENSE-EPL.txt. A copy of the EPL is available at http://www.eclipse.org/legal/epl-v10.html and a copy of the Apache License Version 2.0 is available at http://www.opensource.org/licenses/apache2.0.php.
+ +
Winery: org.eclipse.winery.model.tosca – Version 0.1.20
+ + + + + + + + + +
URLhttp://eclipse.org/winery/
LicenseEPL/Apache 2.0. A copy of the licenses is contained in the files LICENSE-ASL.txt and LICENSE-EPL.txt. A copy of the EPL is available at http://www.eclipse.org/legal/epl-v10.html and a copy of the Apache License Version 2.0 is available at http://www.opensource.org/licenses/apache2.0.php.
+ + + \ No newline at end of file diff --git a/winery/org.eclipse.winery.topologymodeler/about_files/Apache-LICENSE-2.0.txt b/winery/org.eclipse.winery.topologymodeler/about_files/Apache-LICENSE-2.0.txt new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/about_files/Apache-LICENSE-2.0.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/winery/org.eclipse.winery.topologymodeler/about_files/CDDL-v1.1.txt b/winery/org.eclipse.winery.topologymodeler/about_files/CDDL-v1.1.txt new file mode 100644 index 0000000..7cc8719 --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/about_files/CDDL-v1.1.txt @@ -0,0 +1,129 @@ +COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL - Version 1.1) +1. Definitions. + + 1.1. “Contributor” means each individual or entity that creates or contributes to the creation of Modifications. + + 1.2. “Contributor Version” means the combination of the Original Software, prior Modifications used by a Contributor (if any), and the Modifications made by that particular Contributor. + + 1.3. “Covered Software” means (a) the Original Software, or (b) Modifications, or (c) the combination of files containing Original Software with files containing Modifications, in each case including portions thereof. + + 1.4. “Executable” means the Covered Software in any form other than Source Code. + + 1.5. “Initial Developer” means the individual or entity that first makes Original Software available under this License. + + 1.6. “Larger Work” means a work which combines Covered Software or portions thereof with code not governed by the terms of this License. + + 1.7. “License” means this document. + + 1.8. “Licensable” means having the right to grant, to the maximum extent possible, whether at the time of the initial grant or subsequently acquired, any and all of the rights conveyed herein. + + 1.9. “Modifications” means the Source Code and Executable form of any of the following: + + A. Any file that results from an addition to, deletion from or modification of the contents of a file containing Original Software or previous Modifications; + + B. Any new file that contains any part of the Original Software or previous Modification; or + + C. Any new file that is contributed or otherwise made available under the terms of this License. + + 1.10. “Original Software” means the Source Code and Executable form of computer software code that is originally released under this License. + + 1.11. “Patent Claims” means any patent claim(s), now owned or hereafter acquired, including without limitation, method, process, and apparatus claims, in any patent Licensable by grantor. + + 1.12. “Source Code” means (a) the common form of computer software code in which modifications are made and (b) associated documentation included in or with such code. + + 1.13. “You” (or “Your”) means an individual or a legal entity exercising rights under, and complying with all of the terms of, this License. For legal entities, “You” includes any entity which controls, is controlled by, or is under common control with You. For purposes of this definition, “control” means (a) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (b) ownership of more than fifty percent (50%) of the outstanding shares or beneficial ownership of such entity. + +2. License Grants. + + 2.1. The Initial Developer Grant. + + Conditioned upon Your compliance with Section 3.1 below and subject to third party intellectual property claims, the Initial Developer hereby grants You a world-wide, royalty-free, non-exclusive license: + + (a) under intellectual property rights (other than patent or trademark) Licensable by Initial Developer, to use, reproduce, modify, display, perform, sublicense and distribute the Original Software (or portions thereof), with or without Modifications, and/or as part of a Larger Work; and + + (b) under Patent Claims infringed by the making, using or selling of Original Software, to make, have made, use, practice, sell, and offer for sale, and/or otherwise dispose of the Original Software (or portions thereof). + + (c) The licenses granted in Sections 2.1(a) and (b) are effective on the date Initial Developer first distributes or otherwise makes the Original Software available to a third party under the terms of this License. + + (d) Notwithstanding Section 2.1(b) above, no patent license is granted: (1) for code that You delete from the Original Software, or (2) for infringements caused by: (i) the modification of the Original Software, or (ii) the combination of the Original Software with other software or devices. + + 2.2. Contributor Grant. + + Conditioned upon Your compliance with Section 3.1 below and subject to third party intellectual property claims, each Contributor hereby grants You a world-wide, royalty-free, non-exclusive license: + + (a) under intellectual property rights (other than patent or trademark) Licensable by Contributor to use, reproduce, modify, display, perform, sublicense and distribute the Modifications created by such Contributor (or portions thereof), either on an unmodified basis, with other Modifications, as Covered Software and/or as part of a Larger Work; and + + (b) under Patent Claims infringed by the making, using, or selling of Modifications made by that Contributor either alone and/or in combination with its Contributor Version (or portions of such combination), to make, use, sell, offer for sale, have made, and/or otherwise dispose of: (1) Modifications made by that Contributor (or portions thereof); and (2) the combination of Modifications made by that Contributor with its Contributor Version (or portions of such combination). + + (c) The licenses granted in Sections 2.2(a) and 2.2(b) are effective on the date Contributor first distributes or otherwise makes the Modifications available to a third party. + + (d) Notwithstanding Section 2.2(b) above, no patent license is granted: (1) for any code that Contributor has deleted from the Contributor Version; (2) for infringements caused by: (i) third party modifications of Contributor Version, or (ii) the combination of Modifications made by that Contributor with other software (except as part of the Contributor Version) or other devices; or (3) under Patent Claims infringed by Covered Software in the absence of Modifications made by that Contributor. + +3. Distribution Obligations. + + 3.1. Availability of Source Code. + + Any Covered Software that You distribute or otherwise make available in Executable form must also be made available in Source Code form and that Source Code form must be distributed only under the terms of this License. You must include a copy of this License with every copy of the Source Code form of the Covered Software You distribute or otherwise make available. You must inform recipients of any such Covered Software in Executable form as to how they can obtain such Covered Software in Source Code form in a reasonable manner on or through a medium customarily used for software exchange. + + 3.2. Modifications. + + The Modifications that You create or to which You contribute are governed by the terms of this License. You represent that You believe Your Modifications are Your original creation(s) and/or You have sufficient rights to grant the rights conveyed by this License. + + 3.3. Required Notices. + + You must include a notice in each of Your Modifications that identifies You as the Contributor of the Modification. You may not remove or alter any copyright, patent or trademark notices contained within the Covered Software, or any notices of licensing or any descriptive text giving attribution to any Contributor or the Initial Developer. + + 3.4. Application of Additional Terms. + + You may not offer or impose any terms on any Covered Software in Source Code form that alters or restricts the applicable version of this License or the recipients’ rights hereunder. You may choose to offer, and to charge a fee for, warranty, support, indemnity or liability obligations to one or more recipients of Covered Software. However, you may do so only on Your own behalf, and not on behalf of the Initial Developer or any Contributor. You must make it absolutely clear that any such warranty, support, indemnity or liability obligation is offered by You alone, and You hereby agree to indemnify the Initial Developer and every Contributor for any liability incurred by the Initial Developer or such Contributor as a result of warranty, support, indemnity or liability terms You offer. + + 3.5. Distribution of Executable Versions. + + You may distribute the Executable form of the Covered Software under the terms of this License or under the terms of a license of Your choice, which may contain terms different from this License, provided that You are in compliance with the terms of this License and that the license for the Executable form does not attempt to limit or alter the recipient’s rights in the Source Code form from the rights set forth in this License. If You distribute the Covered Software in Executable form under a different license, You must make it absolutely clear that any terms which differ from this License are offered by You alone, not by the Initial Developer or Contributor. You hereby agree to indemnify the Initial Developer and every Contributor for any liability incurred by the Initial Developer or such Contributor as a result of any such terms You offer. + + 3.6. Larger Works. + + You may create a Larger Work by combining Covered Software with other code not governed by the terms of this License and distribute the Larger Work as a single product. In such a case, You must make sure the requirements of this License are fulfilled for the Covered Software. + +4. Versions of the License. + + 4.1. New Versions. + + Oracle is the initial license steward and may publish revised and/or new versions of this License from time to time. Each version will be given a distinguishing version number. Except as provided in Section 4.3, no one other than the license steward has the right to modify this License. + + 4.2. Effect of New Versions. + + You may always continue to use, distribute or otherwise make the Covered Software available under the terms of the version of the License under which You originally received the Covered Software. If the Initial Developer includes a notice in the Original Software prohibiting it from being distributed or otherwise made available under any subsequent version of the License, You must distribute and make the Covered Software available under the terms of the version of the License under which You originally received the Covered Software. Otherwise, You may also choose to use, distribute or otherwise make the Covered Software available under the terms of any subsequent version of the License published by the license steward. + + 4.3. Modified Versions. + + When You are an Initial Developer and You want to create a new license for Your Original Software, You may create and use a modified version of this License if You: (a) rename the license and remove any references to the name of the license steward (except to note that the license differs from this License); and (b) otherwise make it clear that the license contains terms which differ from this License. + +5. DISCLAIMER OF WARRANTY. + +COVERED SOFTWARE IS PROVIDED UNDER THIS LICENSE ON AN “AS IS” BASIS, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES THAT THE COVERED SOFTWARE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED SOFTWARE IS WITH YOU. SHOULD ANY COVERED SOFTWARE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF ANY COVERED SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER. +6. TERMINATION. + + 6.1. This License and the rights granted hereunder will terminate automatically if You fail to comply with terms herein and fail to cure such breach within 30 days of becoming aware of the breach. Provisions which, by their nature, must remain in effect beyond the termination of this License shall survive. + + 6.2. If You assert a patent infringement claim (excluding declaratory judgment actions) against Initial Developer or a Contributor (the Initial Developer or Contributor against whom You assert such claim is referred to as “Participant”) alleging that the Participant Software (meaning the Contributor Version where the Participant is a Contributor or the Original Software where the Participant is the Initial Developer) directly or indirectly infringes any patent, then any and all rights granted directly or indirectly to You by such Participant, the Initial Developer (if the Initial Developer is not the Participant) and all Contributors under Sections 2.1 and/or 2.2 of this License shall, upon 60 days notice from Participant terminate prospectively and automatically at the expiration of such 60 day notice period, unless if within such 60 day period You withdraw Your claim with respect to the Participant Software against such Participant either unilaterally or pursuant to a written agreement with Participant. + + 6.3. If You assert a patent infringement claim against Participant alleging that the Participant Software directly or indirectly infringes any patent where such claim is resolved (such as by license or settlement) prior to the initiation of patent infringement litigation, then the reasonable value of the licenses granted by such Participant under Sections 2.1 or 2.2 shall be taken into account in determining the amount or value of any payment or license. + + 6.4. In the event of termination under Sections 6.1 or 6.2 above, all end user licenses that have been validly granted by You or any distributor hereunder prior to termination (excluding licenses granted to You by any distributor) shall survive termination. + +7. LIMITATION OF LIABILITY. + +UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE INITIAL DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED SOFTWARE, OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL, WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY RESULTING FROM SUCH PARTY’S NEGLIGENCE TO THE EXTENT APPLICABLE LAW PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THIS EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU. +8. U.S. GOVERNMENT END USERS. + +The Covered Software is a “commercial item,” as that term is defined in 48 C.F.R. 2.101 (Oct. 1995), consisting of “commercial computer software” (as that term is defined at 48 C.F.R. § 252.227-7014(a)(1)) and “commercial computer software documentation” as such terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48 C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995), all U.S. Government End Users acquire Covered Software with only those rights set forth herein. This U.S. Government Rights clause is in lieu of, and supersedes, any other FAR, DFAR, or other clause or provision that addresses Government rights in computer software under this License. +9. MISCELLANEOUS. + +This License represents the complete agreement concerning subject matter hereof. If any provision of this License is held to be unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable. This License shall be governed by the law of the jurisdiction specified in a notice contained within the Original Software (except to the extent applicable law, if any, provides otherwise), excluding such jurisdiction’s conflict-of-law provisions. Any litigation relating to this License shall be subject to the jurisdiction of the courts located in the jurisdiction and venue specified in a notice contained within the Original Software, with the losing party responsible for costs, including, without limitation, court costs and reasonable attorneys’ fees and expenses. The application of the United Nations Convention on Contracts for the International Sale of Goods is expressly excluded. Any law or regulation which provides that the language of a contract shall be construed against the drafter shall not apply to this License. You agree that You alone are responsible for compliance with the United States export administration regulations (and the export control laws and regulation of any other countries) when You use, distribute or otherwise make available any Covered Software. +10. RESPONSIBILITY FOR CLAIMS. + +As between Initial Developer and the Contributors, each party is responsible for claims and damages arising, directly or indirectly, out of its utilization of rights under this License and You agree to work with Initial Developer and Contributors to distribute such responsibility on an equitable basis. Nothing herein is intended or shall be deemed to constitute any admission of liability. +NOTICE PURSUANT TO SECTION 9 OF THE COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) + +The code released under the CDDL shall be governed by the laws of the State of California (excluding conflict-of-law provisions). Any litigation relating to this License shall be subject to the jurisdiction of the Federal Courts of the Northern District of California and the state courts of the State of California, with venue lying in Santa Clara County, California. \ No newline at end of file diff --git a/winery/org.eclipse.winery.topologymodeler/about_files/LICENSE-KeyboardJS.txt b/winery/org.eclipse.winery.topologymodeler/about_files/LICENSE-KeyboardJS.txt new file mode 100644 index 0000000..e71620b --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/about_files/LICENSE-KeyboardJS.txt @@ -0,0 +1,25 @@ +Copyright 2011 Robert Hurst. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are +permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of + conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, this list + of conditions and the following disclaimer in the documentation and/or other materials + provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY ROBERT HURST ''AS IS'' AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ROBERT HURST OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those of the +authors and should not be interpreted as representing official policies, either expressed +or implied, of Robert Hurst. \ No newline at end of file diff --git a/winery/org.eclipse.winery.topologymodeler/about_files/LICENSE-XMLWriter.txt b/winery/org.eclipse.winery.topologymodeler/about_files/LICENSE-XMLWriter.txt new file mode 100644 index 0000000..2676da3 --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/about_files/LICENSE-XMLWriter.txt @@ -0,0 +1,27 @@ +Copyright (c) 2014, Ariel Flesler +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + +* Neither the name of the organization nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/winery/org.eclipse.winery.topologymodeler/about_files/LICENSE-biltong.txt b/winery/org.eclipse.winery.topologymodeler/about_files/LICENSE-biltong.txt new file mode 100644 index 0000000..11cb215 --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/about_files/LICENSE-biltong.txt @@ -0,0 +1,22 @@ +Copyright (c) 2013 Simon Porritt + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/winery/org.eclipse.winery.topologymodeler/about_files/LICENSE-boostrap.txt b/winery/org.eclipse.winery.topologymodeler/about_files/LICENSE-boostrap.txt new file mode 100644 index 0000000..8d94aa9 --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/about_files/LICENSE-boostrap.txt @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2011-2014 Twitter, Inc + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/winery/org.eclipse.winery.topologymodeler/about_files/LICENSE-jQuery-UI.txt b/winery/org.eclipse.winery.topologymodeler/about_files/LICENSE-jQuery-UI.txt new file mode 100644 index 0000000..1c693e3 --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/about_files/LICENSE-jQuery-UI.txt @@ -0,0 +1,26 @@ +Copyright 2013 jQuery Foundation and other contributors, +http://jqueryui.com/ + +This software consists of voluntary contributions made by many +individuals (AUTHORS.txt, http://jqueryui.com/about) For exact +contribution history, see the revision history and logs, available +at http://jquery-ui.googlecode.com/svn/ + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/winery/org.eclipse.winery.topologymodeler/about_files/LICENSE-jQuery.txt b/winery/org.eclipse.winery.topologymodeler/about_files/LICENSE-jQuery.txt new file mode 100644 index 0000000..957f26d --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/about_files/LICENSE-jQuery.txt @@ -0,0 +1,21 @@ +Copyright 2013 jQuery Foundation and other contributors +http://jquery.com/ + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/winery/org.eclipse.winery.topologymodeler/about_files/LICENSE-jsPlumb-MIT.txt b/winery/org.eclipse.winery.topologymodeler/about_files/LICENSE-jsPlumb-MIT.txt new file mode 100644 index 0000000..b5bc650 --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/about_files/LICENSE-jsPlumb-MIT.txt @@ -0,0 +1,20 @@ +Copyright (c) 2013 Simon Porritt, http://jsplumb.org/ + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/winery/org.eclipse.winery.topologymodeler/about_files/LICENSE-logback.txt b/winery/org.eclipse.winery.topologymodeler/about_files/LICENSE-logback.txt new file mode 100644 index 0000000..b4fe24e --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/about_files/LICENSE-logback.txt @@ -0,0 +1,15 @@ +Logback LICENSE +--------------- + +Logback: the reliable, generic, fast and flexible logging framework. +Copyright (C) 1999-2012, QOS.ch. All rights reserved. + +This program and the accompanying materials are dual-licensed under +either the terms of the Eclipse Public License v1.0 as published by +the Eclipse Foundation + + or (per the licensee's choosing) + +under the terms of the GNU Lesser General Public License version 2.1 +as published by the Free Software Foundation. + diff --git a/winery/org.eclipse.winery.topologymodeler/about_files/LICENSE-requirejs.txt b/winery/org.eclipse.winery.topologymodeler/about_files/LICENSE-requirejs.txt new file mode 100644 index 0000000..de4ee29 --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/about_files/LICENSE-requirejs.txt @@ -0,0 +1,58 @@ +RequireJS is released under two licenses: new BSD, and MIT. You may pick the +license that best suits your development needs. The text of both licenses are +provided below. + + +The "New" BSD License: +---------------------- + +Copyright (c) 2010-2013, The Dojo Foundation +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of the Dojo Foundation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + + +MIT License +----------- + +Copyright (c) 2010-2013, The Dojo Foundation + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/winery/org.eclipse.winery.topologymodeler/about_files/LICENSE-slf4j-api.txt b/winery/org.eclipse.winery.topologymodeler/about_files/LICENSE-slf4j-api.txt new file mode 100644 index 0000000..37050c9 --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/about_files/LICENSE-slf4j-api.txt @@ -0,0 +1,21 @@ + Copyright (c) 2004-2013 QOS.ch + All rights reserved. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/winery/org.eclipse.winery.topologymodeler/about_files/LICENSE-x-editable.txt b/winery/org.eclipse.winery.topologymodeler/about_files/LICENSE-x-editable.txt new file mode 100644 index 0000000..eeb9357 --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/about_files/LICENSE-x-editable.txt @@ -0,0 +1,22 @@ +Copyright (c) 2012 Vitaliy Potapov + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. diff --git a/winery/org.eclipse.winery.topologymodeler/about_files/MPL-v1.1.txt b/winery/org.eclipse.winery.topologymodeler/about_files/MPL-v1.1.txt new file mode 100644 index 0000000..a8cd934 --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/about_files/MPL-v1.1.txt @@ -0,0 +1,470 @@ + MOZILLA PUBLIC LICENSE + Version 1.1 + + --------------- + +1. Definitions. + + 1.0.1. "Commercial Use" means distribution or otherwise making the + Covered Code available to a third party. + + 1.1. "Contributor" means each entity that creates or contributes to + the creation of Modifications. + + 1.2. "Contributor Version" means the combination of the Original + Code, prior Modifications used by a Contributor, and the Modifications + made by that particular Contributor. + + 1.3. "Covered Code" means the Original Code or Modifications or the + combination of the Original Code and Modifications, in each case + including portions thereof. + + 1.4. "Electronic Distribution Mechanism" means a mechanism generally + accepted in the software development community for the electronic + transfer of data. + + 1.5. "Executable" means Covered Code in any form other than Source + Code. + + 1.6. "Initial Developer" means the individual or entity identified + as the Initial Developer in the Source Code notice required by Exhibit + A. + + 1.7. "Larger Work" means a work which combines Covered Code or + portions thereof with code not governed by the terms of this License. + + 1.8. "License" means this document. + + 1.8.1. "Licensable" means having the right to grant, to the maximum + extent possible, whether at the time of the initial grant or + subsequently acquired, any and all of the rights conveyed herein. + + 1.9. "Modifications" means any addition to or deletion from the + substance or structure of either the Original Code or any previous + Modifications. When Covered Code is released as a series of files, a + Modification is: + A. Any addition to or deletion from the contents of a file + containing Original Code or previous Modifications. + + B. Any new file that contains any part of the Original Code or + previous Modifications. + + 1.10. "Original Code" means Source Code of computer software code + which is described in the Source Code notice required by Exhibit A as + Original Code, and which, at the time of its release under this + License is not already Covered Code governed by this License. + + 1.10.1. "Patent Claims" means any patent claim(s), now owned or + hereafter acquired, including without limitation, method, process, + and apparatus claims, in any patent Licensable by grantor. + + 1.11. "Source Code" means the preferred form of the Covered Code for + making modifications to it, including all modules it contains, plus + any associated interface definition files, scripts used to control + compilation and installation of an Executable, or source code + differential comparisons against either the Original Code or another + well known, available Covered Code of the Contributor's choice. The + Source Code can be in a compressed or archival form, provided the + appropriate decompression or de-archiving software is widely available + for no charge. + + 1.12. "You" (or "Your") means an individual or a legal entity + exercising rights under, and complying with all of the terms of, this + License or a future version of this License issued under Section 6.1. + For legal entities, "You" includes any entity which controls, is + controlled by, or is under common control with You. For purposes of + this definition, "control" means (a) the power, direct or indirect, + to cause the direction or management of such entity, whether by + contract or otherwise, or (b) ownership of more than fifty percent + (50%) of the outstanding shares or beneficial ownership of such + entity. + +2. Source Code License. + + 2.1. The Initial Developer Grant. + The Initial Developer hereby grants You a world-wide, royalty-free, + non-exclusive license, subject to third party intellectual property + claims: + (a) under intellectual property rights (other than patent or + trademark) Licensable by Initial Developer to use, reproduce, + modify, display, perform, sublicense and distribute the Original + Code (or portions thereof) with or without Modifications, and/or + as part of a Larger Work; and + + (b) under Patents Claims infringed by the making, using or + selling of Original Code, to make, have made, use, practice, + sell, and offer for sale, and/or otherwise dispose of the + Original Code (or portions thereof). + + (c) the licenses granted in this Section 2.1(a) and (b) are + effective on the date Initial Developer first distributes + Original Code under the terms of this License. + + (d) Notwithstanding Section 2.1(b) above, no patent license is + granted: 1) for code that You delete from the Original Code; 2) + separate from the Original Code; or 3) for infringements caused + by: i) the modification of the Original Code or ii) the + combination of the Original Code with other software or devices. + + 2.2. Contributor Grant. + Subject to third party intellectual property claims, each Contributor + hereby grants You a world-wide, royalty-free, non-exclusive license + + (a) under intellectual property rights (other than patent or + trademark) Licensable by Contributor, to use, reproduce, modify, + display, perform, sublicense and distribute the Modifications + created by such Contributor (or portions thereof) either on an + unmodified basis, with other Modifications, as Covered Code + and/or as part of a Larger Work; and + + (b) under Patent Claims infringed by the making, using, or + selling of Modifications made by that Contributor either alone + and/or in combination with its Contributor Version (or portions + of such combination), to make, use, sell, offer for sale, have + made, and/or otherwise dispose of: 1) Modifications made by that + Contributor (or portions thereof); and 2) the combination of + Modifications made by that Contributor with its Contributor + Version (or portions of such combination). + + (c) the licenses granted in Sections 2.2(a) and 2.2(b) are + effective on the date Contributor first makes Commercial Use of + the Covered Code. + + (d) Notwithstanding Section 2.2(b) above, no patent license is + granted: 1) for any code that Contributor has deleted from the + Contributor Version; 2) separate from the Contributor Version; + 3) for infringements caused by: i) third party modifications of + Contributor Version or ii) the combination of Modifications made + by that Contributor with other software (except as part of the + Contributor Version) or other devices; or 4) under Patent Claims + infringed by Covered Code in the absence of Modifications made by + that Contributor. + +3. Distribution Obligations. + + 3.1. Application of License. + The Modifications which You create or to which You contribute are + governed by the terms of this License, including without limitation + Section 2.2. The Source Code version of Covered Code may be + distributed only under the terms of this License or a future version + of this License released under Section 6.1, and You must include a + copy of this License with every copy of the Source Code You + distribute. You may not offer or impose any terms on any Source Code + version that alters or restricts the applicable version of this + License or the recipients' rights hereunder. However, You may include + an additional document offering the additional rights described in + Section 3.5. + + 3.2. Availability of Source Code. + Any Modification which You create or to which You contribute must be + made available in Source Code form under the terms of this License + either on the same media as an Executable version or via an accepted + Electronic Distribution Mechanism to anyone to whom you made an + Executable version available; and if made available via Electronic + Distribution Mechanism, must remain available for at least twelve (12) + months after the date it initially became available, or at least six + (6) months after a subsequent version of that particular Modification + has been made available to such recipients. You are responsible for + ensuring that the Source Code version remains available even if the + Electronic Distribution Mechanism is maintained by a third party. + + 3.3. Description of Modifications. + You must cause all Covered Code to which You contribute to contain a + file documenting the changes You made to create that Covered Code and + the date of any change. You must include a prominent statement that + the Modification is derived, directly or indirectly, from Original + Code provided by the Initial Developer and including the name of the + Initial Developer in (a) the Source Code, and (b) in any notice in an + Executable version or related documentation in which You describe the + origin or ownership of the Covered Code. + + 3.4. Intellectual Property Matters + (a) Third Party Claims. + If Contributor has knowledge that a license under a third party's + intellectual property rights is required to exercise the rights + granted by such Contributor under Sections 2.1 or 2.2, + Contributor must include a text file with the Source Code + distribution titled "LEGAL" which describes the claim and the + party making the claim in sufficient detail that a recipient will + know whom to contact. If Contributor obtains such knowledge after + the Modification is made available as described in Section 3.2, + Contributor shall promptly modify the LEGAL file in all copies + Contributor makes available thereafter and shall take other steps + (such as notifying appropriate mailing lists or newsgroups) + reasonably calculated to inform those who received the Covered + Code that new knowledge has been obtained. + + (b) Contributor APIs. + If Contributor's Modifications include an application programming + interface and Contributor has knowledge of patent licenses which + are reasonably necessary to implement that API, Contributor must + also include this information in the LEGAL file. + + (c) Representations. + Contributor represents that, except as disclosed pursuant to + Section 3.4(a) above, Contributor believes that Contributor's + Modifications are Contributor's original creation(s) and/or + Contributor has sufficient rights to grant the rights conveyed by + this License. + + 3.5. Required Notices. + You must duplicate the notice in Exhibit A in each file of the Source + Code. If it is not possible to put such notice in a particular Source + Code file due to its structure, then You must include such notice in a + location (such as a relevant directory) where a user would be likely + to look for such a notice. If You created one or more Modification(s) + You may add your name as a Contributor to the notice described in + Exhibit A. You must also duplicate this License in any documentation + for the Source Code where You describe recipients' rights or ownership + rights relating to Covered Code. You may choose to offer, and to + charge a fee for, warranty, support, indemnity or liability + obligations to one or more recipients of Covered Code. However, You + may do so only on Your own behalf, and not on behalf of the Initial + Developer or any Contributor. You must make it absolutely clear than + any such warranty, support, indemnity or liability obligation is + offered by You alone, and You hereby agree to indemnify the Initial + Developer and every Contributor for any liability incurred by the + Initial Developer or such Contributor as a result of warranty, + support, indemnity or liability terms You offer. + + 3.6. Distribution of Executable Versions. + You may distribute Covered Code in Executable form only if the + requirements of Section 3.1-3.5 have been met for that Covered Code, + and if You include a notice stating that the Source Code version of + the Covered Code is available under the terms of this License, + including a description of how and where You have fulfilled the + obligations of Section 3.2. The notice must be conspicuously included + in any notice in an Executable version, related documentation or + collateral in which You describe recipients' rights relating to the + Covered Code. You may distribute the Executable version of Covered + Code or ownership rights under a license of Your choice, which may + contain terms different from this License, provided that You are in + compliance with the terms of this License and that the license for the + Executable version does not attempt to limit or alter the recipient's + rights in the Source Code version from the rights set forth in this + License. If You distribute the Executable version under a different + license You must make it absolutely clear that any terms which differ + from this License are offered by You alone, not by the Initial + Developer or any Contributor. You hereby agree to indemnify the + Initial Developer and every Contributor for any liability incurred by + the Initial Developer or such Contributor as a result of any such + terms You offer. + + 3.7. Larger Works. + You may create a Larger Work by combining Covered Code with other code + not governed by the terms of this License and distribute the Larger + Work as a single product. In such a case, You must make sure the + requirements of this License are fulfilled for the Covered Code. + +4. Inability to Comply Due to Statute or Regulation. + + If it is impossible for You to comply with any of the terms of this + License with respect to some or all of the Covered Code due to + statute, judicial order, or regulation then You must: (a) comply with + the terms of this License to the maximum extent possible; and (b) + describe the limitations and the code they affect. Such description + must be included in the LEGAL file described in Section 3.4 and must + be included with all distributions of the Source Code. Except to the + extent prohibited by statute or regulation, such description must be + sufficiently detailed for a recipient of ordinary skill to be able to + understand it. + +5. Application of this License. + + This License applies to code to which the Initial Developer has + attached the notice in Exhibit A and to related Covered Code. + +6. Versions of the License. + + 6.1. New Versions. + Netscape Communications Corporation ("Netscape") may publish revised + and/or new versions of the License from time to time. Each version + will be given a distinguishing version number. + + 6.2. Effect of New Versions. + Once Covered Code has been published under a particular version of the + License, You may always continue to use it under the terms of that + version. You may also choose to use such Covered Code under the terms + of any subsequent version of the License published by Netscape. No one + other than Netscape has the right to modify the terms applicable to + Covered Code created under this License. + + 6.3. Derivative Works. + If You create or use a modified version of this License (which you may + only do in order to apply it to code which is not already Covered Code + governed by this License), You must (a) rename Your license so that + the phrases "Mozilla", "MOZILLAPL", "MOZPL", "Netscape", + "MPL", "NPL" or any confusingly similar phrase do not appear in your + license (except to note that your license differs from this License) + and (b) otherwise make it clear that Your version of the license + contains terms which differ from the Mozilla Public License and + Netscape Public License. (Filling in the name of the Initial + Developer, Original Code or Contributor in the notice described in + Exhibit A shall not of themselves be deemed to be modifications of + this License.) + +7. DISCLAIMER OF WARRANTY. + + COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF + DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING. + THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED CODE + IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, + YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE + COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER + OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF + ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER. + +8. TERMINATION. + + 8.1. This License and the rights granted hereunder will terminate + automatically if You fail to comply with terms herein and fail to cure + such breach within 30 days of becoming aware of the breach. All + sublicenses to the Covered Code which are properly granted shall + survive any termination of this License. Provisions which, by their + nature, must remain in effect beyond the termination of this License + shall survive. + + 8.2. If You initiate litigation by asserting a patent infringement + claim (excluding declatory judgment actions) against Initial Developer + or a Contributor (the Initial Developer or Contributor against whom + You file such action is referred to as "Participant") alleging that: + + (a) such Participant's Contributor Version directly or indirectly + infringes any patent, then any and all rights granted by such + Participant to You under Sections 2.1 and/or 2.2 of this License + shall, upon 60 days notice from Participant terminate prospectively, + unless if within 60 days after receipt of notice You either: (i) + agree in writing to pay Participant a mutually agreeable reasonable + royalty for Your past and future use of Modifications made by such + Participant, or (ii) withdraw Your litigation claim with respect to + the Contributor Version against such Participant. If within 60 days + of notice, a reasonable royalty and payment arrangement are not + mutually agreed upon in writing by the parties or the litigation claim + is not withdrawn, the rights granted by Participant to You under + Sections 2.1 and/or 2.2 automatically terminate at the expiration of + the 60 day notice period specified above. + + (b) any software, hardware, or device, other than such Participant's + Contributor Version, directly or indirectly infringes any patent, then + any rights granted to You by such Participant under Sections 2.1(b) + and 2.2(b) are revoked effective as of the date You first made, used, + sold, distributed, or had made, Modifications made by that + Participant. + + 8.3. If You assert a patent infringement claim against Participant + alleging that such Participant's Contributor Version directly or + indirectly infringes any patent where such claim is resolved (such as + by license or settlement) prior to the initiation of patent + infringement litigation, then the reasonable value of the licenses + granted by such Participant under Sections 2.1 or 2.2 shall be taken + into account in determining the amount or value of any payment or + license. + + 8.4. In the event of termination under Sections 8.1 or 8.2 above, + all end user license agreements (excluding distributors and resellers) + which have been validly granted by You or any distributor hereunder + prior to termination shall survive termination. + +9. LIMITATION OF LIABILITY. + + UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT + (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE INITIAL + DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED CODE, + OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR + ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY + CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL, + WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER + COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN + INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF + LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY + RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW + PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE + EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO + THIS EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU. + +10. U.S. GOVERNMENT END USERS. + + The Covered Code is a "commercial item," as that term is defined in + 48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial computer + software" and "commercial computer software documentation," as such + terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48 + C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995), + all U.S. Government End Users acquire Covered Code with only those + rights set forth herein. + +11. MISCELLANEOUS. + + This License represents the complete agreement concerning subject + matter hereof. If any provision of this License is held to be + unenforceable, such provision shall be reformed only to the extent + necessary to make it enforceable. This License shall be governed by + California law provisions (except to the extent applicable law, if + any, provides otherwise), excluding its conflict-of-law provisions. + With respect to disputes in which at least one party is a citizen of, + or an entity chartered or registered to do business in the United + States of America, any litigation relating to this License shall be + subject to the jurisdiction of the Federal Courts of the Northern + District of California, with venue lying in Santa Clara County, + California, with the losing party responsible for costs, including + without limitation, court costs and reasonable attorneys' fees and + expenses. The application of the United Nations Convention on + Contracts for the International Sale of Goods is expressly excluded. + Any law or regulation which provides that the language of a contract + shall be construed against the drafter shall not apply to this + License. + +12. RESPONSIBILITY FOR CLAIMS. + + As between Initial Developer and the Contributors, each party is + responsible for claims and damages arising, directly or indirectly, + out of its utilization of rights under this License and You agree to + work with Initial Developer and Contributors to distribute such + responsibility on an equitable basis. Nothing herein is intended or + shall be deemed to constitute any admission of liability. + +13. MULTIPLE-LICENSED CODE. + + Initial Developer may designate portions of the Covered Code as + "Multiple-Licensed". "Multiple-Licensed" means that the Initial + Developer permits you to utilize portions of the Covered Code under + Your choice of the MPL or the alternative licenses, if any, specified + by the Initial Developer in the file described in Exhibit A. + +EXHIBIT A -Mozilla Public License. + + ``The contents of this file are subject to the Mozilla Public License + Version 1.1 (the "License"); you may not use this file except in + compliance with the License. You may obtain a copy of the License at + http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" + basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the + License for the specific language governing rights and limitations + under the License. + + The Original Code is ______________________________________. + + The Initial Developer of the Original Code is ________________________. + Portions created by ______________________ are Copyright (C) ______ + _______________________. All Rights Reserved. + + Contributor(s): ______________________________________. + + Alternatively, the contents of this file may be used under the terms + of the _____ license (the "[___] License"), in which case the + provisions of [______] License are applicable instead of those + above. If you wish to allow use of your version of this file only + under the terms of the [____] License and not to allow others to use + your version of this file under the MPL, indicate your decision by + deleting the provisions above and replace them with the notice and + other provisions required by the [___] License. If you do not delete + the provisions above, a recipient may use your version of this file + under either the MPL or the [___] License." + + [NOTE: The text of this Exhibit A may differ slightly from the text of + the notices in the Source Code files of the Original Code. You should + use the text of this Exhibit A rather than the text found in the + Original Code Source Code for Your Modifications.] + diff --git a/winery/org.eclipse.winery.topologymodeler/bower.json b/winery/org.eclipse.winery.topologymodeler/bower.json new file mode 100644 index 0000000..a8204ce --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/bower.json @@ -0,0 +1,44 @@ +{ + "name": "Winery topology modeler", + "version": "0.1.37-SNAPSHOT", + "author": "Oliver Kopp ", + "contributors": [ + { + "name": "Uwe Breitenbücher" + }, + { + "name": "Kálmán Képes" + }, + { + "name": "Yves Schubert" + } + ], + "licenses": [ + { + "type": "EPL", + "url": "http://www.eclipse.org/legal/epl-v10.html" + }, + { + "type": "Apache 2.0", + "url": "http://www.apache.org/licenses/LICENSE-2.0.html" + } + ], + "dependencies": { + "blueimp-file-upload": "9.5.3", + "blueimp-tmpl": "2.5.3", + "bootstrap": "3.1.1", + "bootstrap-spinedit": "https://github.com/scyv/bootstrap-spinedit.git#1.0.0", + "jquery": "2.0.3", + "jquery-typing": "https://github.com/tnajdek/jquery-typing.git#0.3.2-2", + "jsPlumb": "1.5.4", + "KeyboardJS": "https://github.com/RobertWHurst/KeyboardJS.git#v0.4.2", + "pnotify": "1.3.1", + "requirejs": "2.1.5", + "select2": "https://github.com/ivaynberg/select2/archive/3.4.5.zip", + "x-editable": "1.5.1", + "XMLWriter": "1.0.2" + }, + "keywords": [ + "TOSCA" + ] +} diff --git a/winery/org.eclipse.winery.topologymodeler/package.json b/winery/org.eclipse.winery.topologymodeler/package.json new file mode 100644 index 0000000..b59dbe9 --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/package.json @@ -0,0 +1,22 @@ +{ + "name": "openo-winery", + "version": "1.0.0", + "description": "openo winery", + "dependencies": { + }, + "devDependencies": { + "bower": "~1.7.9" + }, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "http://oip.zte.com.cn/oipgit/git/Open-O-Community/common-services-common-utilities.git" + }, + "keywords": [ + "openo-winery" + ], + "author": "openo", + "license": "Apache-2.0" +} diff --git a/winery/org.eclipse.winery.topologymodeler/pom.xml b/winery/org.eclipse.winery.topologymodeler/pom.xml new file mode 100644 index 0000000..7d6c9f3 --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/pom.xml @@ -0,0 +1,193 @@ + + + + 4.0.0 + + org.eclipse.winery + winery + 0.1.37-SNAPSHOT + + org.eclipse.winery.topologymodeler + war + + UTF-8 + + + + com.sun.jersey + jersey-server + 1.17.1 + compile + + + commons-logging + commons-logging + + + + + com.sun.jersey + jersey-servlet + 1.17.1 + compile + + + commons-logging + commons-logging + + + + + com.sun.jersey + jersey-core + 1.17.1 + compile + + + commons-logging + commons-logging + + + + + org.eclipse.winery + org.eclipse.winery.repository.client + 0.1.37-SNAPSHOT + compile + + + commons-logging + commons-logging + + + + + org.apache.commons + commons-lang3 + 3.1 + compile + + + commons-logging + commons-logging + + + + + ch.qos.logback + logback-classic + 1.1.1 + compile + + + org.slf4j + jcl-over-slf4j + 1.7.6 + compile + + + + + + org.apache.maven.plugins + maven-war-plugin + 2.4 + + + + ${basedir}/src/main/webapp/WEB-INF + true + WEB-INF + + tags/about.tag + + + + true + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.1 + + 1.7 + 1.7 + + + + com.github.eirslett + frontend-maven-plugin + 1.0 + + + v4.5.0 + 2.15.9 + https://nodejs.org/dist/ + https://registry.npmjs.org/npm/-/ + + + + install node and npm + + initialize + + install-node-and-npm + npm + + + + bower install + initialize + + bower + + + + + + winery-topologymodeler + + + + + org.eclipse.m2e + lifecycle-mapping + 1.0.0 + + + + + + org.apache.maven.plugins + maven-antrun-plugin + [1.0.0,) + + run + + + + + + + + + + + + + + diff --git a/winery/org.eclipse.winery.topologymodeler/sonar-project.js.properties b/winery/org.eclipse.winery.topologymodeler/sonar-project.js.properties new file mode 100644 index 0000000..253705e --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/sonar-project.js.properties @@ -0,0 +1,13 @@ +# required metadata +sonar.projectKey=org.eclipse.winery.topologymodeler-js +sonar.projectName=org.eclipse.winery.topologymodeler-js +sonar.projectVersion=0.1.2 + +# path to source directories (required) +sonar.sources=WebContent/ +sonar.exclusions=components/** + +# The value of the property must be the key of the language. +sonar.language=js + +sonar.sourceEncoding=UTF-8 diff --git a/winery/org.eclipse.winery.topologymodeler/sonar-project.web.properties b/winery/org.eclipse.winery.topologymodeler/sonar-project.web.properties new file mode 100644 index 0000000..b15e63d --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/sonar-project.web.properties @@ -0,0 +1,13 @@ +# required metadata +sonar.projectKey=org.eclipse.winery.topologymodeler-web +sonar.projectName=org.eclipse.winery.topologymodeler-web +sonar.projectVersion=0.1.2 + +# path to source directories (required) +sonar.sources=src/main/webapp/ +sonar.exclusions=components/** + +# The value of the property must be the key of the language. +sonar.language=web + +sonar.sourceEncoding=UTF-8 diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/WineryUtil.java b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/WineryUtil.java new file mode 100644 index 0000000..2dc7e27 --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/WineryUtil.java @@ -0,0 +1,87 @@ +/******************************************************************************* + * 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 + *******************************************************************************/ +package org.eclipse.winery.topologymodeler; + +import java.util.List; +import java.util.SortedMap; +import java.util.SortedSet; +import java.util.TreeMap; +import java.util.TreeSet; + +import org.eclipse.winery.common.interfaces.QNameWithName; + +public class WineryUtil { + + /** + * LocalName is the ID of the element, whereas Name is the speaking name + */ + public static class LocalNameNamePair implements Comparable { + + String localName; + String name; + + + public LocalNameNamePair(String localName, String name) { + this.localName = localName; + this.name = name; + } + + public String getLocalName() { + return this.localName; + } + + public String getName() { + return this.name; + } + + /** + * Ordering according to name + */ + @Override + public int compareTo(LocalNameNamePair otherPair) { + return this.name.compareTo(otherPair.name); + } + + @Override + public int hashCode() { + return this.localName.hashCode(); + } + + @Override + public boolean equals(Object o) { + if (o instanceof LocalNameNamePair) { + return this.localName.equals(((LocalNameNamePair) o).getLocalName()); + } else { + return false; + } + } + } + + + public static SortedMap> convertQNameWithNameListToNamespaceToLocalNameNamePairList(List list) { + if (list == null) { + throw new IllegalArgumentException("list may not be null"); + } + SortedMap> res = new TreeMap<>(); + for (QNameWithName qnameWithName : list) { + SortedSet localNameNamePairSet = res.get(qnameWithName.qname.getNamespaceURI()); + if (localNameNamePairSet == null) { + localNameNamePairSet = new TreeSet<>(); + res.put(qnameWithName.qname.getNamespaceURI(), localNameNamePairSet); + } + LocalNameNamePair pair = new LocalNameNamePair(qnameWithName.qname.getLocalPart(), qnameWithName.name); + localNameNamePairSet.add(pair); + } + return res; + } + +} diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/analyzer/DeferredAnalyzer.java b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/analyzer/DeferredAnalyzer.java new file mode 100644 index 0000000..c4db9bb --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/analyzer/DeferredAnalyzer.java @@ -0,0 +1,60 @@ +/******************************************************************************* + * 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 + *******************************************************************************/ + +package org.eclipse.winery.topologymodeler.addons.topologycompleter.analyzer; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.winery.model.tosca.TNodeTemplate; +import org.eclipse.winery.model.tosca.TRelationshipTemplate; +import org.eclipse.winery.model.tosca.TTopologyTemplate; +import org.eclipse.winery.topologymodeler.addons.topologycompleter.helper.Constants; + +/** + * This class contains a method to analyze a TOSCA {@link TTopologyTemplate} for + * the occurrence of "Deferred"-{@link TRelationshipTemplate}s. + * + * A "Deferred"-{@link TRelationshipTemplate} serves as place holder for any number of Node or Relationship + * Templates. + */ +public class DeferredAnalyzer { + + /** + * Iterates over all {@link TRelationshipTemplate} and checks if its type is "deferred". + * + * @param toscaAnalyzer + * the {@link TOSCAAnalyzer} object to access the data model + * + * @return a list of found deferred {@link TRelationshipTemplate}s + */ + public static List analyzeDeferredRelations(TOSCAAnalyzer toscaAnalyzer) { + + List foundDeferredRelations = new ArrayList(); + + for (TRelationshipTemplate relationshipTemplate : toscaAnalyzer.getRelationshipTemplates()) { + if (relationshipTemplate.getType() != null && relationshipTemplate.getType().getLocalPart().equals(Constants.DEFERRED_QNAME.getLocalPart()) && + relationshipTemplate.getType().getNamespaceURI().equals(Constants.DEFERRED_QNAME.getNamespaceURI())) { + + // TODO: This step has to be done until the "Provisioning-API" + // is implemented. The Deferred RelationshipTemplate can only be + // completed if Requirements exist at the source template. + TNodeTemplate source = (TNodeTemplate) relationshipTemplate.getSourceElement().getRef(); + + if (source.getRequirements() != null) { + foundDeferredRelations.add(relationshipTemplate); + } + } + } + return foundDeferredRelations; + } +} diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/analyzer/PlaceHolderAnalyzer.java b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/analyzer/PlaceHolderAnalyzer.java new file mode 100644 index 0000000..ddf0e91 --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/analyzer/PlaceHolderAnalyzer.java @@ -0,0 +1,52 @@ +/******************************************************************************* + * 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 + *******************************************************************************/ + +package org.eclipse.winery.topologymodeler.addons.topologycompleter.analyzer; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.winery.model.tosca.TNodeTemplate; +import org.eclipse.winery.model.tosca.TNodeType; +import org.eclipse.winery.topologymodeler.addons.topologycompleter.helper.Constants; +import org.eclipse.winery.topologymodeler.addons.topologycompleter.helper.Utils; + +/** + * This class analyzes the occurrence of place holders in a topology and writes them to an {@link ArrayList}. + */ +public class PlaceHolderAnalyzer { + + /** + * This method searches {@link TNodeTemplate}s that are derived from the abstract "PlaceHolder" type and adds them to a list. + * + * @param toscaAnalyzer + * the {@link TOSCAAnalyzer} object to access the data model + * + * @return the found place holders of the topology as a list. + */ + public static List analyzePlaceHolders(TOSCAAnalyzer toscaAnalyzer) { + + List foundPlaceHolders = new ArrayList(); + + // Check the type of the NodeTemplates, write them to a list if the type is derived from the common place holder type. + for (TNodeTemplate nodeTemplate : toscaAnalyzer.getNodeTemplates()) { + + TNodeType nodeType = Utils.getNodeTypeForId(toscaAnalyzer.getNodeTypes(), nodeTemplate.getType()); + + if (nodeType != null && nodeType.getDerivedFrom() != null && nodeType.getDerivedFrom().getTypeRef().getLocalPart().equals(Constants.PLACE_HOLDER_QNAME.getLocalPart()) && + nodeType.getDerivedFrom().getTypeRef().getNamespaceURI().equals(Constants.PLACE_HOLDER_QNAME.getNamespaceURI())) { + foundPlaceHolders.add(nodeTemplate); + } + } + return foundPlaceHolders; + } +} diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/analyzer/RequirementAnalyzer.java b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/analyzer/RequirementAnalyzer.java new file mode 100644 index 0000000..71f3961 --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/analyzer/RequirementAnalyzer.java @@ -0,0 +1,117 @@ +/******************************************************************************* + * 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 + *******************************************************************************/ + +package org.eclipse.winery.topologymodeler.addons.topologycompleter.analyzer; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.eclipse.winery.model.tosca.TCapability; +import org.eclipse.winery.model.tosca.TNodeTemplate; +import org.eclipse.winery.model.tosca.TNodeType; +import org.eclipse.winery.model.tosca.TRelationshipTemplate; +import org.eclipse.winery.model.tosca.TRequirement; +import org.eclipse.winery.model.tosca.TRequirementDefinition; +import org.eclipse.winery.model.tosca.TRequirementType; +import org.eclipse.winery.model.tosca.TTopologyTemplate; +import org.eclipse.winery.topologymodeler.addons.topologycompleter.helper.Utils; + +/** + * This class analyzes the occurrence of TOSCA {@link TRequirement}s in a {@link TTopologyTemplate} and checks whether they + * are already fulfilled or not. + */ +public class RequirementAnalyzer { + + /** + * This method checks if {@link TNodeTemplate}s contain {@link TRequirement}s and adds them to a {@link Map}. + * + * @param toscaAnalyzer + * the {@link TOSCAAnalyzer} object to access the data model + * + * @return a map containing {@link TNodeTemplate}s and their {@link TRequirement}s + */ + public static Map analyzeRequirements(TOSCAAnalyzer toscaAnalyzer) { + + // map containing entries for a Requirement and its corresponding NodeTemplate + Map unfulfilledRequirements = new HashMap(); + + for (TNodeTemplate nodeTemplate : toscaAnalyzer.getNodeTemplates()) { + + List requirements = new ArrayList<>(); + + TNodeType nodeType = Utils.getNodeTypeForId(toscaAnalyzer.getNodeTypes(), nodeTemplate.getType()); + + if (nodeType.getRequirementDefinitions() != null && !nodeType.getRequirementDefinitions().getRequirementDefinition().isEmpty()) { + + List requirementDefinitions = nodeType.getRequirementDefinitions().getRequirementDefinition(); + + // check the requirements of the type of the used NodeTemplate + for (TRequirementDefinition requirementDefinition: requirementDefinitions) { + TRequirement requirement = new TRequirement(); + requirement.setType(requirementDefinition.getRequirementType()); + requirement.setName(requirementDefinition.getName()); + requirement.setId(Utils.createRandomID()); + } + } + + if (nodeTemplate.getRequirements() != null && !nodeTemplate.getRequirements().getRequirement().isEmpty()) { + requirements.addAll(nodeTemplate.getRequirements().getRequirement()); + } + + if (!requirements.isEmpty()) { + // list containing the RelationshipTemplates connecting to the NodeTemplate + List connectors = new ArrayList(); + + // add the connected RelationshipTemplates + for (TRelationshipTemplate connector : toscaAnalyzer.getRelationshipTemplates()) { + if (connector.getSourceElement().getRef().equals(nodeTemplate)) { + connectors.add(connector); + } + } + + // add requirements of unconnected NodeTemplates to the map because they can't be fulfilled + if (connectors.size() == 0) { + for (TRequirement requirement : requirements) { + unfulfilledRequirements.put(requirement, nodeTemplate); + } + } else { + boolean fulfilled = false; + + // check if one of the connected NodeTemplates already fulfill the requirement + for (TRequirement requirement : requirements) { + for (TRelationshipTemplate connector : connectors) { + TNodeTemplate connectedNodeTemplate = (TNodeTemplate) connector.getTargetElement().getRef(); + if (connectedNodeTemplate.getCapabilities() != null) { + for (TCapability capa : connectedNodeTemplate.getCapabilities().getCapability()) { + for (TRequirementType reqType : toscaAnalyzer.getRequirementTypes()) { + if (requirement.getType().getLocalPart().equals(reqType.getName())) { + if (reqType.getRequiredCapabilityType().getLocalPart().equals(capa.getType().getLocalPart()) + && reqType.getRequiredCapabilityType().getNamespaceURI().equals(capa.getType().getNamespaceURI())) { + fulfilled = true; + } + } + } + } + } + } + if (!fulfilled) { + unfulfilledRequirements.put(requirement, nodeTemplate); + } + } + } + } + } + return unfulfilledRequirements; + } +} diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/analyzer/TOSCAAnalyzer.java b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/analyzer/TOSCAAnalyzer.java new file mode 100644 index 0000000..45131a7 --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/analyzer/TOSCAAnalyzer.java @@ -0,0 +1,146 @@ +/******************************************************************************* + * 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 + *******************************************************************************/ + +package org.eclipse.winery.topologymodeler.addons.topologycompleter.analyzer; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.winery.model.tosca.TEntityTemplate; +import org.eclipse.winery.model.tosca.TNodeTemplate; +import org.eclipse.winery.model.tosca.TNodeType; +import org.eclipse.winery.model.tosca.TRelationshipTemplate; +import org.eclipse.winery.model.tosca.TRelationshipType; +import org.eclipse.winery.model.tosca.TRequirement; +import org.eclipse.winery.model.tosca.TRequirementType; +import org.eclipse.winery.model.tosca.TTopologyTemplate; + +/** + * This class contains several methods to analyze the content of a TOSCA {@link TTopologyTemplate} and to fill a data model + * with the analyzed information. This class serves the access to all types and templates of a topology. + */ +public class TOSCAAnalyzer { + + // lists containing the elements of a topology + List nodeTemplates = new ArrayList(); + List relationshipTemplates = new ArrayList(); + List requirements = new ArrayList(); + + List nodeTypes; + List relationshipTypes; + List requirementTypes; + + /** + * This method analyzes the TOSCA {@link TTopologyTemplate} for {@link TNodeTemplate}s, {@link TRelationshipTemplate}s + * and existing {@link TRequirement}s and adds them to a list. + * + * @param topology + * the TOSCA {@link TTopologyTemplate} + */ + public void analyzeTOSCATopology(TTopologyTemplate topology) { + + // fill the data model with content of the topology + List templateNodes = topology.getNodeTemplateOrRelationshipTemplate(); + + for (TEntityTemplate entityTemplate : templateNodes) { + if (entityTemplate instanceof TNodeTemplate) { + // add the node templates and their requirements to the data model + nodeTemplates.add((TNodeTemplate) entityTemplate); + if (((TNodeTemplate) entityTemplate).getRequirements() != null) { + requirements.addAll(((TNodeTemplate) entityTemplate).getRequirements().getRequirement()); + } + } else if (entityTemplate instanceof TRelationshipTemplate) { + // add RelationshipTemplates + relationshipTemplates.add((TRelationshipTemplate) entityTemplate); + } + } + } + + /** + * Setter for the types received from the Winery repository. + * + * @param nodeTypeXMLStrings + * a list of {@link TNodeType}s from the Winery repository + * @param relationshipTypeXMLStrings + * a list of {@link TRelationshipType}s from the Winery repository + * @param requirementTypeList + * a list of {@link TRequirementType}s from the Winery repository + */ + public void setTypes(List nodeTypes, List relationshipTypes, List requirementTypes) { + this.nodeTypes = nodeTypes; + this.relationshipTypes = relationshipTypes; + this.requirementTypes = requirementTypes; + } + + /** + * Returns the {@link TNodeTemplate}s of the topology. + * + * @return the {@link TNodeTemplate}s as a list + */ + public List getNodeTemplates() { + return nodeTemplates; + } + + /** + * Returns the {@link TRelationshipTemplate}s of the topology. + * + * @return the {@link TRelationshipTemplate}s as a list + */ + public List getRelationshipTemplates() { + return relationshipTemplates; + } + + /** + * Returns the {@link TRequirement}s of the topology. + * + * @return the {@link TRequirement}s as a list + */ + public List getRequirements() { + return requirements; + } + + /** + * Returns the {@link TRelationshipType}s of the topology. + * + * @return the {@link TRelationshipType}s as a list + */ + public List getRelationshipTypes() { + return relationshipTypes; + } + + /** + * Returns the {@link TNodeType}s of the topology. + * + * @return the {@link TNodeType}s as a list + */ + public List getNodeTypes() { + return nodeTypes; + } + + /** + * Returns the {@link TRequirementType}s of the topology. + * + * @return the {@link TRequirementType}s as a list + */ + public List getRequirementTypes() { + return requirementTypes; + } + + /** + * Clears all the templates from the data model before the analysis of a topology is restarted. + */ + public void clear() { + nodeTemplates.clear(); + relationshipTemplates.clear(); + requirements.clear(); + } +} diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/analyzer/package-info.java b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/analyzer/package-info.java new file mode 100644 index 0000000..5333b5e --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/analyzer/package-info.java @@ -0,0 +1,17 @@ +/******************************************************************************* + * 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 + *******************************************************************************/ + +/** + * This package contains classes and methods to analyze a TOSCA {@link org.opentosca.model.tosca.TTopologyTemplate} for its content. + */ +package org.eclipse.winery.topologymodeler.addons.topologycompleter.analyzer; + diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/helper/Constants.java b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/helper/Constants.java new file mode 100644 index 0000000..e45c11a --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/helper/Constants.java @@ -0,0 +1,89 @@ +/******************************************************************************* + * 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 + *******************************************************************************/ + +package org.eclipse.winery.topologymodeler.addons.topologycompleter.helper; + +import javax.xml.namespace.QName; + +import org.eclipse.winery.topologymodeler.addons.topologycompleter.topologycompletion.CompletionInterface; + +/** + * This class contains several constants used by the completion add-on. + */ +public class Constants { + + /** + * Constant for the QName of the "deferred" type. + */ + public static final QName DEFERRED_QNAME = new QName("http://www.opentosca.org", "deferred"); + + /** + * Constant for the QName of the "PlaceHolder" type. + */ + public static final QName PLACE_HOLDER_QNAME = new QName("http://www.opentosca.org", "PlaceHolder"); + + /** + * Contains possible types of expandable place holders. + */ + public enum PlaceHolders { + WEBSERVER, DATABASE, OPERATINGSYSTEM, CLOUDPROVIDER; + + /** + * Overwritten toString() method to return formatted strings. + */ + public String toString() { + + switch (this) { + case WEBSERVER: + return "Webserver"; + case DATABASE: + return "Database"; + case OPERATINGSYSTEM: + return "OperatingSystem"; + case CLOUDPROVIDER: + return "CloudProvider"; + default: + return null; + } + } + } + + /** + * The messages returned by the {@link CompletionInterface} + */ + public enum CompletionMessages { + TOPOLOGYCOMPLETE, USERINTERACTION, STEPBYSTEP, SUCCESS, USERTOPOLOGYSELECTION, FAILURE; + + /** + * Overwritten toString() method to return formatted strings. + */ + public String toString() { + + switch (this) { + case TOPOLOGYCOMPLETE: + return "topologyComplete"; + case USERINTERACTION: + return "userInteraction"; + case STEPBYSTEP: + return "stepByStep"; + case SUCCESS: + return "success"; + case USERTOPOLOGYSELECTION: + return "userTopologySelection"; + case FAILURE: + return "failure"; + default: + return null; + } + } + } +} diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/helper/JAXBHelper.java b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/helper/JAXBHelper.java new file mode 100644 index 0000000..84a3e28 --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/helper/JAXBHelper.java @@ -0,0 +1,374 @@ +/******************************************************************************* + * 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 + *******************************************************************************/ + +package org.eclipse.winery.topologymodeler.addons.topologycompleter.helper; + +import java.io.IOException; +import java.io.StringReader; +import java.io.StringWriter; +import java.util.ArrayList; +import java.util.List; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBElement; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Marshaller; +import javax.xml.bind.Unmarshaller; + +import org.eclipse.winery.common.ModelUtilities; +import org.eclipse.winery.common.Util; +import org.eclipse.winery.model.tosca.Definitions; +import org.eclipse.winery.model.tosca.TDefinitions; +import org.eclipse.winery.model.tosca.TEntityTemplate; +import org.eclipse.winery.model.tosca.TNodeTemplate; +import org.eclipse.winery.model.tosca.TRelationshipTemplate; +import org.eclipse.winery.model.tosca.TRelationshipTemplate.SourceElement; +import org.eclipse.winery.model.tosca.TServiceTemplate; +import org.eclipse.winery.model.tosca.TTopologyTemplate; +import org.slf4j.LoggerFactory; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.type.TypeFactory; + +/** + * This class contains methods for marshalling and unmarshalling a topology XML string via JAXB. + * + */ +public class JAXBHelper { + + private static final org.slf4j.Logger logger = LoggerFactory.getLogger(JAXBHelper.class.getName()); + + /** + * This constant is used in the buildXML method which add coordinates to Node Templates so they + * are arranged properly in the Winery topology modeler. + * + * The x coordinate is constant because it is assumed that a stack of NodeTemplates is displayed. + */ + private static final String NODETEMPLATE_X_COORDINATE = "500"; + + /** + * This method creates an JAXB Unmarshaller used by the methods contained in this class. + * + * @return the JAXB unmarshaller object + * + * @throws JAXBException + * this exception can occur when the JAXBContext is created + */ + private static Unmarshaller createUnmarshaller() throws JAXBException { + // initiate JaxB context + JAXBContext context; + context = JAXBContext.newInstance(Definitions.class); + + return context.createUnmarshaller(); + } + + /** + * This method returns a {@link TTopologyTemplate} given as XML string as JaxBObject. + * + * @param xmlString + * the {@link TTopologyTemplate} to be unmarshalled + * + * @return the unmarshalled {@link TTopologyTemplate} + */ + public static TTopologyTemplate getTopologyAsJaxBObject(String xmlString) { + try { + + logger.info("Getting Definitions Document..."); + + StringReader reader = new StringReader(xmlString); + + // unmarshall the XML string + Definitions jaxBDefinitions = (Definitions) createUnmarshaller().unmarshal(reader); + TServiceTemplate serviceTemplate = (TServiceTemplate) jaxBDefinitions.getServiceTemplateOrNodeTypeOrNodeTypeImplementation().get(0); + + logger.info("Unmarshalling successful! "); + + return serviceTemplate.getTopologyTemplate(); + + } catch (JAXBException e) { + logger.error(e.getLocalizedMessage()); + } + return null; + } + + /** + * This method returns {@link TRelationshipTemplate}s as a JaxBObject. + * + * @param xmlString + * the {@link TRelationshipTemplate} to be unmarshalled + * + * @return the unmarshalled {@link TRelationshipTemplate} + */ + public static List getRelationshipTemplatesAsJaxBObject(String xmlString) { + try { + StringReader reader = new StringReader(xmlString); + + // unmarshall + Definitions jaxBDefinitions = (Definitions) createUnmarshaller().unmarshal(reader); + TServiceTemplate serviceTemplate = (TServiceTemplate) jaxBDefinitions.getServiceTemplateOrNodeTypeOrNodeTypeImplementation().get(0); + + List foundRTs = new ArrayList<>(); + for (TEntityTemplate entity : serviceTemplate.getTopologyTemplate().getNodeTemplateOrRelationshipTemplate()) { + if (entity instanceof TRelationshipTemplate) { + foundRTs.add((TRelationshipTemplate) entity); + } + } + + return foundRTs; + + } catch (JAXBException e) { + logger.error(e.getLocalizedMessage()); + } + return null; + + } + + /** + * Turns XML Strings into {@link TEntityTemplate} objects using JaxB. + * + * @param xmlString + * the XMLString to be parsed + * @return the parsed XMLString as {@link TEntityTemplate} + */ + public static List getEntityTemplatesAsJaxBObject(String xmlString) { + try { + StringReader reader = new StringReader(xmlString); + + Definitions jaxBDefinitions = (Definitions) createUnmarshaller().unmarshal(reader); + TServiceTemplate serviceTemplate = (TServiceTemplate) jaxBDefinitions.getServiceTemplateOrNodeTypeOrNodeTypeImplementation().get(0); + + return serviceTemplate.getTopologyTemplate().getNodeTemplateOrRelationshipTemplate(); + + } catch (JAXBException e) { + logger.error(e.getLocalizedMessage()); + } + return null; + + } + + /** + * Converts any object of the TOSCA data model to a JaxBObject. + * + * @param xmlString + * the {@link Definitions} object to be converted + * + * @return the unmarshalled {@link Definitions} object + */ + public static Definitions getXasJaxBObject(String xmlString) { + try { + StringReader reader = new StringReader(xmlString); + Definitions jaxBDefinitions = (Definitions) createUnmarshaller().unmarshal(reader); + + return jaxBDefinitions; + + } catch (JAXBException e) { + logger.error(e.getLocalizedMessage()); + } + return null; + + } + + /** + * This method adds a selection of {@link TNodeTemplate}- and {@link TRelationshipTemplate}-XML-Strings to a {@link TTopologyTemplate}-XML-String using JAXB. + * After the templates have been added, the {@link TTopologyTemplate} object is re-marshalled to an XML-String. + * + * This method is called by the selectionHandler.jsp after several Node or RelationshipTemplates have been chosen in a dialog. + * + * @param topology + * the topology as XML string + * @param allTemplateChoicesAsXML + * all possible template choices as TOSCA-XML strings containing the complete templates + * @param selectedNodeTemplatesAsJSON + * the names of the selected NodeTemplates as JSONArray + * @param selectedRelationshipTemplatesAsJSON + * the names of the selected RelationshipTemplates as JSONArray + * + * @return the complete topology XML string + */ + public static String addTemplatesToTopology(String topology, String allTemplateChoicesAsXML, String selectedNodeTemplatesAsJSON, String selectedRelationshipTemplatesAsJSON) { + try { + + // initialization code for the jackson types used to convert JSON string arrays to a java.util.List + ObjectMapper mapper = new ObjectMapper(); + TypeFactory factory = mapper.getTypeFactory(); + + // convert the JSON array containing the names of the selected RelationshipTemplates to a java.util.List + List selectedRelationshipTemplates = mapper.readValue(selectedRelationshipTemplatesAsJSON, factory.constructCollectionType(List.class, String.class)); + + // convert the topology and the choices to objects using JAXB + TTopologyTemplate topologyTemplate = getTopologyAsJaxBObject(topology); + List allTemplateChoices = getEntityTemplatesAsJaxBObject(allTemplateChoicesAsXML); + + // this distinction of cases is necessary because it is possible that only RelationshipTemplates have been selected + if (selectedNodeTemplatesAsJSON != null) { + + // convert the JSON string array containing the names of the selected NodeTemplates to a java.util.List + List selectedNodeTemplates = mapper.readValue(selectedNodeTemplatesAsJSON, factory.constructCollectionType(List.class, String.class)); + + // search the selected NodeTemplate in the List of all choices by its name to receive its object which will ne added to the topology + for (String nodeTemplateName : selectedNodeTemplates) { + for (TEntityTemplate choice : allTemplateChoices) { + if (choice instanceof TNodeTemplate) { + TNodeTemplate nodeTemplate = (TNodeTemplate) choice; + // matching a name is usually unsafe because the uniqueness cannot be assured, + // however similar names are not possible at this location due to the implementation of the selection dialogs + if (nodeTemplateName.equals(nodeTemplate.getName())) { + // add the selected NodeTemplate to the topology + topologyTemplate.getNodeTemplateOrRelationshipTemplate().add(nodeTemplate); + + // due to the mapping of IDs in the selection dialog, the corresponding Relationship Template of the inserted Node Template misses its SourceElement. + // Re-add it to avoid errors. + for (TEntityTemplate entity: topologyTemplate.getNodeTemplateOrRelationshipTemplate()) { + if (entity instanceof TRelationshipTemplate) { + TRelationshipTemplate relationshipTemplate = (TRelationshipTemplate) entity; + if (relationshipTemplate.getSourceElement().getRef() == null) { + // connect to the added NodeTemplate + SourceElement sourceElement = new SourceElement(); + sourceElement.setRef(nodeTemplate); + relationshipTemplate.setSourceElement(sourceElement); + } + } + } + } + } + } + } + + // now search and add the selected RelationshipTemplate object connecting to the inserted NodeTemplate + for (String relationshipTemplateName : selectedRelationshipTemplates) { + for (TEntityTemplate toBeAdded : allTemplateChoices) { + if (toBeAdded instanceof TRelationshipTemplate) { + TRelationshipTemplate relationshipTemplate = (TRelationshipTemplate) toBeAdded; + if (relationshipTemplateName.equals(relationshipTemplate.getName())) { + topologyTemplate.getNodeTemplateOrRelationshipTemplate().add(relationshipTemplate); + } + } + } + } + + } else { + // in this case only Relationship Templates have been selected + List allRelationshipTemplateChoices = JAXBHelper.getRelationshipTemplatesAsJaxBObject(allTemplateChoicesAsXML); + + // add the target Node Template to the topology which is unique due to the implementation of the selection dialog + topologyTemplate.getNodeTemplateOrRelationshipTemplate().add((TNodeTemplate) ((TRelationshipTemplate) allRelationshipTemplateChoices.get(0)).getTargetElement().getRef()); + + // search the JAXB object of the selected RelationshipTemplate and add it to the topology + for (String relationshipTemplateName : selectedRelationshipTemplates) { + for (TRelationshipTemplate choice : allRelationshipTemplateChoices) { + if (relationshipTemplateName.equals(choice.getName())) { + topologyTemplate.getNodeTemplateOrRelationshipTemplate().add(choice); + } + } + } + + for (TEntityTemplate entityTemplate : topologyTemplate.getNodeTemplateOrRelationshipTemplate()) { + if (entityTemplate instanceof TRelationshipTemplate) { + TRelationshipTemplate relationship = (TRelationshipTemplate) entityTemplate; + + // due to the mapping of IDs in the selection dialog, the corresponding Relationship Template of the inserted Node Template misses its SourceElement. + // Re-add it to avoid errors. + if (relationship.getSourceElement().getRef() == null) { + relationship.getSourceElement().setRef((TNodeTemplate) ((TRelationshipTemplate) allRelationshipTemplateChoices.get(0)).getTargetElement().getRef()); + } + } + } + } + + // re-convert the topology from a JAXB object to an XML string and return it + Definitions definitions = new Definitions(); + TServiceTemplate st = new TServiceTemplate(); + st.setTopologyTemplate(topologyTemplate); + definitions.getServiceTemplateOrNodeTypeOrNodeTypeImplementation().add(st); + JAXBContext context = JAXBContext.newInstance(Definitions.class); + Marshaller m = context.createMarshaller(); + StringWriter stringWriter = new StringWriter(); + + m.marshal(definitions, stringWriter); + + return stringWriter.toString(); + + } catch (JAXBException | IOException e) { + logger.error(e.getLocalizedMessage()); + } + + return null; + } + + + /** + * Marshalls a JAXB object of the TOSCA model to an XML string. + * + * @param clazz + * the class of the object + * @param obj + * the object to be marshalled + * + * @return + */ + public static String getXMLAsString(@SuppressWarnings("rawtypes") Class clazz, Object obj) { + try { + @SuppressWarnings("rawtypes") + JAXBElement rootElement = Util.getJAXBElement(clazz, obj); + JAXBContext context = JAXBContext.newInstance(TDefinitions.class); + Marshaller m; + + m = context.createMarshaller(); + + StringWriter w = new StringWriter(); + m.marshal(rootElement, w); + String res = w.toString(); + + return res; + } catch (JAXBException e) { + logger.error(e.getLocalizedMessage()); + } + return null; + } + + /** + * This methods alters the XML with JAXB so it can be imported in Winery. This is necessary because Winery needs additional information for the position of the templates in the + * Winery-Modeler-UI. + * + * This code is adapted from the org.eclipse.winery.repository.Utils.getXMLAsString() method. + * + * @param topology + * the {@link TTopologyTemplate} to be altered + * + * @return the altered {@link TTopologyTemplate} + */ + public static TTopologyTemplate buildXML(TTopologyTemplate topology) { + + // the coordinate of the NodeTemplate in Winery. Begin 100 pixel from the top to improve arrangement. + int yCoordinates = 100; + + for (TEntityTemplate template : topology.getNodeTemplateOrRelationshipTemplate()) { + // add node templates + if (template instanceof TNodeTemplate) { + + TNodeTemplate nodeTemplate = (TNodeTemplate) template; + + // remove the Requirements tag if necessary + if (nodeTemplate.getRequirements() != null && nodeTemplate.getRequirements().getRequirement() == null) { + nodeTemplate.setRequirements(null); + } + + ModelUtilities.setLeft(nodeTemplate, NODETEMPLATE_X_COORDINATE); + ModelUtilities.setTop(nodeTemplate, Integer.toString(yCoordinates)); + + yCoordinates += 150; + } + } + + return topology; + } +} diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/helper/NodeTemplateConnector.java b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/helper/NodeTemplateConnector.java new file mode 100644 index 0000000..f1d4b6b --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/helper/NodeTemplateConnector.java @@ -0,0 +1,86 @@ +/******************************************************************************* + * 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 + *******************************************************************************/ + +package org.eclipse.winery.topologymodeler.addons.topologycompleter.helper; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.winery.model.tosca.TCapability; +import org.eclipse.winery.model.tosca.TNodeTemplate; +import org.eclipse.winery.model.tosca.TRelationshipType; +import org.eclipse.winery.model.tosca.TRequirement; +import org.eclipse.winery.topologymodeler.addons.topologycompleter.analyzer.TOSCAAnalyzer; + +/** + * This class searches a {@link TRelationshipType} which is able to connect two given {@link TNodeTemplate}s. + * + */ +public class NodeTemplateConnector { + + /** + * Searches a compatible {@link TRelationshipType} to connect two {@link TNodeTemplate}s. + * + * @param source + * the source {@link TNodeTemplate} + * @param target + * the target {@link TNodeTemplate} + * @param toscaAnalyzer + * the {@link TOSCAAnalyzer} object to access the data model + * @param requirement + * the {@link TRequirement} of the source {@link TNodeTemplate} + * + * @return a list of suitable {@link TRelationshipType}s + */ + public static List findRelationshipType(TNodeTemplate source, TNodeTemplate target, TOSCAAnalyzer toscaAnalyzer, TRequirement requirement) { + + List suitableRelationshipTypes = new ArrayList(); + List allRelationshipTypes = toscaAnalyzer.getRelationshipTypes(); + + // in case the connection to a placeholder is searched, no requirement exists + if (requirement != null) { + + List capabilities = target.getCapabilities().getCapability(); + + // check if a RelationshipType can connect a requirement of the source NodeTemplate to a capability of the target NodeTemplate + for (TRelationshipType relationshipType : allRelationshipTypes) { + if (relationshipType.getValidSource() != null && relationshipType.getValidTarget() != null) { + for (TCapability capability : capabilities) { + if ((relationshipType.getValidSource().getTypeRef().equals(requirement.getType()) && relationshipType.getValidTarget().getTypeRef().equals(capability.getType()))) { + suitableRelationshipTypes.add(relationshipType); + } + } + } + } + } + + // to extend the selection check if a RelationshipType can connect the type of the source NodeTemplate to the type of the target NodeTemplate + for (TRelationshipType rt : allRelationshipTypes) { + if (rt.getValidSource() != null && rt.getValidTarget() != null) { + if ((rt.getValidSource().getTypeRef().equals(source.getType()) && rt.getValidTarget().getTypeRef().equals(target.getType()))) { + suitableRelationshipTypes.add(rt); + } + } + } + + // in case no suitable relationship type could be found, search for generic types without the optional ValidSource / ValidTarget elements. + if (suitableRelationshipTypes.isEmpty()) { + for (TRelationshipType rt : allRelationshipTypes) { + if (rt.getValidSource() == null && rt.getValidTarget() == null) { + suitableRelationshipTypes.add(rt); + } + } + } + + return suitableRelationshipTypes; + } +} diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/helper/RESTHelper.java b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/helper/RESTHelper.java new file mode 100644 index 0000000..789d529 --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/helper/RESTHelper.java @@ -0,0 +1,97 @@ +/******************************************************************************* + * 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 + *******************************************************************************/ + +package org.eclipse.winery.topologymodeler.addons.topologycompleter.helper; + +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.net.HttpURLConnection; +import java.net.URL; + + +import org.eclipse.winery.common.Util; +import org.eclipse.winery.model.tosca.TTopologyTemplate; +import org.slf4j.LoggerFactory; + +/** + * This class contains helper methods to call the REST API and PUT/POST information to it. + */ +public class RESTHelper { + + private static final org.slf4j.Logger logger = LoggerFactory.getLogger(RESTHelper.class.getName()); + + /** + * This method uses a REST call to save the completed {@link TTopologyTemplate} to the repository. + * + * @param topology + * the {@link TTopologyTemplate} to be saved + * @param topologyTemplateURL + * the URL the {@link TTopologyTemplate} is saved to + * @param overwriteTopology + * whether the topology is overwritten or a new topology shall be created + * @param topologyName + * the name of the newly created topology to build the URL if a new topology shall be created + * @param topologyNamespace + * the name space of the newly created topology to build the URL if a new topology shall be created + * @param repositoryURL + * the URL to the repository to build the URL if a new topology shall be created + */ + public static void saveCompleteTopology(TTopologyTemplate topology, String topologyTemplateURL, boolean overwriteTopology, String topologyName, String topologyNamespace, String repositoryURL) { + try { + + URL url = null; + + if (overwriteTopology) { + url = new URL(topologyTemplateURL); + } else { + // this is necessary to avoid encoding issues + topologyNamespace = Util.DoubleURLencode(topologyNamespace); + // build the URL with the repositoryURL, the topology namespace and the topology name + url = new URL(repositoryURL + "/servicetemplates/" + topologyNamespace + "/" + topologyName + "/topologytemplate/"); + + logger.info("The URL the topology is saved to: " + url); + } + + // using SSL + System.setProperty("javax.net.ssl.trustStore", "jssecacerts.cert"); + + // configure message + HttpURLConnection urlConn; + urlConn = (HttpURLConnection) url.openConnection(); + + logger.info("Sending HTTP request..."); + + urlConn.setDoOutput(true); + urlConn.setRequestMethod("PUT"); + urlConn.setRequestProperty("Content-type", "text/xml"); + OutputStreamWriter out = new OutputStreamWriter(urlConn.getOutputStream()); + + // build the XML string to be saved + TTopologyTemplate outputTopology = JAXBHelper.buildXML(topology); + String outputString = JAXBHelper.getXMLAsString(outputTopology.getClass(), outputTopology); + + logger.info(outputString); + logger.info("Sending output to Winery."); + + out.write(outputString); + out.close(); + urlConn.getOutputStream().close(); + logger.info("Output sent, waiting for response..."); + urlConn.getInputStream(); + + logger.info("HTTP Response Code is: " + urlConn.getResponseCode()); + + } catch (IOException e) { + logger.error(e.getLocalizedMessage()); + } + } +} diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/helper/Utils.java b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/helper/Utils.java new file mode 100644 index 0000000..5f9826b --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/helper/Utils.java @@ -0,0 +1,127 @@ +/******************************************************************************* + * 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 + *******************************************************************************/ + +package org.eclipse.winery.topologymodeler.addons.topologycompleter.helper; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +import javax.xml.namespace.QName; + +import org.eclipse.winery.model.tosca.TCapabilityDefinition; +import org.eclipse.winery.model.tosca.TNodeTemplate; +import org.eclipse.winery.model.tosca.TNodeType; +import org.eclipse.winery.model.tosca.TRequirement; +import org.eclipse.winery.model.tosca.TRequirementType; +import org.eclipse.winery.model.tosca.TTopologyTemplate; +import org.eclipse.winery.topologymodeler.addons.topologycompleter.analyzer.TOSCAAnalyzer; +import org.slf4j.LoggerFactory; + +/** + * Contains methods to match requirements and capabilities and find elements in the {@link TTopologyTemplate} + */ +public class Utils { + + private static final org.slf4j.Logger logger = LoggerFactory.getLogger(Utils.class.getName()); + + /** + * This method searches {@link TNodeType}s in the repository that match a requirement. + * + * @param requirement + * the requirement to be matched + * @param toscaAnalyzer + * the {@link TOSCAAnalyzer} object to access the data model + * + * @return a list of the matched {@link TNodeType}s + */ + public static List matchRequirementAndCapability(TRequirement requirement, TOSCAAnalyzer toscaAnalyzer) { + + List possibleNodeTypes = new ArrayList(); + + // find all matching Node Types for a requirement by the "requiredCapabilityType" attribute of its type + for (TRequirementType requirementType : toscaAnalyzer.getRequirementTypes()) { + if (requirementType.getName().equals(requirement.getType().getLocalPart())) { + + QName requiredCapabilityType = requirementType.getRequiredCapabilityType(); + for (TNodeType nodeType : toscaAnalyzer.getNodeTypes()) { + if (nodeType.getCapabilityDefinitions() != null) { + for (TCapabilityDefinition cd : nodeType.getCapabilityDefinitions().getCapabilityDefinition()) { + if (cd.getCapabilityType().getLocalPart().equals(requiredCapabilityType.getLocalPart())) { + possibleNodeTypes.add(nodeType); + } + } + } + } + } + } + + return possibleNodeTypes; + } + + /** + * Generates a random {@link UUID} exclusively used by the {@link TemplateBuilder}. + * + * @return the generated {@link UUID} id + */ + public static String createRandomID() { + return UUID.randomUUID().toString(); + } + + /** + * Returns a {@link TNodeTemplate} for a given Id. + * + * @param nodeTemplates + * all the {@link TNodeTemplate} in the {@link TTopologyTemplate} + * @param id + * the id of the {@link TNodeTemplate} to be found + * + * @return the found {@link TNodeTemplate} or null if not found + */ + public static TNodeTemplate getNodeTemplateForId(List nodeTemplates, String id) { + + for (TNodeTemplate nt : nodeTemplates) { + + if (nt.getId().equals(id)) { + return nt; + } + } + + logger.error("No NodeTemplate with " + id + " exists"); + + return null; + + } + + /** + * Returns a {@link TNodeType} for a given Id. + * + * @param nodeTypes + * All the {@link TNodeType} in the {@link TTopologyTemplate} + * @param Id + * The id of the {@link TNodeType} to be searched + * @return the {@link TNodeType} or null if not found + */ + public static TNodeType getNodeTypeForId(List nodeTypes, QName id) { + + for (TNodeType nodeType : nodeTypes) { + if (nodeType.getName().equals(id.getLocalPart()) && nodeType.getTargetNamespace().equals(id.getNamespaceURI())) { + return nodeType; + } + } + + logger.error("No NodeType with " + id + " exists"); + + // no type could be found for the given ID, this case cannot occur if the topology was modelled in the Winery Topology Modeler + return null; + } +} diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/helper/package-info.java b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/helper/package-info.java new file mode 100644 index 0000000..5d42210 --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/helper/package-info.java @@ -0,0 +1,17 @@ +/******************************************************************************* + * 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 + *******************************************************************************/ + +/** + * This package contains helper classes and methods to assist the completion. + */ +package org.eclipse.winery.topologymodeler.addons.topologycompleter.helper; + diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/package-info.java b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/package-info.java new file mode 100644 index 0000000..19e334e --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/package-info.java @@ -0,0 +1,16 @@ +/******************************************************************************* + * 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 + *******************************************************************************/ + +/** + * this package contains classes to complete a topology template + */ +package org.eclipse.winery.topologymodeler.addons.topologycompleter; \ No newline at end of file diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/placeholderhandling/PlaceHolderHandler.java b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/placeholderhandling/PlaceHolderHandler.java new file mode 100644 index 0000000..a384e91 --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/placeholderhandling/PlaceHolderHandler.java @@ -0,0 +1,74 @@ +/******************************************************************************* + * 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 + *******************************************************************************/ + +package org.eclipse.winery.topologymodeler.addons.topologycompleter.placeholderhandling; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.winery.model.tosca.TNodeTemplate; +import org.eclipse.winery.model.tosca.TNodeType; +import org.eclipse.winery.topologymodeler.addons.topologycompleter.analyzer.TOSCAAnalyzer; +import org.eclipse.winery.topologymodeler.addons.topologycompleter.helper.Constants; + +/** + * This class finds suitable replacement types for a place holder. + */ +public class PlaceHolderHandler { + + /** + * This method returns a suitable {@link TNodeType} to replace a given {@link TNodeTemplate} placeholder. + * A suitable Node Type to replace a placeholder is matched by its type. If the type of a NodeType equals the identifier of a placeholder + * it can be used to replace it. + * + * @param nodeTemplate + * the placeholder to be replaced + * @param toscaAnalyzer + * the {@link TOSCAAnalyzer} object to access the data model + * + * @return a list of {@link TNodeType}s to replace the placeholder + */ + public static List getSuitableNodeTypes(TNodeTemplate nodeTemplate, TOSCAAnalyzer toscaAnalyzer) { + + List suitableNodeTypes = new ArrayList<>(); + + // TODO: matching the name without a name space is unsafe and only works assuming that no one creates generic NodeTemplates with the same name as the place holders. + // However a NodeTemplate name does not have a name space. + if (nodeTemplate.getName().equals(Constants.PlaceHolders.WEBSERVER.toString())) { + for (TNodeType nodeType : toscaAnalyzer.getNodeTypes()) { + if (nodeType.getDerivedFrom() != null && nodeType.getDerivedFrom().getTypeRef().getLocalPart().equals(Constants.PlaceHolders.WEBSERVER.toString())) { + suitableNodeTypes.add(nodeType); + } + } + } else if (nodeTemplate.getName().equals(Constants.PlaceHolders.DATABASE.toString())) { + for (TNodeType nodeType : toscaAnalyzer.getNodeTypes()) { + if (nodeType.getDerivedFrom() != null && nodeType.getDerivedFrom().getTypeRef().getLocalPart().equals(Constants.PlaceHolders.DATABASE.toString())) { + suitableNodeTypes.add(nodeType); + } + } + } else if (nodeTemplate.getName().equals(Constants.PlaceHolders.OPERATINGSYSTEM.toString())) { + for (TNodeType nodeType : toscaAnalyzer.getNodeTypes()) { + if (nodeType.getDerivedFrom() != null && nodeType.getDerivedFrom().getTypeRef().getLocalPart().equals(Constants.PlaceHolders.OPERATINGSYSTEM.toString())) { + suitableNodeTypes.add(nodeType); + } + } + } else if (nodeTemplate.getName().equals(Constants.PlaceHolders.CLOUDPROVIDER.toString())) { + for (TNodeType nodeType : toscaAnalyzer.getNodeTypes()) { + if (nodeType.getDerivedFrom() != null && nodeType.getDerivedFrom().getTypeRef().getLocalPart().equals(Constants.PlaceHolders.CLOUDPROVIDER.toString())) { + suitableNodeTypes.add(nodeType); + } + } + } + + return suitableNodeTypes; + } +} diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/topologycompletion/CompletionInterface.java b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/topologycompletion/CompletionInterface.java new file mode 100644 index 0000000..e46d3b1 --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/topologycompletion/CompletionInterface.java @@ -0,0 +1,257 @@ +/******************************************************************************* + * 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 + *******************************************************************************/ + +package org.eclipse.winery.topologymodeler.addons.topologycompleter.topologycompletion; + +import java.util.List; +import java.util.Map; + +import org.eclipse.winery.model.tosca.TEntityTemplate; +import org.eclipse.winery.model.tosca.TNodeTemplate; +import org.eclipse.winery.model.tosca.TNodeType; +import org.eclipse.winery.model.tosca.TRelationshipTemplate; +import org.eclipse.winery.model.tosca.TRelationshipType; +import org.eclipse.winery.model.tosca.TRequirementType; +import org.eclipse.winery.model.tosca.TTopologyTemplate; +import org.eclipse.winery.repository.client.IWineryRepositoryClient; +import org.eclipse.winery.repository.client.WineryRepositoryClientFactory; +import org.eclipse.winery.topologymodeler.addons.topologycompleter.analyzer.DeferredAnalyzer; +import org.eclipse.winery.topologymodeler.addons.topologycompleter.analyzer.PlaceHolderAnalyzer; +import org.eclipse.winery.topologymodeler.addons.topologycompleter.analyzer.RequirementAnalyzer; +import org.eclipse.winery.topologymodeler.addons.topologycompleter.analyzer.TOSCAAnalyzer; +import org.eclipse.winery.topologymodeler.addons.topologycompleter.helper.Constants; +import org.eclipse.winery.topologymodeler.addons.topologycompleter.helper.JAXBHelper; +import org.eclipse.winery.topologymodeler.addons.topologycompleter.helper.RESTHelper; +import org.slf4j.LoggerFactory; + +/** + * This class is the entry point of the TOSCA topology completion which is called by the Winery Topology Modeler. + * It receives an incomplete {@link TTopologyTemplate} from Winery. + * The completion of the incomplete {@link TTopologyTemplate} is managed by this class. + */ +public class CompletionInterface { + + /** + * Logger for debug reasons. + */ + private static final org.slf4j.Logger logger = LoggerFactory.getLogger(CompletionInterface.class.getName()); + + /** + * This global variable is returned to the Winery Topology Modelerer via getCurrentTopology() to display intermediate results when an user interaction is necessary. + */ + private TTopologyTemplate currentTopology; + + /** + * This list contains {@link TTopologyTemplate}s to be chosen by the user when the topology solution isn't unique. + */ + private List topologyTemplateChoices; + + /** + * This List contains {@link TRelationshipTemplate}s to be chosen by the user. + */ + private List relationshipTemplateChoices; + + /** + * This Map contains {@link TNodeTemplate}s and {@link TRelationshipTemplate}s to be chosen by the user during the step-by-step approach. + */ + private Map>> nodeTemplateChoices; + + /** + * String containing an error message to be displayed in Winery if necessary. + */ + private String errorMessage = ""; + + /** + * This method receives an incomplete {@link TTopologyTemplate} and the repository content from Winery. After analyzing the {@link TTopologyTemplate}, the topology is completed. This method will + * return a message after the completion whether the completion was successful, has failed or the user has to interact. + * + * @param topology + * (XMLString) the {@link TTopologyTemplate} to be completed as XMLString + * @param serviceTemplateName + * the name of the ServiceTemplate for REST calls + * @param topologyTemplateURL + * the URL where the template is saved to + * @param overwriteTopology + * determines in which way the {@link TTopologyTemplate} is saved. The current {@link TTopologyTemplate} can either be overwritten or a new topology can be created. + * @param topologyName + * the name of the {@link TTopologyTemplate} when a new {@link TTopologyTemplate} shall be created + * @param topologyNamespace + * the namespace of the {@link TTopologyTemplate} when a new {@link TTopologyTemplate} shall be created + * @param repositoryURL + * the URL to the repository to receive and write TOSCA specific information + * @param stepByStep + * whether the topology completion is processed step-by-step or not + * @param restarted + * whether the topology completion is restarted or started for the first time + * + * @return a message to Winery that contains information whether the topology is complete, the user has to interact or an error occurred. + */ + public String complete(String topology, String serviceTemplateName, String topologyTemplateURL, Boolean overwriteTopology, + String topologyName, String topologyNamespace, String repositoryURL, boolean stepByStep, boolean restarted) { + + logger.info("Starting completion..."); + + //////////////////////////////////////// + // STEP 1: Receive topology from Winery + //////////////////////////////////////// + + logger.info("Saving to: " + topologyTemplateURL); + + logger.info("The service template to be completed is: " + serviceTemplateName); + + // receive types from repository + IWineryRepositoryClient client = WineryRepositoryClientFactory.getWineryRepositoryClient(); + client.addRepository(repositoryURL); + + List nodeTypeList = (List) client.getAllTypes(TNodeType.class); + List relationshipTypeList = (List) client.getAllTypes(TRelationshipType.class); + List requirementTypeList = (List) client.getAllTypes(TRequirementType.class); + + ///////////////////////////////////// + // Step 2: Analyze topology content + ///////////////////////////////////// + + logger.info("The modelled topology as XML: " + topology); + + TTopologyTemplate topologyTemplate = JAXBHelper.getTopologyAsJaxBObject(topology); + + logger.info("Analyzing topology..."); + + // analyze the received topology + TOSCAAnalyzer toscaAnalyzer = new TOSCAAnalyzer(); + toscaAnalyzer.analyzeTOSCATopology(topologyTemplate); + toscaAnalyzer.setTypes(nodeTypeList, relationshipTypeList, requirementTypeList); + + // if the topology is already complete, a message is displayed + if (checkCompletnessOfTopology(toscaAnalyzer) && !restarted) { + return Constants.CompletionMessages.TOPOLOGYCOMPLETE.toString(); + } else { + + ///////////////////////////////////////// + // Step 3: Invoke the topology completion + ///////////////////////////////////////// + logger.info("Invoking Topology Completion..."); + + CompletionManager completionManager = new CompletionManager(toscaAnalyzer, stepByStep); + List completedTopology = completionManager.manageCompletion(topologyTemplate); + + // the user has to interact by choosing a RelationshipTemplate, send message to Winery which will display a dialog + if (completionManager.getUserInteraction() && !stepByStep) { + currentTopology = completedTopology.get(0); + relationshipTemplateChoices = completionManager.getChoices(); + + return Constants.CompletionMessages.USERINTERACTION.toString(); + + } else if (completionManager.getNodeTemplateUserInteraction() && stepByStep) { + // the topology completion is processed Step-by-Step, the user has to choose Node and RelationshipTemplates to be inserted + currentTopology = completedTopology.get(0); + nodeTemplateChoices = completionManager.getTemplateChoices(); + + for (TNodeTemplate nodeTemplate : nodeTemplateChoices.keySet()) { + Map> entityTemplates = nodeTemplateChoices.get(nodeTemplate); + + for (TNodeTemplate entity : entityTemplates.keySet()) { + for (TEntityTemplate relationshipTemplate : entityTemplates.get(entity)) { + // remove entity that has to be chosen next + if (currentTopology.getNodeTemplateOrRelationshipTemplate().contains(relationshipTemplate)) { + currentTopology.getNodeTemplateOrRelationshipTemplate().remove(relationshipTemplate); + } else if (currentTopology.getNodeTemplateOrRelationshipTemplate().contains(entity)) { + currentTopology.getNodeTemplateOrRelationshipTemplate().remove(entity); + } + } + } + } + + return Constants.CompletionMessages.STEPBYSTEP.toString(); + } + + logger.info("Completion successful!"); + + if (completedTopology.size() == 1) { + // solution is unique, save the topology + RESTHelper.saveCompleteTopology(completedTopology.get(0), topologyTemplateURL, overwriteTopology, topologyName, topologyNamespace, repositoryURL); + return Constants.CompletionMessages.SUCCESS.toString(); + } else if (completedTopology.size() > 1) { + // if there are several topology solutions, let the user choose + this.topologyTemplateChoices = completedTopology; + return Constants.CompletionMessages.USERTOPOLOGYSELECTION.toString(); + } else { + // an error occurred + errorMessage = "Error: No suitable NodeTemplate could be found for a Requirement or PlaceHolder."; + return Constants.CompletionMessages.FAILURE.toString(); + } + } + } + + /** + * This method checks if the topology is already complete. It will be called before executing the topology completion but + * only in case the topology completion isn't restarted after a user selection. + * + * @param toscaAnalyzer + * the topology to be checked + * @return whether the topology is complete or not + */ + public boolean checkCompletnessOfTopology(TOSCAAnalyzer toscaAnalyzer) { + + if (RequirementAnalyzer.analyzeRequirements(toscaAnalyzer).isEmpty() && PlaceHolderAnalyzer.analyzePlaceHolders(toscaAnalyzer).isEmpty() + && DeferredAnalyzer.analyzeDeferredRelations(toscaAnalyzer).isEmpty()) { + return true; + } else { + return false; + } + } + + /** + * Returns the current state of the completion. + * + * @return the current {@link TTopologyTemplate} + */ + public TTopologyTemplate getCurrentTopology() { + return currentTopology; + } + + /** + * Returns the choices whenever there are several possible complete {@link TTopologyTemplate}s. They will be displayed in Winery and chosen by the user. + * + * @return the possible {@link TTopologyTemplate} choices as a list. + */ + public List getTopologyTemplateChoices() { + return topologyTemplateChoices; + } + + /** + * Returns the {@link TRelationshipTemplate} choices + * + * @return the {@link TRelationshipTemplate}s to be chosen + */ + public List getRelationshipTemplateChoices() { + return relationshipTemplateChoices; + } + + /** + * Returns several {@link TNodeTemplate} and {@link TRelationshipTemplate} choices when the user selected the step-by-step approach. + * + * @return the {@link TNodeTemplate} choices + */ + public Map>> getNodeTemplateChoices() { + return nodeTemplateChoices; + } + + /** + * Returns a message when an error occurred during the completion. + * + * @return the error message + */ + public String getErrorMessage() { + return errorMessage; + } +} diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/topologycompletion/CompletionManager.java b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/topologycompletion/CompletionManager.java new file mode 100644 index 0000000..1f47cf5 --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/topologycompletion/CompletionManager.java @@ -0,0 +1,358 @@ +/******************************************************************************* + * 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 + *******************************************************************************/ + +package org.eclipse.winery.topologymodeler.addons.topologycompleter.topologycompletion; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.logging.Logger; + +import org.eclipse.winery.model.tosca.TEntityTemplate; +import org.eclipse.winery.model.tosca.TNodeTemplate; +import org.eclipse.winery.model.tosca.TRelationshipTemplate; +import org.eclipse.winery.model.tosca.TRequirement; +import org.eclipse.winery.model.tosca.TTopologyTemplate; +import org.eclipse.winery.topologymodeler.addons.topologycompleter.analyzer.DeferredAnalyzer; +import org.eclipse.winery.topologymodeler.addons.topologycompleter.analyzer.PlaceHolderAnalyzer; +import org.eclipse.winery.topologymodeler.addons.topologycompleter.analyzer.RequirementAnalyzer; +import org.eclipse.winery.topologymodeler.addons.topologycompleter.analyzer.TOSCAAnalyzer; +import org.eclipse.winery.topologymodeler.addons.topologycompleter.topologycompletion.completer.DeferredCompleter; +import org.eclipse.winery.topologymodeler.addons.topologycompleter.topologycompletion.completer.PlaceHolderCompleter; +import org.eclipse.winery.topologymodeler.addons.topologycompleter.topologycompletion.completer.RequirementCompleter; +import org.eclipse.winery.topologymodeler.addons.topologycompleter.topologycompletion.completer.StepByStepCompleter; + +/** + * This class manages the completion of a TOSCA {@link TTopologyTemplate}. + */ +public class CompletionManager { + + private static final Logger logger = Logger.getLogger(CompletionManager.class.getName()); + + /** + * {@link TOSCAAnalyzer} object to access the JAXB data model + */ + TOSCAAnalyzer toscaAnalyzer; + + /** + * Map containing the topology solutions. + * + * The first parameter of the map is an index used to traverse the map easily. The second parameter of the solutions map + * is another map containing a possible topology solution and a boolean value that determines if the topology is complete. + * When all topologies of the solution map are complete, it will be returned to Winery. + */ + Map> solutions; + + /** + * Whether a step-by-step or an one-step approach is conducted + */ + boolean stepByStep; + + /** + * Map containing {@link TNodeTemplate}s and {@link TRelationshipTemplate}s to be chosen by the user in the step-by-step approach. + */ + private Map>> templateChoices; + + /** + * Whether a user interaction for choosing inserted {@link TNodeTemplate}s and {@link TRelationshipTemplate}s is necessary or not. + */ + private boolean nodeTemplateUserInteraction = false; + + /** + * List containing {@link TRelationshipTemplate} to be chosen by the user. + */ + private List choices; + + /** + * Whether a user interaction for choosing inserted {@link TRelationshipTemplate}s is necessary or not. + */ + boolean userInteraction = false; + + /** + * The index of the topology solutions map. + */ + int index; + + /** + * The class constructor. + * + * @param toscaAnalyzer + * the {@link TOSCAAnalyzer} object to access the data model + * @param stepByStep + * whether the topology completion is processed step-by-step or not + */ + public CompletionManager(TOSCAAnalyzer toscaAnalyzer, boolean stepByStep) { + this.toscaAnalyzer = toscaAnalyzer; + this.stepByStep = stepByStep; + this.index = 0; + + // instantiate the solution map + solutions = new HashMap>(); + } + + /** + * This recursive method analyzes and completes a TOSCA {@link TTopologyTemplate}. + * + * @param topology + * the TOSCA {@link TTopologyTemplate} to be completed + * + * @return the complete TOSCA {@link TTopologyTemplate} object + */ + public List manageCompletion(TTopologyTemplate topology) { + + // ------------------------- + // Analyze topology template + // ------------------------- + + // the data model must be cleared before analyzing the topology + toscaAnalyzer.clear(); + + // analyze the content of the topology template + toscaAnalyzer.analyzeTOSCATopology(topology); + + // Note: The TOSCAAnalyzer object is used for the analysis to access the NodeTemplates or RelationshipTemplates directly, + // so no cast from the parent type TEntityTemplate is required + + // -------------------------------- + // Analyze unfulfilled requirements + // -------------------------------- + Map unfulfilledRequirements = RequirementAnalyzer.analyzeRequirements(toscaAnalyzer); + + // --------------------------------------- + // Analyze the occurrence of place holders + // --------------------------------------- + List placeHolders = PlaceHolderAnalyzer.analyzePlaceHolders(toscaAnalyzer); + + // -------------------------------------------------------- + // Analyze the occurrence of deferred RelationshipTemplates + // -------------------------------------------------------- + List deferredRelations = DeferredAnalyzer.analyzeDeferredRelations(toscaAnalyzer); + + // --------------------- + // Complete the topology + // --------------------- + + // with the step by step approach, a user interaction is always necessary. So the topology and + // the choices will be returned in every step. A combination of the step-by-step approach and a deferred topology is not + // possible because every path of the depth search can lead to a dead end. + if (stepByStep && deferredRelations.isEmpty()) { + logger.info("Completing topology step by step."); + + List solutionList = new ArrayList(); + + if (!unfulfilledRequirements.isEmpty() && placeHolders.isEmpty()) { + + // complete a topology containing requirements step by step using the StepByStepCompleter class + StepByStepCompleter stepByStepCompleter = new StepByStepCompleter(topology); + stepByStepCompleter.completeTopologyStepByStep(unfulfilledRequirements, toscaAnalyzer); + + // get the NodeTemplate choices for the user + templateChoices = stepByStepCompleter.getTemplateChoices(); + nodeTemplateUserInteraction = true; + + solutionList.add(topology); + + logger.info("Returning topology for user interaction"); + + return solutionList; + + } else if (unfulfilledRequirements.isEmpty() && !placeHolders.isEmpty()) { + + // complete a topology containing place holders step by step using the StepByStepCompleter class + StepByStepCompleter stepByStepCompleter = new StepByStepCompleter(topology); + TRelationshipTemplate genericRelationship = stepByStepCompleter.completeWildcardTopologyStepByStep(placeHolders, toscaAnalyzer); + + // get the NodeTemplate selection for the user to choose + templateChoices = stepByStepCompleter.getTemplateChoices(); + nodeTemplateUserInteraction = true; + + TNodeTemplate toBeRemoved = stepByStepCompleter.getPlaceHolder(); + topology.getNodeTemplateOrRelationshipTemplate().remove(toBeRemoved); + topology.getNodeTemplateOrRelationshipTemplate().remove(genericRelationship); + + solutionList.add(topology); + logger.info("Returning topology for user interaction"); + + return solutionList; + } else if (unfulfilledRequirements.isEmpty() && placeHolders.isEmpty() && deferredRelations.isEmpty()) { + + // the topology is complete, return it to Winery + + logger.info("The topology is complete."); + + nodeTemplateUserInteraction = false; + solutionList.add(topology); + return solutionList; + } + } else { + // the one-step approach is chosen or the topology contains deferred-RelationshipTemplates + if (unfulfilledRequirements.isEmpty() && placeHolders.isEmpty() && deferredRelations.isEmpty()) { + // the topology does not contain any elements that have to completed, it can be defined as complete + if (solutions.isEmpty()) { + // no topology solutions found, topology could not be completed due to missing types. + // Return an empty list, an error message will be shown in Winery. + return new ArrayList(); + } else { + // this topology is complete, set its boolean value in the map to true + for (Integer i : solutions.keySet()) { + for (TTopologyTemplate t : solutions.get(i).keySet()) { + if (t.equals(topology)) { + solutions.get(i).put(topology, true); + } + } + } + + // check if the map still contains any incomplete topologies. If this is the case, the recursion will continue. + // Otherwise the solutions map is returned. + if (!solutions.values().contains(false)) { + logger.info("The topology is complete."); + List sol = new ArrayList(); + + for (Integer i : solutions.keySet()) { + sol.addAll(solutions.get(i).keySet()); + } + return sol; + } + } + } else if (!unfulfilledRequirements.isEmpty() && placeHolders.isEmpty() && deferredRelations.isEmpty()) { + + logger.info("The topology contains Requirements, but no Place Holders."); + + // complete a topology containing Requirements in one step using the RequirementCompleter class + RequirementCompleter requirementCompleter = new RequirementCompleter(topology); + + List completeTopology = requirementCompleter.completeRequirementTopology(unfulfilledRequirements, toscaAnalyzer); + + for (TTopologyTemplate topologySolution : completeTopology) { + Map topologyMap = new HashMap(); + topologyMap.put(topologySolution, false); + solutions.put(index, topologyMap); + } + + // complete all topology solutions recursively + for (TTopologyTemplate topologySolution : completeTopology) { + manageCompletion(topologySolution); + index++; + } + + } else if (unfulfilledRequirements.isEmpty() && !placeHolders.isEmpty() || !unfulfilledRequirements.isEmpty() && !placeHolders.isEmpty()) { + + logger.info("The topology contains one or more PlaceHolders."); + + // complete a topology containing place holders in one step using the PlaceHolderCompleter class + PlaceHolderCompleter placeHolderCompleter = new PlaceHolderCompleter(topology); + + List completeTopology = placeHolderCompleter.completePlaceholderTopology(placeHolders, toscaAnalyzer); + + if (placeHolderCompleter.getUserInteraction()) { + choices = placeHolderCompleter.getChoices(); + userInteraction = true; + + // user interaction is necessary to choose a inserted Relationship Template, return the topology to winery + List intermediateSolutions = new ArrayList<>(); + TRelationshipTemplate toBeRemoved = null; + for (TEntityTemplate entityTemplate : topology.getNodeTemplateOrRelationshipTemplate()) { + if (entityTemplate instanceof TRelationshipTemplate) { + TRelationshipTemplate relationshipTemplate = (TRelationshipTemplate) entityTemplate; + if (relationshipTemplate.getTargetElement().getRef().equals(placeHolderCompleter.getPlaceHolder())) { + toBeRemoved = relationshipTemplate; + } + } + } + + topology.getNodeTemplateOrRelationshipTemplate().remove(toBeRemoved); + topology.getNodeTemplateOrRelationshipTemplate().remove(placeHolderCompleter.getPlaceHolder()); + + intermediateSolutions.add(topology); + return intermediateSolutions; + } + + int i = 0; + + for (TTopologyTemplate topologySolution : completeTopology) { + Map topologyMap = new HashMap(); + topologyMap.put(topologySolution, false); + solutions.put(i, topologyMap); + i++; + } + + for (TTopologyTemplate topologySolution : completeTopology) { + manageCompletion(topologySolution); + } + } else if (!deferredRelations.isEmpty()) { + + logger.info("The topology contains deferred RelationshipTemplates."); + + // complete a topology containing deferred Relationship Templates in one step using the DeferredCompleter class + DeferredCompleter deferredCompleter = new DeferredCompleter(topology); + List completeTopology = deferredCompleter.completeDeferredTopology(deferredRelations.get(0), toscaAnalyzer); + + int i = 0; + for (TTopologyTemplate solutionTemplate : completeTopology) { + Map topologyMap = new HashMap(); + topologyMap.put(solutionTemplate, false); + solutions.put(i, topologyMap); + i++; + } + + for (TTopologyTemplate topologySolution : completeTopology) { + manageCompletion(topologySolution); + } + } + List sol = new ArrayList(); + for (Integer i : solutions.keySet()) { + sol.addAll(solutions.get(i).keySet()); + } + return sol; + } + + return new ArrayList(); + } + + /** + * Returns whether an user interaction is necessary or not + * + * @return the field userInteraction + */ + public boolean getUserInteraction() { + return userInteraction; + } + + /** + * The possible {@link TRelationshipTemplate} choices + * + * @return the field choices + */ + public List getChoices() { + return choices; + } + + /** + * A map of {@link TNodeTemplate}s and {@link TRelationshipTemplate}s when completing a topology step by step + * + * @return the field nodeTemplateChoices + */ + public Map>> getTemplateChoices() { + return templateChoices; + } + + /** + * Returns whether user interaction by choosing {@link TNodeTemplate}s and {@link TRelationshipTemplate}s is necessary or not + * + * @return the field nodeTemplateUserInteraction + */ + public boolean getNodeTemplateUserInteraction() { + return nodeTemplateUserInteraction; + } + +} diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/topologycompletion/completer/DeferredCompleter.java b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/topologycompletion/completer/DeferredCompleter.java new file mode 100644 index 0000000..8bdf01e --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/topologycompletion/completer/DeferredCompleter.java @@ -0,0 +1,218 @@ +/******************************************************************************* + * 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 + *******************************************************************************/ + +package org.eclipse.winery.topologymodeler.addons.topologycompleter.topologycompletion.completer; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.eclipse.winery.common.ModelUtilities; +import org.eclipse.winery.model.tosca.TCapability; +import org.eclipse.winery.model.tosca.TEntityTemplate; +import org.eclipse.winery.model.tosca.TNodeTemplate; +import org.eclipse.winery.model.tosca.TNodeType; +import org.eclipse.winery.model.tosca.TRelationshipTemplate; +import org.eclipse.winery.model.tosca.TRelationshipType; +import org.eclipse.winery.model.tosca.TRequirement; +import org.eclipse.winery.model.tosca.TRequirementType; +import org.eclipse.winery.model.tosca.TTopologyTemplate; +import org.eclipse.winery.topologymodeler.addons.topologycompleter.analyzer.TOSCAAnalyzer; +import org.eclipse.winery.topologymodeler.addons.topologycompleter.helper.NodeTemplateConnector; +import org.eclipse.winery.topologymodeler.addons.topologycompleter.helper.Utils; + +/** + * This class serves the completion of a topology containing Deferred {@link TRelationshipTemplate}s. + */ +public class DeferredCompleter { + + /** + * The TOSCA {@link TTopologyTemplate} document + */ + TTopologyTemplate topology; + + /** + * A Map containing the requirements removed during the algorithm and their corresponding {@link TNodeTemplate}. + */ + Map removedRequirements; + + /** + * Constructor of the class. + * + * @param topology + * the {@link TTopologyTemplate} to be completed + */ + public DeferredCompleter(TTopologyTemplate topology) { + this.topology = topology; + removedRequirements = new HashMap(); + } + + /** + * Completes a {@link TTopologyTemplate} that contains deferred {@link TRelationshipTemplate}s with a depth search algorithm. A deferred {@link TRelationshipTemplate} serves as place holder for a + * number of {@link TNodeTemplate}s and {@link TRelationshipTemplate}s. + * + * @param deferredRelation + * all found deferred {@link TRelationshipTemplate}s in the topology + * @param toscaAnalyzer + * the {@link TOSCAAnalyzer} object to access the data model + * + * @return the completed topology + */ + public List completeDeferredTopology(TRelationshipTemplate deferredRelation, TOSCAAnalyzer toscaAnalyzer) { + + List solutions = new ArrayList(); + + TNodeTemplate source = (TNodeTemplate) deferredRelation.getSourceElement().getRef(); + TNodeTemplate target = (TNodeTemplate) deferredRelation.getTargetElement().getRef(); + + // TODO Remove this "if clause" after the Provisioning-API is implemented. At the moment Deferred RelationshipTemplates can't be completed + // without the existence of Requirements + if (source.getRequirements() != null && !source.getRequirements().getRequirement().isEmpty()) { + topology.getNodeTemplateOrRelationshipTemplate().remove(deferredRelation); + runDepthFirstSearch(source, target, new ArrayList(), solutions, toscaAnalyzer); + } + + /** + * Note: This code adds Requirements to NodeTemplates that has been removed during the algorithm but could not + * be used to replace the Deferred-RelationshipTemplates. If this step is not done, requirements could get lost. + * + * Therefore all removed Requirements are checked for fulfillment in the topology. If they have not been fulfilled + * they are re-added to the topology. + */ + Set keySet = removedRequirements.keySet(); + + for (TTopologyTemplate topologyTemplate: solutions) { + boolean fulfilled = false; + for (TRequirement requirement: keySet) { + for (TEntityTemplate entity: topologyTemplate.getNodeTemplateOrRelationshipTemplate()) { + if (entity instanceof TNodeTemplate) { + TNodeTemplate nodeTemplate = (TNodeTemplate) entity; + if (nodeTemplate.getCapabilities() != null) { + for (TCapability capability: nodeTemplate.getCapabilities().getCapability()) { + String reqCapaType = ""; + for (TRequirementType reqType: toscaAnalyzer.getRequirementTypes()) { + if (reqType.getName().equals(requirement.getType().getLocalPart())) { + reqCapaType = reqType.getRequiredCapabilityType().getLocalPart(); + } + } + if (capability.getName().equals(reqCapaType)) { + fulfilled = true; + } + } + } + } + } + if (!fulfilled) { + for (TEntityTemplate entity: topologyTemplate.getNodeTemplateOrRelationshipTemplate()) { + if (entity.equals(removedRequirements.get(requirement))) { + TNodeTemplate foundNT = (TNodeTemplate) entity; + foundNT.getRequirements().getRequirement().add(requirement); + } + } + } + } + } + + return solutions; + } + + /** + * Runs a recursive depth search to find the path to the target NodeTemplate. + * + * @param source + * the source node of a given {@link TRelationshipTemplate} + * @param target + * the target node of a given {@link TRelationshipTemplate} + * @param path + * the current path to the target (can be incomplete) + * @param solutions + * list containing all possible solutions of the completion + * @param toscaAnalyzer + * the {@link TOSCAAnalyzer} object to access the data model + * + * @return the path to the target NodeTemplate + */ + private void runDepthFirstSearch(TNodeTemplate source, TNodeTemplate target, List path, List solutions, TOSCAAnalyzer toscaAnalyzer) { + + List matchingNodeTypes = new ArrayList(); + + if (source.getRequirements() != null) { + + List requirementsOfTemplate = new ArrayList<>(); + for (TRequirement requirement : source.getRequirements().getRequirement()) { + requirementsOfTemplate.add(requirement); + } + + for (TRequirement requirement : requirementsOfTemplate) { + + // save the requirement to a list to avoid losing requirements (see line 83) + TRequirement sourceRequirement = new TRequirement(); + sourceRequirement.setId(requirement.getId()); + sourceRequirement.setName(requirement.getName()); + sourceRequirement.setType(requirement.getType()); + + // Remember the removed requirements. In case a requirement + // can't be used for completing the deferred RelationshipTemplate it has to be re-added to the topology. + removedRequirements.put(sourceRequirement, source); + + // search for matching NodeTypes for the requirement + matchingNodeTypes.addAll(Utils.matchRequirementAndCapability(requirement, toscaAnalyzer)); + + // remove the requirement so it is not handled again during the algorithm + source.getRequirements().getRequirement().remove(requirement); + } + } + for (TNodeType match : matchingNodeTypes) { + + if (match.getName().equals(target.getType().getLocalPart()) && match.getTargetNamespace().equals(target.getType().getNamespaceURI())) { + // the search was successful connect the target + List suitableRTs = NodeTemplateConnector.findRelationshipType(source, target, toscaAnalyzer, null); + + for (TRelationshipType rt : suitableRTs) { + TRelationshipTemplate relationship = ModelUtilities.instantiateRelationshipTemplate(rt, source, target); + path.add(relationship); + } + + TTopologyTemplate possiblePath = new TTopologyTemplate(); + possiblePath.getNodeTemplateOrRelationshipTemplate().addAll(topology.getNodeTemplateOrRelationshipTemplate()); + + // add the path to the topology + for (TEntityTemplate pathTemplate : path) { + possiblePath.getNodeTemplateOrRelationshipTemplate().add(pathTemplate); + } + + possiblePath.getNodeTemplateOrRelationshipTemplate().remove(target); + + // this is no good style, however the target has to be the last item in the list for a proper stack layouting + possiblePath.getNodeTemplateOrRelationshipTemplate().add(target); + solutions.add(possiblePath); + path.clear(); + } else { + + // the end of the path is not reached, add the found NodeTemplate and continue the depth search + TNodeTemplate instantiatedNodeTemplate = ModelUtilities.instantiateNodeTemplate(match); + + List suitableRTs = NodeTemplateConnector.findRelationshipType(source, instantiatedNodeTemplate, toscaAnalyzer, null); + + for (TRelationshipType rt : suitableRTs) { + TRelationshipTemplate relationship = ModelUtilities.instantiateRelationshipTemplate(rt, source, instantiatedNodeTemplate); + path.add(relationship); + } + path.add(instantiatedNodeTemplate); + runDepthFirstSearch(instantiatedNodeTemplate, target, path, solutions, toscaAnalyzer); + + } + } + } +} diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/topologycompletion/completer/PlaceHolderCompleter.java b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/topologycompletion/completer/PlaceHolderCompleter.java new file mode 100644 index 0000000..e76d897 --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/topologycompletion/completer/PlaceHolderCompleter.java @@ -0,0 +1,188 @@ +/******************************************************************************* + * 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 + *******************************************************************************/ + +package org.eclipse.winery.topologymodeler.addons.topologycompleter.topologycompletion.completer; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.winery.common.ModelUtilities; +import org.eclipse.winery.model.tosca.TEntityTemplate; +import org.eclipse.winery.model.tosca.TNodeTemplate; +import org.eclipse.winery.model.tosca.TNodeType; +import org.eclipse.winery.model.tosca.TRelationshipTemplate; +import org.eclipse.winery.model.tosca.TRelationshipType; +import org.eclipse.winery.model.tosca.TTopologyTemplate; +import org.eclipse.winery.topologymodeler.addons.topologycompleter.analyzer.TOSCAAnalyzer; +import org.eclipse.winery.topologymodeler.addons.topologycompleter.helper.NodeTemplateConnector; +import org.eclipse.winery.topologymodeler.addons.topologycompleter.placeholderhandling.PlaceHolderHandler; + +/** + * This class completes a {@link TTopologyTemplate} containing place holders. + */ +public class PlaceHolderCompleter { + + /** + * The {@link TTopologyTemplate} to be completed + */ + TTopologyTemplate topology; + + /** + * List containing user choices for {@link TRelationshipTemplate}s + */ + List choices; + + /** + * Whether an user interaction is necessary or not + */ + boolean userInteraction; + + /** + * The last inserted place holder + */ + TNodeTemplate placeHolder; + + /** + * The constructor of the class PlaceHolderCompleter. + * + * @param topology + * the {@link TTopologyTemplate} to be completed + */ + public PlaceHolderCompleter(TTopologyTemplate topology) { + this.topology = topology; + userInteraction = false; + } + + /** + * This method completes a {@link TTopologyTemplate} containing place holders. + * + * @param placeHolders + * the contained place holders + * @param toscaAnalyzer + * the {@link TOSCAAnalyzer} object to access the data model + * + * @return the complete {@link TTopologyTemplate} + */ + public List completePlaceholderTopology(List placeHolders, TOSCAAnalyzer toscaAnalyzer) { + + List solutions = new ArrayList(); + + for (TNodeTemplate placeHolder : placeHolders) { + + List suitableNodeTypes = PlaceHolderHandler.getSuitableNodeTypes(placeHolder, toscaAnalyzer); + + // if there are more than one solution for an inserted NodeTemplate, + // create copies of the topology. The user can choose from them after the completion. + TTopologyTemplate topologyCopy = null; + + for (TNodeType suitableNodeType : suitableNodeTypes) { + topologyCopy = new TTopologyTemplate(); + topologyCopy.getNodeTemplateOrRelationshipTemplate().addAll(topology.getNodeTemplateOrRelationshipTemplate()); + + TNodeTemplate nodeTemplate = ModelUtilities.instantiateNodeTemplate(suitableNodeType); + + List sourceTemplates = new ArrayList<>(); + + // contains RelationshipTemplates connecting to a place holder. + // These Templates are generic and have to be replaced with + // concrete ones. + List placeholderConnections = new ArrayList<>(); + + TRelationshipTemplate foundTarget = null; + for (TEntityTemplate entity : topology.getNodeTemplateOrRelationshipTemplate()) { + if (entity instanceof TRelationshipTemplate) { + TRelationshipTemplate rt = (TRelationshipTemplate) entity; + if (((TNodeTemplate) rt.getTargetElement().getRef()).getId().equals(placeHolder.getId())) { + TRelationshipTemplate placeHolderConnection = (TRelationshipTemplate) entity; + placeholderConnections.add(placeHolderConnection); + sourceTemplates.add((TNodeTemplate) placeHolderConnection.getSourceElement().getRef()); + } else if (((TNodeTemplate) rt.getSourceElement().getRef()).getId().equals(placeHolder.getId())) { + foundTarget = (TRelationshipTemplate) entity; + } + } + } + + // collect all possible RelationshipTemplates that can be used to connect to the placeholder + choices = new ArrayList<>(); + + for (TNodeTemplate sourceTemplate : sourceTemplates) { + // find matching RelationshipTypes to connect the Node Templates + List suitableRTs = NodeTemplateConnector.findRelationshipType(sourceTemplate, nodeTemplate, toscaAnalyzer, null); + for (TRelationshipType rt : suitableRTs) { + TRelationshipTemplate relationship = ModelUtilities.instantiateRelationshipTemplate(rt, sourceTemplate, nodeTemplate); + choices.add(relationship); + } + } + + // set the source elements of the RelationshipTemplates connecting from the replaced placeholder to other NodeTemplates + for (TEntityTemplate entityTemplate : topologyCopy.getNodeTemplateOrRelationshipTemplate()) { + if (entityTemplate instanceof TRelationshipTemplate) { + TRelationshipTemplate relationshipTemplate = (TRelationshipTemplate) entityTemplate; + if (relationshipTemplate.equals(foundTarget)) { + foundTarget.getSourceElement().setRef(nodeTemplate); + } + } + } + + // remove the generic connections to the place holder + topologyCopy.getNodeTemplateOrRelationshipTemplate().removeAll(placeholderConnections); + + // there are more than one possible Relationship Templates to connect to the inserted NodeTemplate(s), so + // interrupt the completion and ask the user which one to insert + if (choices.size() > 1 && sourceTemplates.size() == 1) { + + choices.add(sourceTemplates.get(0)); + choices.add(nodeTemplate); + topologyCopy.getNodeTemplateOrRelationshipTemplate().remove(placeHolder); + + userInteraction = true; + this.placeHolder = placeHolder; + break; + } else if (choices.size() == 1 || sourceTemplates.size() > 1) { + // replace the place holder with an actual NodeTemplate + topologyCopy.getNodeTemplateOrRelationshipTemplate().addAll(choices); + topologyCopy.getNodeTemplateOrRelationshipTemplate().add(nodeTemplate); + topologyCopy.getNodeTemplateOrRelationshipTemplate().remove(placeHolder); + } + solutions.add(topologyCopy); + } + } + return solutions; + } + + /** + * Returns the replaced place holder. + * + * @return the place holder + */ + public TNodeTemplate getPlaceHolder() { + return placeHolder; + } + + /** + * Returns whether an user interaction is necessary or not. + * + * @return the field userInteraction + */ + public boolean getUserInteraction() { + return userInteraction; + } + + /** + * Possible Relationship Template choices. + * + * @return the field choices + */ + public List getChoices() { + return choices; + } +} diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/topologycompletion/completer/RequirementCompleter.java b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/topologycompletion/completer/RequirementCompleter.java new file mode 100644 index 0000000..b2e7c75 --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/topologycompletion/completer/RequirementCompleter.java @@ -0,0 +1,108 @@ +/******************************************************************************* + * 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 + *******************************************************************************/ + +package org.eclipse.winery.topologymodeler.addons.topologycompleter.topologycompletion.completer; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.eclipse.winery.common.ModelUtilities; +import org.eclipse.winery.model.tosca.TEntityTemplate; +import org.eclipse.winery.model.tosca.TNodeTemplate; +import org.eclipse.winery.model.tosca.TNodeType; +import org.eclipse.winery.model.tosca.TRelationshipTemplate; +import org.eclipse.winery.model.tosca.TRelationshipType; +import org.eclipse.winery.model.tosca.TRequirement; +import org.eclipse.winery.model.tosca.TTopologyTemplate; +import org.eclipse.winery.topologymodeler.addons.topologycompleter.analyzer.TOSCAAnalyzer; +import org.eclipse.winery.topologymodeler.addons.topologycompleter.helper.NodeTemplateConnector; +import org.eclipse.winery.topologymodeler.addons.topologycompleter.helper.Utils; + +public class RequirementCompleter { + + /** + * The TOSCA {@link TTopologyTemplate} document. + */ + TTopologyTemplate topology; + + /** + * The constructor the class. + * + * @param topology + * the topology to be completed + */ + public RequirementCompleter(TTopologyTemplate topology) { + this.topology = topology; + } + + /** + * This method completes a topology containing {@link TRequirement}s in one step (without user interaction). + * + * @param unfulfilledRequirements + * all the unfulfilled requirements that has been found in the topology + * @param toscaAnalyzer + * the {@link TOSCAAnalyzer} object to access the data model + * + * @return the complete topology + */ + public List completeRequirementTopology(Map unfulfilledRequirements, TOSCAAnalyzer toscaAnalyzer) { + + List solutions = new ArrayList(); + + Set requirements = unfulfilledRequirements.keySet(); + + TNodeTemplate instantiatedNodeTemplate = null; + + // fulfill the Requirements + for (TRequirement requirement : requirements) { + + // remove the requirement from the NodeTemplate + TNodeTemplate requirementTemplate = unfulfilledRequirements.get(requirement); + for (TEntityTemplate element : topology.getNodeTemplateOrRelationshipTemplate()) { + if (requirementTemplate.getId().equals(element.getId())) { + ((TNodeTemplate) element).getRequirements().getRequirement().remove(requirement); + } + } + + List possibleNodeTypes = Utils.matchRequirementAndCapability(requirement, toscaAnalyzer); + + // create a NodeTemplate for every matching Type, insert it into the topology and create a topology copy for each possible inserted NodeTemplate + TTopologyTemplate topologyCopy = null; + for (TNodeType possibleType : possibleNodeTypes) { + + topologyCopy = new TTopologyTemplate(); + topologyCopy.getNodeTemplateOrRelationshipTemplate().addAll(topology.getNodeTemplateOrRelationshipTemplate()); + + // instantiate the template + instantiatedNodeTemplate = ModelUtilities.instantiateNodeTemplate(possibleType); + topologyCopy.getNodeTemplateOrRelationshipTemplate().add(instantiatedNodeTemplate); + + TNodeTemplate correspondingNodeTemplate = unfulfilledRequirements.get(requirement); + + // find matching RelationshipTypes, instantiate RelationshipTemplates and connect the Node Templates + List suitableRTs = NodeTemplateConnector.findRelationshipType(correspondingNodeTemplate, instantiatedNodeTemplate, toscaAnalyzer, requirement); + for (TRelationshipType rt : suitableRTs) { + TRelationshipTemplate relationship = ModelUtilities.instantiateRelationshipTemplate(rt, correspondingNodeTemplate, instantiatedNodeTemplate); + topologyCopy.getNodeTemplateOrRelationshipTemplate().add(relationship); + } + + solutions.add(topologyCopy); + } + if (solutions.size() > 1) { + break; + } + } + return solutions; + } +} diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/topologycompletion/completer/StepByStepCompleter.java b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/topologycompletion/completer/StepByStepCompleter.java new file mode 100644 index 0000000..b8cc745 --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/topologycompletion/completer/StepByStepCompleter.java @@ -0,0 +1,203 @@ +/******************************************************************************* + * 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 + *******************************************************************************/ + +package org.eclipse.winery.topologymodeler.addons.topologycompleter.topologycompletion.completer; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.eclipse.winery.common.ModelUtilities; +import org.eclipse.winery.model.tosca.TEntityTemplate; +import org.eclipse.winery.model.tosca.TNodeTemplate; +import org.eclipse.winery.model.tosca.TNodeType; +import org.eclipse.winery.model.tosca.TRelationshipTemplate; +import org.eclipse.winery.model.tosca.TRelationshipType; +import org.eclipse.winery.model.tosca.TRequirement; +import org.eclipse.winery.model.tosca.TTopologyTemplate; +import org.eclipse.winery.topologymodeler.addons.topologycompleter.analyzer.TOSCAAnalyzer; +import org.eclipse.winery.topologymodeler.addons.topologycompleter.helper.NodeTemplateConnector; +import org.eclipse.winery.topologymodeler.addons.topologycompleter.helper.Utils; +import org.eclipse.winery.topologymodeler.addons.topologycompleter.placeholderhandling.PlaceHolderHandler; + +/** + * This class handles topologies that are completed step by step + */ +public class StepByStepCompleter { + + /** + * the topology to be completed + */ + TTopologyTemplate topology; + + /** + * the Node and RelationshipTemplates chosen by the user in every step + */ + Map>> templateChoices; + + /** + * the last inserted place holder to be deleted + */ + private TNodeTemplate placeHolder; + + /** + * The constructor of the class. + * + * @param topology + * the {@link TTopologyTemplate} to be completed + */ + public StepByStepCompleter(TTopologyTemplate topology) { + this.topology = topology; + } + + /** + * This method is called when a topology containing {@link TRequirement}s is completed step by step. + * + * @param unfulfilledRequirements + * a list of unfulfilled requirements + * @param placeHolders + * a list of place holders to be fulfilled + * @param toscaAnalyzer + * the {@link TOSCAAnalyzer} object to access the data model + */ + public void completeTopologyStepByStep(Map unfulfilledRequirements, TOSCAAnalyzer toscaAnalyzer) { + + Set requirements = unfulfilledRequirements.keySet(); + + TNodeTemplate nodeTemplate = null; + + for (TRequirement requirement : requirements) { + // remove the requirement from the NodeTemplate + TNodeTemplate requirementTemplate = unfulfilledRequirements.get(requirement); + for (TEntityTemplate element : topology.getNodeTemplateOrRelationshipTemplate()) { + if (requirementTemplate.getId().equals(element.getId())) { + ((TNodeTemplate) element).getRequirements().getRequirement().remove(requirement); + } + } + + List possibleNodeTypes = Utils.matchRequirementAndCapability(requirement, toscaAnalyzer); + + // create a NodeTemplate for each matching node type + List possibleTemplates = new ArrayList<>(); + for (TNodeType possibleType : possibleNodeTypes) { + nodeTemplate = ModelUtilities.instantiateNodeTemplate(possibleType); + possibleTemplates.add(nodeTemplate); + } + + TNodeTemplate correspondingNodeTemplate = unfulfilledRequirements.get(requirement); + + Map> entityTemplates = new HashMap<>(); + + // add all possible choices to a list and return it to the user + for (TNodeTemplate possibleTemplate : possibleTemplates) { + List choices = new ArrayList(); + List suitableRTs = NodeTemplateConnector.findRelationshipType(correspondingNodeTemplate, possibleTemplate, toscaAnalyzer, requirement); + for (TRelationshipType rt : suitableRTs) { + TRelationshipTemplate relationship = ModelUtilities.instantiateRelationshipTemplate(rt, correspondingNodeTemplate, possibleTemplate); + choices.add(relationship); + } + entityTemplates.put(possibleTemplate, choices); + } + + templateChoices = new HashMap>>(); + templateChoices.put(correspondingNodeTemplate, entityTemplates); + + // let the user decide which template shall be inserted + break; + } + + } + + /** + * Completes a place holder {@link TTopologyTemplate} step by step. + * + * @param placeHolders + * the place holders of the topology + * @param toscaAnalyzer + * the {@link TOSCAAnalyzer} object to access the data model. + * @return the generic {@link TRelationshipTemplate} which connects to the place holder. + */ + public TRelationshipTemplate completeWildcardTopologyStepByStep(List placeHolders, TOSCAAnalyzer toscaAnalyzer) { + + // take the first place holder, the order doesn't matter in the step by step approach + TNodeTemplate placeHolder = placeHolders.get(0); + + // get suitable NodeTypes for a placeholder and instantiate NodeTemplates + List suitableNodeTypes = PlaceHolderHandler.getSuitableNodeTypes(placeHolder, toscaAnalyzer); + List suitableNodeTemplates = new ArrayList(); + for (TNodeType suitableNodeType : suitableNodeTypes) { + TNodeTemplate nodeTemplate = ModelUtilities.instantiateNodeTemplate(suitableNodeType); + suitableNodeTemplates.add(nodeTemplate); + } + + /** + * map containing the choices for the user selection + */ + Map> entityTemplates = new HashMap<>(); + + TNodeTemplate sourceTemplate = null; + + // the RelationshipTemplate connecting to the placeholder + TRelationshipTemplate connectingRelationshipTemplate = null; + + for (TEntityTemplate entity : topology.getNodeTemplateOrRelationshipTemplate()) { + if (entity instanceof TRelationshipTemplate) { + TRelationshipTemplate rt = (TRelationshipTemplate) entity; + if (((TNodeTemplate) rt.getTargetElement().getRef()).getId().equals(placeHolder.getId())) { + connectingRelationshipTemplate = (TRelationshipTemplate) entity; + sourceTemplate = (TNodeTemplate) connectingRelationshipTemplate.getSourceElement().getRef(); + } + } + } + + for (TNodeTemplate nodeTemplate : suitableNodeTemplates) { + + List choices = new ArrayList<>(); + + // find matching RelationshipTypes to connect the Node Templates + List suitableRTs = NodeTemplateConnector.findRelationshipType(sourceTemplate, nodeTemplate, toscaAnalyzer, null); + for (TRelationshipType rt : suitableRTs) { + TRelationshipTemplate relationship = ModelUtilities.instantiateRelationshipTemplate(rt, sourceTemplate, nodeTemplate); + choices.add(relationship); + } + entityTemplates.put(nodeTemplate, choices); + } + + templateChoices = new HashMap>>(); + templateChoices.put(sourceTemplate, entityTemplates); + + this.placeHolder = placeHolder; + + return connectingRelationshipTemplate; + + } + + /** + * Returns a map containing the choices for the user selection when the topology is completed step by step. + * + * @return the field ntChoices + */ + public Map>> getTemplateChoices() { + return templateChoices; + } + + /** + * Returns the replaced place holder to remove it from the topology. + * + * @return the place holder + */ + public TNodeTemplate getPlaceHolder() { + return placeHolder; + } +} diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/topologycompletion/completer/package-info.java b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/topologycompletion/completer/package-info.java new file mode 100644 index 0000000..8a097d5 --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/topologycompletion/completer/package-info.java @@ -0,0 +1,17 @@ +/******************************************************************************* + * 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 + *******************************************************************************/ + +/** + * This package contains classes and methods to actually execute the completion for several use cases. + */ +package org.eclipse.winery.topologymodeler.addons.topologycompleter.topologycompletion.completer; + diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/topologycompletion/package-info.java b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/topologycompletion/package-info.java new file mode 100644 index 0000000..bdaf170 --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/topologycompletion/package-info.java @@ -0,0 +1,17 @@ +/******************************************************************************* + * 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 + *******************************************************************************/ + +/** + * This package contains classes and methods to execute and manage the completion. + */ +package org.eclipse.winery.topologymodeler.addons.topologycompleter.topologycompletion; + diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/resources/TopologyCompletionResource.java b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/resources/TopologyCompletionResource.java new file mode 100644 index 0000000..efc36e3 --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/resources/TopologyCompletionResource.java @@ -0,0 +1,136 @@ +/******************************************************************************* + * 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 + *******************************************************************************/ + +package org.eclipse.winery.topologymodeler.resources; + +import java.io.StringReader; + +import javax.ws.rs.FormParam; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Unmarshaller; + +import org.eclipse.winery.model.tosca.Definitions; +import org.eclipse.winery.model.tosca.TNodeTemplate; +import org.eclipse.winery.model.tosca.TRelationshipTemplate; +import org.eclipse.winery.model.tosca.TServiceTemplate; +import org.eclipse.winery.model.tosca.TTopologyTemplate; +import org.eclipse.winery.topologymodeler.addons.topologycompleter.helper.JAXBHelper; +import org.eclipse.winery.topologymodeler.addons.topologycompleter.helper.RESTHelper; + +/** + * This class contains resources used for the topology completion. + * + */ +@Path("/") +public class TopologyCompletionResource { + + /** + * Adds selected {@link TNodeTemplate}s and {@link TRelationshipTemplate}s + * to a topology. + * + * @param topology + * the {@link TTopologyTemplate} as XML string + * @param allChoices + * all possible choices as XML + * @param selectedNodeTemplates + * the selected {@link TNodeTemplate}s as JSON array + * @param selectedRelationshipTemplates + * the selected {@link TRelationshipTemplate}s as JSON array + * @return the enhanced {@link TTopologyTemplate} + */ + @Path("selectionhandler/") + @GET + @Produces(MediaType.TEXT_PLAIN) + public Response handleSelection( + @QueryParam(value = "topology") String topology, + @QueryParam(value = "allChoices") String allChoices, + @QueryParam(value = "selectedNodeTemplates") String selectedNodeTemplates, + @QueryParam(value = "selectedRelationshipTemplates") String selectedRelationshipTemplates) { + return Response + .ok() + .entity(JAXBHelper.addTemplatesToTopology(topology, allChoices, + selectedNodeTemplates, selectedRelationshipTemplates)) + .build(); + } + + /** + * This resource is used to save a {@link TTopologyTemplate} to the repository. + * + * @param topology + * the topology to be saved + * @param templateURL + * the URL the {@link TTopologyTemplate} of the topology template + * @param repositoryURL + * the URL of the repository + * @param topologyName + * the name of the saved {@link TTopologyTemplate} + * @param topologyNamespace + * the namespace of the saved {@link TTopologyTemplate} + * @param overwriteTopology + * whether the {@link TTopologyTemplate} should be overwritten or not + * + * @return whether the save operation has been successful or not + */ + @Path("topologysaver/") + @POST + public Response saveTopology(@FormParam("topology") String topology, + @FormParam(value = "templateURL") String templateURL, + @FormParam(value = "repositoryURL") String repositoryURL, + @FormParam(value = "topologyName") String topologyName, + @FormParam(value = "topologyNamespace") String topologyNamespace, + @FormParam(value = "overwriteTopology") String overwriteTopology) { + try { + + boolean overwrite = Boolean.parseBoolean(overwriteTopology); + + // initiate JaxB context + JAXBContext context; + context = JAXBContext.newInstance(Definitions.class); + StringReader reader = new StringReader(topology); + + // unmarshall the topology XML string + Unmarshaller um; + + um = context.createUnmarshaller(); + + Definitions jaxBDefinitions = (Definitions) um.unmarshal(reader); + TServiceTemplate st = (TServiceTemplate) jaxBDefinitions + .getServiceTemplateOrNodeTypeOrNodeTypeImplementation() + .get(0); + TTopologyTemplate toBeSaved = st.getTopologyTemplate(); + + // depending on the selected save method (overwrite or create new) + // the save method is called + if (overwrite) { + RESTHelper.saveCompleteTopology(toBeSaved, templateURL, true, + "", "", repositoryURL); + } else { + RESTHelper.saveCompleteTopology(toBeSaved, templateURL, false, + topologyName, topologyNamespace, repositoryURL); + } + + return Response.ok().build(); + + } catch (JAXBException e) { + e.printStackTrace(); + return Response.serverError().build(); + } + } +} diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/resources/package-info.java b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/resources/package-info.java new file mode 100644 index 0000000..a06da46 --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/resources/package-info.java @@ -0,0 +1,4 @@ +/** + * Contains the resources of the topology modeler + */ +package org.eclipse.winery.topologymodeler.resources; \ No newline at end of file diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/resources/.gitignore b/winery/org.eclipse.winery.topologymodeler/src/main/resources/.gitignore new file mode 100644 index 0000000..17ae84b --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/src/main/resources/.gitignore @@ -0,0 +1 @@ +rebel.xml diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/webapp/3rdparty/jquery-ui/js/jquery-ui.js b/winery/org.eclipse.winery.topologymodeler/src/main/webapp/3rdparty/jquery-ui/js/jquery-ui.js new file mode 100644 index 0000000..6eccbfe --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/src/main/webapp/3rdparty/jquery-ui/js/jquery-ui.js @@ -0,0 +1,14987 @@ +/*! jQuery UI - v1.10.2 - 2013-03-14 +* http://jqueryui.com +* Includes: jquery.ui.core.js, jquery.ui.widget.js, jquery.ui.mouse.js, jquery.ui.draggable.js, jquery.ui.droppable.js, jquery.ui.resizable.js, jquery.ui.selectable.js, jquery.ui.sortable.js, jquery.ui.effect.js, jquery.ui.accordion.js, jquery.ui.autocomplete.js, jquery.ui.button.js, jquery.ui.datepicker.js, jquery.ui.dialog.js, jquery.ui.effect-blind.js, jquery.ui.effect-bounce.js, jquery.ui.effect-clip.js, jquery.ui.effect-drop.js, jquery.ui.effect-explode.js, jquery.ui.effect-fade.js, jquery.ui.effect-fold.js, jquery.ui.effect-highlight.js, jquery.ui.effect-pulsate.js, jquery.ui.effect-scale.js, jquery.ui.effect-shake.js, jquery.ui.effect-slide.js, jquery.ui.effect-transfer.js, jquery.ui.menu.js, jquery.ui.position.js, jquery.ui.progressbar.js, jquery.ui.slider.js, jquery.ui.spinner.js, jquery.ui.tabs.js, jquery.ui.tooltip.js +* Copyright 2013 jQuery Foundation and other contributors; Licensed MIT */ +(function( $, undefined ) { + +var uuid = 0, + runiqueId = /^ui-id-\d+$/; + +// $.ui might exist from components with no dependencies, e.g., $.ui.position +$.ui = $.ui || {}; + +$.extend( $.ui, { + version: "1.10.2", + + keyCode: { + BACKSPACE: 8, + COMMA: 188, + DELETE: 46, + DOWN: 40, + END: 35, + ENTER: 13, + ESCAPE: 27, + HOME: 36, + LEFT: 37, + NUMPAD_ADD: 107, + NUMPAD_DECIMAL: 110, + NUMPAD_DIVIDE: 111, + NUMPAD_ENTER: 108, + NUMPAD_MULTIPLY: 106, + NUMPAD_SUBTRACT: 109, + PAGE_DOWN: 34, + PAGE_UP: 33, + PERIOD: 190, + RIGHT: 39, + SPACE: 32, + TAB: 9, + UP: 38 + } +}); + +// plugins +$.fn.extend({ + focus: (function( orig ) { + return function( delay, fn ) { + return typeof delay === "number" ? + this.each(function() { + var elem = this; + setTimeout(function() { + $( elem ).focus(); + if ( fn ) { + fn.call( elem ); + } + }, delay ); + }) : + orig.apply( this, arguments ); + }; + })( $.fn.focus ), + + scrollParent: function() { + var scrollParent; + if (($.ui.ie && (/(static|relative)/).test(this.css("position"))) || (/absolute/).test(this.css("position"))) { + scrollParent = this.parents().filter(function() { + return (/(relative|absolute|fixed)/).test($.css(this,"position")) && (/(auto|scroll)/).test($.css(this,"overflow")+$.css(this,"overflow-y")+$.css(this,"overflow-x")); + }).eq(0); + } else { + scrollParent = this.parents().filter(function() { + return (/(auto|scroll)/).test($.css(this,"overflow")+$.css(this,"overflow-y")+$.css(this,"overflow-x")); + }).eq(0); + } + + return (/fixed/).test(this.css("position")) || !scrollParent.length ? $(document) : scrollParent; + }, + + zIndex: function( zIndex ) { + if ( zIndex !== undefined ) { + return this.css( "zIndex", zIndex ); + } + + if ( this.length ) { + var elem = $( this[ 0 ] ), position, value; + while ( elem.length && elem[ 0 ] !== document ) { + // Ignore z-index if position is set to a value where z-index is ignored by the browser + // This makes behavior of this function consistent across browsers + // WebKit always returns auto if the element is positioned + position = elem.css( "position" ); + if ( position === "absolute" || position === "relative" || position === "fixed" ) { + // IE returns 0 when zIndex is not specified + // other browsers return a string + // we ignore the case of nested elements with an explicit value of 0 + //
+ value = parseInt( elem.css( "zIndex" ), 10 ); + if ( !isNaN( value ) && value !== 0 ) { + return value; + } + } + elem = elem.parent(); + } + } + + return 0; + }, + + uniqueId: function() { + return this.each(function() { + if ( !this.id ) { + this.id = "ui-id-" + (++uuid); + } + }); + }, + + removeUniqueId: function() { + return this.each(function() { + if ( runiqueId.test( this.id ) ) { + $( this ).removeAttr( "id" ); + } + }); + } +}); + +// selectors +function focusable( element, isTabIndexNotNaN ) { + var map, mapName, img, + nodeName = element.nodeName.toLowerCase(); + if ( "area" === nodeName ) { + map = element.parentNode; + mapName = map.name; + if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) { + return false; + } + img = $( "img[usemap=#" + mapName + "]" )[0]; + return !!img && visible( img ); + } + return ( /input|select|textarea|button|object/.test( nodeName ) ? + !element.disabled : + "a" === nodeName ? + element.href || isTabIndexNotNaN : + isTabIndexNotNaN) && + // the element and all of its ancestors must be visible + visible( element ); +} + +function visible( element ) { + return $.expr.filters.visible( element ) && + !$( element ).parents().addBack().filter(function() { + return $.css( this, "visibility" ) === "hidden"; + }).length; +} + +$.extend( $.expr[ ":" ], { + data: $.expr.createPseudo ? + $.expr.createPseudo(function( dataName ) { + return function( elem ) { + return !!$.data( elem, dataName ); + }; + }) : + // support: jQuery <1.8 + function( elem, i, match ) { + return !!$.data( elem, match[ 3 ] ); + }, + + focusable: function( element ) { + return focusable( element, !isNaN( $.attr( element, "tabindex" ) ) ); + }, + + tabbable: function( element ) { + var tabIndex = $.attr( element, "tabindex" ), + isTabIndexNaN = isNaN( tabIndex ); + return ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN ); + } +}); + +// support: jQuery <1.8 +if ( !$( "" ).outerWidth( 1 ).jquery ) { + $.each( [ "Width", "Height" ], function( i, name ) { + var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ], + type = name.toLowerCase(), + orig = { + innerWidth: $.fn.innerWidth, + innerHeight: $.fn.innerHeight, + outerWidth: $.fn.outerWidth, + outerHeight: $.fn.outerHeight + }; + + function reduce( elem, size, border, margin ) { + $.each( side, function() { + size -= parseFloat( $.css( elem, "padding" + this ) ) || 0; + if ( border ) { + size -= parseFloat( $.css( elem, "border" + this + "Width" ) ) || 0; + } + if ( margin ) { + size -= parseFloat( $.css( elem, "margin" + this ) ) || 0; + } + }); + return size; + } + + $.fn[ "inner" + name ] = function( size ) { + if ( size === undefined ) { + return orig[ "inner" + name ].call( this ); + } + + return this.each(function() { + $( this ).css( type, reduce( this, size ) + "px" ); + }); + }; + + $.fn[ "outer" + name] = function( size, margin ) { + if ( typeof size !== "number" ) { + return orig[ "outer" + name ].call( this, size ); + } + + return this.each(function() { + $( this).css( type, reduce( this, size, true, margin ) + "px" ); + }); + }; + }); +} + +// support: jQuery <1.8 +if ( !$.fn.addBack ) { + $.fn.addBack = function( selector ) { + return this.add( selector == null ? + this.prevObject : this.prevObject.filter( selector ) + ); + }; +} + +// support: jQuery 1.6.1, 1.6.2 (http://bugs.jquery.com/ticket/9413) +if ( $( "" ).data( "a-b", "a" ).removeData( "a-b" ).data( "a-b" ) ) { + $.fn.removeData = (function( removeData ) { + return function( key ) { + if ( arguments.length ) { + return removeData.call( this, $.camelCase( key ) ); + } else { + return removeData.call( this ); + } + }; + })( $.fn.removeData ); +} + + + + + +// deprecated +$.ui.ie = !!/msie [\w.]+/.exec( navigator.userAgent.toLowerCase() ); + +$.support.selectstart = "onselectstart" in document.createElement( "div" ); +$.fn.extend({ + disableSelection: function() { + return this.bind( ( $.support.selectstart ? "selectstart" : "mousedown" ) + + ".ui-disableSelection", function( event ) { + event.preventDefault(); + }); + }, + + enableSelection: function() { + return this.unbind( ".ui-disableSelection" ); + } +}); + +$.extend( $.ui, { + // $.ui.plugin is deprecated. Use the proxy pattern instead. + plugin: { + add: function( module, option, set ) { + var i, + proto = $.ui[ module ].prototype; + for ( i in set ) { + proto.plugins[ i ] = proto.plugins[ i ] || []; + proto.plugins[ i ].push( [ option, set[ i ] ] ); + } + }, + call: function( instance, name, args ) { + var i, + set = instance.plugins[ name ]; + if ( !set || !instance.element[ 0 ].parentNode || instance.element[ 0 ].parentNode.nodeType === 11 ) { + return; + } + + for ( i = 0; i < set.length; i++ ) { + if ( instance.options[ set[ i ][ 0 ] ] ) { + set[ i ][ 1 ].apply( instance.element, args ); + } + } + } + }, + + // only used by resizable + hasScroll: function( el, a ) { + + //If overflow is hidden, the element might have extra content, but the user wants to hide it + if ( $( el ).css( "overflow" ) === "hidden") { + return false; + } + + var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop", + has = false; + + if ( el[ scroll ] > 0 ) { + return true; + } + + // TODO: determine which cases actually cause this to happen + // if the element doesn't have the scroll set, see if it's possible to + // set the scroll + el[ scroll ] = 1; + has = ( el[ scroll ] > 0 ); + el[ scroll ] = 0; + return has; + } +}); + +})( jQuery ); + +(function( $, undefined ) { + +var uuid = 0, + slice = Array.prototype.slice, + _cleanData = $.cleanData; +$.cleanData = function( elems ) { + for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) { + try { + $( elem ).triggerHandler( "remove" ); + // http://bugs.jquery.com/ticket/8235 + } catch( e ) {} + } + _cleanData( elems ); +}; + +$.widget = function( name, base, prototype ) { + var fullName, existingConstructor, constructor, basePrototype, + // proxiedPrototype allows the provided prototype to remain unmodified + // so that it can be used as a mixin for multiple widgets (#8876) + proxiedPrototype = {}, + namespace = name.split( "." )[ 0 ]; + + name = name.split( "." )[ 1 ]; + fullName = namespace + "-" + name; + + if ( !prototype ) { + prototype = base; + base = $.Widget; + } + + // create selector for plugin + $.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) { + return !!$.data( elem, fullName ); + }; + + $[ namespace ] = $[ namespace ] || {}; + existingConstructor = $[ namespace ][ name ]; + constructor = $[ namespace ][ name ] = function( options, element ) { + // allow instantiation without "new" keyword + if ( !this._createWidget ) { + return new constructor( options, element ); + } + + // allow instantiation without initializing for simple inheritance + // must use "new" keyword (the code above always passes args) + if ( arguments.length ) { + this._createWidget( options, element ); + } + }; + // extend with the existing constructor to carry over any static properties + $.extend( constructor, existingConstructor, { + version: prototype.version, + // copy the object used to create the prototype in case we need to + // redefine the widget later + _proto: $.extend( {}, prototype ), + // track widgets that inherit from this widget in case this widget is + // redefined after a widget inherits from it + _childConstructors: [] + }); + + basePrototype = new base(); + // we need to make the options hash a property directly on the new instance + // otherwise we'll modify the options hash on the prototype that we're + // inheriting from + basePrototype.options = $.widget.extend( {}, basePrototype.options ); + $.each( prototype, function( prop, value ) { + if ( !$.isFunction( value ) ) { + proxiedPrototype[ prop ] = value; + return; + } + proxiedPrototype[ prop ] = (function() { + var _super = function() { + return base.prototype[ prop ].apply( this, arguments ); + }, + _superApply = function( args ) { + return base.prototype[ prop ].apply( this, args ); + }; + return function() { + var __super = this._super, + __superApply = this._superApply, + returnValue; + + this._super = _super; + this._superApply = _superApply; + + returnValue = value.apply( this, arguments ); + + this._super = __super; + this._superApply = __superApply; + + return returnValue; + }; + })(); + }); + constructor.prototype = $.widget.extend( basePrototype, { + // TODO: remove support for widgetEventPrefix + // always use the name + a colon as the prefix, e.g., draggable:start + // don't prefix for widgets that aren't DOM-based + widgetEventPrefix: existingConstructor ? basePrototype.widgetEventPrefix : name + }, proxiedPrototype, { + constructor: constructor, + namespace: namespace, + widgetName: name, + widgetFullName: fullName + }); + + // If this widget is being redefined then we need to find all widgets that + // are inheriting from it and redefine all of them so that they inherit from + // the new version of this widget. We're essentially trying to replace one + // level in the prototype chain. + if ( existingConstructor ) { + $.each( existingConstructor._childConstructors, function( i, child ) { + var childPrototype = child.prototype; + + // redefine the child widget using the same prototype that was + // originally used, but inherit from the new version of the base + $.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor, child._proto ); + }); + // remove the list of existing child constructors from the old constructor + // so the old child constructors can be garbage collected + delete existingConstructor._childConstructors; + } else { + base._childConstructors.push( constructor ); + } + + $.widget.bridge( name, constructor ); +}; + +$.widget.extend = function( target ) { + var input = slice.call( arguments, 1 ), + inputIndex = 0, + inputLength = input.length, + key, + value; + for ( ; inputIndex < inputLength; inputIndex++ ) { + for ( key in input[ inputIndex ] ) { + value = input[ inputIndex ][ key ]; + if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) { + // Clone objects + if ( $.isPlainObject( value ) ) { + target[ key ] = $.isPlainObject( target[ key ] ) ? + $.widget.extend( {}, target[ key ], value ) : + // Don't extend strings, arrays, etc. with objects + $.widget.extend( {}, value ); + // Copy everything else by reference + } else { + target[ key ] = value; + } + } + } + } + return target; +}; + +$.widget.bridge = function( name, object ) { + var fullName = object.prototype.widgetFullName || name; + $.fn[ name ] = function( options ) { + var isMethodCall = typeof options === "string", + args = slice.call( arguments, 1 ), + returnValue = this; + + // allow multiple hashes to be passed on init + options = !isMethodCall && args.length ? + $.widget.extend.apply( null, [ options ].concat(args) ) : + options; + + if ( isMethodCall ) { + this.each(function() { + var methodValue, + instance = $.data( this, fullName ); + if ( !instance ) { + return $.error( "cannot call methods on " + name + " prior to initialization; " + + "attempted to call method '" + options + "'" ); + } + if ( !$.isFunction( instance[options] ) || options.charAt( 0 ) === "_" ) { + return $.error( "no such method '" + options + "' for " + name + " widget instance" ); + } + methodValue = instance[ options ].apply( instance, args ); + if ( methodValue !== instance && methodValue !== undefined ) { + returnValue = methodValue && methodValue.jquery ? + returnValue.pushStack( methodValue.get() ) : + methodValue; + return false; + } + }); + } else { + this.each(function() { + var instance = $.data( this, fullName ); + if ( instance ) { + instance.option( options || {} )._init(); + } else { + $.data( this, fullName, new object( options, this ) ); + } + }); + } + + return returnValue; + }; +}; + +$.Widget = function( /* options, element */ ) {}; +$.Widget._childConstructors = []; + +$.Widget.prototype = { + widgetName: "widget", + widgetEventPrefix: "", + defaultElement: "
", + options: { + disabled: false, + + // callbacks + create: null + }, + _createWidget: function( options, element ) { + element = $( element || this.defaultElement || this )[ 0 ]; + this.element = $( element ); + this.uuid = uuid++; + this.eventNamespace = "." + this.widgetName + this.uuid; + this.options = $.widget.extend( {}, + this.options, + this._getCreateOptions(), + options ); + + this.bindings = $(); + this.hoverable = $(); + this.focusable = $(); + + if ( element !== this ) { + $.data( element, this.widgetFullName, this ); + this._on( true, this.element, { + remove: function( event ) { + if ( event.target === element ) { + this.destroy(); + } + } + }); + this.document = $( element.style ? + // element within the document + element.ownerDocument : + // element is window or document + element.document || element ); + this.window = $( this.document[0].defaultView || this.document[0].parentWindow ); + } + + this._create(); + this._trigger( "create", null, this._getCreateEventData() ); + this._init(); + }, + _getCreateOptions: $.noop, + _getCreateEventData: $.noop, + _create: $.noop, + _init: $.noop, + + destroy: function() { + this._destroy(); + // we can probably remove the unbind calls in 2.0 + // all event bindings should go through this._on() + this.element + .unbind( this.eventNamespace ) + // 1.9 BC for #7810 + // TODO remove dual storage + .removeData( this.widgetName ) + .removeData( this.widgetFullName ) + // support: jquery <1.6.3 + // http://bugs.jquery.com/ticket/9413 + .removeData( $.camelCase( this.widgetFullName ) ); + this.widget() + .unbind( this.eventNamespace ) + .removeAttr( "aria-disabled" ) + .removeClass( + this.widgetFullName + "-disabled " + + "ui-state-disabled" ); + + // clean up events and states + this.bindings.unbind( this.eventNamespace ); + this.hoverable.removeClass( "ui-state-hover" ); + this.focusable.removeClass( "ui-state-focus" ); + }, + _destroy: $.noop, + + widget: function() { + return this.element; + }, + + option: function( key, value ) { + var options = key, + parts, + curOption, + i; + + if ( arguments.length === 0 ) { + // don't return a reference to the internal hash + return $.widget.extend( {}, this.options ); + } + + if ( typeof key === "string" ) { + // handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } } + options = {}; + parts = key.split( "." ); + key = parts.shift(); + if ( parts.length ) { + curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] ); + for ( i = 0; i < parts.length - 1; i++ ) { + curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {}; + curOption = curOption[ parts[ i ] ]; + } + key = parts.pop(); + if ( value === undefined ) { + return curOption[ key ] === undefined ? null : curOption[ key ]; + } + curOption[ key ] = value; + } else { + if ( value === undefined ) { + return this.options[ key ] === undefined ? null : this.options[ key ]; + } + options[ key ] = value; + } + } + + this._setOptions( options ); + + return this; + }, + _setOptions: function( options ) { + var key; + + for ( key in options ) { + this._setOption( key, options[ key ] ); + } + + return this; + }, + _setOption: function( key, value ) { + this.options[ key ] = value; + + if ( key === "disabled" ) { + this.widget() + .toggleClass( this.widgetFullName + "-disabled ui-state-disabled", !!value ) + .attr( "aria-disabled", value ); + this.hoverable.removeClass( "ui-state-hover" ); + this.focusable.removeClass( "ui-state-focus" ); + } + + return this; + }, + + enable: function() { + return this._setOption( "disabled", false ); + }, + disable: function() { + return this._setOption( "disabled", true ); + }, + + _on: function( suppressDisabledCheck, element, handlers ) { + var delegateElement, + instance = this; + + // no suppressDisabledCheck flag, shuffle arguments + if ( typeof suppressDisabledCheck !== "boolean" ) { + handlers = element; + element = suppressDisabledCheck; + suppressDisabledCheck = false; + } + + // no element argument, shuffle and use this.element + if ( !handlers ) { + handlers = element; + element = this.element; + delegateElement = this.widget(); + } else { + // accept selectors, DOM elements + element = delegateElement = $( element ); + this.bindings = this.bindings.add( element ); + } + + $.each( handlers, function( event, handler ) { + function handlerProxy() { + // allow widgets to customize the disabled handling + // - disabled as an array instead of boolean + // - disabled class as method for disabling individual parts + if ( !suppressDisabledCheck && + ( instance.options.disabled === true || + $( this ).hasClass( "ui-state-disabled" ) ) ) { + return; + } + return ( typeof handler === "string" ? instance[ handler ] : handler ) + .apply( instance, arguments ); + } + + // copy the guid so direct unbinding works + if ( typeof handler !== "string" ) { + handlerProxy.guid = handler.guid = + handler.guid || handlerProxy.guid || $.guid++; + } + + var match = event.match( /^(\w+)\s*(.*)$/ ), + eventName = match[1] + instance.eventNamespace, + selector = match[2]; + if ( selector ) { + delegateElement.delegate( selector, eventName, handlerProxy ); + } else { + element.bind( eventName, handlerProxy ); + } + }); + }, + + _off: function( element, eventName ) { + eventName = (eventName || "").split( " " ).join( this.eventNamespace + " " ) + this.eventNamespace; + element.unbind( eventName ).undelegate( eventName ); + }, + + _delay: function( handler, delay ) { + function handlerProxy() { + return ( typeof handler === "string" ? instance[ handler ] : handler ) + .apply( instance, arguments ); + } + var instance = this; + return setTimeout( handlerProxy, delay || 0 ); + }, + + _hoverable: function( element ) { + this.hoverable = this.hoverable.add( element ); + this._on( element, { + mouseenter: function( event ) { + $( event.currentTarget ).addClass( "ui-state-hover" ); + }, + mouseleave: function( event ) { + $( event.currentTarget ).removeClass( "ui-state-hover" ); + } + }); + }, + + _focusable: function( element ) { + this.focusable = this.focusable.add( element ); + this._on( element, { + focusin: function( event ) { + $( event.currentTarget ).addClass( "ui-state-focus" ); + }, + focusout: function( event ) { + $( event.currentTarget ).removeClass( "ui-state-focus" ); + } + }); + }, + + _trigger: function( type, event, data ) { + var prop, orig, + callback = this.options[ type ]; + + data = data || {}; + event = $.Event( event ); + event.type = ( type === this.widgetEventPrefix ? + type : + this.widgetEventPrefix + type ).toLowerCase(); + // the original event may come from any element + // so we need to reset the target on the new event + event.target = this.element[ 0 ]; + + // copy original event properties over to the new event + orig = event.originalEvent; + if ( orig ) { + for ( prop in orig ) { + if ( !( prop in event ) ) { + event[ prop ] = orig[ prop ]; + } + } + } + + this.element.trigger( event, data ); + return !( $.isFunction( callback ) && + callback.apply( this.element[0], [ event ].concat( data ) ) === false || + event.isDefaultPrevented() ); + } +}; + +$.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) { + $.Widget.prototype[ "_" + method ] = function( element, options, callback ) { + if ( typeof options === "string" ) { + options = { effect: options }; + } + var hasOptions, + effectName = !options ? + method : + options === true || typeof options === "number" ? + defaultEffect : + options.effect || defaultEffect; + options = options || {}; + if ( typeof options === "number" ) { + options = { duration: options }; + } + hasOptions = !$.isEmptyObject( options ); + options.complete = callback; + if ( options.delay ) { + element.delay( options.delay ); + } + if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) { + element[ method ]( options ); + } else if ( effectName !== method && element[ effectName ] ) { + element[ effectName ]( options.duration, options.easing, callback ); + } else { + element.queue(function( next ) { + $( this )[ method ](); + if ( callback ) { + callback.call( element[ 0 ] ); + } + next(); + }); + } + }; +}); + +})( jQuery ); + +(function( $, undefined ) { + +var mouseHandled = false; +$( document ).mouseup( function() { + mouseHandled = false; +}); + +$.widget("ui.mouse", { + version: "1.10.2", + options: { + cancel: "input,textarea,button,select,option", + distance: 1, + delay: 0 + }, + _mouseInit: function() { + var that = this; + + this.element + .bind("mousedown."+this.widgetName, function(event) { + return that._mouseDown(event); + }) + .bind("click."+this.widgetName, function(event) { + if (true === $.data(event.target, that.widgetName + ".preventClickEvent")) { + $.removeData(event.target, that.widgetName + ".preventClickEvent"); + event.stopImmediatePropagation(); + return false; + } + }); + + this.started = false; + }, + + // TODO: make sure destroying one instance of mouse doesn't mess with + // other instances of mouse + _mouseDestroy: function() { + this.element.unbind("."+this.widgetName); + if ( this._mouseMoveDelegate ) { + $(document) + .unbind("mousemove."+this.widgetName, this._mouseMoveDelegate) + .unbind("mouseup."+this.widgetName, this._mouseUpDelegate); + } + }, + + _mouseDown: function(event) { + // don't let more than one widget handle mouseStart + if( mouseHandled ) { return; } + + // we may have missed mouseup (out of window) + (this._mouseStarted && this._mouseUp(event)); + + this._mouseDownEvent = event; + + var that = this, + btnIsLeft = (event.which === 1), + // event.target.nodeName works around a bug in IE 8 with + // disabled inputs (#7620) + elIsCancel = (typeof this.options.cancel === "string" && event.target.nodeName ? $(event.target).closest(this.options.cancel).length : false); + if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) { + return true; + } + + this.mouseDelayMet = !this.options.delay; + if (!this.mouseDelayMet) { + this._mouseDelayTimer = setTimeout(function() { + that.mouseDelayMet = true; + }, this.options.delay); + } + + if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) { + this._mouseStarted = (this._mouseStart(event) !== false); + if (!this._mouseStarted) { + event.preventDefault(); + return true; + } + } + + // Click event may never have fired (Gecko & Opera) + if (true === $.data(event.target, this.widgetName + ".preventClickEvent")) { + $.removeData(event.target, this.widgetName + ".preventClickEvent"); + } + + // these delegates are required to keep context + this._mouseMoveDelegate = function(event) { + return that._mouseMove(event); + }; + this._mouseUpDelegate = function(event) { + return that._mouseUp(event); + }; + $(document) + .bind("mousemove."+this.widgetName, this._mouseMoveDelegate) + .bind("mouseup."+this.widgetName, this._mouseUpDelegate); + + event.preventDefault(); + + mouseHandled = true; + return true; + }, + + _mouseMove: function(event) { + // IE mouseup check - mouseup happened when mouse was out of window + if ($.ui.ie && ( !document.documentMode || document.documentMode < 9 ) && !event.button) { + return this._mouseUp(event); + } + + if (this._mouseStarted) { + this._mouseDrag(event); + return event.preventDefault(); + } + + if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) { + this._mouseStarted = + (this._mouseStart(this._mouseDownEvent, event) !== false); + (this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event)); + } + + return !this._mouseStarted; + }, + + _mouseUp: function(event) { + $(document) + .unbind("mousemove."+this.widgetName, this._mouseMoveDelegate) + .unbind("mouseup."+this.widgetName, this._mouseUpDelegate); + + if (this._mouseStarted) { + this._mouseStarted = false; + + if (event.target === this._mouseDownEvent.target) { + $.data(event.target, this.widgetName + ".preventClickEvent", true); + } + + this._mouseStop(event); + } + + return false; + }, + + _mouseDistanceMet: function(event) { + return (Math.max( + Math.abs(this._mouseDownEvent.pageX - event.pageX), + Math.abs(this._mouseDownEvent.pageY - event.pageY) + ) >= this.options.distance + ); + }, + + _mouseDelayMet: function(/* event */) { + return this.mouseDelayMet; + }, + + // These are placeholder methods, to be overriden by extending plugin + _mouseStart: function(/* event */) {}, + _mouseDrag: function(/* event */) {}, + _mouseStop: function(/* event */) {}, + _mouseCapture: function(/* event */) { return true; } +}); + +})(jQuery); + +(function( $, undefined ) { + +$.widget("ui.draggable", $.ui.mouse, { + version: "1.10.2", + widgetEventPrefix: "drag", + options: { + addClasses: true, + appendTo: "parent", + axis: false, + connectToSortable: false, + containment: false, + cursor: "auto", + cursorAt: false, + grid: false, + handle: false, + helper: "original", + iframeFix: false, + opacity: false, + refreshPositions: false, + revert: false, + revertDuration: 500, + scope: "default", + scroll: true, + scrollSensitivity: 20, + scrollSpeed: 20, + snap: false, + snapMode: "both", + snapTolerance: 20, + stack: false, + zIndex: false, + + // callbacks + drag: null, + start: null, + stop: null + }, + _create: function() { + + if (this.options.helper === "original" && !(/^(?:r|a|f)/).test(this.element.css("position"))) { + this.element[0].style.position = "relative"; + } + if (this.options.addClasses){ + this.element.addClass("ui-draggable"); + } + if (this.options.disabled){ + this.element.addClass("ui-draggable-disabled"); + } + + this._mouseInit(); + + }, + + _destroy: function() { + this.element.removeClass( "ui-draggable ui-draggable-dragging ui-draggable-disabled" ); + this._mouseDestroy(); + }, + + _mouseCapture: function(event) { + + var o = this.options; + + // among others, prevent a drag on a resizable-handle + if (this.helper || o.disabled || $(event.target).closest(".ui-resizable-handle").length > 0) { + return false; + } + + //Quit if we're not on a valid handle + this.handle = this._getHandle(event); + if (!this.handle) { + return false; + } + + $(o.iframeFix === true ? "iframe" : o.iframeFix).each(function() { + $("
") + .css({ + width: this.offsetWidth+"px", height: this.offsetHeight+"px", + position: "absolute", opacity: "0.001", zIndex: 1000 + }) + .css($(this).offset()) + .appendTo("body"); + }); + + return true; + + }, + + _mouseStart: function(event) { + + var o = this.options; + + //Create and append the visible helper + this.helper = this._createHelper(event); + + this.helper.addClass("ui-draggable-dragging"); + + //Cache the helper size + this._cacheHelperProportions(); + + //If ddmanager is used for droppables, set the global draggable + if($.ui.ddmanager) { + $.ui.ddmanager.current = this; + } + + /* + * - Position generation - + * This block generates everything position related - it's the core of draggables. + */ + + //Cache the margins of the original element + this._cacheMargins(); + + //Store the helper's css position + this.cssPosition = this.helper.css("position"); + this.scrollParent = this.helper.scrollParent(); + + //The element's absolute position on the page minus margins + this.offset = this.positionAbs = this.element.offset(); + this.offset = { + top: this.offset.top - this.margins.top, + left: this.offset.left - this.margins.left + }; + + $.extend(this.offset, { + click: { //Where the click happened, relative to the element + left: event.pageX - this.offset.left, + top: event.pageY - this.offset.top + }, + parent: this._getParentOffset(), + relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper + }); + + //Generate the original position + this.originalPosition = this.position = this._generatePosition(event); + this.originalPageX = event.pageX; + this.originalPageY = event.pageY; + + //Adjust the mouse offset relative to the helper if "cursorAt" is supplied + (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt)); + + //Set a containment if given in the options + if(o.containment) { + this._setContainment(); + } + + //Trigger event + callbacks + if(this._trigger("start", event) === false) { + this._clear(); + return false; + } + + //Recache the helper size + this._cacheHelperProportions(); + + //Prepare the droppable offsets + if ($.ui.ddmanager && !o.dropBehaviour) { + $.ui.ddmanager.prepareOffsets(this, event); + } + + + this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position + + //If the ddmanager is used for droppables, inform the manager that dragging has started (see #5003) + if ( $.ui.ddmanager ) { + $.ui.ddmanager.dragStart(this, event); + } + + return true; + }, + + _mouseDrag: function(event, noPropagation) { + + //Compute the helpers position + this.position = this._generatePosition(event); + this.positionAbs = this._convertPositionTo("absolute"); + + //Call plugins and callbacks and use the resulting position if something is returned + if (!noPropagation) { + var ui = this._uiHash(); + if(this._trigger("drag", event, ui) === false) { + this._mouseUp({}); + return false; + } + this.position = ui.position; + } + + if(!this.options.axis || this.options.axis !== "y") { + this.helper[0].style.left = this.position.left+"px"; + } + if(!this.options.axis || this.options.axis !== "x") { + this.helper[0].style.top = this.position.top+"px"; + } + if($.ui.ddmanager) { + $.ui.ddmanager.drag(this, event); + } + + return false; + }, + + _mouseStop: function(event) { + + //If we are using droppables, inform the manager about the drop + var element, + that = this, + elementInDom = false, + dropped = false; + if ($.ui.ddmanager && !this.options.dropBehaviour) { + dropped = $.ui.ddmanager.drop(this, event); + } + + //if a drop comes from outside (a sortable) + if(this.dropped) { + dropped = this.dropped; + this.dropped = false; + } + + //if the original element is no longer in the DOM don't bother to continue (see #8269) + element = this.element[0]; + while ( element && (element = element.parentNode) ) { + if (element === document ) { + elementInDom = true; + } + } + if ( !elementInDom && this.options.helper === "original" ) { + return false; + } + + if((this.options.revert === "invalid" && !dropped) || (this.options.revert === "valid" && dropped) || this.options.revert === true || ($.isFunction(this.options.revert) && this.options.revert.call(this.element, dropped))) { + $(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() { + if(that._trigger("stop", event) !== false) { + that._clear(); + } + }); + } else { + if(this._trigger("stop", event) !== false) { + this._clear(); + } + } + + return false; + }, + + _mouseUp: function(event) { + //Remove frame helpers + $("div.ui-draggable-iframeFix").each(function() { + this.parentNode.removeChild(this); + }); + + //If the ddmanager is used for droppables, inform the manager that dragging has stopped (see #5003) + if( $.ui.ddmanager ) { + $.ui.ddmanager.dragStop(this, event); + } + + return $.ui.mouse.prototype._mouseUp.call(this, event); + }, + + cancel: function() { + + if(this.helper.is(".ui-draggable-dragging")) { + this._mouseUp({}); + } else { + this._clear(); + } + + return this; + + }, + + _getHandle: function(event) { + return this.options.handle ? + !!$( event.target ).closest( this.element.find( this.options.handle ) ).length : + true; + }, + + _createHelper: function(event) { + + var o = this.options, + helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event])) : (o.helper === "clone" ? this.element.clone().removeAttr("id") : this.element); + + if(!helper.parents("body").length) { + helper.appendTo((o.appendTo === "parent" ? this.element[0].parentNode : o.appendTo)); + } + + if(helper[0] !== this.element[0] && !(/(fixed|absolute)/).test(helper.css("position"))) { + helper.css("position", "absolute"); + } + + return helper; + + }, + + _adjustOffsetFromHelper: function(obj) { + if (typeof obj === "string") { + obj = obj.split(" "); + } + if ($.isArray(obj)) { + obj = {left: +obj[0], top: +obj[1] || 0}; + } + if ("left" in obj) { + this.offset.click.left = obj.left + this.margins.left; + } + if ("right" in obj) { + this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left; + } + if ("top" in obj) { + this.offset.click.top = obj.top + this.margins.top; + } + if ("bottom" in obj) { + this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top; + } + }, + + _getParentOffset: function() { + + //Get the offsetParent and cache its position + this.offsetParent = this.helper.offsetParent(); + var po = this.offsetParent.offset(); + + // This is a special case where we need to modify a offset calculated on start, since the following happened: + // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent + // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that + // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag + if(this.cssPosition === "absolute" && this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) { + po.left += this.scrollParent.scrollLeft(); + po.top += this.scrollParent.scrollTop(); + } + + //This needs to be actually done for all browsers, since pageX/pageY includes this information + //Ugly IE fix + if((this.offsetParent[0] === document.body) || + (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() === "html" && $.ui.ie)) { + po = { top: 0, left: 0 }; + } + + return { + top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0), + left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0) + }; + + }, + + _getRelativeOffset: function() { + + if(this.cssPosition === "relative") { + var p = this.element.position(); + return { + top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(), + left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft() + }; + } else { + return { top: 0, left: 0 }; + } + + }, + + _cacheMargins: function() { + this.margins = { + left: (parseInt(this.element.css("marginLeft"),10) || 0), + top: (parseInt(this.element.css("marginTop"),10) || 0), + right: (parseInt(this.element.css("marginRight"),10) || 0), + bottom: (parseInt(this.element.css("marginBottom"),10) || 0) + }; + }, + + _cacheHelperProportions: function() { + this.helperProportions = { + width: this.helper.outerWidth(), + height: this.helper.outerHeight() + }; + }, + + _setContainment: function() { + + var over, c, ce, + o = this.options; + + if(o.containment === "parent") { + o.containment = this.helper[0].parentNode; + } + if(o.containment === "document" || o.containment === "window") { + this.containment = [ + o.containment === "document" ? 0 : $(window).scrollLeft() - this.offset.relative.left - this.offset.parent.left, + o.containment === "document" ? 0 : $(window).scrollTop() - this.offset.relative.top - this.offset.parent.top, + (o.containment === "document" ? 0 : $(window).scrollLeft()) + $(o.containment === "document" ? document : window).width() - this.helperProportions.width - this.margins.left, + (o.containment === "document" ? 0 : $(window).scrollTop()) + ($(o.containment === "document" ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top + ]; + } + + if(!(/^(document|window|parent)$/).test(o.containment) && o.containment.constructor !== Array) { + c = $(o.containment); + ce = c[0]; + + if(!ce) { + return; + } + + over = ($(ce).css("overflow") !== "hidden"); + + this.containment = [ + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0), + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0), + (over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderRightWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left - this.margins.right, + (over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderBottomWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top - this.margins.bottom + ]; + this.relative_container = c; + + } else if(o.containment.constructor === Array) { + this.containment = o.containment; + } + + }, + + _convertPositionTo: function(d, pos) { + + if(!pos) { + pos = this.position; + } + + var mod = d === "absolute" ? 1 : -1, + scroll = this.cssPosition === "absolute" && !(this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName); + + return { + top: ( + pos.top + // The absolute mouse position + this.offset.relative.top * mod + // Only for relative positioned nodes: Relative offset from element to offset parent + this.offset.parent.top * mod - // The offsetParent's offset without borders (offset + border) + ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod) + ), + left: ( + pos.left + // The absolute mouse position + this.offset.relative.left * mod + // Only for relative positioned nodes: Relative offset from element to offset parent + this.offset.parent.left * mod - // The offsetParent's offset without borders (offset + border) + ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod) + ) + }; + + }, + + _generatePosition: function(event) { + + var containment, co, top, left, + o = this.options, + scroll = this.cssPosition === "absolute" && !(this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, + scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName), + pageX = event.pageX, + pageY = event.pageY; + + /* + * - Position constraining - + * Constrain the position to a mix of grid, containment. + */ + + if(this.originalPosition) { //If we are not dragging yet, we won't check for options + if(this.containment) { + if (this.relative_container){ + co = this.relative_container.offset(); + containment = [ this.containment[0] + co.left, + this.containment[1] + co.top, + this.containment[2] + co.left, + this.containment[3] + co.top ]; + } + else { + containment = this.containment; + } + + if(event.pageX - this.offset.click.left < containment[0]) { + pageX = containment[0] + this.offset.click.left; + } + if(event.pageY - this.offset.click.top < containment[1]) { + pageY = containment[1] + this.offset.click.top; + } + if(event.pageX - this.offset.click.left > containment[2]) { + pageX = containment[2] + this.offset.click.left; + } + if(event.pageY - this.offset.click.top > containment[3]) { + pageY = containment[3] + this.offset.click.top; + } + } + + if(o.grid) { + //Check for grid elements set to 0 to prevent divide by 0 error causing invalid argument errors in IE (see ticket #6950) + top = o.grid[1] ? this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1] : this.originalPageY; + pageY = containment ? ((top - this.offset.click.top >= containment[1] || top - this.offset.click.top > containment[3]) ? top : ((top - this.offset.click.top >= containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top; + + left = o.grid[0] ? this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0] : this.originalPageX; + pageX = containment ? ((left - this.offset.click.left >= containment[0] || left - this.offset.click.left > containment[2]) ? left : ((left - this.offset.click.left >= containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left; + } + + } + + return { + top: ( + pageY - // The absolute mouse position + this.offset.click.top - // Click offset (relative to the element) + this.offset.relative.top - // Only for relative positioned nodes: Relative offset from element to offset parent + this.offset.parent.top + // The offsetParent's offset without borders (offset + border) + ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) )) + ), + left: ( + pageX - // The absolute mouse position + this.offset.click.left - // Click offset (relative to the element) + this.offset.relative.left - // Only for relative positioned nodes: Relative offset from element to offset parent + this.offset.parent.left + // The offsetParent's offset without borders (offset + border) + ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() )) + ) + }; + + }, + + _clear: function() { + this.helper.removeClass("ui-draggable-dragging"); + if(this.helper[0] !== this.element[0] && !this.cancelHelperRemoval) { + this.helper.remove(); + } + this.helper = null; + this.cancelHelperRemoval = false; + }, + + // From now on bulk stuff - mainly helpers + + _trigger: function(type, event, ui) { + ui = ui || this._uiHash(); + $.ui.plugin.call(this, type, [event, ui]); + //The absolute position has to be recalculated after plugins + if(type === "drag") { + this.positionAbs = this._convertPositionTo("absolute"); + } + return $.Widget.prototype._trigger.call(this, type, event, ui); + }, + + plugins: {}, + + _uiHash: function() { + return { + helper: this.helper, + position: this.position, + originalPosition: this.originalPosition, + offset: this.positionAbs + }; + } + +}); + +$.ui.plugin.add("draggable", "connectToSortable", { + start: function(event, ui) { + + var inst = $(this).data("ui-draggable"), o = inst.options, + uiSortable = $.extend({}, ui, { item: inst.element }); + inst.sortables = []; + $(o.connectToSortable).each(function() { + var sortable = $.data(this, "ui-sortable"); + if (sortable && !sortable.options.disabled) { + inst.sortables.push({ + instance: sortable, + shouldRevert: sortable.options.revert + }); + sortable.refreshPositions(); // Call the sortable's refreshPositions at drag start to refresh the containerCache since the sortable container cache is used in drag and needs to be up to date (this will ensure it's initialised as well as being kept in step with any changes that might have happened on the page). + sortable._trigger("activate", event, uiSortable); + } + }); + + }, + stop: function(event, ui) { + + //If we are still over the sortable, we fake the stop event of the sortable, but also remove helper + var inst = $(this).data("ui-draggable"), + uiSortable = $.extend({}, ui, { item: inst.element }); + + $.each(inst.sortables, function() { + if(this.instance.isOver) { + + this.instance.isOver = 0; + + inst.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance + this.instance.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work) + + //The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: "valid/invalid" + if(this.shouldRevert) { + this.instance.options.revert = this.shouldRevert; + } + + //Trigger the stop of the sortable + this.instance._mouseStop(event); + + this.instance.options.helper = this.instance.options._helper; + + //If the helper has been the original item, restore properties in the sortable + if(inst.options.helper === "original") { + this.instance.currentItem.css({ top: "auto", left: "auto" }); + } + + } else { + this.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance + this.instance._trigger("deactivate", event, uiSortable); + } + + }); + + }, + drag: function(event, ui) { + + var inst = $(this).data("ui-draggable"), that = this; + + $.each(inst.sortables, function() { + + var innermostIntersecting = false, + thisSortable = this; + + //Copy over some variables to allow calling the sortable's native _intersectsWith + this.instance.positionAbs = inst.positionAbs; + this.instance.helperProportions = inst.helperProportions; + this.instance.offset.click = inst.offset.click; + + if(this.instance._intersectsWith(this.instance.containerCache)) { + innermostIntersecting = true; + $.each(inst.sortables, function () { + this.instance.positionAbs = inst.positionAbs; + this.instance.helperProportions = inst.helperProportions; + this.instance.offset.click = inst.offset.click; + if (this !== thisSortable && + this.instance._intersectsWith(this.instance.containerCache) && + $.contains(thisSortable.instance.element[0], this.instance.element[0]) + ) { + innermostIntersecting = false; + } + return innermostIntersecting; + }); + } + + + if(innermostIntersecting) { + //If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once + if(!this.instance.isOver) { + + this.instance.isOver = 1; + //Now we fake the start of dragging for the sortable instance, + //by cloning the list group item, appending it to the sortable and using it as inst.currentItem + //We can then fire the start event of the sortable with our passed browser event, and our own helper (so it doesn't create a new one) + this.instance.currentItem = $(that).clone().removeAttr("id").appendTo(this.instance.element).data("ui-sortable-item", true); + this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it + this.instance.options.helper = function() { return ui.helper[0]; }; + + event.target = this.instance.currentItem[0]; + this.instance._mouseCapture(event, true); + this.instance._mouseStart(event, true, true); + + //Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes + this.instance.offset.click.top = inst.offset.click.top; + this.instance.offset.click.left = inst.offset.click.left; + this.instance.offset.parent.left -= inst.offset.parent.left - this.instance.offset.parent.left; + this.instance.offset.parent.top -= inst.offset.parent.top - this.instance.offset.parent.top; + + inst._trigger("toSortable", event); + inst.dropped = this.instance.element; //draggable revert needs that + //hack so receive/update callbacks work (mostly) + inst.currentItem = inst.element; + this.instance.fromOutside = inst; + + } + + //Provided we did all the previous steps, we can fire the drag event of the sortable on every draggable drag, when it intersects with the sortable + if(this.instance.currentItem) { + this.instance._mouseDrag(event); + } + + } else { + + //If it doesn't intersect with the sortable, and it intersected before, + //we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval + if(this.instance.isOver) { + + this.instance.isOver = 0; + this.instance.cancelHelperRemoval = true; + + //Prevent reverting on this forced stop + this.instance.options.revert = false; + + // The out event needs to be triggered independently + this.instance._trigger("out", event, this.instance._uiHash(this.instance)); + + this.instance._mouseStop(event, true); + this.instance.options.helper = this.instance.options._helper; + + //Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size + this.instance.currentItem.remove(); + if(this.instance.placeholder) { + this.instance.placeholder.remove(); + } + + inst._trigger("fromSortable", event); + inst.dropped = false; //draggable revert needs that + } + + } + + }); + + } +}); + +$.ui.plugin.add("draggable", "cursor", { + start: function() { + var t = $("body"), o = $(this).data("ui-draggable").options; + if (t.css("cursor")) { + o._cursor = t.css("cursor"); + } + t.css("cursor", o.cursor); + }, + stop: function() { + var o = $(this).data("ui-draggable").options; + if (o._cursor) { + $("body").css("cursor", o._cursor); + } + } +}); + +$.ui.plugin.add("draggable", "opacity", { + start: function(event, ui) { + var t = $(ui.helper), o = $(this).data("ui-draggable").options; + if(t.css("opacity")) { + o._opacity = t.css("opacity"); + } + t.css("opacity", o.opacity); + }, + stop: function(event, ui) { + var o = $(this).data("ui-draggable").options; + if(o._opacity) { + $(ui.helper).css("opacity", o._opacity); + } + } +}); + +$.ui.plugin.add("draggable", "scroll", { + start: function() { + var i = $(this).data("ui-draggable"); + if(i.scrollParent[0] !== document && i.scrollParent[0].tagName !== "HTML") { + i.overflowOffset = i.scrollParent.offset(); + } + }, + drag: function( event ) { + + var i = $(this).data("ui-draggable"), o = i.options, scrolled = false; + + if(i.scrollParent[0] !== document && i.scrollParent[0].tagName !== "HTML") { + + if(!o.axis || o.axis !== "x") { + if((i.overflowOffset.top + i.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity) { + i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop + o.scrollSpeed; + } else if(event.pageY - i.overflowOffset.top < o.scrollSensitivity) { + i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop - o.scrollSpeed; + } + } + + if(!o.axis || o.axis !== "y") { + if((i.overflowOffset.left + i.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity) { + i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft + o.scrollSpeed; + } else if(event.pageX - i.overflowOffset.left < o.scrollSensitivity) { + i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft - o.scrollSpeed; + } + } + + } else { + + if(!o.axis || o.axis !== "x") { + if(event.pageY - $(document).scrollTop() < o.scrollSensitivity) { + scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed); + } else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) { + scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed); + } + } + + if(!o.axis || o.axis !== "y") { + if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity) { + scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed); + } else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) { + scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed); + } + } + + } + + if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) { + $.ui.ddmanager.prepareOffsets(i, event); + } + + } +}); + +$.ui.plugin.add("draggable", "snap", { + start: function() { + + var i = $(this).data("ui-draggable"), + o = i.options; + + i.snapElements = []; + + $(o.snap.constructor !== String ? ( o.snap.items || ":data(ui-draggable)" ) : o.snap).each(function() { + var $t = $(this), + $o = $t.offset(); + if(this !== i.element[0]) { + i.snapElements.push({ + item: this, + width: $t.outerWidth(), height: $t.outerHeight(), + top: $o.top, left: $o.left + }); + } + }); + + }, + drag: function(event, ui) { + + var ts, bs, ls, rs, l, r, t, b, i, first, + inst = $(this).data("ui-draggable"), + o = inst.options, + d = o.snapTolerance, + x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width, + y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height; + + for (i = inst.snapElements.length - 1; i >= 0; i--){ + + l = inst.snapElements[i].left; + r = l + inst.snapElements[i].width; + t = inst.snapElements[i].top; + b = t + inst.snapElements[i].height; + + //Yes, I know, this is insane ;) + if(!((l-d < x1 && x1 < r+d && t-d < y1 && y1 < b+d) || (l-d < x1 && x1 < r+d && t-d < y2 && y2 < b+d) || (l-d < x2 && x2 < r+d && t-d < y1 && y1 < b+d) || (l-d < x2 && x2 < r+d && t-d < y2 && y2 < b+d))) { + if(inst.snapElements[i].snapping) { + (inst.options.snap.release && inst.options.snap.release.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item }))); + } + inst.snapElements[i].snapping = false; + continue; + } + + if(o.snapMode !== "inner") { + ts = Math.abs(t - y2) <= d; + bs = Math.abs(b - y1) <= d; + ls = Math.abs(l - x2) <= d; + rs = Math.abs(r - x1) <= d; + if(ts) { + ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top; + } + if(bs) { + ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top; + } + if(ls) { + ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left; + } + if(rs) { + ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left; + } + } + + first = (ts || bs || ls || rs); + + if(o.snapMode !== "outer") { + ts = Math.abs(t - y1) <= d; + bs = Math.abs(b - y2) <= d; + ls = Math.abs(l - x1) <= d; + rs = Math.abs(r - x2) <= d; + if(ts) { + ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top - inst.margins.top; + } + if(bs) { + ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top - inst.margins.top; + } + if(ls) { + ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left; + } + if(rs) { + ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left; + } + } + + if(!inst.snapElements[i].snapping && (ts || bs || ls || rs || first)) { + (inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item }))); + } + inst.snapElements[i].snapping = (ts || bs || ls || rs || first); + + } + + } +}); + +$.ui.plugin.add("draggable", "stack", { + start: function() { + var min, + o = this.data("ui-draggable").options, + group = $.makeArray($(o.stack)).sort(function(a,b) { + return (parseInt($(a).css("zIndex"),10) || 0) - (parseInt($(b).css("zIndex"),10) || 0); + }); + + if (!group.length) { return; } + + min = parseInt($(group[0]).css("zIndex"), 10) || 0; + $(group).each(function(i) { + $(this).css("zIndex", min + i); + }); + this.css("zIndex", (min + group.length)); + } +}); + +$.ui.plugin.add("draggable", "zIndex", { + start: function(event, ui) { + var t = $(ui.helper), o = $(this).data("ui-draggable").options; + if(t.css("zIndex")) { + o._zIndex = t.css("zIndex"); + } + t.css("zIndex", o.zIndex); + }, + stop: function(event, ui) { + var o = $(this).data("ui-draggable").options; + if(o._zIndex) { + $(ui.helper).css("zIndex", o._zIndex); + } + } +}); + +})(jQuery); + +(function( $, undefined ) { + +function isOverAxis( x, reference, size ) { + return ( x > reference ) && ( x < ( reference + size ) ); +} + +$.widget("ui.droppable", { + version: "1.10.2", + widgetEventPrefix: "drop", + options: { + accept: "*", + activeClass: false, + addClasses: true, + greedy: false, + hoverClass: false, + scope: "default", + tolerance: "intersect", + + // callbacks + activate: null, + deactivate: null, + drop: null, + out: null, + over: null + }, + _create: function() { + + var o = this.options, + accept = o.accept; + + this.isover = false; + this.isout = true; + + this.accept = $.isFunction(accept) ? accept : function(d) { + return d.is(accept); + }; + + //Store the droppable's proportions + this.proportions = { width: this.element[0].offsetWidth, height: this.element[0].offsetHeight }; + + // Add the reference and positions to the manager + $.ui.ddmanager.droppables[o.scope] = $.ui.ddmanager.droppables[o.scope] || []; + $.ui.ddmanager.droppables[o.scope].push(this); + + (o.addClasses && this.element.addClass("ui-droppable")); + + }, + + _destroy: function() { + var i = 0, + drop = $.ui.ddmanager.droppables[this.options.scope]; + + for ( ; i < drop.length; i++ ) { + if ( drop[i] === this ) { + drop.splice(i, 1); + } + } + + this.element.removeClass("ui-droppable ui-droppable-disabled"); + }, + + _setOption: function(key, value) { + + if(key === "accept") { + this.accept = $.isFunction(value) ? value : function(d) { + return d.is(value); + }; + } + $.Widget.prototype._setOption.apply(this, arguments); + }, + + _activate: function(event) { + var draggable = $.ui.ddmanager.current; + if(this.options.activeClass) { + this.element.addClass(this.options.activeClass); + } + if(draggable){ + this._trigger("activate", event, this.ui(draggable)); + } + }, + + _deactivate: function(event) { + var draggable = $.ui.ddmanager.current; + if(this.options.activeClass) { + this.element.removeClass(this.options.activeClass); + } + if(draggable){ + this._trigger("deactivate", event, this.ui(draggable)); + } + }, + + _over: function(event) { + + var draggable = $.ui.ddmanager.current; + + // Bail if draggable and droppable are same element + if (!draggable || (draggable.currentItem || draggable.element)[0] === this.element[0]) { + return; + } + + if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) { + if(this.options.hoverClass) { + this.element.addClass(this.options.hoverClass); + } + this._trigger("over", event, this.ui(draggable)); + } + + }, + + _out: function(event) { + + var draggable = $.ui.ddmanager.current; + + // Bail if draggable and droppable are same element + if (!draggable || (draggable.currentItem || draggable.element)[0] === this.element[0]) { + return; + } + + if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) { + if(this.options.hoverClass) { + this.element.removeClass(this.options.hoverClass); + } + this._trigger("out", event, this.ui(draggable)); + } + + }, + + _drop: function(event,custom) { + + var draggable = custom || $.ui.ddmanager.current, + childrenIntersection = false; + + // Bail if draggable and droppable are same element + if (!draggable || (draggable.currentItem || draggable.element)[0] === this.element[0]) { + return false; + } + + this.element.find(":data(ui-droppable)").not(".ui-draggable-dragging").each(function() { + var inst = $.data(this, "ui-droppable"); + if( + inst.options.greedy && + !inst.options.disabled && + inst.options.scope === draggable.options.scope && + inst.accept.call(inst.element[0], (draggable.currentItem || draggable.element)) && + $.ui.intersect(draggable, $.extend(inst, { offset: inst.element.offset() }), inst.options.tolerance) + ) { childrenIntersection = true; return false; } + }); + if(childrenIntersection) { + return false; + } + + if(this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) { + if(this.options.activeClass) { + this.element.removeClass(this.options.activeClass); + } + if(this.options.hoverClass) { + this.element.removeClass(this.options.hoverClass); + } + this._trigger("drop", event, this.ui(draggable)); + return this.element; + } + + return false; + + }, + + ui: function(c) { + return { + draggable: (c.currentItem || c.element), + helper: c.helper, + position: c.position, + offset: c.positionAbs + }; + } + +}); + +$.ui.intersect = function(draggable, droppable, toleranceMode) { + + if (!droppable.offset) { + return false; + } + + var draggableLeft, draggableTop, + x1 = (draggable.positionAbs || draggable.position.absolute).left, x2 = x1 + draggable.helperProportions.width, + y1 = (draggable.positionAbs || draggable.position.absolute).top, y2 = y1 + draggable.helperProportions.height, + l = droppable.offset.left, r = l + droppable.proportions.width, + t = droppable.offset.top, b = t + droppable.proportions.height; + + switch (toleranceMode) { + case "fit": + return (l <= x1 && x2 <= r && t <= y1 && y2 <= b); + case "intersect": + return (l < x1 + (draggable.helperProportions.width / 2) && // Right Half + x2 - (draggable.helperProportions.width / 2) < r && // Left Half + t < y1 + (draggable.helperProportions.height / 2) && // Bottom Half + y2 - (draggable.helperProportions.height / 2) < b ); // Top Half + case "pointer": + draggableLeft = ((draggable.positionAbs || draggable.position.absolute).left + (draggable.clickOffset || draggable.offset.click).left); + draggableTop = ((draggable.positionAbs || draggable.position.absolute).top + (draggable.clickOffset || draggable.offset.click).top); + return isOverAxis( draggableTop, t, droppable.proportions.height ) && isOverAxis( draggableLeft, l, droppable.proportions.width ); + case "touch": + return ( + (y1 >= t && y1 <= b) || // Top edge touching + (y2 >= t && y2 <= b) || // Bottom edge touching + (y1 < t && y2 > b) // Surrounded vertically + ) && ( + (x1 >= l && x1 <= r) || // Left edge touching + (x2 >= l && x2 <= r) || // Right edge touching + (x1 < l && x2 > r) // Surrounded horizontally + ); + default: + return false; + } + +}; + +/* + This manager tracks offsets of draggables and droppables +*/ +$.ui.ddmanager = { + current: null, + droppables: { "default": [] }, + prepareOffsets: function(t, event) { + + var i, j, + m = $.ui.ddmanager.droppables[t.options.scope] || [], + type = event ? event.type : null, // workaround for #2317 + list = (t.currentItem || t.element).find(":data(ui-droppable)").addBack(); + + droppablesLoop: for (i = 0; i < m.length; i++) { + + //No disabled and non-accepted + if(m[i].options.disabled || (t && !m[i].accept.call(m[i].element[0],(t.currentItem || t.element)))) { + continue; + } + + // Filter out elements in the current dragged item + for (j=0; j < list.length; j++) { + if(list[j] === m[i].element[0]) { + m[i].proportions.height = 0; + continue droppablesLoop; + } + } + + m[i].visible = m[i].element.css("display") !== "none"; + if(!m[i].visible) { + continue; + } + + //Activate the droppable if used directly from draggables + if(type === "mousedown") { + m[i]._activate.call(m[i], event); + } + + m[i].offset = m[i].element.offset(); + m[i].proportions = { width: m[i].element[0].offsetWidth, height: m[i].element[0].offsetHeight }; + + } + + }, + drop: function(draggable, event) { + + var dropped = false; + // Create a copy of the droppables in case the list changes during the drop (#9116) + $.each(($.ui.ddmanager.droppables[draggable.options.scope] || []).slice(), function() { + + if(!this.options) { + return; + } + if (!this.options.disabled && this.visible && $.ui.intersect(draggable, this, this.options.tolerance)) { + dropped = this._drop.call(this, event) || dropped; + } + + if (!this.options.disabled && this.visible && this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) { + this.isout = true; + this.isover = false; + this._deactivate.call(this, event); + } + + }); + return dropped; + + }, + dragStart: function( draggable, event ) { + //Listen for scrolling so that if the dragging causes scrolling the position of the droppables can be recalculated (see #5003) + draggable.element.parentsUntil( "body" ).bind( "scroll.droppable", function() { + if( !draggable.options.refreshPositions ) { + $.ui.ddmanager.prepareOffsets( draggable, event ); + } + }); + }, + drag: function(draggable, event) { + + //If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse. + if(draggable.options.refreshPositions) { + $.ui.ddmanager.prepareOffsets(draggable, event); + } + + //Run through all droppables and check their positions based on specific tolerance options + $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() { + + if(this.options.disabled || this.greedyChild || !this.visible) { + return; + } + + var parentInstance, scope, parent, + intersects = $.ui.intersect(draggable, this, this.options.tolerance), + c = !intersects && this.isover ? "isout" : (intersects && !this.isover ? "isover" : null); + if(!c) { + return; + } + + if (this.options.greedy) { + // find droppable parents with same scope + scope = this.options.scope; + parent = this.element.parents(":data(ui-droppable)").filter(function () { + return $.data(this, "ui-droppable").options.scope === scope; + }); + + if (parent.length) { + parentInstance = $.data(parent[0], "ui-droppable"); + parentInstance.greedyChild = (c === "isover"); + } + } + + // we just moved into a greedy child + if (parentInstance && c === "isover") { + parentInstance.isover = false; + parentInstance.isout = true; + parentInstance._out.call(parentInstance, event); + } + + this[c] = true; + this[c === "isout" ? "isover" : "isout"] = false; + this[c === "isover" ? "_over" : "_out"].call(this, event); + + // we just moved out of a greedy child + if (parentInstance && c === "isout") { + parentInstance.isout = false; + parentInstance.isover = true; + parentInstance._over.call(parentInstance, event); + } + }); + + }, + dragStop: function( draggable, event ) { + draggable.element.parentsUntil( "body" ).unbind( "scroll.droppable" ); + //Call prepareOffsets one final time since IE does not fire return scroll events when overflow was caused by drag (see #5003) + if( !draggable.options.refreshPositions ) { + $.ui.ddmanager.prepareOffsets( draggable, event ); + } + } +}; + +})(jQuery); + +(function( $, undefined ) { + +function num(v) { + return parseInt(v, 10) || 0; +} + +function isNumber(value) { + return !isNaN(parseInt(value, 10)); +} + +$.widget("ui.resizable", $.ui.mouse, { + version: "1.10.2", + widgetEventPrefix: "resize", + options: { + alsoResize: false, + animate: false, + animateDuration: "slow", + animateEasing: "swing", + aspectRatio: false, + autoHide: false, + containment: false, + ghost: false, + grid: false, + handles: "e,s,se", + helper: false, + maxHeight: null, + maxWidth: null, + minHeight: 10, + minWidth: 10, + // See #7960 + zIndex: 90, + + // callbacks + resize: null, + start: null, + stop: null + }, + _create: function() { + + var n, i, handle, axis, hname, + that = this, + o = this.options; + this.element.addClass("ui-resizable"); + + $.extend(this, { + _aspectRatio: !!(o.aspectRatio), + aspectRatio: o.aspectRatio, + originalElement: this.element, + _proportionallyResizeElements: [], + _helper: o.helper || o.ghost || o.animate ? o.helper || "ui-resizable-helper" : null + }); + + //Wrap the element if it cannot hold child nodes + if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)) { + + //Create a wrapper element and set the wrapper to the new current internal element + this.element.wrap( + $("
").css({ + position: this.element.css("position"), + width: this.element.outerWidth(), + height: this.element.outerHeight(), + top: this.element.css("top"), + left: this.element.css("left") + }) + ); + + //Overwrite the original this.element + this.element = this.element.parent().data( + "ui-resizable", this.element.data("ui-resizable") + ); + + this.elementIsWrapper = true; + + //Move margins to the wrapper + this.element.css({ marginLeft: this.originalElement.css("marginLeft"), marginTop: this.originalElement.css("marginTop"), marginRight: this.originalElement.css("marginRight"), marginBottom: this.originalElement.css("marginBottom") }); + this.originalElement.css({ marginLeft: 0, marginTop: 0, marginRight: 0, marginBottom: 0}); + + //Prevent Safari textarea resize + this.originalResizeStyle = this.originalElement.css("resize"); + this.originalElement.css("resize", "none"); + + //Push the actual element to our proportionallyResize internal array + this._proportionallyResizeElements.push(this.originalElement.css({ position: "static", zoom: 1, display: "block" })); + + // avoid IE jump (hard set the margin) + this.originalElement.css({ margin: this.originalElement.css("margin") }); + + // fix handlers offset + this._proportionallyResize(); + + } + + this.handles = o.handles || (!$(".ui-resizable-handle", this.element).length ? "e,s,se" : { n: ".ui-resizable-n", e: ".ui-resizable-e", s: ".ui-resizable-s", w: ".ui-resizable-w", se: ".ui-resizable-se", sw: ".ui-resizable-sw", ne: ".ui-resizable-ne", nw: ".ui-resizable-nw" }); + if(this.handles.constructor === String) { + + if ( this.handles === "all") { + this.handles = "n,e,s,w,se,sw,ne,nw"; + } + + n = this.handles.split(","); + this.handles = {}; + + for(i = 0; i < n.length; i++) { + + handle = $.trim(n[i]); + hname = "ui-resizable-"+handle; + axis = $("
"); + + // Apply zIndex to all handles - see #7960 + axis.css({ zIndex: o.zIndex }); + + //TODO : What's going on here? + if ("se" === handle) { + axis.addClass("ui-icon ui-icon-gripsmall-diagonal-se"); + } + + //Insert into internal handles object and append to element + this.handles[handle] = ".ui-resizable-"+handle; + this.element.append(axis); + } + + } + + this._renderAxis = function(target) { + + var i, axis, padPos, padWrapper; + + target = target || this.element; + + for(i in this.handles) { + + if(this.handles[i].constructor === String) { + this.handles[i] = $(this.handles[i], this.element).show(); + } + + //Apply pad to wrapper element, needed to fix axis position (textarea, inputs, scrolls) + if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/textarea|input|select|button/i)) { + + axis = $(this.handles[i], this.element); + + //Checking the correct pad and border + padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth(); + + //The padding type i have to apply... + padPos = [ "padding", + /ne|nw|n/.test(i) ? "Top" : + /se|sw|s/.test(i) ? "Bottom" : + /^e$/.test(i) ? "Right" : "Left" ].join(""); + + target.css(padPos, padWrapper); + + this._proportionallyResize(); + + } + + //TODO: What's that good for? There's not anything to be executed left + if(!$(this.handles[i]).length) { + continue; + } + } + }; + + //TODO: make renderAxis a prototype function + this._renderAxis(this.element); + + this._handles = $(".ui-resizable-handle", this.element) + .disableSelection(); + + //Matching axis name + this._handles.mouseover(function() { + if (!that.resizing) { + if (this.className) { + axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i); + } + //Axis, default = se + that.axis = axis && axis[1] ? axis[1] : "se"; + } + }); + + //If we want to auto hide the elements + if (o.autoHide) { + this._handles.hide(); + $(this.element) + .addClass("ui-resizable-autohide") + .mouseenter(function() { + if (o.disabled) { + return; + } + $(this).removeClass("ui-resizable-autohide"); + that._handles.show(); + }) + .mouseleave(function(){ + if (o.disabled) { + return; + } + if (!that.resizing) { + $(this).addClass("ui-resizable-autohide"); + that._handles.hide(); + } + }); + } + + //Initialize the mouse interaction + this._mouseInit(); + + }, + + _destroy: function() { + + this._mouseDestroy(); + + var wrapper, + _destroy = function(exp) { + $(exp).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing") + .removeData("resizable").removeData("ui-resizable").unbind(".resizable").find(".ui-resizable-handle").remove(); + }; + + //TODO: Unwrap at same DOM position + if (this.elementIsWrapper) { + _destroy(this.element); + wrapper = this.element; + this.originalElement.css({ + position: wrapper.css("position"), + width: wrapper.outerWidth(), + height: wrapper.outerHeight(), + top: wrapper.css("top"), + left: wrapper.css("left") + }).insertAfter( wrapper ); + wrapper.remove(); + } + + this.originalElement.css("resize", this.originalResizeStyle); + _destroy(this.originalElement); + + return this; + }, + + _mouseCapture: function(event) { + var i, handle, + capture = false; + + for (i in this.handles) { + handle = $(this.handles[i])[0]; + if (handle === event.target || $.contains(handle, event.target)) { + capture = true; + } + } + + return !this.options.disabled && capture; + }, + + _mouseStart: function(event) { + + var curleft, curtop, cursor, + o = this.options, + iniPos = this.element.position(), + el = this.element; + + this.resizing = true; + + // bugfix for http://dev.jquery.com/ticket/1749 + if ( (/absolute/).test( el.css("position") ) ) { + el.css({ position: "absolute", top: el.css("top"), left: el.css("left") }); + } else if (el.is(".ui-draggable")) { + el.css({ position: "absolute", top: iniPos.top, left: iniPos.left }); + } + + this._renderProxy(); + + curleft = num(this.helper.css("left")); + curtop = num(this.helper.css("top")); + + if (o.containment) { + curleft += $(o.containment).scrollLeft() || 0; + curtop += $(o.containment).scrollTop() || 0; + } + + //Store needed variables + this.offset = this.helper.offset(); + this.position = { left: curleft, top: curtop }; + this.size = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() }; + this.originalSize = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() }; + this.originalPosition = { left: curleft, top: curtop }; + this.sizeDiff = { width: el.outerWidth() - el.width(), height: el.outerHeight() - el.height() }; + this.originalMousePosition = { left: event.pageX, top: event.pageY }; + + //Aspect Ratio + this.aspectRatio = (typeof o.aspectRatio === "number") ? o.aspectRatio : ((this.originalSize.width / this.originalSize.height) || 1); + + cursor = $(".ui-resizable-" + this.axis).css("cursor"); + $("body").css("cursor", cursor === "auto" ? this.axis + "-resize" : cursor); + + el.addClass("ui-resizable-resizing"); + this._propagate("start", event); + return true; + }, + + _mouseDrag: function(event) { + + //Increase performance, avoid regex + var data, + el = this.helper, props = {}, + smp = this.originalMousePosition, + a = this.axis, + prevTop = this.position.top, + prevLeft = this.position.left, + prevWidth = this.size.width, + prevHeight = this.size.height, + dx = (event.pageX-smp.left)||0, + dy = (event.pageY-smp.top)||0, + trigger = this._change[a]; + + if (!trigger) { + return false; + } + + // Calculate the attrs that will be change + data = trigger.apply(this, [event, dx, dy]); + + // Put this in the mouseDrag handler since the user can start pressing shift while resizing + this._updateVirtualBoundaries(event.shiftKey); + if (this._aspectRatio || event.shiftKey) { + data = this._updateRatio(data, event); + } + + data = this._respectSize(data, event); + + this._updateCache(data); + + // plugins callbacks need to be called first + this._propagate("resize", event); + + if (this.position.top !== prevTop) { + props.top = this.position.top + "px"; + } + if (this.position.left !== prevLeft) { + props.left = this.position.left + "px"; + } + if (this.size.width !== prevWidth) { + props.width = this.size.width + "px"; + } + if (this.size.height !== prevHeight) { + props.height = this.size.height + "px"; + } + el.css(props); + + if (!this._helper && this._proportionallyResizeElements.length) { + this._proportionallyResize(); + } + + // Call the user callback if the element was resized + if ( ! $.isEmptyObject(props) ) { + this._trigger("resize", event, this.ui()); + } + + return false; + }, + + _mouseStop: function(event) { + + this.resizing = false; + var pr, ista, soffseth, soffsetw, s, left, top, + o = this.options, that = this; + + if(this._helper) { + + pr = this._proportionallyResizeElements; + ista = pr.length && (/textarea/i).test(pr[0].nodeName); + soffseth = ista && $.ui.hasScroll(pr[0], "left") /* TODO - jump height */ ? 0 : that.sizeDiff.height; + soffsetw = ista ? 0 : that.sizeDiff.width; + + s = { width: (that.helper.width() - soffsetw), height: (that.helper.height() - soffseth) }; + left = (parseInt(that.element.css("left"), 10) + (that.position.left - that.originalPosition.left)) || null; + top = (parseInt(that.element.css("top"), 10) + (that.position.top - that.originalPosition.top)) || null; + + if (!o.animate) { + this.element.css($.extend(s, { top: top, left: left })); + } + + that.helper.height(that.size.height); + that.helper.width(that.size.width); + + if (this._helper && !o.animate) { + this._proportionallyResize(); + } + } + + $("body").css("cursor", "auto"); + + this.element.removeClass("ui-resizable-resizing"); + + this._propagate("stop", event); + + if (this._helper) { + this.helper.remove(); + } + + return false; + + }, + + _updateVirtualBoundaries: function(forceAspectRatio) { + var pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b, + o = this.options; + + b = { + minWidth: isNumber(o.minWidth) ? o.minWidth : 0, + maxWidth: isNumber(o.maxWidth) ? o.maxWidth : Infinity, + minHeight: isNumber(o.minHeight) ? o.minHeight : 0, + maxHeight: isNumber(o.maxHeight) ? o.maxHeight : Infinity + }; + + if(this._aspectRatio || forceAspectRatio) { + // We want to create an enclosing box whose aspect ration is the requested one + // First, compute the "projected" size for each dimension based on the aspect ratio and other dimension + pMinWidth = b.minHeight * this.aspectRatio; + pMinHeight = b.minWidth / this.aspectRatio; + pMaxWidth = b.maxHeight * this.aspectRatio; + pMaxHeight = b.maxWidth / this.aspectRatio; + + if(pMinWidth > b.minWidth) { + b.minWidth = pMinWidth; + } + if(pMinHeight > b.minHeight) { + b.minHeight = pMinHeight; + } + if(pMaxWidth < b.maxWidth) { + b.maxWidth = pMaxWidth; + } + if(pMaxHeight < b.maxHeight) { + b.maxHeight = pMaxHeight; + } + } + this._vBoundaries = b; + }, + + _updateCache: function(data) { + this.offset = this.helper.offset(); + if (isNumber(data.left)) { + this.position.left = data.left; + } + if (isNumber(data.top)) { + this.position.top = data.top; + } + if (isNumber(data.height)) { + this.size.height = data.height; + } + if (isNumber(data.width)) { + this.size.width = data.width; + } + }, + + _updateRatio: function( data ) { + + var cpos = this.position, + csize = this.size, + a = this.axis; + + if (isNumber(data.height)) { + data.width = (data.height * this.aspectRatio); + } else if (isNumber(data.width)) { + data.height = (data.width / this.aspectRatio); + } + + if (a === "sw") { + data.left = cpos.left + (csize.width - data.width); + data.top = null; + } + if (a === "nw") { + data.top = cpos.top + (csize.height - data.height); + data.left = cpos.left + (csize.width - data.width); + } + + return data; + }, + + _respectSize: function( data ) { + + var o = this._vBoundaries, + a = this.axis, + ismaxw = isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width), ismaxh = isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height), + isminw = isNumber(data.width) && o.minWidth && (o.minWidth > data.width), isminh = isNumber(data.height) && o.minHeight && (o.minHeight > data.height), + dw = this.originalPosition.left + this.originalSize.width, + dh = this.position.top + this.size.height, + cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a); + if (isminw) { + data.width = o.minWidth; + } + if (isminh) { + data.height = o.minHeight; + } + if (ismaxw) { + data.width = o.maxWidth; + } + if (ismaxh) { + data.height = o.maxHeight; + } + + if (isminw && cw) { + data.left = dw - o.minWidth; + } + if (ismaxw && cw) { + data.left = dw - o.maxWidth; + } + if (isminh && ch) { + data.top = dh - o.minHeight; + } + if (ismaxh && ch) { + data.top = dh - o.maxHeight; + } + + // fixing jump error on top/left - bug #2330 + if (!data.width && !data.height && !data.left && data.top) { + data.top = null; + } else if (!data.width && !data.height && !data.top && data.left) { + data.left = null; + } + + return data; + }, + + _proportionallyResize: function() { + + if (!this._proportionallyResizeElements.length) { + return; + } + + var i, j, borders, paddings, prel, + element = this.helper || this.element; + + for ( i=0; i < this._proportionallyResizeElements.length; i++) { + + prel = this._proportionallyResizeElements[i]; + + if (!this.borderDif) { + this.borderDif = []; + borders = [prel.css("borderTopWidth"), prel.css("borderRightWidth"), prel.css("borderBottomWidth"), prel.css("borderLeftWidth")]; + paddings = [prel.css("paddingTop"), prel.css("paddingRight"), prel.css("paddingBottom"), prel.css("paddingLeft")]; + + for ( j = 0; j < borders.length; j++ ) { + this.borderDif[ j ] = ( parseInt( borders[ j ], 10 ) || 0 ) + ( parseInt( paddings[ j ], 10 ) || 0 ); + } + } + + prel.css({ + height: (element.height() - this.borderDif[0] - this.borderDif[2]) || 0, + width: (element.width() - this.borderDif[1] - this.borderDif[3]) || 0 + }); + + } + + }, + + _renderProxy: function() { + + var el = this.element, o = this.options; + this.elementOffset = el.offset(); + + if(this._helper) { + + this.helper = this.helper || $("
"); + + this.helper.addClass(this._helper).css({ + width: this.element.outerWidth() - 1, + height: this.element.outerHeight() - 1, + position: "absolute", + left: this.elementOffset.left +"px", + top: this.elementOffset.top +"px", + zIndex: ++o.zIndex //TODO: Don't modify option + }); + + this.helper + .appendTo("body") + .disableSelection(); + + } else { + this.helper = this.element; + } + + }, + + _change: { + e: function(event, dx) { + return { width: this.originalSize.width + dx }; + }, + w: function(event, dx) { + var cs = this.originalSize, sp = this.originalPosition; + return { left: sp.left + dx, width: cs.width - dx }; + }, + n: function(event, dx, dy) { + var cs = this.originalSize, sp = this.originalPosition; + return { top: sp.top + dy, height: cs.height - dy }; + }, + s: function(event, dx, dy) { + return { height: this.originalSize.height + dy }; + }, + se: function(event, dx, dy) { + return $.extend(this._change.s.apply(this, arguments), this._change.e.apply(this, [event, dx, dy])); + }, + sw: function(event, dx, dy) { + return $.extend(this._change.s.apply(this, arguments), this._change.w.apply(this, [event, dx, dy])); + }, + ne: function(event, dx, dy) { + return $.extend(this._change.n.apply(this, arguments), this._change.e.apply(this, [event, dx, dy])); + }, + nw: function(event, dx, dy) { + return $.extend(this._change.n.apply(this, arguments), this._change.w.apply(this, [event, dx, dy])); + } + }, + + _propagate: function(n, event) { + $.ui.plugin.call(this, n, [event, this.ui()]); + (n !== "resize" && this._trigger(n, event, this.ui())); + }, + + plugins: {}, + + ui: function() { + return { + originalElement: this.originalElement, + element: this.element, + helper: this.helper, + position: this.position, + size: this.size, + originalSize: this.originalSize, + originalPosition: this.originalPosition + }; + } + +}); + +/* + * Resizable Extensions + */ + +$.ui.plugin.add("resizable", "animate", { + + stop: function( event ) { + var that = $(this).data("ui-resizable"), + o = that.options, + pr = that._proportionallyResizeElements, + ista = pr.length && (/textarea/i).test(pr[0].nodeName), + soffseth = ista && $.ui.hasScroll(pr[0], "left") /* TODO - jump height */ ? 0 : that.sizeDiff.height, + soffsetw = ista ? 0 : that.sizeDiff.width, + style = { width: (that.size.width - soffsetw), height: (that.size.height - soffseth) }, + left = (parseInt(that.element.css("left"), 10) + (that.position.left - that.originalPosition.left)) || null, + top = (parseInt(that.element.css("top"), 10) + (that.position.top - that.originalPosition.top)) || null; + + that.element.animate( + $.extend(style, top && left ? { top: top, left: left } : {}), { + duration: o.animateDuration, + easing: o.animateEasing, + step: function() { + + var data = { + width: parseInt(that.element.css("width"), 10), + height: parseInt(that.element.css("height"), 10), + top: parseInt(that.element.css("top"), 10), + left: parseInt(that.element.css("left"), 10) + }; + + if (pr && pr.length) { + $(pr[0]).css({ width: data.width, height: data.height }); + } + + // propagating resize, and updating values for each animation step + that._updateCache(data); + that._propagate("resize", event); + + } + } + ); + } + +}); + +$.ui.plugin.add("resizable", "containment", { + + start: function() { + var element, p, co, ch, cw, width, height, + that = $(this).data("ui-resizable"), + o = that.options, + el = that.element, + oc = o.containment, + ce = (oc instanceof $) ? oc.get(0) : (/parent/.test(oc)) ? el.parent().get(0) : oc; + + if (!ce) { + return; + } + + that.containerElement = $(ce); + + if (/document/.test(oc) || oc === document) { + that.containerOffset = { left: 0, top: 0 }; + that.containerPosition = { left: 0, top: 0 }; + + that.parentData = { + element: $(document), left: 0, top: 0, + width: $(document).width(), height: $(document).height() || document.body.parentNode.scrollHeight + }; + } + + // i'm a node, so compute top, left, right, bottom + else { + element = $(ce); + p = []; + $([ "Top", "Right", "Left", "Bottom" ]).each(function(i, name) { p[i] = num(element.css("padding" + name)); }); + + that.containerOffset = element.offset(); + that.containerPosition = element.position(); + that.containerSize = { height: (element.innerHeight() - p[3]), width: (element.innerWidth() - p[1]) }; + + co = that.containerOffset; + ch = that.containerSize.height; + cw = that.containerSize.width; + width = ($.ui.hasScroll(ce, "left") ? ce.scrollWidth : cw ); + height = ($.ui.hasScroll(ce) ? ce.scrollHeight : ch); + + that.parentData = { + element: ce, left: co.left, top: co.top, width: width, height: height + }; + } + }, + + resize: function( event ) { + var woset, hoset, isParent, isOffsetRelative, + that = $(this).data("ui-resizable"), + o = that.options, + co = that.containerOffset, cp = that.position, + pRatio = that._aspectRatio || event.shiftKey, + cop = { top:0, left:0 }, ce = that.containerElement; + + if (ce[0] !== document && (/static/).test(ce.css("position"))) { + cop = co; + } + + if (cp.left < (that._helper ? co.left : 0)) { + that.size.width = that.size.width + (that._helper ? (that.position.left - co.left) : (that.position.left - cop.left)); + if (pRatio) { + that.size.height = that.size.width / that.aspectRatio; + } + that.position.left = o.helper ? co.left : 0; + } + + if (cp.top < (that._helper ? co.top : 0)) { + that.size.height = that.size.height + (that._helper ? (that.position.top - co.top) : that.position.top); + if (pRatio) { + that.size.width = that.size.height * that.aspectRatio; + } + that.position.top = that._helper ? co.top : 0; + } + + that.offset.left = that.parentData.left+that.position.left; + that.offset.top = that.parentData.top+that.position.top; + + woset = Math.abs( (that._helper ? that.offset.left - cop.left : (that.offset.left - cop.left)) + that.sizeDiff.width ); + hoset = Math.abs( (that._helper ? that.offset.top - cop.top : (that.offset.top - co.top)) + that.sizeDiff.height ); + + isParent = that.containerElement.get(0) === that.element.parent().get(0); + isOffsetRelative = /relative|absolute/.test(that.containerElement.css("position")); + + if(isParent && isOffsetRelative) { + woset -= that.parentData.left; + } + + if (woset + that.size.width >= that.parentData.width) { + that.size.width = that.parentData.width - woset; + if (pRatio) { + that.size.height = that.size.width / that.aspectRatio; + } + } + + if (hoset + that.size.height >= that.parentData.height) { + that.size.height = that.parentData.height - hoset; + if (pRatio) { + that.size.width = that.size.height * that.aspectRatio; + } + } + }, + + stop: function(){ + var that = $(this).data("ui-resizable"), + o = that.options, + co = that.containerOffset, + cop = that.containerPosition, + ce = that.containerElement, + helper = $(that.helper), + ho = helper.offset(), + w = helper.outerWidth() - that.sizeDiff.width, + h = helper.outerHeight() - that.sizeDiff.height; + + if (that._helper && !o.animate && (/relative/).test(ce.css("position"))) { + $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h }); + } + + if (that._helper && !o.animate && (/static/).test(ce.css("position"))) { + $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h }); + } + + } +}); + +$.ui.plugin.add("resizable", "alsoResize", { + + start: function () { + var that = $(this).data("ui-resizable"), + o = that.options, + _store = function (exp) { + $(exp).each(function() { + var el = $(this); + el.data("ui-resizable-alsoresize", { + width: parseInt(el.width(), 10), height: parseInt(el.height(), 10), + left: parseInt(el.css("left"), 10), top: parseInt(el.css("top"), 10) + }); + }); + }; + + if (typeof(o.alsoResize) === "object" && !o.alsoResize.parentNode) { + if (o.alsoResize.length) { o.alsoResize = o.alsoResize[0]; _store(o.alsoResize); } + else { $.each(o.alsoResize, function (exp) { _store(exp); }); } + }else{ + _store(o.alsoResize); + } + }, + + resize: function (event, ui) { + var that = $(this).data("ui-resizable"), + o = that.options, + os = that.originalSize, + op = that.originalPosition, + delta = { + height: (that.size.height - os.height) || 0, width: (that.size.width - os.width) || 0, + top: (that.position.top - op.top) || 0, left: (that.position.left - op.left) || 0 + }, + + _alsoResize = function (exp, c) { + $(exp).each(function() { + var el = $(this), start = $(this).data("ui-resizable-alsoresize"), style = {}, + css = c && c.length ? c : el.parents(ui.originalElement[0]).length ? ["width", "height"] : ["width", "height", "top", "left"]; + + $.each(css, function (i, prop) { + var sum = (start[prop]||0) + (delta[prop]||0); + if (sum && sum >= 0) { + style[prop] = sum || null; + } + }); + + el.css(style); + }); + }; + + if (typeof(o.alsoResize) === "object" && !o.alsoResize.nodeType) { + $.each(o.alsoResize, function (exp, c) { _alsoResize(exp, c); }); + }else{ + _alsoResize(o.alsoResize); + } + }, + + stop: function () { + $(this).removeData("resizable-alsoresize"); + } +}); + +$.ui.plugin.add("resizable", "ghost", { + + start: function() { + + var that = $(this).data("ui-resizable"), o = that.options, cs = that.size; + + that.ghost = that.originalElement.clone(); + that.ghost + .css({ opacity: 0.25, display: "block", position: "relative", height: cs.height, width: cs.width, margin: 0, left: 0, top: 0 }) + .addClass("ui-resizable-ghost") + .addClass(typeof o.ghost === "string" ? o.ghost : ""); + + that.ghost.appendTo(that.helper); + + }, + + resize: function(){ + var that = $(this).data("ui-resizable"); + if (that.ghost) { + that.ghost.css({ position: "relative", height: that.size.height, width: that.size.width }); + } + }, + + stop: function() { + var that = $(this).data("ui-resizable"); + if (that.ghost && that.helper) { + that.helper.get(0).removeChild(that.ghost.get(0)); + } + } + +}); + +$.ui.plugin.add("resizable", "grid", { + + resize: function() { + var that = $(this).data("ui-resizable"), + o = that.options, + cs = that.size, + os = that.originalSize, + op = that.originalPosition, + a = that.axis, + grid = typeof o.grid === "number" ? [o.grid, o.grid] : o.grid, + gridX = (grid[0]||1), + gridY = (grid[1]||1), + ox = Math.round((cs.width - os.width) / gridX) * gridX, + oy = Math.round((cs.height - os.height) / gridY) * gridY, + newWidth = os.width + ox, + newHeight = os.height + oy, + isMaxWidth = o.maxWidth && (o.maxWidth < newWidth), + isMaxHeight = o.maxHeight && (o.maxHeight < newHeight), + isMinWidth = o.minWidth && (o.minWidth > newWidth), + isMinHeight = o.minHeight && (o.minHeight > newHeight); + + o.grid = grid; + + if (isMinWidth) { + newWidth = newWidth + gridX; + } + if (isMinHeight) { + newHeight = newHeight + gridY; + } + if (isMaxWidth) { + newWidth = newWidth - gridX; + } + if (isMaxHeight) { + newHeight = newHeight - gridY; + } + + if (/^(se|s|e)$/.test(a)) { + that.size.width = newWidth; + that.size.height = newHeight; + } else if (/^(ne)$/.test(a)) { + that.size.width = newWidth; + that.size.height = newHeight; + that.position.top = op.top - oy; + } else if (/^(sw)$/.test(a)) { + that.size.width = newWidth; + that.size.height = newHeight; + that.position.left = op.left - ox; + } else { + that.size.width = newWidth; + that.size.height = newHeight; + that.position.top = op.top - oy; + that.position.left = op.left - ox; + } + } + +}); + +})(jQuery); + +(function( $, undefined ) { + +$.widget("ui.selectable", $.ui.mouse, { + version: "1.10.2", + options: { + appendTo: "body", + autoRefresh: true, + distance: 0, + filter: "*", + tolerance: "touch", + + // callbacks + selected: null, + selecting: null, + start: null, + stop: null, + unselected: null, + unselecting: null + }, + _create: function() { + var selectees, + that = this; + + this.element.addClass("ui-selectable"); + + this.dragged = false; + + // cache selectee children based on filter + this.refresh = function() { + selectees = $(that.options.filter, that.element[0]); + selectees.addClass("ui-selectee"); + selectees.each(function() { + var $this = $(this), + pos = $this.offset(); + $.data(this, "selectable-item", { + element: this, + $element: $this, + left: pos.left, + top: pos.top, + right: pos.left + $this.outerWidth(), + bottom: pos.top + $this.outerHeight(), + startselected: false, + selected: $this.hasClass("ui-selected"), + selecting: $this.hasClass("ui-selecting"), + unselecting: $this.hasClass("ui-unselecting") + }); + }); + }; + this.refresh(); + + this.selectees = selectees.addClass("ui-selectee"); + + this._mouseInit(); + + this.helper = $("
"); + }, + + _destroy: function() { + this.selectees + .removeClass("ui-selectee") + .removeData("selectable-item"); + this.element + .removeClass("ui-selectable ui-selectable-disabled"); + this._mouseDestroy(); + }, + + _mouseStart: function(event) { + var that = this, + options = this.options; + + this.opos = [event.pageX, event.pageY]; + + if (this.options.disabled) { + return; + } + + this.selectees = $(options.filter, this.element[0]); + + this._trigger("start", event); + + $(options.appendTo).append(this.helper); + // position helper (lasso) + this.helper.css({ + "left": event.pageX, + "top": event.pageY, + "width": 0, + "height": 0 + }); + + if (options.autoRefresh) { + this.refresh(); + } + + this.selectees.filter(".ui-selected").each(function() { + var selectee = $.data(this, "selectable-item"); + selectee.startselected = true; + if (!event.metaKey && !event.ctrlKey) { + selectee.$element.removeClass("ui-selected"); + selectee.selected = false; + selectee.$element.addClass("ui-unselecting"); + selectee.unselecting = true; + // selectable UNSELECTING callback + that._trigger("unselecting", event, { + unselecting: selectee.element + }); + } + }); + + $(event.target).parents().addBack().each(function() { + var doSelect, + selectee = $.data(this, "selectable-item"); + if (selectee) { + doSelect = (!event.metaKey && !event.ctrlKey) || !selectee.$element.hasClass("ui-selected"); + selectee.$element + .removeClass(doSelect ? "ui-unselecting" : "ui-selected") + .addClass(doSelect ? "ui-selecting" : "ui-unselecting"); + selectee.unselecting = !doSelect; + selectee.selecting = doSelect; + selectee.selected = doSelect; + // selectable (UN)SELECTING callback + if (doSelect) { + that._trigger("selecting", event, { + selecting: selectee.element + }); + } else { + that._trigger("unselecting", event, { + unselecting: selectee.element + }); + } + return false; + } + }); + + }, + + _mouseDrag: function(event) { + + this.dragged = true; + + if (this.options.disabled) { + return; + } + + var tmp, + that = this, + options = this.options, + x1 = this.opos[0], + y1 = this.opos[1], + x2 = event.pageX, + y2 = event.pageY; + + if (x1 > x2) { tmp = x2; x2 = x1; x1 = tmp; } + if (y1 > y2) { tmp = y2; y2 = y1; y1 = tmp; } + this.helper.css({left: x1, top: y1, width: x2-x1, height: y2-y1}); + + this.selectees.each(function() { + var selectee = $.data(this, "selectable-item"), + hit = false; + + //prevent helper from being selected if appendTo: selectable + if (!selectee || selectee.element === that.element[0]) { + return; + } + + if (options.tolerance === "touch") { + hit = ( !(selectee.left > x2 || selectee.right < x1 || selectee.top > y2 || selectee.bottom < y1) ); + } else if (options.tolerance === "fit") { + hit = (selectee.left > x1 && selectee.right < x2 && selectee.top > y1 && selectee.bottom < y2); + } + + if (hit) { + // SELECT + if (selectee.selected) { + selectee.$element.removeClass("ui-selected"); + selectee.selected = false; + } + if (selectee.unselecting) { + selectee.$element.removeClass("ui-unselecting"); + selectee.unselecting = false; + } + if (!selectee.selecting) { + selectee.$element.addClass("ui-selecting"); + selectee.selecting = true; + // selectable SELECTING callback + that._trigger("selecting", event, { + selecting: selectee.element + }); + } + } else { + // UNSELECT + if (selectee.selecting) { + if ((event.metaKey || event.ctrlKey) && selectee.startselected) { + selectee.$element.removeClass("ui-selecting"); + selectee.selecting = false; + selectee.$element.addClass("ui-selected"); + selectee.selected = true; + } else { + selectee.$element.removeClass("ui-selecting"); + selectee.selecting = false; + if (selectee.startselected) { + selectee.$element.addClass("ui-unselecting"); + selectee.unselecting = true; + } + // selectable UNSELECTING callback + that._trigger("unselecting", event, { + unselecting: selectee.element + }); + } + } + if (selectee.selected) { + if (!event.metaKey && !event.ctrlKey && !selectee.startselected) { + selectee.$element.removeClass("ui-selected"); + selectee.selected = false; + + selectee.$element.addClass("ui-unselecting"); + selectee.unselecting = true; + // selectable UNSELECTING callback + that._trigger("unselecting", event, { + unselecting: selectee.element + }); + } + } + } + }); + + return false; + }, + + _mouseStop: function(event) { + var that = this; + + this.dragged = false; + + $(".ui-unselecting", this.element[0]).each(function() { + var selectee = $.data(this, "selectable-item"); + selectee.$element.removeClass("ui-unselecting"); + selectee.unselecting = false; + selectee.startselected = false; + that._trigger("unselected", event, { + unselected: selectee.element + }); + }); + $(".ui-selecting", this.element[0]).each(function() { + var selectee = $.data(this, "selectable-item"); + selectee.$element.removeClass("ui-selecting").addClass("ui-selected"); + selectee.selecting = false; + selectee.selected = true; + selectee.startselected = true; + that._trigger("selected", event, { + selected: selectee.element + }); + }); + this._trigger("stop", event); + + this.helper.remove(); + + return false; + } + +}); + +})(jQuery); + +(function( $, undefined ) { + +/*jshint loopfunc: true */ + +function isOverAxis( x, reference, size ) { + return ( x > reference ) && ( x < ( reference + size ) ); +} + +function isFloating(item) { + return (/left|right/).test(item.css("float")) || (/inline|table-cell/).test(item.css("display")); +} + +$.widget("ui.sortable", $.ui.mouse, { + version: "1.10.2", + widgetEventPrefix: "sort", + ready: false, + options: { + appendTo: "parent", + axis: false, + connectWith: false, + containment: false, + cursor: "auto", + cursorAt: false, + dropOnEmpty: true, + forcePlaceholderSize: false, + forceHelperSize: false, + grid: false, + handle: false, + helper: "original", + items: "> *", + opacity: false, + placeholder: false, + revert: false, + scroll: true, + scrollSensitivity: 20, + scrollSpeed: 20, + scope: "default", + tolerance: "intersect", + zIndex: 1000, + + // callbacks + activate: null, + beforeStop: null, + change: null, + deactivate: null, + out: null, + over: null, + receive: null, + remove: null, + sort: null, + start: null, + stop: null, + update: null + }, + _create: function() { + + var o = this.options; + this.containerCache = {}; + this.element.addClass("ui-sortable"); + + //Get the items + this.refresh(); + + //Let's determine if the items are being displayed horizontally + this.floating = this.items.length ? o.axis === "x" || isFloating(this.items[0].item) : false; + + //Let's determine the parent's offset + this.offset = this.element.offset(); + + //Initialize mouse events for interaction + this._mouseInit(); + + //We're ready to go + this.ready = true; + + }, + + _destroy: function() { + this.element + .removeClass("ui-sortable ui-sortable-disabled"); + this._mouseDestroy(); + + for ( var i = this.items.length - 1; i >= 0; i-- ) { + this.items[i].item.removeData(this.widgetName + "-item"); + } + + return this; + }, + + _setOption: function(key, value){ + if ( key === "disabled" ) { + this.options[ key ] = value; + + this.widget().toggleClass( "ui-sortable-disabled", !!value ); + } else { + // Don't call widget base _setOption for disable as it adds ui-state-disabled class + $.Widget.prototype._setOption.apply(this, arguments); + } + }, + + _mouseCapture: function(event, overrideHandle) { + var currentItem = null, + validHandle = false, + that = this; + + if (this.reverting) { + return false; + } + + if(this.options.disabled || this.options.type === "static") { + return false; + } + + //We have to refresh the items data once first + this._refreshItems(event); + + //Find out if the clicked node (or one of its parents) is a actual item in this.items + $(event.target).parents().each(function() { + if($.data(this, that.widgetName + "-item") === that) { + currentItem = $(this); + return false; + } + }); + if($.data(event.target, that.widgetName + "-item") === that) { + currentItem = $(event.target); + } + + if(!currentItem) { + return false; + } + if(this.options.handle && !overrideHandle) { + $(this.options.handle, currentItem).find("*").addBack().each(function() { + if(this === event.target) { + validHandle = true; + } + }); + if(!validHandle) { + return false; + } + } + + this.currentItem = currentItem; + this._removeCurrentsFromItems(); + return true; + + }, + + _mouseStart: function(event, overrideHandle, noActivation) { + + var i, body, + o = this.options; + + this.currentContainer = this; + + //We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture + this.refreshPositions(); + + //Create and append the visible helper + this.helper = this._createHelper(event); + + //Cache the helper size + this._cacheHelperProportions(); + + /* + * - Position generation - + * This block generates everything position related - it's the core of draggables. + */ + + //Cache the margins of the original element + this._cacheMargins(); + + //Get the next scrolling parent + this.scrollParent = this.helper.scrollParent(); + + //The element's absolute position on the page minus margins + this.offset = this.currentItem.offset(); + this.offset = { + top: this.offset.top - this.margins.top, + left: this.offset.left - this.margins.left + }; + + $.extend(this.offset, { + click: { //Where the click happened, relative to the element + left: event.pageX - this.offset.left, + top: event.pageY - this.offset.top + }, + parent: this._getParentOffset(), + relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper + }); + + // Only after we got the offset, we can change the helper's position to absolute + // TODO: Still need to figure out a way to make relative sorting possible + this.helper.css("position", "absolute"); + this.cssPosition = this.helper.css("position"); + + //Generate the original position + this.originalPosition = this._generatePosition(event); + this.originalPageX = event.pageX; + this.originalPageY = event.pageY; + + //Adjust the mouse offset relative to the helper if "cursorAt" is supplied + (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt)); + + //Cache the former DOM position + this.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] }; + + //If the helper is not the original, hide the original so it's not playing any role during the drag, won't cause anything bad this way + if(this.helper[0] !== this.currentItem[0]) { + this.currentItem.hide(); + } + + //Create the placeholder + this._createPlaceholder(); + + //Set a containment if given in the options + if(o.containment) { + this._setContainment(); + } + + if( o.cursor && o.cursor !== "auto" ) { // cursor option + body = this.document.find( "body" ); + + // support: IE + this.storedCursor = body.css( "cursor" ); + body.css( "cursor", o.cursor ); + + this.storedStylesheet = $( "" ).appendTo( body ); + } + + if(o.opacity) { // opacity option + if (this.helper.css("opacity")) { + this._storedOpacity = this.helper.css("opacity"); + } + this.helper.css("opacity", o.opacity); + } + + if(o.zIndex) { // zIndex option + if (this.helper.css("zIndex")) { + this._storedZIndex = this.helper.css("zIndex"); + } + this.helper.css("zIndex", o.zIndex); + } + + //Prepare scrolling + if(this.scrollParent[0] !== document && this.scrollParent[0].tagName !== "HTML") { + this.overflowOffset = this.scrollParent.offset(); + } + + //Call callbacks + this._trigger("start", event, this._uiHash()); + + //Recache the helper size + if(!this._preserveHelperProportions) { + this._cacheHelperProportions(); + } + + + //Post "activate" events to possible containers + if( !noActivation ) { + for ( i = this.containers.length - 1; i >= 0; i-- ) { + this.containers[ i ]._trigger( "activate", event, this._uiHash( this ) ); + } + } + + //Prepare possible droppables + if($.ui.ddmanager) { + $.ui.ddmanager.current = this; + } + + if ($.ui.ddmanager && !o.dropBehaviour) { + $.ui.ddmanager.prepareOffsets(this, event); + } + + this.dragging = true; + + this.helper.addClass("ui-sortable-helper"); + this._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position + return true; + + }, + + _mouseDrag: function(event) { + var i, item, itemElement, intersection, + o = this.options, + scrolled = false; + + //Compute the helpers position + this.position = this._generatePosition(event); + this.positionAbs = this._convertPositionTo("absolute"); + + if (!this.lastPositionAbs) { + this.lastPositionAbs = this.positionAbs; + } + + //Do scrolling + if(this.options.scroll) { + if(this.scrollParent[0] !== document && this.scrollParent[0].tagName !== "HTML") { + + if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity) { + this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed; + } else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity) { + this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed; + } + + if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity) { + this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed; + } else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity) { + this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed; + } + + } else { + + if(event.pageY - $(document).scrollTop() < o.scrollSensitivity) { + scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed); + } else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) { + scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed); + } + + if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity) { + scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed); + } else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) { + scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed); + } + + } + + if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) { + $.ui.ddmanager.prepareOffsets(this, event); + } + } + + //Regenerate the absolute position used for position checks + this.positionAbs = this._convertPositionTo("absolute"); + + //Set the helper position + if(!this.options.axis || this.options.axis !== "y") { + this.helper[0].style.left = this.position.left+"px"; + } + if(!this.options.axis || this.options.axis !== "x") { + this.helper[0].style.top = this.position.top+"px"; + } + + //Rearrange + for (i = this.items.length - 1; i >= 0; i--) { + + //Cache variables and intersection, continue if no intersection + item = this.items[i]; + itemElement = item.item[0]; + intersection = this._intersectsWithPointer(item); + if (!intersection) { + continue; + } + + // Only put the placeholder inside the current Container, skip all + // items form other containers. This works because when moving + // an item from one container to another the + // currentContainer is switched before the placeholder is moved. + // + // Without this moving items in "sub-sortables" can cause the placeholder to jitter + // beetween the outer and inner container. + if (item.instance !== this.currentContainer) { + continue; + } + + // cannot intersect with itself + // no useless actions that have been done before + // no action if the item moved is the parent of the item checked + if (itemElement !== this.currentItem[0] && + this.placeholder[intersection === 1 ? "next" : "prev"]()[0] !== itemElement && + !$.contains(this.placeholder[0], itemElement) && + (this.options.type === "semi-dynamic" ? !$.contains(this.element[0], itemElement) : true) + ) { + + this.direction = intersection === 1 ? "down" : "up"; + + if (this.options.tolerance === "pointer" || this._intersectsWithSides(item)) { + this._rearrange(event, item); + } else { + break; + } + + this._trigger("change", event, this._uiHash()); + break; + } + } + + //Post events to containers + this._contactContainers(event); + + //Interconnect with droppables + if($.ui.ddmanager) { + $.ui.ddmanager.drag(this, event); + } + + //Call callbacks + this._trigger("sort", event, this._uiHash()); + + this.lastPositionAbs = this.positionAbs; + return false; + + }, + + _mouseStop: function(event, noPropagation) { + + if(!event) { + return; + } + + //If we are using droppables, inform the manager about the drop + if ($.ui.ddmanager && !this.options.dropBehaviour) { + $.ui.ddmanager.drop(this, event); + } + + if(this.options.revert) { + var that = this, + cur = this.placeholder.offset(), + axis = this.options.axis, + animation = {}; + + if ( !axis || axis === "x" ) { + animation.left = cur.left - this.offset.parent.left - this.margins.left + (this.offsetParent[0] === document.body ? 0 : this.offsetParent[0].scrollLeft); + } + if ( !axis || axis === "y" ) { + animation.top = cur.top - this.offset.parent.top - this.margins.top + (this.offsetParent[0] === document.body ? 0 : this.offsetParent[0].scrollTop); + } + this.reverting = true; + $(this.helper).animate( animation, parseInt(this.options.revert, 10) || 500, function() { + that._clear(event); + }); + } else { + this._clear(event, noPropagation); + } + + return false; + + }, + + cancel: function() { + + if(this.dragging) { + + this._mouseUp({ target: null }); + + if(this.options.helper === "original") { + this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"); + } else { + this.currentItem.show(); + } + + //Post deactivating events to containers + for (var i = this.containers.length - 1; i >= 0; i--){ + this.containers[i]._trigger("deactivate", null, this._uiHash(this)); + if(this.containers[i].containerCache.over) { + this.containers[i]._trigger("out", null, this._uiHash(this)); + this.containers[i].containerCache.over = 0; + } + } + + } + + if (this.placeholder) { + //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node! + if(this.placeholder[0].parentNode) { + this.placeholder[0].parentNode.removeChild(this.placeholder[0]); + } + if(this.options.helper !== "original" && this.helper && this.helper[0].parentNode) { + this.helper.remove(); + } + + $.extend(this, { + helper: null, + dragging: false, + reverting: false, + _noFinalSort: null + }); + + if(this.domPosition.prev) { + $(this.domPosition.prev).after(this.currentItem); + } else { + $(this.domPosition.parent).prepend(this.currentItem); + } + } + + return this; + + }, + + serialize: function(o) { + + var items = this._getItemsAsjQuery(o && o.connected), + str = []; + o = o || {}; + + $(items).each(function() { + var res = ($(o.item || this).attr(o.attribute || "id") || "").match(o.expression || (/(.+)[\-=_](.+)/)); + if (res) { + str.push((o.key || res[1]+"[]")+"="+(o.key && o.expression ? res[1] : res[2])); + } + }); + + if(!str.length && o.key) { + str.push(o.key + "="); + } + + return str.join("&"); + + }, + + toArray: function(o) { + + var items = this._getItemsAsjQuery(o && o.connected), + ret = []; + + o = o || {}; + + items.each(function() { ret.push($(o.item || this).attr(o.attribute || "id") || ""); }); + return ret; + + }, + + /* Be careful with the following core functions */ + _intersectsWith: function(item) { + + var x1 = this.positionAbs.left, + x2 = x1 + this.helperProportions.width, + y1 = this.positionAbs.top, + y2 = y1 + this.helperProportions.height, + l = item.left, + r = l + item.width, + t = item.top, + b = t + item.height, + dyClick = this.offset.click.top, + dxClick = this.offset.click.left, + isOverElement = (y1 + dyClick) > t && (y1 + dyClick) < b && (x1 + dxClick) > l && (x1 + dxClick) < r; + + if ( this.options.tolerance === "pointer" || + this.options.forcePointerForContainers || + (this.options.tolerance !== "pointer" && this.helperProportions[this.floating ? "width" : "height"] > item[this.floating ? "width" : "height"]) + ) { + return isOverElement; + } else { + + return (l < x1 + (this.helperProportions.width / 2) && // Right Half + x2 - (this.helperProportions.width / 2) < r && // Left Half + t < y1 + (this.helperProportions.height / 2) && // Bottom Half + y2 - (this.helperProportions.height / 2) < b ); // Top Half + + } + }, + + _intersectsWithPointer: function(item) { + + var isOverElementHeight = (this.options.axis === "x") || isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height), + isOverElementWidth = (this.options.axis === "y") || isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width), + isOverElement = isOverElementHeight && isOverElementWidth, + verticalDirection = this._getDragVerticalDirection(), + horizontalDirection = this._getDragHorizontalDirection(); + + if (!isOverElement) { + return false; + } + + return this.floating ? + ( ((horizontalDirection && horizontalDirection === "right") || verticalDirection === "down") ? 2 : 1 ) + : ( verticalDirection && (verticalDirection === "down" ? 2 : 1) ); + + }, + + _intersectsWithSides: function(item) { + + var isOverBottomHalf = isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height/2), item.height), + isOverRightHalf = isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width/2), item.width), + verticalDirection = this._getDragVerticalDirection(), + horizontalDirection = this._getDragHorizontalDirection(); + + if (this.floating && horizontalDirection) { + return ((horizontalDirection === "right" && isOverRightHalf) || (horizontalDirection === "left" && !isOverRightHalf)); + } else { + return verticalDirection && ((verticalDirection === "down" && isOverBottomHalf) || (verticalDirection === "up" && !isOverBottomHalf)); + } + + }, + + _getDragVerticalDirection: function() { + var delta = this.positionAbs.top - this.lastPositionAbs.top; + return delta !== 0 && (delta > 0 ? "down" : "up"); + }, + + _getDragHorizontalDirection: function() { + var delta = this.positionAbs.left - this.lastPositionAbs.left; + return delta !== 0 && (delta > 0 ? "right" : "left"); + }, + + refresh: function(event) { + this._refreshItems(event); + this.refreshPositions(); + return this; + }, + + _connectWith: function() { + var options = this.options; + return options.connectWith.constructor === String ? [options.connectWith] : options.connectWith; + }, + + _getItemsAsjQuery: function(connected) { + + var i, j, cur, inst, + items = [], + queries = [], + connectWith = this._connectWith(); + + if(connectWith && connected) { + for (i = connectWith.length - 1; i >= 0; i--){ + cur = $(connectWith[i]); + for ( j = cur.length - 1; j >= 0; j--){ + inst = $.data(cur[j], this.widgetFullName); + if(inst && inst !== this && !inst.options.disabled) { + queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element) : $(inst.options.items, inst.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"), inst]); + } + } + } + } + + queries.push([$.isFunction(this.options.items) ? this.options.items.call(this.element, null, { options: this.options, item: this.currentItem }) : $(this.options.items, this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"), this]); + + for (i = queries.length - 1; i >= 0; i--){ + queries[i][0].each(function() { + items.push(this); + }); + } + + return $(items); + + }, + + _removeCurrentsFromItems: function() { + + var list = this.currentItem.find(":data(" + this.widgetName + "-item)"); + + this.items = $.grep(this.items, function (item) { + for (var j=0; j < list.length; j++) { + if(list[j] === item.item[0]) { + return false; + } + } + return true; + }); + + }, + + _refreshItems: function(event) { + + this.items = []; + this.containers = [this]; + + var i, j, cur, inst, targetData, _queries, item, queriesLength, + items = this.items, + queries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]], + connectWith = this._connectWith(); + + if(connectWith && this.ready) { //Shouldn't be run the first time through due to massive slow-down + for (i = connectWith.length - 1; i >= 0; i--){ + cur = $(connectWith[i]); + for (j = cur.length - 1; j >= 0; j--){ + inst = $.data(cur[j], this.widgetFullName); + if(inst && inst !== this && !inst.options.disabled) { + queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]); + this.containers.push(inst); + } + } + } + } + + for (i = queries.length - 1; i >= 0; i--) { + targetData = queries[i][1]; + _queries = queries[i][0]; + + for (j=0, queriesLength = _queries.length; j < queriesLength; j++) { + item = $(_queries[j]); + + item.data(this.widgetName + "-item", targetData); // Data for target checking (mouse manager) + + items.push({ + item: item, + instance: targetData, + width: 0, height: 0, + left: 0, top: 0 + }); + } + } + + }, + + refreshPositions: function(fast) { + + //This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change + if(this.offsetParent && this.helper) { + this.offset.parent = this._getParentOffset(); + } + + var i, item, t, p; + + for (i = this.items.length - 1; i >= 0; i--){ + item = this.items[i]; + + //We ignore calculating positions of all connected containers when we're not over them + if(item.instance !== this.currentContainer && this.currentContainer && item.item[0] !== this.currentItem[0]) { + continue; + } + + t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item; + + if (!fast) { + item.width = t.outerWidth(); + item.height = t.outerHeight(); + } + + p = t.offset(); + item.left = p.left; + item.top = p.top; + } + + if(this.options.custom && this.options.custom.refreshContainers) { + this.options.custom.refreshContainers.call(this); + } else { + for (i = this.containers.length - 1; i >= 0; i--){ + p = this.containers[i].element.offset(); + this.containers[i].containerCache.left = p.left; + this.containers[i].containerCache.top = p.top; + this.containers[i].containerCache.width = this.containers[i].element.outerWidth(); + this.containers[i].containerCache.height = this.containers[i].element.outerHeight(); + } + } + + return this; + }, + + _createPlaceholder: function(that) { + that = that || this; + var className, + o = that.options; + + if(!o.placeholder || o.placeholder.constructor === String) { + className = o.placeholder; + o.placeholder = { + element: function() { + + var nodeName = that.currentItem[0].nodeName.toLowerCase(), + element = $( that.document[0].createElement( nodeName ) ) + .addClass(className || that.currentItem[0].className+" ui-sortable-placeholder") + .removeClass("ui-sortable-helper"); + + if ( nodeName === "tr" ) { + // Use a high colspan to force the td to expand the full + // width of the table (browsers are smart enough to + // handle this properly) + element.append( " " ); + } else if ( nodeName === "img" ) { + element.attr( "src", that.currentItem.attr( "src" ) ); + } + + if ( !className ) { + element.css( "visibility", "hidden" ); + } + + return element; + }, + update: function(container, p) { + + // 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that + // 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified + if(className && !o.forcePlaceholderSize) { + return; + } + + //If the element doesn't have a actual height by itself (without styles coming from a stylesheet), it receives the inline height from the dragged item + if(!p.height()) { p.height(that.currentItem.innerHeight() - parseInt(that.currentItem.css("paddingTop")||0, 10) - parseInt(that.currentItem.css("paddingBottom")||0, 10)); } + if(!p.width()) { p.width(that.currentItem.innerWidth() - parseInt(that.currentItem.css("paddingLeft")||0, 10) - parseInt(that.currentItem.css("paddingRight")||0, 10)); } + } + }; + } + + //Create the placeholder + that.placeholder = $(o.placeholder.element.call(that.element, that.currentItem)); + + //Append it after the actual current item + that.currentItem.after(that.placeholder); + + //Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317) + o.placeholder.update(that, that.placeholder); + + }, + + _contactContainers: function(event) { + var i, j, dist, itemWithLeastDistance, posProperty, sizeProperty, base, cur, nearBottom, floating, + innermostContainer = null, + innermostIndex = null; + + // get innermost container that intersects with item + for (i = this.containers.length - 1; i >= 0; i--) { + + // never consider a container that's located within the item itself + if($.contains(this.currentItem[0], this.containers[i].element[0])) { + continue; + } + + if(this._intersectsWith(this.containers[i].containerCache)) { + + // if we've already found a container and it's more "inner" than this, then continue + if(innermostContainer && $.contains(this.containers[i].element[0], innermostContainer.element[0])) { + continue; + } + + innermostContainer = this.containers[i]; + innermostIndex = i; + + } else { + // container doesn't intersect. trigger "out" event if necessary + if(this.containers[i].containerCache.over) { + this.containers[i]._trigger("out", event, this._uiHash(this)); + this.containers[i].containerCache.over = 0; + } + } + + } + + // if no intersecting containers found, return + if(!innermostContainer) { + return; + } + + // move the item into the container if it's not there already + if(this.containers.length === 1) { + if (!this.containers[innermostIndex].containerCache.over) { + this.containers[innermostIndex]._trigger("over", event, this._uiHash(this)); + this.containers[innermostIndex].containerCache.over = 1; + } + } else { + + //When entering a new container, we will find the item with the least distance and append our item near it + dist = 10000; + itemWithLeastDistance = null; + floating = innermostContainer.floating || isFloating(this.currentItem); + posProperty = floating ? "left" : "top"; + sizeProperty = floating ? "width" : "height"; + base = this.positionAbs[posProperty] + this.offset.click[posProperty]; + for (j = this.items.length - 1; j >= 0; j--) { + if(!$.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) { + continue; + } + if(this.items[j].item[0] === this.currentItem[0]) { + continue; + } + if (floating && !isOverAxis(this.positionAbs.top + this.offset.click.top, this.items[j].top, this.items[j].height)) { + continue; + } + cur = this.items[j].item.offset()[posProperty]; + nearBottom = false; + if(Math.abs(cur - base) > Math.abs(cur + this.items[j][sizeProperty] - base)){ + nearBottom = true; + cur += this.items[j][sizeProperty]; + } + + if(Math.abs(cur - base) < dist) { + dist = Math.abs(cur - base); itemWithLeastDistance = this.items[j]; + this.direction = nearBottom ? "up": "down"; + } + } + + //Check if dropOnEmpty is enabled + if(!itemWithLeastDistance && !this.options.dropOnEmpty) { + return; + } + + if(this.currentContainer === this.containers[innermostIndex]) { + return; + } + + itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true); + this._trigger("change", event, this._uiHash()); + this.containers[innermostIndex]._trigger("change", event, this._uiHash(this)); + this.currentContainer = this.containers[innermostIndex]; + + //Update the placeholder + this.options.placeholder.update(this.currentContainer, this.placeholder); + + this.containers[innermostIndex]._trigger("over", event, this._uiHash(this)); + this.containers[innermostIndex].containerCache.over = 1; + } + + + }, + + _createHelper: function(event) { + + var o = this.options, + helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper === "clone" ? this.currentItem.clone() : this.currentItem); + + //Add the helper to the DOM if that didn't happen already + if(!helper.parents("body").length) { + $(o.appendTo !== "parent" ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]); + } + + if(helper[0] === this.currentItem[0]) { + this._storedCSS = { width: this.currentItem[0].style.width, height: this.currentItem[0].style.height, position: this.currentItem.css("position"), top: this.currentItem.css("top"), left: this.currentItem.css("left") }; + } + + if(!helper[0].style.width || o.forceHelperSize) { + helper.width(this.currentItem.width()); + } + if(!helper[0].style.height || o.forceHelperSize) { + helper.height(this.currentItem.height()); + } + + return helper; + + }, + + _adjustOffsetFromHelper: function(obj) { + if (typeof obj === "string") { + obj = obj.split(" "); + } + if ($.isArray(obj)) { + obj = {left: +obj[0], top: +obj[1] || 0}; + } + if ("left" in obj) { + this.offset.click.left = obj.left + this.margins.left; + } + if ("right" in obj) { + this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left; + } + if ("top" in obj) { + this.offset.click.top = obj.top + this.margins.top; + } + if ("bottom" in obj) { + this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top; + } + }, + + _getParentOffset: function() { + + + //Get the offsetParent and cache its position + this.offsetParent = this.helper.offsetParent(); + var po = this.offsetParent.offset(); + + // This is a special case where we need to modify a offset calculated on start, since the following happened: + // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent + // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that + // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag + if(this.cssPosition === "absolute" && this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) { + po.left += this.scrollParent.scrollLeft(); + po.top += this.scrollParent.scrollTop(); + } + + // This needs to be actually done for all browsers, since pageX/pageY includes this information + // with an ugly IE fix + if( this.offsetParent[0] === document.body || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() === "html" && $.ui.ie)) { + po = { top: 0, left: 0 }; + } + + return { + top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0), + left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0) + }; + + }, + + _getRelativeOffset: function() { + + if(this.cssPosition === "relative") { + var p = this.currentItem.position(); + return { + top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(), + left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft() + }; + } else { + return { top: 0, left: 0 }; + } + + }, + + _cacheMargins: function() { + this.margins = { + left: (parseInt(this.currentItem.css("marginLeft"),10) || 0), + top: (parseInt(this.currentItem.css("marginTop"),10) || 0) + }; + }, + + _cacheHelperProportions: function() { + this.helperProportions = { + width: this.helper.outerWidth(), + height: this.helper.outerHeight() + }; + }, + + _setContainment: function() { + + var ce, co, over, + o = this.options; + if(o.containment === "parent") { + o.containment = this.helper[0].parentNode; + } + if(o.containment === "document" || o.containment === "window") { + this.containment = [ + 0 - this.offset.relative.left - this.offset.parent.left, + 0 - this.offset.relative.top - this.offset.parent.top, + $(o.containment === "document" ? document : window).width() - this.helperProportions.width - this.margins.left, + ($(o.containment === "document" ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top + ]; + } + + if(!(/^(document|window|parent)$/).test(o.containment)) { + ce = $(o.containment)[0]; + co = $(o.containment).offset(); + over = ($(ce).css("overflow") !== "hidden"); + + this.containment = [ + co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left, + co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top, + co.left+(over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left, + co.top+(over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top + ]; + } + + }, + + _convertPositionTo: function(d, pos) { + + if(!pos) { + pos = this.position; + } + var mod = d === "absolute" ? 1 : -1, + scroll = this.cssPosition === "absolute" && !(this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, + scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName); + + return { + top: ( + pos.top + // The absolute mouse position + this.offset.relative.top * mod + // Only for relative positioned nodes: Relative offset from element to offset parent + this.offset.parent.top * mod - // The offsetParent's offset without borders (offset + border) + ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod) + ), + left: ( + pos.left + // The absolute mouse position + this.offset.relative.left * mod + // Only for relative positioned nodes: Relative offset from element to offset parent + this.offset.parent.left * mod - // The offsetParent's offset without borders (offset + border) + ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod) + ) + }; + + }, + + _generatePosition: function(event) { + + var top, left, + o = this.options, + pageX = event.pageX, + pageY = event.pageY, + scroll = this.cssPosition === "absolute" && !(this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName); + + // This is another very weird special case that only happens for relative elements: + // 1. If the css position is relative + // 2. and the scroll parent is the document or similar to the offset parent + // we have to refresh the relative offset during the scroll so there are no jumps + if(this.cssPosition === "relative" && !(this.scrollParent[0] !== document && this.scrollParent[0] !== this.offsetParent[0])) { + this.offset.relative = this._getRelativeOffset(); + } + + /* + * - Position constraining - + * Constrain the position to a mix of grid, containment. + */ + + if(this.originalPosition) { //If we are not dragging yet, we won't check for options + + if(this.containment) { + if(event.pageX - this.offset.click.left < this.containment[0]) { + pageX = this.containment[0] + this.offset.click.left; + } + if(event.pageY - this.offset.click.top < this.containment[1]) { + pageY = this.containment[1] + this.offset.click.top; + } + if(event.pageX - this.offset.click.left > this.containment[2]) { + pageX = this.containment[2] + this.offset.click.left; + } + if(event.pageY - this.offset.click.top > this.containment[3]) { + pageY = this.containment[3] + this.offset.click.top; + } + } + + if(o.grid) { + top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1]; + pageY = this.containment ? ( (top - this.offset.click.top >= this.containment[1] && top - this.offset.click.top <= this.containment[3]) ? top : ((top - this.offset.click.top >= this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top; + + left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0]; + pageX = this.containment ? ( (left - this.offset.click.left >= this.containment[0] && left - this.offset.click.left <= this.containment[2]) ? left : ((left - this.offset.click.left >= this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left; + } + + } + + return { + top: ( + pageY - // The absolute mouse position + this.offset.click.top - // Click offset (relative to the element) + this.offset.relative.top - // Only for relative positioned nodes: Relative offset from element to offset parent + this.offset.parent.top + // The offsetParent's offset without borders (offset + border) + ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) )) + ), + left: ( + pageX - // The absolute mouse position + this.offset.click.left - // Click offset (relative to the element) + this.offset.relative.left - // Only for relative positioned nodes: Relative offset from element to offset parent + this.offset.parent.left + // The offsetParent's offset without borders (offset + border) + ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() )) + ) + }; + + }, + + _rearrange: function(event, i, a, hardRefresh) { + + a ? a[0].appendChild(this.placeholder[0]) : i.item[0].parentNode.insertBefore(this.placeholder[0], (this.direction === "down" ? i.item[0] : i.item[0].nextSibling)); + + //Various things done here to improve the performance: + // 1. we create a setTimeout, that calls refreshPositions + // 2. on the instance, we have a counter variable, that get's higher after every append + // 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same + // 4. this lets only the last addition to the timeout stack through + this.counter = this.counter ? ++this.counter : 1; + var counter = this.counter; + + this._delay(function() { + if(counter === this.counter) { + this.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove + } + }); + + }, + + _clear: function(event, noPropagation) { + + this.reverting = false; + // We delay all events that have to be triggered to after the point where the placeholder has been removed and + // everything else normalized again + var i, + delayedTriggers = []; + + // We first have to update the dom position of the actual currentItem + // Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088) + if(!this._noFinalSort && this.currentItem.parent().length) { + this.placeholder.before(this.currentItem); + } + this._noFinalSort = null; + + if(this.helper[0] === this.currentItem[0]) { + for(i in this._storedCSS) { + if(this._storedCSS[i] === "auto" || this._storedCSS[i] === "static") { + this._storedCSS[i] = ""; + } + } + this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"); + } else { + this.currentItem.show(); + } + + if(this.fromOutside && !noPropagation) { + delayedTriggers.push(function(event) { this._trigger("receive", event, this._uiHash(this.fromOutside)); }); + } + if((this.fromOutside || this.domPosition.prev !== this.currentItem.prev().not(".ui-sortable-helper")[0] || this.domPosition.parent !== this.currentItem.parent()[0]) && !noPropagation) { + delayedTriggers.push(function(event) { this._trigger("update", event, this._uiHash()); }); //Trigger update callback if the DOM position has changed + } + + // Check if the items Container has Changed and trigger appropriate + // events. + if (this !== this.currentContainer) { + if(!noPropagation) { + delayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); }); + delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); }; }).call(this, this.currentContainer)); + delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this)); }; }).call(this, this.currentContainer)); + } + } + + + //Post events to containers + for (i = this.containers.length - 1; i >= 0; i--){ + if(!noPropagation) { + delayedTriggers.push((function(c) { return function(event) { c._trigger("deactivate", event, this._uiHash(this)); }; }).call(this, this.containers[i])); + } + if(this.containers[i].containerCache.over) { + delayedTriggers.push((function(c) { return function(event) { c._trigger("out", event, this._uiHash(this)); }; }).call(this, this.containers[i])); + this.containers[i].containerCache.over = 0; + } + } + + //Do what was originally in plugins + if ( this.storedCursor ) { + this.document.find( "body" ).css( "cursor", this.storedCursor ); + this.storedStylesheet.remove(); + } + if(this._storedOpacity) { + this.helper.css("opacity", this._storedOpacity); + } + if(this._storedZIndex) { + this.helper.css("zIndex", this._storedZIndex === "auto" ? "" : this._storedZIndex); + } + + this.dragging = false; + if(this.cancelHelperRemoval) { + if(!noPropagation) { + this._trigger("beforeStop", event, this._uiHash()); + for (i=0; i < delayedTriggers.length; i++) { + delayedTriggers[i].call(this, event); + } //Trigger all delayed events + this._trigger("stop", event, this._uiHash()); + } + + this.fromOutside = false; + return false; + } + + if(!noPropagation) { + this._trigger("beforeStop", event, this._uiHash()); + } + + //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node! + this.placeholder[0].parentNode.removeChild(this.placeholder[0]); + + if(this.helper[0] !== this.currentItem[0]) { + this.helper.remove(); + } + this.helper = null; + + if(!noPropagation) { + for (i=0; i < delayedTriggers.length; i++) { + delayedTriggers[i].call(this, event); + } //Trigger all delayed events + this._trigger("stop", event, this._uiHash()); + } + + this.fromOutside = false; + return true; + + }, + + _trigger: function() { + if ($.Widget.prototype._trigger.apply(this, arguments) === false) { + this.cancel(); + } + }, + + _uiHash: function(_inst) { + var inst = _inst || this; + return { + helper: inst.helper, + placeholder: inst.placeholder || $([]), + position: inst.position, + originalPosition: inst.originalPosition, + offset: inst.positionAbs, + item: inst.currentItem, + sender: _inst ? _inst.element : null + }; + } + +}); + +})(jQuery); + +(function($, undefined) { + +var dataSpace = "ui-effects-"; + +$.effects = { + effect: {} +}; + +/*! + * jQuery Color Animations v2.1.2 + * https://github.com/jquery/jquery-color + * + * Copyright 2013 jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + * + * Date: Wed Jan 16 08:47:09 2013 -0600 + */ +(function( jQuery, undefined ) { + + var stepHooks = "backgroundColor borderBottomColor borderLeftColor borderRightColor borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor", + + // plusequals test for += 100 -= 100 + rplusequals = /^([\-+])=\s*(\d+\.?\d*)/, + // a set of RE's that can match strings and generate color tuples. + stringParsers = [{ + re: /rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/, + parse: function( execResult ) { + return [ + execResult[ 1 ], + execResult[ 2 ], + execResult[ 3 ], + execResult[ 4 ] + ]; + } + }, { + re: /rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/, + parse: function( execResult ) { + return [ + execResult[ 1 ] * 2.55, + execResult[ 2 ] * 2.55, + execResult[ 3 ] * 2.55, + execResult[ 4 ] + ]; + } + }, { + // this regex ignores A-F because it's compared against an already lowercased string + re: /#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})/, + parse: function( execResult ) { + return [ + parseInt( execResult[ 1 ], 16 ), + parseInt( execResult[ 2 ], 16 ), + parseInt( execResult[ 3 ], 16 ) + ]; + } + }, { + // this regex ignores A-F because it's compared against an already lowercased string + re: /#([a-f0-9])([a-f0-9])([a-f0-9])/, + parse: function( execResult ) { + return [ + parseInt( execResult[ 1 ] + execResult[ 1 ], 16 ), + parseInt( execResult[ 2 ] + execResult[ 2 ], 16 ), + parseInt( execResult[ 3 ] + execResult[ 3 ], 16 ) + ]; + } + }, { + re: /hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/, + space: "hsla", + parse: function( execResult ) { + return [ + execResult[ 1 ], + execResult[ 2 ] / 100, + execResult[ 3 ] / 100, + execResult[ 4 ] + ]; + } + }], + + // jQuery.Color( ) + color = jQuery.Color = function( color, green, blue, alpha ) { + return new jQuery.Color.fn.parse( color, green, blue, alpha ); + }, + spaces = { + rgba: { + props: { + red: { + idx: 0, + type: "byte" + }, + green: { + idx: 1, + type: "byte" + }, + blue: { + idx: 2, + type: "byte" + } + } + }, + + hsla: { + props: { + hue: { + idx: 0, + type: "degrees" + }, + saturation: { + idx: 1, + type: "percent" + }, + lightness: { + idx: 2, + type: "percent" + } + } + } + }, + propTypes = { + "byte": { + floor: true, + max: 255 + }, + "percent": { + max: 1 + }, + "degrees": { + mod: 360, + floor: true + } + }, + support = color.support = {}, + + // element for support tests + supportElem = jQuery( "

" )[ 0 ], + + // colors = jQuery.Color.names + colors, + + // local aliases of functions called often + each = jQuery.each; + +// determine rgba support immediately +supportElem.style.cssText = "background-color:rgba(1,1,1,.5)"; +support.rgba = supportElem.style.backgroundColor.indexOf( "rgba" ) > -1; + +// define cache name and alpha properties +// for rgba and hsla spaces +each( spaces, function( spaceName, space ) { + space.cache = "_" + spaceName; + space.props.alpha = { + idx: 3, + type: "percent", + def: 1 + }; +}); + +function clamp( value, prop, allowEmpty ) { + var type = propTypes[ prop.type ] || {}; + + if ( value == null ) { + return (allowEmpty || !prop.def) ? null : prop.def; + } + + // ~~ is an short way of doing floor for positive numbers + value = type.floor ? ~~value : parseFloat( value ); + + // IE will pass in empty strings as value for alpha, + // which will hit this case + if ( isNaN( value ) ) { + return prop.def; + } + + if ( type.mod ) { + // we add mod before modding to make sure that negatives values + // get converted properly: -10 -> 350 + return (value + type.mod) % type.mod; + } + + // for now all property types without mod have min and max + return 0 > value ? 0 : type.max < value ? type.max : value; +} + +function stringParse( string ) { + var inst = color(), + rgba = inst._rgba = []; + + string = string.toLowerCase(); + + each( stringParsers, function( i, parser ) { + var parsed, + match = parser.re.exec( string ), + values = match && parser.parse( match ), + spaceName = parser.space || "rgba"; + + if ( values ) { + parsed = inst[ spaceName ]( values ); + + // if this was an rgba parse the assignment might happen twice + // oh well.... + inst[ spaces[ spaceName ].cache ] = parsed[ spaces[ spaceName ].cache ]; + rgba = inst._rgba = parsed._rgba; + + // exit each( stringParsers ) here because we matched + return false; + } + }); + + // Found a stringParser that handled it + if ( rgba.length ) { + + // if this came from a parsed string, force "transparent" when alpha is 0 + // chrome, (and maybe others) return "transparent" as rgba(0,0,0,0) + if ( rgba.join() === "0,0,0,0" ) { + jQuery.extend( rgba, colors.transparent ); + } + return inst; + } + + // named colors + return colors[ string ]; +} + +color.fn = jQuery.extend( color.prototype, { + parse: function( red, green, blue, alpha ) { + if ( red === undefined ) { + this._rgba = [ null, null, null, null ]; + return this; + } + if ( red.jquery || red.nodeType ) { + red = jQuery( red ).css( green ); + green = undefined; + } + + var inst = this, + type = jQuery.type( red ), + rgba = this._rgba = []; + + // more than 1 argument specified - assume ( red, green, blue, alpha ) + if ( green !== undefined ) { + red = [ red, green, blue, alpha ]; + type = "array"; + } + + if ( type === "string" ) { + return this.parse( stringParse( red ) || colors._default ); + } + + if ( type === "array" ) { + each( spaces.rgba.props, function( key, prop ) { + rgba[ prop.idx ] = clamp( red[ prop.idx ], prop ); + }); + return this; + } + + if ( type === "object" ) { + if ( red instanceof color ) { + each( spaces, function( spaceName, space ) { + if ( red[ space.cache ] ) { + inst[ space.cache ] = red[ space.cache ].slice(); + } + }); + } else { + each( spaces, function( spaceName, space ) { + var cache = space.cache; + each( space.props, function( key, prop ) { + + // if the cache doesn't exist, and we know how to convert + if ( !inst[ cache ] && space.to ) { + + // if the value was null, we don't need to copy it + // if the key was alpha, we don't need to copy it either + if ( key === "alpha" || red[ key ] == null ) { + return; + } + inst[ cache ] = space.to( inst._rgba ); + } + + // this is the only case where we allow nulls for ALL properties. + // call clamp with alwaysAllowEmpty + inst[ cache ][ prop.idx ] = clamp( red[ key ], prop, true ); + }); + + // everything defined but alpha? + if ( inst[ cache ] && jQuery.inArray( null, inst[ cache ].slice( 0, 3 ) ) < 0 ) { + // use the default of 1 + inst[ cache ][ 3 ] = 1; + if ( space.from ) { + inst._rgba = space.from( inst[ cache ] ); + } + } + }); + } + return this; + } + }, + is: function( compare ) { + var is = color( compare ), + same = true, + inst = this; + + each( spaces, function( _, space ) { + var localCache, + isCache = is[ space.cache ]; + if (isCache) { + localCache = inst[ space.cache ] || space.to && space.to( inst._rgba ) || []; + each( space.props, function( _, prop ) { + if ( isCache[ prop.idx ] != null ) { + same = ( isCache[ prop.idx ] === localCache[ prop.idx ] ); + return same; + } + }); + } + return same; + }); + return same; + }, + _space: function() { + var used = [], + inst = this; + each( spaces, function( spaceName, space ) { + if ( inst[ space.cache ] ) { + used.push( spaceName ); + } + }); + return used.pop(); + }, + transition: function( other, distance ) { + var end = color( other ), + spaceName = end._space(), + space = spaces[ spaceName ], + startColor = this.alpha() === 0 ? color( "transparent" ) : this, + start = startColor[ space.cache ] || space.to( startColor._rgba ), + result = start.slice(); + + end = end[ space.cache ]; + each( space.props, function( key, prop ) { + var index = prop.idx, + startValue = start[ index ], + endValue = end[ index ], + type = propTypes[ prop.type ] || {}; + + // if null, don't override start value + if ( endValue === null ) { + return; + } + // if null - use end + if ( startValue === null ) { + result[ index ] = endValue; + } else { + if ( type.mod ) { + if ( endValue - startValue > type.mod / 2 ) { + startValue += type.mod; + } else if ( startValue - endValue > type.mod / 2 ) { + startValue -= type.mod; + } + } + result[ index ] = clamp( ( endValue - startValue ) * distance + startValue, prop ); + } + }); + return this[ spaceName ]( result ); + }, + blend: function( opaque ) { + // if we are already opaque - return ourself + if ( this._rgba[ 3 ] === 1 ) { + return this; + } + + var rgb = this._rgba.slice(), + a = rgb.pop(), + blend = color( opaque )._rgba; + + return color( jQuery.map( rgb, function( v, i ) { + return ( 1 - a ) * blend[ i ] + a * v; + })); + }, + toRgbaString: function() { + var prefix = "rgba(", + rgba = jQuery.map( this._rgba, function( v, i ) { + return v == null ? ( i > 2 ? 1 : 0 ) : v; + }); + + if ( rgba[ 3 ] === 1 ) { + rgba.pop(); + prefix = "rgb("; + } + + return prefix + rgba.join() + ")"; + }, + toHslaString: function() { + var prefix = "hsla(", + hsla = jQuery.map( this.hsla(), function( v, i ) { + if ( v == null ) { + v = i > 2 ? 1 : 0; + } + + // catch 1 and 2 + if ( i && i < 3 ) { + v = Math.round( v * 100 ) + "%"; + } + return v; + }); + + if ( hsla[ 3 ] === 1 ) { + hsla.pop(); + prefix = "hsl("; + } + return prefix + hsla.join() + ")"; + }, + toHexString: function( includeAlpha ) { + var rgba = this._rgba.slice(), + alpha = rgba.pop(); + + if ( includeAlpha ) { + rgba.push( ~~( alpha * 255 ) ); + } + + return "#" + jQuery.map( rgba, function( v ) { + + // default to 0 when nulls exist + v = ( v || 0 ).toString( 16 ); + return v.length === 1 ? "0" + v : v; + }).join(""); + }, + toString: function() { + return this._rgba[ 3 ] === 0 ? "transparent" : this.toRgbaString(); + } +}); +color.fn.parse.prototype = color.fn; + +// hsla conversions adapted from: +// https://code.google.com/p/maashaack/source/browse/packages/graphics/trunk/src/graphics/colors/HUE2RGB.as?r=5021 + +function hue2rgb( p, q, h ) { + h = ( h + 1 ) % 1; + if ( h * 6 < 1 ) { + return p + (q - p) * h * 6; + } + if ( h * 2 < 1) { + return q; + } + if ( h * 3 < 2 ) { + return p + (q - p) * ((2/3) - h) * 6; + } + return p; +} + +spaces.hsla.to = function ( rgba ) { + if ( rgba[ 0 ] == null || rgba[ 1 ] == null || rgba[ 2 ] == null ) { + return [ null, null, null, rgba[ 3 ] ]; + } + var r = rgba[ 0 ] / 255, + g = rgba[ 1 ] / 255, + b = rgba[ 2 ] / 255, + a = rgba[ 3 ], + max = Math.max( r, g, b ), + min = Math.min( r, g, b ), + diff = max - min, + add = max + min, + l = add * 0.5, + h, s; + + if ( min === max ) { + h = 0; + } else if ( r === max ) { + h = ( 60 * ( g - b ) / diff ) + 360; + } else if ( g === max ) { + h = ( 60 * ( b - r ) / diff ) + 120; + } else { + h = ( 60 * ( r - g ) / diff ) + 240; + } + + // chroma (diff) == 0 means greyscale which, by definition, saturation = 0% + // otherwise, saturation is based on the ratio of chroma (diff) to lightness (add) + if ( diff === 0 ) { + s = 0; + } else if ( l <= 0.5 ) { + s = diff / add; + } else { + s = diff / ( 2 - add ); + } + return [ Math.round(h) % 360, s, l, a == null ? 1 : a ]; +}; + +spaces.hsla.from = function ( hsla ) { + if ( hsla[ 0 ] == null || hsla[ 1 ] == null || hsla[ 2 ] == null ) { + return [ null, null, null, hsla[ 3 ] ]; + } + var h = hsla[ 0 ] / 360, + s = hsla[ 1 ], + l = hsla[ 2 ], + a = hsla[ 3 ], + q = l <= 0.5 ? l * ( 1 + s ) : l + s - l * s, + p = 2 * l - q; + + return [ + Math.round( hue2rgb( p, q, h + ( 1 / 3 ) ) * 255 ), + Math.round( hue2rgb( p, q, h ) * 255 ), + Math.round( hue2rgb( p, q, h - ( 1 / 3 ) ) * 255 ), + a + ]; +}; + + +each( spaces, function( spaceName, space ) { + var props = space.props, + cache = space.cache, + to = space.to, + from = space.from; + + // makes rgba() and hsla() + color.fn[ spaceName ] = function( value ) { + + // generate a cache for this space if it doesn't exist + if ( to && !this[ cache ] ) { + this[ cache ] = to( this._rgba ); + } + if ( value === undefined ) { + return this[ cache ].slice(); + } + + var ret, + type = jQuery.type( value ), + arr = ( type === "array" || type === "object" ) ? value : arguments, + local = this[ cache ].slice(); + + each( props, function( key, prop ) { + var val = arr[ type === "object" ? key : prop.idx ]; + if ( val == null ) { + val = local[ prop.idx ]; + } + local[ prop.idx ] = clamp( val, prop ); + }); + + if ( from ) { + ret = color( from( local ) ); + ret[ cache ] = local; + return ret; + } else { + return color( local ); + } + }; + + // makes red() green() blue() alpha() hue() saturation() lightness() + each( props, function( key, prop ) { + // alpha is included in more than one space + if ( color.fn[ key ] ) { + return; + } + color.fn[ key ] = function( value ) { + var vtype = jQuery.type( value ), + fn = ( key === "alpha" ? ( this._hsla ? "hsla" : "rgba" ) : spaceName ), + local = this[ fn ](), + cur = local[ prop.idx ], + match; + + if ( vtype === "undefined" ) { + return cur; + } + + if ( vtype === "function" ) { + value = value.call( this, cur ); + vtype = jQuery.type( value ); + } + if ( value == null && prop.empty ) { + return this; + } + if ( vtype === "string" ) { + match = rplusequals.exec( value ); + if ( match ) { + value = cur + parseFloat( match[ 2 ] ) * ( match[ 1 ] === "+" ? 1 : -1 ); + } + } + local[ prop.idx ] = value; + return this[ fn ]( local ); + }; + }); +}); + +// add cssHook and .fx.step function for each named hook. +// accept a space separated string of properties +color.hook = function( hook ) { + var hooks = hook.split( " " ); + each( hooks, function( i, hook ) { + jQuery.cssHooks[ hook ] = { + set: function( elem, value ) { + var parsed, curElem, + backgroundColor = ""; + + if ( value !== "transparent" && ( jQuery.type( value ) !== "string" || ( parsed = stringParse( value ) ) ) ) { + value = color( parsed || value ); + if ( !support.rgba && value._rgba[ 3 ] !== 1 ) { + curElem = hook === "backgroundColor" ? elem.parentNode : elem; + while ( + (backgroundColor === "" || backgroundColor === "transparent") && + curElem && curElem.style + ) { + try { + backgroundColor = jQuery.css( curElem, "backgroundColor" ); + curElem = curElem.parentNode; + } catch ( e ) { + } + } + + value = value.blend( backgroundColor && backgroundColor !== "transparent" ? + backgroundColor : + "_default" ); + } + + value = value.toRgbaString(); + } + try { + elem.style[ hook ] = value; + } catch( e ) { + // wrapped to prevent IE from throwing errors on "invalid" values like 'auto' or 'inherit' + } + } + }; + jQuery.fx.step[ hook ] = function( fx ) { + if ( !fx.colorInit ) { + fx.start = color( fx.elem, hook ); + fx.end = color( fx.end ); + fx.colorInit = true; + } + jQuery.cssHooks[ hook ].set( fx.elem, fx.start.transition( fx.end, fx.pos ) ); + }; + }); + +}; + +color.hook( stepHooks ); + +jQuery.cssHooks.borderColor = { + expand: function( value ) { + var expanded = {}; + + each( [ "Top", "Right", "Bottom", "Left" ], function( i, part ) { + expanded[ "border" + part + "Color" ] = value; + }); + return expanded; + } +}; + +// Basic color names only. +// Usage of any of the other color names requires adding yourself or including +// jquery.color.svg-names.js. +colors = jQuery.Color.names = { + // 4.1. Basic color keywords + aqua: "#00ffff", + black: "#000000", + blue: "#0000ff", + fuchsia: "#ff00ff", + gray: "#808080", + green: "#008000", + lime: "#00ff00", + maroon: "#800000", + navy: "#000080", + olive: "#808000", + purple: "#800080", + red: "#ff0000", + silver: "#c0c0c0", + teal: "#008080", + white: "#ffffff", + yellow: "#ffff00", + + // 4.2.3. "transparent" color keyword + transparent: [ null, null, null, 0 ], + + _default: "#ffffff" +}; + +})( jQuery ); + + +/******************************************************************************/ +/****************************** CLASS ANIMATIONS ******************************/ +/******************************************************************************/ +(function() { + +var classAnimationActions = [ "add", "remove", "toggle" ], + shorthandStyles = { + border: 1, + borderBottom: 1, + borderColor: 1, + borderLeft: 1, + borderRight: 1, + borderTop: 1, + borderWidth: 1, + margin: 1, + padding: 1 + }; + +$.each([ "borderLeftStyle", "borderRightStyle", "borderBottomStyle", "borderTopStyle" ], function( _, prop ) { + $.fx.step[ prop ] = function( fx ) { + if ( fx.end !== "none" && !fx.setAttr || fx.pos === 1 && !fx.setAttr ) { + jQuery.style( fx.elem, prop, fx.end ); + fx.setAttr = true; + } + }; +}); + +function getElementStyles( elem ) { + var key, len, + style = elem.ownerDocument.defaultView ? + elem.ownerDocument.defaultView.getComputedStyle( elem, null ) : + elem.currentStyle, + styles = {}; + + if ( style && style.length && style[ 0 ] && style[ style[ 0 ] ] ) { + len = style.length; + while ( len-- ) { + key = style[ len ]; + if ( typeof style[ key ] === "string" ) { + styles[ $.camelCase( key ) ] = style[ key ]; + } + } + // support: Opera, IE <9 + } else { + for ( key in style ) { + if ( typeof style[ key ] === "string" ) { + styles[ key ] = style[ key ]; + } + } + } + + return styles; +} + + +function styleDifference( oldStyle, newStyle ) { + var diff = {}, + name, value; + + for ( name in newStyle ) { + value = newStyle[ name ]; + if ( oldStyle[ name ] !== value ) { + if ( !shorthandStyles[ name ] ) { + if ( $.fx.step[ name ] || !isNaN( parseFloat( value ) ) ) { + diff[ name ] = value; + } + } + } + } + + return diff; +} + +// support: jQuery <1.8 +if ( !$.fn.addBack ) { + $.fn.addBack = function( selector ) { + return this.add( selector == null ? + this.prevObject : this.prevObject.filter( selector ) + ); + }; +} + +$.effects.animateClass = function( value, duration, easing, callback ) { + var o = $.speed( duration, easing, callback ); + + return this.queue( function() { + var animated = $( this ), + baseClass = animated.attr( "class" ) || "", + applyClassChange, + allAnimations = o.children ? animated.find( "*" ).addBack() : animated; + + // map the animated objects to store the original styles. + allAnimations = allAnimations.map(function() { + var el = $( this ); + return { + el: el, + start: getElementStyles( this ) + }; + }); + + // apply class change + applyClassChange = function() { + $.each( classAnimationActions, function(i, action) { + if ( value[ action ] ) { + animated[ action + "Class" ]( value[ action ] ); + } + }); + }; + applyClassChange(); + + // map all animated objects again - calculate new styles and diff + allAnimations = allAnimations.map(function() { + this.end = getElementStyles( this.el[ 0 ] ); + this.diff = styleDifference( this.start, this.end ); + return this; + }); + + // apply original class + animated.attr( "class", baseClass ); + + // map all animated objects again - this time collecting a promise + allAnimations = allAnimations.map(function() { + var styleInfo = this, + dfd = $.Deferred(), + opts = $.extend({}, o, { + queue: false, + complete: function() { + dfd.resolve( styleInfo ); + } + }); + + this.el.animate( this.diff, opts ); + return dfd.promise(); + }); + + // once all animations have completed: + $.when.apply( $, allAnimations.get() ).done(function() { + + // set the final class + applyClassChange(); + + // for each animated element, + // clear all css properties that were animated + $.each( arguments, function() { + var el = this.el; + $.each( this.diff, function(key) { + el.css( key, "" ); + }); + }); + + // this is guarnteed to be there if you use jQuery.speed() + // it also handles dequeuing the next anim... + o.complete.call( animated[ 0 ] ); + }); + }); +}; + +$.fn.extend({ + addClass: (function( orig ) { + return function( classNames, speed, easing, callback ) { + return speed ? + $.effects.animateClass.call( this, + { add: classNames }, speed, easing, callback ) : + orig.apply( this, arguments ); + }; + })( $.fn.addClass ), + + removeClass: (function( orig ) { + return function( classNames, speed, easing, callback ) { + return arguments.length > 1 ? + $.effects.animateClass.call( this, + { remove: classNames }, speed, easing, callback ) : + orig.apply( this, arguments ); + }; + })( $.fn.removeClass ), + + toggleClass: (function( orig ) { + return function( classNames, force, speed, easing, callback ) { + if ( typeof force === "boolean" || force === undefined ) { + if ( !speed ) { + // without speed parameter + return orig.apply( this, arguments ); + } else { + return $.effects.animateClass.call( this, + (force ? { add: classNames } : { remove: classNames }), + speed, easing, callback ); + } + } else { + // without force parameter + return $.effects.animateClass.call( this, + { toggle: classNames }, force, speed, easing ); + } + }; + })( $.fn.toggleClass ), + + switchClass: function( remove, add, speed, easing, callback) { + return $.effects.animateClass.call( this, { + add: add, + remove: remove + }, speed, easing, callback ); + } +}); + +})(); + +/******************************************************************************/ +/*********************************** EFFECTS **********************************/ +/******************************************************************************/ + +(function() { + +$.extend( $.effects, { + version: "1.10.2", + + // Saves a set of properties in a data storage + save: function( element, set ) { + for( var i=0; i < set.length; i++ ) { + if ( set[ i ] !== null ) { + element.data( dataSpace + set[ i ], element[ 0 ].style[ set[ i ] ] ); + } + } + }, + + // Restores a set of previously saved properties from a data storage + restore: function( element, set ) { + var val, i; + for( i=0; i < set.length; i++ ) { + if ( set[ i ] !== null ) { + val = element.data( dataSpace + set[ i ] ); + // support: jQuery 1.6.2 + // http://bugs.jquery.com/ticket/9917 + // jQuery 1.6.2 incorrectly returns undefined for any falsy value. + // We can't differentiate between "" and 0 here, so we just assume + // empty string since it's likely to be a more common value... + if ( val === undefined ) { + val = ""; + } + element.css( set[ i ], val ); + } + } + }, + + setMode: function( el, mode ) { + if (mode === "toggle") { + mode = el.is( ":hidden" ) ? "show" : "hide"; + } + return mode; + }, + + // Translates a [top,left] array into a baseline value + // this should be a little more flexible in the future to handle a string & hash + getBaseline: function( origin, original ) { + var y, x; + switch ( origin[ 0 ] ) { + case "top": y = 0; break; + case "middle": y = 0.5; break; + case "bottom": y = 1; break; + default: y = origin[ 0 ] / original.height; + } + switch ( origin[ 1 ] ) { + case "left": x = 0; break; + case "center": x = 0.5; break; + case "right": x = 1; break; + default: x = origin[ 1 ] / original.width; + } + return { + x: x, + y: y + }; + }, + + // Wraps the element around a wrapper that copies position properties + createWrapper: function( element ) { + + // if the element is already wrapped, return it + if ( element.parent().is( ".ui-effects-wrapper" )) { + return element.parent(); + } + + // wrap the element + var props = { + width: element.outerWidth(true), + height: element.outerHeight(true), + "float": element.css( "float" ) + }, + wrapper = $( "

" ) + .addClass( "ui-effects-wrapper" ) + .css({ + fontSize: "100%", + background: "transparent", + border: "none", + margin: 0, + padding: 0 + }), + // Store the size in case width/height are defined in % - Fixes #5245 + size = { + width: element.width(), + height: element.height() + }, + active = document.activeElement; + + // support: Firefox + // Firefox incorrectly exposes anonymous content + // https://bugzilla.mozilla.org/show_bug.cgi?id=561664 + try { + active.id; + } catch( e ) { + active = document.body; + } + + element.wrap( wrapper ); + + // Fixes #7595 - Elements lose focus when wrapped. + if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) { + $( active ).focus(); + } + + wrapper = element.parent(); //Hotfix for jQuery 1.4 since some change in wrap() seems to actually lose the reference to the wrapped element + + // transfer positioning properties to the wrapper + if ( element.css( "position" ) === "static" ) { + wrapper.css({ position: "relative" }); + element.css({ position: "relative" }); + } else { + $.extend( props, { + position: element.css( "position" ), + zIndex: element.css( "z-index" ) + }); + $.each([ "top", "left", "bottom", "right" ], function(i, pos) { + props[ pos ] = element.css( pos ); + if ( isNaN( parseInt( props[ pos ], 10 ) ) ) { + props[ pos ] = "auto"; + } + }); + element.css({ + position: "relative", + top: 0, + left: 0, + right: "auto", + bottom: "auto" + }); + } + element.css(size); + + return wrapper.css( props ).show(); + }, + + removeWrapper: function( element ) { + var active = document.activeElement; + + if ( element.parent().is( ".ui-effects-wrapper" ) ) { + element.parent().replaceWith( element ); + + // Fixes #7595 - Elements lose focus when wrapped. + if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) { + $( active ).focus(); + } + } + + + return element; + }, + + setTransition: function( element, list, factor, value ) { + value = value || {}; + $.each( list, function( i, x ) { + var unit = element.cssUnit( x ); + if ( unit[ 0 ] > 0 ) { + value[ x ] = unit[ 0 ] * factor + unit[ 1 ]; + } + }); + return value; + } +}); + +// return an effect options object for the given parameters: +function _normalizeArguments( effect, options, speed, callback ) { + + // allow passing all options as the first parameter + if ( $.isPlainObject( effect ) ) { + options = effect; + effect = effect.effect; + } + + // convert to an object + effect = { effect: effect }; + + // catch (effect, null, ...) + if ( options == null ) { + options = {}; + } + + // catch (effect, callback) + if ( $.isFunction( options ) ) { + callback = options; + speed = null; + options = {}; + } + + // catch (effect, speed, ?) + if ( typeof options === "number" || $.fx.speeds[ options ] ) { + callback = speed; + speed = options; + options = {}; + } + + // catch (effect, options, callback) + if ( $.isFunction( speed ) ) { + callback = speed; + speed = null; + } + + // add options to effect + if ( options ) { + $.extend( effect, options ); + } + + speed = speed || options.duration; + effect.duration = $.fx.off ? 0 : + typeof speed === "number" ? speed : + speed in $.fx.speeds ? $.fx.speeds[ speed ] : + $.fx.speeds._default; + + effect.complete = callback || options.complete; + + return effect; +} + +function standardAnimationOption( option ) { + // Valid standard speeds (nothing, number, named speed) + if ( !option || typeof option === "number" || $.fx.speeds[ option ] ) { + return true; + } + + // Invalid strings - treat as "normal" speed + if ( typeof option === "string" && !$.effects.effect[ option ] ) { + return true; + } + + // Complete callback + if ( $.isFunction( option ) ) { + return true; + } + + // Options hash (but not naming an effect) + if ( typeof option === "object" && !option.effect ) { + return true; + } + + // Didn't match any standard API + return false; +} + +$.fn.extend({ + effect: function( /* effect, options, speed, callback */ ) { + var args = _normalizeArguments.apply( this, arguments ), + mode = args.mode, + queue = args.queue, + effectMethod = $.effects.effect[ args.effect ]; + + if ( $.fx.off || !effectMethod ) { + // delegate to the original method (e.g., .show()) if possible + if ( mode ) { + return this[ mode ]( args.duration, args.complete ); + } else { + return this.each( function() { + if ( args.complete ) { + args.complete.call( this ); + } + }); + } + } + + function run( next ) { + var elem = $( this ), + complete = args.complete, + mode = args.mode; + + function done() { + if ( $.isFunction( complete ) ) { + complete.call( elem[0] ); + } + if ( $.isFunction( next ) ) { + next(); + } + } + + // If the element already has the correct final state, delegate to + // the core methods so the internal tracking of "olddisplay" works. + if ( elem.is( ":hidden" ) ? mode === "hide" : mode === "show" ) { + elem[ mode ](); + done(); + } else { + effectMethod.call( elem[0], args, done ); + } + } + + return queue === false ? this.each( run ) : this.queue( queue || "fx", run ); + }, + + show: (function( orig ) { + return function( option ) { + if ( standardAnimationOption( option ) ) { + return orig.apply( this, arguments ); + } else { + var args = _normalizeArguments.apply( this, arguments ); + args.mode = "show"; + return this.effect.call( this, args ); + } + }; + })( $.fn.show ), + + hide: (function( orig ) { + return function( option ) { + if ( standardAnimationOption( option ) ) { + return orig.apply( this, arguments ); + } else { + var args = _normalizeArguments.apply( this, arguments ); + args.mode = "hide"; + return this.effect.call( this, args ); + } + }; + })( $.fn.hide ), + + toggle: (function( orig ) { + return function( option ) { + if ( standardAnimationOption( option ) || typeof option === "boolean" ) { + return orig.apply( this, arguments ); + } else { + var args = _normalizeArguments.apply( this, arguments ); + args.mode = "toggle"; + return this.effect.call( this, args ); + } + }; + })( $.fn.toggle ), + + // helper functions + cssUnit: function(key) { + var style = this.css( key ), + val = []; + + $.each( [ "em", "px", "%", "pt" ], function( i, unit ) { + if ( style.indexOf( unit ) > 0 ) { + val = [ parseFloat( style ), unit ]; + } + }); + return val; + } +}); + +})(); + +/******************************************************************************/ +/*********************************** EASING ***********************************/ +/******************************************************************************/ + +(function() { + +// based on easing equations from Robert Penner (http://www.robertpenner.com/easing) + +var baseEasings = {}; + +$.each( [ "Quad", "Cubic", "Quart", "Quint", "Expo" ], function( i, name ) { + baseEasings[ name ] = function( p ) { + return Math.pow( p, i + 2 ); + }; +}); + +$.extend( baseEasings, { + Sine: function ( p ) { + return 1 - Math.cos( p * Math.PI / 2 ); + }, + Circ: function ( p ) { + return 1 - Math.sqrt( 1 - p * p ); + }, + Elastic: function( p ) { + return p === 0 || p === 1 ? p : + -Math.pow( 2, 8 * (p - 1) ) * Math.sin( ( (p - 1) * 80 - 7.5 ) * Math.PI / 15 ); + }, + Back: function( p ) { + return p * p * ( 3 * p - 2 ); + }, + Bounce: function ( p ) { + var pow2, + bounce = 4; + + while ( p < ( ( pow2 = Math.pow( 2, --bounce ) ) - 1 ) / 11 ) {} + return 1 / Math.pow( 4, 3 - bounce ) - 7.5625 * Math.pow( ( pow2 * 3 - 2 ) / 22 - p, 2 ); + } +}); + +$.each( baseEasings, function( name, easeIn ) { + $.easing[ "easeIn" + name ] = easeIn; + $.easing[ "easeOut" + name ] = function( p ) { + return 1 - easeIn( 1 - p ); + }; + $.easing[ "easeInOut" + name ] = function( p ) { + return p < 0.5 ? + easeIn( p * 2 ) / 2 : + 1 - easeIn( p * -2 + 2 ) / 2; + }; +}); + +})(); + +})(jQuery); + +(function( $, undefined ) { + +var uid = 0, + hideProps = {}, + showProps = {}; + +hideProps.height = hideProps.paddingTop = hideProps.paddingBottom = + hideProps.borderTopWidth = hideProps.borderBottomWidth = "hide"; +showProps.height = showProps.paddingTop = showProps.paddingBottom = + showProps.borderTopWidth = showProps.borderBottomWidth = "show"; + +$.widget( "ui.accordion", { + version: "1.10.2", + options: { + active: 0, + animate: {}, + collapsible: false, + event: "click", + header: "> li > :first-child,> :not(li):even", + heightStyle: "auto", + icons: { + activeHeader: "ui-icon-triangle-1-s", + header: "ui-icon-triangle-1-e" + }, + + // callbacks + activate: null, + beforeActivate: null + }, + + _create: function() { + var options = this.options; + this.prevShow = this.prevHide = $(); + this.element.addClass( "ui-accordion ui-widget ui-helper-reset" ) + // ARIA + .attr( "role", "tablist" ); + + // don't allow collapsible: false and active: false / null + if ( !options.collapsible && (options.active === false || options.active == null) ) { + options.active = 0; + } + + this._processPanels(); + // handle negative values + if ( options.active < 0 ) { + options.active += this.headers.length; + } + this._refresh(); + }, + + _getCreateEventData: function() { + return { + header: this.active, + panel: !this.active.length ? $() : this.active.next(), + content: !this.active.length ? $() : this.active.next() + }; + }, + + _createIcons: function() { + var icons = this.options.icons; + if ( icons ) { + $( "" ) + .addClass( "ui-accordion-header-icon ui-icon " + icons.header ) + .prependTo( this.headers ); + this.active.children( ".ui-accordion-header-icon" ) + .removeClass( icons.header ) + .addClass( icons.activeHeader ); + this.headers.addClass( "ui-accordion-icons" ); + } + }, + + _destroyIcons: function() { + this.headers + .removeClass( "ui-accordion-icons" ) + .children( ".ui-accordion-header-icon" ) + .remove(); + }, + + _destroy: function() { + var contents; + + // clean up main element + this.element + .removeClass( "ui-accordion ui-widget ui-helper-reset" ) + .removeAttr( "role" ); + + // clean up headers + this.headers + .removeClass( "ui-accordion-header ui-accordion-header-active ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top" ) + .removeAttr( "role" ) + .removeAttr( "aria-selected" ) + .removeAttr( "aria-controls" ) + .removeAttr( "tabIndex" ) + .each(function() { + if ( /^ui-accordion/.test( this.id ) ) { + this.removeAttribute( "id" ); + } + }); + this._destroyIcons(); + + // clean up content panels + contents = this.headers.next() + .css( "display", "" ) + .removeAttr( "role" ) + .removeAttr( "aria-expanded" ) + .removeAttr( "aria-hidden" ) + .removeAttr( "aria-labelledby" ) + .removeClass( "ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-state-disabled" ) + .each(function() { + if ( /^ui-accordion/.test( this.id ) ) { + this.removeAttribute( "id" ); + } + }); + if ( this.options.heightStyle !== "content" ) { + contents.css( "height", "" ); + } + }, + + _setOption: function( key, value ) { + if ( key === "active" ) { + // _activate() will handle invalid values and update this.options + this._activate( value ); + return; + } + + if ( key === "event" ) { + if ( this.options.event ) { + this._off( this.headers, this.options.event ); + } + this._setupEvents( value ); + } + + this._super( key, value ); + + // setting collapsible: false while collapsed; open first panel + if ( key === "collapsible" && !value && this.options.active === false ) { + this._activate( 0 ); + } + + if ( key === "icons" ) { + this._destroyIcons(); + if ( value ) { + this._createIcons(); + } + } + + // #5332 - opacity doesn't cascade to positioned elements in IE + // so we need to add the disabled class to the headers and panels + if ( key === "disabled" ) { + this.headers.add( this.headers.next() ) + .toggleClass( "ui-state-disabled", !!value ); + } + }, + + _keydown: function( event ) { + /*jshint maxcomplexity:15*/ + if ( event.altKey || event.ctrlKey ) { + return; + } + + var keyCode = $.ui.keyCode, + length = this.headers.length, + currentIndex = this.headers.index( event.target ), + toFocus = false; + + switch ( event.keyCode ) { + case keyCode.RIGHT: + case keyCode.DOWN: + toFocus = this.headers[ ( currentIndex + 1 ) % length ]; + break; + case keyCode.LEFT: + case keyCode.UP: + toFocus = this.headers[ ( currentIndex - 1 + length ) % length ]; + break; + case keyCode.SPACE: + case keyCode.ENTER: + this._eventHandler( event ); + break; + case keyCode.HOME: + toFocus = this.headers[ 0 ]; + break; + case keyCode.END: + toFocus = this.headers[ length - 1 ]; + break; + } + + if ( toFocus ) { + $( event.target ).attr( "tabIndex", -1 ); + $( toFocus ).attr( "tabIndex", 0 ); + toFocus.focus(); + event.preventDefault(); + } + }, + + _panelKeyDown : function( event ) { + if ( event.keyCode === $.ui.keyCode.UP && event.ctrlKey ) { + $( event.currentTarget ).prev().focus(); + } + }, + + refresh: function() { + var options = this.options; + this._processPanels(); + + // was collapsed or no panel + if ( ( options.active === false && options.collapsible === true ) || !this.headers.length ) { + options.active = false; + this.active = $(); + // active false only when collapsible is true + } if ( options.active === false ) { + this._activate( 0 ); + // was active, but active panel is gone + } else if ( this.active.length && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) { + // all remaining panel are disabled + if ( this.headers.length === this.headers.find(".ui-state-disabled").length ) { + options.active = false; + this.active = $(); + // activate previous panel + } else { + this._activate( Math.max( 0, options.active - 1 ) ); + } + // was active, active panel still exists + } else { + // make sure active index is correct + options.active = this.headers.index( this.active ); + } + + this._destroyIcons(); + + this._refresh(); + }, + + _processPanels: function() { + this.headers = this.element.find( this.options.header ) + .addClass( "ui-accordion-header ui-helper-reset ui-state-default ui-corner-all" ); + + this.headers.next() + .addClass( "ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom" ) + .filter(":not(.ui-accordion-content-active)") + .hide(); + }, + + _refresh: function() { + var maxHeight, + options = this.options, + heightStyle = options.heightStyle, + parent = this.element.parent(), + accordionId = this.accordionId = "ui-accordion-" + + (this.element.attr( "id" ) || ++uid); + + this.active = this._findActive( options.active ) + .addClass( "ui-accordion-header-active ui-state-active ui-corner-top" ) + .removeClass( "ui-corner-all" ); + this.active.next() + .addClass( "ui-accordion-content-active" ) + .show(); + + this.headers + .attr( "role", "tab" ) + .each(function( i ) { + var header = $( this ), + headerId = header.attr( "id" ), + panel = header.next(), + panelId = panel.attr( "id" ); + if ( !headerId ) { + headerId = accordionId + "-header-" + i; + header.attr( "id", headerId ); + } + if ( !panelId ) { + panelId = accordionId + "-panel-" + i; + panel.attr( "id", panelId ); + } + header.attr( "aria-controls", panelId ); + panel.attr( "aria-labelledby", headerId ); + }) + .next() + .attr( "role", "tabpanel" ); + + this.headers + .not( this.active ) + .attr({ + "aria-selected": "false", + tabIndex: -1 + }) + .next() + .attr({ + "aria-expanded": "false", + "aria-hidden": "true" + }) + .hide(); + + // make sure at least one header is in the tab order + if ( !this.active.length ) { + this.headers.eq( 0 ).attr( "tabIndex", 0 ); + } else { + this.active.attr({ + "aria-selected": "true", + tabIndex: 0 + }) + .next() + .attr({ + "aria-expanded": "true", + "aria-hidden": "false" + }); + } + + this._createIcons(); + + this._setupEvents( options.event ); + + if ( heightStyle === "fill" ) { + maxHeight = parent.height(); + this.element.siblings( ":visible" ).each(function() { + var elem = $( this ), + position = elem.css( "position" ); + + if ( position === "absolute" || position === "fixed" ) { + return; + } + maxHeight -= elem.outerHeight( true ); + }); + + this.headers.each(function() { + maxHeight -= $( this ).outerHeight( true ); + }); + + this.headers.next() + .each(function() { + $( this ).height( Math.max( 0, maxHeight - + $( this ).innerHeight() + $( this ).height() ) ); + }) + .css( "overflow", "auto" ); + } else if ( heightStyle === "auto" ) { + maxHeight = 0; + this.headers.next() + .each(function() { + maxHeight = Math.max( maxHeight, $( this ).css( "height", "" ).height() ); + }) + .height( maxHeight ); + } + }, + + _activate: function( index ) { + var active = this._findActive( index )[ 0 ]; + + // trying to activate the already active panel + if ( active === this.active[ 0 ] ) { + return; + } + + // trying to collapse, simulate a click on the currently active header + active = active || this.active[ 0 ]; + + this._eventHandler({ + target: active, + currentTarget: active, + preventDefault: $.noop + }); + }, + + _findActive: function( selector ) { + return typeof selector === "number" ? this.headers.eq( selector ) : $(); + }, + + _setupEvents: function( event ) { + var events = { + keydown: "_keydown" + }; + if ( event ) { + $.each( event.split(" "), function( index, eventName ) { + events[ eventName ] = "_eventHandler"; + }); + } + + this._off( this.headers.add( this.headers.next() ) ); + this._on( this.headers, events ); + this._on( this.headers.next(), { keydown: "_panelKeyDown" }); + this._hoverable( this.headers ); + this._focusable( this.headers ); + }, + + _eventHandler: function( event ) { + var options = this.options, + active = this.active, + clicked = $( event.currentTarget ), + clickedIsActive = clicked[ 0 ] === active[ 0 ], + collapsing = clickedIsActive && options.collapsible, + toShow = collapsing ? $() : clicked.next(), + toHide = active.next(), + eventData = { + oldHeader: active, + oldPanel: toHide, + newHeader: collapsing ? $() : clicked, + newPanel: toShow + }; + + event.preventDefault(); + + if ( + // click on active header, but not collapsible + ( clickedIsActive && !options.collapsible ) || + // allow canceling activation + ( this._trigger( "beforeActivate", event, eventData ) === false ) ) { + return; + } + + options.active = collapsing ? false : this.headers.index( clicked ); + + // when the call to ._toggle() comes after the class changes + // it causes a very odd bug in IE 8 (see #6720) + this.active = clickedIsActive ? $() : clicked; + this._toggle( eventData ); + + // switch classes + // corner classes on the previously active header stay after the animation + active.removeClass( "ui-accordion-header-active ui-state-active" ); + if ( options.icons ) { + active.children( ".ui-accordion-header-icon" ) + .removeClass( options.icons.activeHeader ) + .addClass( options.icons.header ); + } + + if ( !clickedIsActive ) { + clicked + .removeClass( "ui-corner-all" ) + .addClass( "ui-accordion-header-active ui-state-active ui-corner-top" ); + if ( options.icons ) { + clicked.children( ".ui-accordion-header-icon" ) + .removeClass( options.icons.header ) + .addClass( options.icons.activeHeader ); + } + + clicked + .next() + .addClass( "ui-accordion-content-active" ); + } + }, + + _toggle: function( data ) { + var toShow = data.newPanel, + toHide = this.prevShow.length ? this.prevShow : data.oldPanel; + + // handle activating a panel during the animation for another activation + this.prevShow.add( this.prevHide ).stop( true, true ); + this.prevShow = toShow; + this.prevHide = toHide; + + if ( this.options.animate ) { + this._animate( toShow, toHide, data ); + } else { + toHide.hide(); + toShow.show(); + this._toggleComplete( data ); + } + + toHide.attr({ + "aria-expanded": "false", + "aria-hidden": "true" + }); + toHide.prev().attr( "aria-selected", "false" ); + // if we're switching panels, remove the old header from the tab order + // if we're opening from collapsed state, remove the previous header from the tab order + // if we're collapsing, then keep the collapsing header in the tab order + if ( toShow.length && toHide.length ) { + toHide.prev().attr( "tabIndex", -1 ); + } else if ( toShow.length ) { + this.headers.filter(function() { + return $( this ).attr( "tabIndex" ) === 0; + }) + .attr( "tabIndex", -1 ); + } + + toShow + .attr({ + "aria-expanded": "true", + "aria-hidden": "false" + }) + .prev() + .attr({ + "aria-selected": "true", + tabIndex: 0 + }); + }, + + _animate: function( toShow, toHide, data ) { + var total, easing, duration, + that = this, + adjust = 0, + down = toShow.length && + ( !toHide.length || ( toShow.index() < toHide.index() ) ), + animate = this.options.animate || {}, + options = down && animate.down || animate, + complete = function() { + that._toggleComplete( data ); + }; + + if ( typeof options === "number" ) { + duration = options; + } + if ( typeof options === "string" ) { + easing = options; + } + // fall back from options to animation in case of partial down settings + easing = easing || options.easing || animate.easing; + duration = duration || options.duration || animate.duration; + + if ( !toHide.length ) { + return toShow.animate( showProps, duration, easing, complete ); + } + if ( !toShow.length ) { + return toHide.animate( hideProps, duration, easing, complete ); + } + + total = toShow.show().outerHeight(); + toHide.animate( hideProps, { + duration: duration, + easing: easing, + step: function( now, fx ) { + fx.now = Math.round( now ); + } + }); + toShow + .hide() + .animate( showProps, { + duration: duration, + easing: easing, + complete: complete, + step: function( now, fx ) { + fx.now = Math.round( now ); + if ( fx.prop !== "height" ) { + adjust += fx.now; + } else if ( that.options.heightStyle !== "content" ) { + fx.now = Math.round( total - toHide.outerHeight() - adjust ); + adjust = 0; + } + } + }); + }, + + _toggleComplete: function( data ) { + var toHide = data.oldPanel; + + toHide + .removeClass( "ui-accordion-content-active" ) + .prev() + .removeClass( "ui-corner-top" ) + .addClass( "ui-corner-all" ); + + // Work around for rendering bug in IE (#5421) + if ( toHide.length ) { + toHide.parent()[0].className = toHide.parent()[0].className; + } + + this._trigger( "activate", null, data ); + } +}); + +})( jQuery ); + +(function( $, undefined ) { + +// used to prevent race conditions with remote data sources +var requestIndex = 0; + +$.widget( "ui.autocomplete", { + version: "1.10.2", + defaultElement: "", + options: { + appendTo: null, + autoFocus: false, + delay: 300, + minLength: 1, + position: { + my: "left top", + at: "left bottom", + collision: "none" + }, + source: null, + + // callbacks + change: null, + close: null, + focus: null, + open: null, + response: null, + search: null, + select: null + }, + + pending: 0, + + _create: function() { + // Some browsers only repeat keydown events, not keypress events, + // so we use the suppressKeyPress flag to determine if we've already + // handled the keydown event. #7269 + // Unfortunately the code for & in keypress is the same as the up arrow, + // so we use the suppressKeyPressRepeat flag to avoid handling keypress + // events when we know the keydown event was used to modify the + // search term. #7799 + var suppressKeyPress, suppressKeyPressRepeat, suppressInput, + nodeName = this.element[0].nodeName.toLowerCase(), + isTextarea = nodeName === "textarea", + isInput = nodeName === "input"; + + this.isMultiLine = + // Textareas are always multi-line + isTextarea ? true : + // Inputs are always single-line, even if inside a contentEditable element + // IE also treats inputs as contentEditable + isInput ? false : + // All other element types are determined by whether or not they're contentEditable + this.element.prop( "isContentEditable" ); + + this.valueMethod = this.element[ isTextarea || isInput ? "val" : "text" ]; + this.isNewMenu = true; + + this.element + .addClass( "ui-autocomplete-input" ) + .attr( "autocomplete", "off" ); + + this._on( this.element, { + keydown: function( event ) { + /*jshint maxcomplexity:15*/ + if ( this.element.prop( "readOnly" ) ) { + suppressKeyPress = true; + suppressInput = true; + suppressKeyPressRepeat = true; + return; + } + + suppressKeyPress = false; + suppressInput = false; + suppressKeyPressRepeat = false; + var keyCode = $.ui.keyCode; + switch( event.keyCode ) { + case keyCode.PAGE_UP: + suppressKeyPress = true; + this._move( "previousPage", event ); + break; + case keyCode.PAGE_DOWN: + suppressKeyPress = true; + this._move( "nextPage", event ); + break; + case keyCode.UP: + suppressKeyPress = true; + this._keyEvent( "previous", event ); + break; + case keyCode.DOWN: + suppressKeyPress = true; + this._keyEvent( "next", event ); + break; + case keyCode.ENTER: + case keyCode.NUMPAD_ENTER: + // when menu is open and has focus + if ( this.menu.active ) { + // #6055 - Opera still allows the keypress to occur + // which causes forms to submit + suppressKeyPress = true; + event.preventDefault(); + this.menu.select( event ); + } + break; + case keyCode.TAB: + if ( this.menu.active ) { + this.menu.select( event ); + } + break; + case keyCode.ESCAPE: + if ( this.menu.element.is( ":visible" ) ) { + this._value( this.term ); + this.close( event ); + // Different browsers have different default behavior for escape + // Single press can mean undo or clear + // Double press in IE means clear the whole form + event.preventDefault(); + } + break; + default: + suppressKeyPressRepeat = true; + // search timeout should be triggered before the input value is changed + this._searchTimeout( event ); + break; + } + }, + keypress: function( event ) { + if ( suppressKeyPress ) { + suppressKeyPress = false; + event.preventDefault(); + return; + } + if ( suppressKeyPressRepeat ) { + return; + } + + // replicate some key handlers to allow them to repeat in Firefox and Opera + var keyCode = $.ui.keyCode; + switch( event.keyCode ) { + case keyCode.PAGE_UP: + this._move( "previousPage", event ); + break; + case keyCode.PAGE_DOWN: + this._move( "nextPage", event ); + break; + case keyCode.UP: + this._keyEvent( "previous", event ); + break; + case keyCode.DOWN: + this._keyEvent( "next", event ); + break; + } + }, + input: function( event ) { + if ( suppressInput ) { + suppressInput = false; + event.preventDefault(); + return; + } + this._searchTimeout( event ); + }, + focus: function() { + this.selectedItem = null; + this.previous = this._value(); + }, + blur: function( event ) { + if ( this.cancelBlur ) { + delete this.cancelBlur; + return; + } + + clearTimeout( this.searching ); + this.close( event ); + this._change( event ); + } + }); + + this._initSource(); + this.menu = $( "