0d7d88803a93ff3a5ba38e1b708a04720a2afada
[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.Component;
69
70 /**
71  * This class is dedicated to the Instantiation of Commissioned control loop.
72  */
73 @Component
74 @AllArgsConstructor
75 public class ControlLoopInstantiationProvider {
76     private static final String CONTROL_LOOP_NODE_TYPE = "org.onap.policy.clamp.controlloop.ControlLoop";
77     private static final String CONTROL_LOOP_NODE_ELEMENT_TYPE = "ControlLoopElement";
78     private static final String PARTICIPANT_ID_PROPERTY_KEY = "participant_id";
79     private static final String PARTICIPANT_TYPE_PROPERTY_KEY = "participantType";
80     private static final String CL_ELEMENT_NAME = "name";
81     private static final String CL_ELEMENT_VERSION = "version";
82     private static final String INSTANCE_TEXT = "_Instance";
83
84     private static final Gson GSON = new Gson();
85
86     private final ControlLoopProvider controlLoopProvider;
87     private final CommissioningProvider commissioningProvider;
88     private final SupervisionHandler supervisionHandler;
89     private final ParticipantProvider participantProvider;
90
91     private static final Object lockit = new Object();
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
185         synchronized (lockit) {
186             for (ControlLoop controlLoop : controlLoops.getControlLoopList()) {
187                 var checkControlLoopOpt = controlLoopProvider.findControlLoop(controlLoop.getKey().asIdentifier());
188                 if (checkControlLoopOpt.isPresent()) {
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.saveControlLoops(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.saveControlLoops(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             var controlLoopOpt = controlLoopProvider.findControlLoop(name, version);
305             if (controlLoopOpt.isEmpty()) {
306                 throw new PfModelException(Response.Status.NOT_FOUND, "Control Loop not found");
307             }
308             var controlLoop = controlLoopOpt.get();
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             response.setAffectedControlLoops(
315                     List.of(controlLoopProvider.deleteControlLoop(name, version).getKey().asIdentifier()));
316         }
317         return response;
318     }
319
320     /**
321      * Get the requested control loops.
322      *
323      * @param name the name of the control loop to get, null for all control loops
324      * @param version the version of the control loop to get, null for all control loops
325      * @return the control loops
326      * @throws PfModelException on errors getting control loops
327      */
328     public ControlLoops getControlLoops(String name, String version) throws PfModelException {
329         var controlLoops = new ControlLoops();
330         controlLoops.setControlLoopList(controlLoopProvider.getControlLoops(name, version));
331
332         return controlLoops;
333     }
334
335     /**
336      * Issue a command to control loops, setting their ordered state.
337      *
338      * @param command the command to issue to control loops
339      * @return the result of the initiation command
340      * @throws PfModelException on errors setting the ordered state on the control loops
341      * @throws ControlLoopException on ordered state invalid
342      */
343     public InstantiationResponse issueControlLoopCommand(InstantiationCommand command)
344             throws ControlLoopException, PfModelException {
345
346         if (command.getOrderedState() == null) {
347             throw new ControlLoopException(Status.BAD_REQUEST, "ordered state invalid or not specified on command");
348         }
349
350         synchronized (lockit) {
351             var participants = participantProvider.getParticipants();
352             if (participants.isEmpty()) {
353                 throw new ControlLoopException(Status.BAD_REQUEST, "No participants registered");
354             }
355             var validationResult = new BeanValidationResult("InstantiationCommand", command);
356             List<ControlLoop> controlLoops = new ArrayList<>(command.getControlLoopIdentifierList().size());
357             for (ToscaConceptIdentifier id : command.getControlLoopIdentifierList()) {
358                 var controlLoopOpt = controlLoopProvider.findControlLoop(id);
359                 if (controlLoopOpt.isEmpty()) {
360                     validationResult.addResult("ToscaConceptIdentifier", id, ValidationStatus.INVALID,
361                             "ControlLoop with id " + id + " not found");
362                 } else {
363                     var controlLoop = controlLoopOpt.get();
364                     controlLoop.setCascadedOrderedState(command.getOrderedState());
365                     controlLoops.add(controlLoop);
366                 }
367             }
368             if (validationResult.isValid()) {
369                 validationResult = validateIssueControlLoops(controlLoops, participants);
370             }
371             if (!validationResult.isValid()) {
372                 throw new PfModelException(Response.Status.BAD_REQUEST, validationResult.getResult());
373             }
374             controlLoopProvider.saveControlLoops(controlLoops);
375         }
376
377         supervisionHandler.triggerControlLoopSupervision(command.getControlLoopIdentifierList());
378         var response = new InstantiationResponse();
379         response.setAffectedControlLoops(command.getControlLoopIdentifierList());
380
381         return response;
382     }
383
384     private BeanValidationResult validateIssueControlLoops(List<ControlLoop> controlLoops,
385             List<Participant> participants) {
386         var result = new BeanValidationResult("ControlLoops", controlLoops);
387
388         Map<ToscaConceptIdentifier, Participant> participantMap = participants.stream()
389                 .collect(Collectors.toMap(participant -> participant.getKey().asIdentifier(), Function.identity()));
390
391         for (ControlLoop controlLoop : controlLoops) {
392
393             for (var element : controlLoop.getElements().values()) {
394                 var subResult = new BeanValidationResult(ENTRY + element.getDefinition().getName(), element);
395
396                 Participant p = participantMap.get(element.getParticipantId());
397                 if (p == null) {
398                     subResult.addResult(new ObjectValidationResult(CONTROL_LOOP_NODE_ELEMENT_TYPE,
399                             element.getDefinition().getName(), ValidationStatus.INVALID,
400                             "Participant with ID " + element.getParticipantId() + " is not registered"));
401                 } else if (!p.getParticipantType().equals(element.getParticipantType())) {
402                     subResult.addResult(new ObjectValidationResult(CONTROL_LOOP_NODE_ELEMENT_TYPE,
403                             element.getDefinition().getName(), ValidationStatus.INVALID,
404                             "Participant with ID " + element.getParticipantType() + " - " + element.getParticipantId()
405                                     + " is not registered"));
406                 }
407                 result.addResult(subResult);
408             }
409
410         }
411
412         return result;
413     }
414
415     /**
416      * Gets a list of control loops with it's ordered state.
417      *
418      * @param name the name of the control loop to get, null for all control loops
419      * @param version the version of the control loop to get, null for all control loops
420      * @return a list of Instantiation Command
421      * @throws PfModelException on errors getting control loops
422      */
423     public ControlLoopOrderStateResponse getInstantiationOrderState(String name, String version)
424             throws PfModelException {
425
426         List<ControlLoop> controlLoops = controlLoopProvider.getControlLoops(name, version);
427
428         var response = new ControlLoopOrderStateResponse();
429
430         controlLoops.forEach(controlLoop -> {
431             var genericNameVersion = new GenericNameVersion();
432             genericNameVersion.setName(controlLoop.getName());
433             genericNameVersion.setVersion(controlLoop.getVersion());
434             response.getControlLoopIdentifierList().add(genericNameVersion);
435         });
436
437         return response;
438     }
439
440     /**
441      * Saves Instance Properties and Control Loop.
442      * Gets a list of control loops which are primed or de-primed.
443      *
444      * @param name the name of the control loop to get, null for all control loops
445      * @param version the version of the control loop to get, null for all control loops
446      * @return a list of Instantiation Command
447      * @throws PfModelException on errors getting control loops
448      */
449     public ControlLoopPrimedResponse getControlLoopPriming(String name, String version) throws PfModelException {
450
451         List<ControlLoop> controlLoops = controlLoopProvider.getControlLoops(name, version);
452
453         var response = new ControlLoopPrimedResponse();
454
455         controlLoops.forEach(controlLoop -> {
456             var primed = new ControlLoopPrimed();
457             primed.setName(controlLoop.getName());
458             primed.setVersion(controlLoop.getVersion());
459             primed.setPrimed(controlLoop.getPrimed());
460             response.getPrimedControlLoopsList().add(primed);
461         });
462
463         return response;
464     }
465
466     /**
467      * Creates instance element name.
468      *
469      * @param serviceTemplate the service template
470      * @param controlLoops a list of control loops
471      * @return the result of the instance properties and instantiation operation
472      * @throws PfModelException on creation errors
473      */
474     private InstancePropertiesResponse saveInstancePropertiesAndControlLoop(ToscaServiceTemplate serviceTemplate,
475             ControlLoops controlLoops) throws PfModelException {
476
477         var response = new InstancePropertiesResponse();
478
479         Map<String, ToscaNodeTemplate> toscaSavedNodeTemplate;
480
481         synchronized (lockit) {
482             for (ControlLoop controlLoop : controlLoops.getControlLoopList()) {
483                 var checkControlLoopOpt = controlLoopProvider.findControlLoop(controlLoop.getKey().asIdentifier());
484                 if (checkControlLoopOpt.isPresent()) {
485                     throw new PfModelException(Response.Status.BAD_REQUEST,
486                             "Control loop with id " + controlLoop.getKey().asIdentifier() + " already defined");
487                 }
488             }
489
490             toscaSavedNodeTemplate = controlLoopProvider.saveInstanceProperties(serviceTemplate);
491
492             controlLoopProvider.saveControlLoops(controlLoops.getControlLoopList());
493
494         }
495
496         List<ToscaConceptIdentifier> affectedControlLoops = controlLoops.getControlLoopList().stream()
497                 .map(cl -> cl.getKey().asIdentifier()).collect(Collectors.toList());
498
499         List<ToscaConceptIdentifier> toscaAffectedProperties = toscaSavedNodeTemplate.values().stream()
500                 .map(template -> template.getKey().asIdentifier()).collect(Collectors.toList());
501
502         response.setAffectedInstanceProperties(Stream.of(affectedControlLoops, toscaAffectedProperties)
503                 .flatMap(Collection::stream).collect(Collectors.toList()));
504
505         return response;
506     }
507
508     /**
509      * Crates a new Control Loop instance.
510      *
511      * @param instanceName Control Loop Instance name
512      * @param controlLoop empty Control Loop
513      * @param controlLoopElements new Control Loop Element map
514      * @param template original Cloned Tosca Node Template
515      * @param newNodeTemplate new Tosca Node Template
516      */
517     private void crateNewControlLoopInstance(String instanceName, ControlLoop controlLoop,
518             Map<UUID, ControlLoopElement> controlLoopElements, ToscaNodeTemplate template,
519             ToscaNodeTemplate newNodeTemplate) {
520         if (template.getType().equals(CONTROL_LOOP_NODE_TYPE)) {
521             controlLoop.setDefinition(getControlLoopDefinition(newNodeTemplate));
522         }
523
524         if (template.getType().contains(CONTROL_LOOP_NODE_ELEMENT_TYPE)) {
525             ControlLoopElement controlLoopElement = getControlLoopElement(newNodeTemplate);
526             controlLoopElements.put(controlLoopElement.getId(), controlLoopElement);
527         }
528
529         controlLoop.setName("PMSH" + instanceName);
530         controlLoop.setVersion(template.getVersion());
531         controlLoop.setDescription("PMSH control loop " + instanceName);
532         controlLoop.setState(ControlLoopState.UNINITIALISED);
533         controlLoop.setOrderedState(ControlLoopOrderedState.UNINITIALISED);
534     }
535
536     /**
537      * Get's the instance property name of the control loop.
538      *
539      * @param name the name of the control loop to get, null for all control loops
540      * @param version the version of the control loop to get, null for all control loops
541      * @return the instance name of the control loop instance properties
542      * @throws PfModelException on errors getting control loops
543      */
544     private String getInstancePropertyName(String name, String version) throws PfModelException {
545         List<String> toscaDefinitionsNames = controlLoopProvider.getControlLoops(name, version).stream()
546                 .map(ControlLoop::getDefinition).map(ToscaNameVersion::getName).collect(Collectors.toList());
547
548         return toscaDefinitionsNames.stream().reduce("", (s1, s2) -> {
549
550             if (s2.contains(INSTANCE_TEXT)) {
551                 String[] instances = s2.split(INSTANCE_TEXT);
552
553                 return INSTANCE_TEXT + instances[1];
554             }
555
556             return s1;
557         });
558     }
559
560     /**
561      * Generates Instance Name in sequential order and return it to append to the Node Template Name.
562      *
563      * @return instanceName
564      */
565     private String generateSequentialInstanceName() {
566         List<ToscaNodeTemplate> nodeTemplates = controlLoopProvider.getNodeTemplates(null, null);
567
568         int instanceNumber = nodeTemplates.stream().map(ToscaNodeTemplate::getName)
569                 .filter(name -> name.contains(INSTANCE_TEXT)).map(n -> {
570                     String[] defNameArr = n.split(INSTANCE_TEXT);
571
572                     return Integer.parseInt(defNameArr[1]);
573                 }).reduce(0, Math::max);
574
575         return INSTANCE_TEXT + (instanceNumber + 1);
576     }
577
578     /**
579      * Retrieves Control Loop Definition.
580      *
581      * @param template tosca node template
582      * @return control loop definition
583      */
584     private ToscaConceptIdentifier getControlLoopDefinition(ToscaNodeTemplate template) {
585         ToscaConceptIdentifier definition = new ToscaConceptIdentifier();
586         definition.setName(template.getName());
587         definition.setVersion(template.getVersion());
588
589         return definition;
590     }
591
592     /**
593      * Retrieves Control Loop Element.
594      *
595      * @param template tosca node template
596      * @return a control loop element
597      */
598     @SuppressWarnings("unchecked")
599     private ControlLoopElement getControlLoopElement(ToscaNodeTemplate template) {
600         ControlLoopElement controlLoopElement = new ControlLoopElement();
601         ToscaConceptIdentifier definition = new ToscaConceptIdentifier();
602         definition.setName(template.getName());
603         definition.setVersion(template.getVersion());
604         controlLoopElement.setDefinition(definition);
605
606         LinkedTreeMap<String, Object> participantId =
607                 (LinkedTreeMap<String, Object>) template.getProperties().get(PARTICIPANT_ID_PROPERTY_KEY);
608
609         if (participantId != null) {
610             ToscaConceptIdentifier participantIdProperty = new ToscaConceptIdentifier();
611             participantIdProperty.setName(String.valueOf(participantId.get(CL_ELEMENT_NAME)));
612             participantIdProperty.setVersion(String.valueOf(participantId.get(CL_ELEMENT_VERSION)));
613             controlLoopElement.setParticipantId(participantIdProperty);
614         }
615
616         LinkedTreeMap<String, Object> participantType =
617                 (LinkedTreeMap<String, Object>) template.getProperties().get(PARTICIPANT_TYPE_PROPERTY_KEY);
618
619         if (participantType != null) {
620             ToscaConceptIdentifier participantTypeProperty = new ToscaConceptIdentifier();
621             participantTypeProperty.setName(String.valueOf(participantType.get(CL_ELEMENT_NAME)));
622             participantTypeProperty.setVersion(participantType.get(CL_ELEMENT_VERSION).toString());
623             controlLoopElement.setParticipantType(participantTypeProperty);
624         }
625
626         return controlLoopElement;
627     }
628
629     /**
630      * Deep clones ToscaNodeTemplate.
631      *
632      * @param serviceTemplate ToscaServiceTemplate
633      * @return a cloned Hash Map of ToscaNodeTemplate
634      */
635     private Map<String, ToscaNodeTemplate> deepCloneNodeTemplate(ToscaServiceTemplate serviceTemplate) {
636         String jsonString = GSON.toJson(serviceTemplate.getToscaTopologyTemplate().getNodeTemplates());
637
638         Type type = new TypeToken<HashMap<String, ToscaNodeTemplate>>() {}.getType();
639
640         return GSON.fromJson(jsonString, type);
641     }
642
643 }