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