1bff2d74771a88cce340e7918ff7267674b0c617
[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.HashMap;
31 import java.util.List;
32 import java.util.Map;
33 import java.util.UUID;
34 import java.util.function.Function;
35 import java.util.function.UnaryOperator;
36 import java.util.stream.Collectors;
37 import java.util.stream.Stream;
38 import javax.ws.rs.core.Response;
39 import javax.ws.rs.core.Response.Status;
40 import lombok.AllArgsConstructor;
41 import org.onap.policy.clamp.controlloop.common.exception.ControlLoopException;
42 import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoop;
43 import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoopElement;
44 import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoopOrderedState;
45 import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoopState;
46 import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoops;
47 import org.onap.policy.clamp.controlloop.models.controlloop.concepts.Participant;
48 import org.onap.policy.clamp.controlloop.models.controlloop.persistence.provider.ControlLoopProvider;
49 import org.onap.policy.clamp.controlloop.models.controlloop.persistence.provider.ParticipantProvider;
50 import org.onap.policy.clamp.controlloop.models.messages.rest.GenericNameVersion;
51 import org.onap.policy.clamp.controlloop.models.messages.rest.instantiation.ControlLoopOrderStateResponse;
52 import org.onap.policy.clamp.controlloop.models.messages.rest.instantiation.ControlLoopPrimed;
53 import org.onap.policy.clamp.controlloop.models.messages.rest.instantiation.ControlLoopPrimedResponse;
54 import org.onap.policy.clamp.controlloop.models.messages.rest.instantiation.InstancePropertiesResponse;
55 import org.onap.policy.clamp.controlloop.models.messages.rest.instantiation.InstantiationCommand;
56 import org.onap.policy.clamp.controlloop.models.messages.rest.instantiation.InstantiationResponse;
57 import org.onap.policy.clamp.controlloop.runtime.commissioning.CommissioningProvider;
58 import org.onap.policy.clamp.controlloop.runtime.supervision.SupervisionHandler;
59 import org.onap.policy.common.parameters.BeanValidationResult;
60 import org.onap.policy.common.parameters.ObjectValidationResult;
61 import org.onap.policy.common.parameters.ValidationResult;
62 import org.onap.policy.common.parameters.ValidationStatus;
63 import org.onap.policy.models.base.PfModelException;
64 import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
65 import org.onap.policy.models.tosca.authorative.concepts.ToscaNameVersion;
66 import org.onap.policy.models.tosca.authorative.concepts.ToscaNodeTemplate;
67 import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;
68 import org.springframework.stereotype.Service;
69 import org.springframework.transaction.annotation.Transactional;
70
71 /**
72  * This class is dedicated to the Instantiation of Commissioned control loop.
73  */
74 @Service
75 @Transactional
76 @AllArgsConstructor
77 public class ControlLoopInstantiationProvider {
78     private static final String CONTROL_LOOP_NODE_TYPE = "org.onap.policy.clamp.controlloop.ControlLoop";
79     private static final String CONTROL_LOOP_NODE_ELEMENT_TYPE = "ControlLoopElement";
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 CL_ELEMENT_NAME = "name";
83     private static final String CL_ELEMENT_VERSION = "version";
84     private static final String INSTANCE_TEXT = "_Instance";
85
86     private static final Gson GSON = new Gson();
87
88     private final ControlLoopProvider controlLoopProvider;
89     private final CommissioningProvider commissioningProvider;
90     private final SupervisionHandler supervisionHandler;
91     private final ParticipantProvider participantProvider;
92     private static final String ENTRY = "entry ";
93
94     /**
95      * Creates Instance Properties and 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.getAllToscaServiceTemplate().get(0);
109
110         Map<String, ToscaNodeTemplate> persistedNodeTemplateMap =
111                 toscaServiceTemplate.getToscaTopologyTemplate().getNodeTemplates();
112
113         Map<String, ToscaNodeTemplate> nodeTemplates = deepCloneNodeTemplate(serviceTemplate);
114
115         nodeTemplates.forEach((key, template) -> {
116             ToscaNodeTemplate newNodeTemplate = new ToscaNodeTemplate();
117             String name = key + instanceName;
118             String version = template.getVersion();
119             String description = template.getDescription() + instanceName;
120             newNodeTemplate.setName(name);
121             newNodeTemplate.setVersion(version);
122             newNodeTemplate.setDescription(description);
123             newNodeTemplate.setProperties(new HashMap<>(template.getProperties()));
124             newNodeTemplate.setType(template.getType());
125             newNodeTemplate.setTypeVersion(template.getTypeVersion());
126             newNodeTemplate.setMetadata(template.getMetadata());
127
128             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.getAllToscaServiceTemplate().get(0);
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         for (ControlLoop controlLoop : controlLoops.getControlLoopList()) {
185             var checkControlLoopOpt = controlLoopProvider.findControlLoop(controlLoop.getKey().asIdentifier());
186             if (checkControlLoopOpt.isPresent()) {
187                 throw new PfModelException(Response.Status.BAD_REQUEST,
188                         controlLoop.getKey().asIdentifier() + " already defined");
189             }
190         }
191         BeanValidationResult validationResult = validateControlLoops(controlLoops);
192         if (!validationResult.isValid()) {
193             throw new PfModelException(Response.Status.BAD_REQUEST, validationResult.getResult());
194         }
195         controlLoopProvider.saveControlLoops(controlLoops.getControlLoopList());
196
197         var response = new InstantiationResponse();
198         response.setAffectedControlLoops(controlLoops.getControlLoopList().stream()
199                 .map(cl -> cl.getKey().asIdentifier()).collect(Collectors.toList()));
200
201         return response;
202     }
203
204     /**
205      * Update control loops.
206      *
207      * @param controlLoops the control loop
208      * @return the result of the instantiation operation
209      * @throws PfModelException on update errors
210      */
211     public InstantiationResponse updateControlLoops(ControlLoops controlLoops) throws PfModelException {
212         BeanValidationResult validationResult = validateControlLoops(controlLoops);
213         if (!validationResult.isValid()) {
214             throw new PfModelException(Response.Status.BAD_REQUEST, validationResult.getResult());
215         }
216         controlLoopProvider.saveControlLoops(controlLoops.getControlLoopList());
217
218         var response = new InstantiationResponse();
219         response.setAffectedControlLoops(controlLoops.getControlLoopList().stream()
220                 .map(cl -> cl.getKey().asIdentifier()).collect(Collectors.toList()));
221
222         return response;
223     }
224
225     /**
226      * Validate ControlLoops.
227      *
228      * @param controlLoops ControlLoops to validate
229      * @return the result of validation
230      * @throws PfModelException if controlLoops is not valid
231      */
232     private BeanValidationResult validateControlLoops(ControlLoops controlLoops) throws PfModelException {
233
234         var result = new BeanValidationResult("ControlLoops", controlLoops);
235
236         for (ControlLoop controlLoop : controlLoops.getControlLoopList()) {
237             var subResult = new BeanValidationResult(ENTRY + controlLoop.getDefinition().getName(), controlLoop);
238
239             List<ToscaNodeTemplate> toscaNodeTemplates = commissioningProvider.getControlLoopDefinitions(
240                     controlLoop.getDefinition().getName(), controlLoop.getDefinition().getVersion());
241
242             if (toscaNodeTemplates.isEmpty()) {
243                 subResult.addResult(new ObjectValidationResult("ControlLoop", controlLoop.getDefinition().getName(),
244                         ValidationStatus.INVALID, "Commissioned control loop definition not FOUND"));
245             } else if (toscaNodeTemplates.size() > 1) {
246                 subResult.addResult(new ObjectValidationResult("ControlLoop", controlLoop.getDefinition().getName(),
247                         ValidationStatus.INVALID, "Commissioned control loop definition not VALID"));
248             } else {
249
250                 List<ToscaNodeTemplate> clElementDefinitions =
251                         commissioningProvider.getControlLoopElementDefinitions(toscaNodeTemplates.get(0));
252
253                 // @formatter:off
254                 Map<String, ToscaConceptIdentifier> definitions = clElementDefinitions
255                         .stream()
256                         .map(nodeTemplate -> nodeTemplate.getKey().asIdentifier())
257                         .collect(Collectors.toMap(ToscaConceptIdentifier::getName, UnaryOperator.identity()));
258                 // @formatter:on
259
260                 for (ControlLoopElement element : controlLoop.getElements().values()) {
261                     subResult.addResult(validateDefinition(definitions, element.getDefinition()));
262                 }
263             }
264             result.addResult(subResult);
265         }
266         return result;
267     }
268
269     /**
270      * Validate ToscaConceptIdentifier, checking if exist in ToscaConceptIdentifiers map.
271      *
272      * @param definitions map of all ToscaConceptIdentifiers
273      * @param definition ToscaConceptIdentifier to validate
274      * @return the validation result
275      */
276     private ValidationResult validateDefinition(Map<String, ToscaConceptIdentifier> definitions,
277             ToscaConceptIdentifier definition) {
278         var result = new BeanValidationResult(ENTRY + definition.getName(), definition);
279         ToscaConceptIdentifier identifier = definitions.get(definition.getName());
280         if (identifier == null) {
281             result.setResult(ValidationStatus.INVALID, "Not FOUND");
282         } else if (!identifier.equals(definition)) {
283             result.setResult(ValidationStatus.INVALID, "Version not matching");
284         }
285         return (result.isClean() ? null : result);
286     }
287
288     /**
289      * Delete the control loop with the given name and version.
290      *
291      * @param name the name of the control loop to delete
292      * @param version the version of the control loop to delete
293      * @return the result of the deletion
294      * @throws PfModelException on deletion errors
295      */
296     public InstantiationResponse deleteControlLoop(String name, String version) throws PfModelException {
297         var controlLoopOpt = controlLoopProvider.findControlLoop(name, version);
298         if (controlLoopOpt.isEmpty()) {
299             throw new PfModelException(Response.Status.NOT_FOUND, "Control Loop not found");
300         }
301         var controlLoop = controlLoopOpt.get();
302         if (!ControlLoopState.UNINITIALISED.equals(controlLoop.getState())) {
303             throw new PfModelException(Response.Status.BAD_REQUEST,
304                     "Control Loop State is still " + controlLoop.getState());
305         }
306         var response = new InstantiationResponse();
307         response.setAffectedControlLoops(
308                 List.of(controlLoopProvider.deleteControlLoop(name, version).getKey().asIdentifier()));
309         return response;
310     }
311
312     /**
313      * Get the requested control loops.
314      *
315      * @param name the name of the control loop to get, null for all control loops
316      * @param version the version of the control loop to get, null for all control loops
317      * @return the control loops
318      * @throws PfModelException on errors getting control loops
319      */
320     @Transactional(readOnly = true)
321     public ControlLoops getControlLoops(String name, String version) throws PfModelException {
322         var controlLoops = new ControlLoops();
323         controlLoops.setControlLoopList(controlLoopProvider.getControlLoops(name, version));
324
325         return controlLoops;
326     }
327
328     /**
329      * Issue a command to control loops, setting their ordered state.
330      *
331      * @param command the command to issue to control loops
332      * @return the result of the initiation command
333      * @throws PfModelException on errors setting the ordered state on the control loops
334      * @throws ControlLoopException on ordered state invalid
335      */
336     public InstantiationResponse issueControlLoopCommand(InstantiationCommand command)
337             throws ControlLoopException, PfModelException {
338
339         if (command.getOrderedState() == null) {
340             throw new ControlLoopException(Status.BAD_REQUEST, "ordered state invalid or not specified on command");
341         }
342
343         var participants = participantProvider.getParticipants();
344         if (participants.isEmpty()) {
345             throw new ControlLoopException(Status.BAD_REQUEST, "No participants registered");
346         }
347         var validationResult = new BeanValidationResult("InstantiationCommand", command);
348         List<ControlLoop> controlLoops = new ArrayList<>(command.getControlLoopIdentifierList().size());
349         for (ToscaConceptIdentifier id : command.getControlLoopIdentifierList()) {
350             var controlLoopOpt = controlLoopProvider.findControlLoop(id);
351             if (controlLoopOpt.isEmpty()) {
352                 validationResult.addResult("ToscaConceptIdentifier", id, ValidationStatus.INVALID,
353                         "ControlLoop with id " + id + " not found");
354             } else {
355                 var controlLoop = controlLoopOpt.get();
356                 controlLoop.setCascadedOrderedState(command.getOrderedState());
357                 controlLoops.add(controlLoop);
358             }
359         }
360         if (validationResult.isValid()) {
361             validationResult = validateIssueControlLoops(controlLoops, participants);
362         }
363         if (!validationResult.isValid()) {
364             throw new PfModelException(Response.Status.BAD_REQUEST, validationResult.getResult());
365         }
366         controlLoopProvider.saveControlLoops(controlLoops);
367
368         supervisionHandler.triggerControlLoopSupervision(command.getControlLoopIdentifierList());
369         var response = new InstantiationResponse();
370         response.setAffectedControlLoops(command.getControlLoopIdentifierList());
371
372         return response;
373     }
374
375     private BeanValidationResult validateIssueControlLoops(List<ControlLoop> controlLoops,
376             List<Participant> participants) {
377         var result = new BeanValidationResult("ControlLoops", controlLoops);
378
379         Map<ToscaConceptIdentifier, Participant> participantMap = participants.stream()
380                 .collect(Collectors.toMap(participant -> participant.getKey().asIdentifier(), Function.identity()));
381
382         for (ControlLoop controlLoop : controlLoops) {
383
384             for (var element : controlLoop.getElements().values()) {
385
386                 var subResult = new BeanValidationResult(ENTRY + element.getDefinition().getName(), element);
387                 Participant p = participantMap.get(element.getParticipantId());
388                 if (p == null) {
389                     subResult.addResult(new ObjectValidationResult(CONTROL_LOOP_NODE_ELEMENT_TYPE,
390                             element.getDefinition().getName(), ValidationStatus.INVALID,
391                             "Participant with ID " + element.getParticipantId() + " is not registered"));
392                 } else if (!p.getParticipantType().equals(element.getParticipantType())) {
393                     subResult.addResult(new ObjectValidationResult(CONTROL_LOOP_NODE_ELEMENT_TYPE,
394                             element.getDefinition().getName(), ValidationStatus.INVALID,
395                             "Participant with ID " + element.getParticipantType() + " - " + element.getParticipantId()
396                                     + " is not registered"));
397                 }
398                 result.addResult(subResult);
399             }
400
401         }
402
403         return result;
404     }
405
406     /**
407      * Gets a list of control loops with it's ordered state.
408      *
409      * @param name the name of the control loop to get, null for all control loops
410      * @param version the version of the control loop to get, null for all control loops
411      * @return a list of Instantiation Command
412      * @throws PfModelException on errors getting control loops
413      */
414     @Transactional(readOnly = true)
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     @Transactional(readOnly = true)
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         for (var controlLoop : controlLoops.getControlLoopList()) {
471             var checkControlLoopOpt = controlLoopProvider.findControlLoop(controlLoop.getKey().asIdentifier());
472             if (checkControlLoopOpt.isPresent()) {
473                 throw new PfModelException(Response.Status.BAD_REQUEST,
474                         "Control loop with id " + controlLoop.getKey().asIdentifier() + " already defined");
475             }
476         }
477         Map<String, ToscaNodeTemplate> toscaSavedNodeTemplate =
478                 controlLoopProvider.saveInstanceProperties(serviceTemplate);
479         controlLoopProvider.saveControlLoops(controlLoops.getControlLoopList());
480         List<ToscaConceptIdentifier> affectedControlLoops = controlLoops.getControlLoopList().stream()
481                 .map(cl -> cl.getKey().asIdentifier()).collect(Collectors.toList());
482
483         List<ToscaConceptIdentifier> toscaAffectedProperties = toscaSavedNodeTemplate.values().stream()
484                 .map(template -> template.getKey().asIdentifier()).collect(Collectors.toList());
485
486         var response = new InstancePropertiesResponse();
487         response.setAffectedInstanceProperties(Stream.of(affectedControlLoops, toscaAffectedProperties)
488                 .flatMap(Collection::stream).collect(Collectors.toList()));
489
490         return response;
491     }
492
493     /**
494      * Crates a new Control Loop instance.
495      *
496      * @param instanceName Control Loop Instance name
497      * @param controlLoop empty Control Loop
498      * @param controlLoopElements new Control Loop Element map
499      * @param template original Cloned Tosca Node Template
500      * @param newNodeTemplate new Tosca Node Template
501      */
502     private void crateNewControlLoopInstance(String instanceName, ControlLoop controlLoop,
503             Map<UUID, ControlLoopElement> controlLoopElements, ToscaNodeTemplate template,
504             ToscaNodeTemplate newNodeTemplate) {
505         if (template.getType().equals(CONTROL_LOOP_NODE_TYPE)) {
506             controlLoop.setDefinition(getControlLoopDefinition(newNodeTemplate));
507         }
508
509         if (template.getType().contains(CONTROL_LOOP_NODE_ELEMENT_TYPE)) {
510             ControlLoopElement controlLoopElement = getControlLoopElement(newNodeTemplate);
511             controlLoopElements.put(controlLoopElement.getId(), controlLoopElement);
512         }
513
514         controlLoop.setName("PMSH" + instanceName);
515         controlLoop.setVersion(template.getVersion());
516         controlLoop.setDescription("PMSH control loop " + instanceName);
517         controlLoop.setState(ControlLoopState.UNINITIALISED);
518         controlLoop.setOrderedState(ControlLoopOrderedState.UNINITIALISED);
519     }
520
521     /**
522      * Get's the instance property name of the control loop.
523      *
524      * @param name the name of the control loop to get, null for all control loops
525      * @param version the version of the control loop to get, null for all control loops
526      * @return the instance name of the control loop instance properties
527      * @throws PfModelException on errors getting control loops
528      */
529     private String getInstancePropertyName(String name, String version) throws PfModelException {
530         List<String> toscaDefinitionsNames = controlLoopProvider.getControlLoops(name, version).stream()
531                 .map(ControlLoop::getDefinition).map(ToscaNameVersion::getName).collect(Collectors.toList());
532
533         return toscaDefinitionsNames.stream().reduce("", (s1, s2) -> {
534
535             if (s2.contains(INSTANCE_TEXT)) {
536                 String[] instances = s2.split(INSTANCE_TEXT);
537
538                 return INSTANCE_TEXT + instances[1];
539             }
540
541             return s1;
542         });
543     }
544
545     /**
546      * Generates Instance Name in sequential order and return it to append to the Node Template Name.
547      *
548      * @return instanceName
549      */
550     private String generateSequentialInstanceName() {
551         List<ToscaNodeTemplate> nodeTemplates = controlLoopProvider.getAllNodeTemplates();
552
553         int instanceNumber = nodeTemplates.stream().map(ToscaNodeTemplate::getName)
554                 .filter(name -> name.contains(INSTANCE_TEXT)).map(n -> {
555                     String[] defNameArr = n.split(INSTANCE_TEXT);
556
557                     return Integer.parseInt(defNameArr[1]);
558                 }).reduce(0, Math::max);
559
560         return INSTANCE_TEXT + (instanceNumber + 1);
561     }
562
563     /**
564      * Retrieves Control Loop Definition.
565      *
566      * @param template tosca node template
567      * @return control loop definition
568      */
569     private ToscaConceptIdentifier getControlLoopDefinition(ToscaNodeTemplate template) {
570         ToscaConceptIdentifier definition = new ToscaConceptIdentifier();
571         definition.setName(template.getName());
572         definition.setVersion(template.getVersion());
573         return definition;
574     }
575
576     /**
577      * Retrieves Control Loop Element.
578      *
579      * @param template tosca node template
580      * @return a control loop element
581      */
582     @SuppressWarnings("unchecked")
583     private ControlLoopElement getControlLoopElement(ToscaNodeTemplate template) {
584         ControlLoopElement controlLoopElement = new ControlLoopElement();
585         ToscaConceptIdentifier definition = new ToscaConceptIdentifier();
586         definition.setName(template.getName());
587         definition.setVersion(template.getVersion());
588         controlLoopElement.setDefinition(definition);
589         LinkedTreeMap<String, Object> participantId =
590                 (LinkedTreeMap<String, Object>) template.getProperties().get(PARTICIPANT_ID_PROPERTY_KEY);
591         if (participantId != null) {
592             ToscaConceptIdentifier participantIdProperty = new ToscaConceptIdentifier();
593             participantIdProperty.setName(String.valueOf(participantId.get(CL_ELEMENT_NAME)));
594             participantIdProperty.setVersion(String.valueOf(participantId.get(CL_ELEMENT_VERSION)));
595             controlLoopElement.setParticipantId(participantIdProperty);
596         }
597         LinkedTreeMap<String, Object> participantType =
598                 (LinkedTreeMap<String, Object>) template.getProperties().get(PARTICIPANT_TYPE_PROPERTY_KEY);
599         if (participantType != null) {
600             ToscaConceptIdentifier participantTypeProperty = new ToscaConceptIdentifier();
601             participantTypeProperty.setName(String.valueOf(participantType.get(CL_ELEMENT_NAME)));
602             participantTypeProperty.setVersion(participantType.get(CL_ELEMENT_VERSION).toString());
603             controlLoopElement.setParticipantType(participantTypeProperty);
604         }
605         return controlLoopElement;
606     }
607
608     /**
609      * Deep clones ToscaNodeTemplate.
610      *
611      * @param serviceTemplate ToscaServiceTemplate
612      * @return a cloned Hash Map of ToscaNodeTemplate
613      */
614     private Map<String, ToscaNodeTemplate> deepCloneNodeTemplate(ToscaServiceTemplate serviceTemplate) {
615         String jsonString = GSON.toJson(serviceTemplate.getToscaTopologyTemplate().getNodeTemplates());
616         Type type = new TypeToken<HashMap<String, ToscaNodeTemplate>>() {}.getType();
617         return GSON.fromJson(jsonString, type);
618     }
619 }