aboutsummaryrefslogtreecommitdiffstats
path: root/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources
diff options
context:
space:
mode:
authorhuangjian <huang.jian12@zte.com.cn>2016-08-31 16:47:33 +0800
committerhuangjian <huang.jian12@zte.com.cn>2016-08-31 16:47:33 +0800
commitfa49e78cc199526a9e33b59c5194f8e3bf0f0952 (patch)
tree3478e867a8f304266dbceca6e992cceca410ede4 /winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources
parent159d40f0011559c8f82338b29dca1bffd700f2c8 (diff)
Add winery source code
Change-Id: I1c5088121d79b71098c3cba1996c6f784737532e Issue-id: TOSCA-49 Signed-off-by: huangjian <huang.jian12@zte.com.cn>
Diffstat (limited to 'winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources')
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/API/APIResource.java107
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/API/package-info.java20
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/AbstractComponentInstanceResource.java516
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/AbstractComponentInstanceResourceWithNameDerivedFromAbstractFinal.java200
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/AbstractComponentInstanceWithReferencesResource.java52
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/AbstractComponentsResource.java279
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/AbstractComponentsWithTypeReferenceResource.java71
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/ConstraintResource.java69
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/ConstraintsResource.java39
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/EntityTypeResource.java92
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/GenericComponentPageData.java103
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/GenericVisualAppearanceResource.java123
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/IHasName.java43
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/IHasTypeReference.java39
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/INodeTemplateResourceOrNodeTypeImplementationResource.java19
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/INodeTemplateResourceOrNodeTypeImplementationResourceOrRelationshipTypeImplementationResource.java23
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/INodeTypeImplementationResourceOrRelationshipTypeImplementationResource.java19
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/InheritanceResource.java74
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/MainResource.java189
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/SubMenuData.java38
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/IPersistable.java24
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/collections/CollectionsHelper.java42
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/collections/EntityCollectionResource.java206
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/collections/EntityResource.java123
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/collections/IIdDetermination.java20
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/collections/withid/EntityWithIdCollectionResource.java66
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/collections/withid/EntityWithIdResource.java29
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/collections/withoutid/EntityWithoutIdCollectionResource.java114
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/collections/withoutid/EntityWithoutIdResource.java33
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/collections/withoutid/IdDeterminationWithHashCode.java36
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/collections/withoutid/package-info.java17
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/admin/AbstractAdminResource.java45
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/admin/AdminTopResource.java57
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/admin/NamespacesResource.java253
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/admin/RepositoryAdminResource.java112
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/admin/types/AbstractTypesManager.java204
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/admin/types/ConstraintTypesManager.java25
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/admin/types/PlanLanguagesManager.java29
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/admin/types/PlanTypesManager.java28
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/artifacts/DeploymentArtifactResource.java87
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/artifacts/DeploymentArtifactsResource.java73
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/artifacts/GenericArtifactResource.java42
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/artifacts/GenericArtifactsResource.java572
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/artifacts/ImplementationArtifactResource.java95
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/artifacts/ImplementationArtifactsResource.java93
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/documentation/DocumentationResource.java43
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/documentation/DocumentationsResource.java60
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytemplates/IEntityTemplateResource.java34
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytemplates/PropertiesResource.java66
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytemplates/TEntityTemplateResource.java92
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytemplates/TEntityTemplatesResource.java30
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytemplates/artifacttemplates/ArtifactTemplateResource.java308
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytemplates/artifacttemplates/ArtifactTemplatesResource.java21
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytemplates/artifacttemplates/FilesResource.java163
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytemplates/package-info.java27
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytemplates/policytemplates/PolicyTemplateResource.java95
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytemplates/policytemplates/PolicyTemplatesResource.java23
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypeimplementations/EntityTypeImplementationResource.java29
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypeimplementations/nodetypeimplementations/NodeTypeImplementationResource.java105
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypeimplementations/nodetypeimplementations/NodeTypeImplementationsResource.java18
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypeimplementations/package-info.java19
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypeimplementations/relationshiptypeimplementations/RelationshipTypeImplementationResource.java81
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypeimplementations/relationshiptypeimplementations/RelationshipTypeImplementationsResource.java18
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/ImplementationsOfOneType.java74
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/InstanceStatesResource.java133
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/TopologyGraphElementEntityTypeResource.java23
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/artifacttypes/ArtifactTypeResource.java67
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/artifacttypes/ArtifactTypesResource.java90
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/capabilitytypes/CapabilityTypeResource.java47
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/capabilitytypes/CapabilityTypesResource.java22
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/ImplementationsOfOneNodeTypeResource.java101
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/NodeTypeResource.java105
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/NodeTypesResource.java22
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/VisualAppearanceResource.java84
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/reqandcapdefs/AbstractReqOrCapDefResource.java177
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/reqandcapdefs/CapabilityDefinitionResource.java92
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/reqandcapdefs/CapabilityDefinitionsResource.java50
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/reqandcapdefs/RequirementDefinitionResource.java89
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/reqandcapdefs/RequirementDefinitionsResource.java45
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/reqandcapdefs/RequirementOrCapabilityDefinitionsResource.java131
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/package-info.java17
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/policytypes/AppliesToResource.java41
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/policytypes/LanguageResource.java28
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/policytypes/PolicyTypeResource.java66
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/policytypes/PolicyTypesResource.java22
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/properties/JSPData.java85
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/properties/PropertiesDefinitionResource.java161
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/properties/winery/PropertyDefinitionKVListResource.java41
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/properties/winery/PropertyDefinitionKVResource.java59
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/properties/winery/WinerysPropertiesDefinitionResource.java132
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/relationshiptypes/ImplementationsOfOneRelationshipTypeResource.java95
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/relationshiptypes/RelationshipTypeResource.java165
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/relationshiptypes/RelationshipTypesResource.java17
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/relationshiptypes/VisualAppearanceResource.java291
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/requirementtypes/RequiredCapabilityTypeResource.java83
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/requirementtypes/RequirementTypeResource.java44
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/requirementtypes/RequirementTypesResource.java22
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/imports/ImportsResource.java44
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/imports/genericimports/GenericImportResource.java133
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/imports/genericimports/GenericImportsResource.java38
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/imports/xsdimports/XSDImportResource.java174
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/imports/xsdimports/XSDImportsResource.java124
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/interfaces/InterfaceResource.java46
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/interfaces/InterfacesResource.java140
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/interfaces/OperationResource.java71
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/interfaces/OperationsResource.java69
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/interfaces/ParameterResource.java62
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/interfaces/ParametersResource.java99
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/package-info.java27
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/ServiceTemplateResource.java263
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/ServiceTemplatesResource.java18
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/BoundaryDefinitionsJSPData.java113
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/BoundaryDefinitionsResource.java144
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/PropertyMappingsResource.java115
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/interfaces/ExportedInterfaceResource.java34
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/interfaces/ExportedOperationResource.java249
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/interfaces/ExportedOperationsResource.java38
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/interfaces/InterfacesResource.java38
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/interfaces/package-info.java16
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/policies/PoliciesResource.java46
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/policies/PolicyResource.java26
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/policies/package-info.java16
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/reqscaps/CapabilitiesResource.java76
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/reqscaps/CapabilityResource.java26
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/reqscaps/RequirementResource.java26
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/reqscaps/RequirementsResource.java85
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/reqscaps/package-info.java18
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/plans/PlanFileResource.java115
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/plans/PlanResource.java203
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/plans/PlansResource.java205
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/plans/PlansResourceData.java136
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/selfserviceportal/OptionResource.java96
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/selfserviceportal/OptionsResource.java131
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/selfserviceportal/SelfServicePortalResource.java223
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/topologytemplates/NodeTemplateResource.java145
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/topologytemplates/NodeTemplatesResource.java39
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/topologytemplates/RelationshipTemplateResource.java26
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/topologytemplates/RelationshipTemplatesResource.java39
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/topologytemplates/TopologyTemplateResource.java280
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/tags/TagsResource.java38
140 files changed, 12543 insertions, 0 deletions
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/API/APIResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/API/APIResource.java
new file mode 100644
index 0000000..9393b7e
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/API/APIResource.java
@@ -0,0 +1,107 @@
+/*******************************************************************************
+ * Copyright (c) 2015 University of Stuttgart.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ * Oliver Kopp - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.winery.repository.resources.API;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import javax.ws.rs.GET;
+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.ws.rs.core.Response.Status;
+import javax.xml.namespace.QName;
+
+import org.apache.commons.lang3.StringUtils;
+import org.eclipse.winery.common.ids.definitions.ServiceTemplateId;
+import org.eclipse.winery.model.tosca.TNodeTemplate;
+import org.eclipse.winery.repository.backend.BackendUtils;
+import org.eclipse.winery.repository.backend.Repository;
+import org.eclipse.winery.repository.datatypes.select2.Select2DataWithOptGroups;
+import org.eclipse.winery.repository.resources.servicetemplates.ServiceTemplateResource;
+
+public class APIResource {
+
+ @GET
+ @Path("getallartifacttemplatesofcontaineddeploymentartifacts")
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response getAllArtifactTemplatesOfContainedDeploymentArtifacts(@QueryParam("servicetemplate") String serviceTemplateQNameString, @QueryParam("nodetemplateid") String nodeTemplateId) {
+ if (StringUtils.isEmpty(serviceTemplateQNameString)) {
+ return Response.status(Status.BAD_REQUEST).entity("servicetemplate has be given as query parameter").build();
+ }
+
+ QName serviceTemplateQName = QName.valueOf(serviceTemplateQNameString);
+
+ ServiceTemplateId serviceTemplateId = new ServiceTemplateId(serviceTemplateQName);
+ if (!Repository.INSTANCE.exists(serviceTemplateId)) {
+ return Response.status(Status.BAD_REQUEST).entity("service template does not exist").build();
+ }
+ ServiceTemplateResource serviceTemplateResource = new ServiceTemplateResource(serviceTemplateId);
+
+ Collection<QName> artifactTemplates = new ArrayList<>();
+ List<TNodeTemplate> allNestedNodeTemplates = BackendUtils.getAllNestedNodeTemplates(serviceTemplateResource.getServiceTemplate());
+ for (TNodeTemplate nodeTemplate : allNestedNodeTemplates) {
+ if (StringUtils.isEmpty(nodeTemplateId) || nodeTemplate.getId().equals(nodeTemplateId)) {
+ Collection<QName> ats = BackendUtils.getArtifactTemplatesOfReferencedDeploymentArtifacts(nodeTemplate);
+ artifactTemplates.addAll(ats);
+ }
+ }
+
+ // convert QName list to select2 data
+ Select2DataWithOptGroups res = new Select2DataWithOptGroups();
+ for (QName qName : artifactTemplates) {
+ res.add(qName.getNamespaceURI(), qName.toString(), qName.getLocalPart());
+ }
+ return Response.ok().entity(res.asSortedSet()).build();
+ }
+
+ /**
+ * Implementation similar to
+ * getAllArtifactTemplatesOfContainedDeploymentArtifacts. Only difference is
+ * "getArtifactTemplatesOfReferencedImplementationArtifacts" instead of
+ * "getArtifactTemplatesOfReferencedDeploymentArtifacts".
+ */
+ @GET
+ @Path("getallartifacttemplatesofcontainedimplementationartifacts")
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response getAllArtifactTemplatesOfContainedImplementationArtifacts(@QueryParam("servicetemplate") String serviceTemplateQNameString, @QueryParam("nodetemplateid") String nodeTemplateId) {
+ if (StringUtils.isEmpty(serviceTemplateQNameString)) {
+ return Response.status(Status.BAD_REQUEST).entity("servicetemplate has be given as query parameter").build();
+ }
+ QName serviceTemplateQName = QName.valueOf(serviceTemplateQNameString);
+
+ ServiceTemplateId serviceTemplateId = new ServiceTemplateId(serviceTemplateQName);
+ if (!Repository.INSTANCE.exists(serviceTemplateId)) {
+ return Response.status(Status.BAD_REQUEST).entity("service template does not exist").build();
+ }
+ ServiceTemplateResource serviceTemplateResource = new ServiceTemplateResource(serviceTemplateId);
+
+ Collection<QName> artifactTemplates = new ArrayList<>();
+ List<TNodeTemplate> allNestedNodeTemplates = BackendUtils.getAllNestedNodeTemplates(serviceTemplateResource.getServiceTemplate());
+ for (TNodeTemplate nodeTemplate : allNestedNodeTemplates) {
+ if (StringUtils.isEmpty(nodeTemplateId) || nodeTemplate.getId().equals(nodeTemplateId)) {
+ Collection<QName> ats = BackendUtils.getArtifactTemplatesOfReferencedImplementationArtifacts(nodeTemplate);
+ artifactTemplates.addAll(ats);
+ }
+ }
+
+ // convert QName list to select2 data
+ Select2DataWithOptGroups res = new Select2DataWithOptGroups();
+ for (QName qName : artifactTemplates) {
+ res.add(qName.getNamespaceURI(), qName.toString(), qName.getLocalPart());
+ }
+ return Response.ok().entity(res.asSortedSet()).build();
+ }
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/API/package-info.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/API/package-info.java
new file mode 100644
index 0000000..6eda321
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/API/package-info.java
@@ -0,0 +1,20 @@
+/*******************************************************************************
+ * Copyright (c) 2015 University of Stuttgart.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ * Oliver Kopp - initial API and implementation
+ *******************************************************************************/
+
+/**
+ * This package contains all packages providing extended access to the stored models
+ *
+ * The idea is that the resources provide information stored in the respective definition file.
+ * With this API, the stored data is interpreted more abstractly. As a long-term goal, things
+ * such as inherticance should be supported here
+ */
+package org.eclipse.winery.repository.resources.API; \ No newline at end of file
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/AbstractComponentInstanceResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/AbstractComponentInstanceResource.java
new file mode 100644
index 0000000..d4cc201
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/AbstractComponentInstanceResource.java
@@ -0,0 +1,516 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2013,2015 University of Stuttgart.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ * Oliver Kopp - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.winery.repository.resources;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.StringWriter;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+import javax.ws.rs.core.StreamingOutput;
+import javax.ws.rs.core.UriInfo;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Marshaller;
+import javax.xml.bind.Unmarshaller;
+import javax.xml.namespace.QName;
+import javax.xml.parsers.DocumentBuilder;
+
+import org.eclipse.winery.common.RepositoryFileReference;
+import org.eclipse.winery.common.TOSCADocumentBuilderFactory;
+import org.eclipse.winery.common.constants.MimeTypes;
+import org.eclipse.winery.common.ids.Namespace;
+import org.eclipse.winery.common.ids.XMLId;
+import org.eclipse.winery.common.ids.definitions.TOSCAComponentId;
+import org.eclipse.winery.model.tosca.Definitions;
+import org.eclipse.winery.model.tosca.TExtensibleElements;
+import org.eclipse.winery.model.tosca.TImport;
+import org.eclipse.winery.repository.JAXBSupport;
+import org.eclipse.winery.repository.Utils;
+import org.eclipse.winery.repository.backend.BackendUtils;
+import org.eclipse.winery.repository.backend.Repository;
+import org.eclipse.winery.repository.backend.constants.MediaTypes;
+import org.eclipse.winery.repository.export.TOSCAExportUtil;
+import org.eclipse.winery.repository.resources._support.IPersistable;
+import org.eclipse.winery.repository.resources.documentation.DocumentationsResource;
+import org.eclipse.winery.repository.resources.imports.genericimports.GenericImportResource;
+import org.eclipse.winery.repository.resources.tags.TagsResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.Document;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+
+import com.sun.jersey.api.view.Viewable;
+
+/**
+ * Resource for a component (
+ * <ul>
+ * <li>ServiceTemplates,</li>
+ * <li>EntityTypes,</li>
+ * <li>EntityTypeImplementations,</li>
+ * <li>EntityTemplates</li>
+ * </ul>
+ * ). A component is directly nested in a TDefinitions element. See also
+ * {@link org.eclipse.winery.common.ids.definitions.TOSCAComponentId}
+ *
+ * Bundles all operations required for all components. e.g., namespace+XMLid,
+ * object comparison, import, export, tags
+ *
+ * Uses a TDefinitions document as storage.
+ *
+ * Additional setters and getters are added if it comes to Winery's extensions
+ * such as the color of a relationship type
+ */
+public abstract class AbstractComponentInstanceResource implements Comparable<AbstractComponentInstanceResource>, IPersistable {
+
+ private static final Logger logger = LoggerFactory.getLogger(AbstractComponentInstanceResource.class);
+
+ protected final TOSCAComponentId id;
+
+ private final RepositoryFileReference ref;
+
+ // the object representing the data of this resource
+ private Definitions definitions = null;
+
+ // shortcut for this.definitions.getServiceTemplateOrNodeTypeOrNodeTypeImplementation().get(0);
+ protected TExtensibleElements element = null;
+
+
+ /**
+ * Instantiates the resource. Assumes that the resource should exist
+ * (assured by the caller)
+ *
+ * The caller should <em>not</em> create the resource by other ways. E.g.,
+ * by instantiating this resource and then adding data.
+ */
+ public AbstractComponentInstanceResource(TOSCAComponentId id) {
+ this.id = id;
+
+ // the resource itself exists
+ assert (Repository.INSTANCE.exists(id));
+
+ // the data file might not exist
+ this.ref = BackendUtils.getRefOfDefinitions(id);
+ if (Repository.INSTANCE.exists(this.ref)) {
+ this.load();
+ } else {
+ this.createNew();
+ }
+ }
+
+ /**
+ * Convenience method for getId().getNamespace()
+ */
+ public final Namespace getNamespace() {
+ return this.id.getNamespace();
+ }
+
+ /**
+ * Convenience method for getId().getXmlId()
+ */
+ public final XMLId getXmlId() {
+ return this.id.getXmlId();
+ }
+
+ /**
+ * Convenience method for getId().getQName();
+ *
+ * @return the QName associated with this resource
+ */
+ public final QName getQName() {
+ return this.getId().getQName();
+ }
+
+ /**
+ * Returns the id associated with this resource
+ */
+ public final TOSCAComponentId getId() {
+ return this.id;
+ }
+
+ /**
+ * called from AbstractComponentResource
+ */
+ @DELETE
+ public final Response onDelete() {
+ Response res = BackendUtils.delete(this.id);
+ return res;
+ }
+
+ @Override
+ public final int compareTo(AbstractComponentInstanceResource o) {
+ return this.id.compareTo(o.id);
+ }
+
+ @Override
+ public final boolean equals(Object o) {
+ if (o instanceof String) {
+ throw new IllegalStateException();
+ } else if (o instanceof AbstractComponentInstanceResource) {
+ if (o.getClass().equals(this.getClass())) {
+ // only compare if the two objects are from the same class
+ return ((AbstractComponentInstanceResource) o).getId().equals(this.getId());
+ } else {
+ throw new IllegalStateException();
+ }
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+
+ @Override
+ public final int hashCode() {
+ return this.getId().hashCode();
+ }
+
+ @GET
+ @Path("id")
+ public String getTOSCAId() {
+ return this.id.getXmlId().getDecoded();
+ }
+
+ @PUT
+ @Path("id")
+ public Response putId(@FormParam("id") String id) {
+ // this renames the entity type resource
+ // TODO: implement rename functionality
+ return Response.serverError().entity("not yet implemented").build();
+ }
+
+ /**
+ * Main page
+ */
+ // @Produces(MediaType.TEXT_HTML) // not true because of ?csar leads to send
+ // a csar. We nevertheless have to annotate that to be able to get a JSON
+ // representation required for the file upload (in {@link
+ // ArtifactTemplateResource})
+ //
+ // we cannot issue a request expecting content-type application/zip as it is
+ // not possible to offer the result in a "save-as"-dialog:
+ // http://stackoverflow.com/questions/7464665/ajax-response-content-disposition-attachment
+ @GET
+ @Produces(MediaType.TEXT_HTML)
+ public final Response getHTML(@QueryParam(value = "definitions") String definitions, @QueryParam(value = "csar") String csar, @Context UriInfo uriInfo) {
+ if (!Repository.INSTANCE.exists(this.id)) {
+ return Response.status(Status.NOT_FOUND).build();
+ }
+ if (definitions != null) {
+ return Utils.getDefinitionsOfSelectedResource(this, uriInfo.getBaseUri());
+ } else if (csar != null) {
+ return this.getCSAR();
+ } else {
+ String type = Utils.getTypeForInstance(this.getClass());
+ String viewableName = "/jsp/" + Utils.getIntermediateLocationStringForType(type, "/") + "/" + type.toLowerCase() + ".jsp";
+ Viewable viewable = new Viewable(viewableName, this);
+
+ return Response.ok().entity(viewable).build();
+
+ // we can't do the following as the GET request from the browser
+ // cannot set the accept header properly
+ // "vary: accept" header has to be set as we may also return a THOR
+ // on the same URL
+ // return Response.ok().header(HttpHeaders.VARY,
+ // HttpHeaders.ACCEPT).entity(viewable).build();
+ }
+ }
+
+ @GET
+ @Produces(MimeTypes.MIMETYPE_ZIP)
+ public final Response getCSAR() {
+ if (!Repository.INSTANCE.exists(this.id)) {
+ return Response.status(Status.NOT_FOUND).build();
+ }
+ return Utils.getCSARofSelectedResource(this);
+ }
+
+ /**
+ * Returns the definitions of this resource. Includes required imports of
+ * other definitions
+ *
+ * @param csar used because plan generator's GET request lands here
+ */
+ @GET
+ @Produces({MimeTypes.MIMETYPE_TOSCA_DEFINITIONS, MediaType.APPLICATION_XML, MediaType.TEXT_XML})
+ public Response getDefinitionsAsResponse(@QueryParam(value = "csar") String csar) {
+ if (!Repository.INSTANCE.exists(this.id)) {
+ return Response.status(Status.NOT_FOUND).build();
+ }
+
+ if (csar != null) {
+ return Utils.getCSARofSelectedResource(this);
+ }
+
+ StreamingOutput so = new StreamingOutput() {
+
+ @Override
+ public void write(OutputStream output) throws IOException, WebApplicationException {
+ TOSCAExportUtil exporter = new TOSCAExportUtil();
+ // we include everything related
+ Map<String, Object> conf = new HashMap<>();
+ try {
+ exporter.exportTOSCA(AbstractComponentInstanceResource.this.id, output, conf);
+ } catch (JAXBException e) {
+ throw new WebApplicationException(e);
+ }
+ }
+ };
+ return Response.ok().type(MediaType.TEXT_XML).entity(so).build();
+ }
+
+ /**
+ * @throws IllegalStateException if an IOException occurred. We opted not to
+ * propagate the IOException directly as this exception occurs
+ * seldom and is a not an exception to be treated by all callers
+ * in the prototype.
+ */
+ private void load() {
+ try {
+ InputStream is = Repository.INSTANCE.newInputStream(this.ref);
+ Unmarshaller u = JAXBSupport.createUnmarshaller();
+ this.definitions = (Definitions) u.unmarshal(is);
+ } catch (Exception e) {
+ AbstractComponentInstanceResource.logger.error("Could not read content from file " + this.ref, e);
+ throw new IllegalStateException(e);
+ }
+ try {
+ this.element = this.definitions.getServiceTemplateOrNodeTypeOrNodeTypeImplementation().get(0);
+ } catch (IndexOutOfBoundsException e) {
+ if (this instanceof GenericImportResource) {
+ // everything allright:
+ // ImportResource is a quick hack using 99% of the functionality offered here
+ // As only 1% has to be "quick hacked", we do that instead of a clean design
+ // Clean design: Introduce a class between this and AbstractComponentInstanceResource, where this class and ImportResource inhertis from
+ // A clean design introducing a super class AbstractDefinitionsBackedResource does not work, as we currently also support PropertiesBackedResources and such a super class would required multi-inheritance
+ } else {
+ throw new IllegalStateException("Wrong storage format: No ServiceTemplateOrNodeTypeOrNodeTypeImplementation found.");
+ }
+ }
+ }
+
+ @Override
+ public void persist() throws IOException {
+ BackendUtils.persist(this.definitions, this.ref, MediaTypes.MEDIATYPE_TOSCA_DEFINITIONS);
+ }
+
+ /**
+ * Creates a new instance of the object represented by this resource
+ */
+ private void createNew() {
+ this.definitions = BackendUtils.createWrapperDefinitions(this.getId());
+
+ // create empty element
+ this.element = this.createNewElement();
+
+ // add the element to the definitions
+ this.definitions.getServiceTemplateOrNodeTypeOrNodeTypeImplementation().add(this.element);
+
+ // copy ns + id
+ this.copyIdToFields();
+
+ // ensure that the definitions is persisted. Ensures that export works.
+ BackendUtils.persist(this);
+ }
+
+ /**
+ * Creates an empty instance of an Element.
+ *
+ * The implementors do <em>not</em>have to copy the ns and the id to the
+ * appropriate fields.
+ *
+ * we have two implementation possibilities:
+ * <ul>
+ * <li>a) each subclass implements this method and returns the appropriate
+ * object</li>
+ * <li>b) we use java reflection to invoke the right constructor as done in
+ * the resources</li>
+ * </ul>
+ * We opted for a) to increase readability of the code
+ */
+ protected abstract TExtensibleElements createNewElement();
+
+ /**
+ * Copies the current id of the resource to the appropriate fields in the
+ * element.
+ *
+ * For instance, the id is put in the "name" field for EntityTypes
+ *
+ * We opted for a separate method from createNewElement to enable renaming
+ * of the object
+ */
+ protected abstract void copyIdToFields();
+
+ /**
+ * Returns the Element belonging to this resource. As Java does not allow
+ * overriding returned classes, we expect the caller to either cast right or
+ * to use "getXY" defined by each subclass, where XY is the concrete type
+ *
+ * Shortcut for
+ * getDefinitions().getServiceTemplateOrNodeTypeOrNodeTypeImplementation
+ * ().get(0);
+ *
+ * @return TCapabilityType|...
+ */
+ public TExtensibleElements getElement() {
+ return this.element;
+ }
+
+ /**
+ * @return the reference to the internal list of imports. Can be changed if
+ * some imports are required or should be removed
+ * @throws IllegalStateException if definitions was not loaded or not
+ * initialized
+ */
+ protected List<TImport> getImport() {
+ if (this.definitions == null) {
+ throw new IllegalStateException("Trying to access uninitalized definitions object");
+ }
+ return this.definitions.getImport();
+ }
+
+ /**
+ * Returns an XML representation of the definitions
+ *
+ * We return the complete definitions to allow the user changes to it, such
+ * as adding imports, etc.
+ */
+ public String getDefinitionsAsXMLString() {
+ StringWriter w = new StringWriter();
+ Marshaller m = JAXBSupport.createMarshaller(true);
+ try {
+ m.marshal(this.definitions, w);
+ } catch (JAXBException e) {
+ AbstractComponentInstanceResource.logger.error("Could not marshal definitions", e);
+ throw new IllegalStateException(e);
+ }
+ String res = w.toString();
+ return res;
+ }
+
+ /**
+ * @return the reference to the internal Definitions object
+ */
+ public Definitions getDefinitions() {
+ return this.definitions;
+ }
+
+ @PUT
+ @Consumes({MimeTypes.MIMETYPE_TOSCA_DEFINITIONS, MediaType.APPLICATION_XML, MediaType.TEXT_XML})
+ public Response updateDefinitions(InputStream requestBodyStream) {
+ Unmarshaller u;
+ Definitions defs;
+ Document doc;
+ final StringBuilder sb = new StringBuilder();
+ try {
+ DocumentBuilder db = TOSCADocumentBuilderFactory.INSTANCE.getTOSCADocumentBuilder();
+ db.setErrorHandler(new ErrorHandler() {
+
+ @Override
+ public void warning(SAXParseException exception) throws SAXException {
+ // we don't care
+ }
+
+ @Override
+ public void fatalError(SAXParseException exception) throws SAXException {
+ sb.append("Fatal Error: ");
+ sb.append(exception.getMessage());
+ sb.append("\n");
+ }
+
+ @Override
+ public void error(SAXParseException exception) throws SAXException {
+ sb.append("Fatal Error: ");
+ sb.append(exception.getMessage());
+ sb.append("\n");
+ }
+ });
+ doc = db.parse(requestBodyStream);
+ if (sb.length() > 0) {
+ // some error happened
+ // doc is not null, because the parser parses even if it is not XSD conforming
+ return Response.status(Status.BAD_REQUEST).entity(sb.toString()).build();
+ }
+ } catch (SAXException | IOException e) {
+ AbstractComponentInstanceResource.logger.debug("Could not parse XML", e);
+ return Utils.getResponseForException(e);
+ }
+ try {
+ u = JAXBSupport.createUnmarshaller();
+ defs = (Definitions) u.unmarshal(doc);
+ } catch (JAXBException e) {
+ AbstractComponentInstanceResource.logger.debug("Could not unmarshal from request body stream", e);
+ return Utils.getResponseForException(e);
+ }
+
+ // initial validity check
+
+ // we allow changing the target namespace and the id
+ // This allows for inserting arbitrary definitions XML
+ // if (!this.definitions.getTargetNamespace().equals(this.id.getNamespace().getDecoded())) {
+ // return Response.status(Status.BAD_REQUEST).entity("Changing of the namespace is not supported").build();
+ // }
+ // this.definitions.setTargetNamespace(this.id.getNamespace().getDecoded());
+
+ // TODO: check the provided definitions for validity
+
+ TExtensibleElements tExtensibleElements = defs.getServiceTemplateOrNodeTypeOrNodeTypeImplementation().get(0);
+ if (!tExtensibleElements.getClass().equals(this.createNewElement().getClass())) {
+ return Response.status(Status.BAD_REQUEST).entity("First type in Definitions is not matching the type modeled by this resource").build();
+ }
+
+ this.definitions = defs;
+
+ // replace existing element by retrieved data
+ this.element = this.definitions.getServiceTemplateOrNodeTypeOrNodeTypeImplementation().get(0);
+
+ // ensure that ids did not change
+ // TODO: future work: raise error if user changed id or namespace
+ this.copyIdToFields();
+
+ return BackendUtils.persist(this);
+ }
+
+ @GET
+ @Path("xml/")
+ @Produces(MediaType.TEXT_HTML)
+ public Response getXML() {
+ Viewable viewable = new Viewable("/jsp/xmlSource.jsp", this);
+ return Response.ok().entity(viewable).build();
+ }
+
+ @Path("documentation/")
+ public DocumentationsResource getDocumentationsResource() {
+ return new DocumentationsResource(this, this.getElement().getDocumentation());
+ }
+
+ @Path("tags/")
+ public final TagsResource getTags() {
+ return new TagsResource(this.id);
+ }
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/AbstractComponentInstanceResourceWithNameDerivedFromAbstractFinal.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/AbstractComponentInstanceResourceWithNameDerivedFromAbstractFinal.java
new file mode 100644
index 0000000..7bc7c73
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/AbstractComponentInstanceResourceWithNameDerivedFromAbstractFinal.java
@@ -0,0 +1,200 @@
+/*******************************************************************************
+ * 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.repository.resources;
+
+import java.lang.reflect.Method;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+import javax.xml.namespace.QName;
+
+import org.eclipse.winery.common.ModelUtilities;
+import org.eclipse.winery.common.ids.definitions.TOSCAComponentId;
+import org.eclipse.winery.model.tosca.TBoolean;
+import org.eclipse.winery.model.tosca.TEntityType.DerivedFrom;
+import org.eclipse.winery.repository.backend.BackendUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Models a component instance with name, derived from, abstract, and final <br />
+ * Tags are provided by AbstractComponentInstanceResource
+ *
+ * This class mirrors
+ * AbstractComponentInstanceResourceWithNameDerivedFromAbstractFinalConfigurationBacked
+ * . We did not include interfaces as the getters are currently only called at
+ * the jsp
+ */
+public abstract class AbstractComponentInstanceResourceWithNameDerivedFromAbstractFinal extends AbstractComponentInstanceResource {
+
+ private static final Logger logger = LoggerFactory.getLogger(AbstractComponentInstanceResourceWithNameDerivedFromAbstractFinal.class);
+
+
+ protected AbstractComponentInstanceResourceWithNameDerivedFromAbstractFinal(TOSCAComponentId id) {
+ super(id);
+ }
+
+ /**
+ * @return The associated name of this resource. CSDPR01 foresees a NCName
+ * name and no ID for an entity type. Therefore, we use the ID as
+ * unique identification and convert it to a name when a read
+ * request is put.
+ */
+ @GET
+ @Path("name")
+ public String getName() {
+ return ModelUtilities.getName(this.getElement());
+ }
+
+ @PUT
+ @Path("name")
+ public Response putName(String name) {
+ ModelUtilities.setName(this.getElement(), name);
+ return BackendUtils.persist(this);
+ }
+
+ @GET
+ @Path("derivedFrom")
+ public String getDerivedFrom() {
+ // TOSCA does not introduce a type like WithNameDerivedFromAbstractFinal
+ // We could enumerate all possible implementing classes
+ // Or use java reflection, what we're doing now.
+ Method method;
+ // We have three different "DerivedFrom", for NodeTypeImplementation and RelationshipTypeImplementation, we have to assign to a different "DerivedFrom"
+ // This has to be done in the derived resources
+ DerivedFrom derivedFrom;
+ try {
+ method = this.getElement().getClass().getMethod("getDerivedFrom");
+ derivedFrom = (DerivedFrom) method.invoke(this.getElement());
+ } catch (ClassCastException e) {
+ AbstractComponentInstanceResourceWithNameDerivedFromAbstractFinal.logger.error("Seems that *Implementation is now Definitions backed, but not yet fully implented", e);
+ throw new IllegalStateException(e);
+ } catch (Exception e) {
+ AbstractComponentInstanceResourceWithNameDerivedFromAbstractFinal.logger.error("Could not get derivedFrom", e);
+ throw new IllegalStateException(e);
+ }
+ if (derivedFrom == null) {
+ return null;
+ }
+ QName typeRef = derivedFrom.getTypeRef();
+ if (typeRef == null) {
+ return null;
+ } else {
+ return typeRef.toString();
+ }
+ }
+
+ @PUT
+ @Path("derivedFrom")
+ public Response putDerivedFrom(String type) {
+ QName qname = QName.valueOf(type);
+
+ // see getDerivedFrom for verbose comments
+ Method method;
+ DerivedFrom derivedFrom = new DerivedFrom();
+ derivedFrom.setTypeRef(qname);
+ try {
+ method = this.getElement().getClass().getMethod("setDerivedFrom", DerivedFrom.class);
+ method.invoke(this.getElement(), derivedFrom);
+ } catch (ClassCastException e) {
+ AbstractComponentInstanceResourceWithNameDerivedFromAbstractFinal.logger.error("Seems that *Implementation is now Definitions backed, but not yet fully implemented", e);
+ return Response.status(Status.INTERNAL_SERVER_ERROR).entity(e).build();
+ } catch (Exception e) {
+ AbstractComponentInstanceResourceWithNameDerivedFromAbstractFinal.logger.error("Could not set derivedFrom", e);
+ return Response.status(Status.INTERNAL_SERVER_ERROR).entity(e).build();
+ }
+
+ return BackendUtils.persist(this);
+ }
+
+ /**
+ * @param methodName the method to call: getAbstract|getFinal
+ * @return {@inheritDoc}
+ */
+ private String getTBoolean(String methodName) {
+ // see getDerivedFrom for verbose comments
+ Method method;
+ TBoolean tBoolean;
+ try {
+ method = this.getElement().getClass().getMethod(methodName);
+ tBoolean = (TBoolean) method.invoke(this.getElement());
+ } catch (Exception e) {
+ AbstractComponentInstanceResourceWithNameDerivedFromAbstractFinal.logger.error("Could not get boolean " + methodName, e);
+ throw new IllegalStateException(e);
+ }
+ if (tBoolean == null) {
+ return null;
+ } else {
+ return tBoolean.value();
+ }
+ }
+
+ /**
+ * @param methodName the method to call: setAbstract|setFinal
+ * @return {@inheritDoc}
+ */
+ private Response putTBoolean(String tBooleanStr, String methodName) {
+ // see getDerivedFrom for verbose comments
+
+ Method method;
+ TBoolean tBoolean = TBoolean.fromValue(tBooleanStr);
+ try {
+ method = this.getElement().getClass().getMethod(methodName, TBoolean.class);
+ method.invoke(this.getElement(), tBoolean);
+ } catch (Exception e) {
+ AbstractComponentInstanceResourceWithNameDerivedFromAbstractFinal.logger.error("Could not set tBoolean " + methodName, e);
+ return Response.status(Status.INTERNAL_SERVER_ERROR).entity(e).build();
+ }
+
+ return BackendUtils.persist(this);
+ }
+
+ /**
+ * Method name is not "getAbstract" as ${it.abstract} does not work as
+ * "abstract" is not allowed at that place
+ */
+ @GET
+ @Path("abstract")
+ public String getIsAbstract() {
+ return this.getTBoolean("getAbstract");
+ }
+
+ @PUT
+ @Path("abstract")
+ public Response putIsAbstract(String isAbstract) {
+ return this.putTBoolean(isAbstract, "setAbstract");
+ }
+
+ @GET
+ @Path("final")
+ public String getIsFinal() {
+ return this.getTBoolean("getFinal");
+ }
+
+ @PUT
+ @Path("final")
+ public Response putIsFinal(String isFinal) {
+ return this.putTBoolean(isFinal, "setFinal");
+ }
+
+ /**
+ * @return resource managing abstract, final, derivedFrom
+ */
+ @Path("inheritance/")
+ public InheritanceResource getInheritanceManagement() {
+ return new InheritanceResource(this);
+ }
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/AbstractComponentInstanceWithReferencesResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/AbstractComponentInstanceWithReferencesResource.java
new file mode 100644
index 0000000..3b63b0f
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/AbstractComponentInstanceWithReferencesResource.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2013 University of Stuttgart.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ * Oliver Kopp - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.winery.repository.resources;
+
+import javax.ws.rs.core.Response;
+
+import org.eclipse.winery.model.tosca.Definitions;
+import org.eclipse.winery.common.ids.definitions.TOSCAComponentId;
+
+public abstract class AbstractComponentInstanceWithReferencesResource extends AbstractComponentInstanceResource {
+
+ public AbstractComponentInstanceWithReferencesResource(TOSCAComponentId id) {
+ super(id);
+ }
+
+ /**
+ * Ensures that the presented XML is in line with the stored files
+ */
+ @Override
+ public Response getXML() {
+ this.synchronizeReferences();
+ return super.getXML();
+ }
+
+ @Override
+ public String getDefinitionsAsXMLString() {
+ this.synchronizeReferences();
+ return super.getDefinitionsAsXMLString();
+ }
+
+ @Override
+ public Definitions getDefinitions() {
+ this.synchronizeReferences();
+ return super.getDefinitions();
+ }
+
+ /**
+ * Synchronizes the artifact references with the files stored in the
+ * repository
+ */
+ public abstract void synchronizeReferences();
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/AbstractComponentsResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/AbstractComponentsResource.java
new file mode 100644
index 0000000..5702376
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/AbstractComponentsResource.java
@@ -0,0 +1,279 @@
+/*******************************************************************************
+ * 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.repository.resources;
+
+import java.io.StringWriter;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.SortedSet;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+import javax.xml.namespace.QName;
+
+import org.apache.commons.lang3.StringUtils;
+import org.eclipse.winery.common.Util;
+import org.eclipse.winery.common.ids.definitions.ArtifactTemplateId;
+import org.eclipse.winery.common.ids.definitions.PolicyTemplateId;
+import org.eclipse.winery.common.ids.definitions.ServiceTemplateId;
+import org.eclipse.winery.common.ids.definitions.TOSCAComponentId;
+import org.eclipse.winery.repository.Utils;
+import org.eclipse.winery.repository.backend.BackendUtils;
+import org.eclipse.winery.repository.backend.Repository;
+import org.eclipse.winery.repository.backend.ResourceCreationResult;
+import org.eclipse.winery.repository.resources.entitytemplates.artifacttemplates.ArtifactTemplatesResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.fasterxml.jackson.core.JsonFactory;
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.sun.jersey.api.NotFoundException;
+import com.sun.jersey.api.view.Viewable;
+
+/**
+ * Resource handling of a set of components. Each component has to provide a
+ * class to handle the set. This is required to provide the correct instances of
+ * TOSCAcomponentIds.
+ *
+ * TODO: Add generics here!
+ * {@link Utils.getComponentIdClassForComponentContainer} is then obsolete
+ */
+public abstract class AbstractComponentsResource<R extends AbstractComponentInstanceResource> {
+
+ protected static final Logger logger = LoggerFactory.getLogger(AbstractComponentsResource.class);
+
+
+ @GET
+ @Produces(MediaType.TEXT_HTML)
+ public Response getHTML() {
+ return Response.ok().entity(new Viewable("/jsp/genericcomponentpage.jsp", new GenericComponentPageData(this.getClass()))).build();
+ }
+
+ /**
+ * Creates a new component instance in the given namespace
+ *
+ * @param namespace plain namespace
+ * @param id plain id
+ */
+ protected ResourceCreationResult onPost(String namespace, String name) {
+ ResourceCreationResult res;
+ if (StringUtils.isEmpty(namespace) || StringUtils.isEmpty(name)) {
+ res = new ResourceCreationResult(Status.BAD_REQUEST);
+ } else {
+ String id = Utils.createXMLidAsString(name);
+ TOSCAComponentId tcId;
+ try {
+ tcId = this.getTOSCAcomponentId(namespace, id, false);
+ res = this.createComponentInstance(tcId);
+ // in case the resource additionally supports a name attribute, we set the original name
+ if (res.getStatus().equals(Status.CREATED)) {
+ if ((tcId instanceof ServiceTemplateId) || (tcId instanceof ArtifactTemplateId) || (tcId instanceof PolicyTemplateId)) {
+ // these three types have an additional name (instead of a pure id)
+ // we store the name
+ IHasName resource = (IHasName) AbstractComponentsResource.getComponentInstaceResource(tcId);
+ resource.setName(name);
+ }
+ }
+ } catch (Exception e) {
+ AbstractComponentsResource.logger.debug("Could not create id instance", e);
+ res = new ResourceCreationResult(Status.INTERNAL_SERVER_ERROR);
+ }
+ }
+ return res;
+ }
+
+ /**
+ * Creates a new component instance in the given namespace
+ *
+ * @param namespace plain namespace
+ * @param id plain id
+ * @param ignored this parameter is ignored, but necessary for
+ * {@link ArtifactTemplatesResource} to be able to accept the
+ * artifact type at a post
+ */
+ @POST
+ @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
+ @Produces(MediaType.TEXT_PLAIN)
+ public Response onPost(@FormParam("namespace") String namespace, @FormParam("name") String name, String ignored) {
+ ResourceCreationResult res = this.onPost(namespace, name);
+ return res.getResponse();
+ }
+
+ /**
+ * Creates a TOSCAcomponentId for the given namespace / id combination
+ *
+ * Uses reflection to create a new instance
+ */
+ protected TOSCAComponentId getTOSCAcomponentId(String namespace, String id, boolean URLencoded) throws Exception {
+ Class<? extends TOSCAComponentId> idClass = Utils.getComponentIdClassForComponentContainer(this.getClass());
+ return BackendUtils.getTOSCAcomponentId(idClass, namespace, id, URLencoded);
+ }
+
+ /**
+ * Creates a new instance of the current component
+ *
+ * @return <ul>
+ * <li>Status.CREATED (201) if the resource has been created,</li>
+ * <li>Status.CONFLICT if the resource already exists,</li>
+ * <li>Status.INTERNAL_SERVER_ERROR (500) if something went wrong</li>
+ * </ul>
+ */
+ protected ResourceCreationResult createComponentInstance(TOSCAComponentId tcId) {
+ return BackendUtils.create(tcId);
+ }
+
+ @SuppressWarnings("unchecked")
+ private static Class<? extends AbstractComponentInstanceResource> getComponentInstanceResourceClassForType(String type) {
+ // Guess the package
+ String pkg = "org.eclipse.winery.repository.resources.";
+
+ pkg += Utils.getIntermediateLocationStringForType(type, ".");
+
+ // naming convention: Instance is named after container, but without the
+ // plural s
+ String className = pkg + "." + type + "Resource";
+ try {
+ return (Class<? extends AbstractComponentInstanceResource>) Class.forName(className);
+ } catch (ClassNotFoundException e) {
+ throw new IllegalStateException("Could not find id class for component instance", e);
+ }
+ }
+
+ /**
+ *
+ * @param namespace encoded namespace
+ * @param id encoded id
+ * @return an instance of the requested resource
+ */
+ @Path("{namespace}/{id}/")
+ public R getComponentInstaceResource(@PathParam("namespace") String namespace, @PathParam("id") String id) {
+ return this.getComponentInstaceResource(namespace, id, true);
+ }
+
+ /**
+ * @param encoded specifies whether namespace and id are encoded
+ * @return an instance of the requested resource
+ */
+ @SuppressWarnings("unchecked")
+ public R getComponentInstaceResource(String namespace, String id, boolean encoded) {
+ TOSCAComponentId tcId;
+ try {
+ tcId = this.getTOSCAcomponentId(namespace, id, encoded);
+ } catch (Exception e) {
+ throw new IllegalStateException("Could not create id instance", e);
+ }
+ return (R) AbstractComponentsResource.getComponentInstaceResource(tcId);
+ }
+
+ /**
+ * @return an instance of the requested resource
+ */
+ public AbstractComponentInstanceResource getComponentInstaceResource(QName qname) {
+ return this.getComponentInstaceResource(qname.getNamespaceURI(), qname.getLocalPart(), false);
+ }
+
+ /**
+ * @return an instance of the requested resource
+ * @throws NotFoundException if resource doesn't exist.
+ */
+ public static AbstractComponentInstanceResource getComponentInstaceResource(TOSCAComponentId tcId) {
+ String type = Util.getTypeForComponentId(tcId.getClass());
+ if (!Repository.INSTANCE.exists(tcId)) {
+ AbstractComponentsResource.logger.debug("TOSCA component id " + tcId.toString() + " not found");
+ throw new NotFoundException("TOSCA component id " + tcId.toString() + " not found");
+ }
+ Class<? extends AbstractComponentInstanceResource> newResource = AbstractComponentsResource.getComponentInstanceResourceClassForType(type);
+ Constructor<?>[] constructors = newResource.getConstructors();
+ assert (constructors.length == 1);
+ AbstractComponentInstanceResource newInstance;
+ try {
+ newInstance = (AbstractComponentInstanceResource) constructors[0].newInstance(tcId);
+ } catch (InstantiationException | IllegalAccessException
+ | IllegalArgumentException | InvocationTargetException e) {
+ AbstractComponentsResource.logger.error("Could not instantiate sub resource " + tcId);
+ throw new IllegalStateException("Could not instantiate sub resource", e);
+ }
+ return newInstance;
+ }
+
+ /**
+ * Returns resources for all known component instances
+ *
+ * Required by topologytemplateedit.jsp
+ */
+ public Collection<AbstractComponentInstanceResource> getAll() {
+ Class<? extends TOSCAComponentId> idClass = Utils.getComponentIdClassForComponentContainer(this.getClass());
+ SortedSet<? extends TOSCAComponentId> allTOSCAcomponentIds = Repository.INSTANCE.getAllTOSCAComponentIds(idClass);
+ ArrayList<AbstractComponentInstanceResource> res = new ArrayList<AbstractComponentInstanceResource>(allTOSCAcomponentIds.size());
+ for (TOSCAComponentId id : allTOSCAcomponentIds) {
+ AbstractComponentInstanceResource r = AbstractComponentsResource.getComponentInstaceResource(id);
+ res.add(r);
+ }
+ return res;
+ }
+
+ /**
+ * Used by org.eclipse.winery.repository.repository.client and by the
+ * artifactcreationdialog.tag. Especially the "name" field is used there at
+ * the UI
+ *
+ * @return A list of all ids of all instances of this component type. If the
+ * "name" attribute is required, that name is used as id <br />
+ * Format:
+ * <code>[({"namespace": "<namespace>", "id": "<id>"},)* ]</code>. A
+ * <code>name<code> field is added if the model allows an additional name attribute
+ */
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ public String getListOfAllIds() {
+ Class<? extends TOSCAComponentId> idClass = Utils.getComponentIdClassForComponentContainer(this.getClass());
+ boolean supportsNameAttribute = Util.instanceSupportsNameAttribute(idClass);
+ SortedSet<? extends TOSCAComponentId> allTOSCAcomponentIds = Repository.INSTANCE.getAllTOSCAComponentIds(idClass);
+ JsonFactory jsonFactory = new JsonFactory();
+ StringWriter sw = new StringWriter();
+
+ try {
+ JsonGenerator jg = jsonFactory.createGenerator(sw);
+ // We produce org.eclipse.winery.repository.client.WineryRepositoryClient.NamespaceAndId by hand here
+ // Refactoring could move this class to common and fill it here
+ jg.writeStartArray();
+ for (TOSCAComponentId id : allTOSCAcomponentIds) {
+ jg.writeStartObject();
+ jg.writeStringField("namespace", id.getNamespace().getDecoded());
+ jg.writeStringField("id", id.getXmlId().getDecoded());
+ if (supportsNameAttribute) {
+ AbstractComponentInstanceResource componentInstaceResource = AbstractComponentsResource.getComponentInstaceResource(id);
+ String name = ((IHasName) componentInstaceResource).getName();
+ jg.writeStringField("name", name);
+ }
+ jg.writeEndObject();
+ }
+ jg.writeEndArray();
+ jg.close();
+ } catch (Exception e) {
+ AbstractComponentsResource.logger.error(e.getMessage(), e);
+ return "[]";
+ }
+ return sw.toString();
+ }
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/AbstractComponentsWithTypeReferenceResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/AbstractComponentsWithTypeReferenceResource.java
new file mode 100644
index 0000000..33bc1d4
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/AbstractComponentsWithTypeReferenceResource.java
@@ -0,0 +1,71 @@
+/*******************************************************************************
+ * 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.repository.resources;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.POST;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+
+import org.apache.commons.lang3.StringUtils;
+import org.eclipse.winery.common.ids.definitions.TOSCAComponentId;
+import org.eclipse.winery.repository.backend.ResourceCreationResult;
+import org.restdoc.annotations.RestDocParam;
+
+/**
+ * This class does NOT inherit from TEntityTemplatesResource<ArtifactTemplate>
+ * as these templates are directly nested in a TDefinitionsElement
+ */
+public abstract class AbstractComponentsWithTypeReferenceResource<T extends AbstractComponentInstanceResource> extends AbstractComponentsResource<T> {
+
+ /**
+ * Creates the resource and sets the specified type
+ *
+ * In contrast to the other component instances in this package, we
+ * additionally need the parameter "type" to set the type of the artifact
+ * template.
+ *
+ * @param namespace Namespace of the template
+ * @param name name attribute of the template
+ * @param type: QName of the type, format: {namespace}localname is retrieved
+ * from namespace manager
+ *
+ * @return URI of the created Resource, null if resource already exists,
+ * URI_internalServerError if an internal server error occurred
+ */
+ @POST
+ @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
+ @Produces(MediaType.TEXT_PLAIN)
+ @Override
+ public Response onPost(@RestDocParam(description = "Namespace of the component") @FormParam("namespace") String namespace, @RestDocParam(description = "name attribute of the component") @FormParam("name") String name, @RestDocParam(description = "QName of the type, format: {namespace}localname") @FormParam("type") String type) {
+ // only check for type parameter as namespace and name are checked in super.onPost
+ if (StringUtils.isEmpty(type)) {
+ return Response.status(Status.BAD_REQUEST).build();
+ }
+ ResourceCreationResult creationResult = super.onPost(namespace, name);
+ if (!creationResult.isSuccess()) {
+ return creationResult.getResponse();
+ }
+ if (creationResult.getStatus().equals(Status.CREATED)) {
+ IHasTypeReference resource = (IHasTypeReference) AbstractComponentsResource.getComponentInstaceResource((TOSCAComponentId) creationResult.getId());
+ resource.setType(type);
+ // we assume that setType succeeded and just return the result of the
+ // creation of the artifact template resource
+ // Thus, we do NOT change res
+ }
+ return creationResult.getResponse();
+ }
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/ConstraintResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/ConstraintResource.java
new file mode 100644
index 0000000..b9eb345
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/ConstraintResource.java
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * 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.repository.resources;
+
+import java.util.List;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.eclipse.winery.model.tosca.TConstraint;
+import org.eclipse.winery.repository.backend.BackendUtils;
+import org.eclipse.winery.repository.resources._support.collections.withoutid.EntityWithoutIdResource;
+import org.eclipse.winery.repository.resources.entitytypes.nodetypes.NodeTypeResource;
+
+public class ConstraintResource extends EntityWithoutIdResource<TConstraint> {
+
+ /**
+ *
+ * @param constraint the current constraint value
+ * @param list the list this constraint belongs to
+ * @param res the node type resource this constraint belongs to. Required
+ * for saving
+ */
+ public ConstraintResource(TConstraint constraint, int idx, List<TConstraint> list, NodeTypeResource res) {
+ super(constraint, idx, list, res);
+ }
+
+ /**
+ * Required for collectionResource
+ *
+ * @throws ClassCastException of !(res instanceof NodeTypeResource)
+ */
+ public ConstraintResource(TConstraint constraint, int idx, List<TConstraint> list, AbstractComponentInstanceResource res) {
+ this(constraint, idx, list, (NodeTypeResource) res);
+ }
+
+ private TConstraint getConstraint() {
+ return this.o;
+ }
+
+ @GET
+ @Path("type")
+ @Produces(MediaType.TEXT_PLAIN)
+ public String getConstraintType() {
+ return this.getConstraint().getConstraintType();
+ }
+
+ @PUT
+ @Path("type")
+ @Consumes(MediaType.TEXT_PLAIN)
+ public Response putConstraintType(String constraintType) {
+ this.getConstraint().setConstraintType(constraintType);
+ return BackendUtils.persist(this.res);
+ }
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/ConstraintsResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/ConstraintsResource.java
new file mode 100644
index 0000000..8aea92f
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/ConstraintsResource.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * 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.repository.resources;
+
+import java.util.List;
+
+import org.eclipse.winery.model.tosca.TConstraint;
+import org.eclipse.winery.repository.resources._support.collections.withoutid.EntityWithoutIdCollectionResource;
+import org.eclipse.winery.repository.resources.entitytypes.nodetypes.NodeTypeResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.sun.jersey.api.view.Viewable;
+
+public class ConstraintsResource extends EntityWithoutIdCollectionResource<ConstraintResource, TConstraint> {
+
+ private static final Logger logger = LoggerFactory.getLogger(ConstraintsResource.class);
+
+
+ public ConstraintsResource(List<TConstraint> constraints, NodeTypeResource res) {
+ super(ConstraintResource.class, TConstraint.class, constraints, res);
+ }
+
+ @Override
+ public Viewable getHTML() {
+ // TODO Auto-generated method stub
+ throw new IllegalStateException("Not yet implemented.");
+ }
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/EntityTypeResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/EntityTypeResource.java
new file mode 100644
index 0000000..1b70d56
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/EntityTypeResource.java
@@ -0,0 +1,92 @@
+/*******************************************************************************
+ * 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.repository.resources;
+
+import java.util.Collection;
+import java.util.SortedSet;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+
+import org.eclipse.winery.common.ids.definitions.TOSCAComponentId;
+import org.eclipse.winery.model.tosca.TEntityType;
+import org.eclipse.winery.repository.backend.BackendUtils;
+import org.eclipse.winery.repository.datatypes.select2.Select2DataWithOptGroups;
+import org.eclipse.winery.repository.datatypes.select2.Select2OptGroup;
+import org.eclipse.winery.repository.resources.entitytypes.properties.PropertiesDefinitionResource;
+
+public abstract class EntityTypeResource extends AbstractComponentInstanceResourceWithNameDerivedFromAbstractFinal {
+
+ protected EntityTypeResource(TOSCAComponentId id) {
+ super(id);
+ }
+
+ @Override
+ protected void copyIdToFields() {
+ TEntityType entityType = this.getEntityType();
+ entityType.setTargetNamespace(this.getId().getNamespace().getDecoded());
+ entityType.setName(this.getId().getXmlId().getDecoded());
+ }
+
+ /**
+ * Convenience method to avoid casting. Required by
+ * PropertiesDefinitionResource's jsp
+ */
+ public TEntityType getEntityType() {
+ return (TEntityType) this.element;
+ }
+
+ /**
+ * Models PropertiesDefinition
+ */
+ @Path("propertiesdefinition/")
+ public PropertiesDefinitionResource getPropertiesDefinitionResource() {
+ return new PropertiesDefinitionResource(this);
+ }
+
+ /**
+ * Used by children to implement getListOfAllInstances()
+ */
+ protected SortedSet<Select2OptGroup> getListOfAllInstances(Class<? extends TOSCAComponentId> clazz) {
+ Select2DataWithOptGroups data = new Select2DataWithOptGroups();
+
+ Collection<? extends TOSCAComponentId> instanceIds = BackendUtils.getAllElementsRelatedWithATypeAttribute(clazz, this.id.getQName());
+
+ for (TOSCAComponentId instanceId : instanceIds) {
+ String groupText = instanceId.getNamespace().getDecoded();
+ String text = BackendUtils.getName(instanceId);
+ data.add(groupText, instanceId.getQName().toString(), text);
+ }
+
+ return data.asSortedSet();
+ }
+
+ /**
+ * Returns an array suitable for processing in a {@code select2} field See
+ * {@link http://ivaynberg.github.io/select2}
+ *
+ * Each element: {id: "{ns}localname", text: "name/id"}
+ */
+ @Path("instances/")
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ public SortedSet<Select2OptGroup> getListOfAllInstances() {
+ Response res = Response.status(Status.INTERNAL_SERVER_ERROR).entity("not yet implemented").build();
+ throw new WebApplicationException(res);
+ }
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/GenericComponentPageData.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/GenericComponentPageData.java
new file mode 100644
index 0000000..a2a8533
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/GenericComponentPageData.java
@@ -0,0 +1,103 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2013 University of Stuttgart.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ * Oliver Kopp - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.winery.repository.resources;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.SortedSet;
+
+import org.eclipse.winery.common.ids.definitions.ArtifactTypeId;
+import org.eclipse.winery.common.ids.definitions.NodeTypeId;
+import org.eclipse.winery.common.ids.definitions.PolicyTypeId;
+import org.eclipse.winery.common.ids.definitions.RelationshipTypeId;
+import org.eclipse.winery.common.ids.definitions.TOSCAComponentId;
+import org.eclipse.winery.repository.Utils;
+import org.eclipse.winery.repository.backend.Repository;
+import org.eclipse.winery.repository.resources.entitytemplates.artifacttemplates.ArtifactTemplatesResource;
+import org.eclipse.winery.repository.resources.entitytemplates.policytemplates.PolicyTemplatesResource;
+import org.eclipse.winery.repository.resources.entitytypeimplementations.nodetypeimplementations.NodeTypeImplementationsResource;
+import org.eclipse.winery.repository.resources.entitytypeimplementations.relationshiptypeimplementations.RelationshipTypeImplementationsResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public final class GenericComponentPageData {
+
+ private static final Logger logger = LoggerFactory.getLogger(GenericComponentPageData.class);
+
+ private final SortedSet<? extends TOSCAComponentId> componentInstanceIds;
+
+ private final Class<? extends AbstractComponentsResource> resourceClass;
+
+
+ public GenericComponentPageData(Class<? extends AbstractComponentsResource> resourceClass) {
+ this.resourceClass = resourceClass;
+ Class<? extends TOSCAComponentId> cIdClass = Utils.getComponentIdClassForComponentContainer(resourceClass);
+ this.componentInstanceIds = Repository.INSTANCE.getAllTOSCAComponentIds(cIdClass);
+ }
+
+ /**
+ * Outputs the data for GenericComponentPage (Name / Id / Namespace) needed
+ * for the genericcomponentpage.jsp
+ */
+ public SortedSet<? extends TOSCAComponentId> getComponentInstanceIds() {
+ return this.componentInstanceIds;
+ }
+
+ public String getType() {
+ return Utils.getTypeForComponentContainer(this.resourceClass);
+ }
+
+ public String getCSSclass() {
+ // The resources do NOT know their CSS class
+ // Layout is far away from a resource
+ // Instead of a huge if/else-cascade, we derive the CSS name from the
+ // class name
+ String type = this.getType();
+ // convention: first letter in small letters
+ String res = type.substring(0, 1).toLowerCase() + type.substring(1);
+ // this generated "xSDImport" as CSS class for XSDImport
+ return res;
+ }
+
+ public String getLabel() {
+ String type = this.getType();
+ // E.g., convert ArtifactTemplate to Artifact Template
+ String res = type.replaceAll("(\\p{Lower})(\\p{Upper})", "$1 $2");
+ return res;
+ }
+
+ /**
+ * Required for genericcomponentpage.jsp -> addComponentInstance.jsp
+ *
+ * May only be used if the component supports the type (e.g., artifact
+ * templates)
+ *
+ * @return the list of all known <em>types</em>
+ */
+ public Collection<? extends TOSCAComponentId> getTypeSelectorData() {
+ Class<? extends TOSCAComponentId> typeIdClass;
+ if (this.resourceClass.equals(ArtifactTemplatesResource.class)) {
+ typeIdClass = ArtifactTypeId.class;
+ } else if (this.resourceClass.equals(NodeTypeImplementationsResource.class)) {
+ typeIdClass = NodeTypeId.class;
+ } else if (this.resourceClass.equals(RelationshipTypeImplementationsResource.class)) {
+ typeIdClass = RelationshipTypeId.class;
+ } else if (this.resourceClass.equals(PolicyTemplatesResource.class)) {
+ typeIdClass = PolicyTypeId.class;
+ } else {
+ return Collections.emptyList();
+ }
+ SortedSet<? extends TOSCAComponentId> allTOSCAcomponentIds = Repository.INSTANCE.getAllTOSCAComponentIds(typeIdClass);
+ return allTOSCAcomponentIds;
+ }
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/GenericVisualAppearanceResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/GenericVisualAppearanceResource.java
new file mode 100644
index 0000000..51bbcf1
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/GenericVisualAppearanceResource.java
@@ -0,0 +1,123 @@
+/*******************************************************************************
+ * 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.repository.resources;
+
+import java.io.InputStream;
+import java.net.URI;
+import java.util.Map;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.HeaderParam;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.xml.namespace.QName;
+
+import org.eclipse.winery.common.RepositoryFileReference;
+import org.eclipse.winery.common.ids.elements.TOSCAElementId;
+import org.eclipse.winery.repository.Prefs;
+import org.eclipse.winery.repository.Utils;
+import org.eclipse.winery.repository.backend.BackendUtils;
+import org.eclipse.winery.repository.backend.constants.Filename;
+import org.eclipse.winery.repository.datatypes.ids.elements.VisualAppearanceId;
+import org.eclipse.winery.repository.resources.entitytypes.TopologyGraphElementEntityTypeResource;
+
+//import com.fasterxml.jackson.annotation.JsonIgnore; // currently not required
+import com.sun.jersey.multipart.FormDataBodyPart;
+import com.sun.jersey.multipart.FormDataParam;
+
+/**
+ * Contains methods for both visual appearance for
+ * <ul>
+ * <li>node types</li>
+ * <li>relationship types</li>
+ * </ul>
+ */
+public abstract class GenericVisualAppearanceResource {
+
+ protected final Map<QName, String> otherAttributes;
+ protected final TopologyGraphElementEntityTypeResource res;
+ protected final TOSCAElementId id;
+
+
+ @DELETE
+ public Response onDelete() {
+ return BackendUtils.delete(this.id);
+ }
+
+ /**
+ * Used for GUI when accessing the resource as data E.g., for topology
+ * template
+ */
+ //@JsonIgnore
+ public URI getAbsoluteURL() {
+ String URI = Prefs.INSTANCE.getResourcePath();
+ URI = URI + "/" + Utils.getURLforPathInsideRepo(BackendUtils.getPathInsideRepo(this.id));
+ return Utils.createURI(URI);
+ }
+
+ //@JsonIgnore
+ public TOSCAElementId getId() {
+ return this.id;
+ }
+
+ /**
+ * @param res
+ * @param otherAttributes the other attributes of the node/relationship type
+ * @param id the id of this subresource required for storing the images
+ */
+ public GenericVisualAppearanceResource(TopologyGraphElementEntityTypeResource res, Map<QName, String> otherAttributes, VisualAppearanceId id) {
+ this.id = id;
+ this.res = res;
+ this.otherAttributes = otherAttributes;
+ }
+
+ /**
+ * Determines repository reference to file in repo
+ */
+ protected RepositoryFileReference getRepoFileRef(String name) {
+ return new RepositoryFileReference(this.id, name);
+ }
+
+ protected Response getImage(String name, String modified) {
+ RepositoryFileReference target = this.getRepoFileRef(name);
+ return BackendUtils.returnRepoPath(target, modified);
+ }
+
+ /**
+ * Arbitrary images are supported. There currently is no check for valid
+ * image media types
+ */
+ protected Response putImage(String name, InputStream uploadedInputStream, MediaType mediaType) {
+ RepositoryFileReference target = this.getRepoFileRef(name);
+ return BackendUtils.putContentToFile(target, uploadedInputStream, mediaType);
+ }
+
+ @GET
+ @Path("16x16")
+ public Response get16x16Image(@HeaderParam("If-Modified-Since") String modified) {
+ // Even if the extension is "png", it might contain a jpg, too
+ // We keep the file extension as the windows explorer can display previews even if the content is not a png
+ return this.getImage(Filename.FILENAME_SMALL_ICON, modified);
+ }
+
+ @PUT
+ @Path("16x16")
+ @Consumes(MediaType.MULTIPART_FORM_DATA)
+ public Response post16x16Image(@FormDataParam("file") InputStream uploadedInputStream, @FormDataParam("file") FormDataBodyPart body) {
+ return this.putImage(Filename.FILENAME_SMALL_ICON, uploadedInputStream, body.getMediaType());
+ }
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/IHasName.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/IHasName.java
new file mode 100644
index 0000000..08a3696
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/IHasName.java
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * 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.repository.resources;
+
+import javax.ws.rs.FormParam;
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.restdoc.annotations.RestDoc;
+
+/**
+ * Ensures that the AbstractComponentInstance has a getName method
+ */
+public interface IHasName {
+
+ @GET
+ @Path("name")
+ // @formatter:off
+ @RestDoc(methodDescription = "Returns the name of the element. " +
+ "Defaults to the ID of the element. " +
+ "Some other ComponentInstances either carry a name or an ID. ")
+ // @formatter:on
+ @Produces(MediaType.TEXT_PLAIN)
+ public String getName();
+
+ @PUT
+ @Path("name")
+ public Response setName(@FormParam("value") String name);
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/IHasTypeReference.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/IHasTypeReference.java
new file mode 100644
index 0000000..cb42158
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/IHasTypeReference.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * 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.repository.resources;
+
+import javax.ws.rs.core.Response;
+import javax.xml.namespace.QName;
+
+public interface IHasTypeReference {
+
+ /**
+ * @return the QName of the type with full namespace, never null (according
+ * to spec)
+ */
+ public QName getType();
+
+ /**
+ * Sets the type and directly persists the resource
+ */
+ public Response setType(QName type);
+
+ /**
+ * Calls setType(QName) with QName.valueOf(typeStr)
+ *
+ * Directly persists the resource
+ *
+ * @param typeStr a textual representation of a QName
+ */
+ public Response setType(String typeStr);
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/INodeTemplateResourceOrNodeTypeImplementationResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/INodeTemplateResourceOrNodeTypeImplementationResource.java
new file mode 100644
index 0000000..c8438ef
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/INodeTemplateResourceOrNodeTypeImplementationResource.java
@@ -0,0 +1,19 @@
+/*******************************************************************************
+ * 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.repository.resources;
+
+/**
+ * Implementors can have DAs attached
+ */
+public interface INodeTemplateResourceOrNodeTypeImplementationResource extends INodeTemplateResourceOrNodeTypeImplementationResourceOrRelationshipTypeImplementationResource {
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/INodeTemplateResourceOrNodeTypeImplementationResourceOrRelationshipTypeImplementationResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/INodeTemplateResourceOrNodeTypeImplementationResourceOrRelationshipTypeImplementationResource.java
new file mode 100644
index 0000000..7bd178e
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/INodeTemplateResourceOrNodeTypeImplementationResourceOrRelationshipTypeImplementationResource.java
@@ -0,0 +1,23 @@
+/*******************************************************************************
+ * 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.repository.resources;
+
+import org.eclipse.winery.common.ids.Namespace;
+
+/**
+ * Implementors can have IAs or DAs attached
+ */
+public interface INodeTemplateResourceOrNodeTypeImplementationResourceOrRelationshipTypeImplementationResource {
+
+ Namespace getNamespace();
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/INodeTypeImplementationResourceOrRelationshipTypeImplementationResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/INodeTypeImplementationResourceOrRelationshipTypeImplementationResource.java
new file mode 100644
index 0000000..892a7cb
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/INodeTypeImplementationResourceOrRelationshipTypeImplementationResource.java
@@ -0,0 +1,19 @@
+/*******************************************************************************
+ * 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.repository.resources;
+
+/**
+ * Implementors can have IAs attached
+ */
+public interface INodeTypeImplementationResourceOrRelationshipTypeImplementationResource extends INodeTemplateResourceOrNodeTypeImplementationResourceOrRelationshipTypeImplementationResource {
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/InheritanceResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/InheritanceResource.java
new file mode 100644
index 0000000..7cc878a
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/InheritanceResource.java
@@ -0,0 +1,74 @@
+/*******************************************************************************
+ * 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.repository.resources;
+
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+import org.eclipse.winery.common.ids.definitions.TOSCAComponentId;
+import org.eclipse.winery.repository.backend.Repository;
+
+import com.sun.jersey.api.view.Viewable;
+
+/**
+ * Class for managing inheritance properties: abstract, final, derivedFromn
+ *
+ * The linking in the resources tree is different than the others. Here, there
+ * is no additional Id generated.
+ *
+ * We separated the code here to have the collection of valid super types in a
+ * separate class. We think, this is less confusing than including this
+ * functionality in
+ * AbstractComponentInstanceResourceWithNameDerivedFromAbstractFinalDefinitionsBacked
+ */
+public class InheritanceResource {
+
+ private AbstractComponentInstanceResourceWithNameDerivedFromAbstractFinal managedResource;
+
+
+ public InheritanceResource(AbstractComponentInstanceResourceWithNameDerivedFromAbstractFinal res) {
+ this.managedResource = res;
+ }
+
+ @GET
+ @Produces(MediaType.TEXT_HTML)
+ public Viewable getHTML() {
+ return new Viewable("/jsp/inheritance.jsp", this);
+ }
+
+ public String getIsAbstract() {
+ return this.managedResource.getIsAbstract();
+ }
+
+ public String getIsFinal() {
+ return this.managedResource.getIsAbstract();
+ }
+
+ public String getDerivedFrom() {
+ return this.managedResource.getDerivedFrom();
+ }
+
+ /** JSP Data **/
+
+ public SortedSet<? extends TOSCAComponentId> getPossibleSuperTypes() {
+ // sorted by Name, not by namespace
+ SortedSet<? extends TOSCAComponentId> allTOSCAcomponentIds = Repository.INSTANCE.getAllTOSCAComponentIds(this.managedResource.getId().getClass());
+ SortedSet<? extends TOSCAComponentId> res = new TreeSet<>(allTOSCAcomponentIds);
+ res.remove(this.managedResource.getId());
+ // FEATURE: Possibly exclude all subtypes to avoid circles. However, this could be disappointing for users who know what they are doing
+ return res;
+ }
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/MainResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/MainResource.java
new file mode 100644
index 0000000..87b5275
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/MainResource.java
@@ -0,0 +1,189 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2015 University of Stuttgart.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ * Oliver Kopp - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.winery.repository.resources;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+
+import org.apache.commons.io.FileUtils;
+import org.eclipse.winery.repository.Utils;
+import org.eclipse.winery.repository.importing.CSARImporter;
+import org.eclipse.winery.repository.resources.API.APIResource;
+import org.eclipse.winery.repository.resources.admin.AdminTopResource;
+import org.eclipse.winery.repository.resources.entitytemplates.artifacttemplates.ArtifactTemplatesResource;
+import org.eclipse.winery.repository.resources.entitytemplates.policytemplates.PolicyTemplatesResource;
+import org.eclipse.winery.repository.resources.entitytypeimplementations.nodetypeimplementations.NodeTypeImplementationsResource;
+import org.eclipse.winery.repository.resources.entitytypeimplementations.relationshiptypeimplementations.RelationshipTypeImplementationsResource;
+import org.eclipse.winery.repository.resources.entitytypes.artifacttypes.ArtifactTypesResource;
+import org.eclipse.winery.repository.resources.entitytypes.capabilitytypes.CapabilityTypesResource;
+import org.eclipse.winery.repository.resources.entitytypes.nodetypes.NodeTypesResource;
+import org.eclipse.winery.repository.resources.entitytypes.policytypes.PolicyTypesResource;
+import org.eclipse.winery.repository.resources.entitytypes.relationshiptypes.RelationshipTypesResource;
+import org.eclipse.winery.repository.resources.entitytypes.requirementtypes.RequirementTypesResource;
+import org.eclipse.winery.repository.resources.imports.ImportsResource;
+import org.eclipse.winery.repository.resources.servicetemplates.ServiceTemplatesResource;
+import org.restdoc.annotations.RestDoc;
+import org.restdoc.annotations.RestDocParam;
+import org.restdoc.annotations.RestDocReturnCode;
+
+import com.sun.jersey.api.view.Viewable;
+import com.sun.jersey.core.header.FormDataContentDisposition;
+import com.sun.jersey.multipart.FormDataParam;
+
+/**
+ * All paths listed here have to be listed in Jersey's filter configuration
+ */
+@Path("/")
+public class MainResource {
+
+ @Path("API/")
+ public APIResource api() {
+ return new APIResource();
+ }
+
+ @Path("artifacttemplates/")
+ public ArtifactTemplatesResource artifacttemplates() {
+ return new ArtifactTemplatesResource();
+ }
+
+ @Path("artifacttypes/")
+ public ArtifactTypesResource artifactypes() {
+ return new ArtifactTypesResource();
+ }
+
+ @Path("admin/")
+ public AdminTopResource admin() {
+ return new AdminTopResource();
+ }
+
+ @Path("capabilitytypes/")
+ public CapabilityTypesResource capabilitytypes() {
+ return new CapabilityTypesResource();
+ }
+
+ @Path("imports/")
+ public ImportsResource imports() {
+ return new ImportsResource();
+ }
+
+ @Path("nodetypes/")
+ public NodeTypesResource nodetypes() {
+ return new NodeTypesResource();
+ }
+
+ @Path("nodetypeimplementations/")
+ public NodeTypeImplementationsResource nodetypeimplementations() {
+ return new NodeTypeImplementationsResource();
+ }
+
+ @Path("other/")
+ @GET
+ @Produces(MediaType.TEXT_HTML)
+ public Viewable getOtherElements() {
+ return new Viewable("/jsp/otherElements.jsp");
+ }
+
+ @Path("policytemplates/")
+ public PolicyTemplatesResource policytemplates() {
+ return new PolicyTemplatesResource();
+ }
+
+ @Path("policytypes/")
+ public PolicyTypesResource policytypes() {
+ return new PolicyTypesResource();
+ }
+
+ @Path("relationshiptypes/")
+ public RelationshipTypesResource relationshiptypes() {
+ return new RelationshipTypesResource();
+ }
+
+ @Path("requirementtypes/")
+ public RequirementTypesResource requirementtypes() {
+ return new RequirementTypesResource();
+ }
+
+ @Path("relationshiptypeimplementations/")
+ public RelationshipTypeImplementationsResource relationshiptypeimplementations() {
+ return new RelationshipTypeImplementationsResource();
+ }
+
+ @Path("servicetemplates/")
+ public ServiceTemplatesResource servicetemplates() {
+ return new ServiceTemplatesResource();
+ }
+
+ /**
+ * Returns the main page of winery.
+ */
+ @GET
+ @Produces(MediaType.TEXT_HTML)
+ public Response onGet() {
+ return Response.temporaryRedirect(Utils.createURI("servicetemplates/")).build();
+ }
+
+ @POST
+ @Consumes(MediaType.MULTIPART_FORM_DATA)
+ @RestDoc(methodDescription = "Imports the given CSAR (sent by simplesinglefileupload.jsp)")
+ @RestDocReturnCode(code = "200", description = "If the CSAR could be partially imported, the points where it failed are returned in the body")
+ // @formatter:off
+ public Response importCSAR(
+ @FormDataParam("file") InputStream uploadedInputStream, @FormDataParam("file") FormDataContentDisposition fileDetail,
+ @FormDataParam("overwrite") @RestDocParam(description = "true: content of CSAR overwrites existing content. false (default): existing content is kept") Boolean overwrite) {
+ // @formatter:on
+ CSARImporter importer = new CSARImporter();
+ List<String> errors = new ArrayList<String>();
+ boolean ow;
+ ow = (overwrite != null) && overwrite;
+ try {
+ importer.readCSAR(uploadedInputStream, errors, ow, true);
+ } catch (Exception e) {
+ return Response.serverError().entity("Could not import CSAR").entity(e.getMessage()).build();
+ }
+ if (errors.isEmpty()) {
+ return Response.noContent().build();
+ } else {
+ // In case there are errors, we send them as "bad request"
+ return Response.status(Status.BAD_REQUEST).entity(errors).build();
+ }
+ }
+
+ @POST
+ @Consumes(MediaType.APPLICATION_XML)
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response importDefinitions(InputStream is) throws IOException {
+ File toscaFile;
+ toscaFile = File.createTempFile("TOSCA", ".tosca");
+ FileUtils.copyInputStreamToFile(is, toscaFile);
+ CSARImporter importer = new CSARImporter();
+ List<String> errors = new ArrayList<>();
+ importer.importDefinitions(null, toscaFile.toPath(), errors, false, true);
+ if (errors.isEmpty()) {
+ return Response.noContent().build();
+ } else {
+ return Response.status(Status.BAD_REQUEST).entity(errors).build();
+ }
+ }
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/SubMenuData.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/SubMenuData.java
new file mode 100644
index 0000000..3f79c87
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/SubMenuData.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * 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.repository.resources;
+
+/**
+ * Data used to render a submenu item
+ */
+public class SubMenuData {
+
+ private final String href;
+ private final String text;
+
+ public static final SubMenuData SUBMENU_DOCUMENTATION = new SubMenuData("#documentation", "Documentation");
+ public static final SubMenuData SUBMENU_XML = new SubMenuData("#xml", "XML");
+
+
+ public SubMenuData(String href, String text) {
+ this.href = href;
+ this.text = text;
+ }
+
+ public String getHref() {
+ return this.href;
+ }
+
+ public String getText() {
+ return this.text;
+ }
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/IPersistable.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/IPersistable.java
new file mode 100644
index 0000000..85f565c
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/IPersistable.java
@@ -0,0 +1,24 @@
+/*******************************************************************************
+ * 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.repository.resources._support;
+
+import java.io.IOException;
+
+public interface IPersistable {
+
+ /**
+ * @throws IOException if content could not be updated in the repository
+ * @throws IllegalStateException if an JAXBException occurred. This should
+ * never happen.
+ */
+ public void persist() throws IOException;
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/collections/CollectionsHelper.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/collections/CollectionsHelper.java
new file mode 100644
index 0000000..f150855
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/collections/CollectionsHelper.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * 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.repository.resources._support.collections;
+
+import javax.ws.rs.core.Response;
+
+import org.eclipse.winery.repository.backend.BackendUtils;
+import org.eclipse.winery.repository.resources._support.IPersistable;
+
+public class CollectionsHelper {
+
+ private CollectionsHelper() {
+ }
+
+ /**
+ *
+ * @param <X>
+ * @param resource the resource to be persisted
+ * @param idDetermination the object to use to determine the id of the
+ * entity
+ * @param entity the entity that was persisted. Used to determine the id
+ * @return the new id id of the resource
+ */
+ public static <X> Response persist(IPersistable resource, IIdDetermination<X> idDetermination, X entity) {
+ Response res = BackendUtils.persist(resource);
+ if (res.getStatus() == 204) {
+ String id = idDetermination.getId(entity);
+ res = Response.ok(id).build();
+ }
+ return res;
+ }
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/collections/EntityCollectionResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/collections/EntityCollectionResource.java
new file mode 100644
index 0000000..64d0fbe
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/collections/EntityCollectionResource.java
@@ -0,0 +1,206 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2014 University of Stuttgart.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ * Oliver Kopp - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.winery.repository.resources._support.collections;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+
+import org.eclipse.winery.common.Util;
+import org.eclipse.winery.repository.datatypes.select2.Select2DataItem;
+import org.eclipse.winery.repository.resources._support.IPersistable;
+import org.restdoc.annotations.RestDoc;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.sun.jersey.api.NotFoundException;
+import com.sun.jersey.api.view.Viewable;
+
+/**
+ * Class managing a list of entities. It is intended to manage subresources,
+ * which are stored in a list. Either all entities have a unique key given by
+ * the TOSCA specification (subclass EntityWithIdCollectionResource) or a unique
+ * key is generated (subclass EntityWithoutIdCollectionResource)
+ *
+ * @param <EntityResourceT> the resource modeling the entity
+ * @param <EntityT> the entity type of single items in the list
+ */
+public abstract class EntityCollectionResource<EntityResourceT extends EntityResource<EntityT>, EntityT> implements IIdDetermination<EntityT> {
+
+ private static final Logger logger = LoggerFactory.getLogger(EntityCollectionResource.class);
+
+ protected final List<EntityT> list;
+
+ protected final IPersistable res;
+
+ protected final Class<EntityT> entityTClazz;
+
+ protected final Class<EntityResourceT> entityResourceTClazz;
+
+
+ /**
+ * @param clazz the class of EntityT. Required as it is not possible to call
+ * new EntityT (see http://stackoverflow.com/a/1090488/873282)
+ * @param list the list of entities contained in this resource. Has to be
+ * typed <Object> as not all TOSCA elements in the specification
+ * inherit from TExtensibleElements
+ * @param res the main resource the list is belonging to. Required for
+ * persistence.
+ */
+ public EntityCollectionResource(Class<EntityResourceT> entityResourceTClazz, Class<EntityT> entityTClazz, List<EntityT> list, IPersistable res) {
+ this.entityResourceTClazz = entityResourceTClazz;
+ this.entityTClazz = entityTClazz;
+ this.list = list;
+ this.res = res;
+ }
+
+ /**
+ * Returns a list of ids of all entities nested here
+ */
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ public Object getListOfAllEntityIds(@QueryParam("select2") String select2) {
+ if (select2 == null) {
+ return this.getListOfAllEntityIdsAsList();
+ } else {
+ // return data ready for consumption by select2
+ List<Select2DataItem> res = new ArrayList<Select2DataItem>(this.list.size());
+ for (EntityT o : this.list) {
+ String id = this.getId(o);
+ Select2DataItem di = new Select2DataItem(id, id);
+ res.add(di);
+ }
+ return res;
+ }
+ }
+
+ public List<String> getListOfAllEntityIdsAsList() {
+ List<String> res = new ArrayList<String>(this.list.size());
+ for (EntityT o : this.list) {
+ // We assume that different Object serializations *always* have different hashCodes
+ res.add(this.getId(o));
+ }
+ return res;
+ }
+
+ /**
+ * Required by reqandcapdefs.jsp
+ */
+ public List<EntityResourceT> getAllEntityResources() {
+ List<String> listOfAllSubResources = this.getListOfAllEntityIdsAsList();
+ List<EntityResourceT> res = new ArrayList<EntityResourceT>(listOfAllSubResources.size());
+ for (String id : listOfAllSubResources) {
+ res.add(this.getEntityResourceFromDecodedId(id));
+ }
+ return res;
+ }
+
+ public EntityResourceT getEntityResourceFromDecodedId(String id) {
+ EntityT entity = null;
+ int idx = -1;
+ for (EntityT c : this.list) {
+ idx++;
+ String cId = this.getId(c);
+ if (cId.equals(id)) {
+ entity = c;
+ break;
+ }
+ }
+ if (entity == null) {
+ throw new NotFoundException();
+ } else {
+ return this.getEntityResourceInstance(entity, idx);
+ }
+ }
+
+ @Path("{id}/")
+ public EntityResourceT getEntityResource(@PathParam("id") String id) {
+ if (id == null) {
+ throw new IllegalArgumentException("id has to be given");
+ }
+ id = Util.URLdecode(id);
+ return this.getEntityResourceFromDecodedId(id);
+ }
+
+ /**
+ * @param entity the entity to create a resource for
+ * @param idx the index in the list
+ * @return the resource managing the given entity
+ */
+ protected abstract EntityResourceT getEntityResourceInstance(EntityT entity, int idx);
+
+ @GET
+ @Produces(MediaType.TEXT_HTML)
+ @RestDoc(methodDescription = "@return the HTML fragment (DIV-container) to be embedded in the 'Interface' part of nodetype.js ")
+ public Response getHTMLAsResponse() {
+ Viewable viewable = this.getHTML();
+ return Response.ok().header(HttpHeaders.VARY, HttpHeaders.ACCEPT).entity(viewable).build();
+ }
+
+ /**
+ * called by getHTMLAsResponse
+ */
+ public abstract Viewable getHTML();
+
+ /**
+ * Adds a new entity
+ *
+ * In case the element already exists, we return "CONFLICT"
+ */
+ @POST
+ @Consumes({MediaType.TEXT_XML, MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
+ public Response addNewElement(EntityT entity) {
+ if (entity == null) {
+ return Response.status(Status.BAD_REQUEST).entity("a valid XML/JSON element has to be posted").build();
+ }
+ if (this.alreadyContains(entity)) {
+ // we do not replace the element, but replace it
+ return Response.status(Status.CONFLICT).build();
+ }
+ this.list.add(entity);
+ return CollectionsHelper.persist(this.res, this, entity);
+ }
+
+ @Override
+ public abstract String getId(EntityT entity);
+
+ /**
+ * Checks for containment of e in the list. <code>equals</code> is not used
+ * as most EntityT do not offer a valid implementation
+ *
+ * @return true if list already contains e.
+ */
+ public boolean alreadyContains(EntityT e) {
+ String id = this.getId(e);
+ for (EntityT el : this.list) {
+ if (this.getId(el).equals(id)) {
+ // break loop
+ // we found an equal list item
+ return true;
+ }
+ }
+ // all items checked: nothing equal contained
+ return false;
+ }
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/collections/EntityResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/collections/EntityResource.java
new file mode 100644
index 0000000..361fcfb
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/collections/EntityResource.java
@@ -0,0 +1,123 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2013,2015 University of Stuttgart.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ * Oliver Kopp - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.winery.repository.resources._support.collections;
+
+import java.util.List;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+
+import org.eclipse.winery.repository.Utils;
+import org.eclipse.winery.repository.backend.BackendUtils;
+import org.eclipse.winery.repository.resources._support.IPersistable;
+
+/**
+ * Class to hold a single entity residing in a list of entities
+ *
+ * @param <EntityT> the entity type contained in the list
+ */
+public abstract class EntityResource<EntityT> {
+
+ // This is non-final as a "PUT" may update the object
+ // it might be unnecessary to update this object as the resource is created at each request
+ // We update the reference nevertheless to be safe if the resource is used in another context
+ protected EntityT o;
+
+ protected final int idx;
+
+ protected final List<EntityT> list;
+
+ protected final IPersistable res;
+
+ protected IIdDetermination<EntityT> idDetermination;
+
+
+ /**
+ *
+ * @param idDetermination the object offering determination of an id of
+ * EntityT. May be null. If null, then setIdDetermination(obj)
+ * has to be called to enable this class functioning properly
+ * @param o the object this resource is representing
+ * @param idx the index of the object in the list
+ * @param list the list, where the object is stored in
+ * @param res the resource the object/list belongs to
+ */
+ public EntityResource(IIdDetermination<EntityT> idDetermination, EntityT o, int idx, List<EntityT> list, IPersistable res) {
+ this.idDetermination = idDetermination;
+ this.o = o;
+ this.idx = idx;
+ this.list = list;
+ this.res = res;
+ }
+
+ /**
+ * Quick hack for AbstractReqOrCapDefResource which is itself an
+ * IIdDetermination
+ */
+ protected final void setIdDetermination(IIdDetermination<EntityT> idDetermination) {
+ this.idDetermination = idDetermination;
+ }
+
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response getJSON() {
+ assert (this.o != null);
+ return Response.ok().entity(this.o).build();
+ }
+
+ @GET
+ @Produces(MediaType.TEXT_XML)
+ @SuppressWarnings("unchecked")
+ public Response getXML() {
+ assert (this.o != null);
+ // Utils.getXML has to be used as Jersey can only serialize XMLRootElements
+ return Utils.getXML((Class<EntityT>) this.o.getClass(), this.o);
+ }
+
+ /**
+ * Replaces the whole entity by the given entity
+ *
+ * As we use the hash code as index, the index changes when the resource is
+ * updated. This is not in line with REST. The alternative implementation is
+ * to use the index in the list as resource identification. That changes at
+ * each modification of the list itself (if elements are deleted / inserted
+ * before the current entry). When using the hash value, users may
+ * concurrently edit items and the list may also be updated
+ *
+ * @return the new id.
+ */
+ @PUT
+ @Consumes(MediaType.TEXT_XML)
+ @Produces(MediaType.TEXT_PLAIN)
+ public Response setValue(EntityT o) {
+ this.list.set(this.idx, o);
+ this.o = o;
+ return CollectionsHelper.persist(this.res, this.idDetermination, o);
+ }
+
+ @DELETE
+ public Response onDelete() {
+ try {
+ this.list.remove(this.idx);
+ } catch (IndexOutOfBoundsException e) {
+ return Response.status(Status.INTERNAL_SERVER_ERROR).entity("Could not delete entity, even if it should exist").build();
+ }
+ return BackendUtils.persist(this.res);
+ }
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/collections/IIdDetermination.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/collections/IIdDetermination.java
new file mode 100644
index 0000000..e479e70
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/collections/IIdDetermination.java
@@ -0,0 +1,20 @@
+/*******************************************************************************
+ * 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.repository.resources._support.collections;
+
+public interface IIdDetermination<EntityT> {
+
+ /**
+ * @return the id of the given entity
+ */
+ public String getId(EntityT e);
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/collections/withid/EntityWithIdCollectionResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/collections/withid/EntityWithIdCollectionResource.java
new file mode 100644
index 0000000..f428752
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/collections/withid/EntityWithIdCollectionResource.java
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * 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.repository.resources._support.collections.withid;
+
+import java.lang.reflect.Constructor;
+import java.util.List;
+
+import org.eclipse.winery.repository.resources._support.IPersistable;
+import org.eclipse.winery.repository.resources._support.collections.EntityCollectionResource;
+import org.eclipse.winery.repository.resources._support.collections.IIdDetermination;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public abstract class EntityWithIdCollectionResource<EntityResourceT extends EntityWithIdResource<EntityT>, EntityT> extends EntityCollectionResource<EntityResourceT, EntityT> {
+
+ private static final Logger logger = LoggerFactory.getLogger(EntityWithIdCollectionResource.class);
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public EntityWithIdCollectionResource(Class<EntityResourceT> entityResourceTClazz, Class<EntityT> entityTClazz, List<EntityT> list, IPersistable res) {
+ super(entityResourceTClazz, entityTClazz, list, res);
+ }
+
+ /**
+ * Each CollectionResource has to implement the id getting by itself as
+ * TOSCA XSD does not provide a general purpose id fetching mechanism
+ */
+ @Override
+ public abstract String getId(EntityT entity);
+
+ @Override
+ protected EntityResourceT getEntityResourceInstance(EntityT entity, int idx) {
+ Constructor<EntityResourceT> constructor;
+ try {
+ constructor = this.entityResourceTClazz.getConstructor(IIdDetermination.class, this.entityTClazz, int.class, List.class, this.res.getClass());
+ } catch (Exception e) {
+ try {
+ constructor = this.entityResourceTClazz.getConstructor(IIdDetermination.class, this.entityTClazz, int.class, List.class, IPersistable.class);
+ } catch (Exception e2) {
+ EntityWithIdCollectionResource.logger.debug("Could not get constructor", e);
+ EntityWithIdCollectionResource.logger.debug("res.getClass() was {}", this.res.getClass());
+ throw new IllegalStateException(e2);
+ }
+ }
+ EntityResourceT newInstance;
+ try {
+ newInstance = constructor.newInstance(this, entity, idx, this.list, this.res);
+ } catch (Exception e) {
+ EntityWithIdCollectionResource.logger.debug("Could not instantiate class", e);
+ throw new IllegalStateException(e);
+ }
+ return newInstance;
+ }
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/collections/withid/EntityWithIdResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/collections/withid/EntityWithIdResource.java
new file mode 100644
index 0000000..1ac6775
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/collections/withid/EntityWithIdResource.java
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * 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.repository.resources._support.collections.withid;
+
+import java.util.List;
+
+import org.eclipse.winery.repository.resources._support.IPersistable;
+import org.eclipse.winery.repository.resources._support.collections.EntityResource;
+import org.eclipse.winery.repository.resources._support.collections.IIdDetermination;
+
+public class EntityWithIdResource<EntityT> extends EntityResource<EntityT> {
+
+ /**
+ * {@inheritDoc}
+ */
+ public EntityWithIdResource(IIdDetermination<EntityT> idDetermination, EntityT o, int idx, List<EntityT> list, IPersistable res) {
+ super(idDetermination, o, idx, list, res);
+ }
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/collections/withoutid/EntityWithoutIdCollectionResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/collections/withoutid/EntityWithoutIdCollectionResource.java
new file mode 100644
index 0000000..8255f5d
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/collections/withoutid/EntityWithoutIdCollectionResource.java
@@ -0,0 +1,114 @@
+/*******************************************************************************
+ * 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.repository.resources._support.collections.withoutid;
+
+import java.lang.reflect.Constructor;
+import java.util.List;
+
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+
+import org.eclipse.winery.common.Util;
+import org.eclipse.winery.repository.Utils;
+import org.eclipse.winery.repository.resources.AbstractComponentInstanceResource;
+import org.eclipse.winery.repository.resources._support.IPersistable;
+import org.eclipse.winery.repository.resources._support.collections.EntityCollectionResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.sun.jersey.api.NotFoundException;
+
+/**
+ * Class managing a list of entities. It is intended to manage subresources,
+ * where the TOSCA specification did not specify a unique key. Currently, the
+ * hashCode of the XML String representation is used. If other representation
+ * should be used, the method {@code getEntityResource} has to be overriden.
+ *
+ * @param <EntityResourceT> the resource modeling the entity
+ * @param <EntityT> the entity type of single items in the list
+ */
+public abstract class EntityWithoutIdCollectionResource<EntityResourceT extends EntityWithoutIdResource<EntityT>, EntityT> extends EntityCollectionResource<EntityResourceT, EntityT> {
+
+ private static final Logger logger = LoggerFactory.getLogger(EntityWithoutIdCollectionResource.class);
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public EntityWithoutIdCollectionResource(Class<EntityResourceT> entityResourceTClazz, Class<EntityT> entityTClazz, List<EntityT> list, IPersistable res) {
+ super(entityResourceTClazz, entityTClazz, list, res);
+ }
+
+ /**
+ * Method searching the list for an id with the hashcode instead of
+ * getId(EntityT)
+ */
+ @Override
+ @Path("{id}/")
+ public EntityResourceT getEntityResource(@PathParam("id") String id) {
+ id = Util.URLdecode(id);
+ int idInt;
+ try {
+ idInt = Integer.parseInt(id);
+ } catch (java.lang.NumberFormatException e) {
+ throw new NotFoundException(id + " is not a valid id");
+ }
+ EntityT entity = null;
+ int idx = -1;
+ for (EntityT c : this.list) {
+ idx++;
+ // speed optimization - instead of using getId() we directly use the hash code
+ int hash = Utils.getXMLAsString(c).hashCode();
+ if (hash == idInt) {
+ entity = c;
+ break;
+ }
+ }
+ if (entity == null) {
+ throw new NotFoundException();
+ } else {
+ return this.getEntityResourceInstance(entity, idx);
+ }
+ }
+
+ @Override
+ public String getId(EntityT entity) {
+ return IdDeterminationWithHashCode.INSTANCE.getId(entity);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected EntityResourceT getEntityResourceInstance(EntityT entity, int idx) {
+ Constructor<EntityResourceT> constructor;
+ try {
+ constructor = this.entityResourceTClazz.getConstructor(this.entityTClazz, int.class, List.class, AbstractComponentInstanceResource.class);
+ } catch (Exception e) {
+ try {
+ constructor = this.entityResourceTClazz.getConstructor(this.entityTClazz, int.class, List.class, IPersistable.class);
+ } catch (NoSuchMethodException | SecurityException e1) {
+ EntityWithoutIdCollectionResource.logger.debug("Could not get constructor", e);
+ throw new IllegalStateException(e);
+ }
+ }
+ EntityResourceT newInstance;
+ try {
+ newInstance = constructor.newInstance(entity, idx, this.list, this.res);
+ } catch (Exception e) {
+ EntityWithoutIdCollectionResource.logger.debug("Could not instantiate class", e);
+ throw new IllegalStateException(e);
+ }
+ return newInstance;
+ }
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/collections/withoutid/EntityWithoutIdResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/collections/withoutid/EntityWithoutIdResource.java
new file mode 100644
index 0000000..0cf2766
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/collections/withoutid/EntityWithoutIdResource.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2013 University of Stuttgart.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ * Oliver Kopp - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.winery.repository.resources._support.collections.withoutid;
+
+import java.util.List;
+
+import org.eclipse.winery.repository.resources._support.IPersistable;
+import org.eclipse.winery.repository.resources._support.collections.EntityResource;
+import org.eclipse.winery.repository.resources._support.collections.IIdDetermination;
+
+/**
+ * {@inheritDoc}
+ */
+public abstract class EntityWithoutIdResource<EntityT> extends EntityResource<EntityT> {
+
+ /**
+ * {@inheritDoc}
+ */
+ @SuppressWarnings("unchecked")
+ public EntityWithoutIdResource(EntityT o, int idx, List<EntityT> list, IPersistable res) {
+ super((IIdDetermination<EntityT>) IdDeterminationWithHashCode.INSTANCE, o, idx, list, res);
+ }
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/collections/withoutid/IdDeterminationWithHashCode.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/collections/withoutid/IdDeterminationWithHashCode.java
new file mode 100644
index 0000000..6b4e247
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/collections/withoutid/IdDeterminationWithHashCode.java
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2013 University of Stuttgart.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ * Oliver Kopp - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.winery.repository.resources._support.collections.withoutid;
+
+import org.eclipse.winery.repository.Utils;
+import org.eclipse.winery.repository.resources._support.collections.IIdDetermination;
+
+public class IdDeterminationWithHashCode implements IIdDetermination<Object> {
+
+ public static final IdDeterminationWithHashCode INSTANCE = new IdDeterminationWithHashCode();
+
+
+ @Override
+ public String getId(Object entity) {
+ // We assume that different Object serializations *always* have different hashCodes
+ int hash = Utils.getXMLAsString(entity).hashCode();
+ return Integer.toString(hash);
+ }
+
+ /**
+ * Static wrapper method for functions.tld
+ */
+ public static String getIdStatically(Object entity) {
+ return IdDeterminationWithHashCode.INSTANCE.getId(entity);
+ }
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/collections/withoutid/package-info.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/collections/withoutid/package-info.java
new file mode 100644
index 0000000..c62b344
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/collections/withoutid/package-info.java
@@ -0,0 +1,17 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+/**
+ * This package contains abstract resources implementing common functionality to
+ * support collections of entities, where the data model does not provide a
+ * unique id
+ */
+package org.eclipse.winery.repository.resources._support.collections.withoutid; \ No newline at end of file
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/admin/AbstractAdminResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/admin/AbstractAdminResource.java
new file mode 100644
index 0000000..cd4e20e
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/admin/AbstractAdminResource.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * 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.repository.resources.admin;
+
+import javax.ws.rs.DELETE;
+import javax.ws.rs.core.Response;
+
+import org.apache.commons.configuration.Configuration;
+import org.eclipse.winery.repository.backend.BackendUtils;
+import org.eclipse.winery.repository.backend.Repository;
+import org.eclipse.winery.repository.datatypes.ids.admin.AdminId;
+
+/**
+ * Instance of one admin resource
+ *
+ * Offers a configuration object to store data
+ */
+public abstract class AbstractAdminResource {
+
+ protected final AdminId id;
+ protected Configuration configuration;
+
+
+ /**
+ * @param id the id of the element rendered by this resource
+ */
+ public AbstractAdminResource(AdminId id) {
+ this.id = id;
+ this.configuration = Repository.INSTANCE.getConfiguration(id);
+ }
+
+ @DELETE
+ public Response onDelete() {
+ return BackendUtils.delete(this.id);
+ }
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/admin/AdminTopResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/admin/AdminTopResource.java
new file mode 100644
index 0000000..7e4a662
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/admin/AdminTopResource.java
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * 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.repository.resources.admin;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+import org.eclipse.winery.repository.resources.admin.types.ConstraintTypesManager;
+import org.eclipse.winery.repository.resources.admin.types.PlanLanguagesManager;
+import org.eclipse.winery.repository.resources.admin.types.PlanTypesManager;
+
+import com.sun.jersey.api.view.Viewable;
+
+public class AdminTopResource {
+
+ @GET
+ @Produces(MediaType.TEXT_HTML)
+ public Viewable getHTML() {
+ return new Viewable("/jsp/admin/adminindex.jsp", this);
+ }
+
+ @Path("namespaces/")
+ public NamespacesResource getNamespacesResource() {
+ return NamespacesResource.INSTANCE;
+ }
+
+ @Path("repository/")
+ public RepositoryAdminResource getRepositoryAdminResource() {
+ return new RepositoryAdminResource();
+ }
+
+ @Path("planlanguages/")
+ public PlanLanguagesManager getPlanLanguagesResource() {
+ return PlanLanguagesManager.INSTANCE;
+ }
+
+ @Path("plantypes/")
+ public PlanTypesManager getPlanTypesResource() {
+ return PlanTypesManager.INSTANCE;
+ }
+
+ @Path("constrainttypes/")
+ public ConstraintTypesManager getConstraintTypesManager() {
+ return ConstraintTypesManager.INSTANCE;
+ }
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/admin/NamespacesResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/admin/NamespacesResource.java
new file mode 100644
index 0000000..f8fb9f1
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/admin/NamespacesResource.java
@@ -0,0 +1,253 @@
+/*******************************************************************************
+ * 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.repository.resources.admin;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.TreeSet;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+
+import org.apache.commons.lang3.StringUtils;
+import org.eclipse.winery.common.Util;
+import org.eclipse.winery.common.ids.Namespace;
+import org.eclipse.winery.repository.Utils;
+import org.eclipse.winery.repository.backend.Repository;
+import org.eclipse.winery.repository.datatypes.ids.admin.NamespacesId;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.sun.jersey.api.view.Viewable;
+
+/**
+ * Manages prefixes for the namespaces
+ */
+public class NamespacesResource extends AbstractAdminResource {
+
+ private static final Logger logger = LoggerFactory.getLogger(NamespacesResource.class);
+
+ public final static NamespacesResource INSTANCE = new NamespacesResource();
+
+ private Integer nsCount = 0;
+
+
+ private NamespacesResource() {
+ super(new NamespacesId());
+
+ // globally set prefixes
+ // if that behavior is not desired, the code has to be moved to "generatePrefix" which checks for existence, ...
+ this.configuration.setProperty("http://www.w3.org/2001/XMLSchema", "xsd");
+ this.configuration.setProperty("http://www.w3.org/XML/1998/namespace", "xmlns");
+ this.configuration.setProperty(org.eclipse.winery.common.constants.Namespaces.TOSCA_NAMESPACE, "tosca");
+ this.configuration.setProperty(org.eclipse.winery.common.constants.Namespaces.TOSCA_WINERY_EXTENSIONS_NAMESPACE, "winery");
+ }
+
+ private Collection<String> getAllPrefixes() {
+ Iterator<String> keys = this.configuration.getKeys();
+ HashSet<String> res = new HashSet<String>();
+ while (keys.hasNext()) {
+ String key = keys.next();
+ String prefix = this.configuration.getString(key);
+ res.add(prefix);
+ }
+ return res;
+ }
+
+ @GET
+ @Produces(MediaType.TEXT_HTML)
+ public Response getHTML() {
+ Viewable viewable = new Viewable("/jsp/admin/namespaces.jsp", this);
+ return Response.ok().entity(viewable).build();
+ }
+
+ /**
+ * Sets / overwrites prefix/namespace mapping
+ *
+ * In case the prefix is already bound to another namespace, BAD_REQUEST is
+ * returned.
+ */
+ @POST
+ @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
+ public Response addNamespace(@FormParam("namespace") String namespace, @FormParam("nsPrefix") String prefix) {
+ if (StringUtils.isEmpty(namespace)) {
+ return Response.status(Status.BAD_REQUEST).entity("namespace must be given.").build();
+ }
+ if (StringUtils.isEmpty(prefix)) {
+ return Response.status(Status.BAD_REQUEST).entity("prefix must be given.").build();
+ }
+ namespace = Util.URLdecode(namespace);
+ prefix = Util.URLdecode(prefix);
+ Collection<String> allPrefixes = this.getAllPrefixes();
+ if (allPrefixes.contains(prefix)) {
+ if (NamespacesResource.getPrefix(namespace).equals(prefix)) {
+ return Response.notModified().build();
+ } else {
+ // the requested prefix is already bound to a different namespace
+ return Response.status(Status.BAD_REQUEST).entity("prefix already bound to a different namespace.").build();
+ }
+ }
+ this.configuration.setProperty(namespace, prefix);
+ return Response.noContent().build();
+ }
+
+ /**
+ * Deletes given namespace from the repository
+ *
+ * @param URI to delete. The namespace is URLencoded.
+ * @return
+ */
+ @DELETE
+ @Path("{namespace}")
+ public Response onDelete(@PathParam("namespace") String URI) {
+ Response res;
+ URI = Util.URLdecode(URI);
+ if (this.configuration.containsKey(URI)) {
+ this.configuration.clearProperty(URI);
+ res = Response.noContent().build();
+ } else {
+ res = Response.status(Status.NOT_FOUND).build();
+ }
+ return res;
+ }
+
+ /**
+ * SIDEFFECT: URI is added to list of known namespaces if it did not exist
+ * before
+ */
+ public static String getPrefix(Namespace namespace) {
+ String ns = namespace.getDecoded();
+ return NamespacesResource.getPrefix(ns);
+ }
+
+ @Path("{namespace}")
+ @GET
+ @Produces(MediaType.TEXT_PLAIN)
+ public String getPrefixForEncodedNamespace(@PathParam("namespace") String URI) {
+ URI = Util.URLdecode(URI);
+ return NamespacesResource.getPrefix(URI);
+ }
+
+ /**
+ * SIDEFFECT: URI is added to list of known namespaces if it did not exist
+ * before
+ */
+ public static String getPrefix(String namespace) {
+ if (namespace == null) {
+ throw new IllegalArgumentException("Namespace must not be null");
+ }
+ String prefix = NamespacesResource.INSTANCE.configuration.getString(namespace);
+ if (prefix == null) {
+ prefix = NamespacesResource.generatePrefix(namespace);
+ NamespacesResource.INSTANCE.configuration.setProperty(namespace, prefix);
+ }
+ return prefix;
+ }
+
+ private static String generatePrefix(String namespace) {
+ String prefix = null;
+ Collection<String> allPrefixes = NamespacesResource.INSTANCE.getAllPrefixes();
+
+ // TODO: generate prefix using URI (and not "arbitrary" prefix)
+ do {
+ prefix = String.format("ns%d", NamespacesResource.INSTANCE.nsCount);
+ NamespacesResource.INSTANCE.nsCount++;
+ } while (allPrefixes.contains(prefix));
+ return prefix;
+ }
+
+ /**
+ * Returns the list of all namespaces registered with his manager. It could
+ * be incomplete, if entries have been added manually to the repository
+ *
+ * @return all namespaces registered with this manager.
+ */
+ private HashSet<Namespace> getRegisteredNamespaces() {
+ HashSet<Namespace> res = new HashSet<Namespace>();
+ Iterator<String> keys = this.configuration.getKeys();
+ while (keys.hasNext()) {
+ String key = keys.next();
+ Namespace ns = new Namespace(key, false);
+ res.add(ns);
+ }
+ return res;
+ }
+
+ /**
+ * Returns the list of all namespaces registered with his manager and used
+ * at component instances.
+ */
+ public static Collection<Namespace> getNamespaces() {
+ HashSet<Namespace> res = NamespacesResource.INSTANCE.getRegisteredNamespaces();
+ res.addAll(Repository.INSTANCE.getUsedNamespaces());
+ return res;
+ }
+
+ /**
+ * This method is required because static methods cannot be accessed by EL
+ *
+ * @return see getNamespaces()
+ */
+ public Collection<Namespace> getNamespacesForJSP() {
+ return NamespacesResource.getNamespaces();
+ }
+
+ /**
+ * Returns the list of all namespaces registered with his manager and used
+ * at component instances.
+ *
+ * @return a JSON list containing the non-encoded URIs of each known
+ * namespace
+ */
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ public String getNamespacesAsJSONlist() {
+ Collection<Namespace> namespaces = NamespacesResource.getNamespaces();
+
+ // We now have all namespaces
+ // We need to convert from Namespace to String
+
+ TreeSet<String> stringNamespaces = new TreeSet<String>();
+ for (Namespace ns : namespaces) {
+ stringNamespaces.add(ns.getDecoded());
+ }
+
+ String res;
+ try {
+ res = Utils.mapper.writeValueAsString(stringNamespaces);
+ } catch (JsonProcessingException e) {
+ NamespacesResource.logger.error(e.getMessage(), e);
+ res = "[]";
+ }
+ return res;
+ }
+
+ /**
+ * Checks whether a prefix is registered for a namespace
+ *
+ * Used at CSARImporter
+ */
+ public boolean getIsPrefixKnownForNamespace(String namespace) {
+ return this.configuration.containsKey(namespace);
+ }
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/admin/RepositoryAdminResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/admin/RepositoryAdminResource.java
new file mode 100644
index 0000000..408704d
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/admin/RepositoryAdminResource.java
@@ -0,0 +1,112 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2013 University of Stuttgart.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ * Oliver Kopp - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.winery.repository.resources.admin;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.StreamingOutput;
+
+import org.eclipse.winery.repository.Prefs;
+import org.eclipse.winery.repository.backend.IRepositoryAdministration;
+import org.eclipse.winery.repository.backend.Repository;
+import org.eclipse.winery.repository.backend.filebased.GitBasedRepository;
+import org.restdoc.annotations.RestDoc;
+import org.restdoc.annotations.RestDocParam;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.sun.jersey.api.view.Viewable;
+import com.sun.jersey.core.header.FormDataContentDisposition;
+import com.sun.jersey.multipart.FormDataParam;
+
+public class RepositoryAdminResource {
+
+ private static final Logger logger = LoggerFactory.getLogger(RepositoryAdminResource.class);
+
+
+ // @formatter:off
+ @GET
+ @Produces(MediaType.TEXT_HTML) // we cannot add MimeTypes.MIMETYPE_ZIP as dumpRepository also produces that mimetype
+ @RestDoc(methodDescription = "Returns the repository admin page and implements administration utility")
+ public Response onGet(
+ @QueryParam(value = "dump") @RestDocParam(description = "If given, a dump of the repository is sent") String dump,
+ @QueryParam(value = "reset") @RestDocParam(description = "Resets the repository to the last &ldquo;official&rdquo; known state") String reset,
+ @QueryParam(value = "commit") @RestDocParam(description = "Commits the current state to the repository and pushes it upstream") String commit
+ ) {
+ // @formatter:on
+ if (dump != null) {
+ return this.dumpRepository();
+ } else if (reset != null) {
+ try {
+ ((GitBasedRepository) Prefs.INSTANCE.getRepository()).cleanAndResetHard();
+ } catch (Exception e) {
+ Response res;
+ res = Response.serverError().entity(e.getMessage()).build();
+ return res;
+ }
+ return Response.noContent().build();
+ } else if (commit != null) {
+ try {
+ ((GitBasedRepository) Prefs.INSTANCE.getRepository()).addCommitPush();
+ } catch (Exception e) {
+ Response res;
+ res = Response.serverError().entity(e.getMessage()).build();
+ return res;
+ }
+ return Response.noContent().build();
+ } else {
+ Viewable viewable = new Viewable("/jsp/admin/repository.jsp", this);
+ return Response.ok().entity(viewable).build();
+ }
+ }
+
+ /**
+ * Imports the given ZIP
+ */
+ @POST
+ @Consumes(MediaType.MULTIPART_FORM_DATA)
+ public Response importRepositoryDump(@FormDataParam("file") InputStream uploadedInputStream, @FormDataParam("file") FormDataContentDisposition fileDetail) {
+ ((IRepositoryAdministration) Repository.INSTANCE).doImport(uploadedInputStream);
+ return Response.noContent().build();
+ }
+
+ @DELETE
+ public void deleteRepositoryData() {
+ ((IRepositoryAdministration) Repository.INSTANCE).doClear();
+ }
+
+ @GET
+ @Produces(org.eclipse.winery.common.constants.MimeTypes.MIMETYPE_ZIP)
+ public Response dumpRepository() {
+ StreamingOutput so = new StreamingOutput() {
+
+ @Override
+ public void write(OutputStream output) throws IOException, WebApplicationException {
+ ((IRepositoryAdministration) Repository.INSTANCE).doDump(output);
+ }
+ };
+ StringBuilder sb = new StringBuilder();
+ sb.append("attachment;filename=\"repository.zip\"");
+ return Response.ok().header("Content-Disposition", sb.toString()).type(org.eclipse.winery.common.constants.MimeTypes.MIMETYPE_ZIP).entity(so).build();
+ }
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/admin/types/AbstractTypesManager.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/admin/types/AbstractTypesManager.java
new file mode 100644
index 0000000..bf3c024
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/admin/types/AbstractTypesManager.java
@@ -0,0 +1,204 @@
+/*******************************************************************************
+ * 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.repository.resources.admin.types;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+import javax.ws.rs.DELETE;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+import javax.ws.rs.core.UriInfo;
+
+import org.apache.commons.lang3.StringUtils;
+import org.eclipse.winery.common.Util;
+import org.eclipse.winery.repository.datatypes.TypeWithShortName;
+import org.eclipse.winery.repository.datatypes.ids.admin.TypesId;
+import org.eclipse.winery.repository.datatypes.select2.Select2DataItem;
+import org.eclipse.winery.repository.resources.admin.AbstractAdminResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.sun.jersey.api.view.Viewable;
+
+/**
+ * Handles longname/shortname by using properties
+ *
+ * FIXME: This class does NOT support dynamic reloading of the underlying
+ * Configuration instance
+ *
+ */
+public abstract class AbstractTypesManager extends AbstractAdminResource {
+
+ @Context
+ private UriInfo uriInfo;
+
+ protected static final Logger logger = LoggerFactory.getLogger(AbstractTypesManager.class);
+
+ // hashes from a long type string to the type object holding complete type data
+ private final HashMap<String, TypeWithShortName> hashTypeStringToType;
+
+
+ public AbstractTypesManager(TypesId id) {
+ super(id);
+ // now, this.configuration is filled with stored data
+
+ // copy over information from configuration to internal data structure
+ this.hashTypeStringToType = new HashMap<String, TypeWithShortName>();
+ Iterator<String> keys = this.configuration.getKeys();
+ while (keys.hasNext()) {
+ String key = keys.next();
+ String value = this.configuration.getString(key);
+ TypeWithShortName typeInfo = new TypeWithShortName(key, value);
+ this.hashTypeStringToType.put(key, typeInfo);
+ }
+ }
+
+ protected void addData(String longName, String shortName) {
+ TypeWithShortName t = new TypeWithShortName(longName, shortName);
+ this.addData(t);
+ }
+
+ /**
+ * Adds data to the internal data structure WITHOUT persisting it
+ *
+ * More or less a quick hack to enable adding default types without
+ * persisting them in the storage
+ *
+ * @param t the type to add
+ */
+ private void addData(TypeWithShortName t) {
+ this.hashTypeStringToType.put(t.getType(), t);
+ }
+
+ public synchronized void addTypeWithShortName(TypeWithShortName type) {
+ this.addData(type);
+ this.configuration.setProperty(type.getType(), type.getShortName());
+ }
+
+ /**
+ * Removes a type. Will not remove a type added by "addData"
+ */
+ @DELETE
+ @Path("{type}")
+ public Response removeTypeWithResponse(@PathParam("type") String type) {
+ type = Util.URLdecode(type);
+ if (this.configuration.containsKey(type)) {
+ this.hashTypeStringToType.remove(type);
+ this.configuration.clearProperty(type);
+ return Response.noContent().build();
+ } else if (this.hashTypeStringToType.containsKey(type)) {
+ // predefined types may not be deleted
+ // this branch is hit at types added via addData (e.g., predefined plantypes)
+ return Response.status(Status.FORBIDDEN).build();
+ } else {
+ return Response.status(Status.NOT_FOUND).build();
+ }
+ }
+
+ /**
+ * Returns a sorted list of all available types
+ */
+ public Collection<TypeWithShortName> getTypes() {
+ Collection<TypeWithShortName> res = new TreeSet<TypeWithShortName>(this.hashTypeStringToType.values());
+ return res;
+ }
+
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ public Object getTypesAsJSONArrayList(@QueryParam("select2") String select2) {
+ if (select2 == null) {
+ return this.getTypes();
+ } else {
+ // select2 mode
+ SortedSet<Select2DataItem> res = new TreeSet<>();
+ for (TypeWithShortName t : this.getTypes()) {
+ Select2DataItem item = new Select2DataItem(t.getType(), t.getShortName());
+ res.add(item);
+ }
+ return res;
+ }
+ }
+
+ /**
+ * <b>SIDEEFFECT:</b> If there currently isn't any short type name, it is
+ * created
+ */
+ public TypeWithShortName getTypeWithShortName(String typeString) {
+ TypeWithShortName t = this.hashTypeStringToType.get(typeString);
+ if (t == null) {
+ String shortName = this.getShortName(typeString);
+ t = new TypeWithShortName(typeString, shortName);
+ this.addTypeWithShortName(t);
+ }
+ return t;
+ }
+
+ /**
+ * <b>SIDEEFFECT:</b> If there currently isn't any short type name, it is
+ * created
+ */
+ public String getShortName(String typeString) {
+ TypeWithShortName type = this.hashTypeStringToType.get(typeString);
+ String res;
+ if (type == null) {
+ // happens if artifact type is not registered in artifacttypes.list
+ // (DATAFILENAME)
+ res = typeString;
+ } else {
+ res = type.getShortName();
+ }
+ return res;
+ }
+
+ @GET
+ @Produces(MediaType.TEXT_HTML)
+ public Viewable getHTML(@Context UriInfo uriInfo) {
+ this.uriInfo = uriInfo;
+ return new Viewable("/jsp/admin/types/types.jsp", this);
+ }
+
+ @POST
+ public Response updateTypeMapping(@FormParam("shortname") String shortName, @FormParam("type") String type) {
+ if (StringUtils.isEmpty(shortName)) {
+ return Response.status(Status.BAD_REQUEST).entity("shortName has to be given").build();
+ }
+ if (StringUtils.isEmpty(type)) {
+ return Response.status(Status.BAD_REQUEST).entity("type has to be given").build();
+ }
+ shortName = Util.URLdecode(shortName);
+ type = Util.URLdecode(type);
+ TypeWithShortName tws = new TypeWithShortName(type, shortName);
+ this.addTypeWithShortName(tws);
+ return Response.noContent().build();
+ }
+
+ /**
+ * Required by types.jsp
+ */
+ public String getURL() {
+ return this.uriInfo.getAbsolutePath().toString();
+ }
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/admin/types/ConstraintTypesManager.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/admin/types/ConstraintTypesManager.java
new file mode 100644
index 0000000..d8a9c0e
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/admin/types/ConstraintTypesManager.java
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * 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.repository.resources.admin.types;
+
+import org.eclipse.winery.repository.datatypes.ids.admin.ConstraintTypesId;
+
+public class ConstraintTypesManager extends AbstractTypesManager {
+
+ public final static ConstraintTypesManager INSTANCE = new ConstraintTypesManager();
+
+
+ private ConstraintTypesManager() {
+ super(new ConstraintTypesId());
+ }
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/admin/types/PlanLanguagesManager.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/admin/types/PlanLanguagesManager.java
new file mode 100644
index 0000000..e5b35b9
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/admin/types/PlanLanguagesManager.java
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * 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.repository.resources.admin.types;
+
+import org.eclipse.winery.repository.datatypes.ids.admin.PlanLanguagesId;
+
+public class PlanLanguagesManager extends AbstractTypesManager {
+
+ public final static PlanLanguagesManager INSTANCE = new PlanLanguagesManager();
+
+
+ private PlanLanguagesManager() {
+ super(new PlanLanguagesId());
+ // add data without rendering in the plan languages file
+ this.addData(org.eclipse.winery.common.constants.Namespaces.URI_BPEL20_EXECUTABLE, "BPEL 2.0 (executable)");
+ this.addData(org.eclipse.winery.common.constants.Namespaces.URI_BPMN20_MODEL, "BPMN 2.0");
+ this.addData(org.eclipse.winery.common.constants.Namespaces.URI_BPMN4TOSCA_20, "BPMN4TOSCA 2.0");
+ }
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/admin/types/PlanTypesManager.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/admin/types/PlanTypesManager.java
new file mode 100644
index 0000000..de6e7ba
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/admin/types/PlanTypesManager.java
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * 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.repository.resources.admin.types;
+
+import org.eclipse.winery.repository.datatypes.ids.admin.PlanTypesId;
+
+public class PlanTypesManager extends AbstractTypesManager {
+
+ public final static PlanTypesManager INSTANCE = new PlanTypesManager();
+
+
+ private PlanTypesManager() {
+ super(new PlanTypesId());
+ // add data without rendering in the plan types file
+ this.addData(org.eclipse.winery.repository.Constants.TOSCA_PLANTYPE_BUILD_PLAN, "Build Plan");
+ this.addData(org.eclipse.winery.repository.Constants.TOSCA_PLANTYPE_TERMINATION_PLAN, "Termination Plan");
+ }
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/artifacts/DeploymentArtifactResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/artifacts/DeploymentArtifactResource.java
new file mode 100644
index 0000000..ec7a86b
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/artifacts/DeploymentArtifactResource.java
@@ -0,0 +1,87 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2013,2015 University of Stuttgart.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ * Oliver Kopp - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.winery.repository.resources.artifacts;
+
+import java.util.List;
+
+import org.eclipse.winery.common.ids.definitions.ArtifactTemplateId;
+import org.eclipse.winery.common.ids.definitions.ArtifactTypeId;
+import org.eclipse.winery.model.tosca.TDeploymentArtifact;
+import org.eclipse.winery.repository.backend.BackendUtils;
+import org.eclipse.winery.repository.resources._support.IPersistable;
+import org.eclipse.winery.repository.resources._support.collections.IIdDetermination;
+
+public class DeploymentArtifactResource extends GenericArtifactResource<TDeploymentArtifact> {
+
+ private final TDeploymentArtifact a;
+
+
+ /**
+ * Converts the given artifactId to an DeploymentArtifact.
+ *
+ * <em>SIDE EFFECT</em> Adds it to the DeploymentArtifacts list if it does
+ * not yet exist.
+ */
+ private static TDeploymentArtifact getDeploymentArtifact(String artifactId, List<TDeploymentArtifact> deploymentArtifacts) {
+ for (TDeploymentArtifact ia : deploymentArtifacts) {
+ if (ia.getName().equals(artifactId)) {
+ return ia;
+ }
+ }
+ // DA does not exist in list
+ TDeploymentArtifact ia = new TDeploymentArtifact();
+ ia.setName(artifactId);
+ deploymentArtifacts.add(ia);
+ return ia;
+ }
+
+ public DeploymentArtifactResource(String artifactId, List<TDeploymentArtifact> deploymentArtifacts, IPersistable res) {
+ this(DeploymentArtifactResource.getDeploymentArtifact(artifactId, deploymentArtifacts), deploymentArtifacts, res);
+ }
+
+ public DeploymentArtifactResource(IIdDetermination<TDeploymentArtifact> idDetermination, TDeploymentArtifact o, int idx, List<TDeploymentArtifact> list, IPersistable res) {
+ super(idDetermination, o, idx, list, res);
+ this.a = o;
+ }
+
+ public DeploymentArtifactResource(TDeploymentArtifact deploymentArtifact, List<TDeploymentArtifact> deploymentArtifacts, IPersistable res) {
+ this(new IIdDetermination<TDeploymentArtifact>() {
+
+ @Override
+ public String getId(TDeploymentArtifact e) {
+ return e.getName();
+ }
+ }, deploymentArtifact, deploymentArtifacts.indexOf(deploymentArtifact), deploymentArtifacts, res);
+ }
+
+ public TDeploymentArtifact getDeploymentArtifact() {
+ return this.a;
+ }
+
+ @Override
+ public void setArtifactType(ArtifactTypeId artifactTypeId) {
+ this.getDeploymentArtifact().setArtifactType(artifactTypeId.getQName());
+ BackendUtils.persist(this.res);
+ }
+
+ @Override
+ public void setArtifactTemplate(ArtifactTemplateId artifactTemplateId) {
+ this.getDeploymentArtifact().setArtifactRef(artifactTemplateId.getQName());
+ BackendUtils.persist(this.res);
+ }
+
+ @Override
+ public TDeploymentArtifact getA() {
+ return this.a;
+ }
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/artifacts/DeploymentArtifactsResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/artifacts/DeploymentArtifactsResource.java
new file mode 100644
index 0000000..dcb5ca7
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/artifacts/DeploymentArtifactsResource.java
@@ -0,0 +1,73 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2013,2015 University of Stuttgart.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ * Oliver Kopp - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.winery.repository.resources.artifacts;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.eclipse.winery.model.tosca.TDeploymentArtifact;
+import org.eclipse.winery.model.tosca.TDeploymentArtifacts;
+import org.eclipse.winery.model.tosca.TNodeTemplate;
+import org.eclipse.winery.repository.resources.INodeTemplateResourceOrNodeTypeImplementationResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class DeploymentArtifactsResource extends GenericArtifactsResource<DeploymentArtifactResource, TDeploymentArtifact> {
+
+ private static final Logger logger = LoggerFactory.getLogger(DeploymentArtifactsResource.class);
+
+ private List<TDeploymentArtifact> deploymentArtifacts;
+
+
+ public DeploymentArtifactsResource(List<TDeploymentArtifact> deploymentArtifact, INodeTemplateResourceOrNodeTypeImplementationResource res) {
+ super(DeploymentArtifactResource.class, TDeploymentArtifact.class, deploymentArtifact, res);
+ this.deploymentArtifacts = deploymentArtifact;
+ }
+
+ /**
+ * Determines the list of DAs belonging to the given node template.
+ *
+ * If no DAs are existing, an empty list is created in the model for the
+ * node template
+ */
+ private static List<TDeploymentArtifact> getDeploymentArtifacts(TNodeTemplate nodeTemplate) {
+ TDeploymentArtifacts deploymentArtifacts = nodeTemplate.getDeploymentArtifacts();
+ final List<TDeploymentArtifact> res;
+ if (deploymentArtifacts == null) {
+ deploymentArtifacts = new TDeploymentArtifacts();
+ nodeTemplate.setDeploymentArtifacts(deploymentArtifacts);
+ }
+ res = deploymentArtifacts.getDeploymentArtifact();
+ return res;
+ }
+
+ public DeploymentArtifactsResource(TNodeTemplate nodeTemplate, INodeTemplateResourceOrNodeTypeImplementationResource res) {
+ this(DeploymentArtifactsResource.getDeploymentArtifacts(nodeTemplate), res);
+ }
+
+ @Override
+ public Collection<DeploymentArtifactResource> getAllArtifactResources() {
+ Collection<DeploymentArtifactResource> res = new ArrayList<DeploymentArtifactResource>(this.deploymentArtifacts.size());
+ for (TDeploymentArtifact da : this.deploymentArtifacts) {
+ DeploymentArtifactResource r = new DeploymentArtifactResource(da, this.deploymentArtifacts, this.res);
+ res.add(r);
+ }
+ return res;
+ }
+
+ @Override
+ public String getId(TDeploymentArtifact entity) {
+ return entity.getName();
+ }
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/artifacts/GenericArtifactResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/artifacts/GenericArtifactResource.java
new file mode 100644
index 0000000..9295082
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/artifacts/GenericArtifactResource.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2013,2015 University of Stuttgart.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ * Oliver Kopp - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.winery.repository.resources.artifacts;
+
+import java.util.List;
+
+import org.eclipse.winery.common.ids.definitions.ArtifactTemplateId;
+import org.eclipse.winery.common.ids.definitions.ArtifactTypeId;
+import org.eclipse.winery.repository.resources._support.IPersistable;
+import org.eclipse.winery.repository.resources._support.collections.IIdDetermination;
+import org.eclipse.winery.repository.resources._support.collections.withid.EntityWithIdResource;
+
+/**
+ * Currently no common things for deployment artifacts and implementation
+ * artifacts as the data model also has no common ancestor (besides
+ * TExensibleElement)
+ */
+public abstract class GenericArtifactResource<ArtifactT> extends EntityWithIdResource<ArtifactT> {
+
+ public GenericArtifactResource(IIdDetermination<ArtifactT> idDetermination, ArtifactT o, int idx, List<ArtifactT> list, IPersistable res) {
+ super(idDetermination, o, idx, list, res);
+ }
+
+ public abstract void setArtifactType(ArtifactTypeId artifactTypeId);
+
+ public abstract void setArtifactTemplate(ArtifactTemplateId artifactTemplateId);
+
+ /**
+ * required by artifacts.jsp
+ */
+ public abstract ArtifactT getA();
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/artifacts/GenericArtifactsResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/artifacts/GenericArtifactsResource.java
new file mode 100644
index 0000000..0cef56e
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/artifacts/GenericArtifactsResource.java
@@ -0,0 +1,572 @@
+/*******************************************************************************
+ * 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.repository.resources.artifacts;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.StringReader;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URL;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.SortedSet;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.POST;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+import javax.ws.rs.core.UriInfo;
+import javax.xml.namespace.QName;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.apache.commons.lang3.StringUtils;
+import org.eclipse.winery.common.RepositoryFileReference;
+import org.eclipse.winery.common.Util;
+import org.eclipse.winery.common.ids.Namespace;
+import org.eclipse.winery.common.ids.XMLId;
+import org.eclipse.winery.common.ids.definitions.ArtifactTemplateId;
+import org.eclipse.winery.common.ids.definitions.ArtifactTypeId;
+import org.eclipse.winery.common.ids.definitions.NodeTypeId;
+import org.eclipse.winery.common.ids.definitions.TOSCAComponentId;
+import org.eclipse.winery.generators.ia.Generator;
+import org.eclipse.winery.model.tosca.TDeploymentArtifact;
+import org.eclipse.winery.model.tosca.TEntityTemplate.Properties;
+import org.eclipse.winery.model.tosca.TImplementationArtifacts.ImplementationArtifact;
+import org.eclipse.winery.model.tosca.TInterface;
+import org.eclipse.winery.model.tosca.TNodeType;
+import org.eclipse.winery.repository.Utils;
+import org.eclipse.winery.repository.backend.BackendUtils;
+import org.eclipse.winery.repository.backend.Repository;
+import org.eclipse.winery.repository.backend.ResourceCreationResult;
+import org.eclipse.winery.repository.backend.filebased.FileUtils;
+import org.eclipse.winery.repository.datatypes.ids.elements.ArtifactTemplateDirectoryId;
+import org.eclipse.winery.repository.resources.AbstractComponentInstanceResource;
+import org.eclipse.winery.repository.resources.AbstractComponentsResource;
+import org.eclipse.winery.repository.resources.IHasTypeReference;
+import org.eclipse.winery.repository.resources.INodeTemplateResourceOrNodeTypeImplementationResourceOrRelationshipTypeImplementationResource;
+import org.eclipse.winery.repository.resources._support.collections.withid.EntityWithIdCollectionResource;
+import org.eclipse.winery.repository.resources.entitytemplates.PropertiesResource;
+import org.eclipse.winery.repository.resources.entitytemplates.artifacttemplates.ArtifactTemplateResource;
+import org.eclipse.winery.repository.resources.entitytypeimplementations.EntityTypeImplementationResource;
+import org.eclipse.winery.repository.resources.entitytypeimplementations.nodetypeimplementations.NodeTypeImplementationResource;
+import org.eclipse.winery.repository.resources.entitytypeimplementations.relationshiptypeimplementations.RelationshipTypeImplementationResource;
+import org.eclipse.winery.repository.resources.entitytypes.nodetypes.NodeTypeResource;
+import org.eclipse.winery.repository.resources.servicetemplates.topologytemplates.NodeTemplateResource;
+import org.restdoc.annotations.RestDoc;
+import org.restdoc.annotations.RestDocParam;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Text;
+import org.xml.sax.InputSource;
+
+import com.sun.jersey.api.view.Viewable;
+
+/**
+ * Resource handling both deployment and implementation artifacts
+ *
+ */
+public abstract class GenericArtifactsResource<ArtifactResource extends GenericArtifactResource<ArtifactT>, ArtifactT> extends EntityWithIdCollectionResource<ArtifactResource, ArtifactT> {
+
+ private static final Logger logger = LoggerFactory.getLogger(GenericArtifactsResource.class);
+
+ protected final INodeTemplateResourceOrNodeTypeImplementationResourceOrRelationshipTypeImplementationResource resWithNamespace;
+
+
+ public GenericArtifactsResource(Class<ArtifactResource> entityResourceTClazz, Class<ArtifactT> entityTClazz, List<ArtifactT> list, INodeTemplateResourceOrNodeTypeImplementationResourceOrRelationshipTypeImplementationResource res) {
+ super(entityResourceTClazz, entityTClazz, list, GenericArtifactsResource.getAbstractComponentInstanceResource(res));
+ this.resWithNamespace = res;
+ }
+
+ // @formatter:off
+
+ /**
+ * @return TImplementationArtifact | TDeploymentArtifact (XML) | URL of generated IA zip (in case of autoGenerateIA)
+ */
+ @POST
+ @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
+ @Produces(MediaType.TEXT_XML)
+ @RestDoc(methodDescription = "Creates a new implementation/deployment artifact. " +
+ "If an implementation artifact with the same name already exists, it is <em>overridden</em>.")
+ @SuppressWarnings("unchecked")
+ public Response onPost(
+ @FormParam("artifactName")
+ @RestDocParam(description = "This is the name of the implementation/deployment artifact. " +
+ "Is <em>also</em>used as prefix of the name of the corresponding artifact template if no specific template is provided. " +
+ "In contrast to CS01, we require a artifactName also for the implementationArtifact to be able to properly referencing it.")
+ String artifactNameStr,
+
+ @FormParam("artifactTemplate")
+ @RestDocParam(description = "QName of the artifact Template - used by Winery Backend instead of artifactTemplateName + artifactTemplateNS")
+ String artifactTemplate,
+
+ @FormParam("artifactTemplateName")
+ @RestDocParam(description = "if provided and autoCreateArtifactTemplate, a template of this id localname and artifactTemplateNS generated. " +
+ "Winery always sends this string if auto creation is desired.")
+ String artifactTemplateName,
+
+ @FormParam("artifactTemplateNS")
+ String artifactTemplateNS,
+
+ @FormParam("autoCreateArtifactTemplate")
+ @RestDocParam(description = "if empty, no, or false, no artifact template is created. " +
+ "An artifact type has to be given in that case. " +
+ "Furthermore, an artifact template name + artifact template namespace has to be provided. " +
+ "Otherwise, the artifactNameStr is used as name for the artifact and a <em>new</em> artifact template is created having {@code <artifactNameString>Template} as name")
+ String autoCreateArtifactTemplate,
+
+ @FormParam("artifactType")
+ @RestDocParam(description = "QName of the type, format: {namespace}localname. " +
+ "Optional if artifactTemplateName + artifactTempalteNS is provided")
+ String artifactTypeStr,
+
+ @FormParam("artifactSpecificContent")
+ @RestDocParam(description = "<em>XML</em> snippet that should be put inside the artifact XML in the TOSCA serialization. " +
+ "This feature will be removed soon. " +
+ "TODO: This only works if there is a single child element expected and not several elements. " +
+ "Future versions of the Winery will support arbitrary content there.")
+ String artifactSpecificContent,
+
+ @FormParam("interfaceName")
+ String interfaceNameStr,
+
+ @FormParam("operationName")
+ String operationNameStr,
+
+ @FormParam("autoGenerateIA")
+ @RestDocParam(description = "If not empty, the IA generator will be called")
+ String autoGenerateIA,
+
+ @FormParam("javapackage")
+ @RestDocParam(description = "The Java package to use for IA generation")
+ String javapackage,
+
+ @Context UriInfo uriInfo
+ ){
+ // we assume that the parent ComponentInstance container exists
+
+ // @formatter:on
+
+ if (StringUtils.isEmpty(artifactNameStr)) {
+ return Response.status(Status.BAD_REQUEST).entity("Empty artifactName").build();
+ }
+ if (StringUtils.isEmpty(artifactTypeStr)) {
+ if (StringUtils.isEmpty(artifactTemplateName) || StringUtils.isEmpty(artifactTemplateNS)) {
+ if (StringUtils.isEmpty(artifactTemplate)) {
+ return Response.status(Status.BAD_REQUEST).entity("No artifact type given and no template given. Cannot guess artifact type").build();
+ }
+ }
+ }
+
+ if (!StringUtils.isEmpty(autoGenerateIA)) {
+ if (StringUtils.isEmpty(javapackage)) {
+ return Response.status(Status.BAD_REQUEST).entity("no java package name supplied for IA auto generation.").build();
+ }
+ if (StringUtils.isEmpty(interfaceNameStr)) {
+ return Response.status(Status.BAD_REQUEST).entity("no interface name supplied for IA auto generation.").build();
+ }
+ }
+
+ // convert second calling form to first calling form
+ if (!StringUtils.isEmpty(artifactTemplate)) {
+ QName qname = QName.valueOf(artifactTemplate);
+ artifactTemplateName = qname.getLocalPart();
+ artifactTemplateNS = qname.getNamespaceURI();
+ }
+
+ Document doc = null;
+
+ // check artifact specific content for validity
+ // if invalid, abort and do not create anything
+ if (!StringUtils.isEmpty(artifactSpecificContent)) {
+ try {
+ DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+ InputSource is = new InputSource();
+ StringReader sr = new StringReader(artifactSpecificContent);
+ is.setCharacterStream(sr);
+ doc = db.parse(is);
+ } catch (Exception e) {
+ // FIXME: currently we allow a single element only. However, the content should be internally wrapped by an (arbitrary) XML element as the content will be nested in the artifact element, too
+ GenericArtifactsResource.logger.debug("Invalid content", e);
+ return Response.status(Status.BAD_REQUEST).entity(e.getMessage()).build();
+ }
+ }
+
+ // determine artifactTemplate and artifactType
+
+ ArtifactTypeId artifactTypeId;
+ ArtifactTemplateId artifactTemplateId = null;
+ ArtifactTemplateResource artifactTemplateResource = null;
+
+ boolean doAutoCreateArtifactTemplate = !(StringUtils.isEmpty(autoCreateArtifactTemplate) || autoCreateArtifactTemplate.equalsIgnoreCase("no") || autoCreateArtifactTemplate.equalsIgnoreCase("false"));
+ if (!doAutoCreateArtifactTemplate) {
+ // no auto creation
+ if (!StringUtils.isEmpty(artifactTemplateName) && !StringUtils.isEmpty(artifactTemplateNS)) {
+ QName artifactTemplateQName = new QName(artifactTemplateNS, artifactTemplateName);
+ artifactTemplateId = BackendUtils.getTOSCAcomponentId(ArtifactTemplateId.class, artifactTemplateQName);
+ }
+ if (StringUtils.isEmpty(artifactTypeStr)) {
+ // derive the type from the artifact template
+ if (artifactTemplateId == null) {
+ return Response.status(Status.NOT_ACCEPTABLE).entity("No artifactTemplate and no artifactType provided. Deriving the artifactType is not possible.").build();
+ }
+ artifactTemplateResource = new ArtifactTemplateResource(artifactTemplateId);
+ artifactTypeId = BackendUtils.getTOSCAcomponentId(ArtifactTypeId.class, artifactTemplateResource.getType());
+ } else {
+ // artifactTypeStr is directly given, use that
+ artifactTypeId = BackendUtils.getTOSCAcomponentId(ArtifactTypeId.class, artifactTypeStr);
+ }
+ } else {
+ // do the artifact template auto creation magic
+
+ if (StringUtils.isEmpty(artifactTypeStr)) {
+ return Response.status(Status.BAD_REQUEST).entity("Artifact template auto creation requested, but no artifact type supplied.").build();
+ }
+
+ // we assume that the type points to a valid artifact type
+ artifactTypeId = BackendUtils.getTOSCAcomponentId(ArtifactTypeId.class, artifactTypeStr);
+
+ if (StringUtils.isEmpty(artifactTemplateName) || StringUtils.isEmpty(artifactTemplateNS)) {
+ // no explicit name provided
+ // we use the artifactNameStr as prefix for the
+ // artifact template name
+
+ // we create a new artifact template in the namespace of the parent
+ // element
+ Namespace namespace = this.resWithNamespace.getNamespace();
+
+ artifactTemplateId = new ArtifactTemplateId(namespace, new XMLId(artifactNameStr + "artifactTemplate", false));
+ } else {
+ QName artifactTemplateQName = new QName(artifactTemplateNS, artifactTemplateName);
+ artifactTemplateId = new ArtifactTemplateId(artifactTemplateQName);
+ }
+ ResourceCreationResult creationResult = BackendUtils.create(artifactTemplateId);
+ if (!creationResult.isSuccess()) {
+ // something went wrong. skip
+ return creationResult.getResponse();
+ }
+
+ // associate the type to the created artifact template
+ artifactTemplateResource = new ArtifactTemplateResource(artifactTemplateId);
+ // set the type. The resource is automatically persisted inside
+ artifactTemplateResource.setType(artifactTypeStr);
+ }
+
+ // variable artifactTypeId is set
+ // variable artifactTemplateId is not null if artifactTemplate has been generated
+
+ // we have to generate the DA/IA resource now
+ // Doing it here instead of doing it at the subclasses is dirty on the
+ // one hand, but quicker to implement on the other hand
+
+ // Create the artifact itself
+
+ ArtifactT resultingArtifact;
+
+ if (this instanceof ImplementationArtifactsResource) {
+ ImplementationArtifact a = new ImplementationArtifact();
+ // Winery internal id is the name of the artifact:
+ // store the name
+ a.setName(artifactNameStr);
+ a.setInterfaceName(interfaceNameStr);
+ a.setOperationName(operationNameStr);
+ assert (artifactTypeId != null);
+ a.setArtifactType(artifactTypeId.getQName());
+ if (artifactTemplateId != null) {
+ a.setArtifactRef(artifactTemplateId.getQName());
+ }
+ if (doc != null) {
+ // the content has been checked for validity at the beginning of the method.
+ // If this point in the code is reached, the XML has been parsed into doc
+ // just copy over the dom node. Hopefully, that works...
+ a.getAny().add(doc.getDocumentElement());
+ }
+
+ this.list.add((ArtifactT) a);
+ resultingArtifact = (ArtifactT) a;
+ } else {
+ // for comments see other branch
+
+ TDeploymentArtifact a = new TDeploymentArtifact();
+ a.setName(artifactNameStr);
+ assert (artifactTypeId != null);
+ a.setArtifactType(artifactTypeId.getQName());
+ if (artifactTemplateId != null) {
+ a.setArtifactRef(artifactTemplateId.getQName());
+ }
+ if (doc != null) {
+ a.getAny().add(doc.getDocumentElement());
+ }
+
+ this.list.add((ArtifactT) a);
+ resultingArtifact = (ArtifactT) a;
+ }
+
+ Response persistResponse = BackendUtils.persist(super.res);
+ // TODO: check for error and in case one found return that
+
+ if (StringUtils.isEmpty(autoGenerateIA)) {
+ // no IA generation
+ // we include an XML for the data table
+
+ String implOrDeplArtifactXML = Utils.getXMLAsString(resultingArtifact);
+
+ return Response.created(Utils.createURI(Util.URLencode(artifactNameStr))).entity(implOrDeplArtifactXML).build();
+ } else {
+ // after everything was created, we fire up the artifact generation
+ return this.generateImplementationArtifact(interfaceNameStr, javapackage, uriInfo, artifactTemplateId, artifactTemplateResource);
+ }
+ }
+
+ /**
+ * Generates a unique and valid name to be used for the generated maven
+ * project name, java project name, class name, port type name.
+ */
+ private String generateName(NodeTypeId nodeTypeId, String interfaceName) {
+ String name = Util.namespaceToJavaPackage(nodeTypeId.getNamespace().getDecoded());
+ name += Util.FORBIDDEN_CHARACTER_REPLACEMENT;
+
+ // Winery already ensures that this is a valid NCName
+ // getName() returns the id of the nodeType: A nodeType carries the "id" attribute only (and no name attribute)
+ name += nodeTypeId.getXmlId().getDecoded();
+
+ // Two separators to distinguish node type and interface part
+ name += Util.FORBIDDEN_CHARACTER_REPLACEMENT;
+ name += Util.FORBIDDEN_CHARACTER_REPLACEMENT;
+ name += Util.namespaceToJavaPackage(interfaceName);
+
+ // In addition we must replace '.', because Java class names must not
+ // contain dots, but for Winery they are fine.
+ return name.replace(".", Util.FORBIDDEN_CHARACTER_REPLACEMENT);
+ }
+
+ /**
+ * Generates the implementation artifact using the implementation artifact
+ * generator. Also sets the proeprties according to the requirements of
+ * OpenTOSCA.
+ *
+ * @param interfaceNameStr
+ * @param javapackage
+ * @param uriInfo
+ * @param artifactTemplateId
+ * @param artifactTemplateResource the resource associated with the
+ * artifactTempalteId. If null, the object is created in this
+ * method
+ *
+ * @return {@inheritDoc}
+ */
+ private Response generateImplementationArtifact(String interfaceNameStr, String javapackage, UriInfo uriInfo, ArtifactTemplateId artifactTemplateId, ArtifactTemplateResource artifactTemplateResource) {
+ TInterface iface;
+
+ assert (this instanceof ImplementationArtifactsResource);
+ IHasTypeReference typeRes = (EntityTypeImplementationResource) this.res;
+ QName type = typeRes.getType();
+ TOSCAComponentId typeId;
+ TNodeType nodeType = null;
+ if (typeRes instanceof NodeTypeImplementationResource) {
+ // TODO: refactor: This is more a model/repo utilities thing than something which should happen here...
+
+ typeId = new NodeTypeId(type);
+ NodeTypeResource ntRes = (NodeTypeResource) AbstractComponentsResource.getComponentInstaceResource(typeId);
+
+ // required for IA Generation
+ nodeType = ntRes.getNodeType();
+
+ List<TInterface> interfaces = nodeType.getInterfaces().getInterface();
+ Iterator<TInterface> it = interfaces.iterator();
+ do {
+ iface = it.next();
+ if (iface.getName().equals(interfaceNameStr)) {
+ break;
+ }
+ } while (it.hasNext());
+ // iface now contains the right interface
+ } else {
+ assert (typeRes instanceof RelationshipTypeImplementationResource);
+ return Response.serverError().entity("IA creation for relation ship type implementations not yet possible").build();
+ }
+
+ Path workingDir;
+ try {
+ workingDir = Files.createTempDirectory("winery");
+ } catch (IOException e2) {
+ GenericArtifactsResource.logger.debug("Could not create temporary directory", e2);
+ return Response.serverError().entity("Could not create temporary directory").build();
+ }
+
+ URI artifactTemplateFilesUri = uriInfo.getBaseUri().resolve(Utils.getAbsoluteURL(artifactTemplateId)).resolve("files/");
+ URL artifactTemplateFilesUrl;
+ try {
+ artifactTemplateFilesUrl = artifactTemplateFilesUri.toURL();
+ } catch (MalformedURLException e2) {
+ GenericArtifactsResource.logger.debug("Could not convert URI to URL", e2);
+ return Response.serverError().entity("Could not convert URI to URL").build();
+ }
+
+ String name = this.generateName((NodeTypeId) typeId, interfaceNameStr);
+ Generator gen = new Generator(iface, javapackage, artifactTemplateFilesUrl, name, workingDir.toFile());
+ File zipFile = gen.generateProject();
+ if (zipFile == null) {
+ return Response.serverError().entity("IA generator failed").build();
+ }
+
+ // store it
+ // TODO: refactor: this is more a RepositoryUtils thing than a special thing here; see also importFile at CSARImporter
+
+ ArtifactTemplateDirectoryId fileDir = new ArtifactTemplateDirectoryId(artifactTemplateId);
+ RepositoryFileReference fref = new RepositoryFileReference(fileDir, zipFile.getName().toString());
+ try (InputStream is = Files.newInputStream(zipFile.toPath());
+ BufferedInputStream bis = new BufferedInputStream(is)) {
+ String mediaType = Utils.getMimeType(bis, zipFile.getName());
+ // TODO: do the catch thing as in CSARImporter
+
+ Repository.INSTANCE.putContentToFile(fref, bis, MediaType.valueOf(mediaType));
+ } catch (IOException e1) {
+ throw new IllegalStateException("Could not import generated files", e1);
+ }
+
+ // cleanup dir
+ try {
+ FileUtils.forceDelete(workingDir);
+ } catch (IOException e) {
+ GenericArtifactsResource.logger.debug("Could not delete working directory", e);
+ }
+
+ // store the properties in the artifact template
+ if (artifactTemplateResource == null) {
+ artifactTemplateResource = (ArtifactTemplateResource) AbstractComponentsResource.getComponentInstaceResource(artifactTemplateId);
+ }
+ this.storeProperties(artifactTemplateResource, typeId, name);
+
+ URI url = uriInfo.getBaseUri().resolve(Utils.getAbsoluteURL(fref));
+ return Response.created(url).build();
+ }
+
+
+ private final String NS_OPENTOSCA_WAR_TYPE = "http://www.uni-stuttgart.de/opentosca";
+
+
+ private void storeProperties(ArtifactTemplateResource artifactTemplateResource, TOSCAComponentId typeId, String name) {
+ // We generate the properties by hand instead of using JAX-B as using JAX-B causes issues at org.eclipse.winery.common.ModelUtilities.getPropertiesKV(TEntityTemplate):
+ // getAny() does not always return "w3c.dom.element" anymore
+
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ DocumentBuilder builder;
+ try {
+ builder = dbf.newDocumentBuilder();
+ } catch (ParserConfigurationException e) {
+ GenericArtifactsResource.logger.error(e.getMessage(), e);
+ return;
+ }
+ Document doc = builder.newDocument();
+ Element root = doc.createElementNS(this.NS_OPENTOSCA_WAR_TYPE, "WSProperties");
+ doc.appendChild(root);
+
+ Element element = doc.createElementNS(this.NS_OPENTOSCA_WAR_TYPE, "ServiceEndpoint");
+ Text text = doc.createTextNode("/services/" + name + "Port");
+ element.appendChild(text);
+ root.appendChild(element);
+
+ element = doc.createElementNS(this.NS_OPENTOSCA_WAR_TYPE, "PortType");
+ text = doc.createTextNode("{" + typeId.getNamespace().getDecoded() + "}" + name);
+ element.appendChild(text);
+ root.appendChild(element);
+
+ element = doc.createElementNS(this.NS_OPENTOSCA_WAR_TYPE, "InvocationType");
+ text = doc.createTextNode("SOAP/HTTP");
+ element.appendChild(text);
+ root.appendChild(element);
+
+ Properties properties = new Properties();
+ properties.setAny(root);
+ PropertiesResource propertiesResource = artifactTemplateResource.getPropertiesResource();
+ propertiesResource.setProperties(properties);
+ }
+
+ @Override
+ public Viewable getHTML() {
+ return new Viewable("/jsp/artifacts/artifacts.jsp", this);
+ }
+
+ /**
+ * Required for artifacts.jsp
+ *
+ * @return list of known artifact types.
+ */
+ public List<QName> getAllArtifactTypes() {
+ SortedSet<ArtifactTypeId> allArtifactTypes = Repository.INSTANCE.getAllTOSCAComponentIds(ArtifactTypeId.class);
+ List<QName> res = new ArrayList<QName>(allArtifactTypes.size());
+ for (ArtifactTypeId id : allArtifactTypes) {
+ res.add(id.getQName());
+ }
+ return res;
+ }
+
+ /**
+ * Required for artifacts.jsp
+ *
+ * @return list of all contained artifacts.
+ */
+ public abstract Collection<ArtifactResource> getAllArtifactResources();
+
+ /**
+ * Required by artifact.jsp to decide whether to display
+ * "Deployment Artifact" or "Implementation Artifact"
+ */
+ public boolean getIsDeploymentArtifacts() {
+ boolean res = (this instanceof DeploymentArtifactsResource);
+ return res;
+ }
+
+ /**
+ * required by artifacts.jsp
+ */
+ public String getNamespace() {
+ return this.resWithNamespace.getNamespace().getDecoded();
+ }
+
+ /**
+ * For saving resources, an AbstractComponentInstanceResource is required.
+ * DAs may be attached to a node template, which is not an
+ * AbstractComponentInstanceResource, but its grandparent resource
+ * ServiceTemplate is
+ *
+ * @param res the resource to determine the the
+ * AbstractComponentInstanceResource for
+ * @return the AbstractComponentInstanceResource where the given res is
+ * contained in
+ */
+ public static AbstractComponentInstanceResource getAbstractComponentInstanceResource(INodeTemplateResourceOrNodeTypeImplementationResourceOrRelationshipTypeImplementationResource res) {
+ final AbstractComponentInstanceResource r;
+ if (res instanceof NodeTemplateResource) {
+ r = ((NodeTemplateResource) res).getServiceTemplateResource();
+ } else {
+ // quick hack: the resource has to be an abstract component instance
+ r = (AbstractComponentInstanceResource) res;
+ }
+ return r;
+ }
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/artifacts/ImplementationArtifactResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/artifacts/ImplementationArtifactResource.java
new file mode 100644
index 0000000..bc5580c
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/artifacts/ImplementationArtifactResource.java
@@ -0,0 +1,95 @@
+/*******************************************************************************
+ * 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.repository.resources.artifacts;
+
+import java.util.List;
+
+import org.eclipse.winery.common.ids.definitions.ArtifactTemplateId;
+import org.eclipse.winery.common.ids.definitions.ArtifactTypeId;
+import org.eclipse.winery.model.tosca.TImplementationArtifacts.ImplementationArtifact;
+import org.eclipse.winery.repository.backend.BackendUtils;
+import org.eclipse.winery.repository.resources._support.IPersistable;
+import org.eclipse.winery.repository.resources._support.collections.IIdDetermination;
+
+public class ImplementationArtifactResource extends GenericArtifactResource<ImplementationArtifact> {
+
+ private ImplementationArtifact a;
+
+
+ /**
+ * Converts the given artifactId to an ImplementArtifact.
+ *
+ * <em>SIDE EFFECT</em> Adds it to the implementationArtifacts list if it
+ * does not yet exist.
+ */
+ private static ImplementationArtifact getImplementationArtifact(String artifactId, List<ImplementationArtifact> implementationArtifacts) {
+ if (artifactId == null) {
+ throw new IllegalArgumentException("artifactId must not be null");
+ }
+ if (implementationArtifacts == null) {
+ throw new IllegalArgumentException("implementationArtifacts must not be null");
+ }
+ for (ImplementationArtifact ia : implementationArtifacts) {
+ // ia.getName() might be null as TOSCA COS01 does not forsee a name on the implementation artifact
+ // Therefore, we begin the test with "artifactId"
+ if (artifactId.equals(ia.getName())) {
+ return ia;
+ }
+ }
+ // IA does not exist in list
+ ImplementationArtifact ia = new ImplementationArtifact();
+ ia.setName(artifactId);
+ implementationArtifacts.add(ia);
+ return ia;
+ }
+
+ public ImplementationArtifactResource(String artifactId, List<ImplementationArtifact> implementationArtifacts, IPersistable res) {
+ this(ImplementationArtifactResource.getImplementationArtifact(artifactId, implementationArtifacts), implementationArtifacts, res);
+ }
+
+ public ImplementationArtifactResource(IIdDetermination<ImplementationArtifact> idDetermination, ImplementationArtifact o, int idx, List<ImplementationArtifact> list, IPersistable res) {
+ super(idDetermination, o, idx, list, res);
+ this.a = o;
+ }
+
+ public ImplementationArtifactResource(ImplementationArtifact a, List<ImplementationArtifact> implementationArtifacts, IPersistable res) {
+ this(new IIdDetermination<ImplementationArtifact>() {
+
+ @Override
+ public String getId(ImplementationArtifact e) {
+ return e.getName();
+ }
+ }, a, implementationArtifacts.indexOf(a), implementationArtifacts, res);
+ }
+
+ public ImplementationArtifact getImplementationArtifact() {
+ return this.a;
+ }
+
+ @Override
+ public void setArtifactType(ArtifactTypeId artifactTypeId) {
+ this.getImplementationArtifact().setArtifactType(artifactTypeId.getQName());
+ BackendUtils.persist(this.res);
+ }
+
+ @Override
+ public void setArtifactTemplate(ArtifactTemplateId artifactTemplateId) {
+ this.getImplementationArtifact().setArtifactRef(artifactTemplateId.getQName());
+ BackendUtils.persist(this.res);
+ }
+
+ @Override
+ public ImplementationArtifact getA() {
+ return this.a;
+ }
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/artifacts/ImplementationArtifactsResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/artifacts/ImplementationArtifactsResource.java
new file mode 100644
index 0000000..e1d7aa6
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/artifacts/ImplementationArtifactsResource.java
@@ -0,0 +1,93 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2013,2015 University of Stuttgart.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ * Oliver Kopp - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.winery.repository.resources.artifacts;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import javax.xml.namespace.QName;
+
+import org.eclipse.winery.model.tosca.TImplementationArtifacts.ImplementationArtifact;
+import org.eclipse.winery.repository.resources.INodeTypeImplementationResourceOrRelationshipTypeImplementationResource;
+import org.eclipse.winery.repository.resources.entitytypeimplementations.nodetypeimplementations.NodeTypeImplementationResource;
+import org.eclipse.winery.repository.resources.entitytypeimplementations.relationshiptypeimplementations.RelationshipTypeImplementationResource;
+import org.eclipse.winery.repository.resources.entitytypes.nodetypes.NodeTypeResource;
+import org.eclipse.winery.repository.resources.entitytypes.nodetypes.NodeTypesResource;
+import org.eclipse.winery.repository.resources.entitytypes.relationshiptypes.RelationshipTypeResource;
+import org.eclipse.winery.repository.resources.entitytypes.relationshiptypes.RelationshipTypesResource;
+import org.eclipse.winery.repository.resources.interfaces.InterfaceResource;
+
+/**
+ * ImplementationArtifact instead of TImplementationArtifact has to be used
+ * because of difference in the XSD at tImplementationArtifacts vs.
+ * tDeploymentArtifacts
+ */
+public class ImplementationArtifactsResource extends GenericArtifactsResource<ImplementationArtifactResource, ImplementationArtifact> {
+
+ private List<ImplementationArtifact> implementationArtifacts;
+
+
+ public ImplementationArtifactsResource(List<ImplementationArtifact> implementationArtifact, INodeTypeImplementationResourceOrRelationshipTypeImplementationResource res) {
+ super(ImplementationArtifactResource.class, ImplementationArtifact.class, implementationArtifact, res);
+ this.implementationArtifacts = implementationArtifact;
+ }
+
+ /**
+ * @return a cast to TNodeTypeImplementationResource of the parent of this
+ * resource.
+ */
+ protected NodeTypeImplementationResource getNTI() {
+ return (NodeTypeImplementationResource) this.res;
+ }
+
+ /**
+ * @return a cast to TNodeTypeImplementationResource of the parent of this
+ * resource.
+ */
+ protected RelationshipTypeImplementationResource getRTI() {
+ return (RelationshipTypeImplementationResource) this.res;
+ }
+
+ @Override
+ public Collection<ImplementationArtifactResource> getAllArtifactResources() {
+ Collection<ImplementationArtifactResource> res = new ArrayList<ImplementationArtifactResource>(this.implementationArtifacts.size());
+ for (ImplementationArtifact da : this.implementationArtifacts) {
+ ImplementationArtifactResource r = new ImplementationArtifactResource(da, this.implementationArtifacts, this.res);
+ res.add(r);
+ }
+ return res;
+ }
+
+ /** required by artifacts.jsp **/
+ public List<InterfaceResource> getInterfacesOfAssociatedType() {
+ boolean isNodeTypeImplementation = this.res instanceof NodeTypeImplementationResource;
+ QName type;
+ List<InterfaceResource> interfaces = new ArrayList<InterfaceResource>();
+ if (isNodeTypeImplementation) {
+ type = this.getNTI().getType();
+ NodeTypeResource typeResource = (NodeTypeResource) new NodeTypesResource().getComponentInstaceResource(type);
+ interfaces.addAll(typeResource.getInterfaces().getAllEntityResources());
+ } else {
+ type = this.getRTI().getType();
+ RelationshipTypeResource typeResource = (RelationshipTypeResource) new RelationshipTypesResource().getComponentInstaceResource(type);
+ interfaces.addAll(typeResource.getSourceInterfaces().getAllEntityResources());
+ interfaces.addAll(typeResource.getTargetInterfaces().getAllEntityResources());
+ }
+ return interfaces;
+ }
+
+ @Override
+ public String getId(ImplementationArtifact entity) {
+ return entity.getName();
+ }
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/documentation/DocumentationResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/documentation/DocumentationResource.java
new file mode 100644
index 0000000..6783948
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/documentation/DocumentationResource.java
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * 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.repository.resources.documentation;
+
+import java.util.List;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.eclipse.winery.model.tosca.TDocumentation;
+import org.eclipse.winery.repository.resources._support.IPersistable;
+import org.eclipse.winery.repository.resources._support.collections.CollectionsHelper;
+import org.eclipse.winery.repository.resources._support.collections.withoutid.EntityWithoutIdResource;
+
+public class DocumentationResource extends EntityWithoutIdResource<TDocumentation> {
+
+ public DocumentationResource(TDocumentation o, int idx, List<TDocumentation> list, IPersistable res) {
+ super(o, idx, list, res);
+ }
+
+ @PUT
+ @Consumes(MediaType.TEXT_HTML)
+ @Produces(MediaType.TEXT_PLAIN)
+ public Response setValue(String documentation) {
+ this.o.getContent().clear();
+ this.o.getContent().add(documentation);
+ this.list.set(this.idx, this.o);
+ return CollectionsHelper.persist(this.res, this.idDetermination, this.o);
+ }
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/documentation/DocumentationsResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/documentation/DocumentationsResource.java
new file mode 100644
index 0000000..1466a57
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/documentation/DocumentationsResource.java
@@ -0,0 +1,60 @@
+/*******************************************************************************
+ * 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.repository.resources.documentation;
+
+import java.util.List;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.POST;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+
+import org.eclipse.winery.model.tosca.TDocumentation;
+import org.eclipse.winery.repository.resources._support.IPersistable;
+import org.eclipse.winery.repository.resources._support.collections.CollectionsHelper;
+import org.eclipse.winery.repository.resources._support.collections.withoutid.EntityWithoutIdCollectionResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.sun.jersey.api.view.Viewable;
+
+public class DocumentationsResource extends EntityWithoutIdCollectionResource<DocumentationResource, TDocumentation> {
+
+ private static final Logger logger = LoggerFactory.getLogger(DocumentationResource.class);
+
+
+ public DocumentationsResource(IPersistable res, List<TDocumentation> documentations) {
+ super(DocumentationResource.class, TDocumentation.class, documentations, res);
+ }
+
+ @Override
+ public Viewable getHTML() {
+ return new Viewable("/jsp/documentation.jsp", this.list);
+ }
+
+ /**
+ * Adds a new documentation
+ */
+ @POST
+ @Consumes(MediaType.TEXT_HTML)
+ public Response addNewElement(String documentation) {
+ if (documentation == null) {
+ return Response.status(Status.BAD_REQUEST).entity("No content provided").build();
+ }
+ TDocumentation doc = new TDocumentation();
+ doc.getContent().add(documentation);
+ // TODO: check for duplicates as in instance states
+ this.list.add(doc);
+ return CollectionsHelper.persist(this.res, this, doc);
+ }
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytemplates/IEntityTemplateResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytemplates/IEntityTemplateResource.java
new file mode 100644
index 0000000..e5025b1
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytemplates/IEntityTemplateResource.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * 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.repository.resources.entitytemplates;
+
+import javax.ws.rs.DELETE;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Response;
+
+import org.eclipse.winery.model.tosca.TEntityTemplate;
+import org.eclipse.winery.repository.resources.AbstractComponentInstanceResource;
+import org.eclipse.winery.repository.resources.IHasTypeReference;
+
+/**
+ * Interface ensuring that no methods are forgotten when implementing an
+ * {@link AbstractComponentInstanceResource}, which is also a template
+ */
+public interface IEntityTemplateResource<E extends TEntityTemplate> extends IHasTypeReference {
+
+ @Path("properties/")
+ public PropertiesResource getPropertiesResource();
+
+ @DELETE
+ public Response onDelete();
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytemplates/PropertiesResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytemplates/PropertiesResource.java
new file mode 100644
index 0000000..4341095
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytemplates/PropertiesResource.java
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * 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.repository.resources.entitytemplates;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.eclipse.winery.model.tosca.TEntityTemplate;
+import org.eclipse.winery.repository.backend.BackendUtils;
+import org.eclipse.winery.repository.resources.AbstractComponentInstanceResource;
+
+import com.sun.jersey.api.view.Viewable;
+
+public class PropertiesResource {
+
+ private AbstractComponentInstanceResource res;
+ private TEntityTemplate template;
+
+
+ /**
+ * @param template the template to store the definitions at
+ * @param res the resource to save after modifications
+ */
+ public PropertiesResource(TEntityTemplate template, AbstractComponentInstanceResource res) {
+ this.template = template;
+ this.res = res;
+ }
+
+ /**
+ * Currently, properties can only be updated as a whole XML fragment
+ *
+ * Getting/setting a fragment of properties is not possible yet
+ */
+ @PUT
+ @Consumes({MediaType.APPLICATION_XML, MediaType.TEXT_XML, MediaType.APPLICATION_JSON})
+ public Response setProperties(TEntityTemplate.Properties properties) {
+ this.getTemplate().setProperties(properties);
+ return BackendUtils.persist(this.res);
+ }
+
+ @GET
+ @Produces(MediaType.TEXT_HTML)
+ public Viewable getHTML() {
+ return new Viewable("/jsp/entitytemplates/properties.jsp", this);
+ }
+
+ /** data for the JSP **/
+
+ public TEntityTemplate getTemplate() {
+ return this.template;
+ }
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytemplates/TEntityTemplateResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytemplates/TEntityTemplateResource.java
new file mode 100644
index 0000000..ee9064b
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytemplates/TEntityTemplateResource.java
@@ -0,0 +1,92 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2014 University of Stuttgart.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ * Oliver Kopp - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.winery.repository.resources.entitytemplates;
+
+import java.util.List;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Response;
+import javax.xml.namespace.QName;
+
+import org.eclipse.winery.model.tosca.TEntityTemplate;
+import org.eclipse.winery.repository.backend.BackendUtils;
+import org.eclipse.winery.repository.resources.AbstractComponentInstanceResource;
+import org.eclipse.winery.repository.resources.IHasTypeReference;
+import org.eclipse.winery.repository.resources._support.IPersistable;
+import org.eclipse.winery.repository.resources._support.collections.IIdDetermination;
+import org.eclipse.winery.repository.resources._support.collections.withid.EntityWithIdResource;
+
+public class TEntityTemplateResource<E extends TEntityTemplate> extends EntityWithIdResource<E> implements IEntityTemplateResource<E>, IHasTypeReference {
+
+ /**
+ * This constructor is used for both entity templates nested in an component
+ * instance as well as for entity templates being component instances
+ * itself.
+ *
+ * As Java does not support multi-inheritance, we implemented a quick hack
+ * to re-use this class as inner implementation at templates extending
+ * AbstractComponentInstanceResourceDefinitionsBacked
+ */
+ public TEntityTemplateResource(IIdDetermination<E> idDetermination, E o, int idx, List<E> list, IPersistable res) {
+ super(idDetermination, o, idx, list, res);
+ }
+
+ // public String getId() {
+ // return this.template.getId();
+ // }
+ //
+ // public void setId(String id) {
+ // // TODO: There is no check for uniqueness of the given id
+ // this.template.setId(id);
+ // }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public QName getType() {
+ return this.o.getType();
+ }
+
+ @Path("type")
+ @GET
+ public String getTypeAsQNameString() {
+ return this.getType().toString();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Response setType(QName type) {
+ this.o.setType(type);
+ return BackendUtils.persist(this.res);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Response setType(String typeStr) {
+ return this.setType(QName.valueOf(typeStr));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public PropertiesResource getPropertiesResource() {
+ return new PropertiesResource(this.o, (AbstractComponentInstanceResource) this.res);
+ }
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytemplates/TEntityTemplatesResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytemplates/TEntityTemplatesResource.java
new file mode 100644
index 0000000..256e376
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytemplates/TEntityTemplatesResource.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2014 University of Stuttgart.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ * Oliver Kopp - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.winery.repository.resources.entitytemplates;
+
+import java.util.List;
+
+import org.eclipse.winery.model.tosca.TEntityTemplate;
+import org.eclipse.winery.repository.resources._support.IPersistable;
+import org.eclipse.winery.repository.resources._support.collections.withid.EntityWithIdCollectionResource;
+import org.eclipse.winery.repository.resources._support.collections.withid.EntityWithIdResource;
+
+/**
+ * This resource models the list of TEntityTemplates
+ */
+public abstract class TEntityTemplatesResource<R extends EntityWithIdResource<T>, T extends TEntityTemplate> extends EntityWithIdCollectionResource<R, T> {
+
+ public TEntityTemplatesResource(Class<R> entityResourceTClazz, Class<T> entityTClazz, List<T> list, IPersistable res) {
+ super(entityResourceTClazz, entityTClazz, list, res);
+ }
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytemplates/artifacttemplates/ArtifactTemplateResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytemplates/artifacttemplates/ArtifactTemplateResource.java
new file mode 100644
index 0000000..f3ed0e9
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytemplates/artifacttemplates/ArtifactTemplateResource.java
@@ -0,0 +1,308 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2014 University of Stuttgart.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ * Oliver Kopp - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.winery.repository.resources.entitytemplates.artifacttemplates;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.SortedSet;
+
+import javax.ws.rs.GET;
+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.ws.rs.core.Response.Status;
+import javax.xml.namespace.QName;
+
+import org.eclipse.winery.common.RepositoryFileReference;
+import org.eclipse.winery.common.ids.definitions.ArtifactTemplateId;
+import org.eclipse.winery.common.ids.definitions.ArtifactTypeId;
+import org.eclipse.winery.common.ids.definitions.NodeTypeImplementationId;
+import org.eclipse.winery.common.ids.definitions.RelationshipTypeImplementationId;
+import org.eclipse.winery.common.ids.definitions.ServiceTemplateId;
+import org.eclipse.winery.model.tosca.TArtifactReference;
+import org.eclipse.winery.model.tosca.TArtifactTemplate;
+import org.eclipse.winery.model.tosca.TArtifactTemplate.ArtifactReferences;
+import org.eclipse.winery.model.tosca.TDeploymentArtifact;
+import org.eclipse.winery.model.tosca.TDeploymentArtifacts;
+import org.eclipse.winery.model.tosca.TEntityTemplate;
+import org.eclipse.winery.model.tosca.TExtensibleElements;
+import org.eclipse.winery.model.tosca.TImplementationArtifact;
+import org.eclipse.winery.model.tosca.TImplementationArtifacts;
+import org.eclipse.winery.model.tosca.TNodeTemplate;
+import org.eclipse.winery.model.tosca.TTopologyTemplate;
+import org.eclipse.winery.repository.Utils;
+import org.eclipse.winery.repository.backend.BackendUtils;
+import org.eclipse.winery.repository.backend.Repository;
+import org.eclipse.winery.repository.datatypes.ids.elements.ArtifactTemplateDirectoryId;
+import org.eclipse.winery.repository.resources.AbstractComponentInstanceWithReferencesResource;
+import org.eclipse.winery.repository.resources.AbstractComponentsResource;
+import org.eclipse.winery.repository.resources.IHasName;
+import org.eclipse.winery.repository.resources.entitytemplates.IEntityTemplateResource;
+import org.eclipse.winery.repository.resources.entitytemplates.PropertiesResource;
+import org.eclipse.winery.repository.resources.entitytemplates.TEntityTemplateResource;
+import org.eclipse.winery.repository.resources.entitytypeimplementations.nodetypeimplementations.NodeTypeImplementationResource;
+import org.eclipse.winery.repository.resources.entitytypeimplementations.relationshiptypeimplementations.RelationshipTypeImplementationResource;
+import org.eclipse.winery.repository.resources.entitytypes.artifacttypes.ArtifactTypeResource;
+import org.eclipse.winery.repository.resources.servicetemplates.ServiceTemplateResource;
+
+/**
+ * Models an Artifact Template with its artifact references
+ *
+ * The associated files (through tArtifactReference) are stored directly within
+ * this resource. The element <ArtifactReference> is generated during export
+ * only
+ *
+ * This class inherits from AbstractComponentInstanceResourceDefinitionsBacked
+ * and not from TEntityTemplateResource<TArtifactTemplate>, because
+ * ArtifactTemplates are directly available under TDefinitions and we need the
+ * generic resource handling
+ */
+
+public class ArtifactTemplateResource extends AbstractComponentInstanceWithReferencesResource implements IEntityTemplateResource<TArtifactTemplate>, IHasName {
+
+ private final TEntityTemplateResource<TArtifactTemplate> entityTemplateResource;
+
+
+ public ArtifactTemplateResource(ArtifactTemplateId id) {
+ super(id);
+ // we provide the minimum requirements for the resource
+ this.entityTemplateResource = new TEntityTemplateResource<TArtifactTemplate>(null, this.getTArtifactTemplate(), 0, null, this);
+ }
+
+ /**
+ * @return null if no artifact type resource is defined
+ */
+ public ArtifactTypeResource getAritfactTypeResource() {
+ ArtifactTypeId atId = new ArtifactTypeId(this.getTArtifactTemplate().getType());
+ return new ArtifactTypeResource(atId);
+ }
+
+ private TArtifactTemplate getTArtifactTemplate() {
+ return (TArtifactTemplate) this.element;
+ }
+
+ @Override
+ public String getName() {
+ String name = this.getTArtifactTemplate().getName();
+ if (name == null) {
+ return this.getTArtifactTemplate().getId();
+ } else {
+ return name;
+ }
+ }
+
+ @Override
+ public Response setName(String name) {
+ this.getTArtifactTemplate().setName(name);
+ return BackendUtils.persist(this);
+ }
+
+ @Override
+ protected TExtensibleElements createNewElement() {
+ return new TArtifactTemplate();
+ }
+
+ @Override
+ protected void copyIdToFields() {
+ this.getTArtifactTemplate().setId(this.getId().getXmlId().getDecoded());
+ // Namespace cannot be set as the namespace is contained in TDefinitions only
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void synchronizeReferences() {
+ TArtifactTemplate template = this.getTArtifactTemplate();
+
+ ArtifactTemplateDirectoryId fileDir = new ArtifactTemplateDirectoryId((ArtifactTemplateId) this.id);
+ SortedSet<RepositoryFileReference> files = Repository.INSTANCE.getContainedFiles(fileDir);
+ if (files.isEmpty()) {
+ // clear artifact references
+ template.setArtifactReferences(null);
+ } else {
+ ArtifactReferences artifactReferences = new ArtifactReferences();
+ template.setArtifactReferences(artifactReferences);
+ List<TArtifactReference> artRefList = artifactReferences.getArtifactReference();
+ for (RepositoryFileReference ref : files) {
+ // determine path
+ // path relative from the root of the CSAR is ok (COS01, line 2663)
+ String path = Utils.getURLforPathInsideRepo(BackendUtils.getPathInsideRepo(ref));
+
+ // put path into data structure
+ // we do not use Inlude/Exclude as we directly reference a concrete file
+ TArtifactReference artRef = new TArtifactReference();
+ artRef.setReference(path);
+ artRefList.add(artRef);
+ }
+ }
+ }
+
+ @Path("files/")
+ public FilesResource getFilesResource() {
+ ArtifactTemplateDirectoryId fileDir = new ArtifactTemplateDirectoryId((ArtifactTemplateId) this.id);
+ return new FilesResource(fileDir);
+ }
+
+ /***********************************************************************
+ * "inheritance" from TEntityTemplateResource<TArtifactTemplate> *
+ *
+ * Offering all methods of TEntityTemplateResource<TArtifactTemplate> and
+ * forwarding it to our private instance of it
+ */
+
+ @Override
+ public QName getType() {
+ return this.entityTemplateResource.getType();
+ }
+
+ @Override
+ public Response setType(QName type) {
+ this.entityTemplateResource.setType(type);
+ return BackendUtils.persist(this);
+ }
+
+ @Override
+ public Response setType(String typeStr) {
+ this.entityTemplateResource.setType(typeStr);
+ return BackendUtils.persist(this);
+ }
+
+ @Override
+ public PropertiesResource getPropertiesResource() {
+ return new PropertiesResource(this.getTArtifactTemplate(), this);
+ }
+
+ int getReferenceCount() {
+ // We do not use a database, therefore, we have to go through all possibilities pointing to the artifact template
+ // DAs and IAs point to an artifact template
+ // DAs are contained in Node Type Implementations and Node Templates
+ // IAs are contained in Node Type Implementations and Relationship Type Implementations
+
+ int count = 0;
+
+ Collection<TDeploymentArtifact> allDAs = new HashSet<>();
+ Collection<TImplementationArtifact> allIAs = new HashSet<>();
+
+ // handle Node Type Implementation, which contains DAs and IAs
+ SortedSet<NodeTypeImplementationId> nodeTypeImplementations = Repository.INSTANCE.getAllTOSCAComponentIds(NodeTypeImplementationId.class);
+ for (NodeTypeImplementationId ntiId : nodeTypeImplementations) {
+ NodeTypeImplementationResource ntiRes = (NodeTypeImplementationResource) AbstractComponentsResource.getComponentInstaceResource(ntiId);
+ TDeploymentArtifacts deploymentArtifacts = ntiRes.getNTI().getDeploymentArtifacts();
+ if (deploymentArtifacts != null) {
+ allDAs.addAll(deploymentArtifacts.getDeploymentArtifact());
+ }
+ TImplementationArtifacts implementationArtifacts = ntiRes.getNTI().getImplementationArtifacts();
+ if (implementationArtifacts != null) {
+ allIAs.addAll(implementationArtifacts.getImplementationArtifact());
+ }
+ }
+
+ // check all Relationshiptype Implementations for IAs
+ SortedSet<RelationshipTypeImplementationId> relationshipTypeImplementations = Repository.INSTANCE.getAllTOSCAComponentIds(RelationshipTypeImplementationId.class);
+ for (RelationshipTypeImplementationId rtiId : relationshipTypeImplementations) {
+ RelationshipTypeImplementationResource rtiRes = (RelationshipTypeImplementationResource) AbstractComponentsResource.getComponentInstaceResource(rtiId);
+ TImplementationArtifacts implementationArtifacts = rtiRes.getRTI().getImplementationArtifacts();
+ if (implementationArtifacts != null) {
+ allIAs.addAll(implementationArtifacts.getImplementationArtifact());
+ }
+ }
+
+ // check all node templates for DAs
+ SortedSet<ServiceTemplateId> serviceTemplates = Repository.INSTANCE.getAllTOSCAComponentIds(ServiceTemplateId.class);
+ for (ServiceTemplateId sid : serviceTemplates) {
+ ServiceTemplateResource serviceTemplateRes = (ServiceTemplateResource) AbstractComponentsResource.getComponentInstaceResource(sid);
+ TTopologyTemplate topologyTemplate = serviceTemplateRes.getServiceTemplate().getTopologyTemplate();
+ if (topologyTemplate != null) {
+ List<TEntityTemplate> nodeTemplateOrRelationshipTemplate = topologyTemplate.getNodeTemplateOrRelationshipTemplate();
+ for (TEntityTemplate template : nodeTemplateOrRelationshipTemplate) {
+ if (template instanceof TNodeTemplate) {
+ TNodeTemplate nodeTemplate = (TNodeTemplate) template;
+ TDeploymentArtifacts deploymentArtifacts = nodeTemplate.getDeploymentArtifacts();
+ if (deploymentArtifacts != null) {
+ allDAs.addAll(deploymentArtifacts.getDeploymentArtifact());
+ }
+ }
+ }
+ }
+ }
+
+ // now we have all DAs and IAs
+
+ QName ourQName = this.getQName();
+
+ // check DAs for artifact templates
+ for (TDeploymentArtifact da : allDAs) {
+ QName artifactRef = da.getArtifactRef();
+ if (ourQName.equals(artifactRef)) {
+ count++;
+ }
+ }
+
+ // check IAs for artifact templates
+ for (TImplementationArtifact ia : allIAs) {
+ QName artifactRef = ia.getArtifactRef();
+ if (ourQName.equals(artifactRef)) {
+ count++;
+ }
+ }
+
+ return count;
+ }
+
+ /**
+ * Query parameter {@code type}:<br />
+ * Returns the type of the artifact template
+ *
+ * Query parameter {@code referenceCount}:<br />
+ * Determines the number of elements known by the repository which point to
+ * this resource. This method probably can be moved up the type hierarchy.
+ * Currently, it is only required here by the topology modeler.
+ *
+ * @return the type of the artifact template OR the number of references
+ * pointing to this resource
+ */
+ @GET
+ @Produces(MediaType.TEXT_PLAIN)
+ public Response getRefereneCount(@QueryParam("referenceCount") String referenceCount, @QueryParam("type") String type) {
+ if (referenceCount != null) {
+ String res = Integer.toString(this.getReferenceCount());
+ return Response.ok().entity(res).build();
+ } else if (type != null) {
+ String res = this.getType().toString();
+ return Response.ok().entity(res).build();
+ } else {
+ // we enforce the query parameter to be extensible to other queries
+ return Response.status(Status.BAD_REQUEST).entity("You have to pass the query parameter referenceCount or type").build();
+ }
+
+ }
+
+ /* not yet implemented */
+ /*
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response getReferenes(@QueryParam("references") String references) {
+ if (references== null) {
+ // we enforce the query parameter to be extensible to other queries
+ return Response.status(Status.BAD_REQUEST).entity("You have to pass the query parameter references").build();
+ }
+
+ String res = Integer.toString(this.getReferenceCount());
+ return Response.ok().entity(res).build();
+ }
+ */
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytemplates/artifacttemplates/ArtifactTemplatesResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytemplates/artifacttemplates/ArtifactTemplatesResource.java
new file mode 100644
index 0000000..e02a668
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytemplates/artifacttemplates/ArtifactTemplatesResource.java
@@ -0,0 +1,21 @@
+/*******************************************************************************
+ * 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.repository.resources.entitytemplates.artifacttemplates;
+
+import org.eclipse.winery.repository.resources.AbstractComponentsWithTypeReferenceResource;
+
+/**
+ * This class does NOT inherit from TEntityTemplatesResource<ArtifactTemplate>
+ * as these templates are directly nested in a TDefinitionsElement
+ */
+public class ArtifactTemplatesResource extends AbstractComponentsWithTypeReferenceResource<ArtifactTemplateResource> {
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytemplates/artifacttemplates/FilesResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytemplates/artifacttemplates/FilesResource.java
new file mode 100644
index 0000000..0a910fe
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytemplates/artifacttemplates/FilesResource.java
@@ -0,0 +1,163 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2013,2015 University of Stuttgart.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ * Oliver Kopp - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.winery.repository.resources.entitytemplates.artifacttemplates;
+
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.SortedSet;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.HeaderParam;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+import javax.ws.rs.core.UriInfo;
+
+import org.apache.commons.io.FilenameUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.eclipse.winery.common.RepositoryFileReference;
+import org.eclipse.winery.common.Util;
+import org.eclipse.winery.repository.Constants;
+import org.eclipse.winery.repository.Utils;
+import org.eclipse.winery.repository.backend.BackendUtils;
+import org.eclipse.winery.repository.backend.Repository;
+import org.eclipse.winery.repository.datatypes.FileMeta;
+import org.eclipse.winery.repository.datatypes.ids.elements.ArtifactTemplateDirectoryId;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.sun.jersey.api.view.Viewable;
+import com.sun.jersey.core.header.FormDataContentDisposition;
+import com.sun.jersey.multipart.FormDataBodyPart;
+import com.sun.jersey.multipart.FormDataParam;
+
+public class FilesResource {
+
+ private static final Logger logger = LoggerFactory.getLogger(FilesResource.class);
+ private final ArtifactTemplateDirectoryId fileDir;
+
+
+ public FilesResource(ArtifactTemplateDirectoryId fileDir) {
+ this.fileDir = fileDir;
+ }
+
+ private String getData4jqueryFileUpload(List<FileMeta> metas) {
+ String data4jqueryFileUpload = Utils.Object2JSON(metas);
+ data4jqueryFileUpload = "{\"files\":" + data4jqueryFileUpload + "}";
+ return data4jqueryFileUpload;
+ }
+
+ /**
+ * Handles the upload of a <em>single</em> file. Adds the given file to the
+ * current artifact template.
+ *
+ * If the file already exists, is it <em>overridden</em>
+ *
+ * @return JSON with data required by JQuery-File-Upload (see
+ * https://github.com/blueimp/jQuery-File-Upload/wiki/Setup)
+ */
+ @POST
+ @Produces(MediaType.APPLICATION_JSON)
+ @Consumes(MediaType.MULTIPART_FORM_DATA)
+ public Response onPost(@FormDataParam("files[]") InputStream uploadedInputStream, @FormDataParam("files[]") FormDataContentDisposition fileDetail, @FormDataParam("files[]") FormDataBodyPart body, @Context UriInfo uriInfo) {
+ // existence check not required as instantiation of the resource ensures that the object only exists if the resource exists
+ FilesResource.logger.debug("Beginning with file upload");
+
+ String fileName = fileDetail.getFileName();
+ if (StringUtils.isEmpty(fileName)) {
+ return Response.status(Status.BAD_REQUEST).build();
+ }
+ RepositoryFileReference ref = this.fileName2fileRef(fileName, false);
+
+ // TODO: instead of fixing the media type, we could overwrite the browser's mediatype by using some user configuration
+ BufferedInputStream bis = new BufferedInputStream(uploadedInputStream);
+ MediaType mediaType = Utils.getFixedMimeType(bis, fileName, body.getMediaType());
+
+ Response response = BackendUtils.putContentToFile(ref, bis, mediaType);
+ if (response.getStatus() == Status.INTERNAL_SERVER_ERROR.getStatusCode()) {
+ return response;
+ }
+
+ // create FileMeta object
+ String URL = Utils.getAbsoluteURL(this.fileDir) + Util.URLencode(fileName);
+ String thumbnailURL = uriInfo.getBaseUriBuilder().path(Constants.PATH_MIMETYPEIMAGES).path(FilenameUtils.getExtension(fileName) + Constants.SUFFIX_MIMETYPEIMAGES).build().toString();
+ long size;
+ try {
+ size = Repository.INSTANCE.getSize(ref);
+ } catch (IOException e) {
+ FilesResource.logger.error(e.getMessage(), e);
+ return Response.serverError().entity(e.getMessage()).build();
+ }
+ FileMeta fileMeta = new FileMeta(fileName, size, URL, thumbnailURL);
+
+ List<FileMeta> metas = new ArrayList<FileMeta>();
+ metas.add(fileMeta);
+ return Response.created(Utils.createURI(URL)).entity(this.getData4jqueryFileUpload(metas)).build();
+ }
+
+ /**
+ * Returns a list of file meta object
+ */
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ public String getJSON() {
+ return this.getData4jqueryFileUpload(this.getAllFileMetas());
+ }
+
+ private List<FileMeta> getAllFileMetas() {
+ List<FileMeta> res = new ArrayList<FileMeta>();
+ SortedSet<RepositoryFileReference> fileRefs = Repository.INSTANCE.getContainedFiles(this.fileDir);
+ for (RepositoryFileReference ref : fileRefs) {
+ res.add(new FileMeta(ref));
+ }
+ return res;
+ }
+
+ private RepositoryFileReference fileName2fileRef(String fileName, boolean encoded) {
+ if (encoded) {
+ fileName = Util.URLdecode(fileName);
+ }
+ RepositoryFileReference ref = new RepositoryFileReference(this.fileDir, fileName);
+ return ref;
+ }
+
+ @GET
+ @Produces(MediaType.TEXT_HTML)
+ public Viewable getHTML() {
+ return new Viewable("/jsp/entitytemplates/artifacttemplates/files.jsp");
+ }
+
+ @GET
+ @Path("/{fileName}")
+ public Response getFile(@PathParam("fileName") String fileName, @HeaderParam("If-Modified-Since") String modified) {
+ RepositoryFileReference ref = this.fileName2fileRef(fileName, true);
+ return BackendUtils.returnRepoPath(ref, modified);
+ }
+
+ @DELETE
+ @Path("/{fileName}")
+ public Response deleteFile(@PathParam("fileName") String fileName) {
+ RepositoryFileReference ref = this.fileName2fileRef(fileName, true);
+ return BackendUtils.delete(ref);
+ }
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytemplates/package-info.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytemplates/package-info.java
new file mode 100644
index 0000000..4375378
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytemplates/package-info.java
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+/**
+ * The sub packages of this package contains all resources, which are derived
+ * from tEntityTemplate
+ *
+ * EntityTemplates get their namespaces from the surrounding
+ * Definitions-element. <br />
+ * Nevertheless, they are stored using the same filesystem structure as
+ * EntityTypes
+ *
+ * {@link org.eclipse.winery.repository.resources.servicetemplates.topologytemplates.RelationshipTemplateResource}
+ * and
+ * {@link org.eclipse.winery.repository.resources.servicetemplates.topologytemplates.NodeTemplateResource}
+ * are stored in the topology package
+ */
+package org.eclipse.winery.repository.resources.entitytemplates;
+
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytemplates/policytemplates/PolicyTemplateResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytemplates/policytemplates/PolicyTemplateResource.java
new file mode 100644
index 0000000..e69a282
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytemplates/policytemplates/PolicyTemplateResource.java
@@ -0,0 +1,95 @@
+/*******************************************************************************
+ * 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.repository.resources.entitytemplates.policytemplates;
+
+import javax.ws.rs.core.Response;
+import javax.xml.namespace.QName;
+
+import org.eclipse.winery.common.ids.definitions.PolicyTemplateId;
+import org.eclipse.winery.model.tosca.TExtensibleElements;
+import org.eclipse.winery.model.tosca.TPolicyTemplate;
+import org.eclipse.winery.repository.backend.BackendUtils;
+import org.eclipse.winery.repository.resources.AbstractComponentInstanceResource;
+import org.eclipse.winery.repository.resources.IHasName;
+import org.eclipse.winery.repository.resources.entitytemplates.IEntityTemplateResource;
+import org.eclipse.winery.repository.resources.entitytemplates.PropertiesResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public final class PolicyTemplateResource extends AbstractComponentInstanceResource implements IEntityTemplateResource<TPolicyTemplate>, IHasName {
+
+ private static final Logger logger = LoggerFactory.getLogger(PolicyTemplateResource.class);
+
+
+ /**
+ * Constructor has to be public because of test cases
+ */
+ public PolicyTemplateResource(PolicyTemplateId id) {
+ super(id);
+ }
+
+ /**
+ * Convenience method to avoid casting at the caller's side.
+ */
+ public TPolicyTemplate getPolicyTemplate() {
+ return (TPolicyTemplate) this.getElement();
+ }
+
+ @Override
+ protected TExtensibleElements createNewElement() {
+ return new TPolicyTemplate();
+ }
+
+ @Override
+ public QName getType() {
+ return this.getPolicyTemplate().getType();
+ }
+
+ @Override
+ public Response setType(QName type) {
+ this.getPolicyTemplate().setType(type);
+ return BackendUtils.persist(this);
+ }
+
+ @Override
+ public Response setType(String typeStr) {
+ this.getPolicyTemplate().setType(QName.valueOf(typeStr));
+ return BackendUtils.persist(this);
+ }
+
+ @Override
+ public PropertiesResource getPropertiesResource() {
+ return new PropertiesResource(this.getPolicyTemplate(), this);
+ }
+
+ @Override
+ protected void copyIdToFields() {
+ this.getPolicyTemplate().setId(this.getId().getXmlId().getDecoded());
+ }
+
+ @Override
+ public String getName() {
+ String name = this.getPolicyTemplate().getName();
+ if (name == null) {
+ return this.getPolicyTemplate().getId();
+ } else {
+ return name;
+ }
+ }
+
+ @Override
+ public Response setName(String name) {
+ this.getPolicyTemplate().setName(name);
+ return BackendUtils.persist(this);
+ }
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytemplates/policytemplates/PolicyTemplatesResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytemplates/policytemplates/PolicyTemplatesResource.java
new file mode 100644
index 0000000..685ab66
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytemplates/policytemplates/PolicyTemplatesResource.java
@@ -0,0 +1,23 @@
+/*******************************************************************************
+ * 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.repository.resources.entitytemplates.policytemplates;
+
+import org.eclipse.winery.repository.resources.AbstractComponentsWithTypeReferenceResource;
+
+/**
+ * Manages all policy types in all available namespaces <br />
+ * The actual implementation is done in the
+ * AbstractComponentsWithTypeReferenceResource
+ */
+public class PolicyTemplatesResource extends AbstractComponentsWithTypeReferenceResource<PolicyTemplateResource> {
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypeimplementations/EntityTypeImplementationResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypeimplementations/EntityTypeImplementationResource.java
new file mode 100644
index 0000000..8b48e74
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypeimplementations/EntityTypeImplementationResource.java
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * 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.repository.resources.entitytypeimplementations;
+
+import org.eclipse.winery.common.ids.definitions.TOSCAComponentId;
+import org.eclipse.winery.repository.resources.AbstractComponentInstanceResourceWithNameDerivedFromAbstractFinal;
+import org.eclipse.winery.repository.resources.IHasTypeReference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public abstract class EntityTypeImplementationResource extends AbstractComponentInstanceResourceWithNameDerivedFromAbstractFinal implements IHasTypeReference {
+
+ private static final Logger logger = LoggerFactory.getLogger(EntityTypeImplementationResource.class);
+
+
+ protected EntityTypeImplementationResource(TOSCAComponentId id) {
+ super(id);
+ }
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypeimplementations/nodetypeimplementations/NodeTypeImplementationResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypeimplementations/nodetypeimplementations/NodeTypeImplementationResource.java
new file mode 100644
index 0000000..95b95d2
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypeimplementations/nodetypeimplementations/NodeTypeImplementationResource.java
@@ -0,0 +1,105 @@
+/*******************************************************************************
+ * 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.repository.resources.entitytypeimplementations.nodetypeimplementations;
+
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Response;
+import javax.xml.namespace.QName;
+
+import org.eclipse.winery.common.ids.definitions.NodeTypeImplementationId;
+import org.eclipse.winery.model.tosca.TDeploymentArtifacts;
+import org.eclipse.winery.model.tosca.TExtensibleElements;
+import org.eclipse.winery.model.tosca.TImplementationArtifacts;
+import org.eclipse.winery.model.tosca.TNodeTypeImplementation;
+import org.eclipse.winery.repository.backend.BackendUtils;
+import org.eclipse.winery.repository.resources.INodeTemplateResourceOrNodeTypeImplementationResource;
+import org.eclipse.winery.repository.resources.INodeTypeImplementationResourceOrRelationshipTypeImplementationResource;
+import org.eclipse.winery.repository.resources.artifacts.DeploymentArtifactsResource;
+import org.eclipse.winery.repository.resources.artifacts.ImplementationArtifactsResource;
+import org.eclipse.winery.repository.resources.entitytypeimplementations.EntityTypeImplementationResource;
+
+public class NodeTypeImplementationResource extends EntityTypeImplementationResource implements INodeTemplateResourceOrNodeTypeImplementationResource, INodeTypeImplementationResourceOrRelationshipTypeImplementationResource {
+
+ public NodeTypeImplementationResource(NodeTypeImplementationId id) {
+ super(id);
+ }
+
+ /**
+ * public because of exporter
+ */
+ public TNodeTypeImplementation getNTI() {
+ return (TNodeTypeImplementation) this.getElement();
+ }
+
+ /**
+ * Even if both node type implementations and relationship type
+ * implementations have implementation artifacts, there is no common
+ * supertype. To avoid endless casts, we just implement the method here
+ *
+ * @return
+ */
+ @Path("implementationartifacts/")
+ public ImplementationArtifactsResource getImplementationArtifacts() {
+ TImplementationArtifacts implementationArtifacts;
+ implementationArtifacts = this.getNTI().getImplementationArtifacts();
+ if (implementationArtifacts == null) {
+ implementationArtifacts = new TImplementationArtifacts();
+ this.getNTI().setImplementationArtifacts(implementationArtifacts);
+ }
+ return new ImplementationArtifactsResource(implementationArtifacts.getImplementationArtifact(), this);
+ }
+
+ /**
+ * Only NodeTypes have deployment artifacts, not RelationshipType.
+ * Therefore, this method is declared in
+ * {@link NodeTypeImplementationResource} and not in
+ * {@link EntityTypeImplementationResource}
+ */
+ @Path("deploymentartifacts/")
+ public DeploymentArtifactsResource getDeploymentArtifacts() {
+ TDeploymentArtifacts deploymentArtifacts;
+ deploymentArtifacts = this.getNTI().getDeploymentArtifacts();
+ if (deploymentArtifacts == null) {
+ deploymentArtifacts = new TDeploymentArtifacts();
+ this.getNTI().setDeploymentArtifacts(deploymentArtifacts);
+ }
+ return new DeploymentArtifactsResource(deploymentArtifacts.getDeploymentArtifact(), this);
+ }
+
+ @Override
+ protected TExtensibleElements createNewElement() {
+ return new TNodeTypeImplementation();
+ }
+
+ @Override
+ protected void copyIdToFields() {
+ this.getNTI().setTargetNamespace(this.getId().getNamespace().getDecoded());
+ this.getNTI().setName(this.getId().getXmlId().getDecoded());
+ }
+
+ @Override
+ public QName getType() {
+ return this.getNTI().getNodeType();
+ }
+
+ @Override
+ public Response setType(QName type) {
+ this.getNTI().setNodeType(type);
+ return BackendUtils.persist(this);
+ }
+
+ @Override
+ public Response setType(String typeStr) {
+ QName type = QName.valueOf(typeStr);
+ return this.setType(type);
+ }
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypeimplementations/nodetypeimplementations/NodeTypeImplementationsResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypeimplementations/nodetypeimplementations/NodeTypeImplementationsResource.java
new file mode 100644
index 0000000..b9c0836
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypeimplementations/nodetypeimplementations/NodeTypeImplementationsResource.java
@@ -0,0 +1,18 @@
+/*******************************************************************************
+ * 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.repository.resources.entitytypeimplementations.nodetypeimplementations;
+
+import org.eclipse.winery.repository.resources.AbstractComponentsWithTypeReferenceResource;
+
+public class NodeTypeImplementationsResource extends AbstractComponentsWithTypeReferenceResource<NodeTypeImplementationResource> {
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypeimplementations/package-info.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypeimplementations/package-info.java
new file mode 100644
index 0000000..af1c346
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypeimplementations/package-info.java
@@ -0,0 +1,19 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+/**
+ * The sub packages of this package contains all resources, which are
+ * implementations of a type. <br />
+ * The specification does NOT introduce tEntityTypeImplementation, but we
+ * implement as if that had been happened.
+ */
+package org.eclipse.winery.repository.resources.entitytypeimplementations;
+
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypeimplementations/relationshiptypeimplementations/RelationshipTypeImplementationResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypeimplementations/relationshiptypeimplementations/RelationshipTypeImplementationResource.java
new file mode 100644
index 0000000..521758a
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypeimplementations/relationshiptypeimplementations/RelationshipTypeImplementationResource.java
@@ -0,0 +1,81 @@
+/*******************************************************************************
+ * 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.repository.resources.entitytypeimplementations.relationshiptypeimplementations;
+
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Response;
+import javax.xml.namespace.QName;
+
+import org.eclipse.winery.common.ids.definitions.RelationshipTypeImplementationId;
+import org.eclipse.winery.model.tosca.TExtensibleElements;
+import org.eclipse.winery.model.tosca.TImplementationArtifacts;
+import org.eclipse.winery.model.tosca.TRelationshipTypeImplementation;
+import org.eclipse.winery.repository.backend.BackendUtils;
+import org.eclipse.winery.repository.resources.INodeTypeImplementationResourceOrRelationshipTypeImplementationResource;
+import org.eclipse.winery.repository.resources.artifacts.ImplementationArtifactsResource;
+import org.eclipse.winery.repository.resources.entitytypeimplementations.EntityTypeImplementationResource;
+
+public class RelationshipTypeImplementationResource extends EntityTypeImplementationResource implements INodeTypeImplementationResourceOrRelationshipTypeImplementationResource {
+
+ public RelationshipTypeImplementationResource(RelationshipTypeImplementationId id) {
+ super(id);
+ }
+
+ public TRelationshipTypeImplementation getRTI() {
+ return (TRelationshipTypeImplementation) this.getElement();
+ }
+
+ /**
+ * Even if both node type implementations and relationship type
+ * implementations have implementation artifacts, there is no common
+ * supertype. To avoid endless casts, we just implement the method here
+ */
+ @Path("implementationartifacts/")
+ public ImplementationArtifactsResource getImplementationArtifacts() {
+ TImplementationArtifacts implementationArtifacts;
+ implementationArtifacts = this.getRTI().getImplementationArtifacts();
+ if (implementationArtifacts == null) {
+ implementationArtifacts = new TImplementationArtifacts();
+ this.getRTI().setImplementationArtifacts(implementationArtifacts);
+ }
+ return new ImplementationArtifactsResource(implementationArtifacts.getImplementationArtifact(), this);
+ }
+
+ @Override
+ protected TExtensibleElements createNewElement() {
+ return new TRelationshipTypeImplementation();
+ }
+
+ @Override
+ protected void copyIdToFields() {
+ this.getRTI().setTargetNamespace(this.getId().getNamespace().getDecoded());
+ this.getRTI().setName(this.getId().getXmlId().getDecoded());
+ }
+
+ @Override
+ public QName getType() {
+ return this.getRTI().getRelationshipType();
+ }
+
+ @Override
+ public Response setType(QName type) {
+ this.getRTI().setRelationshipType(type);
+ return BackendUtils.persist(this);
+ }
+
+ @Override
+ public Response setType(String typeStr) {
+ QName qname = QName.valueOf(typeStr);
+ return this.setType(qname);
+ }
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypeimplementations/relationshiptypeimplementations/RelationshipTypeImplementationsResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypeimplementations/relationshiptypeimplementations/RelationshipTypeImplementationsResource.java
new file mode 100644
index 0000000..f503a6f
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypeimplementations/relationshiptypeimplementations/RelationshipTypeImplementationsResource.java
@@ -0,0 +1,18 @@
+/*******************************************************************************
+ * 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.repository.resources.entitytypeimplementations.relationshiptypeimplementations;
+
+import org.eclipse.winery.repository.resources.AbstractComponentsWithTypeReferenceResource;
+
+public class RelationshipTypeImplementationsResource extends AbstractComponentsWithTypeReferenceResource<RelationshipTypeImplementationResource> {
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/ImplementationsOfOneType.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/ImplementationsOfOneType.java
new file mode 100644
index 0000000..5f4d06e
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/ImplementationsOfOneType.java
@@ -0,0 +1,74 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2013,2015 University of Stuttgart.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ * Oliver Kopp - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.winery.repository.resources.entitytypes;
+
+import java.util.Collection;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.eclipse.winery.common.ids.Namespace;
+import org.eclipse.winery.common.ids.definitions.TopologyGraphElementEntityTypeId;
+import org.eclipse.winery.repository.resources.admin.NamespacesResource;
+
+import com.sun.jersey.api.view.Viewable;
+
+/**
+ * specifies the methods required by implementations.jsp
+ */
+public abstract class ImplementationsOfOneType {
+
+ private final TopologyGraphElementEntityTypeId typeId;
+
+
+ public ImplementationsOfOneType(TopologyGraphElementEntityTypeId typeId) {
+ this.typeId = typeId;
+ }
+
+ public TopologyGraphElementEntityTypeId getTypeId() {
+ return this.typeId;
+ }
+
+ @GET
+ @Produces(MediaType.TEXT_HTML)
+ public Response getHTML() {
+ Viewable viewable = new Viewable("/jsp/entitytypes/implementations.jsp", this);
+ return Response.ok().entity(viewable).build();
+ }
+
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ public abstract Response getJSON();
+
+ public Collection<Namespace> getNamespaceAutocompletionList() {
+ return NamespacesResource.getNamespaces();
+ }
+
+ /**
+ * @return a list of type implementations implementing the associated node
+ * type
+ */
+ public abstract String getImplementationsTableData();
+
+ /**
+ * The string used as URL part
+ */
+ public abstract String getType();
+
+ /**
+ * The string displayed to the user
+ */
+ public abstract String getTypeStr();
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/InstanceStatesResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/InstanceStatesResource.java
new file mode 100644
index 0000000..4eaea1c
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/InstanceStatesResource.java
@@ -0,0 +1,133 @@
+/*******************************************************************************
+ * 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.repository.resources.entitytypes;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+
+import org.apache.commons.lang3.StringUtils;
+import org.eclipse.winery.model.tosca.TTopologyElementInstanceStates;
+import org.eclipse.winery.model.tosca.TTopologyElementInstanceStates.InstanceState;
+import org.eclipse.winery.common.Util;
+import org.eclipse.winery.repository.backend.BackendUtils;
+
+import com.sun.jersey.api.view.Viewable;
+
+/**
+ * Resource for instance states <br />
+ * Used by relationship types and node types
+ */
+public class InstanceStatesResource {
+
+ private TopologyGraphElementEntityTypeResource typeResource;
+ private TTopologyElementInstanceStates instanceStates;
+
+
+ /**
+ *
+ * @param instanceStates the instanceStates to manage
+ * @param typeResource the type resource, where the instance states are
+ * managed. This reference is required to fire "persist()" in
+ * case of updates
+ */
+ public InstanceStatesResource(TTopologyElementInstanceStates instanceStates, TopologyGraphElementEntityTypeResource typeResource) {
+ this.instanceStates = instanceStates;
+ this.typeResource = typeResource;
+ }
+
+ @GET
+ @Produces(MediaType.TEXT_HTML)
+ public Viewable getHTML() {
+ return new Viewable("/jsp/entitytypes/instancestates.jsp", this);
+ }
+
+ public List<String> getInstanceStates() {
+ List<InstanceState> instanceStates = this.instanceStates.getInstanceState();
+ ArrayList<String> states = new ArrayList<String>(instanceStates.size());
+ for (InstanceState instanceState : instanceStates) {
+ states.add(instanceState.getState());
+ }
+ return states;
+ }
+
+ @DELETE
+ @Path("{instanceState}")
+ public Response deleteInstanceState(@PathParam("instanceState") String instanceStateToRemove) {
+ if (StringUtils.isEmpty(instanceStateToRemove)) {
+ return Response.status(Status.BAD_REQUEST).entity("null instance to remove").build();
+ }
+ instanceStateToRemove = Util.URLdecode(instanceStateToRemove);
+
+ // InstanceState does not override "equals()", therefore we have to manually remove it
+
+ List<InstanceState> instanceStates = this.instanceStates.getInstanceState();
+ Iterator<InstanceState> iterator = instanceStates.iterator();
+ boolean found = false;
+ while (iterator.hasNext() && !found) {
+ if (iterator.next().getState().equals(instanceStateToRemove)) {
+ found = true;
+ }
+ }
+
+ if (!found) {
+ return Response.status(Status.NOT_FOUND).build();
+ }
+
+ iterator.remove();
+
+ return BackendUtils.persist(this.typeResource);
+ }
+
+ @POST
+ @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
+ public Response addInstanceState(@FormParam("state") String state) {
+ if (StringUtils.isEmpty(state)) {
+ return Response.notAcceptable(null).build();
+ }
+
+ // InstanceState does not override "equals()", therefore we have to manually check for existance
+
+ List<InstanceState> instanceStates = this.instanceStates.getInstanceState();
+ Iterator<InstanceState> iterator = instanceStates.iterator();
+ boolean found = false;
+ while (iterator.hasNext() && !found) {
+ if (iterator.next().getState().equals(state)) {
+ found = true;
+ }
+ }
+
+ if (found) {
+ // no error, just return
+ return Response.noContent().build();
+ }
+
+ InstanceState instanceState = new InstanceState();
+ instanceState.setState(state);
+ instanceStates.add(instanceState);
+
+ return BackendUtils.persist(this.typeResource);
+ }
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/TopologyGraphElementEntityTypeResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/TopologyGraphElementEntityTypeResource.java
new file mode 100644
index 0000000..6cebfe8
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/TopologyGraphElementEntityTypeResource.java
@@ -0,0 +1,23 @@
+/*******************************************************************************
+ * 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.repository.resources.entitytypes;
+
+import org.eclipse.winery.common.ids.definitions.TOSCAComponentId;
+import org.eclipse.winery.repository.resources.EntityTypeResource;
+
+public abstract class TopologyGraphElementEntityTypeResource extends EntityTypeResource {
+
+ protected TopologyGraphElementEntityTypeResource(TOSCAComponentId id) {
+ super(id);
+ }
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/artifacttypes/ArtifactTypeResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/artifacttypes/ArtifactTypeResource.java
new file mode 100644
index 0000000..232d4f9
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/artifacttypes/ArtifactTypeResource.java
@@ -0,0 +1,67 @@
+/*******************************************************************************
+ * 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.repository.resources.entitytypes.artifacttypes;
+
+import java.util.SortedSet;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Response;
+import javax.xml.namespace.QName;
+
+import org.eclipse.winery.common.constants.Namespaces;
+import org.eclipse.winery.common.ids.definitions.ArtifactTemplateId;
+import org.eclipse.winery.common.ids.definitions.ArtifactTypeId;
+import org.eclipse.winery.model.tosca.TArtifactType;
+import org.eclipse.winery.model.tosca.TExtensibleElements;
+import org.eclipse.winery.repository.backend.BackendUtils;
+import org.eclipse.winery.repository.datatypes.select2.Select2OptGroup;
+import org.eclipse.winery.repository.resources.EntityTypeResource;
+
+public class ArtifactTypeResource extends EntityTypeResource {
+
+ public ArtifactTypeResource(ArtifactTypeId id) {
+ super(id);
+ }
+
+
+ private final QName qnameFileExtension = new QName(Namespaces.TOSCA_WINERY_EXTENSIONS_NAMESPACE, "fileExtension");
+
+
+ /**
+ * @return the file extension associated with this artifact type. May be
+ * null
+ */
+ @GET
+ @Path("/fileextension")
+ public String getAssociatedFileExtension() {
+ return this.getDefinitions().getOtherAttributes().get(this.qnameFileExtension);
+ }
+
+ @PUT
+ @Path("/fileextension")
+ public Response setAssociatedFileExtension(String fileExtension) {
+ this.getDefinitions().getOtherAttributes().put(this.qnameFileExtension, fileExtension);
+ return BackendUtils.persist(this);
+ }
+
+ @Override
+ protected TExtensibleElements createNewElement() {
+ return new TArtifactType();
+ }
+
+ @Override
+ public SortedSet<Select2OptGroup> getListOfAllInstances() {
+ return this.getListOfAllInstances(ArtifactTemplateId.class);
+ }
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/artifacttypes/ArtifactTypesResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/artifacttypes/ArtifactTypesResource.java
new file mode 100644
index 0000000..b52aa31
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/artifacttypes/ArtifactTypesResource.java
@@ -0,0 +1,90 @@
+/*******************************************************************************
+ * 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.repository.resources.entitytypes.artifacttypes;
+
+import java.util.SortedSet;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+
+import org.eclipse.winery.common.ids.definitions.ArtifactTypeId;
+import org.eclipse.winery.repository.backend.Repository;
+import org.eclipse.winery.repository.resources.AbstractComponentsResource;
+
+public class ArtifactTypesResource extends AbstractComponentsResource<ArtifactTypeResource> {
+
+ // This cannot be used as the INSTANCE is per startup of the whole
+ // application
+ // We could do some checking for the number of ArtifactTypeResources or
+ // timestamp,
+ //
+ // private final HashMap<String, ArtifactTypeResource> fileExtensionMapping
+ // = new ArtifactTypesResource().getFileExtensionMapping();
+
+ /**
+ * @return a mapping from file extension to artifact type resources
+ */
+ // public HashMap<String, ArtifactTypeResource> getFileExtensionMapping() {
+ // HashMap<String, ArtifactTypeResource> res = new HashMap<String,
+ // ArtifactTypeResource>();
+ // for (ArtifactTypeResource at : this.getArtifactTypeResources()) {
+ // if (at.getAssociatedFileExtension() != null) {
+ // res.put(at.getAssociatedFileExtension(), at);
+ // }
+ // }
+ // return res;
+ // }
+
+ @GET
+ // should be "QName", but that MIME type is not available. XLink is too
+ // complicated for our setup
+ @Produces(MediaType.TEXT_PLAIN)
+ public Response getArtifactTypeQNameForExtension(@QueryParam("extension") String extension) {
+ if (extension == null) {
+ return Response.status(Status.NOT_ACCEPTABLE).build();
+ }
+ ArtifactTypeResource artifactType = this.getArtifactTypeForExtension(extension);
+ Response res;
+ if (artifactType == null) {
+ res = Response.status(Status.NOT_FOUND).build();
+ } else {
+ res = Response.ok().entity(artifactType.getId().getQName().toString()).build();
+ }
+ return res;
+ }
+
+ /**
+ * Returns the first matching ArtifactTypeResource for the given file
+ * extension. Returns null if no such ArtifactType can be found
+ *
+ * The case of the extension is ignored.
+ *
+ * This is more a DAO method
+ */
+ public ArtifactTypeResource getArtifactTypeForExtension(String extension) {
+ SortedSet<ArtifactTypeId> allArtifactTypeIds = Repository.INSTANCE.getAllTOSCAComponentIds(ArtifactTypeId.class);
+ ArtifactTypeResource res = null;
+ for (ArtifactTypeId id : allArtifactTypeIds) {
+ ArtifactTypeResource r = new ArtifactTypeResource(id);
+ if (extension.equalsIgnoreCase(r.getAssociatedFileExtension())) {
+ res = r;
+ break;
+ }
+ }
+ return res;
+ }
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/capabilitytypes/CapabilityTypeResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/capabilitytypes/CapabilityTypeResource.java
new file mode 100644
index 0000000..924efd4
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/capabilitytypes/CapabilityTypeResource.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * 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.repository.resources.entitytypes.capabilitytypes;
+
+import org.eclipse.winery.model.tosca.TCapabilityType;
+import org.eclipse.winery.model.tosca.TExtensibleElements;
+import org.eclipse.winery.common.ids.definitions.CapabilityTypeId;
+import org.eclipse.winery.repository.resources.EntityTypeResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public final class CapabilityTypeResource extends EntityTypeResource {
+
+ private static final Logger logger = LoggerFactory.getLogger(CapabilityTypeResource.class);
+
+
+ /**
+ * Constructor has to be public because of test cases
+ */
+ public CapabilityTypeResource(CapabilityTypeId id) {
+ super(id);
+ }
+
+ /**
+ * Convenience method to avoid casting at the caller's side.
+ *
+ * @return the CapabilityType object this resource is representing
+ */
+ public TCapabilityType getCapabilityType() {
+ return (TCapabilityType) this.getElement();
+ }
+
+ @Override
+ protected TExtensibleElements createNewElement() {
+ return new TCapabilityType();
+ }
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/capabilitytypes/CapabilityTypesResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/capabilitytypes/CapabilityTypesResource.java
new file mode 100644
index 0000000..a34aac2
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/capabilitytypes/CapabilityTypesResource.java
@@ -0,0 +1,22 @@
+/*******************************************************************************
+ * 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.repository.resources.entitytypes.capabilitytypes;
+
+import org.eclipse.winery.repository.resources.AbstractComponentsResource;
+
+/**
+ * Manages all capability types in all available namespaces <br />
+ * The actual implementation is done in the AbstractComponentsResource
+ */
+public class CapabilityTypesResource extends AbstractComponentsResource<CapabilityTypeResource> {
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/ImplementationsOfOneNodeTypeResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/ImplementationsOfOneNodeTypeResource.java
new file mode 100644
index 0000000..63d483d
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/ImplementationsOfOneNodeTypeResource.java
@@ -0,0 +1,101 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2013,2015 University of Stuttgart.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ * Oliver Kopp - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.winery.repository.resources.entitytypes.nodetypes;
+
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.Collection;
+
+import javax.ws.rs.core.Response;
+import javax.xml.namespace.QName;
+
+import org.eclipse.winery.common.ids.definitions.NodeTypeId;
+import org.eclipse.winery.common.ids.definitions.NodeTypeImplementationId;
+import org.eclipse.winery.repository.backend.BackendUtils;
+import org.eclipse.winery.repository.resources.entitytypes.ImplementationsOfOneType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.fasterxml.jackson.core.JsonFactory;
+import com.fasterxml.jackson.core.JsonGenerator;
+
+public class ImplementationsOfOneNodeTypeResource extends ImplementationsOfOneType {
+
+ private static final Logger logger = LoggerFactory.getLogger(ImplementationsOfOneNodeTypeResource.class);
+
+
+ /**
+ * The constructor is different from the usual constructors as this resource
+ * does NOT store own data, but retrieves its data solely from the
+ * associated node type
+ *
+ * @param nodeTypeId the node type id, where this list of implementations
+ * belongs to
+ */
+ public ImplementationsOfOneNodeTypeResource(NodeTypeId nodeTypeId) {
+ super(nodeTypeId);
+ }
+
+ /**
+ * required by implementations.jsp
+ *
+ * @return for each node type implementation implementing the associated
+ * node type
+ */
+ @Override
+ public String getImplementationsTableData() {
+ String res;
+ JsonFactory jsonFactory = new JsonFactory();
+ StringWriter tableDataSW = new StringWriter();
+ try {
+ JsonGenerator jGenerator = jsonFactory.createGenerator(tableDataSW);
+ jGenerator.writeStartArray();
+
+ Collection<NodeTypeImplementationId> allNodeTypeImplementations = BackendUtils.getAllElementsRelatedWithATypeAttribute(NodeTypeImplementationId.class, this.getTypeId().getQName());
+ for (NodeTypeImplementationId ntiID : allNodeTypeImplementations) {
+ jGenerator.writeStartArray();
+ jGenerator.writeString(ntiID.getNamespace().getDecoded());
+ jGenerator.writeString(ntiID.getXmlId().getDecoded());
+ jGenerator.writeEndArray();
+ }
+ jGenerator.writeEndArray();
+ jGenerator.close();
+ tableDataSW.close();
+ res = tableDataSW.toString();
+ } catch (Exception e) {
+ ImplementationsOfOneNodeTypeResource.logger.error(e.getMessage(), e);
+ res = "[]";
+ }
+ return res;
+ }
+
+ @Override
+ public String getType() {
+ return "nodetype";
+ }
+
+ @Override
+ public String getTypeStr() {
+ return "Node Type";
+ }
+
+ @Override
+ public Response getJSON() {
+ Collection<NodeTypeImplementationId> allImplementations = BackendUtils.getAllElementsRelatedWithATypeAttribute(NodeTypeImplementationId.class, this.getTypeId().getQName());
+ ArrayList<QName> res = new ArrayList<QName>(allImplementations.size());
+ for (NodeTypeImplementationId id : allImplementations) {
+ res.add(id.getQName());
+ }
+ return Response.ok().entity(res).build();
+ }
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/NodeTypeResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/NodeTypeResource.java
new file mode 100644
index 0000000..6c573a5
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/NodeTypeResource.java
@@ -0,0 +1,105 @@
+/*******************************************************************************
+ * 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.repository.resources.entitytypes.nodetypes;
+
+import javax.ws.rs.Path;
+
+import org.eclipse.winery.model.tosca.TExtensibleElements;
+import org.eclipse.winery.model.tosca.TNodeType;
+import org.eclipse.winery.model.tosca.TNodeType.CapabilityDefinitions;
+import org.eclipse.winery.model.tosca.TNodeType.Interfaces;
+import org.eclipse.winery.model.tosca.TNodeType.RequirementDefinitions;
+import org.eclipse.winery.model.tosca.TTopologyElementInstanceStates;
+import org.eclipse.winery.common.ids.definitions.NodeTypeId;
+import org.eclipse.winery.repository.resources.entitytypes.InstanceStatesResource;
+import org.eclipse.winery.repository.resources.entitytypes.TopologyGraphElementEntityTypeResource;
+import org.eclipse.winery.repository.resources.entitytypes.nodetypes.reqandcapdefs.CapabilityDefinitionsResource;
+import org.eclipse.winery.repository.resources.entitytypes.nodetypes.reqandcapdefs.RequirementDefinitionsResource;
+import org.eclipse.winery.repository.resources.interfaces.InterfacesResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class NodeTypeResource extends TopologyGraphElementEntityTypeResource {
+
+ private static final Logger logger = LoggerFactory.getLogger(NodeTypeResource.class);
+
+
+ public NodeTypeResource(NodeTypeId id) {
+ super(id);
+ }
+
+ /**
+ * Convenience method to avoid casting at the caller's side.
+ */
+ public TNodeType getNodeType() {
+ return (TNodeType) this.getElement();
+ }
+
+ /** sub-resources **/
+
+ @Path("implementations/")
+ public ImplementationsOfOneNodeTypeResource getImplementations() {
+ return new ImplementationsOfOneNodeTypeResource((NodeTypeId) this.id);
+ }
+
+ @Path("instancestates/")
+ public InstanceStatesResource getInstanceStatesResource() {
+ TTopologyElementInstanceStates instanceStates = this.getNodeType().getInstanceStates();
+ if (instanceStates == null) {
+ // if an explicit (empty) list does not exist, create it
+ instanceStates = new TTopologyElementInstanceStates();
+ this.getNodeType().setInstanceStates(instanceStates);
+ }
+ return new InstanceStatesResource(instanceStates, this);
+ }
+
+ @Path("interfaces/")
+ public InterfacesResource getInterfaces() {
+ Interfaces interfaces = this.getNodeType().getInterfaces();
+ if (interfaces == null) {
+ interfaces = new Interfaces();
+ this.getNodeType().setInterfaces(interfaces);
+ }
+ return new InterfacesResource(null, interfaces.getInterface(), this);
+ }
+
+ @Path("requirementdefinitions/")
+ public RequirementDefinitionsResource getRequirementDefinitions() {
+ RequirementDefinitions definitions = this.getNodeType().getRequirementDefinitions();
+ if (definitions == null) {
+ definitions = new RequirementDefinitions();
+ this.getNodeType().setRequirementDefinitions(definitions);
+ }
+ return new RequirementDefinitionsResource(this, definitions.getRequirementDefinition());
+ }
+
+ @Path("capabilitydefinitions/")
+ public CapabilityDefinitionsResource getCapabilityDefinitions() {
+ CapabilityDefinitions definitions = this.getNodeType().getCapabilityDefinitions();
+ if (definitions == null) {
+ definitions = new CapabilityDefinitions();
+ this.getNodeType().setCapabilityDefinitions(definitions);
+ }
+ return new CapabilityDefinitionsResource(this, definitions.getCapabilityDefinition());
+ }
+
+ @Path("visualappearance/")
+ public VisualAppearanceResource getVisualAppearanceResource() {
+ return new VisualAppearanceResource(this, this.getElement().getOtherAttributes(), (NodeTypeId) this.id);
+ }
+
+ @Override
+ protected TExtensibleElements createNewElement() {
+ return new TNodeType();
+ }
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/NodeTypesResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/NodeTypesResource.java
new file mode 100644
index 0000000..798e5a5
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/NodeTypesResource.java
@@ -0,0 +1,22 @@
+/*******************************************************************************
+ * 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.repository.resources.entitytypes.nodetypes;
+
+import org.eclipse.winery.repository.resources.AbstractComponentsResource;
+
+/**
+ * Manages all nodetypes in all available namespaces <br />
+ * The actual implementation is done in the AbstractComponentsResource
+ */
+public class NodeTypesResource extends AbstractComponentsResource<NodeTypeResource> {
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/VisualAppearanceResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/VisualAppearanceResource.java
new file mode 100644
index 0000000..d897efe
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/VisualAppearanceResource.java
@@ -0,0 +1,84 @@
+/*******************************************************************************
+ * 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.repository.resources.entitytypes.nodetypes;
+
+import java.io.InputStream;
+import java.util.Map;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.GET;
+import javax.ws.rs.HeaderParam;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.xml.namespace.QName;
+
+import org.eclipse.winery.common.constants.QNames;
+import org.eclipse.winery.common.ids.definitions.NodeTypeId;
+import org.eclipse.winery.repository.backend.BackendUtils;
+import org.eclipse.winery.repository.backend.constants.Filename;
+import org.eclipse.winery.repository.datatypes.ids.elements.VisualAppearanceId;
+import org.eclipse.winery.repository.resources.GenericVisualAppearanceResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.sun.jersey.api.view.Viewable;
+import com.sun.jersey.multipart.FormDataBodyPart;
+import com.sun.jersey.multipart.FormDataParam;
+
+public class VisualAppearanceResource extends GenericVisualAppearanceResource {
+
+ private static final Logger logger = LoggerFactory.getLogger(VisualAppearanceResource.class);
+
+
+ public VisualAppearanceResource(NodeTypeResource res, Map<QName, String> map, NodeTypeId parentId) {
+ super(res, map, new VisualAppearanceId(parentId));
+ }
+
+ @GET
+ @Produces(MediaType.TEXT_HTML)
+ public Response getHTML() {
+ Viewable viewable = new Viewable("/jsp/entitytypes/nodetypes/visualappearance.jsp", this);
+ return Response.ok().entity(viewable).build();
+ }
+
+ @GET
+ @Path("50x50")
+ public Response get50x50Image(@HeaderParam("If-Modified-Since") String modified) {
+ return this.getImage(Filename.FILENAME_BIG_ICON, modified);
+ }
+
+ @PUT
+ @Path("50x50")
+ @Consumes(MediaType.MULTIPART_FORM_DATA)
+ public Response post50x50Image(@FormDataParam("file") InputStream uploadedInputStream, @FormDataParam("file") FormDataBodyPart body) {
+ return this.putImage(Filename.FILENAME_BIG_ICON, uploadedInputStream, body.getMediaType());
+ }
+
+ @GET
+ @Path("bordercolor")
+ public String getBorderColor() {
+ return BackendUtils.getColorAndSetDefaultIfNotExisting(this.getId().getParent().getXmlId().getDecoded(), QNames.QNAME_BORDER_COLOR, this.otherAttributes, this.res);
+ }
+
+ @PUT
+ @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
+ @Path("bordercolor")
+ public Response putBorderColor(@FormParam("color") String color) {
+ this.otherAttributes.put(QNames.QNAME_BORDER_COLOR, color);
+ return BackendUtils.persist(this.res);
+ }
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/reqandcapdefs/AbstractReqOrCapDefResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/reqandcapdefs/AbstractReqOrCapDefResource.java
new file mode 100644
index 0000000..b7eea92
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/reqandcapdefs/AbstractReqOrCapDefResource.java
@@ -0,0 +1,177 @@
+/*******************************************************************************
+ * 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.repository.resources.entitytypes.nodetypes.reqandcapdefs;
+
+import java.lang.reflect.Method;
+import java.util.List;
+
+import javax.ws.rs.FormParam;
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.xml.namespace.QName;
+
+import org.eclipse.winery.model.tosca.TCapabilityDefinition;
+import org.eclipse.winery.model.tosca.TConstraint;
+import org.eclipse.winery.model.tosca.TRequirementDefinition;
+import org.eclipse.winery.repository.backend.BackendUtils;
+import org.eclipse.winery.repository.resources.ConstraintsResource;
+import org.eclipse.winery.repository.resources._support.collections.IIdDetermination;
+import org.eclipse.winery.repository.resources._support.collections.withid.EntityWithIdResource;
+import org.eclipse.winery.repository.resources.entitytypes.nodetypes.NodeTypeResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Bundles common properties of TRequirementDefinition and TCapabilityDefinition
+ *
+ * We agreed in the project not to modify org.eclipse.winery.model.tosca.
+ * Therefore, this resource models the common properties of a
+ * TRequirementDefinition and a TCapabilityDefinition
+ */
+public abstract class AbstractReqOrCapDefResource<ReqOrCapDef> extends EntityWithIdResource<ReqOrCapDef> implements IIdDetermination<ReqOrCapDef> {
+
+ private static final Logger logger = LoggerFactory.getLogger(AbstractReqOrCapDefResource.class);
+
+ protected NodeTypeResource parent;
+
+ // the capability or the requirement
+ private Object reqOrCapDef;
+
+ private List<TConstraint> constraints;
+
+
+ /**
+ * @param constraints additional parameter (in comparison to the constructor
+ * of EntityWithIdResource) as we require that sublist for the
+ * constrinats sub resource
+ */
+ public AbstractReqOrCapDefResource(IIdDetermination<ReqOrCapDef> idDetermination, ReqOrCapDef reqOrCapDef, int idx, List<ReqOrCapDef> list, NodeTypeResource res, List<TConstraint> constraints) {
+ super(idDetermination, reqOrCapDef, idx, list, res);
+ assert ((reqOrCapDef instanceof TRequirementDefinition) || (reqOrCapDef instanceof TCapabilityDefinition));
+ this.parent = res;
+ this.reqOrCapDef = reqOrCapDef;
+ this.constraints = constraints;
+ }
+
+ @GET
+ @Path("name")
+ public String getName() {
+ return (String) this.invokeGetter("getName");
+ }
+
+ static String getName(Object reqOrCapDef) {
+ return (String) AbstractReqOrCapDefResource.invokeGetter(reqOrCapDef, "getName");
+ }
+
+ @GET
+ @Path("lowerbound")
+ public int getLowerBound() {
+ return (int) this.invokeGetter("getLowerBound");
+ }
+
+ @GET
+ @Path("upperbound")
+ public String getUpperBound() {
+ return (String) this.invokeGetter("getUpperBound");
+ }
+
+ @PUT
+ @Path("name")
+ public Response setName(@FormParam(value = "name") String name) {
+ // TODO: type check - see also min/max Instance of a node template
+ this.invokeSetter("setName", name);
+ return BackendUtils.persist(this.parent);
+ }
+
+ @PUT
+ @Path("lowerbound")
+ public Response setLowerBound(@FormParam(value = "lowerbound") String value) {
+ // TODO: type check
+ this.invokeSetter("setLowerBound", value);
+ return BackendUtils.persist(this.parent);
+ }
+
+ @PUT
+ @Path("upperbound")
+ public Response setUpperBound(@FormParam(value = "upperbound") String value) {
+ // TODO: type check
+ this.invokeSetter("setUpperBound", value);
+ return BackendUtils.persist(this.parent);
+ }
+
+ @Path("constraints/")
+ public ConstraintsResource getConstraintsResource() {
+ return new ConstraintsResource(this.constraints, this.parent);
+ }
+
+ private static Object invokeGetter(Object reqOrCapDef, String getterName) {
+ Method method;
+ Object res;
+ try {
+ method = reqOrCapDef.getClass().getMethod(getterName);
+ res = method.invoke(reqOrCapDef);
+ } catch (Exception e) {
+ AbstractReqOrCapDefResource.logger.error("Could not invoke getter {}", getterName, e);
+ throw new IllegalStateException(e);
+ }
+ return res;
+ }
+
+ private Object invokeGetter(String getterName) {
+ return AbstractReqOrCapDefResource.invokeGetter(this.reqOrCapDef, getterName);
+ }
+
+ /**
+ * Quick hack method for RequirementOrCapabilityDefinitionsResource
+ */
+ static void invokeSetter(Object reqOrCapDef, String setterName, Object value) {
+ Method method;
+ try {
+ method = reqOrCapDef.getClass().getMethod(setterName, value.getClass());
+ method.invoke(reqOrCapDef, value);
+ } catch (Exception e) {
+ AbstractReqOrCapDefResource.logger.error("Could not invoke setter {}", setterName, e);
+ throw new IllegalStateException(e);
+ }
+ }
+
+ private void invokeSetter(String setterName, Object value) {
+ AbstractReqOrCapDefResource.invokeSetter(this.reqOrCapDef, setterName, value);
+ }
+
+ @GET
+ @Path("type")
+ @Produces(MediaType.TEXT_PLAIN)
+ public String getTypeAsString() {
+ return this.getType().toString();
+ }
+
+ /**
+ * required by the JSP.
+ *
+ * Therefore, we have two getters for the type: QName for the JSP and String
+ * for REST clients
+ */
+ public abstract QName getType();
+
+ /**
+ * Required by reqandcapdefs.jsp
+ */
+ public Object getDef() {
+ return this.reqOrCapDef;
+ }
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/reqandcapdefs/CapabilityDefinitionResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/reqandcapdefs/CapabilityDefinitionResource.java
new file mode 100644
index 0000000..0fd3bd3
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/reqandcapdefs/CapabilityDefinitionResource.java
@@ -0,0 +1,92 @@
+/*******************************************************************************
+ * 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.repository.resources.entitytypes.nodetypes.reqandcapdefs;
+
+import java.util.List;
+
+import javax.ws.rs.FormParam;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Response;
+import javax.xml.namespace.QName;
+
+import org.eclipse.winery.model.tosca.TCapabilityDefinition;
+import org.eclipse.winery.model.tosca.TCapabilityDefinition.Constraints;
+import org.eclipse.winery.model.tosca.TConstraint;
+import org.eclipse.winery.repository.backend.BackendUtils;
+import org.eclipse.winery.repository.resources.AbstractComponentInstanceResource;
+import org.eclipse.winery.repository.resources._support.IPersistable;
+import org.eclipse.winery.repository.resources._support.collections.IIdDetermination;
+import org.eclipse.winery.repository.resources.entitytypes.nodetypes.NodeTypeResource;
+
+/**
+ * Implementation similar to RequirementDefinitionResource, but with
+ * TCapabilityDefinition instead of TRequirementDefinition
+ */
+public final class CapabilityDefinitionResource extends AbstractReqOrCapDefResource<TCapabilityDefinition> {
+
+ private TCapabilityDefinition capDef;
+
+
+ /**
+ * Constructor has to follow the pattern of EnetityTResource as the
+ * constructor is invoked by reflection in EntityWithIdcollectionResource
+ *
+ * @param res the resource this req def is nested in. Has to be of Type
+ * "NodeTypeResource". Due to the implementation of
+ * org.eclipse.winery .repository.resources._support.collections.
+ * withid.EntityWithIdCollectionResource
+ * .getEntityResourceInstance(EntityT, int), we have to use
+ * "AbstractComponentInstanceResource" as type
+ */
+ public CapabilityDefinitionResource(IIdDetermination<TCapabilityDefinition> idDetermination, TCapabilityDefinition capDef, int idx, List<TCapabilityDefinition> list, AbstractComponentInstanceResource res) {
+ super(idDetermination, capDef, idx, list, (NodeTypeResource) res, CapabilityDefinitionResource.getConstraints(capDef));
+ this.capDef = capDef;
+ }
+
+ /**
+ * Quick hack to avoid internal server error
+ */
+ public CapabilityDefinitionResource(IIdDetermination<TCapabilityDefinition> idDetermination, TCapabilityDefinition capDef, int idx, List<TCapabilityDefinition> list, IPersistable res) {
+ this(idDetermination, capDef, idx, list, (AbstractComponentInstanceResource) res);
+ }
+
+ /**
+ * Fetch the list of constraints from the given definition. If the list does
+ * not exist, the list is created an stored in the given capDef
+ */
+ public static List<TConstraint> getConstraints(TCapabilityDefinition capDef) {
+ Constraints constraints = capDef.getConstraints();
+ if (constraints == null) {
+ constraints = new Constraints();
+ capDef.setConstraints(constraints);
+ }
+ return constraints.getConstraint();
+ }
+
+ public QName getType() {
+ return this.capDef.getCapabilityType();
+ }
+
+ @PUT
+ @Path("type")
+ public Response setType(@FormParam(value = "type") String value) {
+ QName qname = QName.valueOf(value);
+ this.capDef.setCapabilityType(qname);
+ return BackendUtils.persist(this.parent);
+ }
+
+ @Override
+ public String getId(TCapabilityDefinition e) {
+ return e.getName();
+ }
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/reqandcapdefs/CapabilityDefinitionsResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/reqandcapdefs/CapabilityDefinitionsResource.java
new file mode 100644
index 0000000..d93edb4
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/reqandcapdefs/CapabilityDefinitionsResource.java
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * 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.repository.resources.entitytypes.nodetypes.reqandcapdefs;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.SortedSet;
+
+import javax.xml.namespace.QName;
+
+import org.eclipse.winery.common.ids.definitions.CapabilityTypeId;
+import org.eclipse.winery.model.tosca.TCapabilityDefinition;
+import org.eclipse.winery.repository.backend.BackendUtils;
+import org.eclipse.winery.repository.backend.Repository;
+import org.eclipse.winery.repository.resources.entitytypes.nodetypes.NodeTypeResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.sun.jersey.api.view.Viewable;
+
+public class CapabilityDefinitionsResource extends RequirementOrCapabilityDefinitionsResource<CapabilityDefinitionResource, TCapabilityDefinition> {
+
+ private static final Logger logger = LoggerFactory.getLogger(CapabilityDefinitionsResource.class);
+
+
+ public CapabilityDefinitionsResource(NodeTypeResource res, List<TCapabilityDefinition> defs) {
+ super(CapabilityDefinitionResource.class, TCapabilityDefinition.class, defs, res);
+ }
+
+ @Override
+ public Viewable getHTML() {
+ return new Viewable("/jsp/entitytypes/nodetypes/reqandcapdefs/capdefs.jsp", this);
+ }
+
+ @Override
+ public Collection<QName> getAllTypes() {
+ SortedSet<CapabilityTypeId> allTOSCAComponentIds = Repository.INSTANCE.getAllTOSCAComponentIds(CapabilityTypeId.class);
+ return BackendUtils.convertTOSCAComponentIdCollectionToQNameCollection(allTOSCAComponentIds);
+ }
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/reqandcapdefs/RequirementDefinitionResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/reqandcapdefs/RequirementDefinitionResource.java
new file mode 100644
index 0000000..aeee000
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/reqandcapdefs/RequirementDefinitionResource.java
@@ -0,0 +1,89 @@
+/*******************************************************************************
+ * 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.repository.resources.entitytypes.nodetypes.reqandcapdefs;
+
+import java.util.List;
+
+import javax.ws.rs.FormParam;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Response;
+import javax.xml.namespace.QName;
+
+import org.eclipse.winery.model.tosca.TConstraint;
+import org.eclipse.winery.model.tosca.TRequirementDefinition;
+import org.eclipse.winery.model.tosca.TRequirementDefinition.Constraints;
+import org.eclipse.winery.repository.backend.BackendUtils;
+import org.eclipse.winery.repository.resources.AbstractComponentInstanceResource;
+import org.eclipse.winery.repository.resources._support.IPersistable;
+import org.eclipse.winery.repository.resources._support.collections.IIdDetermination;
+import org.eclipse.winery.repository.resources.entitytypes.nodetypes.NodeTypeResource;
+
+public final class RequirementDefinitionResource extends AbstractReqOrCapDefResource<TRequirementDefinition> {
+
+ private TRequirementDefinition reqDef;
+
+
+ /**
+ * Constructor has to follow the pattern of EnetityTResource as the
+ * constructor is invoked by reflection in EntityWithIdcollectionResource
+ *
+ * @param res the resource this req def is nested in. Has to be of Type
+ * "NodeTypeResource". Due to the implementation of
+ * org.eclipse.winery .repository.resources._support.collections.
+ * withid.EntityWithIdCollectionResource
+ * .getEntityResourceInstance(EntityT, int), we have to use
+ * "AbstractComponentInstanceResource" as type
+ */
+ public RequirementDefinitionResource(IIdDetermination<TRequirementDefinition> idDetermination, TRequirementDefinition reqDef, int idx, List<TRequirementDefinition> list, AbstractComponentInstanceResource res) {
+ super(idDetermination, reqDef, idx, list, (NodeTypeResource) res, RequirementDefinitionResource.getConstraints(reqDef));
+ this.reqDef = reqDef;
+ }
+
+ /**
+ * Quick fix to avoid internal server error when opening
+ * RequirementDefinitions Tab
+ */
+ public RequirementDefinitionResource(IIdDetermination<TRequirementDefinition> idDetermination, TRequirementDefinition reqDef, int idx, List<TRequirementDefinition> list, IPersistable res) {
+ this(idDetermination, reqDef, idx, list, (AbstractComponentInstanceResource) res);
+ }
+
+ /**
+ * Fetch the list of constraints from the given definition. If the list does
+ * not exist, the list is created an stored in the given def
+ */
+ public static List<TConstraint> getConstraints(TRequirementDefinition def) {
+ Constraints constraints = def.getConstraints();
+ if (constraints == null) {
+ constraints = new Constraints();
+ def.setConstraints(constraints);
+ }
+ return constraints.getConstraint();
+ }
+
+ public QName getType() {
+ return this.reqDef.getRequirementType();
+ }
+
+ @PUT
+ @Path("type")
+ public Response setType(@FormParam(value = "type") String value) {
+ QName qname = QName.valueOf(value);
+ this.reqDef.setRequirementType(qname);
+ return BackendUtils.persist(this.parent);
+ }
+
+ @Override
+ public String getId(TRequirementDefinition e) {
+ return e.getName();
+ }
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/reqandcapdefs/RequirementDefinitionsResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/reqandcapdefs/RequirementDefinitionsResource.java
new file mode 100644
index 0000000..62db596
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/reqandcapdefs/RequirementDefinitionsResource.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * 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.repository.resources.entitytypes.nodetypes.reqandcapdefs;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.SortedSet;
+
+import javax.xml.namespace.QName;
+
+import org.eclipse.winery.common.ids.definitions.RequirementTypeId;
+import org.eclipse.winery.model.tosca.TRequirementDefinition;
+import org.eclipse.winery.repository.backend.BackendUtils;
+import org.eclipse.winery.repository.backend.Repository;
+import org.eclipse.winery.repository.resources.entitytypes.nodetypes.NodeTypeResource;
+
+import com.sun.jersey.api.view.Viewable;
+
+public class RequirementDefinitionsResource extends RequirementOrCapabilityDefinitionsResource<RequirementDefinitionResource, TRequirementDefinition> {
+
+ public RequirementDefinitionsResource(NodeTypeResource res, List<TRequirementDefinition> defs) {
+ super(RequirementDefinitionResource.class, TRequirementDefinition.class, defs, res);
+ }
+
+ @Override
+ public Viewable getHTML() {
+ return new Viewable("/jsp/entitytypes/nodetypes/reqandcapdefs/reqdefs.jsp", this);
+ }
+
+ @Override
+ public Collection<QName> getAllTypes() {
+ SortedSet<RequirementTypeId> allTOSCAComponentIds = Repository.INSTANCE.getAllTOSCAComponentIds(RequirementTypeId.class);
+ return BackendUtils.convertTOSCAComponentIdCollectionToQNameCollection(allTOSCAComponentIds);
+ }
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/reqandcapdefs/RequirementOrCapabilityDefinitionsResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/reqandcapdefs/RequirementOrCapabilityDefinitionsResource.java
new file mode 100644
index 0000000..0c6936e
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/reqandcapdefs/RequirementOrCapabilityDefinitionsResource.java
@@ -0,0 +1,131 @@
+/*******************************************************************************
+ * 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.repository.resources.entitytypes.nodetypes.reqandcapdefs;
+
+import java.util.Collection;
+import java.util.List;
+
+import javax.ws.rs.FormParam;
+import javax.ws.rs.POST;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+import javax.xml.namespace.QName;
+
+import org.apache.commons.lang3.StringUtils;
+import org.eclipse.winery.model.tosca.TCapabilityDefinition;
+import org.eclipse.winery.model.tosca.TRequirementDefinition;
+import org.eclipse.winery.repository.backend.BackendUtils;
+import org.eclipse.winery.repository.resources._support.collections.withid.EntityWithIdCollectionResource;
+import org.eclipse.winery.repository.resources.entitytypes.nodetypes.NodeTypeResource;
+
+import com.sun.jersey.api.view.Viewable;
+
+/**
+ * This superclass has only a few methods as we cannot easily abstract from the
+ * subclasses: We would need Java reflection to invoke "getName" (to get the
+ * subresource). The hope is that this copy'n'paste programming will not
+ * introduce bugs when changing childs
+ *
+ * We try to abstract from the problems by using generics and reflections
+ *
+ * @param <ReqDefOrCapDef> TRequirementDefinition or TCapabilityDefinition
+ * @param <ReqDefOrCapDefResource> the resource managing ReqDefOrCapDef
+ */
+public abstract class RequirementOrCapabilityDefinitionsResource<ReqDefOrCapDefResource extends AbstractReqOrCapDefResource<ReqDefOrCapDef>, ReqDefOrCapDef> extends EntityWithIdCollectionResource<ReqDefOrCapDefResource, ReqDefOrCapDef> {
+
+ protected final NodeTypeResource res;
+
+
+ public RequirementOrCapabilityDefinitionsResource(Class<ReqDefOrCapDefResource> entityResourceTClazz, Class<ReqDefOrCapDef> entityTClazz, List<ReqDefOrCapDef> list, NodeTypeResource res) {
+ super(entityResourceTClazz, entityTClazz, list, res);
+ this.res = res;
+ }
+
+ @Override
+ public abstract Viewable getHTML();
+
+ /**
+ * @return collection of all available types
+ */
+ public abstract Collection<QName> getAllTypes();
+
+ @POST
+ // As there is no supertype of TCapabilityType and TRequirementType containing the common attributes, we have to rely on unchecked casts
+ @SuppressWarnings("unchecked")
+ public Response onPost(@FormParam("name") String name, @FormParam("type") String type, @FormParam("lowerbound") String lowerBound, @FormParam("upperbound") String upperbound) {
+ if (StringUtils.isEmpty(name)) {
+ return Response.status(Status.BAD_REQUEST).entity("Name has to be provided").build();
+ }
+ if (StringUtils.isEmpty(type)) {
+ return Response.status(Status.BAD_REQUEST).entity("Type has to be provided").build();
+ }
+
+ int lbound = 1;
+ if (!StringUtils.isEmpty(lowerBound)) {
+ try {
+ lbound = Integer.parseInt(lowerBound);
+ } catch (NumberFormatException e) {
+ return Response.status(Status.BAD_REQUEST).entity("Bad format of lowerbound: " + e.getMessage()).build();
+ }
+ }
+
+ String ubound = "1";
+ if (!StringUtils.isEmpty(upperbound)) {
+ ubound = upperbound;
+ }
+
+ // we also support replacement of existing requirements
+ // therefore, we loop through the existing requirements
+ int idx = -1;
+ boolean found = false;
+ for (ReqDefOrCapDef d : this.list) {
+ idx++;
+ if (this.getId(d).equals(name)) {
+ found = true;
+ break;
+ }
+ }
+
+ QName typeQName = QName.valueOf(type);
+ // Create object and put type in it
+ ReqDefOrCapDef def;
+ if (this instanceof CapabilityDefinitionsResource) {
+ def = (ReqDefOrCapDef) new TCapabilityDefinition();
+ ((TCapabilityDefinition) def).setCapabilityType(typeQName);
+ } else {
+ assert (this instanceof RequirementDefinitionsResource);
+ def = (ReqDefOrCapDef) new TRequirementDefinition();
+ ((TRequirementDefinition) def).setRequirementType(typeQName);
+ }
+
+ // copy all other data into object
+ AbstractReqOrCapDefResource.invokeSetter(def, "setName", name);
+ AbstractReqOrCapDefResource.invokeSetter(def, "setLowerBound", lbound);
+ AbstractReqOrCapDefResource.invokeSetter(def, "setUpperBound", ubound);
+
+ if (found) {
+ // replace element
+ this.list.set(idx, def);
+ } else {
+ // add new element
+ this.list.add(def);
+ }
+
+ Response r = BackendUtils.persist(this.res);
+ return r;
+ }
+
+ @Override
+ public String getId(ReqDefOrCapDef reqDefOrCapDef) {
+ return AbstractReqOrCapDefResource.getName(reqDefOrCapDef);
+ }
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/package-info.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/package-info.java
new file mode 100644
index 0000000..6fbbc5a
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/package-info.java
@@ -0,0 +1,17 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+/**
+ * The sub packages of this package contains all resources, which are derived
+ * from tEntityType
+ */
+package org.eclipse.winery.repository.resources.entitytypes;
+
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/policytypes/AppliesToResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/policytypes/AppliesToResource.java
new file mode 100644
index 0000000..0e4b560
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/policytypes/AppliesToResource.java
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2013 University of Stuttgart.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ * Oliver Kopp - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.winery.repository.resources.entitytypes.policytypes;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+import org.eclipse.winery.model.tosca.TPolicyType;
+
+import com.sun.jersey.api.view.Viewable;
+
+public class AppliesToResource {
+
+ private PolicyTypeResource policyTypeResource;
+
+
+ public AppliesToResource(PolicyTypeResource policyTypeResource) {
+ this.policyTypeResource = policyTypeResource;
+ }
+
+ @GET
+ @Produces(MediaType.TEXT_HTML)
+ public Viewable getHTML() {
+ return new Viewable("/jsp/entitytypes/policytypes/appliesto.jsp", this);
+ }
+
+ public TPolicyType getPolicyType() {
+ return this.policyTypeResource.getPolicyType();
+ }
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/policytypes/LanguageResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/policytypes/LanguageResource.java
new file mode 100644
index 0000000..036cc73
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/policytypes/LanguageResource.java
@@ -0,0 +1,28 @@
+package org.eclipse.winery.repository.resources.entitytypes.policytypes;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+import com.sun.jersey.api.view.Viewable;
+
+public class LanguageResource {
+
+ private PolicyTypeResource policyTypeResource;
+
+
+ public LanguageResource(PolicyTypeResource policyTypeResource) {
+ this.policyTypeResource = policyTypeResource;
+ }
+
+ @GET
+ @Produces(MediaType.TEXT_HTML)
+ public Viewable getHTML() {
+ return new Viewable("/jsp/entitytypes/policytypes/language.jsp", this);
+ }
+
+ public String getLanguage() {
+ return this.policyTypeResource.getPolicyType().getPolicyLanguage();
+ }
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/policytypes/PolicyTypeResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/policytypes/PolicyTypeResource.java
new file mode 100644
index 0000000..62c728a
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/policytypes/PolicyTypeResource.java
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * 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.repository.resources.entitytypes.policytypes;
+
+import java.util.SortedSet;
+
+import javax.ws.rs.Path;
+
+import org.eclipse.winery.common.ids.definitions.PolicyTemplateId;
+import org.eclipse.winery.common.ids.definitions.PolicyTypeId;
+import org.eclipse.winery.model.tosca.TExtensibleElements;
+import org.eclipse.winery.model.tosca.TPolicyType;
+import org.eclipse.winery.repository.datatypes.select2.Select2OptGroup;
+import org.eclipse.winery.repository.resources.EntityTypeResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public final class PolicyTypeResource extends EntityTypeResource {
+
+ private static final Logger logger = LoggerFactory.getLogger(PolicyTypeResource.class);
+
+
+ /**
+ * Constructor has to be public because of test cases
+ */
+ public PolicyTypeResource(PolicyTypeId id) {
+ super(id);
+ }
+
+ /**
+ * Convenience method to avoid casting at the caller's side.
+ */
+ public TPolicyType getPolicyType() {
+ return (TPolicyType) this.getElement();
+ }
+
+ @Override
+ protected TExtensibleElements createNewElement() {
+ return new TPolicyType();
+ }
+
+ @Path("appliesto/")
+ public AppliesToResource getAppliesTo() {
+ return new AppliesToResource(this);
+ }
+
+ @Path("language/")
+ public LanguageResource getLanguage() {
+ return new LanguageResource(this);
+ }
+
+ @Override
+ public SortedSet<Select2OptGroup> getListOfAllInstances() {
+ return this.getListOfAllInstances(PolicyTemplateId.class);
+ }
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/policytypes/PolicyTypesResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/policytypes/PolicyTypesResource.java
new file mode 100644
index 0000000..17d4db0
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/policytypes/PolicyTypesResource.java
@@ -0,0 +1,22 @@
+/*******************************************************************************
+ * 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.repository.resources.entitytypes.policytypes;
+
+import org.eclipse.winery.repository.resources.AbstractComponentsResource;
+
+/**
+ * Manages all policy types in all available namespaces <br />
+ * The actual implementation is done in the AbstractComponentsResource
+ */
+public class PolicyTypesResource extends AbstractComponentsResource<PolicyTypeResource> {
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/properties/JSPData.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/properties/JSPData.java
new file mode 100644
index 0000000..a5338ed
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/properties/JSPData.java
@@ -0,0 +1,85 @@
+/*******************************************************************************
+ * 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.repository.resources.entitytypes.properties;
+
+import java.util.List;
+
+import org.eclipse.winery.common.propertydefinitionkv.PropertyDefinitionKV;
+import org.eclipse.winery.common.propertydefinitionkv.WinerysPropertiesDefinition;
+import org.eclipse.winery.model.tosca.TEntityType;
+
+/**
+ * Collects data used by the JSP
+ */
+public class JSPData {
+
+ // FIXME: this is a quick hack and provides a fixed list of available
+ // property types only. This list has to be made dynamically updatable (and offer plugins to edit)
+ // currently only http://www.w3.org/TR/2001/REC-xmlschema-2-20010502/#built-in-datatypes are supported
+ private static final String[] availablePropertyTypes = {"xsd:string", "xsd:boolean", "xsd:decimal", "xsd:float", "xsd:anyURI", "xsd:QName"};
+
+ private final PropertiesDefinitionResource propertiesDefinitionResource;
+ private final WinerysPropertiesDefinition wpd;
+
+
+ public JSPData(PropertiesDefinitionResource propertiesDefinitionResource, WinerysPropertiesDefinition wpd) {
+ this.propertiesDefinitionResource = propertiesDefinitionResource;
+ this.wpd = wpd;
+ }
+
+ public List<PropertyDefinitionKV> getPropertyDefinitionKVList() {
+ // as this method is used by the JSP, we have to initialize the list and not provide a fake list
+ // in other words: we are in the mode, where the user has chosen the winery property handling
+ assert (this.getIsWineryKeyValueProperties());
+ if (this.wpd.getPropertyDefinitionKVList() == null) {
+ return java.util.Collections.emptyList();
+ } else {
+ return this.wpd.getPropertyDefinitionKVList();
+ }
+ }
+
+ public Boolean getIsWineryKeyValueProperties() {
+ return (this.wpd != null);
+ // the jsp renders list data only if the list is existing
+ // we could (somehow) also always keep the old list, but we opted for keeping the choice between the four options also in the XML (and not storing stale data)
+ // in the case, the WPD is derived from XSD, the list is rendered nevertheless
+ }
+
+ public boolean getIsWineryKeyValuePropertiesDerivedFromXSD() {
+ return ((this.wpd != null) && (this.wpd.getIsDerivedFromXSD() != null));
+ }
+
+ public String[] getAvailablePropertyTypes() {
+ return JSPData.availablePropertyTypes;
+ }
+
+ public TEntityType getEntityType() {
+ return this.propertiesDefinitionResource.getEntityType();
+ }
+
+ public String getElementName() {
+ if (this.wpd == null) {
+ return null;
+ } else {
+ return this.wpd.getElementName();
+ }
+ }
+
+ public String getNamespace() {
+ if (this.wpd == null) {
+ return null;
+ } else {
+ return this.wpd.getNamespace();
+ }
+ }
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/properties/PropertiesDefinitionResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/properties/PropertiesDefinitionResource.java
new file mode 100644
index 0000000..6a63791
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/properties/PropertiesDefinitionResource.java
@@ -0,0 +1,161 @@
+/*******************************************************************************
+ * 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.repository.resources.entitytypes.properties;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+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.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+import javax.xml.namespace.QName;
+
+import org.apache.commons.lang3.StringUtils;
+import org.eclipse.winery.common.ModelUtilities;
+import org.eclipse.winery.common.constants.MimeTypes;
+import org.eclipse.winery.common.propertydefinitionkv.WinerysPropertiesDefinition;
+import org.eclipse.winery.model.tosca.TEntityType;
+import org.eclipse.winery.model.tosca.TEntityType.PropertiesDefinition;
+import org.eclipse.winery.repository.backend.BackendUtils;
+import org.eclipse.winery.repository.resources.EntityTypeResource;
+import org.eclipse.winery.repository.resources.entitytypes.properties.winery.WinerysPropertiesDefinitionResource;
+import org.restdoc.annotations.RestDoc;
+import org.restdoc.annotations.RestDocParam;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.sun.jersey.api.view.Viewable;
+
+/**
+ * Models
+ * <ol>
+ * <li>TOSCA conforming properties definition (XML element / XML schema / none)</li>
+ * <li>Winery's KV properties (in the subresource "winery")</li>
+ * </ol>
+ *
+ * This class does not have "KV" in its name, because it models
+ * {@link TEntityType.PropertiesDefinition}
+ */
+public class PropertiesDefinitionResource {
+
+ private static final Logger logger = LoggerFactory.getLogger(PropertiesDefinitionResource.class);
+
+ // We hold a copy of super.res as we work on the type EntityTypeResource instead of AbstractComponentInstanceResource
+ private final EntityTypeResource parentRes;
+
+ // we assume that this class is created at each request
+ // therefore, we can have "wpd" final
+ private final WinerysPropertiesDefinition wpd;
+
+
+ public PropertiesDefinitionResource(EntityTypeResource res) {
+ this.parentRes = res;
+ this.wpd = ModelUtilities.getWinerysPropertiesDefinition(res.getEntityType());
+ }
+
+ @GET
+ @Produces(MediaType.TEXT_HTML)
+ public Viewable getHTML() {
+ return new Viewable("/jsp/entitytypes/properties/propertiesDefinition.jsp", new JSPData(this, this.wpd));
+ }
+
+ public TEntityType getEntityType() {
+ return this.parentRes.getEntityType();
+ }
+
+ @Path("winery/")
+ public WinerysPropertiesDefinitionResource getWinerysPropertiesDefinitionResource() {
+ // this.wpd is null if there is no winery definition exisitin. The subresource handles that case, too
+ return new WinerysPropertiesDefinitionResource(this.parentRes, this.wpd);
+ }
+
+ @DELETE
+ public Response clearPropertiesDefinition() {
+ this.getEntityType().setPropertiesDefinition(null);
+ ModelUtilities.removeWinerysPropertiesDefinition(this.getEntityType());
+ return BackendUtils.persist(this.parentRes);
+ }
+
+ public boolean getIsWineryKeyValueProperties() {
+ return (this.wpd != null);
+ }
+
+ @GET
+ @Produces(MimeTypes.MIMETYPE_XSD)
+ public Response getXSD() {
+ if (this.getIsWineryKeyValueProperties()) {
+ return Response.ok().entity(ModelUtilities.getWinerysPropertiesDefinitionXSDAsDocument(this.wpd)).build();
+ } else {
+ // not yet implemented
+ // We would have to check the imports in the repo for the defined property
+ // This also has to be similarly done at the export to determine the right imports
+ return Response.status(Status.NOT_FOUND).build();
+ }
+ }
+
+ @GET
+ @RestDoc(methodDescription = "We provide the XSD at . and at ./xsd/ to enable simple quering in the browser without the hazzle of setting the correct mime type.")
+ @Path("xsd/")
+ @Produces(MimeTypes.MIMETYPE_XSD)
+ public Response getXSDAtSubResource() {
+ return this.getXSD();
+ }
+
+ // @formatter:off
+ @POST
+ @RestDoc(methodDescription="Updates/creates a property based on XSD element or XML schema.")
+ @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
+ @Produces(MediaType.TEXT_PLAIN)
+ public Response onPost(
+ @FormParam("name") @RestDocParam(description="Either xsdelement or xsdtype. 'name' comes from x-editable, which uses that as field name") String name,
+ @FormParam("value") @RestDocParam(description="The qname") String value) {
+ // @formatter:on
+ if (StringUtils.isEmpty(name)) {
+ return Response.status(Status.BAD_REQUEST).entity("You have to provide a key/type or a name/value pair").build();
+ }
+ if (StringUtils.isEmpty(value)) {
+ return Response.status(Status.BAD_REQUEST).entity("If a name is provided, a value has also to be provided").build();
+ }
+
+ // first of all, remove Winery's Properties definition (if it exists)
+ ModelUtilities.removeWinerysPropertiesDefinition(this.getEntityType());
+
+ QName qname = QName.valueOf(value);
+
+ // replace old properties definition by new one
+ PropertiesDefinition def = new PropertiesDefinition();
+ if (name.equals("xsdtype")) {
+ def.setType(qname);
+ } else if (name.equals("xsdelement")) {
+ def.setElement(qname);
+ } else {
+ return Response.status(Status.BAD_REQUEST).entity("Invalid name. Choose xsdelement or xsdtype").build();
+ }
+ this.getEntityType().setPropertiesDefinition(def);
+ List<String> errors = new ArrayList<>();
+ BackendUtils.deriveWPD(this.getEntityType(), errors);
+ // currently the errors are just logged
+ for (String error : errors) {
+ PropertiesDefinitionResource.logger.debug(error);
+ }
+ return BackendUtils.persist(this.parentRes);
+
+ }
+
+} \ No newline at end of file
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/properties/winery/PropertyDefinitionKVListResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/properties/winery/PropertyDefinitionKVListResource.java
new file mode 100644
index 0000000..f967042
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/properties/winery/PropertyDefinitionKVListResource.java
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2013 University of Stuttgart.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ * Oliver Kopp - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.winery.repository.resources.entitytypes.properties.winery;
+
+import org.eclipse.winery.common.propertydefinitionkv.PropertyDefinitionKV;
+import org.eclipse.winery.common.propertydefinitionkv.PropertyDefinitionKVList;
+import org.eclipse.winery.repository.resources.EntityTypeResource;
+import org.eclipse.winery.repository.resources._support.collections.withid.EntityWithIdCollectionResource;
+
+import com.sun.jersey.api.view.Viewable;
+
+/**
+ * Supports Winery's k/v properties introducing sub resources
+ * "PropertyDefinition", which defines <em>one</em> property
+ */
+public class PropertyDefinitionKVListResource extends EntityWithIdCollectionResource<PropertyDefinitionKVResource, PropertyDefinitionKV> {
+
+ public PropertyDefinitionKVListResource(EntityTypeResource res, PropertyDefinitionKVList list) {
+ super(PropertyDefinitionKVResource.class, PropertyDefinitionKV.class, list, res);
+ }
+
+ @Override
+ public String getId(PropertyDefinitionKV entity) {
+ return entity.getKey();
+ }
+
+ @Override
+ public Viewable getHTML() {
+ throw new IllegalStateException("Not yet implemented.");
+ }
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/properties/winery/PropertyDefinitionKVResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/properties/winery/PropertyDefinitionKVResource.java
new file mode 100644
index 0000000..00a8d24
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/properties/winery/PropertyDefinitionKVResource.java
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * 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.repository.resources.entitytypes.properties.winery;
+
+import java.util.List;
+
+import javax.ws.rs.FormParam;
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Response;
+
+import org.eclipse.winery.common.propertydefinitionkv.PropertyDefinitionKV;
+import org.eclipse.winery.repository.backend.BackendUtils;
+import org.eclipse.winery.repository.resources.AbstractComponentInstanceResource;
+import org.eclipse.winery.repository.resources._support.IPersistable;
+import org.eclipse.winery.repository.resources._support.collections.IIdDetermination;
+import org.eclipse.winery.repository.resources._support.collections.withid.EntityWithIdResource;
+import org.restdoc.annotations.RestDoc;
+
+/**
+ * Models a definition of one property
+ *
+ * This is NOT in line with CSPRD01, which forces one element of one type
+ */
+public class PropertyDefinitionKVResource extends EntityWithIdResource<PropertyDefinitionKV> {
+
+ public PropertyDefinitionKVResource(IIdDetermination<PropertyDefinitionKV> idDetermination, PropertyDefinitionKV o, int idx, List<PropertyDefinitionKV> list, AbstractComponentInstanceResource res) {
+ super(idDetermination, o, idx, list, res);
+ }
+
+ public PropertyDefinitionKVResource(IIdDetermination<PropertyDefinitionKV> idDetermination, PropertyDefinitionKV o, int idx, List<PropertyDefinitionKV> list, IPersistable res) {
+ super(idDetermination, o, idx, list, res);
+ }
+
+ @GET
+ @RestDoc(methodDescription = "@return type is the 'id' of the type ('shortType'), not the full type name")
+ @Path("type")
+ public String getType() {
+ return this.o.getType();
+ }
+
+ @PUT
+ @RestDoc(methodDescription = "@return type is the 'id' of the type ('shortType'), not the full type name")
+ @Path("type")
+ public Response setType(@FormParam("type") String type) {
+ this.o.setType(type);
+ return BackendUtils.persist(this.res);
+ }
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/properties/winery/WinerysPropertiesDefinitionResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/properties/winery/WinerysPropertiesDefinitionResource.java
new file mode 100644
index 0000000..0d219e3
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/properties/winery/WinerysPropertiesDefinitionResource.java
@@ -0,0 +1,132 @@
+/*******************************************************************************
+ * 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.repository.resources.entitytypes.properties.winery;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.eclipse.winery.model.tosca.TEntityType;
+import org.eclipse.winery.common.ModelUtilities;
+import org.eclipse.winery.common.propertydefinitionkv.PropertyDefinitionKVList;
+import org.eclipse.winery.common.propertydefinitionkv.WinerysPropertiesDefinition;
+import org.eclipse.winery.repository.backend.BackendUtils;
+import org.eclipse.winery.repository.resources.EntityTypeResource;
+import org.restdoc.annotations.RestDoc;
+
+import com.sun.jersey.api.NotFoundException;
+
+public class WinerysPropertiesDefinitionResource {
+
+ private final EntityTypeResource res;
+ private final WinerysPropertiesDefinition wpd;
+
+
+ /**
+ * @param res the resource where winery's k/v properties are defined
+ * @param wpd winery's properties definition object, MAY be null
+ */
+ public WinerysPropertiesDefinitionResource(EntityTypeResource res, WinerysPropertiesDefinition wpd) {
+ this.res = res;
+ this.wpd = wpd;
+ }
+
+ @POST
+ @RestDoc(methodDescription = "switches the mode to winery properties instead of element/type properties")
+ public Response onPost() {
+ TEntityType et = this.res.getEntityType();
+
+ // clear current properties definition
+ et.setPropertiesDefinition(null);
+
+ // create empty winery properties definition and persist it
+ WinerysPropertiesDefinition wpd = new WinerysPropertiesDefinition();
+ ModelUtilities.replaceWinerysPropertiesDefinition(et, wpd);
+ return BackendUtils.persist(this.res);
+ }
+
+ @Path("namespace")
+ @GET
+ @Produces(MediaType.TEXT_PLAIN)
+ public String getNamespace() {
+ if (this.wpd == null) {
+ throw new NotFoundException();
+ }
+ return this.wpd.getNamespace();
+ }
+
+ @Path("namespace")
+ @PUT
+ @Consumes(MediaType.TEXT_PLAIN)
+ public Response setNamespace(String namespace) {
+ if (this.wpd == null) {
+ throw new NotFoundException();
+ }
+ this.wpd.setNamespace(namespace);
+ return BackendUtils.persist(this.res);
+ }
+
+ @Path("elementname")
+ @GET
+ @Produces(MediaType.TEXT_PLAIN)
+ public String getElementName() {
+ if (this.wpd == null) {
+ throw new NotFoundException();
+ }
+ return this.wpd.getElementName();
+ }
+
+ @Path("elementname")
+ @PUT
+ @Consumes(MediaType.TEXT_PLAIN)
+ public Response setLocalname(String elementName) {
+ if (this.wpd == null) {
+ throw new NotFoundException();
+ }
+ this.wpd.setElementName(elementName);
+ return BackendUtils.persist(this.res);
+ }
+
+ @Path("elementname")
+ @PUT
+ @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
+ public Response setLocalnameViaWebUI(@FormParam(value = "name") String elementName) {
+ if (this.wpd == null) {
+ throw new NotFoundException();
+ }
+ this.wpd.setElementName(elementName);
+ return BackendUtils.persist(this.res);
+ }
+
+ /**
+ * Here, also the addition of k/v properties is handled.
+ */
+ @Path("list/")
+ public PropertyDefinitionKVListResource getListResource() {
+ if (this.wpd == null) {
+ throw new NotFoundException();
+ }
+ PropertyDefinitionKVList list = this.wpd.getPropertyDefinitionKVList();
+ if (list == null) {
+ list = new PropertyDefinitionKVList();
+ this.wpd.setPropertyDefinitionKVList(list);
+ }
+ return new PropertyDefinitionKVListResource(this.res, list);
+ }
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/relationshiptypes/ImplementationsOfOneRelationshipTypeResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/relationshiptypes/ImplementationsOfOneRelationshipTypeResource.java
new file mode 100644
index 0000000..c7cf2d6
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/relationshiptypes/ImplementationsOfOneRelationshipTypeResource.java
@@ -0,0 +1,95 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2013,2015 University of Stuttgart.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ * Oliver Kopp - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.winery.repository.resources.entitytypes.relationshiptypes;
+
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.Collection;
+
+import javax.ws.rs.core.Response;
+import javax.xml.namespace.QName;
+
+import org.eclipse.winery.common.ids.definitions.RelationshipTypeId;
+import org.eclipse.winery.common.ids.definitions.RelationshipTypeImplementationId;
+import org.eclipse.winery.repository.backend.BackendUtils;
+import org.eclipse.winery.repository.resources.entitytypes.ImplementationsOfOneType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.fasterxml.jackson.core.JsonFactory;
+import com.fasterxml.jackson.core.JsonGenerator;
+
+public class ImplementationsOfOneRelationshipTypeResource extends ImplementationsOfOneType {
+
+ public ImplementationsOfOneRelationshipTypeResource(RelationshipTypeId typeId) {
+ super(typeId);
+ }
+
+
+ private static final Logger logger = LoggerFactory.getLogger(ImplementationsOfOneRelationshipTypeResource.class);
+
+
+ /**
+ * required by implementations.jsp
+ *
+ * Method similar top the one of ImplementationsOfOneNodeTypeResource
+ *
+ * @return for each node type implementation implementing the associated
+ * node type
+ */
+ @Override
+ public String getImplementationsTableData() {
+ String res;
+ JsonFactory jsonFactory = new JsonFactory();
+ StringWriter tableDataSW = new StringWriter();
+ try {
+ JsonGenerator jGenerator = jsonFactory.createGenerator(tableDataSW);
+ jGenerator.writeStartArray();
+
+ Collection<RelationshipTypeImplementationId> allNTIids = BackendUtils.getAllElementsRelatedWithATypeAttribute(RelationshipTypeImplementationId.class, this.getTypeId().getQName());
+ for (RelationshipTypeImplementationId ntiID : allNTIids) {
+ jGenerator.writeStartArray();
+ jGenerator.writeString(ntiID.getNamespace().getDecoded());
+ jGenerator.writeString(ntiID.getXmlId().getDecoded());
+ jGenerator.writeEndArray();
+ }
+ jGenerator.writeEndArray();
+ jGenerator.close();
+ tableDataSW.close();
+ res = tableDataSW.toString();
+ } catch (Exception e) {
+ ImplementationsOfOneRelationshipTypeResource.logger.error(e.getMessage(), e);
+ res = "[]";
+ }
+ return res;
+ }
+
+ @Override
+ public String getType() {
+ return "relationshiptype";
+ }
+
+ @Override
+ public String getTypeStr() {
+ return "Relationship Type";
+ }
+
+ @Override
+ public Response getJSON() {
+ Collection<RelationshipTypeImplementationId> allImplementations = BackendUtils.getAllElementsRelatedWithATypeAttribute(RelationshipTypeImplementationId.class, this.getTypeId().getQName());
+ ArrayList<QName> res = new ArrayList<QName>(allImplementations.size());
+ for (RelationshipTypeImplementationId id : allImplementations) {
+ res.add(id.getQName());
+ }
+ return Response.ok().entity(res).build();
+ }
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/relationshiptypes/RelationshipTypeResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/relationshiptypes/RelationshipTypeResource.java
new file mode 100644
index 0000000..c874bd5
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/relationshiptypes/RelationshipTypeResource.java
@@ -0,0 +1,165 @@
+/*******************************************************************************
+ * 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.repository.resources.entitytypes.relationshiptypes;
+
+import java.util.Collection;
+import java.util.SortedSet;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.xml.namespace.QName;
+
+import org.eclipse.winery.model.tosca.TExtensibleElements;
+import org.eclipse.winery.model.tosca.TRelationshipType;
+import org.eclipse.winery.model.tosca.TRelationshipType.SourceInterfaces;
+import org.eclipse.winery.model.tosca.TRelationshipType.TargetInterfaces;
+import org.eclipse.winery.model.tosca.TRelationshipType.ValidSource;
+import org.eclipse.winery.model.tosca.TRelationshipType.ValidTarget;
+import org.eclipse.winery.model.tosca.TTopologyElementInstanceStates;
+import org.eclipse.winery.common.ids.definitions.NodeTypeId;
+import org.eclipse.winery.common.ids.definitions.RelationshipTypeId;
+import org.eclipse.winery.repository.backend.BackendUtils;
+import org.eclipse.winery.repository.backend.Repository;
+import org.eclipse.winery.repository.resources.entitytypes.InstanceStatesResource;
+import org.eclipse.winery.repository.resources.entitytypes.TopologyGraphElementEntityTypeResource;
+import org.eclipse.winery.repository.resources.interfaces.InterfacesResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.sun.jersey.api.view.Viewable;
+
+public class RelationshipTypeResource extends TopologyGraphElementEntityTypeResource {
+
+ private static final Logger logger = LoggerFactory.getLogger(RelationshipTypeResource.class);
+
+
+ public RelationshipTypeResource(RelationshipTypeId id) {
+ super(id);
+ }
+
+ @Path("implementations/")
+ public ImplementationsOfOneRelationshipTypeResource getImplementations() {
+ return new ImplementationsOfOneRelationshipTypeResource((RelationshipTypeId) this.id);
+ }
+
+ @Path("visualappearance/")
+ public VisualAppearanceResource getVisualAppearanceResource() {
+ return new VisualAppearanceResource(this, this.getElement().getOtherAttributes(), (RelationshipTypeId) this.id);
+ }
+
+ @Path("instancestates/")
+ public InstanceStatesResource getInstanceStatesResource() {
+ TTopologyElementInstanceStates instanceStates = this.getRelationshipType().getInstanceStates();
+ if (instanceStates == null) {
+ // if an explicit (empty) list does not exist, create it
+ instanceStates = new TTopologyElementInstanceStates();
+ this.getRelationshipType().setInstanceStates(instanceStates);
+ }
+ return new InstanceStatesResource(this.getRelationshipType().getInstanceStates(), this);
+ }
+
+ @Path("sourceinterfaces/")
+ public InterfacesResource getSourceInterfaces() {
+ SourceInterfaces interfaces = this.getRelationshipType().getSourceInterfaces();
+ if (interfaces == null) {
+ interfaces = new SourceInterfaces();
+ this.getRelationshipType().setSourceInterfaces(interfaces);
+ }
+ return new InterfacesResource("source", interfaces.getInterface(), this);
+ }
+
+ @Path("targetinterfaces/")
+ public InterfacesResource getTargetInterfaces() {
+ TargetInterfaces interfaces = this.getRelationshipType().getTargetInterfaces();
+ if (interfaces == null) {
+ interfaces = new TargetInterfaces();
+ this.getRelationshipType().setTargetInterfaces(interfaces);
+ }
+ return new InterfacesResource("target", interfaces.getInterface(), this);
+ }
+
+ @Path("validendings/")
+ @GET
+ @Produces(MediaType.TEXT_HTML)
+ public Response getHTML() {
+ Viewable viewable = new Viewable("/jsp/entitytypes/relationshiptypes/validendings.jsp", this);
+ return Response.ok().entity(viewable).build();
+ }
+
+ @Path("validsource")
+ @GET
+ public String getValidSource() {
+ ValidSource validSource;
+ if (((validSource = this.getRelationshipType().getValidSource()) == null) || (validSource.getTypeRef() == null)) {
+ return null;
+ }
+ return this.getRelationshipType().getValidSource().getTypeRef().toString();
+ }
+
+ @Path("validsource")
+ @PUT
+ @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
+ public Response setValidSource(String typeRef) {
+ ValidSource vs = new ValidSource();
+ QName qname = QName.valueOf(typeRef);
+ vs.setTypeRef(qname);
+ this.getRelationshipType().setValidSource(vs);
+ return BackendUtils.persist(this);
+ }
+
+ @Path("validtarget")
+ @GET
+ public String getValidTarget() {
+ ValidTarget validTarget;
+ if (((validTarget = this.getRelationshipType().getValidTarget()) == null) || (validTarget.getTypeRef() == null)) {
+ return null;
+ }
+ return this.getRelationshipType().getValidTarget().getTypeRef().toString();
+ }
+
+ @Path("validtarget")
+ @PUT
+ @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
+ public Response setValidTarget(String typeRef) {
+ ValidTarget vt = new ValidTarget();
+ QName qname = QName.valueOf(typeRef);
+ vt.setTypeRef(qname);
+ this.getRelationshipType().setValidTarget(vt);
+ return BackendUtils.persist(this);
+ }
+
+ /**
+ * Required for validendings.jsp
+ */
+ public Collection<NodeTypeId> getPossibleValidEndings() {
+ SortedSet<NodeTypeId> allNodeTypeIds = Repository.INSTANCE.getAllTOSCAComponentIds(NodeTypeId.class);
+ return allNodeTypeIds;
+ }
+
+ /**
+ * Convenience method to avoid casting at the caller's side.
+ */
+ public TRelationshipType getRelationshipType() {
+ return (TRelationshipType) this.getElement();
+ }
+
+ @Override
+ protected TExtensibleElements createNewElement() {
+ return new TRelationshipType();
+ }
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/relationshiptypes/RelationshipTypesResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/relationshiptypes/RelationshipTypesResource.java
new file mode 100644
index 0000000..1c73ab0
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/relationshiptypes/RelationshipTypesResource.java
@@ -0,0 +1,17 @@
+/*******************************************************************************
+ * 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.repository.resources.entitytypes.relationshiptypes;
+
+import org.eclipse.winery.repository.resources.AbstractComponentsResource;
+
+public class RelationshipTypesResource extends AbstractComponentsResource<RelationshipTypeResource> {
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/relationshiptypes/VisualAppearanceResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/relationshiptypes/VisualAppearanceResource.java
new file mode 100644
index 0000000..c17c19b
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/relationshiptypes/VisualAppearanceResource.java
@@ -0,0 +1,291 @@
+/*******************************************************************************
+ * 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
+ * Jerome Tagliaferri - support for setting the color
+ *******************************************************************************/
+package org.eclipse.winery.repository.resources.entitytypes.relationshiptypes;
+
+import java.io.StringWriter;
+import java.util.Map;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+import javax.xml.namespace.QName;
+
+import org.apache.commons.lang3.StringUtils;
+import org.eclipse.winery.common.constants.Defaults;
+import org.eclipse.winery.common.constants.Namespaces;
+import org.eclipse.winery.common.constants.QNames;
+import org.eclipse.winery.common.ids.definitions.RelationshipTypeId;
+import org.eclipse.winery.repository.backend.BackendUtils;
+import org.eclipse.winery.repository.datatypes.ids.elements.VisualAppearanceId;
+import org.eclipse.winery.repository.resources.GenericVisualAppearanceResource;
+import org.restdoc.annotations.RestDoc;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.fasterxml.jackson.core.JsonFactory;
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.sun.jersey.api.view.Viewable;
+
+public class VisualAppearanceResource extends GenericVisualAppearanceResource {
+
+ private static final Logger logger = LoggerFactory.getLogger(VisualAppearanceResource.class);
+
+ private static final QName QNAME_ARROWHEAD_SOURCE = new QName(Namespaces.TOSCA_WINERY_EXTENSIONS_NAMESPACE, "sourceArrowHead");
+ private static final QName QNAME_ARROWHEAD_TARGET = new QName(Namespaces.TOSCA_WINERY_EXTENSIONS_NAMESPACE, "targetArrowHead");
+ private static final QName QNAME_DASH = new QName(Namespaces.TOSCA_WINERY_EXTENSIONS_NAMESPACE, "dash");
+ private static final QName QNAME_LINEWIDTH = new QName(Namespaces.TOSCA_WINERY_EXTENSIONS_NAMESPACE, "linewidth");
+ private static final QName QNAME_HOVER_COLOR = new QName(Namespaces.TOSCA_WINERY_EXTENSIONS_NAMESPACE, "hovercolor");
+
+
+ public VisualAppearanceResource(RelationshipTypeResource res, Map<QName, String> map, RelationshipTypeId parentId) {
+ super(res, map, new VisualAppearanceId(parentId));
+ }
+
+ @GET
+ @Produces(MediaType.TEXT_HTML)
+ public Response getHTML() {
+ Viewable viewable = new Viewable("/jsp/entitytypes/relationshiptypes/visualappearance.jsp", this);
+ return Response.ok().entity(viewable).build();
+ }
+
+ @GET
+ @RestDoc(methodDescription = "@return JSON object to be used at jsPlumb.registerConnectionType('NAME', <data>)")
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response getConnectionTypeForJsPlumbData() {
+ JsonFactory jsonFactory = new JsonFactory();
+ StringWriter sw = new StringWriter();
+ try {
+ JsonGenerator jg = jsonFactory.createGenerator(sw);
+ jg.writeStartObject();
+
+ jg.writeFieldName("connector");
+ jg.writeString("Flowchart");
+
+ jg.writeFieldName("paintStyle");
+ jg.writeStartObject();
+ jg.writeFieldName("lineWidth");
+ jg.writeNumber(this.getLineWidth());
+ jg.writeFieldName("strokeStyle");
+ jg.writeObject(this.getColor());
+ String dash = this.getDash();
+ if (!StringUtils.isEmpty(dash)) {
+ String dashStyle = null;
+ switch (dash) {
+ case "dotted":
+ dashStyle = "1 5";
+ break;
+ case "dotted2":
+ dashStyle = "3 4";
+ break;
+ case "plain":
+ // default works
+ // otherwise, "1 0" can be used
+ break;
+ }
+ if (dashStyle != null) {
+ jg.writeStringField("dashstyle", dashStyle);
+ }
+ }
+ jg.writeEndObject();
+
+ jg.writeFieldName("hoverPaintStyle");
+ jg.writeStartObject();
+ jg.writeFieldName("strokeStyle");
+ jg.writeObject(this.getHoverColor());
+ jg.writeEndObject();
+
+ // BEGIN: Overlays
+
+ jg.writeFieldName("overlays");
+ jg.writeStartArray();
+
+ // source arrow head
+ String head = this.getSourceArrowHead();
+ if (!head.equals("none")) {
+ jg.writeStartArray();
+ jg.writeString(head);
+
+ jg.writeStartObject();
+
+ jg.writeFieldName("location");
+ jg.writeNumber(0);
+
+ // arrow should point towards the node and not away from it
+ jg.writeFieldName("direction");
+ jg.writeNumber(-1);
+
+ jg.writeFieldName("width");
+ jg.writeNumber(20);
+
+ jg.writeFieldName("length");
+ jg.writeNumber(12);
+
+ jg.writeEndObject();
+ jg.writeEndArray();
+ }
+
+ // target arrow head
+ head = this.getTargetArrowHead();
+ if (!head.equals("none")) {
+ jg.writeStartArray();
+ jg.writeString(head);
+ jg.writeStartObject();
+ jg.writeFieldName("location");
+ jg.writeNumber(1);
+ jg.writeFieldName("width");
+ jg.writeNumber(20);
+ jg.writeFieldName("length");
+ jg.writeNumber(12);
+ jg.writeEndObject();
+ jg.writeEndArray();
+ }
+
+ // Type in brackets on the arrow
+ jg.writeStartArray();
+ jg.writeString("Label");
+ jg.writeStartObject();
+ jg.writeStringField("id", "label");
+ jg.writeStringField("label", "(" + ((RelationshipTypeResource) this.res).getName() + ")");
+ jg.writeStringField("cssClass", "relationshipTypeLabel");
+ jg.writeFieldName("location");
+ jg.writeNumber(0.5);
+ jg.writeEndObject();
+ jg.writeEndArray();
+
+ jg.writeEndArray();
+
+ // END: Overlays
+
+ jg.writeEndObject();
+
+ jg.close();
+ } catch (Exception e) {
+ VisualAppearanceResource.logger.error(e.getMessage(), e);
+ return Response.status(Status.INTERNAL_SERVER_ERROR).entity(e).build();
+ }
+ String res = sw.toString();
+ return Response.ok(res).build();
+ }
+
+ private String getOtherAttributeWithDefault(QName qname, String def) {
+ String res = this.otherAttributes.get(qname);
+ if (StringUtils.isEmpty(res)) {
+ return def;
+ } else {
+ return res;
+ }
+ }
+
+ /* * * source arrow head * * */
+
+ public String getSourceArrowHead() {
+ return this.getOtherAttributeWithDefault(VisualAppearanceResource.QNAME_ARROWHEAD_SOURCE, Defaults.DEFAULT_RT_ARROWHEAD_SOURCE);
+ }
+
+ @PUT
+ @Consumes(MediaType.TEXT_PLAIN)
+ @Path("sourcearrowhead")
+ public Response onPutSourceHead(String config) {
+ if (StringUtils.isEmpty(config)) {
+ return Response.status(Status.BAD_REQUEST).entity("config must not be empty").build();
+ }
+ this.otherAttributes.put(VisualAppearanceResource.QNAME_ARROWHEAD_SOURCE, config);
+ return BackendUtils.persist(this.res);
+ }
+
+ /* * * target arrow head * * */
+
+ public String getTargetArrowHead() {
+ return this.getOtherAttributeWithDefault(VisualAppearanceResource.QNAME_ARROWHEAD_TARGET, Defaults.DEFAULT_RT_ARROWHEAD_TARGET);
+ }
+
+ @PUT
+ @Consumes(MediaType.TEXT_PLAIN)
+ @Path("targetarrowhead")
+ public Response onPutTargetHead(String config) {
+ if (StringUtils.isEmpty(config)) {
+ return Response.status(Status.BAD_REQUEST).entity("config must not be empty").build();
+ }
+ this.otherAttributes.put(VisualAppearanceResource.QNAME_ARROWHEAD_TARGET, config);
+ return BackendUtils.persist(this.res);
+ }
+
+ /* * *
+ *
+ * stroke dash array / represents the line
+ *
+ * Attention: if a linewidth != 1 is chosen, the dash has to be multiplied somehow by the line width
+ * See: http://jsplumbtoolkit.com/doc/paint-styles:
+ * "The dashstyle attribute is specified as an array of strokes and spaces, where each value is some multiple of the width of the Connector"
+ *
+ * * * */
+
+ public String getDash() {
+ return this.getOtherAttributeWithDefault(VisualAppearanceResource.QNAME_DASH, Defaults.DEFAULT_RT_DASH);
+ }
+
+ @PUT
+ @Consumes(MediaType.TEXT_PLAIN)
+ @Path("dash")
+ public Response onPutDash(String config) {
+ if (StringUtils.isEmpty(config)) {
+ return Response.status(Status.BAD_REQUEST).entity("config must not be empty").build();
+ }
+ this.otherAttributes.put(VisualAppearanceResource.QNAME_DASH, config);
+ return BackendUtils.persist(this.res);
+ }
+
+ /* * * stroke/line width * * */
+
+ public String getLineWidth() {
+ return this.getOtherAttributeWithDefault(VisualAppearanceResource.QNAME_LINEWIDTH, Defaults.DEFAULT_RT_LINEWIDTH);
+ }
+
+ /* * * color * * */
+
+ /**
+ * read by topologytemplateeditor.jsp via ${it.color}
+ */
+ public String getColor() {
+ return BackendUtils.getColorAndSetDefaultIfNotExisting(this.getId().getParent().getXmlId().getDecoded(), QNames.QNAME_COLOR, this.otherAttributes, this.res);
+ }
+
+ @PUT
+ @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
+ @Path("color")
+ public Response onPutColor(@FormParam("color") String color) {
+ this.otherAttributes.put(QNames.QNAME_COLOR, color);
+ return BackendUtils.persist(this.res);
+ }
+
+ /**
+ * read by topologytemplateeditor.jsp via ${it.hoverColor}
+ */
+ public String getHoverColor() {
+ return this.getOtherAttributeWithDefault(VisualAppearanceResource.QNAME_HOVER_COLOR, Defaults.DEFAULT_RT_HOVER_COLOR);
+ }
+
+ @PUT
+ @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
+ @Path("hovercolor")
+ public Response onPutHoverColor(@FormParam("color") String color) {
+ this.otherAttributes.put(VisualAppearanceResource.QNAME_HOVER_COLOR, color);
+ return BackendUtils.persist(this.res);
+ }
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/requirementtypes/RequiredCapabilityTypeResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/requirementtypes/RequiredCapabilityTypeResource.java
new file mode 100644
index 0000000..c076835
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/requirementtypes/RequiredCapabilityTypeResource.java
@@ -0,0 +1,83 @@
+/*******************************************************************************
+ * 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.repository.resources.entitytypes.requirementtypes;
+
+import java.util.Collection;
+import java.util.SortedSet;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+import javax.xml.namespace.QName;
+
+import org.apache.commons.lang3.StringUtils;
+import org.eclipse.winery.common.ids.definitions.CapabilityTypeId;
+import org.eclipse.winery.model.tosca.TRequirementType;
+import org.eclipse.winery.repository.backend.BackendUtils;
+import org.eclipse.winery.repository.backend.Repository;
+
+import com.sun.jersey.api.NotFoundException;
+import com.sun.jersey.api.view.Viewable;
+
+public class RequiredCapabilityTypeResource {
+
+ private RequirementTypeResource requirementTypeResource;
+
+
+ public RequiredCapabilityTypeResource(RequirementTypeResource requirementTypeResource) {
+ this.requirementTypeResource = requirementTypeResource;
+ }
+
+ @GET
+ @Produces(MediaType.TEXT_HTML)
+ public Viewable getHTML() {
+ return new Viewable("/jsp/entitytypes/requirementtypes/requiredcapabilitytype.jsp", this);
+ }
+
+ public TRequirementType getRequirementType() {
+ return this.requirementTypeResource.getRequirementType();
+ }
+
+ @PUT
+ @Consumes(MediaType.TEXT_PLAIN)
+ public Response putRequiredCapabilityType(String type) {
+ if (StringUtils.isEmpty(type)) {
+ return Response.status(Status.BAD_REQUEST).entity("type must not be empty").build();
+ }
+ QName qname = QName.valueOf(type);
+ CapabilityTypeId id = new CapabilityTypeId(qname);
+ if (Repository.INSTANCE.exists(id)) {
+ // everything allright. Store new reference
+ this.getRequirementType().setRequiredCapabilityType(qname);
+ return BackendUtils.persist(this.requirementTypeResource);
+ } else {
+ throw new NotFoundException("Given QName could not be resolved to an existing capability type");
+ }
+ }
+
+ @DELETE
+ public Response deleteRequiredCapabilityType() {
+ this.getRequirementType().setRequiredCapabilityType(null);
+ return BackendUtils.persist(this.requirementTypeResource);
+ }
+
+ /** required for jsp **/
+ public Collection<QName> getAllCapabilityTypes() {
+ SortedSet<CapabilityTypeId> allTOSCAComponentIds = Repository.INSTANCE.getAllTOSCAComponentIds(CapabilityTypeId.class);
+ return BackendUtils.convertTOSCAComponentIdCollectionToQNameCollection(allTOSCAComponentIds);
+ }
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/requirementtypes/RequirementTypeResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/requirementtypes/RequirementTypeResource.java
new file mode 100644
index 0000000..0f143fb
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/requirementtypes/RequirementTypeResource.java
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * 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.repository.resources.entitytypes.requirementtypes;
+
+import javax.ws.rs.Path;
+
+import org.eclipse.winery.model.tosca.TExtensibleElements;
+import org.eclipse.winery.model.tosca.TRequirementType;
+import org.eclipse.winery.common.ids.definitions.RequirementTypeId;
+import org.eclipse.winery.repository.resources.EntityTypeResource;
+
+public class RequirementTypeResource extends EntityTypeResource {
+
+ public RequirementTypeResource(RequirementTypeId id) {
+ super(id);
+ }
+
+ /**
+ * Convenience method to avoid casting at the caller's side.
+ */
+ public TRequirementType getRequirementType() {
+ return (TRequirementType) this.getElement();
+ }
+
+ @Override
+ protected TExtensibleElements createNewElement() {
+ return new TRequirementType();
+ }
+
+ @Path("requiredcapabilitytype/")
+ public RequiredCapabilityTypeResource getRequiredCapabilityTypeResource() {
+ return new RequiredCapabilityTypeResource(this);
+ }
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/requirementtypes/RequirementTypesResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/requirementtypes/RequirementTypesResource.java
new file mode 100644
index 0000000..955e4fb
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/requirementtypes/RequirementTypesResource.java
@@ -0,0 +1,22 @@
+/*******************************************************************************
+ * 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.repository.resources.entitytypes.requirementtypes;
+
+import org.eclipse.winery.repository.resources.AbstractComponentsResource;
+
+/**
+ * Manages all capability types in all available namespaces <br />
+ * The actual implementation is done in the AbstractComponentsResource
+ */
+public class RequirementTypesResource extends AbstractComponentsResource<RequirementTypeResource> {
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/imports/ImportsResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/imports/ImportsResource.java
new file mode 100644
index 0000000..82ff02e
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/imports/ImportsResource.java
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * 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.repository.resources.imports;
+
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+
+import org.eclipse.winery.common.Util;
+import org.eclipse.winery.repository.resources.AbstractComponentsResource;
+import org.eclipse.winery.repository.resources.imports.genericimports.GenericImportsResource;
+import org.eclipse.winery.repository.resources.imports.xsdimports.XSDImportsResource;
+
+/**
+ * The specification does not nest the sequence of import elements in an imports
+ * container. We introduce such a container to be consistent with the other
+ * resource naming
+ */
+public class ImportsResource {
+
+ @Path("{id}/")
+ public AbstractComponentsResource getXSDsResource(@PathParam("id") String id) {
+ // once: decoding for browser locations
+ id = Util.URLdecode(id);
+ // once again: real URI
+ id = Util.URLdecode(id);
+ if (id.equals("http://www.w3.org/2001/XMLSchema")) {
+ // Models http://www.w3.org/2001/XMLSchema. We do not use xsd instead of the
+ // encoded namespace, because this induces special cases at many places
+ return new XSDImportsResource();
+ } else {
+ return new GenericImportsResource(id);
+ }
+ }
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/imports/genericimports/GenericImportResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/imports/genericimports/GenericImportResource.java
new file mode 100644
index 0000000..ddcb462
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/imports/genericimports/GenericImportResource.java
@@ -0,0 +1,133 @@
+/*******************************************************************************
+ * 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.repository.resources.imports.genericimports;
+
+import java.util.SortedSet;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+
+import org.eclipse.winery.common.RepositoryFileReference;
+import org.eclipse.winery.common.Util;
+import org.eclipse.winery.common.ids.definitions.imports.GenericImportId;
+import org.eclipse.winery.model.tosca.TExtensibleElements;
+import org.eclipse.winery.model.tosca.TImport;
+import org.eclipse.winery.repository.backend.BackendUtils;
+import org.eclipse.winery.repository.backend.Repository;
+import org.eclipse.winery.repository.resources.AbstractComponentInstanceResource;
+
+public class GenericImportResource extends AbstractComponentInstanceResource {
+
+ // The import belonging to this resource
+ protected final TImport theImport;
+
+
+ public GenericImportResource(GenericImportId id) {
+ super(id);
+
+ boolean needsPersistence = false;
+
+ if (this.getDefinitions().getServiceTemplateOrNodeTypeOrNodeTypeImplementation().isEmpty()) {
+ // super class loaded an existing definitions
+
+ // we have to manually assign our import right
+ this.theImport = this.getDefinitions().getImport().get(0);
+
+ // element is not assigned as there are no service templates/...
+ // we assign the value to be sure that no NPEs occur
+ this.element = this.theImport;
+ } else {
+ // super class created a new import
+
+ // store it locally
+ this.theImport = (TImport) this.element;
+
+ // undo the side effect of adding it at the wrong place at TDefinitions
+ this.getDefinitions().getServiceTemplateOrNodeTypeOrNodeTypeImplementation().clear();
+
+ // add import at the right place
+ this.getDefinitions().getImport().add(this.theImport);
+
+ // Super class has persisted the definitions
+ // We have to persist the new variant
+ needsPersistence = true;
+ }
+
+ if (this.theImport.getLocation() == null) {
+ // invalid import -- try to synchronize with storage
+
+ SortedSet<RepositoryFileReference> containedFiles = Repository.INSTANCE.getContainedFiles(id);
+ // there is also a .definitions contained
+ // we are only interested in the non-.definitions
+ for (RepositoryFileReference ref : containedFiles) {
+ if (!ref.getFileName().endsWith(".definitions")) {
+ // associated file found
+ // set the filename of the import to the found xsd
+ // TODO: no more validity checks are done currently. In the case of XSD: targetNamespace matches, not more than one xsd
+ this.theImport.setLocation(ref.getFileName());
+ needsPersistence = true;
+ break;
+ }
+ }
+ }
+
+ if (needsPersistence) {
+ BackendUtils.persist(this);
+ }
+ }
+
+ @Override
+ protected TExtensibleElements createNewElement() {
+ throw new IllegalStateException("This should not never happen.");
+ }
+
+ @Override
+ protected void copyIdToFields() {
+ // this.theImport cannot be used as this method is called by the super constructor
+ ((TImport) this.element).setNamespace(this.id.getNamespace().getDecoded());
+ }
+
+ @GET
+ @Path("{filename}")
+ public Response getFile(@PathParam("filename") String fileName) {
+ fileName = Util.URLdecode(fileName);
+ String location;
+ if ((location = this.getLocation()) == null) {
+ return Response.status(Status.NOT_FOUND).build();
+ }
+ if (!location.equals(fileName)) {
+ return Response.status(Status.NOT_FOUND).build();
+ }
+ RepositoryFileReference ref = new RepositoryFileReference(this.id, location);
+ return BackendUtils.returnRepoPath(ref, null);
+
+ }
+
+ public String getLocation() {
+ return this.theImport.getLocation();
+ }
+
+ /**
+ * @return a name suitable for componentnaming.jspf
+ */
+ public String getName() {
+ if (this.getLocation() == null) {
+ return this.id.getXmlId().getDecoded();
+ } else {
+ return this.getLocation();
+ }
+ }
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/imports/genericimports/GenericImportsResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/imports/genericimports/GenericImportsResource.java
new file mode 100644
index 0000000..9117175
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/imports/genericimports/GenericImportsResource.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * 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.repository.resources.imports.genericimports;
+
+import org.eclipse.winery.common.ids.definitions.imports.GenericImportId;
+import org.eclipse.winery.repository.resources.AbstractComponentsResource;
+
+/**
+ * Manages a certain kind of imports without special treatments
+ */
+public class GenericImportsResource extends AbstractComponentsResource<GenericImportResource> {
+
+ private String type;
+
+
+ /**
+ * @param id the (decoded) id, e.g., http://schemas.xmlsoap.org/wsdl/
+ */
+ public GenericImportsResource(String id) {
+ this.type = id;
+ }
+
+ @Override
+ public GenericImportResource getComponentInstaceResource(String namespace, String id, boolean encoded) {
+ GenericImportId iId = new GenericImportId(namespace, id, encoded, this.type);
+ return new GenericImportResource(iId);
+ }
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/imports/xsdimports/XSDImportResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/imports/xsdimports/XSDImportResource.java
new file mode 100644
index 0000000..49ea468
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/imports/xsdimports/XSDImportResource.java
@@ -0,0 +1,174 @@
+/*******************************************************************************
+ * 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.repository.resources.imports.xsdimports;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+import javax.xml.XMLConstants;
+
+import org.apache.xerces.xs.XSConstants;
+import org.apache.xerces.xs.XSModel;
+import org.apache.xerces.xs.XSNamedMap;
+import org.apache.xerces.xs.XSObject;
+import org.eclipse.winery.common.RepositoryFileReference;
+import org.eclipse.winery.common.ids.definitions.imports.XSDImportId;
+import org.eclipse.winery.model.tosca.TExtensibleElements;
+import org.eclipse.winery.model.tosca.TImport;
+import org.eclipse.winery.repository.Utils;
+import org.eclipse.winery.repository.backend.BackendUtils;
+import org.eclipse.winery.repository.backend.Repository;
+import org.eclipse.winery.repository.resources.imports.genericimports.GenericImportResource;
+import org.restdoc.annotations.RestDoc;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+
+/**
+ * Even if we are not a component instance, we use that infrastructure to manage
+ * imports. Some hacks will be necessary. However, these are less effort than
+ * doing a clean design
+ */
+public class XSDImportResource extends GenericImportResource {
+
+ private static final Logger logger = LoggerFactory.getLogger(XSDImportResource.class);
+
+
+ public XSDImportResource(XSDImportId id) {
+ super(id);
+ }
+
+ @Override
+ protected TExtensibleElements createNewElement() {
+ TImport imp = new TImport();
+ imp.setImportType(XMLConstants.W3C_XML_SCHEMA_NS_URI);
+ return imp;
+ }
+
+ /**
+ * public required by XSDImportsResource
+ *
+ * @return null if XSD file does not exist
+ */
+ public RepositoryFileReference getXSDFileReference() {
+ String loc = this.getLocation();
+ if (loc == null) {
+ return null;
+ }
+ final RepositoryFileReference ref = new RepositoryFileReference(this.id, loc);
+ return ref;
+ }
+
+ /**
+ * @return null if no file is associated
+ */
+ private XSModel getXSModel() {
+ final RepositoryFileReference ref = this.getXSDFileReference();
+ return BackendUtils.getXSModel(ref);
+ }
+
+ // we need "unchecked", because of the parsing of the cache
+ @SuppressWarnings("unchecked")
+ public Collection<String> getAllDefinedLocalNames(short type) {
+ RepositoryFileReference ref = this.getXSDFileReference();
+ if (ref == null) {
+ return Collections.emptySet();
+ }
+ Date lastUpdate = Repository.INSTANCE.getLastUpdate(ref);
+
+ String cacheFileName = "definedLocalNames " + Integer.toString(type) + ".cache";
+ RepositoryFileReference cacheRef = new RepositoryFileReference(this.id, cacheFileName);
+ boolean cacheNeedsUpdate = true;
+ if (Repository.INSTANCE.exists(cacheRef)) {
+ Date lastUpdateCache = Repository.INSTANCE.getLastUpdate(cacheRef);
+ if (lastUpdate.compareTo(lastUpdateCache) <= 0) {
+ cacheNeedsUpdate = false;
+ }
+ }
+
+ List<String> result;
+ if (cacheNeedsUpdate) {
+
+ XSModel model = this.getXSModel();
+ if (model == null) {
+ return Collections.emptySet();
+ }
+ XSNamedMap components = model.getComponents(type);
+ //@SuppressWarnings("unchecked")
+ int len = components.getLength();
+ result = new ArrayList<String>(len);
+ for (int i = 0; i < len; i++) {
+ XSObject item = components.item(i);
+ // if queried for TYPE_DEFINITION, then XSD base types (such as IDREF) are also returned
+ // We want to return only types defined in the namespace of this resource
+ if (item.getNamespace().equals(this.id.getNamespace().getDecoded())) {
+ result.add(item.getName());
+ }
+ }
+
+ String cacheContent = null;
+ try {
+ cacheContent = Utils.mapper.writeValueAsString(result);
+ } catch (JsonProcessingException e) {
+ XSDImportResource.logger.error("Could not generate cache content", e);
+ }
+ try {
+ Repository.INSTANCE.putContentToFile(cacheRef, cacheContent, MediaType.APPLICATION_JSON_TYPE);
+ } catch (IOException e) {
+ XSDImportResource.logger.error("Could not update cache", e);
+ }
+ } else {
+ // read content from cache
+ // cache should contain most recent information
+ try (InputStream is = Repository.INSTANCE.newInputStream(cacheRef)) {
+ result = Utils.mapper.readValue(is, java.util.List.class);
+ } catch (IOException e) {
+ XSDImportResource.logger.error("Could not read from cache", e);
+ result = Collections.emptyList();
+ }
+ }
+ return result;
+ }
+
+ public Collection<String> getAllDefinedElementsLocalNames() {
+ return this.getAllDefinedLocalNames(XSConstants.ELEMENT_DECLARATION);
+ }
+
+ public Collection<String> getAllDefinedTypesLocalNames() {
+ return this.getAllDefinedLocalNames(XSConstants.TYPE_DEFINITION);
+ }
+
+ @GET
+ @RestDoc(methodDescription = "May be used by the modeler to generate an XML editor based on the XML schema")
+ // we cannot use "MimeTypes.MIMETYPE_XSD" here as the latter is "text/xml" and org.eclipse.winery.repository.resources.AbstractComponentInstanceResource.getDefinitionsAsResponse() also produces text/xml
+ @Produces("text/xsd")
+ public Response getXSD() {
+ String location;
+ if ((location = this.getLocation()) == null) {
+ return Response.status(Status.NOT_FOUND).build();
+ }
+ RepositoryFileReference ref = new RepositoryFileReference(this.id, location);
+ return BackendUtils.returnRepoPath(ref, null);
+ }
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/imports/xsdimports/XSDImportsResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/imports/xsdimports/XSDImportsResource.java
new file mode 100644
index 0000000..61af3bd
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/imports/xsdimports/XSDImportsResource.java
@@ -0,0 +1,124 @@
+/*******************************************************************************
+ * 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.repository.resources.imports.xsdimports;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+
+import org.eclipse.winery.common.RepositoryFileReference;
+import org.eclipse.winery.common.ids.Namespace;
+import org.eclipse.winery.common.ids.definitions.imports.XSDImportId;
+import org.eclipse.winery.repository.Utils;
+import org.eclipse.winery.repository.backend.Repository;
+import org.eclipse.winery.repository.resources.AbstractComponentsResource;
+import org.restdoc.annotations.RestDoc;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+
+/**
+ * Manages all imports of type XML Schema Definition <br />
+ * The actual implementation is done in the AbstractComponentsResource
+ *
+ * FIXME: This class should be generalized to handle ImportId
+ */
+public class XSDImportsResource extends AbstractComponentsResource<XSDImportResource> {
+
+ @Path("{namespace}/")
+ @GET
+ @RestDoc(methodDescription = "Returns all available local names of defined elements in this namespace")
+ @Produces(MediaType.APPLICATION_JSON)
+ public String getAllElementLocalNames(@PathParam("namespace") String nsString, @QueryParam(value = "elements") String returnElements, @QueryParam(value = "types") String returnTypes) {
+ // returnElements is not read as either types or elements may be read
+ Set<String> allNCNames = this.getAllElementLocalNamesAsSet(nsString, returnTypes != null);
+ try {
+ return Utils.mapper.writeValueAsString(allNCNames);
+ } catch (JsonProcessingException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ /**
+ * @param nsString the namesapce as String
+ * @param returnTypes true: return ElementTypes, false: return Elements
+ */
+ private Set<String> getAllElementLocalNamesAsSet(final String nsString, final boolean getTypes) {
+ Set<XSDImportId> importsOfNS = this.getImportsOfNS(nsString);
+
+ // TreeSet enables ordering
+ Set<String> allNCNames = new TreeSet<String>();
+
+ for (XSDImportId imp : importsOfNS) {
+ XSDImportResource res = new XSDImportResource(imp);
+ Collection<String> col;
+ if (getTypes) {
+ col = res.getAllDefinedTypesLocalNames();
+ } else {
+ col = res.getAllDefinedElementsLocalNames();
+ }
+ allNCNames.addAll(col);
+ }
+ return allNCNames;
+ }
+
+ /**
+ * Finds out all imports belonging to the given namespace
+ *
+ * @param nsString the namespace to query
+ */
+ private Set<XSDImportId> getImportsOfNS(final String nsString) {
+ // FIXME: Currently not supported by the repository, therefore, we filter by hand
+ Set<XSDImportId> allImports = Repository.INSTANCE.getAllTOSCAComponentIds(XSDImportId.class);
+ Namespace ns = new Namespace(nsString, true);
+ Set<XSDImportId> importsOfNs = new HashSet<XSDImportId>();
+ for (XSDImportId imp : allImports) {
+ if (imp.getNamespace().equals(ns)) {
+ importsOfNs.add(imp);
+ }
+ }
+ return importsOfNs;
+ }
+
+ /**
+ * Returns a mapping from localnames to XSD files, containing the defined
+ * local names for the given namespace
+ */
+ public Map<String, RepositoryFileReference> getMapFromLocalNameToXSD(final String nsString, final boolean getTypes) {
+ Set<XSDImportId> importsOfNS = this.getImportsOfNS(nsString);
+ Map<String, RepositoryFileReference> result = new HashMap<>();
+ for (XSDImportId imp : importsOfNS) {
+ XSDImportResource res = new XSDImportResource(imp);
+ Collection<String> col;
+ if (getTypes) {
+ col = res.getAllDefinedTypesLocalNames();
+ } else {
+ col = res.getAllDefinedElementsLocalNames();
+ }
+ RepositoryFileReference ref = res.getXSDFileReference();
+ for (String localName : col) {
+ result.put(localName, ref);
+ }
+ }
+ return result;
+ }
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/interfaces/InterfaceResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/interfaces/InterfaceResource.java
new file mode 100644
index 0000000..b7b7c15
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/interfaces/InterfaceResource.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * 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.repository.resources.interfaces;
+
+import java.util.List;
+
+import javax.ws.rs.Path;
+
+import org.eclipse.winery.model.tosca.TInterface;
+import org.eclipse.winery.model.tosca.TOperation;
+import org.eclipse.winery.repository.resources._support.IPersistable;
+import org.eclipse.winery.repository.resources._support.collections.IIdDetermination;
+import org.eclipse.winery.repository.resources._support.collections.withid.EntityWithIdResource;
+
+public class InterfaceResource extends EntityWithIdResource<TInterface> {
+
+ private final TInterface iface;
+
+
+ public InterfaceResource(IIdDetermination<TInterface> idDetermination, TInterface o, int idx, List<TInterface> list, IPersistable res) {
+ super(idDetermination, o, idx, list, res);
+ this.iface = o;
+ }
+
+ /**
+ * required by artifacts.jsp
+ */
+ public String getName() {
+ return this.iface.getName();
+ }
+
+ @Path("operations/")
+ public OperationsResource getOperationsResouce() {
+ List<TOperation> list = this.o.getOperation();
+ return new OperationsResource(list, this.res);
+ }
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/interfaces/InterfacesResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/interfaces/InterfacesResource.java
new file mode 100644
index 0000000..4acfbd9
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/interfaces/InterfacesResource.java
@@ -0,0 +1,140 @@
+/*******************************************************************************
+ * 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.repository.resources.interfaces;
+
+import java.util.List;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.POST;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+
+import org.apache.commons.lang3.StringUtils;
+import org.eclipse.winery.model.tosca.TInterface;
+import org.eclipse.winery.repository.backend.BackendUtils;
+import org.eclipse.winery.repository.resources._support.IPersistable;
+import org.eclipse.winery.repository.resources._support.collections.withid.EntityWithIdCollectionResource;
+import org.eclipse.winery.repository.resources.entitytypes.TopologyGraphElementEntityTypeResource;
+import org.eclipse.winery.repository.resources.entitytypes.relationshiptypes.RelationshipTypeResource;
+import org.restdoc.annotations.RestDoc;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.sun.jersey.api.view.Viewable;
+
+public class InterfacesResource extends EntityWithIdCollectionResource<InterfaceResource, TInterface> {
+
+ private static final Logger logger = LoggerFactory.getLogger(InterfacesResource.class);
+
+ private TopologyGraphElementEntityTypeResource typeResource;
+
+ private String urlPrefix;
+
+
+ public InterfacesResource(IPersistable res, List<TInterface> list) {
+ super(InterfaceResource.class, TInterface.class, list, res);
+ }
+
+ /**
+ * @param urlPrefix prefix to be prepended to the URL.
+ * "source"|"target"|null. E.g., "source" for "sourceinterfaces"
+ */
+ public InterfacesResource(String urlPrefix, List<TInterface> list, IPersistable typeResource) {
+ super(InterfaceResource.class, TInterface.class, list, typeResource);
+ this.urlPrefix = urlPrefix;
+ this.typeResource = (TopologyGraphElementEntityTypeResource) typeResource;
+ }
+
+ @Override
+ public Viewable getHTML() {
+ return new Viewable("/jsp/interfaces/interfaces.jsp", this);
+ }
+
+ /**
+ * Implementation base: <br />
+ * {@link org.eclipse.winery.repository.resources.AbstractComponentResource.
+ * onPost(String)}
+ *
+ * @return entity: id of the stored interface
+ */
+ @POST
+ @RestDoc(methodDescription = "Creates a new interface. Returns conflict if interface already exists")
+ @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
+ @Produces(MediaType.TEXT_PLAIN)
+ public Response onPost(@FormParam("interfaceName") String interfaceName) {
+ if (StringUtils.isEmpty(interfaceName)) {
+ return Response.status(Status.BAD_REQUEST).entity("null interfaceName").build();
+ }
+
+ TInterface iface = new TInterface();
+ iface.setName(interfaceName);
+
+ // check for duplicates
+ // return "conflict" if interface already exists
+ if (this.alreadyContains(iface)) {
+ return Response.status(Status.CONFLICT).build();
+ }
+
+ this.list.add(iface);
+ return BackendUtils.persist(this.res);
+ }
+
+ /**
+ * Required by interfaces.jsp
+ */
+ public String getUrlPrefix() {
+ return this.urlPrefix;
+ }
+
+ @Override
+ public String getId(TInterface entity) {
+ return entity.getName();
+ }
+
+ /**
+ * @return the namespace of the node/relationship type
+ */
+ public String getNamespace() {
+ return this.typeResource.getId().getNamespace().getDecoded();
+ }
+
+ /**
+ * @return the name of the node/relationship type
+ */
+ public String getName() {
+ return this.typeResource.getName();
+ }
+
+ public String getRelationshipTypeOrNodeTypeURLFragment() {
+ if (this.typeResource instanceof RelationshipTypeResource) {
+ return "relationshiptype";
+ } else {
+ return "nodetype";
+ }
+ }
+
+ public String getRelationshipTypeOrNodeType() {
+ if (this.typeResource instanceof RelationshipTypeResource) {
+ return "Relationship Type";
+ } else {
+ return "Node Type";
+ }
+ }
+
+ public String getTypeQName() {
+ String res = this.typeResource.getId().getQName().toString();
+ return res;
+ }
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/interfaces/OperationResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/interfaces/OperationResource.java
new file mode 100644
index 0000000..7657e99
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/interfaces/OperationResource.java
@@ -0,0 +1,71 @@
+/*******************************************************************************
+ * 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.repository.resources.interfaces;
+
+import java.util.List;
+
+import javax.ws.rs.Path;
+
+import org.eclipse.winery.model.tosca.TInterface;
+import org.eclipse.winery.model.tosca.TOperation;
+import org.eclipse.winery.model.tosca.TOperation.InputParameters;
+import org.eclipse.winery.model.tosca.TOperation.OutputParameters;
+import org.eclipse.winery.repository.resources._support.IPersistable;
+import org.eclipse.winery.repository.resources._support.collections.IIdDetermination;
+import org.eclipse.winery.repository.resources._support.collections.withid.EntityWithIdResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class OperationResource extends EntityWithIdResource<TOperation> {
+
+ private static final Logger logger = LoggerFactory.getLogger(OperationResource.class);
+
+
+ public OperationResource(IIdDetermination<TOperation> idDetermination, TOperation o, int idx, List<TOperation> list, IPersistable res) {
+ super(idDetermination, o, idx, list, res);
+ }
+
+ /**
+ * @return TOperation object for the corresponding object of operationName
+ * in the operation list contained in the given interface. null if
+ * interface could not be found in list
+ */
+ public static TOperation getTOperation(String operationName, TInterface iface) {
+ List<TOperation> operationList = iface.getOperation();
+ for (TOperation op : operationList) {
+ if (op.getName().equals(operationName)) {
+ return op;
+ }
+ }
+ return null;
+ }
+
+ @Path("inputparameters/")
+ public ParametersResource getInputparameters() {
+ InputParameters inputParameters = this.o.getInputParameters();
+ if (inputParameters == null) {
+ inputParameters = new InputParameters();
+ this.o.setInputParameters(inputParameters);
+ }
+ return new ParametersResource(inputParameters.getInputParameter(), this.res);
+ }
+
+ @Path("outputparameters/")
+ public ParametersResource getOutputparameters() {
+ OutputParameters outputParameters = this.o.getOutputParameters();
+ if (outputParameters == null) {
+ outputParameters = new OutputParameters();
+ this.o.setOutputParameters(outputParameters);
+ }
+ return new ParametersResource(outputParameters.getOutputParameter(), this.res);
+ }
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/interfaces/OperationsResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/interfaces/OperationsResource.java
new file mode 100644
index 0000000..3e214e4
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/interfaces/OperationsResource.java
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * 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.repository.resources.interfaces;
+
+import java.util.List;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.POST;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+
+import org.apache.commons.lang3.StringUtils;
+import org.eclipse.winery.model.tosca.TOperation;
+import org.eclipse.winery.common.Util;
+import org.eclipse.winery.repository.backend.BackendUtils;
+import org.eclipse.winery.repository.resources._support.IPersistable;
+import org.eclipse.winery.repository.resources._support.collections.withid.EntityWithIdCollectionResource;
+import org.restdoc.annotations.RestDocParam;
+
+import com.sun.jersey.api.view.Viewable;
+
+public class OperationsResource extends EntityWithIdCollectionResource<OperationResource, TOperation> {
+
+ public OperationsResource(List<TOperation> list, IPersistable res) {
+ super(OperationResource.class, TOperation.class, list, res);
+ }
+
+ @Override
+ public String getId(TOperation entity) {
+ return entity.getName();
+ }
+
+ @Override
+ public Viewable getHTML() {
+ throw new IllegalStateException("Not yet implemented.");
+ }
+
+ @POST
+ @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
+ @Produces(MediaType.TEXT_PLAIN)
+ public Response createOperation(@FormParam("name") @RestDocParam(description = "used as name and id") String operationName) {
+ if (StringUtils.isEmpty(operationName)) {
+ return Response.status(Status.BAD_REQUEST).entity("operationName not provided").build();
+ }
+
+ operationName = Util.URLdecode(operationName);
+
+ // TODO: check for duplicates as in instance states
+
+ TOperation operation = new TOperation();
+ operation.setName(operationName);
+ this.list.add(operation);
+
+ return BackendUtils.persist(this.res);
+ }
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/interfaces/ParameterResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/interfaces/ParameterResource.java
new file mode 100644
index 0000000..46662fd
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/interfaces/ParameterResource.java
@@ -0,0 +1,62 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2013,2015 University of Stuttgart.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ * Oliver Kopp - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.winery.repository.resources.interfaces;
+
+import java.util.List;
+
+import javax.ws.rs.FormParam;
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Response;
+
+import org.eclipse.winery.model.tosca.TBoolean;
+import org.eclipse.winery.model.tosca.TParameter;
+import org.eclipse.winery.repository.backend.BackendUtils;
+import org.eclipse.winery.repository.resources._support.IPersistable;
+import org.eclipse.winery.repository.resources._support.collections.IIdDetermination;
+import org.eclipse.winery.repository.resources._support.collections.withid.EntityWithIdResource;
+
+public class ParameterResource extends EntityWithIdResource<TParameter> {
+
+ public ParameterResource(IIdDetermination<TParameter> idDetermination, TParameter o, int idx, List<TParameter> list, IPersistable res) {
+ super(idDetermination, o, idx, list, res);
+ }
+
+ @GET
+ @Path("type")
+ public String getType() {
+ return this.o.getType();
+ }
+
+ @PUT
+ @Path("type")
+ public Response putType(@FormParam(value = "type") String type) {
+ this.o.setType(type);
+ return BackendUtils.persist(this.res);
+ }
+
+ @GET
+ @Path("required")
+ public String getRequired() {
+ return this.o.getRequired().toString();
+ }
+
+ @PUT
+ @Path("required")
+ public Response putRequired(@FormParam(value = "required") String required) {
+ TBoolean tb = TBoolean.valueOf(required);
+ this.o.setRequired(tb);
+ return BackendUtils.persist(this.res);
+ }
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/interfaces/ParametersResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/interfaces/ParametersResource.java
new file mode 100644
index 0000000..c3afcbc
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/interfaces/ParametersResource.java
@@ -0,0 +1,99 @@
+/*******************************************************************************
+ * 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.repository.resources.interfaces;
+
+import java.util.List;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.POST;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+
+import org.apache.commons.lang3.StringUtils;
+import org.eclipse.winery.model.tosca.TBoolean;
+import org.eclipse.winery.model.tosca.TParameter;
+import org.eclipse.winery.repository.backend.BackendUtils;
+import org.eclipse.winery.repository.resources._support.IPersistable;
+import org.eclipse.winery.repository.resources._support.collections.withid.EntityWithIdCollectionResource;
+import org.restdoc.annotations.RestDocParam;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.sun.jersey.api.view.Viewable;
+
+public class ParametersResource extends EntityWithIdCollectionResource<ParameterResource, TParameter> {
+
+ private static final Logger logger = LoggerFactory.getLogger(ParametersResource.class);
+
+
+ public ParametersResource(List<TParameter> parameters, IPersistable typeResource) {
+ super(ParameterResource.class, TParameter.class, parameters, typeResource);
+ }
+
+ @POST
+ @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
+ @Produces(MediaType.TEXT_PLAIN)
+ // @formatter:off
+ public Response createParamter(
+ @FormParam("name") String name,
+ @FormParam("type") String type,
+ @FormParam("required") @RestDocParam(description="type tYesNo, not Boolean. For convenience, on/off is also supported. In case this parameter is not provided, 'off' is assumed. This is in contrast to the specification, but it eases implementing the UI") String required) {
+ // @formatter:on
+ if (StringUtils.isEmpty(name)) {
+ return Response.status(Status.BAD_REQUEST).entity("name must not be null").build();
+ }
+ if (StringUtils.isEmpty(type)) {
+ return Response.status(Status.BAD_REQUEST).entity("type must not be null").build();
+ }
+
+ TParameter param = new TParameter();
+ param.setName(name);
+ param.setType(type);
+ TBoolean tb;
+ if (required == null) {
+ // The specification states that the default value is "yes"
+ // We assume "no", because Chrome does not send the checkbox data if a checkbox is not checked
+ tb = TBoolean.NO;
+ } else {
+ if (required.equalsIgnoreCase("on")) {
+ tb = TBoolean.YES;
+ } else if (required.equalsIgnoreCase("off")) {
+ tb = TBoolean.NO;
+ } else {
+ try {
+ tb = TBoolean.valueOf(required);
+ } catch (java.lang.IllegalArgumentException e) {
+ return Response.status(Status.BAD_REQUEST).entity("Wrong format of required").build();
+ }
+ }
+ }
+ param.setRequired(tb);
+
+ this.list.add(param);
+
+ return BackendUtils.persist(this.res);
+ }
+
+ @Override
+ public String getId(TParameter entity) {
+ return entity.getName();
+ }
+
+ @Override
+ public Viewable getHTML() {
+ throw new IllegalStateException("Not yet implemented.");
+ }
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/package-info.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/package-info.java
new file mode 100644
index 0000000..ea94a21
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/package-info.java
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+/**
+ * This package contains the REST resources
+ *
+ * Mostly, they produces Viewables, where a JSP and the current resource is
+ * passed As the JSP itself handles plain Java objects and not Responses, the
+ * resources have also methods returning POJOs. This might be ugly design, but
+ * was quick to implement.
+ *
+ * The package structure is mirrored in src/main/webapp/jsp to ease finding the
+ * JSPs belonging to a resource.
+ *
+ * The resources are <em>not</em> in line with the resource model of the TOSCA
+ * container. Especially, we do not employ HATEOAS here.
+ */
+package org.eclipse.winery.repository.resources;
+
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/ServiceTemplateResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/ServiceTemplateResource.java
new file mode 100644
index 0000000..6a249df
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/ServiceTemplateResource.java
@@ -0,0 +1,263 @@
+/*******************************************************************************
+ * 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.repository.resources.servicetemplates;
+
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import java.util.SortedSet;
+
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+import javax.xml.namespace.QName;
+
+import org.eclipse.winery.common.RepositoryFileReference;
+import org.eclipse.winery.common.ids.XMLId;
+import org.eclipse.winery.common.ids.definitions.ServiceTemplateId;
+import org.eclipse.winery.common.ids.elements.PlanId;
+import org.eclipse.winery.common.ids.elements.PlansId;
+import org.eclipse.winery.model.tosca.TBoundaryDefinitions;
+import org.eclipse.winery.model.tosca.TExtensibleElements;
+import org.eclipse.winery.model.tosca.TPlan;
+import org.eclipse.winery.model.tosca.TPlan.PlanModelReference;
+import org.eclipse.winery.model.tosca.TPlans;
+import org.eclipse.winery.model.tosca.TServiceTemplate;
+import org.eclipse.winery.model.tosca.TTopologyTemplate;
+import org.eclipse.winery.repository.Utils;
+import org.eclipse.winery.repository.backend.BackendUtils;
+import org.eclipse.winery.repository.backend.Repository;
+import org.eclipse.winery.repository.resources.AbstractComponentInstanceWithReferencesResource;
+import org.eclipse.winery.repository.resources.IHasName;
+import org.eclipse.winery.repository.resources.servicetemplates.boundarydefinitions.BoundaryDefinitionsResource;
+import org.eclipse.winery.repository.resources.servicetemplates.plans.PlansResource;
+import org.eclipse.winery.repository.resources.servicetemplates.selfserviceportal.SelfServicePortalResource;
+import org.eclipse.winery.repository.resources.servicetemplates.topologytemplates.TopologyTemplateResource;
+import org.restdoc.annotations.RestDoc;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ServiceTemplateResource extends AbstractComponentInstanceWithReferencesResource implements IHasName {
+
+ private static final Logger logger = LoggerFactory.getLogger(ServiceTemplateResource.class);
+
+
+ public ServiceTemplateResource(ServiceTemplateId id) {
+ super(id);
+ }
+
+ /** sub-resources **/
+
+ @Path("topologytemplate/")
+ public TopologyTemplateResource getTopologyTemplateResource() {
+ if (this.getServiceTemplate().getTopologyTemplate() == null) {
+ // the main service template resource exists
+ // default topology template: empty template
+ // This eases the JSPs etc. and is valid as a non-existant topology template is equal to an empty one
+ this.getServiceTemplate().setTopologyTemplate(new TTopologyTemplate());
+ }
+ return new TopologyTemplateResource(this);
+ }
+
+ @Path("plans/")
+ public PlansResource getPlansResource() {
+ TPlans plans = this.getServiceTemplate().getPlans();
+ if (plans == null) {
+ plans = new TPlans();
+ this.getServiceTemplate().setPlans(plans);
+ }
+ return new PlansResource(plans.getPlan(), this);
+ }
+
+ @Path("selfserviceportal/")
+ public SelfServicePortalResource getSelfServicePortalResource() {
+ return new SelfServicePortalResource(this);
+ }
+
+ @Path("boundarydefinitions/")
+ public BoundaryDefinitionsResource getBoundaryDefinitionsResource() {
+ TBoundaryDefinitions boundaryDefinitions = this.getServiceTemplate().getBoundaryDefinitions();
+ if (boundaryDefinitions == null) {
+ boundaryDefinitions = new TBoundaryDefinitions();
+ this.getServiceTemplate().setBoundaryDefinitions(boundaryDefinitions);
+ }
+ return new BoundaryDefinitionsResource(this, boundaryDefinitions);
+ }
+
+ @Override
+ public String getName() {
+ String name = this.getServiceTemplate().getName();
+ if (name == null) {
+ // place default
+ name = this.getId().getXmlId().getDecoded();
+ }
+ return name;
+ }
+
+ @Override
+ public Response setName(String name) {
+ this.getServiceTemplate().setName(name);
+ return BackendUtils.persist(this);
+ }
+
+ // @formatter:off
+ @GET
+ @RestDoc(methodDescription="Returns the associated node type, which can be substituted by this service template.<br />" +
+ "@return a QName of the form {namespace}localName is returned.")
+ @Path("substitutableNodeType")
+ @Produces(MediaType.TEXT_PLAIN)
+ // @formatter:on
+ public Response getSubstitutableNodeTypeAsResponse() {
+ QName qname = this.getServiceTemplate().getSubstitutableNodeType();
+ if (qname == null) {
+ return Response.status(Status.NOT_FOUND).build();
+ } else {
+ return Response.ok(qname.toString()).build();
+ }
+ }
+
+ /**
+ *
+ * @return null if there is no substitutable node type
+ */
+ public QName getSubstitutableNodeType() {
+ return this.getServiceTemplate().getSubstitutableNodeType();
+ }
+
+ @DELETE
+ @RestDoc(methodDescription = "Removes the association to substitutable node type")
+ @Path("substitutableNodeType")
+ public Response deleteSubstitutableNodeType() {
+ this.getServiceTemplate().setSubstitutableNodeType(null);
+ BackendUtils.persist(this);
+ return Response.noContent().build();
+ }
+
+ public TServiceTemplate getServiceTemplate() {
+ return (TServiceTemplate) this.getElement();
+ }
+
+ @Override
+ protected TExtensibleElements createNewElement() {
+ return new TServiceTemplate();
+ }
+
+ @Override
+ protected void copyIdToFields() {
+ this.getServiceTemplate().setId(this.getId().getXmlId().getDecoded());
+ this.getServiceTemplate().setTargetNamespace(this.getId().getNamespace().getDecoded());
+ }
+
+ /**
+ * Synchronizes the known plans with the data in the XML. When there is a
+ * stored file, but no known entry in the XML, we guess "BPEL" as language
+ * and "build plan" as type.
+ *
+ * @throws IOException
+ */
+ @Override
+ public void synchronizeReferences() {
+ // locally stored plans
+ TPlans plans = this.getServiceTemplate().getPlans();
+
+ // plans stored in the repository
+ PlansId plansContainerId = new PlansId((ServiceTemplateId) this.getId());
+ SortedSet<PlanId> nestedPlans = Repository.INSTANCE.getNestedIds(plansContainerId, PlanId.class);
+
+ Set<PlanId> plansToAdd = new HashSet<PlanId>();
+ plansToAdd.addAll(nestedPlans);
+
+ if (nestedPlans.isEmpty()) {
+ if (plans == null) {
+ // data on the file system equals the data -> no plans
+ return;
+ } else {
+ // we have to check for equality later
+ }
+ }
+
+ if (plans == null) {
+ plans = new TPlans();
+ this.getServiceTemplate().setPlans(plans);
+ }
+
+ for (Iterator<TPlan> iterator = plans.getPlan().iterator(); iterator.hasNext();) {
+ TPlan plan = iterator.next();
+ if (plan.getPlanModel() != null) {
+ // in case, a plan is directly contained in a Model element, we do not need to do anything
+ continue;
+ }
+ PlanModelReference planModelReference = plan.getPlanModelReference();
+ if ((planModelReference = plan.getPlanModelReference()) != null) {
+ String ref = planModelReference.getReference();
+ if ((ref == null) || ref.startsWith("../")) {
+ // references to local plans start with "../"
+ // special case (due to errors in the importer): empty PlanModelReference field
+ if (plan.getId() == null) {
+ // invalid plan entry: no id.
+ // we remove the entry
+ iterator.remove();
+ continue;
+ }
+ PlanId planId = new PlanId(plansContainerId, new XMLId(plan.getId(), false));
+ if (nestedPlans.contains(planId)) {
+ // everything allright
+ // we do NOT need to add the plan on the HDD to the XML
+ plansToAdd.remove(planId);
+ } else {
+ // no local storage for the plan, we remove it from the XML
+ iterator.remove();
+ }
+ }
+ }
+ }
+
+ // add all plans locally stored, but not contained in the XML, as plan element to the plans of the service template.
+ List<TPlan> thePlans = plans.getPlan();
+ for (PlanId planId : plansToAdd) {
+ SortedSet<RepositoryFileReference> files = Repository.INSTANCE.getContainedFiles(planId);
+ if (files.size() != 1) {
+ throw new IllegalStateException("Currently, only one file per plan is supported.");
+ }
+ RepositoryFileReference ref = files.iterator().next();
+
+ TPlan plan = new TPlan();
+ plan.setId(planId.getXmlId().getDecoded());
+ plan.setName(planId.getXmlId().getDecoded());
+ plan.setPlanType(org.eclipse.winery.repository.Constants.TOSCA_PLANTYPE_BUILD_PLAN);
+ plan.setPlanLanguage(org.eclipse.winery.common.constants.Namespaces.URI_BPEL20_EXECUTABLE);
+
+ // create a PlanModelReferenceElement pointing to that file
+ String path = Utils.getURLforPathInsideRepo(BackendUtils.getPathInsideRepo(ref));
+ // path is relative from the definitions element
+ path = "../" + path;
+ PlanModelReference pref = new PlanModelReference();
+ pref.setReference(path);
+
+ plan.setPlanModelReference(pref);
+ thePlans.add(plan);
+ }
+
+ try {
+ this.persist();
+ } catch (IOException e) {
+ throw new IllegalStateException("Could not persist resource", e);
+ }
+ return;
+ }
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/ServiceTemplatesResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/ServiceTemplatesResource.java
new file mode 100644
index 0000000..fd8b82c
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/ServiceTemplatesResource.java
@@ -0,0 +1,18 @@
+/*******************************************************************************
+ * 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.repository.resources.servicetemplates;
+
+import org.eclipse.winery.repository.resources.AbstractComponentsResource;
+
+public class ServiceTemplatesResource extends AbstractComponentsResource<ServiceTemplateResource> {
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/BoundaryDefinitionsJSPData.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/BoundaryDefinitionsJSPData.java
new file mode 100644
index 0000000..0d4b141
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/BoundaryDefinitionsJSPData.java
@@ -0,0 +1,113 @@
+package org.eclipse.winery.repository.resources.servicetemplates.boundarydefinitions;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.SortedSet;
+
+import javax.xml.namespace.QName;
+
+import org.apache.commons.lang3.StringEscapeUtils;
+import org.apache.taglibs.standard.functions.Functions;
+import org.eclipse.winery.common.ModelUtilities;
+import org.eclipse.winery.common.ids.definitions.PolicyTypeId;
+import org.eclipse.winery.model.tosca.TBoundaryDefinitions;
+import org.eclipse.winery.model.tosca.TBoundaryDefinitions.Properties;
+import org.eclipse.winery.model.tosca.TPlan;
+import org.eclipse.winery.model.tosca.TPlans;
+import org.eclipse.winery.model.tosca.TServiceTemplate;
+import org.eclipse.winery.repository.Utils;
+import org.eclipse.winery.repository.backend.BackendUtils;
+import org.eclipse.winery.repository.backend.Repository;
+import org.eclipse.winery.repository.datatypes.TypeWithShortName;
+import org.eclipse.winery.repository.datatypes.select2.Select2DataItem;
+import org.eclipse.winery.repository.resources.admin.types.ConstraintTypesManager;
+
+public class BoundaryDefinitionsJSPData {
+
+ private final TServiceTemplate ste;
+ private final TBoundaryDefinitions defs;
+ private URI baseURI;
+
+
+ /**
+ *
+ * @param ste the service template of the boundary definitions. Required to
+ * get a list of all plans
+ * @param baseURI the base URI of the service. Requried for rendering the
+ * topology template for the selections
+ */
+ public BoundaryDefinitionsJSPData(TServiceTemplate ste, URI baseURI) {
+ this.ste = ste;
+ this.defs = ste.getBoundaryDefinitions();
+ this.baseURI = baseURI;
+ }
+
+ private String getDefinedProperties() {
+ Properties p = ModelUtilities.getProperties(this.defs);
+ Object o = p.getAny();
+ if (o == null) {
+ // nothing stored -> return empty string
+ return "";
+ } else {
+ // something stored --> return that
+ return Utils.getXMLAsString(p.getAny());
+ }
+ }
+
+ /**
+ * Helper method to return an initialized properties object only containing
+ * the user-defined properties. The TOSCA properties-element is not returned
+ * as the TOSCA XSD allows a single element only
+ */
+ public String getDefinedPropertiesAsEscapedHTML() {
+ String s = this.getDefinedProperties();
+ s = StringEscapeUtils.escapeHtml4(s);
+ return s;
+ }
+
+ public String getDefinedPropertiesAsJSONString() {
+ String s = this.getDefinedProperties();
+ s = StringEscapeUtils.escapeEcmaScript(s);
+ return s;
+ }
+
+ public TBoundaryDefinitions getDefs() {
+ return this.defs;
+ }
+
+ public String getBoundaryDefinitionsAsXMLStringEncoded() {
+ String res = Utils.getXMLAsString(this.defs);
+ return Functions.escapeXml(res);
+ }
+
+ public Collection<TypeWithShortName> getConstraintTypes() {
+ return ConstraintTypesManager.INSTANCE.getTypes();
+ }
+
+ public Collection<QName> getAllPolicyTypes() {
+ SortedSet<PolicyTypeId> allTOSCAComponentIds = Repository.INSTANCE.getAllTOSCAComponentIds(PolicyTypeId.class);
+ return BackendUtils.convertTOSCAComponentIdCollectionToQNameCollection(allTOSCAComponentIds);
+ }
+
+ public String getRepositoryURL() {
+ return this.baseURI.toString();
+ }
+
+ public List<Select2DataItem> getlistOfAllPlans() {
+ TPlans plans = this.ste.getPlans();
+ if (plans == null) {
+ return null;
+ } else {
+ List<Select2DataItem> res = new ArrayList<>(plans.getPlan().size());
+ for (TPlan plan : plans.getPlan()) {
+ String id = plan.getId();
+ String name = ModelUtilities.getNameWithIdFallBack(plan);
+ Select2DataItem di = new Select2DataItem(id, name);
+ res.add(di);
+ }
+ return res;
+ }
+ }
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/BoundaryDefinitionsResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/BoundaryDefinitionsResource.java
new file mode 100644
index 0000000..58dfbe9
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/BoundaryDefinitionsResource.java
@@ -0,0 +1,144 @@
+/*******************************************************************************
+ * Copyright (c) 2013-2014 University of Stuttgart.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ * Oliver Kopp - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.winery.repository.resources.servicetemplates.boundarydefinitions;
+
+import java.util.List;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+
+import org.eclipse.winery.common.ModelUtilities;
+import org.eclipse.winery.model.tosca.TBoundaryDefinitions;
+import org.eclipse.winery.model.tosca.TBoundaryDefinitions.Capabilities;
+import org.eclipse.winery.model.tosca.TBoundaryDefinitions.Interfaces;
+import org.eclipse.winery.model.tosca.TBoundaryDefinitions.Policies;
+import org.eclipse.winery.model.tosca.TBoundaryDefinitions.Properties;
+import org.eclipse.winery.model.tosca.TBoundaryDefinitions.Properties.PropertyMappings;
+import org.eclipse.winery.model.tosca.TBoundaryDefinitions.Requirements;
+import org.eclipse.winery.model.tosca.TCapabilityRef;
+import org.eclipse.winery.model.tosca.TRequirementRef;
+import org.eclipse.winery.repository.backend.BackendUtils;
+import org.eclipse.winery.repository.resources.servicetemplates.ServiceTemplateResource;
+import org.eclipse.winery.repository.resources.servicetemplates.boundarydefinitions.interfaces.InterfacesResource;
+import org.eclipse.winery.repository.resources.servicetemplates.boundarydefinitions.policies.PoliciesResource;
+import org.eclipse.winery.repository.resources.servicetemplates.boundarydefinitions.reqscaps.CapabilitiesResource;
+import org.eclipse.winery.repository.resources.servicetemplates.boundarydefinitions.reqscaps.RequirementsResource;
+import org.restdoc.annotations.RestDoc;
+import org.restdoc.annotations.RestDocParam;
+import org.w3c.dom.Document;
+
+import com.sun.jersey.api.view.Viewable;
+
+public class BoundaryDefinitionsResource {
+
+ private final ServiceTemplateResource serviceTemplateResource;
+ private final TBoundaryDefinitions boundaryDefinitions;
+
+
+ public BoundaryDefinitionsResource(ServiceTemplateResource serviceTemplateResource, TBoundaryDefinitions boundaryDefinitions) {
+ this.serviceTemplateResource = serviceTemplateResource;
+ this.boundaryDefinitions = boundaryDefinitions;
+ }
+
+ @GET
+ @Produces(MediaType.TEXT_HTML)
+ public Viewable getHTML(@Context UriInfo uriInfo) {
+ return new Viewable("/jsp/servicetemplates/boundarydefinitions/boundarydefinitions.jsp", new BoundaryDefinitionsJSPData(this.serviceTemplateResource.getServiceTemplate(), uriInfo.getBaseUri()));
+ }
+
+ @PUT
+ @RestDoc(methodDescription = "Replaces the boundary definitions by the information given in the XML")
+ @Consumes(MediaType.TEXT_XML)
+ public Response setModel(TBoundaryDefinitions boundaryDefinitions) {
+ this.serviceTemplateResource.getServiceTemplate().setBoundaryDefinitions(boundaryDefinitions);
+ return BackendUtils.persist(this.serviceTemplateResource);
+ }
+
+ @Path("properties/")
+ @PUT
+ @Consumes(MediaType.TEXT_XML)
+ @RestDoc(resourceDescription = "Models the user-defined properties. The property mappings go into a separate resource propertymappings.")
+ public Response putProperties(@RestDocParam(description = "Stored properties. The XSD allows a single element only. Therefore, we go for the contained element") Document doc) {
+ org.eclipse.winery.model.tosca.TBoundaryDefinitions.Properties properties = ModelUtilities.getProperties(this.boundaryDefinitions);
+ properties.setAny(doc.getDocumentElement());
+ return BackendUtils.persist(this.serviceTemplateResource);
+ }
+
+ @Path("requirements/")
+ public RequirementsResource getRequiremensResource() {
+ Requirements requirements = this.boundaryDefinitions.getRequirements();
+ if (requirements == null) {
+ requirements = new Requirements();
+ this.boundaryDefinitions.setRequirements(requirements);
+ }
+ List<TRequirementRef> refs = requirements.getRequirement();
+ return new RequirementsResource(this.serviceTemplateResource, refs);
+ }
+
+ @Path("capabilities/")
+ public CapabilitiesResource getCapabilitiesResource() {
+ Capabilities caps = this.boundaryDefinitions.getCapabilities();
+ if (caps == null) {
+ caps = new Capabilities();
+ this.boundaryDefinitions.setCapabilities(caps);
+ }
+ List<TCapabilityRef> refs = caps.getCapability();
+ return new CapabilitiesResource(this.serviceTemplateResource, refs);
+ }
+
+ @Path("policies/")
+ public PoliciesResource getPoliciesResource() {
+ Policies policies = this.boundaryDefinitions.getPolicies();
+ if (policies == null) {
+ policies = new Policies();
+ this.boundaryDefinitions.setPolicies(policies);
+ }
+ return new PoliciesResource(policies.getPolicy(), this.serviceTemplateResource);
+ }
+
+ /**
+ * This path is below "boundary definitions" to ease implementation If it
+ * was modeled following the XSD, it would have been nested below
+ * "properties". We did not do that
+ */
+ @Path("propertymappings/")
+ public PropertyMappingsResource getPropertyMappings() {
+ Properties properties = this.boundaryDefinitions.getProperties();
+ if (properties == null) {
+ properties = new Properties();
+ this.boundaryDefinitions.setProperties(properties);
+ }
+ PropertyMappings propertyMappings = properties.getPropertyMappings();
+ if (propertyMappings == null) {
+ propertyMappings = new PropertyMappings();
+ properties.setPropertyMappings(propertyMappings);
+ }
+ return new PropertyMappingsResource(propertyMappings, this.serviceTemplateResource);
+ }
+
+ @Path("interfaces/")
+ public InterfacesResource getInterfacesResource() {
+ Interfaces interfaces = this.boundaryDefinitions.getInterfaces();
+ if (interfaces == null) {
+ interfaces = new Interfaces();
+ this.boundaryDefinitions.setInterfaces(interfaces);
+ }
+ return new InterfacesResource(interfaces.getInterface(), this.serviceTemplateResource);
+ }
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/PropertyMappingsResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/PropertyMappingsResource.java
new file mode 100644
index 0000000..a6872e0
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/PropertyMappingsResource.java
@@ -0,0 +1,115 @@
+/*******************************************************************************
+ * Copyright (c) 2013-2014 University of Stuttgart.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ * Oliver Kopp - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.winery.repository.resources.servicetemplates.boundarydefinitions;
+
+import java.util.Iterator;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+
+import org.apache.commons.lang3.StringUtils;
+import org.eclipse.winery.common.ModelUtilities;
+import org.eclipse.winery.common.Util;
+import org.eclipse.winery.model.tosca.TBoundaryDefinitions.Properties.PropertyMappings;
+import org.eclipse.winery.model.tosca.TEntityTemplate;
+import org.eclipse.winery.model.tosca.TPropertyMapping;
+import org.eclipse.winery.repository.backend.BackendUtils;
+import org.eclipse.winery.repository.resources.servicetemplates.ServiceTemplateResource;
+import org.restdoc.annotations.RestDoc;
+
+public class PropertyMappingsResource {
+
+ private final PropertyMappings propertyMappings;
+ private final ServiceTemplateResource res;
+
+
+ public PropertyMappingsResource(PropertyMappings propertyMappings, ServiceTemplateResource res) {
+ this.propertyMappings = propertyMappings;
+ this.res = res;
+ }
+
+ @Path("{serviceTemplatePropertyRef}")
+ @DELETE
+ public Response onDelete(@PathParam("serviceTemplatePropertyRef") String serviceTemplatePropertyRef) {
+ serviceTemplatePropertyRef = Util.URLdecode(serviceTemplatePropertyRef);
+ Iterator<TPropertyMapping> iterator = this.propertyMappings.getPropertyMapping().iterator();
+ while (iterator.hasNext()) {
+ TPropertyMapping propertyMapping = iterator.next();
+ if (propertyMapping.getServiceTemplatePropertyRef().equals(serviceTemplatePropertyRef)) {
+ iterator.remove();
+ return BackendUtils.persist(this.res);
+ }
+ }
+ // if the property mapping was not found, we reach this point
+ // otherwise "iterator.remove()" has called and the resource persisted
+ return Response.status(Status.NOT_FOUND).build();
+ }
+
+ private void updatePropertyMapping(TPropertyMapping propertyMapping, String serviceTemplatePropertyRef, TEntityTemplate template, String targetPropertyRef) {
+ propertyMapping.setServiceTemplatePropertyRef(serviceTemplatePropertyRef);
+ propertyMapping.setTargetObjectRef(template);
+ propertyMapping.setTargetPropertyRef(targetPropertyRef);
+ }
+
+ @RestDoc(methodDescription = "Creates or updates a property mapping with the given fields")
+ @POST
+ @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
+ // @formatter:off
+ public Response onPost(
+ @FormParam("serviceTemplatePropertyRef") String serviceTemplatePropertyRef,
+ @FormParam("targetObjectRef") String targetObjectRef,
+ @FormParam("targetPropertyRef") String targetPropertyRef
+ ) {
+ // @formatter:on
+ if (StringUtils.isEmpty(serviceTemplatePropertyRef)) {
+ return Response.status(Status.BAD_REQUEST).entity("serviceTemplatePropertyRef must not be empty").build();
+ }
+ if (StringUtils.isEmpty(targetObjectRef)) {
+ return Response.status(Status.BAD_REQUEST).entity("targetObjectRef must not be empty").build();
+ }
+ if (StringUtils.isEmpty(targetPropertyRef)) {
+ return Response.status(Status.BAD_REQUEST).entity("targetPropertyRef must not be empty").build();
+ }
+
+ TEntityTemplate template = ModelUtilities.findNodeTemplateOrRequirementOfNodeTemplateOrCapabilityOfNodeTemplateOrRelationshipTemplate(this.res.getServiceTemplate().getTopologyTemplate(), targetObjectRef);
+ if (template == null) {
+ return Response.status(Status.BAD_REQUEST).entity("targetObjectRef " + targetObjectRef + " could not be resolved.").build();
+ }
+
+ // replace propertyMapping if it exists
+ Iterator<TPropertyMapping> iterator = this.propertyMappings.getPropertyMapping().iterator();
+ while (iterator.hasNext()) {
+ TPropertyMapping propertyMapping = iterator.next();
+ if (propertyMapping.getServiceTemplatePropertyRef().equals(serviceTemplatePropertyRef)) {
+ // we found a property with the same mapping
+ // just update it ...
+ this.updatePropertyMapping(propertyMapping, serviceTemplatePropertyRef, template, targetPropertyRef);
+ // ... and finish processing
+ return BackendUtils.persist(this.res);
+ }
+ }
+
+ // the property mapping didn't exist,
+ // we create a new one
+ TPropertyMapping newPropertyMapping = new TPropertyMapping();
+ this.updatePropertyMapping(newPropertyMapping, serviceTemplatePropertyRef, template, targetPropertyRef);
+ return BackendUtils.persist(this.res);
+ }
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/interfaces/ExportedInterfaceResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/interfaces/ExportedInterfaceResource.java
new file mode 100644
index 0000000..b69e802
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/interfaces/ExportedInterfaceResource.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2014 University of Stuttgart.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ * Oliver Kopp - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.winery.repository.resources.servicetemplates.boundarydefinitions.interfaces;
+
+import java.util.List;
+
+import javax.ws.rs.Path;
+
+import org.eclipse.winery.model.tosca.TExportedInterface;
+import org.eclipse.winery.repository.resources._support.IPersistable;
+import org.eclipse.winery.repository.resources._support.collections.IIdDetermination;
+import org.eclipse.winery.repository.resources._support.collections.withid.EntityWithIdResource;
+
+public class ExportedInterfaceResource extends EntityWithIdResource<TExportedInterface> {
+
+ public ExportedInterfaceResource(IIdDetermination<TExportedInterface> idDetermination, TExportedInterface o, int idx, List<TExportedInterface> list, IPersistable res) {
+ super(idDetermination, o, idx, list, res);
+ }
+
+ @Path("exportedoperations/")
+ public ExportedOperationsResource getExportedOperationsResource() {
+ return new ExportedOperationsResource(this.o.getOperation(), this.res);
+ }
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/interfaces/ExportedOperationResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/interfaces/ExportedOperationResource.java
new file mode 100644
index 0000000..dd10751
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/interfaces/ExportedOperationResource.java
@@ -0,0 +1,249 @@
+/*******************************************************************************
+ * Copyright (c) 2014 University of Stuttgart.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ * Oliver Kopp - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.winery.repository.resources.servicetemplates.boundarydefinitions.interfaces;
+
+import java.io.StringWriter;
+import java.util.List;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+
+import org.eclipse.winery.common.ModelUtilities;
+import org.eclipse.winery.model.tosca.TExportedOperation;
+import org.eclipse.winery.model.tosca.TExportedOperation.NodeOperation;
+import org.eclipse.winery.model.tosca.TExportedOperation.Plan;
+import org.eclipse.winery.model.tosca.TExportedOperation.RelationshipOperation;
+import org.eclipse.winery.model.tosca.TNodeTemplate;
+import org.eclipse.winery.model.tosca.TPlan;
+import org.eclipse.winery.model.tosca.TRelationshipTemplate;
+import org.eclipse.winery.model.tosca.TServiceTemplate;
+import org.eclipse.winery.repository.backend.BackendUtils;
+import org.eclipse.winery.repository.resources._support.IPersistable;
+import org.eclipse.winery.repository.resources._support.collections.IIdDetermination;
+import org.eclipse.winery.repository.resources._support.collections.withid.EntityWithIdResource;
+import org.eclipse.winery.repository.resources.servicetemplates.ServiceTemplateResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.fasterxml.jackson.core.JsonFactory;
+import com.fasterxml.jackson.core.JsonGenerator;
+
+public class ExportedOperationResource extends EntityWithIdResource<TExportedOperation> {
+
+ private static final Logger logger = LoggerFactory.getLogger(ExportedOperationResource.class);
+
+
+ public ExportedOperationResource(IIdDetermination<TExportedOperation> idDetermination, TExportedOperation o, int idx, List<TExportedOperation> list, IPersistable res) {
+ super(idDetermination, o, idx, list, res);
+ }
+
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ public String getJSONRepresentation() {
+ JsonFactory jsonFactory = new JsonFactory();
+ StringWriter sw = new StringWriter();
+ try {
+ JsonGenerator jg = jsonFactory.createGenerator(sw);
+ jg.writeStartObject();
+ String type = this.getType();
+ jg.writeStringField("type", type);
+ jg.writeStringField("ref", this.getReference());
+ if ((type != null) && (!type.equals("Plan"))) {
+ jg.writeStringField("interfacename", this.getInterfaceName());
+ jg.writeStringField("operationname", this.getOperationName());
+ }
+ jg.writeEndObject();
+ jg.close();
+ } catch (Exception e) {
+ ExportedOperationResource.logger.error(e.getMessage(), e);
+ throw new WebApplicationException(Response.status(Status.INTERNAL_SERVER_ERROR).entity(e).build());
+ }
+ String res = sw.toString();
+ return res;
+ }
+
+ /**
+ *
+ * @return "NodeOperation" | "RelationshipOperation" | "Plan" | null. null
+ * is returned if no type is set
+ */
+ @Path("type")
+ @GET
+ public String getType() {
+ if (this.o.getNodeOperation() != null) {
+ return "NodeOperation";
+ } else if (this.o.getRelationshipOperation() != null) {
+ return "RelationshipOperation";
+ } else if (this.o.getPlan() != null) {
+ return "Plan";
+ } else {
+ return null;
+ }
+ }
+
+ @Path("type")
+ @PUT
+ public Response setType(String type) {
+ switch (type) {
+ case "NodeOperation":
+ if (this.o.getNodeOperation() == null) {
+ // only do something, if the type is really changed
+ this.o.setRelationshipOperation(null);
+ this.o.setPlan(null);
+ NodeOperation no = new NodeOperation();
+ this.o.setNodeOperation(no);
+ }
+ break;
+ case "RelationshipOperation":
+ if (this.o.getRelationshipOperation() == null) {
+ // only do something, if the type is really changed
+ this.o.setNodeOperation(null);
+ this.o.setPlan(null);
+ RelationshipOperation ro = new RelationshipOperation();
+ this.o.setRelationshipOperation(ro);
+ }
+ break;
+ case "Plan":
+ if (this.o.getPlan() == null) {
+ // only do something, if the type is really changed
+ this.o.setNodeOperation(null);
+ this.o.setRelationshipOperation(null);
+ Plan plan = new Plan();
+ this.o.setPlan(plan);
+ }
+ break;
+ default:
+ return Response.status(Status.BAD_REQUEST).entity("Unknown type " + type).build();
+ }
+ return BackendUtils.persist(this.res);
+ }
+
+ /**
+ * @return null if no reference is set
+ */
+ @Path("ref")
+ @GET
+ public String getReference() {
+ if (this.o.getNodeOperation() != null) {
+ TNodeTemplate nt = (TNodeTemplate) this.o.getNodeOperation().getNodeRef();
+ if (nt == null) {
+ return null;
+ }
+ return nt.getId();
+ } else if (this.o.getRelationshipOperation() != null) {
+ TRelationshipTemplate rt = (TRelationshipTemplate) this.o.getRelationshipOperation().getRelationshipRef();
+ if (rt == null) {
+ return null;
+ }
+ return rt.getId();
+ } else if (this.o.getPlan() != null) {
+ TPlan plan = (TPlan) this.o.getPlan().getPlanRef();
+ if (plan == null) {
+ return null;
+ }
+ return plan.getId();
+ } else {
+ // no type set -> no reference can be returned
+ return null;
+ }
+ }
+
+ @Path("ref")
+ @PUT
+ public Response setReference(String ref) {
+ TServiceTemplate ste = ((ServiceTemplateResource) this.res).getServiceTemplate();
+
+ // we assume that a correctly set type also means that getX (getNodeOperation, ...) returns non null
+ switch (this.getType()) {
+ case "NodeOperation":
+ TNodeTemplate nodeTemplate = ModelUtilities.resolveNodeTemplate(ste, ref);
+ this.o.getNodeOperation().setNodeRef(nodeTemplate);
+ break;
+ case "RelationshipOperation":
+ TRelationshipTemplate relationshipTemplate = ModelUtilities.resolveRelationshipTemplate(ste, ref);
+ this.o.getRelationshipOperation().setRelationshipRef(relationshipTemplate);
+ break;
+ case "Plan":
+ TPlan plan = ModelUtilities.resolvePlan(ste, ref);
+ this.o.getPlan().setPlanRef(plan);
+ break;
+ default:
+ return Response.status(Status.INTERNAL_SERVER_ERROR).entity("Unknown type " + this.getType()).build();
+ }
+ return BackendUtils.persist(this.res);
+ }
+
+ @Path("interfacename")
+ @GET
+ public String getInterfaceName() {
+ if (this.o.getNodeOperation() != null) {
+ return this.o.getNodeOperation().getInterfaceName();
+ } else if (this.o.getRelationshipOperation() != null) {
+ return this.o.getRelationshipOperation().getInterfaceName();
+ } else if (this.o.getPlan() != null) {
+ throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity("A plan does not carry an interface").build());
+ } else {
+ throw new WebApplicationException(Response.status(Status.INTERNAL_SERVER_ERROR).entity("Unsupported state of ExportedOperation").build());
+ }
+ }
+
+ @Path("interfacename")
+ @PUT
+ public Response setInterfaceName(String interfacename) {
+ if (this.o.getNodeOperation() != null) {
+ this.o.getNodeOperation().setInterfaceName(interfacename);
+ } else if (this.o.getRelationshipOperation() != null) {
+ this.o.getRelationshipOperation().setInterfaceName(interfacename);
+ } else if (this.o.getPlan() != null) {
+ throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity("A plan does not carry an interface").build());
+ } else {
+ throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity("No type set").build());
+ }
+ return BackendUtils.persist(this.res);
+ }
+
+ @Path("operationname")
+ @GET
+ public String getOperationName() {
+ if (this.o.getNodeOperation() != null) {
+ return this.o.getNodeOperation().getOperationName();
+ } else if (this.o.getRelationshipOperation() != null) {
+ return this.o.getRelationshipOperation().getOperationName();
+ } else if (this.o.getPlan() != null) {
+ throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity("A plan does not carry an operation").build());
+ } else {
+ throw new WebApplicationException(Response.status(Status.INTERNAL_SERVER_ERROR).entity("Unsupported state of ExportedOperation").build());
+ }
+ }
+
+ @Path("operationname")
+ @PUT
+ public Response setOperationName(String name) {
+ if (this.o.getNodeOperation() != null) {
+ this.o.getNodeOperation().setOperationName(name);
+ } else if (this.o.getRelationshipOperation() != null) {
+ this.o.getRelationshipOperation().setOperationName(name);
+ } else if (this.o.getPlan() != null) {
+ throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity("A plan does not carry an operation").build());
+ } else {
+ throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity("No type set").build());
+ }
+ return BackendUtils.persist(this.res);
+ }
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/interfaces/ExportedOperationsResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/interfaces/ExportedOperationsResource.java
new file mode 100644
index 0000000..d8788fd
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/interfaces/ExportedOperationsResource.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 2014 University of Stuttgart.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ * Oliver Kopp - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.winery.repository.resources.servicetemplates.boundarydefinitions.interfaces;
+
+import java.util.List;
+
+import org.eclipse.winery.model.tosca.TExportedOperation;
+import org.eclipse.winery.repository.resources._support.IPersistable;
+import org.eclipse.winery.repository.resources._support.collections.withid.EntityWithIdCollectionResource;
+
+import com.sun.jersey.api.view.Viewable;
+
+public class ExportedOperationsResource extends EntityWithIdCollectionResource<ExportedOperationResource, TExportedOperation> {
+
+ public ExportedOperationsResource(List<TExportedOperation> list, IPersistable res) {
+ super(ExportedOperationResource.class, TExportedOperation.class, list, res);
+ }
+
+ @Override
+ public String getId(TExportedOperation entity) {
+ return entity.getName();
+ }
+
+ @Override
+ public Viewable getHTML() {
+ throw new IllegalStateException("No implementation required: boundarydefinitions.jsp contains all required html.");
+ }
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/interfaces/InterfacesResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/interfaces/InterfacesResource.java
new file mode 100644
index 0000000..301f457
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/interfaces/InterfacesResource.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 2014 University of Stuttgart.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ * Oliver Kopp - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.winery.repository.resources.servicetemplates.boundarydefinitions.interfaces;
+
+import java.util.List;
+
+import org.eclipse.winery.model.tosca.TExportedInterface;
+import org.eclipse.winery.repository.resources._support.IPersistable;
+import org.eclipse.winery.repository.resources._support.collections.withid.EntityWithIdCollectionResource;
+
+import com.sun.jersey.api.view.Viewable;
+
+public class InterfacesResource extends EntityWithIdCollectionResource<ExportedInterfaceResource, TExportedInterface> {
+
+ public InterfacesResource(List<TExportedInterface> list, IPersistable res) {
+ super(ExportedInterfaceResource.class, TExportedInterface.class, list, res);
+ }
+
+ @Override
+ public String getId(TExportedInterface entity) {
+ return entity.getName();
+ }
+
+ @Override
+ public Viewable getHTML() {
+ throw new IllegalStateException("No implementation required: boundarydefinitions.jsp contains all required html.");
+ }
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/interfaces/package-info.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/interfaces/package-info.java
new file mode 100644
index 0000000..6a342ea
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/interfaces/package-info.java
@@ -0,0 +1,16 @@
+/*******************************************************************************
+ * Copyright (c) 2014 University of Stuttgart.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ * Oliver Kopp - initial API and implementation
+ *******************************************************************************/
+
+/**
+ * This package models exported interfaces nested in a boundary definitions.
+ */
+package org.eclipse.winery.repository.resources.servicetemplates.boundarydefinitions.interfaces; \ No newline at end of file
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/policies/PoliciesResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/policies/PoliciesResource.java
new file mode 100644
index 0000000..b18341f
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/policies/PoliciesResource.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright (c) 2014 University of Stuttgart.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ * Oliver Kopp - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.winery.repository.resources.servicetemplates.boundarydefinitions.policies;
+
+import java.util.List;
+
+import javax.ws.rs.PUT;
+import javax.ws.rs.core.Response;
+
+import org.eclipse.winery.model.tosca.TPolicy;
+import org.eclipse.winery.repository.backend.BackendUtils;
+import org.eclipse.winery.repository.resources._support.IPersistable;
+import org.eclipse.winery.repository.resources._support.collections.withoutid.EntityWithoutIdCollectionResource;
+
+import com.sun.jersey.api.view.Viewable;
+
+public class PoliciesResource extends EntityWithoutIdCollectionResource<PolicyResource, TPolicy> {
+
+ public PoliciesResource(List<TPolicy> list, IPersistable res) {
+ super(PolicyResource.class, TPolicy.class, list, res);
+ }
+
+ @Override
+ public Viewable getHTML() {
+ throw new IllegalStateException("Not required: boundarydefinitions.jsp also includes the content of the Policy tab.");
+ }
+
+ @PUT
+ public Response replaceAll(List<TPolicy> newList) {
+ this.list.clear();
+ for (TPolicy policy : newList) {
+ this.list.add(policy);
+ }
+ return BackendUtils.persist(this.res);
+ }
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/policies/PolicyResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/policies/PolicyResource.java
new file mode 100644
index 0000000..08fbd8d
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/policies/PolicyResource.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2014 University of Stuttgart.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ * Oliver Kopp - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.winery.repository.resources.servicetemplates.boundarydefinitions.policies;
+
+import java.util.List;
+
+import org.eclipse.winery.model.tosca.TPolicy;
+import org.eclipse.winery.repository.resources._support.IPersistable;
+import org.eclipse.winery.repository.resources._support.collections.withoutid.EntityWithoutIdResource;
+
+public class PolicyResource extends EntityWithoutIdResource<TPolicy> {
+
+ public PolicyResource(TPolicy o, int idx, List<TPolicy> list, IPersistable res) {
+ super(o, idx, list, res);
+ }
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/policies/package-info.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/policies/package-info.java
new file mode 100644
index 0000000..45bc0c7
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/policies/package-info.java
@@ -0,0 +1,16 @@
+/*******************************************************************************
+ * Copyright (c) 2014 University of Stuttgart.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ * Oliver Kopp - initial API and implementation
+ *******************************************************************************/
+
+/**
+ * This package models policies nested in a boundary definitions. It could be resued for the topology modeler, but currently, this is not necessary.
+ */
+package org.eclipse.winery.repository.resources.servicetemplates.boundarydefinitions.policies; \ No newline at end of file
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/reqscaps/CapabilitiesResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/reqscaps/CapabilitiesResource.java
new file mode 100644
index 0000000..80f2640
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/reqscaps/CapabilitiesResource.java
@@ -0,0 +1,76 @@
+/*******************************************************************************
+ * Copyright (c) 2014 University of Stuttgart.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ * Oliver Kopp - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.winery.repository.resources.servicetemplates.boundarydefinitions.reqscaps;
+
+import java.util.List;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.POST;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+
+import org.eclipse.winery.common.ModelUtilities;
+import org.eclipse.winery.model.tosca.TCapability;
+import org.eclipse.winery.model.tosca.TCapabilityRef;
+import org.eclipse.winery.repository.resources._support.IPersistable;
+import org.eclipse.winery.repository.resources._support.collections.CollectionsHelper;
+import org.eclipse.winery.repository.resources._support.collections.withoutid.EntityWithoutIdCollectionResource;
+import org.eclipse.winery.repository.resources.servicetemplates.ServiceTemplateResource;
+
+import com.sun.jersey.api.view.Viewable;
+
+/**
+ * This class is an adaption from
+ * {@link org.eclipse.winery.repository.resources.servicetemplates.boundarydefinitions.reqscaps.RequirementsResource}
+ */
+public class CapabilitiesResource extends EntityWithoutIdCollectionResource<CapabilityResource, TCapabilityRef> {
+
+ public CapabilitiesResource(IPersistable res, List<TCapabilityRef> refs) {
+ super(CapabilityResource.class, TCapabilityRef.class, refs, res);
+ }
+
+ @Override
+ public Viewable getHTML() {
+ throw new IllegalStateException("Not yet required: boundarydefinitions.jsp renders all tab content.");
+ }
+
+ @POST
+ @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
+ public Response addNewElement(@FormParam("name") String name, @FormParam("ref") String reference) {
+ // Implementation adapted from super addNewElement
+
+ if (reference == null) {
+ return Response.status(Status.BAD_REQUEST).entity("A reference has to be provided").build();
+ }
+
+ TCapabilityRef ref = new TCapabilityRef();
+ ref.setName(name); // may also be null
+
+ // The XML model fordces us to put a reference to the object and not just the string
+ ServiceTemplateResource rs = (ServiceTemplateResource) this.res;
+ TCapability resolved = ModelUtilities.resolveCapability(rs.getServiceTemplate(), reference);
+ // In case nothing was found: report back to the user
+ if (resolved == null) {
+ return Response.status(Status.BAD_REQUEST).entity("Reference could not be resolved").build();
+ }
+
+ ref.setRef(resolved);
+
+ // "this.alreadyContains(ref)" cannot be called as this leads to a mappable exception: The data does not contain an id where the given ref attribute may point to
+
+ this.list.add(ref);
+ return CollectionsHelper.persist(this.res, this, ref);
+ }
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/reqscaps/CapabilityResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/reqscaps/CapabilityResource.java
new file mode 100644
index 0000000..7cb7b49
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/reqscaps/CapabilityResource.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2014 University of Stuttgart.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ * Oliver Kopp - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.winery.repository.resources.servicetemplates.boundarydefinitions.reqscaps;
+
+import java.util.List;
+
+import org.eclipse.winery.model.tosca.TCapabilityRef;
+import org.eclipse.winery.repository.resources._support.IPersistable;
+import org.eclipse.winery.repository.resources._support.collections.withoutid.EntityWithoutIdResource;
+
+public class CapabilityResource extends EntityWithoutIdResource<TCapabilityRef> {
+
+ public CapabilityResource(TCapabilityRef o, int idx, List<TCapabilityRef> list, IPersistable res) {
+ super(o, idx, list, res);
+ }
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/reqscaps/RequirementResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/reqscaps/RequirementResource.java
new file mode 100644
index 0000000..72a7476
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/reqscaps/RequirementResource.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2014 University of Stuttgart.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ * Oliver Kopp - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.winery.repository.resources.servicetemplates.boundarydefinitions.reqscaps;
+
+import java.util.List;
+
+import org.eclipse.winery.model.tosca.TRequirementRef;
+import org.eclipse.winery.repository.resources._support.IPersistable;
+import org.eclipse.winery.repository.resources._support.collections.withoutid.EntityWithoutIdResource;
+
+public class RequirementResource extends EntityWithoutIdResource<TRequirementRef> {
+
+ public RequirementResource(TRequirementRef o, int idx, List<TRequirementRef> list, IPersistable res) {
+ super(o, idx, list, res);
+ }
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/reqscaps/RequirementsResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/reqscaps/RequirementsResource.java
new file mode 100644
index 0000000..dc6ad94
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/reqscaps/RequirementsResource.java
@@ -0,0 +1,85 @@
+/*******************************************************************************
+ * Copyright (c) 2014 University of Stuttgart.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ * Oliver Kopp - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.winery.repository.resources.servicetemplates.boundarydefinitions.reqscaps;
+
+import java.util.List;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.POST;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+
+import org.eclipse.winery.common.ModelUtilities;
+import org.eclipse.winery.model.tosca.TRequirement;
+import org.eclipse.winery.model.tosca.TRequirementRef;
+import org.eclipse.winery.repository.resources._support.IPersistable;
+import org.eclipse.winery.repository.resources._support.collections.CollectionsHelper;
+import org.eclipse.winery.repository.resources._support.collections.withoutid.EntityWithoutIdCollectionResource;
+import org.eclipse.winery.repository.resources.servicetemplates.ServiceTemplateResource;
+
+import com.sun.jersey.api.view.Viewable;
+
+/**
+ * This class is mirrored at
+ * {@link org.eclipse.winery.repository.resources.servicetemplates.boundarydefinitions.reqscaps.CapabilitiesResource}
+ */
+public class RequirementsResource extends EntityWithoutIdCollectionResource<RequirementResource, TRequirementRef> {
+
+ public RequirementsResource(IPersistable res, List<TRequirementRef> refs) {
+ super(RequirementResource.class, TRequirementRef.class, refs, res);
+ }
+
+ @Override
+ public Viewable getHTML() {
+ throw new IllegalStateException("Not yet required: boundarydefinitions.jsp renders all tab content.");
+ }
+
+ /**
+ * Adds an element using form-encoding
+ *
+ * This is necessary as TRequirementRef contains an IDREF and the XML
+ * snippet itself does not contain the target id
+ *
+ * @param name the optional name of the requirement
+ * @param reference the reference to a requirement in the topology
+ */
+ @POST
+ @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
+ public Response addNewElement(@FormParam("name") String name, @FormParam("ref") String reference) {
+ // Implementation adapted from super addNewElement
+
+ if (reference == null) {
+ return Response.status(Status.BAD_REQUEST).entity("A reference has to be provided").build();
+ }
+
+ TRequirementRef ref = new TRequirementRef();
+ ref.setName(name); // may also be null
+
+ // The XML model forces us to put a reference to the object and not just the string
+ ServiceTemplateResource rs = (ServiceTemplateResource) this.res;
+ TRequirement resolved = ModelUtilities.resolveRequirement(rs.getServiceTemplate(), reference);
+ // In case nothing was found: report back to the user
+ if (resolved == null) {
+ return Response.status(Status.BAD_REQUEST).entity("Reference could not be resolved").build();
+ }
+
+ ref.setRef(resolved);
+
+ // "this.alreadyContains(ref)" cannot be called as this leads to a mappable exception: The data does not contain an id where the given ref attribute may point to
+
+ this.list.add(ref);
+ return CollectionsHelper.persist(this.res, this, ref);
+ }
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/reqscaps/package-info.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/reqscaps/package-info.java
new file mode 100644
index 0000000..f6a3c5d
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/reqscaps/package-info.java
@@ -0,0 +1,18 @@
+/*******************************************************************************
+ * Copyright (c) 2014 University of Stuttgart.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ * Oliver Kopp - initial API and implementation
+ *******************************************************************************/
+
+/**
+ * This package contains all classes for requirement refs and capability refs
+ *
+ * They are nested as "Requirements" / "Capabilities" in the boundary definitions, but the things itself are called "...Ref"
+ */
+package org.eclipse.winery.repository.resources.servicetemplates.boundarydefinitions.reqscaps; \ No newline at end of file
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/plans/PlanFileResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/plans/PlanFileResource.java
new file mode 100644
index 0000000..5a4b56f
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/plans/PlanFileResource.java
@@ -0,0 +1,115 @@
+/*******************************************************************************
+ * Copyright (c) 2014-2015 University of Stuttgart.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ * Oliver Kopp - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.winery.repository.resources.servicetemplates.plans;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.HeaderParam;
+import javax.ws.rs.PUT;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+
+import org.eclipse.winery.common.RepositoryFileReference;
+import org.eclipse.winery.common.ids.elements.PlanId;
+import org.eclipse.winery.model.tosca.TPlan;
+import org.eclipse.winery.repository.backend.BackendUtils;
+import org.eclipse.winery.repository.backend.Repository;
+import org.eclipse.winery.repository.resources.servicetemplates.ServiceTemplateResource;
+import org.restdoc.annotations.RestDoc;
+
+import com.sun.jersey.core.header.FormDataContentDisposition;
+import com.sun.jersey.multipart.FormDataBodyPart;
+import com.sun.jersey.multipart.FormDataParam;
+
+public class PlanFileResource {
+
+ private final PlanId planId;
+ private TPlan plan;
+ private ServiceTemplateResource res;
+
+
+ public PlanFileResource(ServiceTemplateResource res, PlanId planId, TPlan plan) {
+ this.res = res;
+ this.planId = planId;
+ this.plan = plan;
+ }
+
+ /**
+ * Extracts the file reference from plan's planModelReference
+ */
+ private RepositoryFileReference getFileRef() {
+ String reference = this.plan.getPlanModelReference().getReference();
+ File f = new File(reference);
+ return new RepositoryFileReference(this.planId, f.getName());
+ }
+
+ @PUT
+ @Consumes({MediaType.MULTIPART_FORM_DATA})
+ @RestDoc(methodDescription = "Resource currently works for BPMN4TOSCA plans only")
+ // @formatter:off
+ public Response onPutFile(
+ @FormDataParam("file") InputStream uploadedInputStream,
+ @FormDataParam("file") FormDataContentDisposition fileDetail,
+ @FormDataParam("file") FormDataBodyPart body
+ ) {
+ // @formatter:on
+
+ String fileName = fileDetail.getFileName();
+ RepositoryFileReference ref = new RepositoryFileReference(this.planId, fileName);
+ RepositoryFileReference oldRef = this.getFileRef();
+ boolean persistanceNecessary;
+ if (ref.equals(oldRef)) {
+ // nothing todo, file will be replaced
+ persistanceNecessary = false;
+ } else {
+ // new filename sent
+ BackendUtils.delete(oldRef);
+ PlansResource.setPlanModelReference(this.plan, this.planId, fileName);
+ persistanceNecessary = true;
+ }
+
+ // Really store it
+ try {
+ Repository.INSTANCE.putContentToFile(ref, uploadedInputStream, body.getMediaType());
+ } catch (IOException e1) {
+ return Response.status(Status.INTERNAL_SERVER_ERROR).entity("Could not store plan. " + e1.getMessage()).build();
+ }
+
+ if (persistanceNecessary) {
+ return BackendUtils.persist(this.res);
+ } else {
+ return Response.noContent().build();
+ }
+ }
+
+ @PUT
+ @Consumes({MediaType.APPLICATION_JSON})
+ // @formatter:off
+ public Response onPutJSON(InputStream is) {
+ RepositoryFileReference ref = this.getFileRef();
+ return BackendUtils.putContentToFile(ref, is, MediaType.APPLICATION_JSON_TYPE);
+ }
+
+ /**
+ * Returns the stored file.
+ */
+ @GET
+ public Response getFile(@HeaderParam("If-Modified-Since") String modified) {
+ RepositoryFileReference ref = this.getFileRef();
+ return BackendUtils.returnRepoPath(ref, modified);
+ }
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/plans/PlanResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/plans/PlanResource.java
new file mode 100644
index 0000000..704c831
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/plans/PlanResource.java
@@ -0,0 +1,203 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2015 University of Stuttgart.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ * Oliver Kopp - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.winery.repository.resources.servicetemplates.plans;
+
+import java.io.IOException;
+import java.net.URI;
+import java.util.List;
+
+import javax.ws.rs.DELETE;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+import javax.ws.rs.core.UriInfo;
+
+import org.apache.commons.lang3.StringUtils;
+import org.eclipse.winery.common.Util;
+import org.eclipse.winery.common.ids.XMLId;
+import org.eclipse.winery.common.ids.definitions.ServiceTemplateId;
+import org.eclipse.winery.common.ids.definitions.TOSCAComponentId;
+import org.eclipse.winery.common.ids.elements.PlanId;
+import org.eclipse.winery.common.ids.elements.PlansId;
+import org.eclipse.winery.model.tosca.TPlan;
+import org.eclipse.winery.model.tosca.TPlan.InputParameters;
+import org.eclipse.winery.model.tosca.TPlan.OutputParameters;
+import org.eclipse.winery.repository.Prefs;
+import org.eclipse.winery.repository.Utils;
+import org.eclipse.winery.repository.backend.BackendUtils;
+import org.eclipse.winery.repository.backend.Repository;
+import org.eclipse.winery.repository.resources.IHasName;
+import org.eclipse.winery.repository.resources._support.collections.IIdDetermination;
+import org.eclipse.winery.repository.resources._support.collections.withid.EntityWithIdResource;
+import org.eclipse.winery.repository.resources.interfaces.ParametersResource;
+import org.eclipse.winery.repository.resources.servicetemplates.ServiceTemplateResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Does <em>not</em> implement
+ * {@link org.eclipse.winery.repository.resources.IHasTypeReference}, because
+ * the type of a plan is outside the system of TOSCA.
+ */
+public class PlanResource extends EntityWithIdResource<TPlan> implements IHasName {
+
+ private static final Logger logger = LoggerFactory.getLogger(PlanResource.class);
+
+
+ public PlanResource(IIdDetermination<TPlan> idDetermination, TPlan o, int idx, List<TPlan> list, ServiceTemplateResource res) {
+ super(idDetermination, o, idx, list, res);
+ }
+
+ /**
+ * Ugly hack to get the parent service template resource
+ *
+ */
+ public ServiceTemplateResource getServiceTemplateResource() {
+ // Solution proposal 1: Each sub-resource should know its parent service
+ // template
+ //
+ // Solution proposal 2 (Generic solution): Each resource should know its
+ // parent resource
+ //
+ // Does not work when plan is used at as component instance (then,
+ // serviceTemplateResource is null). In this case, a plan is not associated
+ // with a service template.
+
+ // we cannot use "((PlanId) id).getParent()" as this "only" returns an
+ // ID
+ // we could create a newly resource based on that ID
+ // However, the parent resource has already been created when the
+ // PlanResource has been generated:
+ // Jersey crawls down from the main resource through the service
+ // template resource to the plan resource
+ return (ServiceTemplateResource) this.res;
+ }
+
+ /**
+ * Determines the id of the current resource
+ */
+ private PlanId getId() {
+ ServiceTemplateId sId = (ServiceTemplateId) this.getServiceTemplateResource().getId();
+ PlansId psId = new PlansId(sId);
+ PlanId pId = new PlanId(psId, new XMLId(this.o.getId(), false));
+ return pId;
+ }
+
+ @Override
+ @DELETE
+ public Response onDelete() {
+ Response res = super.onDelete();
+ if (Utils.isSuccessFulResponse(res)) {
+ try {
+ Repository.INSTANCE.forceDelete(this.getId());
+ } catch (IOException e) {
+ return Response.status(Status.INTERNAL_SERVER_ERROR).entity("Could not remove plan file").build();
+ }
+ return BackendUtils.persist(this.res);
+ } else {
+ return res;
+ }
+ }
+
+ @GET
+ @Produces(MediaType.TEXT_HTML)
+ public Response getHTML(@Context UriInfo uriInfo) {
+ boolean isBPMN4TOSCA = this.o.getPlanLanguage().equals(org.eclipse.winery.common.constants.Namespaces.URI_BPMN4TOSCA_20);
+ String bpmn4toscaBaseURL = Prefs.INSTANCE.getBPMN4TOSCABaseURL();
+ if (isBPMN4TOSCA && (!StringUtils.isEmpty(bpmn4toscaBaseURL))) {
+ String uri = bpmn4toscaBaseURL;
+ URI repositoryURI = uriInfo.getBaseUri();
+ uri += "?repositoryURL=" + Util.URLencode(repositoryURI.toString());
+ TOSCAComponentId serviceTemplateId = this.getServiceTemplateResource().getId();
+ uri += "&namespace=" + serviceTemplateId.getNamespace().getEncoded();
+ uri += "&id=" + serviceTemplateId.getXmlId().getEncoded();
+ uri += "&plan=" + this.getName();
+ return Response.temporaryRedirect(Utils.createURI(uri)).build();
+ } else {
+ // return Response.ok().entity("No editor plugin found for plan language " + this.o.getPlanLanguage()).build();
+ URI fileURI = uriInfo.getAbsolutePath().resolve("file");
+ return Response.seeOther(fileURI).build();
+ }
+ }
+
+ @Override
+ public String getName() {
+ String name = this.o.getName();
+ if (name == null) {
+ name = this.o.getId();
+ }
+ return name;
+ }
+
+ @Override
+ public Response setName(@FormParam("value") String name) {
+ this.o.setName(name);
+ return BackendUtils.persist(this.res);
+ }
+
+ @Path("file")
+ public PlanFileResource getPlanFileResource() {
+ return new PlanFileResource((ServiceTemplateResource) this.res, this.getId(), this.o);
+ }
+
+ @GET
+ @Path("type")
+ public String getType() {
+ return this.o.getPlanType();
+ }
+
+ @PUT
+ @Path("type")
+ public Response setType(@FormParam("type") String type) {
+ this.o.setPlanType(type);
+ return BackendUtils.persist(this.res);
+ }
+
+ @GET
+ @Path("language")
+ public String getLanguage() {
+ return this.o.getPlanLanguage();
+ }
+
+ @PUT
+ @Path("language")
+ public Response setLanguage(@FormParam("language") String language) {
+ this.o.setPlanType(language);
+ return BackendUtils.persist(this.res);
+ }
+
+ @Path("inputparameters/")
+ public ParametersResource getInputParametersResource() {
+ InputParameters inputParameters = this.o.getInputParameters();
+ if (inputParameters == null) {
+ inputParameters = new InputParameters();
+ this.o.setInputParameters(inputParameters);
+ }
+ return new ParametersResource(inputParameters.getInputParameter(), this.getServiceTemplateResource());
+ }
+
+ @Path("outputparameters/")
+ public ParametersResource getOutputParametersResource() {
+ OutputParameters outputParameters = this.o.getOutputParameters();
+ if (outputParameters == null) {
+ outputParameters = new OutputParameters();
+ this.o.setOutputParameters(outputParameters);
+ }
+ return new ParametersResource(outputParameters.getOutputParameter(), this.getServiceTemplateResource());
+ }
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/plans/PlansResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/plans/PlansResource.java
new file mode 100644
index 0000000..13a8420
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/plans/PlansResource.java
@@ -0,0 +1,205 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2015 University of Stuttgart.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ * Oliver Kopp - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.winery.repository.resources.servicetemplates.plans;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.StringWriter;
+import java.util.List;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.POST;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+
+import org.apache.commons.lang3.StringUtils;
+import org.eclipse.winery.common.RepositoryFileReference;
+import org.eclipse.winery.common.Util;
+import org.eclipse.winery.common.ids.XMLId;
+import org.eclipse.winery.common.ids.definitions.ServiceTemplateId;
+import org.eclipse.winery.common.ids.elements.PlanId;
+import org.eclipse.winery.common.ids.elements.PlansId;
+import org.eclipse.winery.model.tosca.TPlan;
+import org.eclipse.winery.model.tosca.TPlan.PlanModelReference;
+import org.eclipse.winery.repository.Constants;
+import org.eclipse.winery.repository.Utils;
+import org.eclipse.winery.repository.backend.BackendUtils;
+import org.eclipse.winery.repository.backend.Repository;
+import org.eclipse.winery.repository.resources._support.collections.withid.EntityWithIdCollectionResource;
+import org.eclipse.winery.repository.resources.admin.types.PlanLanguagesManager;
+import org.eclipse.winery.repository.resources.admin.types.PlanTypesManager;
+import org.eclipse.winery.repository.resources.servicetemplates.ServiceTemplateResource;
+import org.restdoc.annotations.RestDoc;
+import org.restdoc.annotations.RestDocParam;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.fasterxml.jackson.core.JsonFactory;
+import com.fasterxml.jackson.core.JsonGenerationException;
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.sun.jersey.api.view.Viewable;
+import com.sun.jersey.core.header.FormDataContentDisposition;
+import com.sun.jersey.multipart.FormDataBodyPart;
+import com.sun.jersey.multipart.FormDataParam;
+
+/**
+ * Presents the plans nested in one Service Template
+ */
+public class PlansResource extends EntityWithIdCollectionResource<PlanResource, TPlan> {
+
+ private static final Logger logger = LoggerFactory.getLogger(PlansResource.class);
+
+
+ public PlansResource(List<TPlan> plans, ServiceTemplateResource res) {
+ super(PlanResource.class, TPlan.class, plans, res);
+ }
+
+ @Override
+ public Viewable getHTML() {
+ return new Viewable("/jsp/servicetemplates/plans/plans.jsp", new PlansResourceData(this.list));
+ }
+
+ @POST
+ @RestDoc(methodDescription = "<p>Linked plans are currently not supported. Existing plans with the same id are overwritten</p> <p>@return JSON with .tableData: Array with row data for dataTable</p>")
+ @Consumes({MediaType.MULTIPART_FORM_DATA})
+ @Produces(MediaType.APPLICATION_JSON)
+ // the supertype consumes JSON and XML at org.eclipse.winery.repository.resources._support.collections.EntityCollectionResource.addNewElement(EntityT)
+ // @formatter:off
+ public Response onPost(
+ @FormDataParam("planName") String name,
+ @FormDataParam("planType") String type,
+ @FormDataParam("planLanguage") @RestDocParam(description = "the plan language (e..g, BPMN or BPEL). Full URL.") String language,
+ @FormDataParam("file") @RestDocParam(description="(optional in the case of BPMN4TOSCA) file containing the plan.") InputStream uploadedInputStream,
+ @FormDataParam("file") FormDataContentDisposition fileDetail,
+ @FormDataParam("file") FormDataBodyPart body
+ ) {
+ // @formatter:on
+ if (StringUtils.isEmpty(name)) {
+ return Response.status(Status.BAD_REQUEST).entity("planName must be given").build();
+ }
+ if (StringUtils.isEmpty(type)) {
+ return Response.status(Status.BAD_REQUEST).entity("planType must be given").build();
+ }
+ if (StringUtils.isEmpty(language)) {
+ return Response.status(Status.BAD_REQUEST).entity("planLanguage must be given").build();
+ }
+
+ boolean bpmn4toscaMode = org.eclipse.winery.common.constants.Namespaces.URI_BPMN4TOSCA_20.equals(language);
+ if (!bpmn4toscaMode) {
+ if (uploadedInputStream == null) {
+ return Response.status(Status.BAD_REQUEST).entity("file must be given").build();
+ }
+ }
+
+ // A plan carries both a name and an ID
+ // To be user-friendly, we create the ID based on the name
+ // the drawback is, that we do not allow two plans with the same name
+ // during creation, but allow renaming plans to the same name (as we do
+ // not allow ID renaming)
+ String xmlId = Utils.createXMLidAsString(name);
+
+ // BEGIN: Store plan file
+
+ // Determine Id
+ PlansId plansId = new PlansId((ServiceTemplateId) ((ServiceTemplateResource) this.res).getId());
+ PlanId planId = new PlanId(plansId, new XMLId(xmlId, false));
+ // Ensure overwriting
+ if (Repository.INSTANCE.exists(planId)) {
+ try {
+ Repository.INSTANCE.forceDelete(planId);
+ // Quick hack to remove the deleted plan from the plans element
+ ((ServiceTemplateResource) this.res).synchronizeReferences();
+ } catch (IOException e) {
+ return Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
+ }
+ }
+
+ String fileName;
+ if (bpmn4toscaMode) {
+ fileName = xmlId + Constants.SUFFIX_BPMN4TOSCA;
+ RepositoryFileReference ref = new RepositoryFileReference(planId, fileName);
+ try {
+ Repository.INSTANCE.putContentToFile(ref, "{}", MediaType.APPLICATION_JSON_TYPE);
+ } catch (IOException e1) {
+ return Response.status(Status.INTERNAL_SERVER_ERROR).entity("Could not create empty plan. " + e1.getMessage()).build();
+ }
+ } else {
+ // We use the filename also as local file name. Alternatively, we could use the xml id
+ // With URL encoding, this should not be an issue
+ fileName = Util.URLencode(fileDetail.getFileName());
+
+ // Really store it
+ RepositoryFileReference ref = new RepositoryFileReference(planId, fileName);
+ try {
+ Repository.INSTANCE.putContentToFile(ref, uploadedInputStream, body.getMediaType());
+ } catch (IOException e1) {
+ return Response.status(Status.INTERNAL_SERVER_ERROR).entity("Could not store plan. " + e1.getMessage()).build();
+ }
+ }
+ // END: Store plan file
+
+ TPlan plan = new TPlan();
+ plan.setId(xmlId);
+ plan.setName(name);
+ plan.setPlanType(type);
+ plan.setPlanLanguage(language);
+ PlansResource.setPlanModelReference(plan, planId, fileName);
+ this.list.add(plan);
+
+ // prepare result
+ JsonFactory jsonFactory = new JsonFactory();
+ StringWriter sw = new StringWriter();
+ try {
+ JsonGenerator jGenerator = jsonFactory.createGenerator(sw);
+ jGenerator.writeStartObject();
+ jGenerator.writeFieldName("tableData");
+ jGenerator.writeStartArray();
+ jGenerator.writeString(xmlId);
+ jGenerator.writeString(""); // precondition
+ jGenerator.writeString(name);
+ jGenerator.writeString(PlanTypesManager.INSTANCE.getShortName(type));
+ jGenerator.writeString(PlanLanguagesManager.INSTANCE.getShortName(language));
+ jGenerator.writeEndArray();
+ jGenerator.writeEndObject();
+ jGenerator.close();
+ sw.close();
+ } catch (JsonGenerationException e) {
+ PlansResource.logger.error(e.getMessage(), e);
+ return Response.serverError().build();
+ } catch (IOException e) {
+ PlansResource.logger.error(e.getMessage(), e);
+ return Response.serverError().build();
+ }
+
+ Response res = BackendUtils.persist(this.res);
+ if (res.getStatus() == 204) {
+ // everything OK, return created
+ return Response.created(Utils.createURI(Util.URLencode(xmlId))).entity(sw.toString()).build();
+ } else {
+ return res;
+ }
+ }
+
+ static void setPlanModelReference(TPlan plan, PlanId planId, String fileName) {
+ PlanModelReference pref = new PlanModelReference();
+ // Set path relative to Definitions/ path inside CSAR.
+ pref.setReference("../" + Utils.getURLforPathInsideRepo(BackendUtils.getPathInsideRepo(planId)) + fileName);
+ plan.setPlanModelReference(pref);
+ }
+
+ @Override
+ public String getId(TPlan plan) {
+ return plan.getId();
+ }
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/plans/PlansResourceData.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/plans/PlansResourceData.java
new file mode 100644
index 0000000..8527eb4
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/plans/PlansResourceData.java
@@ -0,0 +1,136 @@
+/*******************************************************************************
+ * 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.repository.resources.servicetemplates.plans;
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.util.Collection;
+import java.util.List;
+
+import org.eclipse.winery.model.tosca.TPlan;
+import org.eclipse.winery.model.tosca.TPlan.PlanModelReference;
+import org.eclipse.winery.repository.datatypes.TypeWithShortName;
+import org.eclipse.winery.repository.resources.admin.types.PlanLanguagesManager;
+import org.eclipse.winery.repository.resources.admin.types.PlanTypesManager;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.fasterxml.jackson.core.JsonFactory;
+import com.fasterxml.jackson.core.JsonGenerationException;
+import com.fasterxml.jackson.core.JsonGenerator;
+
+public class PlansResourceData {
+
+ private static final Logger logger = LoggerFactory.getLogger(PlansResourceData.class);
+
+ // data: [ [id, pre, name, type, lang]* ]
+ private String embeddedPlansTableData;
+
+ // data: [ [id, pre, name, type, lang, reference]* ]
+ private String linkedPlansTableData;
+
+
+ /**
+ * Data object for the JSP
+ *
+ * @param serviceTemplateResource the service template the plans belong to
+ */
+ public PlansResourceData(List<TPlan> plans) {
+ if (plans.isEmpty()) {
+ this.embeddedPlansTableData = "[]";
+ this.linkedPlansTableData = "[]";
+ return;
+ }
+ JsonFactory jsonFactory = new JsonFactory();
+ StringWriter embeddedPlansTableDataSW = new StringWriter();
+ StringWriter linkedPlansTableDataSW = new StringWriter();
+ try {
+ JsonGenerator jGeneratorEmbedded = jsonFactory.createGenerator(embeddedPlansTableDataSW);
+ JsonGenerator jGeneratorLinked = jsonFactory.createGenerator(linkedPlansTableDataSW);
+
+ jGeneratorEmbedded.writeStartArray();
+ jGeneratorLinked.writeStartArray();
+
+ for (TPlan plan : plans) {
+ String name = plan.getName();
+ if (name == null) {
+ // name defaults to id
+ name = plan.getId();
+ }
+ String type = PlanTypesManager.INSTANCE.getShortName(plan.getPlanType());
+ String language = PlanLanguagesManager.INSTANCE.getShortName(plan.getPlanLanguage());
+ PlanModelReference planModelReference = plan.getPlanModelReference();
+ String reference = planModelReference != null ? planModelReference.getReference() : null;
+ JsonGenerator gen;
+ boolean writeReference;
+ if (reference == null) {
+ gen = jGeneratorEmbedded;
+ writeReference = false;
+ } else if (reference.startsWith("../")) {
+ gen = jGeneratorEmbedded;
+ writeReference = false;
+ } else {
+ gen = jGeneratorLinked;
+ writeReference = true;
+ }
+
+ gen.writeStartArray();
+ gen.writeString(plan.getId());
+ gen.writeString(""); // precondition
+ gen.writeString(name);
+ gen.writeString(type);
+ gen.writeString(language);
+ if (writeReference) {
+ gen.writeString(reference);
+ }
+ gen.writeEndArray();
+ }
+
+ jGeneratorEmbedded.writeEndArray();
+ jGeneratorLinked.writeEndArray();
+
+ jGeneratorEmbedded.close();
+ embeddedPlansTableDataSW.close();
+ jGeneratorLinked.close();
+ linkedPlansTableDataSW.close();
+ } catch (JsonGenerationException e) {
+ PlansResourceData.logger.error(e.getMessage(), e);
+ this.embeddedPlansTableData = "[]";
+ this.linkedPlansTableData = "[]";
+ return;
+ } catch (IOException e) {
+ PlansResourceData.logger.error("", e);
+ this.embeddedPlansTableData = "[]";
+ this.linkedPlansTableData = "[]";
+ return;
+ }
+ this.embeddedPlansTableData = embeddedPlansTableDataSW.toString();
+ this.linkedPlansTableData = linkedPlansTableDataSW.toString();
+ }
+
+ public String getEmbeddedPlansTableData() {
+ return this.embeddedPlansTableData;
+ }
+
+ public String getLinkedPlansTableData() {
+ return this.linkedPlansTableData;
+ }
+
+ public Collection<TypeWithShortName> getPlanTypes() {
+ return PlanTypesManager.INSTANCE.getTypes();
+ }
+
+ public Collection<TypeWithShortName> getPlanLanguages() {
+ return PlanLanguagesManager.INSTANCE.getTypes();
+ }
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/selfserviceportal/OptionResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/selfserviceportal/OptionResource.java
new file mode 100644
index 0000000..9ce11f9
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/selfserviceportal/OptionResource.java
@@ -0,0 +1,96 @@
+/*******************************************************************************
+ * 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.repository.resources.servicetemplates.selfserviceportal;
+
+import java.io.IOException;
+import java.util.List;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.HeaderParam;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+
+import org.eclipse.winery.model.selfservice.ApplicationOption;
+import org.eclipse.winery.common.RepositoryFileReference;
+import org.eclipse.winery.repository.backend.BackendUtils;
+import org.eclipse.winery.repository.backend.Repository;
+import org.eclipse.winery.repository.datatypes.ids.elements.SelfServiceMetaDataId;
+import org.eclipse.winery.repository.resources._support.collections.IIdDetermination;
+import org.eclipse.winery.repository.resources._support.collections.withid.EntityWithIdResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class OptionResource extends EntityWithIdResource<ApplicationOption> {
+
+ private static final Logger logger = LoggerFactory.getLogger(OptionResource.class);
+
+ static final String ICON_JPG = "icon.jpg";
+ static final String PLAN_INPUT_XML = "plan.input.xml";
+ private SelfServiceMetaDataId ssmdId;
+
+
+ public OptionResource(IIdDetermination<ApplicationOption> idDetermination, ApplicationOption o, int idx, List<ApplicationOption> list, SelfServicePortalResource res) {
+ super(idDetermination, o, idx, list, res);
+ this.ssmdId = ((SelfServicePortalResource) this.res).getId();
+ }
+
+ private String getFileNamePrefix() {
+ return OptionResource.getFileNamePrefix(this.o.getId());
+ }
+
+ public static String getFileNamePrefix(String id) {
+ return "option_" + id + "_";
+ }
+
+ @Path(OptionResource.ICON_JPG)
+ @GET
+ public Response getIcon(@HeaderParam("If-Modified-Since") String modified) {
+ RepositoryFileReference ref = new RepositoryFileReference(this.ssmdId, this.getFileNamePrefix() + OptionResource.ICON_JPG);
+ return BackendUtils.returnRepoPath(ref, modified);
+ }
+
+ @Path("planinputmessage")
+ @GET
+ public Response getPlanInputMessage(@HeaderParam("If-Modified-Since") String modified) {
+ RepositoryFileReference ref = new RepositoryFileReference(this.ssmdId, this.getFileNamePrefix() + OptionResource.PLAN_INPUT_XML);
+ return BackendUtils.returnRepoPath(ref, modified);
+ }
+
+ @Override
+ public Response onDelete() {
+ // delete icon and plan model reference ...
+
+ // delete icon
+ // we use the URL stored in the data instead of the generated URL to be compatible with manually edits
+ RepositoryFileReference ref = new RepositoryFileReference(this.ssmdId, this.o.getIconUrl());
+ try {
+ Repository.INSTANCE.forceDelete(ref);
+ } catch (IOException e) {
+ OptionResource.logger.error("Could not remove file", e);
+ return Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
+ }
+
+ // delete plan input
+ // we use the URL stored in the data instead of the generated URL to be compatible with manually edits
+ ref = new RepositoryFileReference(this.ssmdId, this.o.getPlanInputMessageUrl());
+ try {
+ Repository.INSTANCE.forceDelete(ref);
+ } catch (IOException e) {
+ OptionResource.logger.error("Could not remove file", e);
+ return Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
+ }
+
+ // after deleting files, continue with list deletion
+ return super.onDelete();
+ }
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/selfserviceportal/OptionsResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/selfserviceportal/OptionsResource.java
new file mode 100644
index 0000000..86fa102
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/selfserviceportal/OptionsResource.java
@@ -0,0 +1,131 @@
+/*******************************************************************************
+ * 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.repository.resources.servicetemplates.selfserviceportal;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.List;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.POST;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+
+import org.apache.commons.lang3.StringUtils;
+import org.eclipse.winery.model.selfservice.ApplicationOption;
+import org.eclipse.winery.common.RepositoryFileReference;
+import org.eclipse.winery.repository.Utils;
+import org.eclipse.winery.repository.backend.BackendUtils;
+import org.eclipse.winery.repository.backend.Repository;
+import org.eclipse.winery.repository.datatypes.ids.elements.SelfServiceMetaDataId;
+import org.eclipse.winery.repository.resources._support.collections.withid.EntityWithIdCollectionResource;
+import org.restdoc.annotations.RestDoc;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.sun.jersey.api.view.Viewable;
+import com.sun.jersey.core.header.FormDataContentDisposition;
+import com.sun.jersey.multipart.FormDataBodyPart;
+import com.sun.jersey.multipart.FormDataParam;
+
+public class OptionsResource extends EntityWithIdCollectionResource<OptionResource, ApplicationOption> {
+
+ private static final Logger logger = LoggerFactory.getLogger(OptionsResource.class);
+
+
+ public OptionsResource(List<ApplicationOption> list, SelfServicePortalResource res) {
+ super(OptionResource.class, ApplicationOption.class, list, res);
+ }
+
+ @Override
+ public String getId(ApplicationOption entity) {
+ return entity.getId();
+ }
+
+ @Override
+ public Viewable getHTML() {
+ throw new IllegalStateException("Not yet implemented.");
+ }
+
+ @POST
+ @RestDoc(methodDescription = "Adds a new option<p>TODO: @return JSON with .tableData: Array with row data for dataTable</p>")
+ @Consumes(MediaType.MULTIPART_FORM_DATA)
+ // @formatter:off
+ public Response onPost(
+ @FormDataParam("name") String name,
+ @FormDataParam("description") String description,
+ @FormDataParam("planServiceName") String planServiceName,
+ @FormDataParam("planInputMessage") String planInputMessage,
+ @FormDataParam("file") InputStream uploadedInputStream,
+ @FormDataParam("file") FormDataContentDisposition fileDetail,
+ @FormDataParam("file") FormDataBodyPart body
+ ) {
+ // @formatter:on
+ if (StringUtils.isEmpty(name)) {
+ return Response.status(Status.BAD_REQUEST).entity("planName must be given").build();
+ }
+ if (StringUtils.isEmpty(description)) {
+ return Response.status(Status.BAD_REQUEST).entity("description must be given").build();
+ }
+ if (StringUtils.isEmpty(planServiceName)) {
+ return Response.status(Status.BAD_REQUEST).entity("planServiceName must be given").build();
+ }
+ if (StringUtils.isEmpty(planInputMessage)) {
+ return Response.status(Status.BAD_REQUEST).entity("planInputMessage must be given").build();
+ }
+ if (uploadedInputStream == null) {
+ return Response.status(Status.BAD_REQUEST).entity("file has to be provided").build();
+ }
+ ApplicationOption option = new ApplicationOption();
+
+ String id = Utils.createXMLidAsString(name);
+
+ String fileNamePrefix = OptionResource.getFileNamePrefix(id);
+ String iconFileName = fileNamePrefix + OptionResource.ICON_JPG;
+ String planInputMessageFileName = fileNamePrefix + OptionResource.PLAN_INPUT_XML;
+
+ // create option data
+ option.setId(id);
+ option.setName(name);
+ option.setDescription(description);
+ option.setIconUrl(iconFileName);
+ option.setPlanInputMessageUrl(planInputMessageFileName);
+ option.setPlanServiceName(planServiceName);
+
+ // BEGIN: store icon and planInputMessage
+
+ SelfServiceMetaDataId ssmdId = ((SelfServicePortalResource) this.res).getId();
+
+ RepositoryFileReference iconRef = new RepositoryFileReference(ssmdId, iconFileName);
+ try {
+ Repository.INSTANCE.putContentToFile(iconRef, uploadedInputStream, body.getMediaType());
+ } catch (IOException e) {
+ OptionsResource.logger.error(e.getMessage(), e);
+ return Response.serverError().entity(e.getMessage()).build();
+ }
+
+ RepositoryFileReference planInputMessageRef = new RepositoryFileReference(ssmdId, planInputMessageFileName);
+ try {
+ Repository.INSTANCE.putContentToFile(planInputMessageRef, planInputMessage, MediaType.TEXT_XML_TYPE);
+ } catch (IOException e) {
+ OptionsResource.logger.error(e.getMessage(), e);
+ return Response.serverError().entity(e.getMessage()).build();
+ }
+
+ // END: store icon and planInputMessage
+
+ this.list.add(option);
+ Response response = BackendUtils.persist(this.res);
+ return response;
+ }
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/selfserviceportal/SelfServicePortalResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/selfserviceportal/SelfServicePortalResource.java
new file mode 100644
index 0000000..98e1dcf
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/selfserviceportal/SelfServicePortalResource.java
@@ -0,0 +1,223 @@
+/*******************************************************************************
+ * 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.repository.resources.servicetemplates.selfserviceportal;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.StringWriter;
+import java.util.List;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.GET;
+import javax.ws.rs.HeaderParam;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Unmarshaller;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.taglibs.standard.functions.Functions;
+import org.eclipse.winery.common.RepositoryFileReference;
+import org.eclipse.winery.common.ids.definitions.ServiceTemplateId;
+import org.eclipse.winery.model.selfservice.Application;
+import org.eclipse.winery.model.selfservice.Application.Options;
+import org.eclipse.winery.model.tosca.TDocumentation;
+import org.eclipse.winery.repository.JAXBSupport;
+import org.eclipse.winery.repository.Utils;
+import org.eclipse.winery.repository.backend.BackendUtils;
+import org.eclipse.winery.repository.backend.Repository;
+import org.eclipse.winery.repository.datatypes.ids.elements.SelfServiceMetaDataId;
+import org.eclipse.winery.repository.resources._support.IPersistable;
+import org.eclipse.winery.repository.resources.servicetemplates.ServiceTemplateResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.sun.jersey.api.view.Viewable;
+import com.sun.jersey.multipart.FormDataBodyPart;
+import com.sun.jersey.multipart.FormDataParam;
+
+public class SelfServicePortalResource implements IPersistable {
+
+ private static final Logger logger = LoggerFactory.getLogger(SelfServicePortalResource.class);
+
+ private final ServiceTemplateResource serviceTemplateResource;
+
+ public final RepositoryFileReference data_xml_ref;
+ public final RepositoryFileReference icon_jpg_ref;
+ public final RepositoryFileReference image_jpg_ref;
+
+ private final Application application;
+
+ private final SelfServiceMetaDataId id;
+
+
+ public SelfServicePortalResource(ServiceTemplateId serviceTemplateId) {
+ this(null, serviceTemplateId);
+ }
+
+ public SelfServicePortalResource(ServiceTemplateResource serviceTemplateResource) {
+ this(serviceTemplateResource, (ServiceTemplateId) serviceTemplateResource.getId());
+ }
+
+ SelfServiceMetaDataId getId() {
+ return this.id;
+ }
+
+ /**
+ * @param serviceTemplateResource may be null
+ * @param serviceTemplateId the id, must not be null
+ */
+ private SelfServicePortalResource(ServiceTemplateResource serviceTemplateResource, ServiceTemplateId serviceTemplateId) {
+ this.serviceTemplateResource = serviceTemplateResource;
+ this.id = new SelfServiceMetaDataId(serviceTemplateId);
+ this.data_xml_ref = new RepositoryFileReference(this.id, "data.xml");
+ this.icon_jpg_ref = new RepositoryFileReference(this.id, "icon.jpg");
+ this.image_jpg_ref = new RepositoryFileReference(this.id, "image.jpg");
+ this.application = this.getData();
+ }
+
+ private Application getData() {
+ if (Repository.INSTANCE.exists(this.data_xml_ref)) {
+ Unmarshaller u = JAXBSupport.createUnmarshaller();
+ try (InputStream is = Repository.INSTANCE.newInputStream(this.data_xml_ref);) {
+ return (Application) u.unmarshal(is);
+ } catch (IOException | JAXBException e) {
+ SelfServicePortalResource.logger.error("Could not read from " + this.data_xml_ref, e);
+ return new Application();
+ }
+ } else {
+ return this.getDefaultApplicationData();
+ }
+ }
+
+ private Application getDefaultApplicationData() {
+ Application app = new Application();
+ app.setIconUrl("icon.jpg");
+ app.setImageUrl("image.jpg");
+ if (this.serviceTemplateResource != null) {
+ app.setDisplayName(this.serviceTemplateResource.getName());
+ List<TDocumentation> documentation = this.serviceTemplateResource.getServiceTemplate().getDocumentation();
+ if ((documentation != null) && (!documentation.isEmpty())) {
+ TDocumentation doc = documentation.get(0);
+ List<Object> content = doc.getContent();
+ if ((content != null) && (!content.isEmpty())) {
+ app.setDescription(content.get(0).toString());
+ }
+ }
+ }
+ return app;
+ }
+
+ @GET
+ @Produces(MediaType.TEXT_HTML)
+ public Viewable getHTML() {
+ return new Viewable("/jsp/servicetemplates/selfservicemetadata/selfservicemetadata.jsp", this);
+ }
+
+ @Override
+ public void persist() throws IOException {
+ BackendUtils.persist(this.application, this.data_xml_ref, MediaType.TEXT_XML_TYPE);
+ }
+
+ @PUT
+ @Consumes(MediaType.TEXT_XML)
+ public Response onPutXML(Application data) {
+ String content = Utils.getXMLAsString(data);
+ return BackendUtils.putContentToFile(this.data_xml_ref, content, MediaType.TEXT_XML_TYPE);
+ }
+
+ @Path("icon.jpg")
+ @GET
+ public Response getIcon(@HeaderParam("If-Modified-Since") String modified) {
+ RepositoryFileReference ref = new RepositoryFileReference(this.id, "icon.jpg");
+ return BackendUtils.returnRepoPath(ref, modified);
+ }
+
+ @Path("icon.jpg")
+ @PUT
+ @Consumes(MediaType.MULTIPART_FORM_DATA)
+ public Response putIcon(@FormDataParam("file") InputStream uploadedInputStream, @FormDataParam("file") FormDataBodyPart body) {
+ RepositoryFileReference ref = new RepositoryFileReference(this.id, "icon.jpg");
+ return BackendUtils.putContentToFile(ref, uploadedInputStream, body.getMediaType());
+ }
+
+ @Path("image.jpg")
+ @GET
+ public Response getImage(@HeaderParam("If-Modified-Since") String modified) {
+ RepositoryFileReference ref = new RepositoryFileReference(this.id, "image.jpg");
+ return BackendUtils.returnRepoPath(ref, modified);
+ }
+
+ @Path("image.jpg")
+ @PUT
+ @Consumes(MediaType.MULTIPART_FORM_DATA)
+ public Response putImage(@FormDataParam("file") InputStream uploadedInputStream, @FormDataParam("file") FormDataBodyPart body) {
+ RepositoryFileReference ref = new RepositoryFileReference(this.id, "image.jpg");
+ return BackendUtils.putContentToFile(ref, uploadedInputStream, body.getMediaType());
+ }
+
+ @Path("displayname")
+ @PUT
+ public Response onPutOnDisplayName(@FormParam("value") String value) {
+ this.application.setDisplayName(value);
+ return BackendUtils.persist(this);
+ }
+
+ @Path("description")
+ @PUT
+ public Response onPutOnDescription(@FormParam("value") String value) {
+ this.application.setDescription(value);
+ return BackendUtils.persist(this);
+ }
+
+ @Path("options/")
+ public OptionsResource getOptionsResource() {
+ Options options = this.application.getOptions();
+ if (options == null) {
+ options = new Options();
+ this.application.setOptions(options);
+ }
+ return new OptionsResource(options.getOption(), this);
+ }
+
+ /**
+ * @return the internal application object. Used for the export.
+ */
+ public Application getApplication() {
+ return this.application;
+ }
+
+ /**
+ * Used in JSP only
+ */
+ public String getApplicationAsXMLStringEncoded() {
+ String res;
+ if (Repository.INSTANCE.exists(this.data_xml_ref)) {
+ StringWriter sw = new StringWriter();
+ try (InputStream is = Repository.INSTANCE.newInputStream(this.data_xml_ref);) {
+ IOUtils.copy(is, sw);
+ } catch (IOException e) {
+ SelfServicePortalResource.logger.error("Could not read from file", e);
+ }
+ res = sw.toString();
+ } else {
+ // return skeleton for application
+ // application object is already filled with default values if no file exists in repo
+ res = Utils.getXMLAsString(this.getApplication());
+ }
+ return Functions.escapeXml(res);
+ }
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/topologytemplates/NodeTemplateResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/topologytemplates/NodeTemplateResource.java
new file mode 100644
index 0000000..2a59aa5
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/topologytemplates/NodeTemplateResource.java
@@ -0,0 +1,145 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2014 University of Stuttgart.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ * Oliver Kopp - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.winery.repository.resources.servicetemplates.topologytemplates;
+
+import java.util.List;
+import java.util.Map;
+
+import javax.ws.rs.FormParam;
+import javax.ws.rs.GET;
+import javax.ws.rs.HEAD;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Response;
+import javax.xml.namespace.QName;
+
+import org.eclipse.winery.common.constants.Namespaces;
+import org.eclipse.winery.common.ids.Namespace;
+import org.eclipse.winery.model.tosca.TNodeTemplate;
+import org.eclipse.winery.repository.backend.BackendUtils;
+import org.eclipse.winery.repository.resources.INodeTemplateResourceOrNodeTypeImplementationResource;
+import org.eclipse.winery.repository.resources._support.IPersistable;
+import org.eclipse.winery.repository.resources._support.collections.IIdDetermination;
+import org.eclipse.winery.repository.resources.artifacts.DeploymentArtifactsResource;
+import org.eclipse.winery.repository.resources.entitytemplates.TEntityTemplateResource;
+import org.eclipse.winery.repository.resources.servicetemplates.ServiceTemplateResource;
+import org.restdoc.annotations.RestDoc;
+
+public class NodeTemplateResource extends TEntityTemplateResource<TNodeTemplate> implements INodeTemplateResourceOrNodeTypeImplementationResource {
+
+ public NodeTemplateResource(IIdDetermination<TNodeTemplate> idDetermination, TNodeTemplate o, int idx, List<TNodeTemplate> list, IPersistable res) {
+ super(idDetermination, o, idx, list, res);
+ }
+
+ @Path("deploymentartifacts/")
+ public DeploymentArtifactsResource getDeploymentArtifacts() {
+ return new DeploymentArtifactsResource(this.o, this);
+ }
+
+ @GET
+ @RestDoc(methodDescription = "* The following methods are currently *not* used by the topology modeler.<br />" + "The modeler is using the repository client to interact with the repository")
+ @Path("minInstances")
+ public String getMinInstances() {
+ return Integer.toString(this.o.getMinInstances());
+ }
+
+ @PUT
+ @Path("minInstances")
+ public Response setMinInstances(@FormParam(value = "minInstances") String minInstances) {
+ int min = Integer.parseInt(minInstances);
+ this.o.setMinInstances(min);
+ return BackendUtils.persist(this.res);
+ }
+
+ @GET
+ @Path("maxInstances")
+ public String getMaxInstances() {
+ return this.o.getMaxInstances();
+ }
+
+ @PUT
+ @Path("maxInstances")
+ public Response setMaxInstances(@FormParam(value = "maxInstances") String maxInstances) {
+ // TODO: check for valid integer | "unbound"
+ this.o.setMaxInstances(maxInstances);
+ return BackendUtils.persist(this.res);
+ }
+
+
+ /* * *
+ * The visual appearance
+ *
+ * We do not use a subresource "visualappearance" here to avoid generation of more objects
+ * * */
+
+ private final QName qnameX = new QName(Namespaces.TOSCA_WINERY_EXTENSIONS_NAMESPACE, "x");
+ private final QName qnameY = new QName(Namespaces.TOSCA_WINERY_EXTENSIONS_NAMESPACE, "y");
+
+
+ @Path("x")
+ @GET
+ @RestDoc(methodDescription = "@return the x coordinate of the node template")
+ public String getX() {
+ Map<QName, String> otherAttributes = this.o.getOtherAttributes();
+ return otherAttributes.get(this.qnameX);
+ }
+
+ @Path("x")
+ @PUT
+ public Response setX(String x) {
+ this.o.getOtherAttributes().put(this.qnameX, x);
+ return BackendUtils.persist(this.res);
+ }
+
+ @Path("y")
+ @GET
+ @RestDoc(methodDescription = "@return the y coordinate of the node template")
+ public String getY() {
+ Map<QName, String> otherAttributes = this.o.getOtherAttributes();
+ return otherAttributes.get(this.qnameY);
+ }
+
+ @Path("y")
+ @PUT
+ public Response setY(String y) {
+ this.o.getOtherAttributes().put(this.qnameY, y);
+ return BackendUtils.persist(this.res);
+ }
+
+ @Override
+ public Namespace getNamespace() {
+ // TODO Auto-generated method stub
+ throw new IllegalStateException("Not yet implemented.");
+ }
+
+ /**
+ * Required for persistence after a change of the deployment artifact.
+ * Required by DeploymentArtifactResource to be able to persist
+ *
+ * @return the service template this node template belongs to
+ */
+ public ServiceTemplateResource getServiceTemplateResource() {
+ return (ServiceTemplateResource) this.res;
+ }
+
+ /**
+ * required for topology modeler to check for existence of a node template
+ * at the server
+ *
+ * @return empty response
+ */
+ @HEAD
+ public Response getHEAD() {
+ return Response.noContent().build();
+ }
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/topologytemplates/NodeTemplatesResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/topologytemplates/NodeTemplatesResource.java
new file mode 100644
index 0000000..64c5de8
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/topologytemplates/NodeTemplatesResource.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2014 University of Stuttgart.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ * Oliver Kopp - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.winery.repository.resources.servicetemplates.topologytemplates;
+
+import java.util.List;
+
+import org.eclipse.winery.model.tosca.TNodeTemplate;
+import org.eclipse.winery.repository.resources._support.IPersistable;
+import org.eclipse.winery.repository.resources.entitytemplates.TEntityTemplatesResource;
+
+import com.sun.jersey.api.view.Viewable;
+
+public class NodeTemplatesResource extends TEntityTemplatesResource<NodeTemplateResource, TNodeTemplate> {
+
+ public NodeTemplatesResource(List<TNodeTemplate> list, IPersistable res) {
+ super(NodeTemplateResource.class, TNodeTemplate.class, list, res);
+ }
+
+ @Override
+ public String getId(TNodeTemplate entity) {
+ return entity.getId();
+ }
+
+ @Override
+ public Viewable getHTML() {
+ // TODO Auto-generated method stub
+ throw new IllegalStateException("Not yet implemented.");
+ }
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/topologytemplates/RelationshipTemplateResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/topologytemplates/RelationshipTemplateResource.java
new file mode 100644
index 0000000..a3eaed5
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/topologytemplates/RelationshipTemplateResource.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2014 University of Stuttgart.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ * Oliver Kopp - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.winery.repository.resources.servicetemplates.topologytemplates;
+
+import java.util.List;
+
+import org.eclipse.winery.model.tosca.TRelationshipTemplate;
+import org.eclipse.winery.repository.resources._support.IPersistable;
+import org.eclipse.winery.repository.resources._support.collections.IIdDetermination;
+import org.eclipse.winery.repository.resources.entitytemplates.TEntityTemplateResource;
+
+public class RelationshipTemplateResource extends TEntityTemplateResource<TRelationshipTemplate> {
+
+ public RelationshipTemplateResource(IIdDetermination<TRelationshipTemplate> idDetermination, TRelationshipTemplate o, int idx, List<TRelationshipTemplate> list, IPersistable res) {
+ super(idDetermination, o, idx, list, res);
+ }
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/topologytemplates/RelationshipTemplatesResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/topologytemplates/RelationshipTemplatesResource.java
new file mode 100644
index 0000000..8073e83
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/topologytemplates/RelationshipTemplatesResource.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2014 University of Stuttgart.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ * Oliver Kopp - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.winery.repository.resources.servicetemplates.topologytemplates;
+
+import java.util.List;
+
+import org.eclipse.winery.model.tosca.TRelationshipTemplate;
+import org.eclipse.winery.repository.resources._support.IPersistable;
+import org.eclipse.winery.repository.resources.entitytemplates.TEntityTemplatesResource;
+
+import com.sun.jersey.api.view.Viewable;
+
+public class RelationshipTemplatesResource extends TEntityTemplatesResource<RelationshipTemplateResource, TRelationshipTemplate> {
+
+ public RelationshipTemplatesResource(List<TRelationshipTemplate> list, IPersistable res) {
+ super(RelationshipTemplateResource.class, TRelationshipTemplate.class, list, res);
+ }
+
+ @Override
+ public String getId(TRelationshipTemplate entity) {
+ return entity.getId();
+ }
+
+ @Override
+ public Viewable getHTML() {
+ // TODO Auto-generated method stub
+ throw new IllegalStateException("Not yet implemented.");
+ }
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/topologytemplates/TopologyTemplateResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/topologytemplates/TopologyTemplateResource.java
new file mode 100644
index 0000000..b4b3646
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/topologytemplates/TopologyTemplateResource.java
@@ -0,0 +1,280 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2015 University of Stuttgart.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ * Oliver Kopp - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.winery.repository.resources.servicetemplates.topologytemplates;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+
+import org.eclipse.winery.common.Util;
+import org.eclipse.winery.common.ids.definitions.ServiceTemplateId;
+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.TTopologyTemplate;
+import org.eclipse.winery.repository.Prefs;
+import org.eclipse.winery.repository.Utils;
+import org.eclipse.winery.repository.backend.BackendUtils;
+import org.eclipse.winery.repository.client.IWineryRepositoryClient;
+import org.eclipse.winery.repository.client.WineryRepositoryClientFactory;
+import org.eclipse.winery.repository.json.TopologyTemplateModule;
+import org.eclipse.winery.repository.resources.servicetemplates.ServiceTemplateResource;
+import org.restdoc.annotations.RestDoc;
+import org.restdoc.annotations.RestDocParam;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+import com.sun.jersey.api.client.Client;
+import com.sun.jersey.api.client.WebResource.Builder;
+import com.sun.jersey.api.view.Viewable;
+
+public class TopologyTemplateResource {
+
+ private static final Logger logger = LoggerFactory.getLogger(TopologyTemplateResource.class);
+
+ private final TTopologyTemplate topologyTemplate;
+
+ private final ServiceTemplateResource serviceTemplateRes;
+
+
+ /**
+ * A topology template is always nested in a service template
+ */
+ public TopologyTemplateResource(ServiceTemplateResource parent) {
+ this.topologyTemplate = parent.getServiceTemplate().getTopologyTemplate();
+ this.serviceTemplateRes = parent;
+ }
+
+
+ public static class DataForJSP {
+
+ private String location;
+ private TTopologyTemplate topologyTemplate;
+ private URI repositoryURI;
+ private String additonalCSS;
+ private Boolean autoLayoutOnLoad;
+ private String additionalScript;
+
+
+ public DataForJSP(String location, URI repositoryURI, TTopologyTemplate topologyTemplate, String additonalCSS, String additionalScript, Boolean autoLayoutOnLoad) {
+ this.location = location;
+ this.repositoryURI = repositoryURI;
+ this.topologyTemplate = topologyTemplate;
+ this.additonalCSS = additonalCSS;
+ this.additionalScript = additionalScript;
+ this.autoLayoutOnLoad = autoLayoutOnLoad;
+ }
+
+ public String getLocation() {
+ return this.location;
+ }
+
+ public TTopologyTemplate getTopologyTemplate() {
+ return this.topologyTemplate;
+ }
+
+ public String getAdditonalCSS() {
+ return this.additonalCSS;
+ }
+
+ public String getAdditionalScript() {
+ return this.additionalScript;
+ }
+
+ public Boolean getAutoLayoutOnLoad() {
+ return this.autoLayoutOnLoad;
+ }
+
+ public IWineryRepositoryClient getClient() {
+ // Quick hack
+ // IWineryRepository is not implemented by Prefs.INSTANCE.getRepository()
+ // Therefore, we have to generate a real WineryRepositoryClient even if that causes more http load
+ IWineryRepositoryClient client = WineryRepositoryClientFactory.getWineryRepositoryClient();
+ client.addRepository(this.repositoryURI.toString());
+ return client;
+ }
+
+ }
+
+
+ @GET
+ @RestDoc(methodDescription = "?edit is used in the URL to get the jsPlumb-based editor")
+ @Produces(MediaType.TEXT_HTML)
+ // @formatter:off
+ public Response getHTML(
+ @QueryParam(value = "edit") String edit,
+ @QueryParam(value = "script") @RestDocParam(description = "the script to include in a <script> tag. The function wineryViewExternalScriptOnLoad if it is defined. Only available if 'view' is also set") String script,
+ @QueryParam(value = "view") String view,
+ @QueryParam(value = "autoLayoutOnLoad") String autoLayoutOnLoad,
+ @Context UriInfo uriInfo) {
+ // @formatter:on
+ Response res;
+ String JSPName;
+ String location = Prefs.INSTANCE.getWineryTopologyModelerPath();
+ location = uriInfo.getBaseUri().resolve(location).toString();
+ // at the topology modeler, jersey needs to have an absolute path
+ URI repositoryURI = uriInfo.getBaseUri();
+ location = location + "/?repositoryURL=";
+ location = location + Util.URLencode(repositoryURI.toString());
+ ServiceTemplateId serviceTemplate = (ServiceTemplateId) this.serviceTemplateRes.getId();
+ location = location + "&ns=";
+ location = location + serviceTemplate.getNamespace().getEncoded();
+ location = location + "&id=";
+ location = location + serviceTemplate.getXmlId().getEncoded();
+ if (edit == null) {
+ String additionalCSS = null;
+ Boolean autoLayoutOnLoadBoolean = false;
+ if (view == null) {
+ // integration in Winery
+ // currently not maintained: Winery includes ?view as iframe
+ JSPName = "/jsp/servicetemplates/topologytemplates/topologytemplate.jsp";
+ } else {
+ // view only mode
+ // fullscreen: additionalCSS and script possible
+ if (!"".equals(view)) {
+ // view with additional CSS
+ URI cssURI = URI.create(view);
+ if (cssURI.isAbsolute()) {
+ additionalCSS = view;
+ } else {
+ // relative URLs starts at "/css/topologyrendering/"
+ additionalCSS = uriInfo.getBaseUri().resolve("css/topologytemplaterendering/").resolve(view).toString();
+ if (!additionalCSS.endsWith(".css")) {
+ additionalCSS += ".css";
+ }
+ }
+ }
+ if (autoLayoutOnLoad != null) {
+ autoLayoutOnLoadBoolean = true;
+ }
+ JSPName = "/jsp/servicetemplates/topologytemplates/topologytemplateview.jsp";
+ }
+ Viewable viewable = new Viewable(JSPName, new DataForJSP(location, repositoryURI, this.topologyTemplate, additionalCSS, script, autoLayoutOnLoadBoolean));
+ res = Response.ok().header(HttpHeaders.VARY, HttpHeaders.ACCEPT).entity(viewable).build();
+ } else {
+ // edit mode
+ URI uri = Utils.createURI(location);
+ res = Response.seeOther(uri).build();
+ }
+ return res;
+ }
+
+ /**
+ *
+ * @param uriInfo the URI ending with "topologytemplate/" of a service
+ * template
+ */
+ @GET
+ @Produces(MediaType.TEXT_PLAIN)
+ public Response triggerGenerateBuildPlan(@Context UriInfo uriInfo) {
+ String plansURI = uriInfo.getAbsolutePath().resolve("../plans/").toString();
+ String csarURI = uriInfo.getAbsolutePath().resolve("../?csar").toString();
+
+ String request = "<generatePlanForTopology><CSARURL>";
+ request += csarURI;
+ request += "</CSARURL><PLANPOSTURL>";
+ request += plansURI;
+ request += "</PLANPOSTURL></generatePlanForTopology>";
+
+ Client client = Client.create();
+ Builder wr = client.resource("http://localhost:1339/planbuilder/sync").type(MediaType.APPLICATION_XML);
+
+ try {
+ wr.post(String.class, request);
+ } catch (com.sun.jersey.api.client.UniformInterfaceException e) {
+ return Response.serverError().entity(e.getMessage()).build();
+ }
+
+ return Response.ok().build();
+ }
+
+ // @formatter:off
+ @GET
+ @RestDoc(methodDescription="Returns a JSON representation of the topology template. <br />" +
+ "X and Y coordinates are embedded as attributes. QName string with Namespace: <br />" +
+ "{@link org.eclipse.winery.repository.common.constants.Namespaces.TOSCA_WINERY_EXTENSIONS_NAMESPACE} <br />" +
+ "@return The JSON representation of the topology template <em>without</em> associated artifacts and without the parent service template")
+ @Produces(MediaType.APPLICATION_JSON)
+ // @formatter:on
+ public Response getComponentInstanceJSON() {
+ Response res;
+ ObjectMapper mapper = new ObjectMapper();
+ mapper.enable(SerializationFeature.INDENT_OUTPUT);
+ mapper.registerModule(new TopologyTemplateModule());
+ try {
+ // convert it to json
+ String json = mapper.writeValueAsString(this.topologyTemplate);
+ res = Response.ok(json).build();
+ } catch (Exception e) {
+ TopologyTemplateResource.logger.error(e.getMessage(), e);
+ res = Response.serverError().entity(e.getMessage()).build();
+ }
+ return res;
+ }
+
+ @Path("nodetemplates/")
+ public NodeTemplatesResource getNodeTemplatesResource() {
+ // FIXME: onDelete will not work as we have a copy of the original list. We have to add a "listener" to remove at the list and route that remove to the original list
+ List<TNodeTemplate> l = BackendUtils.getAllNestedNodeTemplates(this.serviceTemplateRes.getServiceTemplate());
+ return new NodeTemplatesResource(l, this.serviceTemplateRes);
+ }
+
+ @Path("relationshiptemplates/")
+ public RelationshipTemplatesResource getRelationshipTemplatesResource() {
+ // FIXME: onDelete will not work. See getNodeTemplatesResource
+ List<TRelationshipTemplate> l = new ArrayList<TRelationshipTemplate>();
+ for (TEntityTemplate t : this.topologyTemplate.getNodeTemplateOrRelationshipTemplate()) {
+ if (t instanceof TRelationshipTemplate) {
+ l.add((TRelationshipTemplate) t);
+ }
+ }
+ return new RelationshipTemplatesResource(l, this.serviceTemplateRes);
+ }
+
+ @PUT
+ @RestDoc(methodDescription = "Replaces the topology by the information given in the XML")
+ @Consumes(MediaType.TEXT_XML)
+ public Response setModel(TTopologyTemplate topologyTemplate) {
+ this.serviceTemplateRes.getServiceTemplate().setTopologyTemplate(topologyTemplate);
+ return BackendUtils.persist(this.serviceTemplateRes);
+ }
+
+ // @formatter:off
+ @GET
+ @RestDoc(methodDescription="<p>Returns an XML representation of the topology template." +
+ " X and Y coordinates are embedded as attributes. Namespace:" +
+ "{@link org.eclipse.winery.repository.common.constants.Namespaces.TOSCA_WINERY_EXTENSIONS_NAMESPACE} </p>" +
+ "<p>{@link org.eclipse.winery.repository.client.WineryRepositoryClient." +
+ "getTopologyTemplate(QName)} consumes this template</p>" +
+ "<p>@return The XML representation of the topology template <em>without</em>" +
+ "associated artifacts and without the parent service template </p>")
+ @Produces(MediaType.TEXT_XML)
+ // @formatter:on
+ public Response getComponentInstanceXML() {
+ return Utils.getXML(TTopologyTemplate.class, this.topologyTemplate);
+ }
+
+}
diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/tags/TagsResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/tags/TagsResource.java
new file mode 100644
index 0000000..21596e6
--- /dev/null
+++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/tags/TagsResource.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * 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.repository.resources.tags;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+import org.eclipse.winery.common.ids.definitions.TOSCAComponentId;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.sun.jersey.api.view.Viewable;
+
+public class TagsResource {
+
+ private static final Logger logger = LoggerFactory.getLogger(TagsResource.class);
+
+
+ public TagsResource(TOSCAComponentId parentId) {
+ }
+
+ @GET
+ @Produces(MediaType.TEXT_HTML)
+ public Viewable getHTML() {
+ return new Viewable("/jsp/tags/tags.jsp", this);
+ }
+
+}