1 /*******************************************************************************
2 * Copyright (c) 2012-2013 University of Stuttgart.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * and the Apache License 2.0 which both accompany this distribution,
6 * and are available at http://www.eclipse.org/legal/epl-v10.html
7 * and http://www.apache.org/licenses/LICENSE-2.0
10 * Kálmán Képes - initial API and implementation and/or initial documentation
11 * Oliver Kopp - adapted to new storage model and to TOSCA v1.0
12 *******************************************************************************/
13 package org.eclipse.winery.repository.export;
15 import java.io.IOException;
16 import java.io.OutputStream;
17 import java.lang.reflect.Constructor;
18 import java.lang.reflect.InvocationTargetException;
20 import java.util.ArrayList;
21 import java.util.Collection;
22 import java.util.Collections;
23 import java.util.HashMap;
24 import java.util.HashSet;
25 import java.util.List;
27 import java.util.SortedSet;
29 import javax.xml.XMLConstants;
30 import javax.xml.bind.JAXBException;
31 import javax.xml.bind.Marshaller;
32 import javax.xml.namespace.QName;
34 import org.apache.commons.lang3.StringUtils;
35 import org.eclipse.winery.common.ModelUtilities;
36 import org.eclipse.winery.common.RepositoryFileReference;
37 import org.eclipse.winery.common.Util;
38 import org.eclipse.winery.common.constants.QNames;
39 import org.eclipse.winery.common.ids.definitions.ArtifactTemplateId;
40 import org.eclipse.winery.common.ids.definitions.ArtifactTypeId;
41 import org.eclipse.winery.common.ids.definitions.CapabilityTypeId;
42 import org.eclipse.winery.common.ids.definitions.EntityTypeId;
43 import org.eclipse.winery.common.ids.definitions.NodeTypeId;
44 import org.eclipse.winery.common.ids.definitions.NodeTypeImplementationId;
45 import org.eclipse.winery.common.ids.definitions.PolicyTemplateId;
46 import org.eclipse.winery.common.ids.definitions.PolicyTypeId;
47 import org.eclipse.winery.common.ids.definitions.RelationshipTypeId;
48 import org.eclipse.winery.common.ids.definitions.RelationshipTypeImplementationId;
49 import org.eclipse.winery.common.ids.definitions.RequirementTypeId;
50 import org.eclipse.winery.common.ids.definitions.ServiceTemplateId;
51 import org.eclipse.winery.common.ids.definitions.TOSCAComponentId;
52 import org.eclipse.winery.common.ids.definitions.TopologyGraphElementEntityTypeId;
53 import org.eclipse.winery.common.ids.definitions.imports.GenericImportId;
54 import org.eclipse.winery.common.ids.elements.PlanId;
55 import org.eclipse.winery.common.ids.elements.PlansId;
56 import org.eclipse.winery.common.propertydefinitionkv.WinerysPropertiesDefinition;
57 import org.eclipse.winery.model.tosca.Definitions;
58 import org.eclipse.winery.model.tosca.TBoundaryDefinitions;
59 import org.eclipse.winery.model.tosca.TBoundaryDefinitions.Policies;
60 import org.eclipse.winery.model.tosca.TCapability;
61 import org.eclipse.winery.model.tosca.TCapabilityDefinition;
62 import org.eclipse.winery.model.tosca.TDeploymentArtifact;
63 import org.eclipse.winery.model.tosca.TDeploymentArtifacts;
64 import org.eclipse.winery.model.tosca.TEntityTemplate;
65 import org.eclipse.winery.model.tosca.TEntityType;
66 import org.eclipse.winery.model.tosca.TEntityType.PropertiesDefinition;
67 import org.eclipse.winery.model.tosca.TImplementationArtifact;
68 import org.eclipse.winery.model.tosca.TImplementationArtifacts;
69 import org.eclipse.winery.model.tosca.TImport;
70 import org.eclipse.winery.model.tosca.TNodeTemplate;
71 import org.eclipse.winery.model.tosca.TNodeTemplate.Capabilities;
72 import org.eclipse.winery.model.tosca.TNodeTemplate.Requirements;
73 import org.eclipse.winery.model.tosca.TNodeType;
74 import org.eclipse.winery.model.tosca.TNodeType.CapabilityDefinitions;
75 import org.eclipse.winery.model.tosca.TNodeType.RequirementDefinitions;
76 import org.eclipse.winery.model.tosca.TPolicy;
77 import org.eclipse.winery.model.tosca.TRelationshipTemplate;
78 import org.eclipse.winery.model.tosca.TRelationshipType;
79 import org.eclipse.winery.model.tosca.TRelationshipType.ValidSource;
80 import org.eclipse.winery.model.tosca.TRelationshipType.ValidTarget;
81 import org.eclipse.winery.model.tosca.TRequirement;
82 import org.eclipse.winery.model.tosca.TRequirementDefinition;
83 import org.eclipse.winery.repository.JAXBSupport;
84 import org.eclipse.winery.repository.Utils;
85 import org.eclipse.winery.repository.backend.BackendUtils;
86 import org.eclipse.winery.repository.backend.Repository;
87 import org.eclipse.winery.repository.backend.constants.Filename;
88 import org.eclipse.winery.repository.datatypes.ids.elements.ArtifactTemplateDirectoryId;
89 import org.eclipse.winery.repository.datatypes.ids.elements.VisualAppearanceId;
90 import org.eclipse.winery.repository.resources.AbstractComponentInstanceResource;
91 import org.eclipse.winery.repository.resources.AbstractComponentInstanceResourceWithNameDerivedFromAbstractFinal;
92 import org.eclipse.winery.repository.resources.AbstractComponentsResource;
93 import org.eclipse.winery.repository.resources.EntityTypeResource;
94 import org.eclipse.winery.repository.resources.entitytemplates.artifacttemplates.ArtifactTemplateResource;
95 import org.eclipse.winery.repository.resources.entitytemplates.policytemplates.PolicyTemplateResource;
96 import org.eclipse.winery.repository.resources.entitytypeimplementations.nodetypeimplementations.NodeTypeImplementationResource;
97 import org.eclipse.winery.repository.resources.entitytypeimplementations.relationshiptypeimplementations.RelationshipTypeImplementationResource;
98 import org.eclipse.winery.repository.resources.entitytypes.nodetypes.NodeTypeResource;
99 import org.eclipse.winery.repository.resources.entitytypes.relationshiptypes.RelationshipTypeResource;
100 import org.eclipse.winery.repository.resources.entitytypes.requirementtypes.RequirementTypeResource;
101 import org.eclipse.winery.repository.resources.servicetemplates.ServiceTemplateResource;
102 import org.slf4j.ext.XLogger;
103 import org.slf4j.ext.XLoggerFactory;
104 import org.w3c.dom.Document;
106 public class TOSCAExportUtil {
108 private static final XLogger logger = XLoggerFactory.getXLogger(TOSCAExportUtil.class);
111 * these two are GLOBAL VARIABLES leading to the fact that this class has to
112 * be constructed for each export
115 // collects the references to be put in the CSAR and the assigned path in
117 // this allows to use other paths in the CSAR than on the local storage
118 private Map<RepositoryFileReference, String> referencesToPathInCSARMap = null;
121 * Currently a very simple approach to configure the export
123 private Map<String, Object> exportConfiguration;
126 public enum ExportProperties {
127 INCLUDEXYCOORDINATES, REPOSITORY_URI
132 * Writes the <em>complete</em> tosca xml into the given outputstream
134 * @param id the id of the TOSCA component instance to export
135 * @param out outputstream to write to
136 * @param addRelatedComponents true: all referenced components
137 * (artifactTemplates, artifactTypes, ...) are added, false: only
138 * the XML belonging to the id is exported. If XML types are
139 * generated by Winery (e.g., the properties XSD for node types),
140 * these XML types are also exported
141 * @param exportConfiguration the configuration map for the export. Uses
142 * @param exportedState exportedState object to modify. ExportProperties
143 * provides the possible keys
144 * @return a collection of TOSCAcomponentIds referenced by the given
146 * @throws JAXBException
148 public Collection<TOSCAComponentId> exportTOSCA(TOSCAComponentId id, OutputStream out, Map<String, Object> exportConfiguration) throws IOException, JAXBException {
149 this.exportConfiguration = exportConfiguration;
150 this.initializeExport();
151 return this.writeDefinitionsElement(id, out);
154 private void initializeExport() {
155 this.setDefaultExportConfiguration();
156 // quick hack to avoid NPE
157 if (this.referencesToPathInCSARMap == null) {
158 this.referencesToPathInCSARMap = new HashMap<>();
163 * Quick hack to set defaults. Typically, a configuration builder or similar
166 private void setDefaultExportConfiguration() {
167 this.checkConfig(ExportProperties.INCLUDEXYCOORDINATES, Boolean.FALSE);
170 private void checkConfig(ExportProperties propKey, Boolean bo) {
171 if (!this.exportConfiguration.containsKey(propKey.toString())) {
172 this.exportConfiguration.put(propKey.toString(), bo);
177 * Writes the <em>complete</em> TOSCA XML into the given outputstream.
178 * Additionally, a the artifactMap is filled to enable the CSAR exporter to
179 * create necessary entries in TOSCA-Meta and to add them to the CSAR itself
181 * @param id the component instance to export
182 * @param out outputstream to write to
183 * @param exportConfiguration Configures the exporter
184 * @param referencesToPathInCSARMap collects the references to export. It is
185 * updated during the export
186 * @return a collection of TOSCAcomponentIds referenced by the given
188 * @throws JAXBException
190 protected Collection<TOSCAComponentId> exportTOSCA(TOSCAComponentId id, OutputStream out, Map<RepositoryFileReference, String> referencesToPathInCSARMap, Map<String, Object> exportConfiguration) throws IOException, JAXBException {
191 this.referencesToPathInCSARMap = referencesToPathInCSARMap;
192 return this.exportTOSCA(id, out, exportConfiguration);
196 * Called when the entry resource is definitions backed
198 * @throws JAXBException
200 private void writeDefinitionsElement(Definitions entryDefinitions, OutputStream out) throws JAXBException {
201 Marshaller m = JAXBSupport.createMarshaller(true);
202 m.marshal(entryDefinitions, out);
206 * Writes the Definitions belonging to the given TOSCA component to the
209 * @return a collection of TOSCAcomponentIds referenced by the given
212 * @throws IOException
213 * @throws JAXBException
214 * @throws IllegalStateException if tcId does not exist
216 private Collection<TOSCAComponentId> writeDefinitionsElement(TOSCAComponentId tcId, OutputStream out) throws IOException, JAXBException {
217 if (!Repository.INSTANCE.exists(tcId)) {
218 String error = "Component instance " + tcId.toString() + " does not exist.";
219 TOSCAExportUtil.logger.error(error);
220 throw new IllegalStateException(error);
223 AbstractComponentInstanceResource res = AbstractComponentsResource.getComponentInstaceResource(tcId);
224 Definitions entryDefinitions = res.getDefinitions();
226 // BEGIN: Definitions modification
227 // the "imports" collection contains the imports of Definitions, not of other definitions
228 // the other definitions are stored in entryDefinitions.getImport()
229 // we modify the internal definitions object directly. It is not written back to the storage. Therefore, we do not need to clone it
231 // the imports (pointing to not-definitions (xsd, wsdl, ...)) already have a correct relative URL. (quick hack)
232 URI uri = (URI) this.exportConfiguration.get(TOSCAExportUtil.ExportProperties.REPOSITORY_URI.toString());
234 // we are in the plain-XML mode, the URLs of the imports have to be adjusted
235 for (TImport i : entryDefinitions.getImport()) {
236 String loc = i.getLocation();
237 assert (loc.startsWith("../"));
238 loc = loc.substring(3);
240 // now the location is an absolute URL
245 // files of imports have to be added to the CSAR, too
246 for (TImport i : entryDefinitions.getImport()) {
247 String loc = i.getLocation();
248 if (Util.isRelativeURI(loc)) {
249 // locally stored, add to CSAR
250 GenericImportId iid = new GenericImportId(i);
251 String fileName = Util.getLastURIPart(loc);
252 fileName = Util.URLdecode(fileName);
253 RepositoryFileReference ref = new RepositoryFileReference(iid, fileName);
254 this.putRefAsReferencedItemInCSAR(ref);
258 // adjust imports: add imports of definitions to it
259 Collection<TOSCAComponentId> referencedTOSCAComponentIds = this.getReferencedTOSCAComponentIds(tcId);
260 Collection<TImport> imports = new ArrayList<>();
261 for (TOSCAComponentId id : referencedTOSCAComponentIds) {
262 this.addToImports(id, imports);
264 entryDefinitions.getImport().addAll(imports);
266 if (res.getElement() instanceof TEntityType) {
267 // we have an entity type with a possible properties definition
268 EntityTypeResource entityTypeRes = (EntityTypeResource) res;
269 WinerysPropertiesDefinition wpd = ModelUtilities.getWinerysPropertiesDefinition(entityTypeRes.getEntityType());
271 if (wpd.getIsDerivedFromXSD() == null) {
272 // Write WPD only to file if it exists and is NOT derived from an XSD (which may happen during import)
274 String wrapperElementNamespace = wpd.getNamespace();
275 String wrapperElementLocalName = wpd.getElementName();
277 // BEGIN: add import and put into CSAR
279 TImport imp = new TImport();
280 entryDefinitions.getImport().add(imp);
282 // fill known import values
283 imp.setImportType(XMLConstants.W3C_XML_SCHEMA_NS_URI);
284 imp.setNamespace(wrapperElementNamespace);
285 // add "winerysPropertiesDefinition" flag to import tag to support
286 Map<QName, String> otherAttributes = imp.getOtherAttributes();
287 otherAttributes.put(QNames.QNAME_WINERYS_PROPERTIES_DEFINITION_ATTRIBUTE, "true");
289 // Determine location
290 String loc = BackendUtils.getImportLocationForWinerysPropertiesDefinitionXSD((EntityTypeId) tcId, uri, wrapperElementLocalName);
292 TOSCAExportUtil.logger.trace("CSAR Export mode. Putting XSD into CSAR");
294 // XSD has to be put into the CSAR
295 Document document = ModelUtilities.getWinerysPropertiesDefinitionXSDAsDocument(wpd);
297 // loc in import is URLencoded, loc on filesystem isn't
298 String locInCSAR = Util.URLdecode(loc);
299 // furthermore, the path has to start from the root of the CSAR; currently, it starts from Definitions/
300 locInCSAR = locInCSAR.substring(3);
301 TOSCAExportUtil.logger.trace("Location in CSAR: {}", locInCSAR);
302 this.referencesToPathInCSARMap.put(new DummyRepositoryFileReferenceForGeneratedXSD(document), locInCSAR);
304 imp.setLocation(loc);
306 // END: add import and put into CSAR
308 // BEGIN: generate TOSCA conforming PropertiesDefinition
310 TEntityType entityType = entityTypeRes.getEntityType();
311 PropertiesDefinition propertiesDefinition = new PropertiesDefinition();
312 propertiesDefinition.setType(new QName(wrapperElementNamespace, wrapperElementLocalName));
313 entityType.setPropertiesDefinition(propertiesDefinition);
315 // END: generate TOSCA conforming PropertiesDefinition
317 // otherwise WPD exists, but is derived from XSD
318 // we DO NOT have to remove the winery properties definition from the output to allow "debugging" of the CSAR
323 // END: Definitions modification
325 this.writeDefinitionsElement(entryDefinitions, out);
327 return referencedTOSCAComponentIds;
330 private Collection<TOSCAComponentId> getReferencedTOSCAComponentIds(EntityTypeId id) {
331 return this.getReferencedTOSCAComponentIdOfParentForAnAbstractComponentsWithTypeReferenceResource(id);
335 * There is now equivalent id class for
336 * AbstractComponentInstanceResourceWithNameDerivedFromAbstractFinal,
337 * therefore we take the super type and hope that the caller knows what he
340 private Collection<TOSCAComponentId> getReferencedTOSCAComponentIdOfParentForAnAbstractComponentsWithTypeReferenceResource(TOSCAComponentId id) {
341 AbstractComponentInstanceResourceWithNameDerivedFromAbstractFinal res = (AbstractComponentInstanceResourceWithNameDerivedFromAbstractFinal) AbstractComponentsResource.getComponentInstaceResource(id);
342 String derivedFrom = res.getInheritanceManagement().getDerivedFrom();
343 if (StringUtils.isEmpty(derivedFrom)) {
344 return Collections.emptySet();
346 // Instantiate an id with the same class as the current id
347 TOSCAComponentId parentId;
348 QName qname = QName.valueOf(derivedFrom);
350 Constructor<? extends TOSCAComponentId> constructor;
352 constructor = id.getClass().getConstructor(QName.class);
353 } catch (NoSuchMethodException | SecurityException e1) {
354 throw new IllegalStateException("Could get constructor to instantiate parent id", e1);
357 parentId = constructor.newInstance(qname);
358 } catch (InstantiationException | IllegalAccessException
359 | IllegalArgumentException | InvocationTargetException e) {
360 throw new IllegalStateException("Could not instantiate id for parent", e);
363 Collection<TOSCAComponentId> result = new ArrayList<>(1);
364 result.add(parentId);
370 * This method is intended to be used by exportTOSCA. However,
371 * org.eclipse.winery.repository.client requires an XML representation of a
372 * component instances without a surrounding definitions element.
374 * We name this method differently to prevent wrong calling due to
377 * @param definitionsElement the parent XML element
379 private Collection<TOSCAComponentId> getReferencedTOSCAComponentIds(TOSCAComponentId id) {
380 Collection<TOSCAComponentId> referencedTOSCAComponentIds;
382 // first of all, handle the concrete elements
383 if (id instanceof ServiceTemplateId) {
384 referencedTOSCAComponentIds = this.prepareForExport((ServiceTemplateId) id);
385 } else if (id instanceof NodeTypeId) {
386 referencedTOSCAComponentIds = this.getReferencedTOSCAComponentIds((NodeTypeId) id);
387 } else if (id instanceof NodeTypeImplementationId) {
388 referencedTOSCAComponentIds = this.getReferencedTOSCAComponentIds((NodeTypeImplementationId) id);
389 } else if (id instanceof RelationshipTypeId) {
390 referencedTOSCAComponentIds = this.getReferencedTOSCAComponentIds((RelationshipTypeId) id);
391 } else if (id instanceof RelationshipTypeImplementationId) {
392 referencedTOSCAComponentIds = this.getReferencedTOSCAComponentIds((RelationshipTypeImplementationId) id);
393 } else if (id instanceof RequirementTypeId) {
394 referencedTOSCAComponentIds = this.getReferencedTOSCAComponentIds((RequirementTypeId) id);
395 } else if (id instanceof CapabilityTypeId) {
396 referencedTOSCAComponentIds = this.getReferencedTOSCAComponentIds((CapabilityTypeId) id);
397 } else if (id instanceof ArtifactTypeId) {
398 referencedTOSCAComponentIds = this.getReferencedTOSCAComponentIds((ArtifactTypeId) id);
399 } else if (id instanceof ArtifactTemplateId) {
400 referencedTOSCAComponentIds = this.prepareForExport((ArtifactTemplateId) id);
401 } else if (id instanceof PolicyTypeId) {
402 referencedTOSCAComponentIds = this.getReferencedTOSCAComponentIds((PolicyTypeId) id);
403 } else if (id instanceof PolicyTemplateId) {
404 referencedTOSCAComponentIds = this.getReferencedTOSCAComponentIds((PolicyTemplateId) id);
405 } else if (id instanceof GenericImportId) {
406 // in case of imports, there are no other ids referenced
407 referencedTOSCAComponentIds = Collections.emptyList();
409 throw new IllegalStateException("Unhandled id class " + id.getClass());
412 // Then, handle the super classes, which support inheritance
413 // Currently, it is EntityType and EntityTypeImplementation only
414 // Since the latter does not exist in the TOSCA MetaModel, we just handle EntityType here
415 if (id instanceof EntityTypeId) {
416 Collection<TOSCAComponentId> additionalRefs = this.getReferencedTOSCAComponentIds((EntityTypeId) id);
417 // the original referenceTOSCAComponentIds could be unmodifiable
418 // we just create a new one...
419 referencedTOSCAComponentIds = new ArrayList<>(referencedTOSCAComponentIds);
420 // ...and add the new reference
421 referencedTOSCAComponentIds.addAll(additionalRefs);
424 return referencedTOSCAComponentIds;
428 * Adds the given id as import to the given imports collection
430 private void addToImports(TOSCAComponentId id, Collection<TImport> imports) {
431 TImport imp = new TImport();
432 imp.setImportType(org.eclipse.winery.common.constants.Namespaces.TOSCA_NAMESPACE);
433 imp.setNamespace(id.getNamespace().getDecoded());
434 URI uri = (URI) this.exportConfiguration.get(TOSCAExportUtil.ExportProperties.REPOSITORY_URI.toString());
436 // self-contained mode
437 // all Definitions are contained in "Definitions" directory, therefore, we provide the filename only
438 // references are resolved relatively from a definitions element (COS01, line 425)
439 String fn = CSARExporter.getDefinitionsFileName(id);
440 fn = Util.URLencode(fn);
443 String path = Utils.getURLforPathInsideRepo(BackendUtils.getPathInsideRepo(id));
444 path = path + "?definitions";
445 URI absoluteURI = uri.resolve(path);
446 imp.setLocation(absoluteURI.toString());
450 // FIXME: Currently the depended elements (such as the artifact templates linked to a node type implementation) are gathered by the corresponding "addXY" method.
451 // Reason: the corresponding TDefinitions element is *not* updated if a related element is added/removed.
452 // That means: The imports are not changed.
453 // The current issue is that TOSCA allows imports of Definitions only and the repository has the concrete elements as main structure
454 // Although during save the import can be updated (by fetching the associated resource and get the definitions of it),
455 // The concrete definitions cannot be determined without
456 // a) having a complete index of all definitions in the repository
457 // b) crawling through the *complete* repository
458 // Possibly the current solution, just lazily adding all dependent elements is the better solution.
461 private Collection<TOSCAComponentId> getReferencedTOSCAComponentIds(NodeTypeImplementationId id) {
462 // We have to use a HashSet to ensure that no duplicate ids are added
463 // There may be multiple DAs/IAs referencing the same type
464 Collection<TOSCAComponentId> ids = new HashSet<>();
466 NodeTypeImplementationResource res = new NodeTypeImplementationResource(id);
469 TDeploymentArtifacts deploymentArtifacts = res.getNTI().getDeploymentArtifacts();
470 if (deploymentArtifacts != null) {
471 for (TDeploymentArtifact da : deploymentArtifacts.getDeploymentArtifact()) {
473 if ((qname = da.getArtifactRef()) != null) {
474 ids.add(new ArtifactTemplateId(qname));
476 ids.add(new ArtifactTypeId(da.getArtifactType()));
481 TImplementationArtifacts implementationArtifacts = res.getNTI().getImplementationArtifacts();
482 if (implementationArtifacts != null) {
483 for (TImplementationArtifact ia : implementationArtifacts.getImplementationArtifact()) {
485 if ((qname = ia.getArtifactRef()) != null) {
486 ids.add(new ArtifactTemplateId(qname));
488 ids.add(new ArtifactTypeId(ia.getArtifactType()));
493 ids.addAll(this.getReferencedTOSCAComponentIdOfParentForAnAbstractComponentsWithTypeReferenceResource(id));
498 private Collection<TOSCAComponentId> getReferencedTOSCAComponentIds(RelationshipTypeImplementationId id) {
499 // We have to use a HashSet to ensure that no duplicate ids are added
500 // There may be multiple IAs referencing the same type
501 Collection<TOSCAComponentId> ids = new HashSet<>();
503 RelationshipTypeImplementationResource res = new RelationshipTypeImplementationResource(id);
506 for (TImplementationArtifact ia : res.getRTI().getImplementationArtifacts().getImplementationArtifact()) {
508 if ((qname = ia.getArtifactRef()) != null) {
509 ids.add(new ArtifactTemplateId(qname));
511 ids.add(new ArtifactTypeId(ia.getArtifactType()));
515 ids.addAll(this.getReferencedTOSCAComponentIdOfParentForAnAbstractComponentsWithTypeReferenceResource(id));
520 private Collection<TOSCAComponentId> getReferencedTOSCAComponentIds(RequirementTypeId id) {
521 Collection<TOSCAComponentId> ids = new ArrayList<>(1);
523 RequirementTypeResource res = new RequirementTypeResource(id);
524 QName requiredCapabilityType = res.getRequirementType().getRequiredCapabilityType();
525 if (requiredCapabilityType != null) {
526 CapabilityTypeId capId = new CapabilityTypeId(requiredCapabilityType);
532 private Collection<TOSCAComponentId> getReferencedTOSCAComponentIds(CapabilityTypeId id) {
533 return Collections.emptyList();
536 private Collection<TOSCAComponentId> getReferencedTOSCAComponentIds(PolicyTypeId id) {
537 return Collections.emptyList();
540 private Collection<TOSCAComponentId> getReferencedTOSCAComponentIds(PolicyTemplateId id) {
541 Collection<TOSCAComponentId> ids = new ArrayList<>();
542 PolicyTemplateResource res = new PolicyTemplateResource(id);
543 ids.add(new PolicyTypeId(res.getType()));
548 * Synchronizes the plan model references and returns the referenced TOSCA
551 private Collection<TOSCAComponentId> prepareForExport(ServiceTemplateId id) {
552 // We have to use a HashSet to ensure that no duplicate ids are added
553 // E.g., there may be multiple relationship templates having the same type
554 Collection<TOSCAComponentId> ids = new HashSet<>();
555 ServiceTemplateResource res = new ServiceTemplateResource(id);
557 // ensure that the plans stored locally are the same ones as stored in the definitions
558 res.synchronizeReferences();
560 // add all plans as reference in the CSAR
561 // the data model is consistent with the repository
562 // we crawl through the repository to as putRefAsReferencedItemInCSAR expects a repository file reference
563 PlansId plansContainerId = new PlansId(id);
564 SortedSet<PlanId> nestedPlans = Repository.INSTANCE.getNestedIds(plansContainerId, PlanId.class);
565 for (PlanId planId : nestedPlans) {
566 SortedSet<RepositoryFileReference> containedFiles = Repository.INSTANCE.getContainedFiles(planId);
567 // even if we currently support only one file in the directory, we just add everything
568 for (RepositoryFileReference ref : containedFiles) {
569 this.putRefAsReferencedItemInCSAR(ref);
573 // add included things to export queue
575 TBoundaryDefinitions boundaryDefs;
576 if ((boundaryDefs = res.getServiceTemplate().getBoundaryDefinitions()) != null) {
577 Policies policies = boundaryDefs.getPolicies();
578 if (policies != null) {
579 for (TPolicy policy : policies.getPolicy()) {
580 PolicyTypeId policyTypeId = new PolicyTypeId(policy.getPolicyType());
581 ids.add(policyTypeId);
585 // reqs and caps don't have to be exported here as they are references to existing reqs/caps (of nested node templates)
588 if (res.getServiceTemplate().getTopologyTemplate() != null) {
589 for (TEntityTemplate entityTemplate : res.getServiceTemplate().getTopologyTemplate().getNodeTemplateOrRelationshipTemplate()) {
590 QName qname = entityTemplate.getType();
591 if (entityTemplate instanceof TNodeTemplate) {
592 ids.add(new NodeTypeId(qname));
593 TNodeTemplate n = (TNodeTemplate) entityTemplate;
595 // crawl through deployment artifacts
596 TDeploymentArtifacts deploymentArtifacts = n.getDeploymentArtifacts();
597 if (deploymentArtifacts != null) {
598 List<TDeploymentArtifact> das = deploymentArtifacts.getDeploymentArtifact();
599 for (TDeploymentArtifact da : das) {
600 ids.add(new ArtifactTypeId(da.getArtifactType()));
601 if ((qname = da.getArtifactRef()) != null) {
602 ids.add(new ArtifactTemplateId(qname));
607 // crawl through reqs/caps
608 Requirements requirements = n.getRequirements();
609 if (requirements != null) {
610 for (TRequirement req : requirements.getRequirement()) {
611 QName type = req.getType();
612 RequirementTypeId rtId = new RequirementTypeId(type);
616 Capabilities capabilities = n.getCapabilities();
617 if (capabilities != null) {
618 for (TCapability cap : capabilities.getCapability()) {
619 QName type = cap.getType();
620 CapabilityTypeId ctId = new CapabilityTypeId(type);
625 // crawl through policies
626 org.eclipse.winery.model.tosca.TNodeTemplate.Policies policies = n.getPolicies();
627 if (policies != null) {
628 for (TPolicy pol : policies.getPolicy()) {
629 QName type = pol.getPolicyType();
630 PolicyTypeId ctId = new PolicyTypeId(type);
635 assert (entityTemplate instanceof TRelationshipTemplate);
636 ids.add(new RelationshipTypeId(qname));
644 private Collection<TOSCAComponentId> getReferencedTOSCAComponentIds(ArtifactTypeId id) {
645 // no recursive crawling needed
646 return Collections.emptyList();
650 * Determines the referenced TOSCA Component Ids and also updates the
651 * references in the Artifact Template
653 * @return a collection of referenced TOCSA Component Ids
655 private Collection<TOSCAComponentId> prepareForExport(ArtifactTemplateId id) {
656 Collection<TOSCAComponentId> ids = new ArrayList<>();
658 ArtifactTemplateResource res = new ArtifactTemplateResource(id);
661 QName type = res.getType();
663 throw new IllegalStateException("Type is null for " + id.toString());
665 ids.add(new ArtifactTypeId(type));
669 // This method is called BEFORE the concrete definitions element is written.
670 // Therefore, we adapt the content of the attached files to the really existing files
671 res.synchronizeReferences();
673 ArtifactTemplateDirectoryId fileDir = new ArtifactTemplateDirectoryId(id);
674 SortedSet<RepositoryFileReference> files = Repository.INSTANCE.getContainedFiles(fileDir);
675 for (RepositoryFileReference ref : files) {
676 // Even if writing a TOSCA only (!this.writingCSAR),
677 // we put the virtual path in the TOSCA
678 // Reason: Winery is mostly used as a service and local storage
679 // reference to not make sense
680 // The old implementation had absolutePath.toUri().toString();
681 // there, but this does not work when using a cloud blob store.
683 this.putRefAsReferencedItemInCSAR(ref);
690 * Puts the given reference as item in the CSAR
692 * Thereby, it uses the global variable referencesToPathInCSARMap
694 private void putRefAsReferencedItemInCSAR(RepositoryFileReference ref) {
696 String path = BackendUtils.getPathInsideRepo(ref);
698 // put mapping reference to path into global map
699 // the path is the same as put in "synchronizeReferences"
700 this.referencesToPathInCSARMap.put(ref, path);
703 private Collection<TOSCAComponentId> getReferencedTOSCAComponentIds(RelationshipTypeId id) {
704 Collection<TOSCAComponentId> ids = new ArrayList<>();
706 // add all implementations
707 Collection<RelationshipTypeImplementationId> allTypeImplementations = BackendUtils.getAllElementsRelatedWithATypeAttribute(RelationshipTypeImplementationId.class, id.getQName());
708 for (RelationshipTypeImplementationId ntiId : allTypeImplementations) {
712 RelationshipTypeResource res = new RelationshipTypeResource(id);
713 TRelationshipType relationshipType = (TRelationshipType) res.getElement();
715 ValidSource validSource = relationshipType.getValidSource();
716 if (validSource != null) {
717 QName typeRef = validSource.getTypeRef();
718 // can be a node type or a requirement type
720 // similar code as for valid target (difference: req/cap)
721 NodeTypeId ntId = new NodeTypeId(typeRef);
722 if (Repository.INSTANCE.exists(ntId)) {
725 RequirementTypeId rtId = new RequirementTypeId(typeRef);
730 ValidTarget validTarget = relationshipType.getValidTarget();
731 if (validTarget != null) {
732 QName typeRef = validTarget.getTypeRef();
733 // can be a node type or a capability type
735 // similar code as for valid target (difference: req/cap)
736 NodeTypeId ntId = new NodeTypeId(typeRef);
737 if (Repository.INSTANCE.exists(ntId)) {
740 CapabilityTypeId capId = new CapabilityTypeId(typeRef);
745 this.addVisualAppearanceToCSAR(id);
750 private Collection<TOSCAComponentId> getReferencedTOSCAComponentIds(NodeTypeId id) {
751 Collection<TOSCAComponentId> ids = new ArrayList<>();
752 Collection<NodeTypeImplementationId> allNodeTypeImplementations = BackendUtils.getAllElementsRelatedWithATypeAttribute(NodeTypeImplementationId.class, id.getQName());
753 for (NodeTypeImplementationId ntiId : allNodeTypeImplementations) {
757 NodeTypeResource res = new NodeTypeResource(id);
758 TNodeType nodeType = (TNodeType) res.getElement();
760 // add all referenced requirement types
761 RequirementDefinitions reqDefsContainer = nodeType.getRequirementDefinitions();
762 if (reqDefsContainer != null) {
763 List<TRequirementDefinition> reqDefs = reqDefsContainer.getRequirementDefinition();
764 for (TRequirementDefinition reqDef : reqDefs) {
765 RequirementTypeId reqTypeId = new RequirementTypeId(reqDef.getRequirementType());
770 // add all referenced capability types
771 CapabilityDefinitions capDefsContainer = nodeType.getCapabilityDefinitions();
772 if (capDefsContainer != null) {
773 List<TCapabilityDefinition> capDefs = capDefsContainer.getCapabilityDefinition();
774 for (TCapabilityDefinition capDef : capDefs) {
775 CapabilityTypeId capTypeId = new CapabilityTypeId(capDef.getCapabilityType());
780 this.addVisualAppearanceToCSAR(id);
785 private void addVisualAppearanceToCSAR(TopologyGraphElementEntityTypeId id) {
786 VisualAppearanceId visId = new VisualAppearanceId(id);
787 if (Repository.INSTANCE.exists(visId)) {
788 // we do NOT check for the id, but simply check for bigIcon.png (only exists in NodeType) and smallIcon.png (exists in NodeType and RelationshipType)
790 RepositoryFileReference ref = new RepositoryFileReference(visId, Filename.FILENAME_BIG_ICON);
791 if (Repository.INSTANCE.exists(ref)) {
792 this.referencesToPathInCSARMap.put(ref, BackendUtils.getPathInsideRepo(ref));
795 ref = new RepositoryFileReference(visId, Filename.FILENAME_SMALL_ICON);
796 if (Repository.INSTANCE.exists(ref)) {
797 this.referencesToPathInCSARMap.put(ref, BackendUtils.getPathInsideRepo(ref));