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
10 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 * SPDX-License-Identifier: Apache-2.0
19 * ============LICENSE_END=========================================================
22 package org.onap.policy.clamp.acm.runtime.instantiation;
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;
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;
72 * This class is dedicated to the Instantiation of Commissioned automation composition.
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 = "-";
86 private static final Gson GSON = new Gson();
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 ";
95 * Creates Instance Properties and automation composition.
97 * @param serviceTemplate the service template
98 * @return the result of the instantiation operation
99 * @throws PfModelException on creation errors
101 public InstancePropertiesResponse createInstanceProperties(ToscaServiceTemplate serviceTemplate)
102 throws PfModelException {
104 String instanceName = serviceTemplate.getName();
105 AutomationComposition automationComposition = new AutomationComposition();
106 Map<UUID, AutomationCompositionElement> automationCompositionElements = new HashMap<>();
108 ToscaServiceTemplate toscaServiceTemplate = commissioningProvider.getAllToscaServiceTemplate().get(0);
110 Map<String, ToscaNodeTemplate> persistedNodeTemplateMap =
111 toscaServiceTemplate.getToscaTopologyTemplate().getNodeTemplates();
113 Map<String, ToscaNodeTemplate> nodeTemplates = deepCloneNodeTemplate(serviceTemplate);
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());
128 crateNewAutomationCompositionInstance(instanceName, automationComposition, automationCompositionElements,
129 template, newNodeTemplate);
131 persistedNodeTemplateMap.put(name, newNodeTemplate);
134 AutomationCompositions automationCompositions = new AutomationCompositions();
136 serviceTemplate.getToscaTopologyTemplate().getNodeTemplates().putAll(persistedNodeTemplateMap);
138 automationComposition.setElements(automationCompositionElements);
139 automationCompositions.getAutomationCompositionList().add(automationComposition);
141 return saveInstancePropertiesAndAutomationComposition(serviceTemplate, automationCompositions);
145 * Updates Instance Properties and Automation Composition Instance.
147 * @param name the name of the automation composition to update
148 * @param version the version of the automation composition to update
149 * @param serviceTemplate tosca service template body
150 * @return InstancePropertiesResponse response from updating instance properties
151 * @throws PfModelException exception if incorrect instance name
153 public InstancePropertiesResponse updatesInstanceProperties(
154 String name, String version, ToscaServiceTemplate serviceTemplate) throws PfModelException {
156 if (name.length() < 3) {
157 throw new PfModelException(Status.BAD_REQUEST, "Instance Name cannot be empty or less than 3 characters!");
160 Map<String, ToscaNodeTemplate> nodeTemplates = deepCloneNodeTemplate(serviceTemplate);
161 Map<String, ToscaNodeTemplate> updatedNodeTemplates = new HashMap<>();
163 String instanceName = serviceTemplate.getName();
165 nodeTemplates.forEach((key, template) -> {
166 ToscaNodeTemplate toscaNodeTemplate = new ToscaNodeTemplate();
168 String updatedName = updateInstanceNameDescription(instanceName, name, key);
169 String updatedDescription = updateInstanceNameDescription(
170 instanceName, name, template.getDescription());
172 toscaNodeTemplate.setName(updatedName);
173 toscaNodeTemplate.setDescription(updatedDescription);
174 toscaNodeTemplate.setCapabilities(template.getCapabilities());
175 toscaNodeTemplate.setRequirements(template.getRequirements());
176 toscaNodeTemplate.setMetadata(template.getMetadata());
177 toscaNodeTemplate.setProperties(template.getProperties());
178 toscaNodeTemplate.setDerivedFrom(template.getDerivedFrom());
179 toscaNodeTemplate.setVersion(template.getVersion());
180 toscaNodeTemplate.setType(template.getType());
181 toscaNodeTemplate.setTypeVersion(template.getTypeVersion());
183 String updatedKey = updateInstanceNameDescription(instanceName, name, key);
185 updatedNodeTemplates.put(updatedKey, toscaNodeTemplate);
188 serviceTemplate.getToscaTopologyTemplate().getNodeTemplates().clear();
189 serviceTemplate.getToscaTopologyTemplate().getNodeTemplates().putAll(updatedNodeTemplates);
191 AutomationCompositions automationCompositions = updateAutomationComposition(
194 deleteInstanceProperties(name, version);
196 return saveInstancePropertiesAndAutomationComposition(serviceTemplate, automationCompositions);
200 * Deletes Instance Properties.
202 * @param name the name of the automation composition to delete
203 * @param version the version of the automation composition to delete
204 * @return the result of the deletion
205 * @throws PfModelException on deletion errors
207 public InstantiationResponse deleteInstanceProperties(String name, String version) throws PfModelException {
209 String instanceName = getInstancePropertyName(name, version);
211 Map<String, ToscaNodeTemplate> filteredToscaNodeTemplateMap = new HashMap<>();
213 ToscaServiceTemplate toscaServiceTemplate = commissioningProvider.getAllToscaServiceTemplate().get(0);
215 toscaServiceTemplate.getToscaTopologyTemplate().getNodeTemplates().forEach((key, nodeTemplate) -> {
216 if (!nodeTemplate.getName().contains(instanceName)) {
217 filteredToscaNodeTemplateMap.put(key, nodeTemplate);
221 List<ToscaNodeTemplate> filteredToscaNodeTemplateList =
222 toscaServiceTemplate.getToscaTopologyTemplate().getNodeTemplates().values().stream()
223 .filter(nodeTemplate -> nodeTemplate.getName().contains(instanceName)).collect(Collectors.toList());
225 InstantiationResponse response = this.deleteAutomationComposition(name, version);
227 automationCompositionProvider.deleteInstanceProperties(filteredToscaNodeTemplateMap,
228 filteredToscaNodeTemplateList);
234 * Create automation compositions.
236 * @param automationCompositions the automation composition
237 * @return the result of the instantiation operation
238 * @throws PfModelException on creation errors
240 public InstantiationResponse createAutomationCompositions(AutomationCompositions automationCompositions)
241 throws PfModelException {
242 for (AutomationComposition automationComposition : automationCompositions.getAutomationCompositionList()) {
243 var checkAutomationCompositionOpt =
244 automationCompositionProvider.findAutomationComposition(automationComposition.getKey().asIdentifier());
245 if (checkAutomationCompositionOpt.isPresent()) {
246 throw new PfModelException(Response.Status.BAD_REQUEST,
247 automationComposition.getKey().asIdentifier() + " already defined");
250 BeanValidationResult validationResult = validateAutomationCompositions(automationCompositions);
251 if (!validationResult.isValid()) {
252 throw new PfModelException(Response.Status.BAD_REQUEST, validationResult.getResult());
254 automationCompositionProvider.saveAutomationCompositions(automationCompositions.getAutomationCompositionList());
256 var response = new InstantiationResponse();
257 response.setAffectedAutomationCompositions(automationCompositions.getAutomationCompositionList().stream()
258 .map(ac -> ac.getKey().asIdentifier()).collect(Collectors.toList()));
264 * Update automation compositions.
266 * @param automationCompositions the automation composition
267 * @return the result of the instantiation operation
268 * @throws PfModelException on update errors
270 public InstantiationResponse updateAutomationCompositions(AutomationCompositions automationCompositions)
271 throws PfModelException {
272 BeanValidationResult validationResult = validateAutomationCompositions(automationCompositions);
273 if (!validationResult.isValid()) {
274 throw new PfModelException(Response.Status.BAD_REQUEST, validationResult.getResult());
276 automationCompositionProvider.saveAutomationCompositions(automationCompositions.getAutomationCompositionList());
278 var response = new InstantiationResponse();
279 response.setAffectedAutomationCompositions(automationCompositions.getAutomationCompositionList().stream()
280 .map(ac -> ac.getKey().asIdentifier()).collect(Collectors.toList()));
286 * Validate AutomationCompositions.
288 * @param automationCompositions AutomationCompositions to validate
289 * @return the result of validation
290 * @throws PfModelException if automationCompositions is not valid
292 private BeanValidationResult validateAutomationCompositions(AutomationCompositions automationCompositions)
293 throws PfModelException {
295 var result = new BeanValidationResult("AutomationCompositions", automationCompositions);
297 for (AutomationComposition automationComposition : automationCompositions.getAutomationCompositionList()) {
298 var subResult = new BeanValidationResult(ENTRY + automationComposition.getDefinition().getName(),
299 automationComposition);
301 List<ToscaNodeTemplate> toscaNodeTemplates = commissioningProvider.getAutomationCompositionDefinitions(
302 automationComposition.getDefinition().getName(), automationComposition.getDefinition().getVersion());
304 if (toscaNodeTemplates.isEmpty()) {
306 new ObjectValidationResult("AutomationComposition", automationComposition.getDefinition().getName(),
307 ValidationStatus.INVALID, "Commissioned automation composition definition not found"));
308 } else if (toscaNodeTemplates.size() > 1) {
310 new ObjectValidationResult("AutomationComposition", automationComposition.getDefinition().getName(),
311 ValidationStatus.INVALID, "Commissioned automation composition definition not valid"));
314 List<ToscaNodeTemplate> acElementDefinitions =
315 commissioningProvider.getAutomationCompositionElementDefinitions(toscaNodeTemplates.get(0));
318 Map<String, ToscaConceptIdentifier> definitions = acElementDefinitions
320 .map(nodeTemplate -> nodeTemplate.getKey().asIdentifier())
321 .collect(Collectors.toMap(ToscaConceptIdentifier::getName, UnaryOperator.identity()));
324 for (AutomationCompositionElement element : automationComposition.getElements().values()) {
325 subResult.addResult(validateDefinition(definitions, element.getDefinition()));
328 result.addResult(subResult);
334 * Validate ToscaConceptIdentifier, checking if exist in ToscaConceptIdentifiers map.
336 * @param definitions map of all ToscaConceptIdentifiers
337 * @param definition ToscaConceptIdentifier to validate
338 * @return the validation result
340 private ValidationResult validateDefinition(Map<String, ToscaConceptIdentifier> definitions,
341 ToscaConceptIdentifier definition) {
342 var result = new BeanValidationResult(ENTRY + definition.getName(), definition);
343 ToscaConceptIdentifier identifier = definitions.get(definition.getName());
344 if (identifier == null) {
345 result.setResult(ValidationStatus.INVALID, "Not found");
346 } else if (!identifier.equals(definition)) {
347 result.setResult(ValidationStatus.INVALID, "Version not matching");
349 return (result.isClean() ? null : result);
353 * Delete the automation composition with the given name and version.
355 * @param name the name of the automation composition to delete
356 * @param version the version of the automation composition to delete
357 * @return the result of the deletion
358 * @throws PfModelException on deletion errors
360 public InstantiationResponse deleteAutomationComposition(String name, String version) throws PfModelException {
361 var automationCompositionOpt = automationCompositionProvider.findAutomationComposition(name, version);
362 if (automationCompositionOpt.isEmpty()) {
363 throw new PfModelException(Response.Status.NOT_FOUND, "Automation composition not found");
365 var automationComposition = automationCompositionOpt.get();
366 if (!AutomationCompositionState.UNINITIALISED.equals(automationComposition.getState())) {
367 throw new PfModelException(Response.Status.BAD_REQUEST,
368 "Automation composition state is still " + automationComposition.getState());
370 var response = new InstantiationResponse();
371 response.setAffectedAutomationCompositions(
372 List.of(automationCompositionProvider.deleteAutomationComposition(name, version).getKey().asIdentifier()));
377 * Get the requested automation compositions.
379 * @param name the name of the automation composition to get, null for all automation compositions
380 * @param version the version of the automation composition to get, null for all automation compositions
381 * @return the automation compositions
382 * @throws PfModelException on errors getting automation compositions
384 @Transactional(readOnly = true)
385 public AutomationCompositions getAutomationCompositions(String name, String version) throws PfModelException {
386 var automationCompositions = new AutomationCompositions();
387 automationCompositions
388 .setAutomationCompositionList(automationCompositionProvider.getAutomationCompositions(name, version));
390 return automationCompositions;
394 * Issue a command to automation compositions, setting their ordered state.
396 * @param command the command to issue to automation compositions
397 * @return the result of the initiation command
398 * @throws PfModelException on errors setting the ordered state on the automation compositions
399 * @throws AutomationCompositionException on ordered state invalid
401 public InstantiationResponse issueAutomationCompositionCommand(InstantiationCommand command)
402 throws AutomationCompositionException, PfModelException {
404 if (command.getOrderedState() == null) {
405 throw new AutomationCompositionException(Status.BAD_REQUEST,
406 "ordered state invalid or not specified on command");
409 var participants = participantProvider.getParticipants();
410 if (participants.isEmpty()) {
411 throw new AutomationCompositionException(Status.BAD_REQUEST, "No participants registered");
413 var validationResult = new BeanValidationResult("InstantiationCommand", command);
414 List<AutomationComposition> automationCompositions =
415 new ArrayList<>(command.getAutomationCompositionIdentifierList().size());
416 for (ToscaConceptIdentifier id : command.getAutomationCompositionIdentifierList()) {
417 var automationCompositionOpt = automationCompositionProvider.findAutomationComposition(id);
418 if (automationCompositionOpt.isEmpty()) {
419 validationResult.addResult("ToscaConceptIdentifier", id, ValidationStatus.INVALID,
420 "AutomationComposition with id " + id + " not found");
422 var automationComposition = automationCompositionOpt.get();
423 automationComposition.setCascadedOrderedState(command.getOrderedState());
424 automationCompositions.add(automationComposition);
427 if (validationResult.isValid()) {
428 validationResult = validateIssueAutomationCompositions(automationCompositions, participants);
430 if (!validationResult.isValid()) {
431 throw new PfModelException(Response.Status.BAD_REQUEST, validationResult.getResult());
433 automationCompositionProvider.saveAutomationCompositions(automationCompositions);
435 supervisionHandler.triggerAutomationCompositionSupervision(command.getAutomationCompositionIdentifierList());
436 var response = new InstantiationResponse();
437 response.setAffectedAutomationCompositions(command.getAutomationCompositionIdentifierList());
442 private BeanValidationResult validateIssueAutomationCompositions(List<AutomationComposition> automationCompositions,
443 List<Participant> participants) {
444 var result = new BeanValidationResult("AutomationCompositions", automationCompositions);
446 Map<ToscaConceptIdentifier, Participant> participantMap = participants.stream()
447 .collect(Collectors.toMap(participant -> participant.getKey().asIdentifier(), Function.identity()));
449 for (AutomationComposition automationComposition : automationCompositions) {
451 for (var element : automationComposition.getElements().values()) {
453 var subResult = new BeanValidationResult(ENTRY + element.getDefinition().getName(), element);
454 Participant p = participantMap.get(element.getParticipantId());
456 subResult.addResult(new ObjectValidationResult(AUTOMATION_COMPOSITION_NODE_ELEMENT_TYPE,
457 element.getDefinition().getName(), ValidationStatus.INVALID,
458 "Participant with ID " + element.getParticipantId() + " is not registered"));
459 } else if (!p.getParticipantType().equals(element.getParticipantType())) {
460 subResult.addResult(new ObjectValidationResult(AUTOMATION_COMPOSITION_NODE_ELEMENT_TYPE,
461 element.getDefinition().getName(), ValidationStatus.INVALID,
462 "Participant with ID " + element.getParticipantType() + " - " + element.getParticipantId()
463 + " is not registered"));
465 result.addResult(subResult);
474 * Gets a list of automation compositions with it's ordered state.
476 * @param name the name of the automation composition to get, null for all automation compositions
477 * @param version the version of the automation composition to get, null for all automation compositions
478 * @return a list of Instantiation Command
479 * @throws PfModelException on errors getting automation compositions
481 @Transactional(readOnly = true)
482 public AutomationCompositionOrderStateResponse getInstantiationOrderState(String name, String version)
483 throws PfModelException {
485 List<AutomationComposition> automationCompositions =
486 automationCompositionProvider.getAutomationCompositions(name, version);
488 var response = new AutomationCompositionOrderStateResponse();
490 automationCompositions.forEach(automationComposition -> {
491 var genericNameVersion = new GenericNameVersion();
492 genericNameVersion.setName(automationComposition.getName());
493 genericNameVersion.setVersion(automationComposition.getVersion());
494 response.getAutomationCompositionIdentifierList().add(genericNameVersion);
501 * Saves Instance Properties and automation composition.
502 * Gets a list of automation compositions which are primed or de-primed.
504 * @param name the name of the automation composition to get, null for all automation compositions
505 * @param version the version of the automation composition to get, null for all automation compositions
506 * @return a list of Instantiation Command
507 * @throws PfModelException on errors getting automation compositions
509 @Transactional(readOnly = true)
510 public AutomationCompositionPrimedResponse getAutomationCompositionPriming(String name, String version)
511 throws PfModelException {
513 List<AutomationComposition> automationCompositions =
514 automationCompositionProvider.getAutomationCompositions(name, version);
516 var response = new AutomationCompositionPrimedResponse();
518 automationCompositions.forEach(automationComposition -> {
519 var primed = new AutomationCompositionPrimed();
520 primed.setName(automationComposition.getName());
521 primed.setVersion(automationComposition.getVersion());
522 primed.setPrimed(automationComposition.getPrimed());
523 response.getPrimedAutomationCompositionsList().add(primed);
530 * Creates instance element name.
532 * @param serviceTemplate the service template
533 * @param automationCompositions a list of automation compositions
534 * @return the result of the instance properties and instantiation operation
535 * @throws PfModelException on creation errors
537 private InstancePropertiesResponse saveInstancePropertiesAndAutomationComposition(
538 ToscaServiceTemplate serviceTemplate, AutomationCompositions automationCompositions) throws PfModelException {
540 for (var automationComposition : automationCompositions.getAutomationCompositionList()) {
541 var checkAutomationCompositionOpt =
542 automationCompositionProvider.findAutomationComposition(automationComposition.getKey().asIdentifier());
543 if (checkAutomationCompositionOpt.isPresent()) {
544 throw new PfModelException(Response.Status.BAD_REQUEST, "Automation composition with id "
545 + automationComposition.getKey().asIdentifier() + " already defined");
548 Map<String, ToscaNodeTemplate> toscaSavedNodeTemplate =
549 automationCompositionProvider.saveInstanceProperties(serviceTemplate);
550 automationCompositionProvider.saveAutomationCompositions(automationCompositions.getAutomationCompositionList());
551 List<ToscaConceptIdentifier> affectedAutomationCompositions = automationCompositions
552 .getAutomationCompositionList().stream().map(ac -> ac.getKey().asIdentifier()).collect(Collectors.toList());
554 List<ToscaConceptIdentifier> toscaAffectedProperties = toscaSavedNodeTemplate.values().stream()
555 .map(template -> template.getKey().asIdentifier()).collect(Collectors.toList());
557 var response = new InstancePropertiesResponse();
558 response.setAffectedInstanceProperties(Stream.of(affectedAutomationCompositions, toscaAffectedProperties)
559 .flatMap(Collection::stream).collect(Collectors.toList()));
565 * Crates a new automation composition instance.
567 * @param instanceName automation composition Instance name
568 * @param automationComposition empty automation composition
569 * @param automationCompositionElements new automation composition Element map
570 * @param template original Cloned Tosca Node Template
571 * @param newNodeTemplate new Tosca Node Template
573 private void crateNewAutomationCompositionInstance(String instanceName, AutomationComposition automationComposition,
574 Map<UUID, AutomationCompositionElement> automationCompositionElements, ToscaNodeTemplate template,
575 ToscaNodeTemplate newNodeTemplate) {
576 if (template.getType().equals(AUTOMATION_COMPOSITION_NODE_TYPE)) {
577 automationComposition.setDefinition(getAutomationCompositionDefinition(newNodeTemplate));
580 if (template.getType().contains(AUTOMATION_COMPOSITION_NODE_ELEMENT_TYPE)) {
581 AutomationCompositionElement automationCompositionElement =
582 getAutomationCompositionElement(newNodeTemplate);
583 automationCompositionElements.put(automationCompositionElement.getId(), automationCompositionElement);
586 automationComposition.setName(instanceName);
587 automationComposition.setVersion(template.getVersion());
588 automationComposition.setDescription("Automation composition " + instanceName);
589 automationComposition.setState(AutomationCompositionState.UNINITIALISED);
590 automationComposition.setOrderedState(AutomationCompositionOrderedState.UNINITIALISED);
594 * Get's the instance property name of the automation composition.
596 * @param name the name of the automation composition to get, null for all automation compositions
597 * @param version the version of the automation composition to get, null for all automation compositions
598 * @return the instance name of the automation composition instance properties
599 * @throws PfModelException on errors getting automation compositions
601 private String getInstancePropertyName(String name, String version) throws PfModelException {
602 List<String> toscaDefinitionsNames =
603 automationCompositionProvider.getAutomationCompositions(name, version).stream()
604 .map(AutomationComposition::getDefinition).map(ToscaNameVersion::getName).collect(Collectors.toList());
606 return toscaDefinitionsNames.stream().reduce("", (s1, s2) -> {
608 if (s2.contains(HYPHEN)) {
609 String[] instances = s2.split(HYPHEN);
611 return HYPHEN + instances[1];
619 * Retrieves automation composition Definition.
621 * @param template tosca node template
622 * @return automation composition definition
624 private ToscaConceptIdentifier getAutomationCompositionDefinition(ToscaNodeTemplate template) {
625 ToscaConceptIdentifier definition = new ToscaConceptIdentifier();
626 definition.setName(template.getName());
627 definition.setVersion(template.getVersion());
632 * Retrieves automation composition Element.
634 * @param template tosca node template
635 * @return a automation composition element
637 @SuppressWarnings("unchecked")
638 private AutomationCompositionElement getAutomationCompositionElement(ToscaNodeTemplate template) {
639 AutomationCompositionElement automationCompositionElement = new AutomationCompositionElement();
640 ToscaConceptIdentifier definition = new ToscaConceptIdentifier();
641 definition.setName(template.getName());
642 definition.setVersion(template.getVersion());
643 automationCompositionElement.setDefinition(definition);
644 LinkedTreeMap<String, Object> participantId =
645 (LinkedTreeMap<String, Object>) template.getProperties().get(PARTICIPANT_ID_PROPERTY_KEY);
646 if (participantId != null) {
647 ToscaConceptIdentifier participantIdProperty = new ToscaConceptIdentifier();
648 participantIdProperty.setName(String.valueOf(participantId.get(AC_ELEMENT_NAME)));
649 participantIdProperty.setVersion(String.valueOf(participantId.get(AC_ELEMENT_VERSION)));
650 automationCompositionElement.setParticipantId(participantIdProperty);
652 LinkedTreeMap<String, Object> participantType =
653 (LinkedTreeMap<String, Object>) template.getProperties().get(PARTICIPANT_TYPE_PROPERTY_KEY);
654 if (participantType != null) {
655 ToscaConceptIdentifier participantTypeProperty = new ToscaConceptIdentifier();
656 participantTypeProperty.setName(String.valueOf(participantType.get(AC_ELEMENT_NAME)));
657 participantTypeProperty.setVersion(participantType.get(AC_ELEMENT_VERSION).toString());
658 automationCompositionElement.setParticipantType(participantTypeProperty);
660 return automationCompositionElement;
664 * Deep clones ToscaNodeTemplate.
666 * @param serviceTemplate ToscaServiceTemplate
667 * @return a cloned Hash Map of ToscaNodeTemplate
669 private Map<String, ToscaNodeTemplate> deepCloneNodeTemplate(ToscaServiceTemplate serviceTemplate) {
670 String jsonString = GSON.toJson(serviceTemplate.getToscaTopologyTemplate().getNodeTemplates());
671 Type type = new TypeToken<HashMap<String, ToscaNodeTemplate>>() {}.getType();
672 return GSON.fromJson(jsonString, type);
676 * Updates Automation composition instance name.
678 * @param oldInstanceName previous saved instance name
679 * @param newInstanceName new instance name to replace the previous one
680 * @return AutomationCompositions updated
681 * @throws PfModelException exception to compositions is not defined
683 private AutomationCompositions updateAutomationComposition(
684 String oldInstanceName, String newInstanceName) throws PfModelException {
686 List<AutomationComposition> filteredAcmList = automationCompositionProvider.getAutomationCompositions()
687 .stream().filter(acm -> acm.getName().contains(oldInstanceName)).collect(Collectors.toList());
689 if (filteredAcmList.isEmpty()) {
690 throw new PfModelException(Status.BAD_REQUEST, "Automation compositions not defined!");
693 AutomationComposition automationComposition = filteredAcmList.get(0);
695 automationComposition.getDefinition()
696 .setName(updateInstanceNameDescription(newInstanceName, oldInstanceName,
697 automationComposition.getDefinition().getName()));
699 automationComposition.setName(newInstanceName);
701 automationComposition.setDescription(
702 updateInstanceNameDescription(newInstanceName, oldInstanceName,
703 automationComposition.getDescription()));
705 automationComposition.getElements().forEach((uuid, automationCompositionElement) -> {
706 automationCompositionElement.getDefinition()
707 .setName(updateInstanceNameDescription(newInstanceName, oldInstanceName,
708 automationCompositionElement.getDefinition().getName()));
711 AutomationCompositions automationCompositions = new AutomationCompositions();
712 automationCompositions.getAutomationCompositionList().add(automationComposition);
714 return automationCompositions;
719 * Updates instance and description.
721 * @param newInstanceName new instance name to replace the previous one
722 * @param oldInstanceName previous saved instance name
723 * @param value to be updated
724 * @return String updated instance name or description
726 private String updateInstanceNameDescription(
727 String newInstanceName, String oldInstanceName, String value) {
728 String toBeReplaced = value.substring(value.indexOf(oldInstanceName));
730 String replace = value.replace(toBeReplaced, newInstanceName);