40d4c5a85031e4cb0407143aa43d9a72cbad056a
[policy/clamp.git] /
1 /*-
2  * ============LICENSE_START=======================================================
3  * Copyright (C) 2021 Nordix Foundation.
4  * Modifications Copyright (C) 2021 AT&T Intellectual Property. All rights reserved.
5  * ================================================================================
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *      http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  * SPDX-License-Identifier: Apache-2.0
19  * ============LICENSE_END=========================================================
20  */
21
22 package org.onap.policy.clamp.acm.runtime.instantiation;
23
24 import com.google.gson.Gson;
25 import com.google.gson.internal.LinkedTreeMap;
26 import com.google.gson.reflect.TypeToken;
27 import java.lang.reflect.Type;
28 import java.util.ArrayList;
29 import java.util.Collection;
30 import java.util.HashMap;
31 import java.util.List;
32 import java.util.Map;
33 import java.util.UUID;
34 import java.util.function.Function;
35 import java.util.function.UnaryOperator;
36 import java.util.stream.Collectors;
37 import java.util.stream.Stream;
38 import javax.ws.rs.core.Response;
39 import javax.ws.rs.core.Response.Status;
40 import lombok.AllArgsConstructor;
41 import org.onap.policy.clamp.acm.runtime.commissioning.CommissioningProvider;
42 import org.onap.policy.clamp.acm.runtime.supervision.SupervisionHandler;
43 import org.onap.policy.clamp.common.acm.exception.AutomationCompositionException;
44 import org.onap.policy.clamp.models.acm.concepts.AutomationComposition;
45 import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionElement;
46 import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionOrderedState;
47 import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionState;
48 import org.onap.policy.clamp.models.acm.concepts.AutomationCompositions;
49 import org.onap.policy.clamp.models.acm.concepts.Participant;
50 import org.onap.policy.clamp.models.acm.messages.rest.GenericNameVersion;
51 import org.onap.policy.clamp.models.acm.messages.rest.instantiation.AutomationCompositionOrderStateResponse;
52 import org.onap.policy.clamp.models.acm.messages.rest.instantiation.AutomationCompositionPrimed;
53 import org.onap.policy.clamp.models.acm.messages.rest.instantiation.AutomationCompositionPrimedResponse;
54 import org.onap.policy.clamp.models.acm.messages.rest.instantiation.InstancePropertiesResponse;
55 import org.onap.policy.clamp.models.acm.messages.rest.instantiation.InstantiationCommand;
56 import org.onap.policy.clamp.models.acm.messages.rest.instantiation.InstantiationResponse;
57 import org.onap.policy.clamp.models.acm.persistence.provider.AutomationCompositionProvider;
58 import org.onap.policy.clamp.models.acm.persistence.provider.ParticipantProvider;
59 import org.onap.policy.common.parameters.BeanValidationResult;
60 import org.onap.policy.common.parameters.ObjectValidationResult;
61 import org.onap.policy.common.parameters.ValidationResult;
62 import org.onap.policy.common.parameters.ValidationStatus;
63 import org.onap.policy.models.base.PfModelException;
64 import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
65 import org.onap.policy.models.tosca.authorative.concepts.ToscaNameVersion;
66 import org.onap.policy.models.tosca.authorative.concepts.ToscaNodeTemplate;
67 import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;
68 import org.springframework.stereotype.Service;
69 import org.springframework.transaction.annotation.Transactional;
70
71 /**
72  * This class is dedicated to the Instantiation of Commissioned automation composition.
73  */
74 @Service
75 @Transactional
76 @AllArgsConstructor
77 public class AutomationCompositionInstantiationProvider {
78     private static final String AUTOMATION_COMPOSITION_NODE_TYPE = "org.onap.policy.clamp.acm.AutomationComposition";
79     private static final String AUTOMATION_COMPOSITION_NODE_ELEMENT_TYPE = "AutomationCompositionElement";
80     private static final String PARTICIPANT_ID_PROPERTY_KEY = "participant_id";
81     private static final String PARTICIPANT_TYPE_PROPERTY_KEY = "participantType";
82     private static final String AC_ELEMENT_NAME = "name";
83     private static final String AC_ELEMENT_VERSION = "version";
84     private static final String HYPHEN = "-";
85
86     private static final Gson GSON = new Gson();
87
88     private final AutomationCompositionProvider automationCompositionProvider;
89     private final CommissioningProvider commissioningProvider;
90     private final SupervisionHandler supervisionHandler;
91     private final ParticipantProvider participantProvider;
92     private static final String ENTRY = "entry ";
93
94     /**
95      * Creates Instance Properties and automation composition.
96      *
97      * @param serviceTemplate the service template
98      * @return the result of the instantiation operation
99      * @throws PfModelException on creation errors
100      */
101     public InstancePropertiesResponse createInstanceProperties(ToscaServiceTemplate serviceTemplate)
102         throws PfModelException {
103
104         String instanceName = serviceTemplate.getName();
105         AutomationComposition automationComposition = new AutomationComposition();
106         Map<UUID, AutomationCompositionElement> automationCompositionElements = new HashMap<>();
107
108         ToscaServiceTemplate toscaServiceTemplate = commissioningProvider.getAllToscaServiceTemplate().get(0);
109
110         Map<String, ToscaNodeTemplate> persistedNodeTemplateMap =
111             toscaServiceTemplate.getToscaTopologyTemplate().getNodeTemplates();
112
113         Map<String, ToscaNodeTemplate> nodeTemplates = deepCloneNodeTemplate(serviceTemplate);
114
115         nodeTemplates.forEach((key, template) -> {
116             ToscaNodeTemplate newNodeTemplate = new ToscaNodeTemplate();
117             String name = key + "-" + instanceName;
118             String version = template.getVersion();
119             String description = template.getDescription() + " " + instanceName;
120             newNodeTemplate.setName(name);
121             newNodeTemplate.setVersion(version);
122             newNodeTemplate.setDescription(description);
123             newNodeTemplate.setProperties(new HashMap<>(template.getProperties()));
124             newNodeTemplate.setType(template.getType());
125             newNodeTemplate.setTypeVersion(template.getTypeVersion());
126             newNodeTemplate.setMetadata(template.getMetadata());
127
128             crateNewAutomationCompositionInstance(instanceName, automationComposition, automationCompositionElements,
129                 template, newNodeTemplate);
130
131             persistedNodeTemplateMap.put(name, newNodeTemplate);
132         });
133
134         AutomationCompositions automationCompositions = new AutomationCompositions();
135
136         serviceTemplate.getToscaTopologyTemplate().getNodeTemplates().putAll(persistedNodeTemplateMap);
137
138         automationComposition.setElements(automationCompositionElements);
139         automationCompositions.getAutomationCompositionList().add(automationComposition);
140
141         return saveInstancePropertiesAndAutomationComposition(serviceTemplate, automationCompositions);
142     }
143
144     /**
145      * Deletes Instance Properties.
146      *
147      * @param name the name of the automation composition to delete
148      * @param version the version of the automation composition to delete
149      * @return the result of the deletion
150      * @throws PfModelException on deletion errors
151      */
152     public InstantiationResponse deleteInstanceProperties(String name, String version) throws PfModelException {
153
154         String instanceName = getInstancePropertyName(name, version);
155
156         Map<String, ToscaNodeTemplate> filteredToscaNodeTemplateMap = new HashMap<>();
157
158         ToscaServiceTemplate toscaServiceTemplate = commissioningProvider.getAllToscaServiceTemplate().get(0);
159
160         toscaServiceTemplate.getToscaTopologyTemplate().getNodeTemplates().forEach((key, nodeTemplate) -> {
161             if (!nodeTemplate.getName().contains(instanceName)) {
162                 filteredToscaNodeTemplateMap.put(key, nodeTemplate);
163             }
164         });
165
166         List<ToscaNodeTemplate> filteredToscaNodeTemplateList =
167             toscaServiceTemplate.getToscaTopologyTemplate().getNodeTemplates().values().stream()
168                 .filter(nodeTemplate -> nodeTemplate.getName().contains(instanceName)).collect(Collectors.toList());
169
170         InstantiationResponse response = this.deleteAutomationComposition(name, version);
171
172         automationCompositionProvider.deleteInstanceProperties(filteredToscaNodeTemplateMap,
173             filteredToscaNodeTemplateList);
174
175         return response;
176     }
177
178     /**
179      * Create automation compositions.
180      *
181      * @param automationCompositions the automation composition
182      * @return the result of the instantiation operation
183      * @throws PfModelException on creation errors
184      */
185     public InstantiationResponse createAutomationCompositions(AutomationCompositions automationCompositions)
186         throws PfModelException {
187         for (AutomationComposition automationComposition : automationCompositions.getAutomationCompositionList()) {
188             var checkAutomationCompositionOpt =
189                 automationCompositionProvider.findAutomationComposition(automationComposition.getKey().asIdentifier());
190             if (checkAutomationCompositionOpt.isPresent()) {
191                 throw new PfModelException(Response.Status.BAD_REQUEST,
192                     automationComposition.getKey().asIdentifier() + " already defined");
193             }
194         }
195         BeanValidationResult validationResult = validateAutomationCompositions(automationCompositions);
196         if (!validationResult.isValid()) {
197             throw new PfModelException(Response.Status.BAD_REQUEST, validationResult.getResult());
198         }
199         automationCompositionProvider.saveAutomationCompositions(automationCompositions.getAutomationCompositionList());
200
201         var response = new InstantiationResponse();
202         response.setAffectedAutomationCompositions(automationCompositions.getAutomationCompositionList().stream()
203             .map(ac -> ac.getKey().asIdentifier()).collect(Collectors.toList()));
204
205         return response;
206     }
207
208     /**
209      * Update automation compositions.
210      *
211      * @param automationCompositions the automation composition
212      * @return the result of the instantiation operation
213      * @throws PfModelException on update errors
214      */
215     public InstantiationResponse updateAutomationCompositions(AutomationCompositions automationCompositions)
216         throws PfModelException {
217         BeanValidationResult validationResult = validateAutomationCompositions(automationCompositions);
218         if (!validationResult.isValid()) {
219             throw new PfModelException(Response.Status.BAD_REQUEST, validationResult.getResult());
220         }
221         automationCompositionProvider.saveAutomationCompositions(automationCompositions.getAutomationCompositionList());
222
223         var response = new InstantiationResponse();
224         response.setAffectedAutomationCompositions(automationCompositions.getAutomationCompositionList().stream()
225             .map(ac -> ac.getKey().asIdentifier()).collect(Collectors.toList()));
226
227         return response;
228     }
229
230     /**
231      * Validate AutomationCompositions.
232      *
233      * @param automationCompositions AutomationCompositions to validate
234      * @return the result of validation
235      * @throws PfModelException if automationCompositions is not valid
236      */
237     private BeanValidationResult validateAutomationCompositions(AutomationCompositions automationCompositions)
238         throws PfModelException {
239
240         var result = new BeanValidationResult("AutomationCompositions", automationCompositions);
241
242         for (AutomationComposition automationComposition : automationCompositions.getAutomationCompositionList()) {
243             var subResult = new BeanValidationResult(ENTRY + automationComposition.getDefinition().getName(),
244                 automationComposition);
245
246             List<ToscaNodeTemplate> toscaNodeTemplates = commissioningProvider.getAutomationCompositionDefinitions(
247                 automationComposition.getDefinition().getName(), automationComposition.getDefinition().getVersion());
248
249             if (toscaNodeTemplates.isEmpty()) {
250                 subResult.addResult(
251                     new ObjectValidationResult("AutomationComposition", automationComposition.getDefinition().getName(),
252                         ValidationStatus.INVALID, "Commissioned automation composition definition not found"));
253             } else if (toscaNodeTemplates.size() > 1) {
254                 subResult.addResult(
255                     new ObjectValidationResult("AutomationComposition", automationComposition.getDefinition().getName(),
256                         ValidationStatus.INVALID, "Commissioned automation composition definition not valid"));
257             } else {
258
259                 List<ToscaNodeTemplate> acElementDefinitions =
260                     commissioningProvider.getAutomationCompositionElementDefinitions(toscaNodeTemplates.get(0));
261
262                 // @formatter:off
263                 Map<String, ToscaConceptIdentifier> definitions = acElementDefinitions
264                         .stream()
265                         .map(nodeTemplate -> nodeTemplate.getKey().asIdentifier())
266                         .collect(Collectors.toMap(ToscaConceptIdentifier::getName, UnaryOperator.identity()));
267                 // @formatter:on
268
269                 for (AutomationCompositionElement element : automationComposition.getElements().values()) {
270                     subResult.addResult(validateDefinition(definitions, element.getDefinition()));
271                 }
272             }
273             result.addResult(subResult);
274         }
275         return result;
276     }
277
278     /**
279      * Validate ToscaConceptIdentifier, checking if exist in ToscaConceptIdentifiers map.
280      *
281      * @param definitions map of all ToscaConceptIdentifiers
282      * @param definition ToscaConceptIdentifier to validate
283      * @return the validation result
284      */
285     private ValidationResult validateDefinition(Map<String, ToscaConceptIdentifier> definitions,
286         ToscaConceptIdentifier definition) {
287         var result = new BeanValidationResult(ENTRY + definition.getName(), definition);
288         ToscaConceptIdentifier identifier = definitions.get(definition.getName());
289         if (identifier == null) {
290             result.setResult(ValidationStatus.INVALID, "Not found");
291         } else if (!identifier.equals(definition)) {
292             result.setResult(ValidationStatus.INVALID, "Version not matching");
293         }
294         return (result.isClean() ? null : result);
295     }
296
297     /**
298      * Delete the automation composition with the given name and version.
299      *
300      * @param name the name of the automation composition to delete
301      * @param version the version of the automation composition to delete
302      * @return the result of the deletion
303      * @throws PfModelException on deletion errors
304      */
305     public InstantiationResponse deleteAutomationComposition(String name, String version) throws PfModelException {
306         var automationCompositionOpt = automationCompositionProvider.findAutomationComposition(name, version);
307         if (automationCompositionOpt.isEmpty()) {
308             throw new PfModelException(Response.Status.NOT_FOUND, "Automation composition not found");
309         }
310         var automationComposition = automationCompositionOpt.get();
311         if (!AutomationCompositionState.UNINITIALISED.equals(automationComposition.getState())) {
312             throw new PfModelException(Response.Status.BAD_REQUEST,
313                 "Automation composition state is still " + automationComposition.getState());
314         }
315         var response = new InstantiationResponse();
316         response.setAffectedAutomationCompositions(
317             List.of(automationCompositionProvider.deleteAutomationComposition(name, version).getKey().asIdentifier()));
318         return response;
319     }
320
321     /**
322      * Get the requested automation compositions.
323      *
324      * @param name the name of the automation composition to get, null for all automation compositions
325      * @param version the version of the automation composition to get, null for all automation compositions
326      * @return the automation compositions
327      * @throws PfModelException on errors getting automation compositions
328      */
329     @Transactional(readOnly = true)
330     public AutomationCompositions getAutomationCompositions(String name, String version) throws PfModelException {
331         var automationCompositions = new AutomationCompositions();
332         automationCompositions
333             .setAutomationCompositionList(automationCompositionProvider.getAutomationCompositions(name, version));
334
335         return automationCompositions;
336     }
337
338     /**
339      * Issue a command to automation compositions, setting their ordered state.
340      *
341      * @param command the command to issue to automation compositions
342      * @return the result of the initiation command
343      * @throws PfModelException on errors setting the ordered state on the automation compositions
344      * @throws AutomationCompositionException on ordered state invalid
345      */
346     public InstantiationResponse issueAutomationCompositionCommand(InstantiationCommand command)
347         throws AutomationCompositionException, PfModelException {
348
349         if (command.getOrderedState() == null) {
350             throw new AutomationCompositionException(Status.BAD_REQUEST,
351                 "ordered state invalid or not specified on command");
352         }
353
354         var participants = participantProvider.getParticipants();
355         if (participants.isEmpty()) {
356             throw new AutomationCompositionException(Status.BAD_REQUEST, "No participants registered");
357         }
358         var validationResult = new BeanValidationResult("InstantiationCommand", command);
359         List<AutomationComposition> automationCompositions =
360             new ArrayList<>(command.getAutomationCompositionIdentifierList().size());
361         for (ToscaConceptIdentifier id : command.getAutomationCompositionIdentifierList()) {
362             var automationCompositionOpt = automationCompositionProvider.findAutomationComposition(id);
363             if (automationCompositionOpt.isEmpty()) {
364                 validationResult.addResult("ToscaConceptIdentifier", id, ValidationStatus.INVALID,
365                     "AutomationComposition with id " + id + " not found");
366             } else {
367                 var automationComposition = automationCompositionOpt.get();
368                 automationComposition.setCascadedOrderedState(command.getOrderedState());
369                 automationCompositions.add(automationComposition);
370             }
371         }
372         if (validationResult.isValid()) {
373             validationResult = validateIssueAutomationCompositions(automationCompositions, participants);
374         }
375         if (!validationResult.isValid()) {
376             throw new PfModelException(Response.Status.BAD_REQUEST, validationResult.getResult());
377         }
378         automationCompositionProvider.saveAutomationCompositions(automationCompositions);
379
380         supervisionHandler.triggerAutomationCompositionSupervision(command.getAutomationCompositionIdentifierList());
381         var response = new InstantiationResponse();
382         response.setAffectedAutomationCompositions(command.getAutomationCompositionIdentifierList());
383
384         return response;
385     }
386
387     private BeanValidationResult validateIssueAutomationCompositions(List<AutomationComposition> automationCompositions,
388         List<Participant> participants) {
389         var result = new BeanValidationResult("AutomationCompositions", automationCompositions);
390
391         Map<ToscaConceptIdentifier, Participant> participantMap = participants.stream()
392             .collect(Collectors.toMap(participant -> participant.getKey().asIdentifier(), Function.identity()));
393
394         for (AutomationComposition automationComposition : automationCompositions) {
395
396             for (var element : automationComposition.getElements().values()) {
397
398                 var subResult = new BeanValidationResult(ENTRY + element.getDefinition().getName(), element);
399                 Participant p = participantMap.get(element.getParticipantId());
400                 if (p == null) {
401                     subResult.addResult(new ObjectValidationResult(AUTOMATION_COMPOSITION_NODE_ELEMENT_TYPE,
402                         element.getDefinition().getName(), ValidationStatus.INVALID,
403                         "Participant with ID " + element.getParticipantId() + " is not registered"));
404                 } else if (!p.getParticipantType().equals(element.getParticipantType())) {
405                     subResult.addResult(new ObjectValidationResult(AUTOMATION_COMPOSITION_NODE_ELEMENT_TYPE,
406                         element.getDefinition().getName(), ValidationStatus.INVALID,
407                         "Participant with ID " + element.getParticipantType() + " - " + element.getParticipantId()
408                             + " is not registered"));
409                 }
410                 result.addResult(subResult);
411             }
412
413         }
414
415         return result;
416     }
417
418     /**
419      * Gets a list of automation compositions with it's ordered state.
420      *
421      * @param name the name of the automation composition to get, null for all automation compositions
422      * @param version the version of the automation composition to get, null for all automation compositions
423      * @return a list of Instantiation Command
424      * @throws PfModelException on errors getting automation compositions
425      */
426     @Transactional(readOnly = true)
427     public AutomationCompositionOrderStateResponse getInstantiationOrderState(String name, String version)
428         throws PfModelException {
429
430         List<AutomationComposition> automationCompositions =
431             automationCompositionProvider.getAutomationCompositions(name, version);
432
433         var response = new AutomationCompositionOrderStateResponse();
434
435         automationCompositions.forEach(automationComposition -> {
436             var genericNameVersion = new GenericNameVersion();
437             genericNameVersion.setName(automationComposition.getName());
438             genericNameVersion.setVersion(automationComposition.getVersion());
439             response.getAutomationCompositionIdentifierList().add(genericNameVersion);
440         });
441
442         return response;
443     }
444
445     /**
446      * Saves Instance Properties and automation composition.
447      * Gets a list of automation compositions which are primed or de-primed.
448      *
449      * @param name the name of the automation composition to get, null for all automation compositions
450      * @param version the version of the automation composition to get, null for all automation compositions
451      * @return a list of Instantiation Command
452      * @throws PfModelException on errors getting automation compositions
453      */
454     @Transactional(readOnly = true)
455     public AutomationCompositionPrimedResponse getAutomationCompositionPriming(String name, String version)
456         throws PfModelException {
457
458         List<AutomationComposition> automationCompositions =
459             automationCompositionProvider.getAutomationCompositions(name, version);
460
461         var response = new AutomationCompositionPrimedResponse();
462
463         automationCompositions.forEach(automationComposition -> {
464             var primed = new AutomationCompositionPrimed();
465             primed.setName(automationComposition.getName());
466             primed.setVersion(automationComposition.getVersion());
467             primed.setPrimed(automationComposition.getPrimed());
468             response.getPrimedAutomationCompositionsList().add(primed);
469         });
470
471         return response;
472     }
473
474     /**
475      * Creates instance element name.
476      *
477      * @param serviceTemplate the service template
478      * @param automationCompositions a list of automation compositions
479      * @return the result of the instance properties and instantiation operation
480      * @throws PfModelException on creation errors
481      */
482     private InstancePropertiesResponse saveInstancePropertiesAndAutomationComposition(
483         ToscaServiceTemplate serviceTemplate, AutomationCompositions automationCompositions) throws PfModelException {
484
485         for (var automationComposition : automationCompositions.getAutomationCompositionList()) {
486             var checkAutomationCompositionOpt =
487                 automationCompositionProvider.findAutomationComposition(automationComposition.getKey().asIdentifier());
488             if (checkAutomationCompositionOpt.isPresent()) {
489                 throw new PfModelException(Response.Status.BAD_REQUEST, "Automation composition with id "
490                     + automationComposition.getKey().asIdentifier() + " already defined");
491             }
492         }
493         Map<String, ToscaNodeTemplate> toscaSavedNodeTemplate =
494             automationCompositionProvider.saveInstanceProperties(serviceTemplate);
495         automationCompositionProvider.saveAutomationCompositions(automationCompositions.getAutomationCompositionList());
496         List<ToscaConceptIdentifier> affectedAutomationCompositions = automationCompositions
497             .getAutomationCompositionList().stream().map(ac -> ac.getKey().asIdentifier()).collect(Collectors.toList());
498
499         List<ToscaConceptIdentifier> toscaAffectedProperties = toscaSavedNodeTemplate.values().stream()
500             .map(template -> template.getKey().asIdentifier()).collect(Collectors.toList());
501
502         var response = new InstancePropertiesResponse();
503         response.setAffectedInstanceProperties(Stream.of(affectedAutomationCompositions, toscaAffectedProperties)
504             .flatMap(Collection::stream).collect(Collectors.toList()));
505
506         return response;
507     }
508
509     /**
510      * Crates a new automation composition instance.
511      *
512      * @param instanceName automation composition Instance name
513      * @param automationComposition empty automation composition
514      * @param automationCompositionElements new automation composition Element map
515      * @param template original Cloned Tosca Node Template
516      * @param newNodeTemplate new Tosca Node Template
517      */
518     private void crateNewAutomationCompositionInstance(String instanceName, AutomationComposition automationComposition,
519         Map<UUID, AutomationCompositionElement> automationCompositionElements, ToscaNodeTemplate template,
520         ToscaNodeTemplate newNodeTemplate) {
521         if (template.getType().equals(AUTOMATION_COMPOSITION_NODE_TYPE)) {
522             automationComposition.setDefinition(getAutomationCompositionDefinition(newNodeTemplate));
523         }
524
525         if (template.getType().contains(AUTOMATION_COMPOSITION_NODE_ELEMENT_TYPE)) {
526             AutomationCompositionElement automationCompositionElement =
527                 getAutomationCompositionElement(newNodeTemplate);
528             automationCompositionElements.put(automationCompositionElement.getId(), automationCompositionElement);
529         }
530
531         automationComposition.setName(instanceName);
532         automationComposition.setVersion(template.getVersion());
533         automationComposition.setDescription("Automation composition " + instanceName);
534         automationComposition.setState(AutomationCompositionState.UNINITIALISED);
535         automationComposition.setOrderedState(AutomationCompositionOrderedState.UNINITIALISED);
536     }
537
538     /**
539      * Get's the instance property name of the automation composition.
540      *
541      * @param name the name of the automation composition to get, null for all automation compositions
542      * @param version the version of the automation composition to get, null for all automation compositions
543      * @return the instance name of the automation composition instance properties
544      * @throws PfModelException on errors getting automation compositions
545      */
546     private String getInstancePropertyName(String name, String version) throws PfModelException {
547         List<String> toscaDefinitionsNames =
548             automationCompositionProvider.getAutomationCompositions(name, version).stream()
549                 .map(AutomationComposition::getDefinition).map(ToscaNameVersion::getName).collect(Collectors.toList());
550
551         return toscaDefinitionsNames.stream().reduce("", (s1, s2) -> {
552
553             if (s2.contains(HYPHEN)) {
554                 String[] instances = s2.split(HYPHEN);
555
556                 return HYPHEN + instances[1];
557             }
558
559             return s1;
560         });
561     }
562
563     /**
564      * Retrieves automation composition Definition.
565      *
566      * @param template tosca node template
567      * @return automation composition definition
568      */
569     private ToscaConceptIdentifier getAutomationCompositionDefinition(ToscaNodeTemplate template) {
570         ToscaConceptIdentifier definition = new ToscaConceptIdentifier();
571         definition.setName(template.getName());
572         definition.setVersion(template.getVersion());
573         return definition;
574     }
575
576     /**
577      * Retrieves automation composition Element.
578      *
579      * @param template tosca node template
580      * @return a automation composition element
581      */
582     @SuppressWarnings("unchecked")
583     private AutomationCompositionElement getAutomationCompositionElement(ToscaNodeTemplate template) {
584         AutomationCompositionElement automationCompositionElement = new AutomationCompositionElement();
585         ToscaConceptIdentifier definition = new ToscaConceptIdentifier();
586         definition.setName(template.getName());
587         definition.setVersion(template.getVersion());
588         automationCompositionElement.setDefinition(definition);
589         LinkedTreeMap<String, Object> participantId =
590             (LinkedTreeMap<String, Object>) template.getProperties().get(PARTICIPANT_ID_PROPERTY_KEY);
591         if (participantId != null) {
592             ToscaConceptIdentifier participantIdProperty = new ToscaConceptIdentifier();
593             participantIdProperty.setName(String.valueOf(participantId.get(AC_ELEMENT_NAME)));
594             participantIdProperty.setVersion(String.valueOf(participantId.get(AC_ELEMENT_VERSION)));
595             automationCompositionElement.setParticipantId(participantIdProperty);
596         }
597         LinkedTreeMap<String, Object> participantType =
598             (LinkedTreeMap<String, Object>) template.getProperties().get(PARTICIPANT_TYPE_PROPERTY_KEY);
599         if (participantType != null) {
600             ToscaConceptIdentifier participantTypeProperty = new ToscaConceptIdentifier();
601             participantTypeProperty.setName(String.valueOf(participantType.get(AC_ELEMENT_NAME)));
602             participantTypeProperty.setVersion(participantType.get(AC_ELEMENT_VERSION).toString());
603             automationCompositionElement.setParticipantType(participantTypeProperty);
604         }
605         return automationCompositionElement;
606     }
607
608     /**
609      * Deep clones ToscaNodeTemplate.
610      *
611      * @param serviceTemplate ToscaServiceTemplate
612      * @return a cloned Hash Map of ToscaNodeTemplate
613      */
614     private Map<String, ToscaNodeTemplate> deepCloneNodeTemplate(ToscaServiceTemplate serviceTemplate) {
615         String jsonString = GSON.toJson(serviceTemplate.getToscaTopologyTemplate().getNodeTemplates());
616         Type type = new TypeToken<HashMap<String, ToscaNodeTemplate>>() {}.getType();
617         return GSON.fromJson(jsonString, type);
618     }
619 }