5ec6158bdb51cd96ae0fcb108d2f532a1fad7ba5
[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.controlloop.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.Collections;
31 import java.util.HashMap;
32 import java.util.List;
33 import java.util.Map;
34 import java.util.UUID;
35 import java.util.function.Function;
36 import java.util.function.UnaryOperator;
37 import java.util.stream.Collectors;
38 import java.util.stream.Stream;
39 import javax.ws.rs.core.Response;
40 import javax.ws.rs.core.Response.Status;
41 import lombok.AllArgsConstructor;
42 import org.onap.policy.clamp.controlloop.common.exception.ControlLoopException;
43 import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoop;
44 import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoopElement;
45 import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoopOrderedState;
46 import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoopState;
47 import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoops;
48 import org.onap.policy.clamp.controlloop.models.controlloop.concepts.Participant;
49 import org.onap.policy.clamp.controlloop.models.controlloop.persistence.provider.ControlLoopProvider;
50 import org.onap.policy.clamp.controlloop.models.controlloop.persistence.provider.ParticipantProvider;
51 import org.onap.policy.clamp.controlloop.models.messages.rest.GenericNameVersion;
52 import org.onap.policy.clamp.controlloop.models.messages.rest.instantiation.ControlLoopOrderStateResponse;
53 import org.onap.policy.clamp.controlloop.models.messages.rest.instantiation.ControlLoopPrimed;
54 import org.onap.policy.clamp.controlloop.models.messages.rest.instantiation.ControlLoopPrimedResponse;
55 import org.onap.policy.clamp.controlloop.models.messages.rest.instantiation.InstancePropertiesResponse;
56 import org.onap.policy.clamp.controlloop.models.messages.rest.instantiation.InstantiationCommand;
57 import org.onap.policy.clamp.controlloop.models.messages.rest.instantiation.InstantiationResponse;
58 import org.onap.policy.clamp.controlloop.runtime.commissioning.CommissioningProvider;
59 import org.onap.policy.clamp.controlloop.runtime.supervision.SupervisionHandler;
60 import org.onap.policy.common.parameters.BeanValidationResult;
61 import org.onap.policy.common.parameters.ObjectValidationResult;
62 import org.onap.policy.common.parameters.ValidationResult;
63 import org.onap.policy.common.parameters.ValidationStatus;
64 import org.onap.policy.models.base.PfModelException;
65 import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
66 import org.onap.policy.models.tosca.authorative.concepts.ToscaNameVersion;
67 import org.onap.policy.models.tosca.authorative.concepts.ToscaNodeTemplate;
68 import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;
69 import org.springframework.stereotype.Component;
70
71 /**
72  * This class is dedicated to the Instantiation of Commissioned control loop.
73  */
74 @Component
75 @AllArgsConstructor
76 public class ControlLoopInstantiationProvider {
77     private static final String CONTROL_LOOP_NODE_TYPE = "org.onap.policy.clamp.controlloop.ControlLoop";
78     private static final String CONTROL_LOOP_NODE_ELEMENT_TYPE = "ControlLoopElement";
79     private static final String PARTICIPANT_ID_PROPERTY_KEY = "participant_id";
80     private static final String PARTICIPANT_TYPE_PROPERTY_KEY = "participantType";
81     private static final String CL_ELEMENT_NAME = "name";
82     private static final String CL_ELEMENT_VERSION = "version";
83     private static final String INSTANCE_TEXT = "_Instance";
84
85     private static final Gson GSON = new Gson();
86
87     private final ControlLoopProvider controlLoopProvider;
88     private final CommissioningProvider commissioningProvider;
89     private final SupervisionHandler supervisionHandler;
90     private final ParticipantProvider participantProvider;
91
92     private static final Object lockit = new Object();
93
94     /**
95      * Creates Instance Properties and Control Loop.
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 = generateSequentialInstanceName();
105         ControlLoop controlLoop = new ControlLoop();
106         Map<UUID, ControlLoopElement> controlLoopElements = new HashMap<>();
107
108         ToscaServiceTemplate toscaServiceTemplate = commissioningProvider.getToscaServiceTemplate(null, null);
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             crateNewControlLoopInstance(instanceName, controlLoop, controlLoopElements, template, newNodeTemplate);
129
130             persistedNodeTemplateMap.put(name, newNodeTemplate);
131         });
132
133         ControlLoops controlLoops = new ControlLoops();
134
135         serviceTemplate.getToscaTopologyTemplate().getNodeTemplates().putAll(persistedNodeTemplateMap);
136
137         controlLoop.setElements(controlLoopElements);
138         controlLoops.getControlLoopList().add(controlLoop);
139
140         return saveInstancePropertiesAndControlLoop(serviceTemplate, controlLoops);
141     }
142
143     /**
144      * Deletes Instance Properties.
145      *
146      * @param name the name of the control loop to delete
147      * @param version the version of the control loop to delete
148      * @return the result of the deletion
149      * @throws PfModelException on deletion errors
150      */
151     public InstantiationResponse deleteInstanceProperties(String name, String version) throws PfModelException {
152
153         String instanceName = getInstancePropertyName(name, version);
154
155         Map<String, ToscaNodeTemplate> filteredToscaNodeTemplateMap = new HashMap<>();
156
157         ToscaServiceTemplate toscaServiceTemplate = commissioningProvider.getToscaServiceTemplate(name, version);
158
159         toscaServiceTemplate.getToscaTopologyTemplate().getNodeTemplates().forEach((key, nodeTemplate) -> {
160             if (!nodeTemplate.getName().contains(instanceName)) {
161                 filteredToscaNodeTemplateMap.put(key, nodeTemplate);
162             }
163         });
164
165         List<ToscaNodeTemplate> filteredToscaNodeTemplateList = toscaServiceTemplate.getToscaTopologyTemplate()
166                 .getNodeTemplates().values().stream()
167                 .filter(nodeTemplate -> nodeTemplate.getName().contains(instanceName)).collect(Collectors.toList());
168
169         InstantiationResponse response = this.deleteControlLoop(name, version);
170
171         controlLoopProvider.deleteInstanceProperties(filteredToscaNodeTemplateMap, filteredToscaNodeTemplateList);
172
173         return response;
174     }
175
176     /**
177      * Create control loops.
178      *
179      * @param controlLoops the control loop
180      * @return the result of the instantiation operation
181      * @throws PfModelException on creation errors
182      */
183     public InstantiationResponse createControlLoops(ControlLoops controlLoops) throws PfModelException {
184
185         synchronized (lockit) {
186             for (ControlLoop controlLoop : controlLoops.getControlLoopList()) {
187                 var checkControlLoop = controlLoopProvider.getControlLoop(controlLoop.getKey().asIdentifier());
188                 if (checkControlLoop != null) {
189                     throw new PfModelException(Response.Status.BAD_REQUEST,
190                             controlLoop.getKey().asIdentifier() + " already defined");
191                 }
192             }
193             BeanValidationResult validationResult = validateControlLoops(controlLoops);
194             if (!validationResult.isValid()) {
195                 throw new PfModelException(Response.Status.BAD_REQUEST, validationResult.getResult());
196             }
197             controlLoopProvider.createControlLoops(controlLoops.getControlLoopList());
198         }
199
200         var response = new InstantiationResponse();
201         response.setAffectedControlLoops(controlLoops.getControlLoopList().stream()
202                 .map(cl -> cl.getKey().asIdentifier()).collect(Collectors.toList()));
203
204         return response;
205     }
206
207     /**
208      * Update control loops.
209      *
210      * @param controlLoops the control loop
211      * @return the result of the instantiation operation
212      * @throws PfModelException on update errors
213      */
214     public InstantiationResponse updateControlLoops(ControlLoops controlLoops) throws PfModelException {
215         synchronized (lockit) {
216             BeanValidationResult validationResult = validateControlLoops(controlLoops);
217             if (!validationResult.isValid()) {
218                 throw new PfModelException(Response.Status.BAD_REQUEST, validationResult.getResult());
219             }
220             controlLoopProvider.updateControlLoops(controlLoops.getControlLoopList());
221         }
222
223         var response = new InstantiationResponse();
224         response.setAffectedControlLoops(controlLoops.getControlLoopList().stream()
225                 .map(cl -> cl.getKey().asIdentifier()).collect(Collectors.toList()));
226
227         return response;
228     }
229
230     /**
231      * Validate ControlLoops.
232      *
233      * @param controlLoops ControlLoops to validate
234      * @return the result of validation
235      * @throws PfModelException if controlLoops is not valid
236      */
237     private BeanValidationResult validateControlLoops(ControlLoops controlLoops) throws PfModelException {
238
239         var result = new BeanValidationResult("ControlLoops", controlLoops);
240
241         for (ControlLoop controlLoop : controlLoops.getControlLoopList()) {
242             var subResult = new BeanValidationResult("entry " + controlLoop.getDefinition().getName(), controlLoop);
243
244             List<ToscaNodeTemplate> toscaNodeTemplates = commissioningProvider.getControlLoopDefinitions(
245                     controlLoop.getDefinition().getName(), controlLoop.getDefinition().getVersion());
246
247             if (toscaNodeTemplates.isEmpty()) {
248                 subResult.addResult(new ObjectValidationResult("ControlLoop", controlLoop.getDefinition().getName(),
249                         ValidationStatus.INVALID, "Commissioned control loop definition not FOUND"));
250             } else if (toscaNodeTemplates.size() > 1) {
251                 subResult.addResult(new ObjectValidationResult("ControlLoop", controlLoop.getDefinition().getName(),
252                         ValidationStatus.INVALID, "Commissioned control loop definition not VALID"));
253             } else {
254
255                 List<ToscaNodeTemplate> clElementDefinitions =
256                         commissioningProvider.getControlLoopElementDefinitions(toscaNodeTemplates.get(0));
257
258                 // @formatter:off
259                 Map<String, ToscaConceptIdentifier> definitions = clElementDefinitions
260                         .stream()
261                         .map(nodeTemplate -> nodeTemplate.getKey().asIdentifier())
262                         .collect(Collectors.toMap(ToscaConceptIdentifier::getName, UnaryOperator.identity()));
263                 // @formatter:on
264
265                 for (ControlLoopElement element : controlLoop.getElements().values()) {
266                     subResult.addResult(validateDefinition(definitions, element.getDefinition()));
267                 }
268             }
269             result.addResult(subResult);
270         }
271         return result;
272     }
273
274     /**
275      * Validate ToscaConceptIdentifier, checking if exist in ToscaConceptIdentifiers map.
276      *
277      * @param definitions map of all ToscaConceptIdentifiers
278      * @param definition ToscaConceptIdentifier to validate
279      * @return the validation result
280      */
281     private ValidationResult validateDefinition(Map<String, ToscaConceptIdentifier> definitions,
282             ToscaConceptIdentifier definition) {
283         var result = new BeanValidationResult("entry " + definition.getName(), definition);
284         ToscaConceptIdentifier identifier = definitions.get(definition.getName());
285         if (identifier == null) {
286             result.setResult(ValidationStatus.INVALID, "Not FOUND");
287         } else if (!identifier.equals(definition)) {
288             result.setResult(ValidationStatus.INVALID, "Version not matching");
289         }
290         return (result.isClean() ? null : result);
291     }
292
293     /**
294      * Delete the control loop with the given name and version.
295      *
296      * @param name the name of the control loop to delete
297      * @param version the version of the control loop to delete
298      * @return the result of the deletion
299      * @throws PfModelException on deletion errors
300      */
301     public InstantiationResponse deleteControlLoop(String name, String version) throws PfModelException {
302         var response = new InstantiationResponse();
303         synchronized (lockit) {
304             List<ControlLoop> controlLoops = controlLoopProvider.getControlLoops(name, version);
305             if (controlLoops.isEmpty()) {
306                 throw new PfModelException(Response.Status.NOT_FOUND, "Control Loop not found");
307             }
308             for (ControlLoop controlLoop : controlLoops) {
309                 if (!ControlLoopState.UNINITIALISED.equals(controlLoop.getState())) {
310                     throw new PfModelException(Response.Status.BAD_REQUEST,
311                             "Control Loop State is still " + controlLoop.getState());
312                 }
313             }
314
315             response.setAffectedControlLoops(Collections
316                     .singletonList(controlLoopProvider.deleteControlLoop(name, version).getKey().asIdentifier()));
317         }
318         return response;
319     }
320
321     /**
322      * Get the requested control loops.
323      *
324      * @param name the name of the control loop to get, null for all control loops
325      * @param version the version of the control loop to get, null for all control loops
326      * @return the control loops
327      * @throws PfModelException on errors getting control loops
328      */
329     public ControlLoops getControlLoops(String name, String version) throws PfModelException {
330         var controlLoops = new ControlLoops();
331         controlLoops.setControlLoopList(controlLoopProvider.getControlLoops(name, version));
332
333         return controlLoops;
334     }
335
336     /**
337      * Issue a command to control loops, setting their ordered state.
338      *
339      * @param command the command to issue to control loops
340      * @return the result of the initiation command
341      * @throws PfModelException on errors setting the ordered state on the control loops
342      * @throws ControlLoopException on ordered state invalid
343      */
344     public InstantiationResponse issueControlLoopCommand(InstantiationCommand command)
345             throws ControlLoopException, PfModelException {
346
347         if (command.getOrderedState() == null) {
348             throw new ControlLoopException(Status.BAD_REQUEST, "ordered state invalid or not specified on command");
349         }
350
351         synchronized (lockit) {
352             var participants = participantProvider.getParticipants(null, null);
353             if (participants.isEmpty()) {
354                 throw new ControlLoopException(Status.BAD_REQUEST, "No participants registered");
355             }
356             List<ControlLoop> controlLoops = new ArrayList<>(command.getControlLoopIdentifierList().size());
357             for (ToscaConceptIdentifier id : command.getControlLoopIdentifierList()) {
358                 var controlLoop = controlLoopProvider.getControlLoop(id);
359                 controlLoop.setCascadedOrderedState(command.getOrderedState());
360                 controlLoops.add(controlLoop);
361             }
362             BeanValidationResult validationResult = validateIssueControlLoops(controlLoops, participants);
363             if (!validationResult.isValid()) {
364                 throw new PfModelException(Response.Status.BAD_REQUEST, validationResult.getResult());
365             }
366             controlLoopProvider.updateControlLoops(controlLoops);
367         }
368
369         supervisionHandler.triggerControlLoopSupervision(command.getControlLoopIdentifierList());
370         var response = new InstantiationResponse();
371         response.setAffectedControlLoops(command.getControlLoopIdentifierList());
372
373         return response;
374     }
375
376     private BeanValidationResult validateIssueControlLoops(List<ControlLoop> controlLoops,
377             List<Participant> participants) {
378         var result = new BeanValidationResult("ControlLoops", controlLoops);
379
380         Map<ToscaConceptIdentifier, Participant> participantMap = participants.stream()
381                 .collect(Collectors.toMap(participant -> participant.getKey().asIdentifier(), Function.identity()));
382
383         for (ControlLoop controlLoop : controlLoops) {
384
385             for (var element : controlLoop.getElements().values()) {
386                 var subResult = new BeanValidationResult("entry " + element.getDefinition().getName(), element);
387
388                 Participant p = participantMap.get(element.getParticipantId());
389                 if (p == null) {
390                     subResult.addResult(new ObjectValidationResult(CONTROL_LOOP_NODE_ELEMENT_TYPE,
391                             element.getDefinition().getName(), ValidationStatus.INVALID,
392                             "Participant with ID " + element.getParticipantId() + " is not registered"));
393                 } else if (!p.getParticipantType().equals(element.getParticipantType())) {
394                     subResult.addResult(new ObjectValidationResult(CONTROL_LOOP_NODE_ELEMENT_TYPE,
395                             element.getDefinition().getName(), ValidationStatus.INVALID,
396                             "Participant with ID " + element.getParticipantType() + " - " + element.getParticipantId()
397                                     + " is not registered"));
398                 }
399                 result.addResult(subResult);
400             }
401
402         }
403
404         return result;
405     }
406
407     /**
408      * Gets a list of control loops with it's ordered state.
409      *
410      * @param name the name of the control loop to get, null for all control loops
411      * @param version the version of the control loop to get, null for all control loops
412      * @return a list of Instantiation Command
413      * @throws PfModelException on errors getting control loops
414      */
415     public ControlLoopOrderStateResponse getInstantiationOrderState(String name, String version)
416             throws PfModelException {
417
418         List<ControlLoop> controlLoops = controlLoopProvider.getControlLoops(name, version);
419
420         var response = new ControlLoopOrderStateResponse();
421
422         controlLoops.forEach(controlLoop -> {
423             var genericNameVersion = new GenericNameVersion();
424             genericNameVersion.setName(controlLoop.getName());
425             genericNameVersion.setVersion(controlLoop.getVersion());
426             response.getControlLoopIdentifierList().add(genericNameVersion);
427         });
428
429         return response;
430     }
431
432     /**
433      * Saves Instance Properties and Control Loop.
434      * Gets a list of control loops which are primed or de-primed.
435      *
436      * @param name the name of the control loop to get, null for all control loops
437      * @param version the version of the control loop to get, null for all control loops
438      * @return a list of Instantiation Command
439      * @throws PfModelException on errors getting control loops
440      */
441     public ControlLoopPrimedResponse getControlLoopPriming(String name, String version) throws PfModelException {
442
443         List<ControlLoop> controlLoops = controlLoopProvider.getControlLoops(name, version);
444
445         var response = new ControlLoopPrimedResponse();
446
447         controlLoops.forEach(controlLoop -> {
448             var primed = new ControlLoopPrimed();
449             primed.setName(controlLoop.getName());
450             primed.setVersion(controlLoop.getVersion());
451             primed.setPrimed(controlLoop.getPrimed());
452             response.getPrimedControlLoopsList().add(primed);
453         });
454
455         return response;
456     }
457
458     /**
459      * Creates instance element name.
460      *
461      * @param serviceTemplate the service template
462      * @param controlLoops a list of control loops
463      * @return the result of the instance properties and instantiation operation
464      * @throws PfModelException on creation errors
465      */
466     private InstancePropertiesResponse saveInstancePropertiesAndControlLoop(ToscaServiceTemplate serviceTemplate,
467             ControlLoops controlLoops) throws PfModelException {
468
469         var response = new InstancePropertiesResponse();
470
471         Map<String, ToscaNodeTemplate> toscaSavedNodeTemplate;
472
473         synchronized (lockit) {
474             for (ControlLoop controlLoop : controlLoops.getControlLoopList()) {
475                 var checkControlLoop = controlLoopProvider.getControlLoop(controlLoop.getKey().asIdentifier());
476                 if (checkControlLoop != null) {
477                     throw new PfModelException(Response.Status.BAD_REQUEST,
478                             "Control loop with id " + controlLoop.getKey().asIdentifier() + " already defined");
479                 }
480             }
481
482             toscaSavedNodeTemplate = controlLoopProvider.saveInstanceProperties(serviceTemplate);
483
484             controlLoopProvider.createControlLoops(controlLoops.getControlLoopList());
485
486         }
487
488         List<ToscaConceptIdentifier> affectedControlLoops = controlLoops.getControlLoopList().stream()
489                 .map(cl -> cl.getKey().asIdentifier()).collect(Collectors.toList());
490
491         List<ToscaConceptIdentifier> toscaAffectedProperties = toscaSavedNodeTemplate.values().stream()
492                 .map(template -> template.getKey().asIdentifier()).collect(Collectors.toList());
493
494         response.setAffectedInstanceProperties(Stream.of(affectedControlLoops, toscaAffectedProperties)
495                 .flatMap(Collection::stream).collect(Collectors.toList()));
496
497         return response;
498     }
499
500     /**
501      * Crates a new Control Loop instance.
502      *
503      * @param instanceName Control Loop Instance name
504      * @param controlLoop empty Control Loop
505      * @param controlLoopElements new Control Loop Element map
506      * @param template original Cloned Tosca Node Template
507      * @param newNodeTemplate new Tosca Node Template
508      */
509     private void crateNewControlLoopInstance(String instanceName, ControlLoop controlLoop,
510             Map<UUID, ControlLoopElement> controlLoopElements, ToscaNodeTemplate template,
511             ToscaNodeTemplate newNodeTemplate) {
512         if (template.getType().equals(CONTROL_LOOP_NODE_TYPE)) {
513             controlLoop.setDefinition(getControlLoopDefinition(newNodeTemplate));
514         }
515
516         if (template.getType().contains(CONTROL_LOOP_NODE_ELEMENT_TYPE)) {
517             ControlLoopElement controlLoopElement = getControlLoopElement(newNodeTemplate);
518             controlLoopElements.put(controlLoopElement.getId(), controlLoopElement);
519         }
520
521         controlLoop.setName("PMSH" + instanceName);
522         controlLoop.setVersion(template.getVersion());
523         controlLoop.setDescription("PMSH control loop " + instanceName);
524         controlLoop.setState(ControlLoopState.UNINITIALISED);
525         controlLoop.setOrderedState(ControlLoopOrderedState.UNINITIALISED);
526     }
527
528     /**
529      * Get's the instance property name of the control loop.
530      *
531      * @param name the name of the control loop to get, null for all control loops
532      * @param version the version of the control loop to get, null for all control loops
533      * @return the instance name of the control loop instance properties
534      * @throws PfModelException on errors getting control loops
535      */
536     private String getInstancePropertyName(String name, String version) throws PfModelException {
537         List<String> toscaDefinitionsNames = controlLoopProvider.getControlLoops(name, version).stream()
538                 .map(ControlLoop::getDefinition).map(ToscaNameVersion::getName).collect(Collectors.toList());
539
540         return toscaDefinitionsNames.stream().reduce("", (s1, s2) -> {
541
542             if (s2.contains(INSTANCE_TEXT)) {
543                 String[] instances = s2.split(INSTANCE_TEXT);
544
545                 return INSTANCE_TEXT + instances[1];
546             }
547
548             return s1;
549         });
550     }
551
552     /**
553      * Generates Instance Name in sequential order and return it to append to the Node Template Name.
554      *
555      * @return instanceName
556      */
557     private String generateSequentialInstanceName() {
558         List<ToscaNodeTemplate> nodeTemplates = controlLoopProvider.getNodeTemplates(null, null);
559
560         int instanceNumber = nodeTemplates.stream().map(ToscaNodeTemplate::getName)
561                 .filter(name -> name.contains(INSTANCE_TEXT)).map(n -> {
562                     String[] defNameArr = n.split(INSTANCE_TEXT);
563
564                     return Integer.parseInt(defNameArr[1]);
565                 }).reduce(0, Math::max);
566
567         return INSTANCE_TEXT + (instanceNumber + 1);
568     }
569
570     /**
571      * Retrieves Control Loop Definition.
572      *
573      * @param template tosca node template
574      * @return control loop definition
575      */
576     private ToscaConceptIdentifier getControlLoopDefinition(ToscaNodeTemplate template) {
577         ToscaConceptIdentifier definition = new ToscaConceptIdentifier();
578         definition.setName(template.getName());
579         definition.setVersion(template.getVersion());
580
581         return definition;
582     }
583
584     /**
585      * Retrieves Control Loop Element.
586      *
587      * @param template tosca node template
588      * @return a control loop element
589      */
590     @SuppressWarnings("unchecked")
591     private ControlLoopElement getControlLoopElement(ToscaNodeTemplate template) {
592         ControlLoopElement controlLoopElement = new ControlLoopElement();
593         ToscaConceptIdentifier definition = new ToscaConceptIdentifier();
594         definition.setName(template.getName());
595         definition.setVersion(template.getVersion());
596         controlLoopElement.setDefinition(definition);
597
598         LinkedTreeMap<String, Object> participantId =
599                 (LinkedTreeMap<String, Object>) template.getProperties().get(PARTICIPANT_ID_PROPERTY_KEY);
600
601         if (participantId != null) {
602             ToscaConceptIdentifier participantIdProperty = new ToscaConceptIdentifier();
603             participantIdProperty.setName(String.valueOf(participantId.get(CL_ELEMENT_NAME)));
604             participantIdProperty.setVersion(String.valueOf(participantId.get(CL_ELEMENT_VERSION)));
605             controlLoopElement.setParticipantId(participantIdProperty);
606         }
607
608         LinkedTreeMap<String, Object> participantType =
609                 (LinkedTreeMap<String, Object>) template.getProperties().get(PARTICIPANT_TYPE_PROPERTY_KEY);
610
611         if (participantType != null) {
612             ToscaConceptIdentifier participantTypeProperty = new ToscaConceptIdentifier();
613             participantTypeProperty.setName(String.valueOf(participantType.get(CL_ELEMENT_NAME)));
614             participantTypeProperty.setVersion(participantType.get(CL_ELEMENT_VERSION).toString());
615             controlLoopElement.setParticipantType(participantTypeProperty);
616         }
617
618         return controlLoopElement;
619     }
620
621     /**
622      * Deep clones ToscaNodeTemplate.
623      *
624      * @param serviceTemplate ToscaServiceTemplate
625      * @return a cloned Hash Map of ToscaNodeTemplate
626      */
627     private Map<String, ToscaNodeTemplate> deepCloneNodeTemplate(ToscaServiceTemplate serviceTemplate) {
628         String jsonString = GSON.toJson(serviceTemplate.getToscaTopologyTemplate().getNodeTemplates());
629
630         Type type = new TypeToken<HashMap<String, ToscaNodeTemplate>>() {}.getType();
631
632         return GSON.fromJson(jsonString, type);
633     }
634
635 }