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