2 * ============LICENSE_START=======================================================
3 * Copyright (C) 2021 Nordix Foundation.
4 * ================================================================================
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
17 * SPDX-License-Identifier: Apache-2.0
18 * ============LICENSE_END=========================================================
21 package org.onap.policy.clamp.controlloop.runtime.commissioning;
23 import com.fasterxml.jackson.core.JsonProcessingException;
24 import com.fasterxml.jackson.databind.ObjectMapper;
25 import com.fasterxml.jackson.databind.PropertyNamingStrategies;
26 import com.fasterxml.jackson.module.jsonSchema.factories.SchemaFactoryWrapper;
27 import java.util.ArrayList;
28 import java.util.Collections;
29 import java.util.HashMap;
30 import java.util.List;
32 import java.util.stream.Collectors;
33 import org.apache.commons.collections4.CollectionUtils;
34 import org.apache.commons.collections4.MapUtils;
35 import org.onap.policy.clamp.controlloop.models.controlloop.persistence.provider.ControlLoopProvider;
36 import org.onap.policy.clamp.controlloop.models.messages.rest.commissioning.CommissioningResponse;
37 import org.onap.policy.models.base.PfModelException;
38 import org.onap.policy.models.provider.PolicyModelsProvider;
39 import org.onap.policy.models.tosca.authorative.concepts.ToscaCapabilityType;
40 import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
41 import org.onap.policy.models.tosca.authorative.concepts.ToscaDataType;
42 import org.onap.policy.models.tosca.authorative.concepts.ToscaNodeTemplate;
43 import org.onap.policy.models.tosca.authorative.concepts.ToscaNodeType;
44 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyType;
45 import org.onap.policy.models.tosca.authorative.concepts.ToscaProperty;
46 import org.onap.policy.models.tosca.authorative.concepts.ToscaRelationshipType;
47 import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;
48 import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplates;
49 import org.onap.policy.models.tosca.authorative.concepts.ToscaTopologyTemplate;
50 import org.onap.policy.models.tosca.authorative.concepts.ToscaTypedEntityFilter;
51 import org.springframework.stereotype.Component;
54 * This class provides the create, read and delete actions on Commissioning of Control Loop concepts in the database to
58 public class CommissioningProvider {
59 public static final String CONTROL_LOOP_NODE_TYPE = "org.onap.policy.clamp.controlloop.ControlLoop";
61 private final PolicyModelsProvider modelsProvider;
62 private final ControlLoopProvider clProvider;
64 private static final Object lockit = new Object();
67 * Create a commissioning provider.
69 * @param modelsProvider the PolicyModelsProvider
70 * @param clProvider the ControlLoopProvider
72 public CommissioningProvider(PolicyModelsProvider modelsProvider, ControlLoopProvider clProvider) {
73 this.modelsProvider = modelsProvider;
74 this.clProvider = clProvider;
78 * Create control loops from a service template.
80 * @param serviceTemplate the service template
81 * @return the result of the commissioning operation
82 * @throws PfModelException on creation errors
84 public CommissioningResponse createControlLoopDefinitions(ToscaServiceTemplate serviceTemplate)
85 throws PfModelException {
86 synchronized (lockit) {
87 modelsProvider.createServiceTemplate(serviceTemplate);
90 var response = new CommissioningResponse();
92 response.setAffectedControlLoopDefinitions(serviceTemplate.getToscaTopologyTemplate().getNodeTemplates()
95 .map(template -> template.getKey().asIdentifier())
96 .collect(Collectors.toList()));
103 * Delete the control loop definition with the given name and version.
105 * @param name the name of the control loop definition to delete
106 * @param version the version of the control loop to delete
107 * @return the result of the deletion
108 * @throws PfModelException on deletion errors
110 public CommissioningResponse deleteControlLoopDefinition(String name, String version) throws PfModelException {
111 synchronized (lockit) {
112 modelsProvider.deleteServiceTemplate(name, version);
115 var response = new CommissioningResponse();
116 response.setAffectedControlLoopDefinitions(
117 Collections.singletonList(new ToscaConceptIdentifier(name, version)));
123 * Get control loop node templates.
125 * @param clName the name of the control loop, null for all
126 * @param clVersion the version of the control loop, null for all
127 * @return list of control loop node templates
128 * @throws PfModelException on errors getting control loop definitions
130 public List<ToscaNodeTemplate> getControlLoopDefinitions(String clName, String clVersion) throws PfModelException {
133 ToscaTypedEntityFilter<ToscaNodeTemplate> nodeTemplateFilter = ToscaTypedEntityFilter
134 .<ToscaNodeTemplate>builder()
137 .type(CONTROL_LOOP_NODE_TYPE)
141 return clProvider.getFilteredNodeTemplates(nodeTemplateFilter);
145 * Get the control loop elements from a control loop node template.
147 * @param controlLoopNodeTemplate the control loop node template
148 * @return a list of the control loop element node templates in a control loop node template
149 * @throws PfModelException on errors get control loop element node templates
151 public List<ToscaNodeTemplate> getControlLoopElementDefinitions(ToscaNodeTemplate controlLoopNodeTemplate)
152 throws PfModelException {
153 if (!CONTROL_LOOP_NODE_TYPE.equals(controlLoopNodeTemplate.getType())) {
154 return Collections.emptyList();
157 if (MapUtils.isEmpty(controlLoopNodeTemplate.getProperties())) {
158 return Collections.emptyList();
161 @SuppressWarnings("unchecked")
162 List<Map<String, String>> controlLoopElements =
163 (List<Map<String, String>>) controlLoopNodeTemplate.getProperties().get("elements");
165 if (CollectionUtils.isEmpty(controlLoopElements)) {
166 return Collections.emptyList();
169 List<ToscaNodeTemplate> controlLoopElementList = new ArrayList<>();
171 controlLoopElementList.addAll(
174 .map(elementMap -> clProvider.getNodeTemplates(elementMap.get("name"),
175 elementMap.get("version")))
176 .flatMap(List::stream)
177 .collect(Collectors.toList())
181 return controlLoopElementList;
185 * Get the initial node types with common or instance properties.
187 * @param fullNodeTypes map of all the node types in the specified template
188 * @param common boolean to indicate whether common or instance properties are required
189 * @return node types map that only has common properties
190 * @throws PfModelException on errors getting node type with common properties
192 private Map<String, ToscaNodeType> getInitialNodeTypesMap(
193 Map<String, ToscaNodeType> fullNodeTypes, boolean common) {
195 var tempNodeTypesMap = new HashMap<String, ToscaNodeType>();
197 fullNodeTypes.forEach((key, nodeType) -> {
198 var tempToscaNodeType = new ToscaNodeType();
199 tempToscaNodeType.setName(key);
201 var resultantPropertyMap = findCommonOrInstancePropsInNodeTypes(
204 if (!resultantPropertyMap.isEmpty()) {
205 tempToscaNodeType.setProperties(resultantPropertyMap);
206 tempNodeTypesMap.put(key, tempToscaNodeType);
209 return tempNodeTypesMap;
212 private Map<String, ToscaProperty> findCommonOrInstancePropsInNodeTypes(
213 ToscaNodeType nodeType, boolean common) {
215 var tempCommonPropertyMap = new HashMap<String, ToscaProperty>();
216 var tempInstancePropertyMap = new HashMap<String, ToscaProperty>();
218 nodeType.getProperties().forEach((propKey, prop) -> {
220 if (prop.getMetadata() != null) {
221 prop.getMetadata().forEach((k, v) -> {
222 if (k.equals("common") && v.equals("true") && common) {
223 tempCommonPropertyMap.put(propKey, prop);
224 } else if (k.equals("common") && v.equals("false") && !common) {
225 tempInstancePropertyMap.put(propKey, prop);
230 tempInstancePropertyMap.put(propKey, prop);
234 if (tempCommonPropertyMap.isEmpty() && !common) {
235 return tempInstancePropertyMap;
237 return tempCommonPropertyMap;
242 * Get the node types derived from those that have common properties.
244 * @param initialNodeTypes map of all the node types in the specified template
245 * @param filteredNodeTypes map of all the node types that have common or instance properties
246 * @return all node types that have common properties including their children
247 * @throws PfModelException on errors getting node type with common properties
249 private Map<String, ToscaNodeType> getFinalNodeTypesMap(
250 Map<String, ToscaNodeType> initialNodeTypes,
251 Map<String, ToscaNodeType> filteredNodeTypes) {
252 for (var i = 0; i < initialNodeTypes.size(); i++) {
253 initialNodeTypes.forEach((key, nodeType) -> {
254 var tempToscaNodeType = new ToscaNodeType();
255 tempToscaNodeType.setName(key);
257 if (filteredNodeTypes.get(nodeType.getDerivedFrom()) != null) {
258 tempToscaNodeType.setName(key);
260 var finalProps = new HashMap<String, ToscaProperty>(
261 filteredNodeTypes.get(nodeType.getDerivedFrom()).getProperties());
263 tempToscaNodeType.setProperties(finalProps);
267 filteredNodeTypes.putIfAbsent(key, tempToscaNodeType);
271 return filteredNodeTypes;
275 * Get the requested node types with common or instance properties.
277 * @param common boolean indicating common or instance properties
278 * @param name the name of the definition to get, null for all definitions
279 * @param version the version of the definition to get, null for all definitions
280 * @return the node types with common or instance properties
281 * @throws PfModelException on errors getting node type properties
283 private Map<String, ToscaNodeType> getCommonOrInstancePropertiesFromNodeTypes(
284 boolean common, String name, String version)
285 throws PfModelException {
286 var serviceTemplates = new ToscaServiceTemplates();
287 serviceTemplates.setServiceTemplates(modelsProvider.getServiceTemplateList(name, version));
288 var tempNodeTypesMap =
289 this.getInitialNodeTypesMap(serviceTemplates.getServiceTemplates().get(0).getNodeTypes(), common);
291 return this.getFinalNodeTypesMap(
292 serviceTemplates.getServiceTemplates().get(0).getNodeTypes(), tempNodeTypesMap);
297 * Get node templates with appropriate common or instance properties added.
299 * @param initialNodeTemplates map of all the node templates in the specified template
300 * @param nodeTypeProps map of all the node types that have common or instance properties including children
301 * @return all node templates with appropriate common or instance properties added
302 * @throws PfModelException on errors getting map of node templates with common or instance properties added
304 private Map<String, ToscaNodeTemplate> getDerivedCommonOrInstanceNodeTemplates(
305 Map<String, ToscaNodeTemplate> initialNodeTemplates,
306 Map<String, ToscaNodeType> nodeTypeProps) {
308 var finalNodeTemplatesMap = new HashMap<String, ToscaNodeTemplate>();
310 initialNodeTemplates.forEach((templateKey, template) -> {
311 if (nodeTypeProps.containsKey(template.getType())) {
312 var finalMergedProps = new HashMap<String, Object>();
314 nodeTypeProps.get(template.getType()).getProperties().forEach(finalMergedProps::putIfAbsent);
316 template.setProperties(finalMergedProps);
318 finalNodeTemplatesMap.put(templateKey, template);
323 return finalNodeTemplatesMap;
327 * Get node templates with common properties added.
329 * @param common boolean indicating common or instance properties to be used
330 * @param name the name of the definition to use, null for all definitions
331 * @param version the version of the definition to use, null for all definitions
332 * @return the nodes templates with common or instance properties
333 * @throws PfModelException on errors getting common or instance properties from node_templates
335 public Map<String, ToscaNodeTemplate> getNodeTemplatesWithCommonOrInstanceProperties(
336 boolean common, String name, String version) throws PfModelException {
338 var commonOrInstanceNodeTypeProps =
339 this.getCommonOrInstancePropertiesFromNodeTypes(common, name, version);
341 var serviceTemplates = new ToscaServiceTemplates();
342 serviceTemplates.setServiceTemplates(modelsProvider.getServiceTemplateList(name, version));
344 return this.getDerivedCommonOrInstanceNodeTemplates(
345 serviceTemplates.getServiceTemplates().get(0).getToscaTopologyTemplate().getNodeTemplates(),
346 commonOrInstanceNodeTypeProps);
350 * Get the requested control loop definitions.
352 * @param name the name of the definition to get, null for all definitions
353 * @param version the version of the definition to get, null for all definitions
354 * @return the control loop definitions
355 * @throws PfModelException on errors getting control loop definitions
357 public ToscaServiceTemplate getToscaServiceTemplate(String name, String version) throws PfModelException {
358 var serviceTemplates = new ToscaServiceTemplates();
359 serviceTemplates.setServiceTemplates(modelsProvider.getServiceTemplateList(name, version));
360 return serviceTemplates.getServiceTemplates().get(0);
364 * Get the tosca service template with only required sections.
366 * @param name the name of the template to get, null for all definitions
367 * @param version the version of the template to get, null for all definitions
368 * @return the tosca service template
369 * @throws PfModelException on errors getting tosca service template
371 public Map<String, Object> getToscaServiceTemplateReduced(String name, String version) throws PfModelException {
372 var serviceTemplates = new ToscaServiceTemplates();
373 serviceTemplates.setServiceTemplates(modelsProvider.getServiceTemplateList(name, version));
375 ToscaServiceTemplate fullTemplate = serviceTemplates.getServiceTemplates().get(0);
377 var template = new HashMap<String, Object>();
378 template.put("tosca_definitions_version", fullTemplate.getToscaDefinitionsVersion());
379 template.put("data_types", fullTemplate.getDataTypes());
380 template.put("policy_types", fullTemplate.getPolicyTypes());
381 template.put("node_types", fullTemplate.getNodeTypes());
382 template.put("topology_template", fullTemplate.getToscaTopologyTemplate());
388 * Get the requested json schema.
390 * @param section section of the tosca service template to get schema for
391 * @return the specified tosca service template or section Json Schema
392 * @throws PfModelException on errors with retrieving the classes
393 * @throws JsonProcessingException on errors generating the schema
395 public String getToscaServiceTemplateSchema(String section) throws PfModelException, JsonProcessingException {
396 var mapper = new ObjectMapper();
397 mapper.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE);
398 var visitor = new SchemaFactoryWrapper();
402 mapper.acceptJsonFormatVisitor(mapper.constructType(ToscaDataType.class), visitor);
404 case "capability_types":
405 mapper.acceptJsonFormatVisitor(mapper.constructType(ToscaCapabilityType.class), visitor);
408 mapper.acceptJsonFormatVisitor(mapper.constructType(ToscaNodeType.class), visitor);
410 case "relationship_types":
411 mapper.acceptJsonFormatVisitor(mapper.constructType(ToscaRelationshipType.class), visitor);
414 mapper.acceptJsonFormatVisitor(mapper.constructType(ToscaPolicyType.class), visitor);
416 case "topology_template":
417 mapper.acceptJsonFormatVisitor(mapper.constructType(ToscaTopologyTemplate.class), visitor);
419 case "node_templates":
420 mapper.acceptJsonFormatVisitor(mapper.getTypeFactory()
421 .constructCollectionType(List.class, ToscaNodeTemplate.class), visitor);
424 mapper.acceptJsonFormatVisitor(mapper.constructType(ToscaServiceTemplate.class), visitor);
427 var jsonSchema = visitor.finalSchema();
428 return mapper.writerWithDefaultPrettyPrinter().writeValueAsString(jsonSchema);