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
10 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 * SPDX-License-Identifier: Apache-2.0
19 * ============LICENSE_END=========================================================
22 package org.onap.policy.clamp.acm.runtime.commissioning;
24 import com.google.gson.Gson;
25 import com.google.gson.GsonBuilder;
26 import com.google.gson.JsonPrimitive;
27 import com.google.gson.JsonSerializer;
28 import java.util.ArrayList;
29 import java.util.Collections;
30 import java.util.HashMap;
31 import java.util.List;
33 import java.util.stream.Collectors;
34 import javax.ws.rs.core.Response.Status;
35 import org.apache.commons.collections4.CollectionUtils;
36 import org.apache.commons.collections4.MapUtils;
37 import org.onap.policy.clamp.acm.runtime.supervision.SupervisionHandler;
38 import org.onap.policy.clamp.models.acm.concepts.Participant;
39 import org.onap.policy.clamp.models.acm.messages.rest.commissioning.CommissioningResponse;
40 import org.onap.policy.clamp.models.acm.persistence.provider.AutomationCompositionProvider;
41 import org.onap.policy.clamp.models.acm.persistence.provider.ParticipantProvider;
42 import org.onap.policy.clamp.models.acm.persistence.provider.ServiceTemplateProvider;
43 import org.onap.policy.models.base.PfModelException;
44 import org.onap.policy.models.tosca.authorative.concepts.ToscaCapabilityType;
45 import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
46 import org.onap.policy.models.tosca.authorative.concepts.ToscaDataType;
47 import org.onap.policy.models.tosca.authorative.concepts.ToscaNodeTemplate;
48 import org.onap.policy.models.tosca.authorative.concepts.ToscaNodeType;
49 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyType;
50 import org.onap.policy.models.tosca.authorative.concepts.ToscaRelationshipType;
51 import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;
52 import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplates;
53 import org.onap.policy.models.tosca.authorative.concepts.ToscaTopologyTemplate;
54 import org.onap.policy.models.tosca.authorative.concepts.ToscaTypedEntityFilter;
55 import org.springframework.boot.context.event.ApplicationReadyEvent;
56 import org.springframework.context.event.EventListener;
57 import org.springframework.stereotype.Service;
58 import org.springframework.transaction.annotation.Transactional;
61 * This class provides the create, read and delete actions on Commissioning of automation composition concepts in the
62 * database to the callers.
66 public class CommissioningProvider {
67 public static final String AUTOMATION_COMPOSITION_NODE_TYPE = "org.onap.policy.clamp.acm.AutomationComposition";
68 private static final String HYPHEN = "-";
70 private final ServiceTemplateProvider serviceTemplateProvider;
71 private final AutomationCompositionProvider acProvider;
72 private final ParticipantProvider participantProvider;
73 private final SupervisionHandler supervisionHandler;
75 private static final Map<String, String> sections = new HashMap<>();
76 private Gson gson = new Gson();
79 * Create a commissioning provider.
81 * @param serviceTemplateProvider the ServiceTemplate Provider
82 * @param acProvider the AutomationComposition Provider
83 * @param supervisionHandler the Supervision Handler
84 * @param participantProvider the Participant Provider
86 public CommissioningProvider(ServiceTemplateProvider serviceTemplateProvider,
87 AutomationCompositionProvider acProvider, SupervisionHandler supervisionHandler,
88 ParticipantProvider participantProvider) {
89 this.serviceTemplateProvider = serviceTemplateProvider;
90 this.acProvider = acProvider;
91 this.supervisionHandler = supervisionHandler;
92 this.participantProvider = participantProvider;
96 * Event listener initiilize function called at ApplicationReadyEvent.
99 @EventListener(ApplicationReadyEvent.class)
100 public void initialize() {
101 GsonBuilder builder = new GsonBuilder();
102 builder.registerTypeAdapter(ToscaServiceTemplate.class,
103 (JsonSerializer<ToscaServiceTemplate>) (src, typeOfSrc, context) -> new JsonPrimitive(src.toString()));
104 builder.registerTypeAdapter(ToscaDataType.class,
105 (JsonSerializer<ToscaDataType>) (src, typeOfSrc, context) -> new JsonPrimitive(src.toString()));
106 builder.registerTypeAdapter(ToscaCapabilityType.class,
107 (JsonSerializer<ToscaCapabilityType>) (src, typeOfSrc, context) -> new JsonPrimitive(src.toString()));
108 builder.registerTypeAdapter(ToscaNodeType.class,
109 (JsonSerializer<ToscaNodeType>) (src, typeOfSrc, context) -> new JsonPrimitive(src.toString()));
110 builder.registerTypeAdapter(ToscaRelationshipType.class,
111 (JsonSerializer<ToscaRelationshipType>) (src, typeOfSrc, context) -> new JsonPrimitive(src.toString()));
112 builder.registerTypeAdapter(ToscaPolicyType.class,
113 (JsonSerializer<ToscaPolicyType>) (src, typeOfSrc, context) -> new JsonPrimitive(src.toString()));
114 builder.registerTypeAdapter(ToscaTopologyTemplate.class,
115 (JsonSerializer<ToscaTopologyTemplate>) (src, typeOfSrc, context) -> new JsonPrimitive(src.toString()));
116 builder.registerTypeAdapter(ToscaNodeTemplate.class,
117 (JsonSerializer<ToscaNodeTemplate>) (src, typeOfSrc, context) -> new JsonPrimitive(src.toString()));
118 builder.setPrettyPrinting();
119 gson = builder.create();
121 sections.put("data_types", gson.toJson(new ToscaDataType()));
122 sections.put("capability_types", gson.toJson(new ToscaCapabilityType()));
123 sections.put("node_types", gson.toJson(new ToscaNodeType()));
124 sections.put("relationship_types", gson.toJson(new ToscaRelationshipType()));
125 sections.put("policy_types", gson.toJson(new ToscaPolicyType()));
126 sections.put("topology_template", gson.toJson(new ToscaTopologyTemplate()));
127 sections.put("node_templates", gson.toJson(new ToscaNodeTemplate()));
128 sections.put("all", gson.toJson(new ToscaServiceTemplate()));
132 * Create automation compositions from a service template.
134 * @param serviceTemplate the service template
135 * @return the result of the commissioning operation
136 * @throws PfModelException on creation errors
138 public CommissioningResponse createAutomationCompositionDefinitions(ToscaServiceTemplate serviceTemplate)
139 throws PfModelException {
141 if (verifyIfInstancePropertiesExists()) {
142 throw new PfModelException(Status.BAD_REQUEST,
143 "Delete instances, to commission automation composition definitions");
145 serviceTemplate = serviceTemplateProvider.createServiceTemplate(serviceTemplate);
146 List<Participant> participantList = participantProvider.getParticipants();
147 if (!participantList.isEmpty()) {
148 supervisionHandler.handleSendCommissionMessage(serviceTemplate.getName(), serviceTemplate.getVersion());
150 var response = new CommissioningResponse();
152 response.setAffectedAutomationCompositionDefinitions(
153 serviceTemplate.getToscaTopologyTemplate().getNodeTemplates()
156 .map(template -> template.getKey().asIdentifier())
157 .collect(Collectors.toList()));
164 * Delete the automation composition definition with the given name and version.
166 * @param name the name of the automation composition definition to delete
167 * @param version the version of the automation composition to delete
168 * @return the result of the deletion
169 * @throws PfModelException on deletion errors
171 public CommissioningResponse deleteAutomationCompositionDefinition(String name, String version)
172 throws PfModelException {
174 if (verifyIfInstancePropertiesExists()) {
175 throw new PfModelException(Status.BAD_REQUEST,
176 "Delete instances, to commission automation composition definitions");
178 List<Participant> participantList = participantProvider.getParticipants();
179 if (!participantList.isEmpty()) {
180 supervisionHandler.handleSendDeCommissionMessage();
182 serviceTemplateProvider.deleteServiceTemplate(name, version);
183 var response = new CommissioningResponse();
184 response.setAffectedAutomationCompositionDefinitions(List.of(new ToscaConceptIdentifier(name, version)));
190 * Get automation composition node templates.
192 * @param acName the name of the automation composition, null for all
193 * @param acVersion the version of the automation composition, null for all
194 * @return list of automation composition node templates
195 * @throws PfModelException on errors getting automation composition definitions
197 @Transactional(readOnly = true)
198 public List<ToscaNodeTemplate> getAutomationCompositionDefinitions(String acName, String acVersion)
199 throws PfModelException {
202 ToscaTypedEntityFilter<ToscaNodeTemplate> nodeTemplateFilter = ToscaTypedEntityFilter
203 .<ToscaNodeTemplate>builder()
206 .type(AUTOMATION_COMPOSITION_NODE_TYPE)
210 return acProvider.getFilteredNodeTemplates(nodeTemplateFilter);
214 * Get the automation composition elements from a automation composition node template.
216 * @param automationCompositionNodeTemplate the automation composition node template
217 * @return a list of the automation composition element node templates in a automation composition node template
218 * @throws PfModelException on errors get automation composition element node templates
220 @Transactional(readOnly = true)
221 public List<ToscaNodeTemplate> getAutomationCompositionElementDefinitions(
222 ToscaNodeTemplate automationCompositionNodeTemplate) throws PfModelException {
223 if (!AUTOMATION_COMPOSITION_NODE_TYPE.equals(automationCompositionNodeTemplate.getType())) {
224 return Collections.emptyList();
227 if (MapUtils.isEmpty(automationCompositionNodeTemplate.getProperties())) {
228 return Collections.emptyList();
231 @SuppressWarnings("unchecked")
232 List<Map<String, String>> automationCompositionElements =
233 (List<Map<String, String>>) automationCompositionNodeTemplate.getProperties().get("elements");
235 if (CollectionUtils.isEmpty(automationCompositionElements)) {
236 return Collections.emptyList();
239 List<ToscaNodeTemplate> automationCompositionElementList = new ArrayList<>();
241 automationCompositionElementList.addAll(
242 automationCompositionElements
244 .map(elementMap -> acProvider.getNodeTemplates(elementMap.get("name"),
245 elementMap.get("version")))
246 .flatMap(List::stream)
247 .collect(Collectors.toList())
251 return automationCompositionElementList;
255 * Get node templates with common properties added.
257 * @param common boolean indicating common or instance properties to be used
258 * @param name the name of the definition to use, null for all definitions
259 * @param version the version of the definition to use, null for all definitions
260 * @return the nodes templates with common or instance properties
261 * @throws PfModelException on errors getting common or instance properties from node_templates
263 @Transactional(readOnly = true)
264 public Map<String, ToscaNodeTemplate> getNodeTemplatesWithCommonOrInstanceProperties(boolean common, String name,
265 String version) throws PfModelException {
267 if (common && verifyIfInstancePropertiesExists()) {
268 throw new PfModelException(Status.BAD_REQUEST,
269 "Cannot create or edit common properties, delete all the instantiations first");
272 var serviceTemplateList = serviceTemplateProvider.getServiceTemplateList(name, version);
273 var commonOrInstanceNodeTypeProps =
274 serviceTemplateProvider.getCommonOrInstancePropertiesFromNodeTypes(common, serviceTemplateList.get(0));
276 var serviceTemplates = new ToscaServiceTemplates();
277 serviceTemplates.setServiceTemplates(filterToscaNodeTemplateInstance(serviceTemplateList));
279 return serviceTemplateProvider.getDerivedCommonOrInstanceNodeTemplates(
280 serviceTemplates.getServiceTemplates().get(0).getToscaTopologyTemplate().getNodeTemplates(),
281 commonOrInstanceNodeTypeProps);
285 * Get the requested automation composition definitions.
287 * @param name the name of the definition to get, null for all definitions
288 * @param version the version of the definition to get, null for all definitions
289 * @return the automation composition definitions
290 * @throws PfModelException on errors getting automation composition definitions
292 @Transactional(readOnly = true)
293 public ToscaServiceTemplate getToscaServiceTemplate(String name, String version) throws PfModelException {
294 return serviceTemplateProvider.getToscaServiceTemplate(name, version);
298 * Get All the requested automation composition definitions.
300 * @return the automation composition definitions
301 * @throws PfModelException on errors getting automation composition definitions
303 @Transactional(readOnly = true)
304 public List<ToscaServiceTemplate> getAllToscaServiceTemplate() throws PfModelException {
305 return serviceTemplateProvider.getAllServiceTemplates();
309 * Get the tosca service template with only required sections.
311 * @param name the name of the template to get, null for all definitions
312 * @param version the version of the template to get, null for all definitions
313 * @return the tosca service template
314 * @throws PfModelException on errors getting tosca service template
316 @Transactional(readOnly = true)
317 public String getToscaServiceTemplateReduced(String name, String version) throws PfModelException {
318 var serviceTemplateList = serviceTemplateProvider.getServiceTemplateList(name, version);
320 List<ToscaServiceTemplate> filteredServiceTemplateList = filterToscaNodeTemplateInstance(serviceTemplateList);
322 if (filteredServiceTemplateList.isEmpty()) {
323 throw new PfModelException(Status.BAD_REQUEST, "Invalid Service Template");
326 ToscaServiceTemplate fullTemplate = filteredServiceTemplateList.get(0);
328 var template = new HashMap<String, Object>();
329 template.put("tosca_definitions_version", fullTemplate.getToscaDefinitionsVersion());
330 template.put("data_types", fullTemplate.getDataTypes());
331 template.put("policy_types", fullTemplate.getPolicyTypes());
332 template.put("node_types", fullTemplate.getNodeTypes());
333 template.put("topology_template", fullTemplate.getToscaTopologyTemplate());
335 return gson.toJson(template);
339 * Get the requested json schema.
341 * @param section section of the tosca service template to get schema for
342 * @return the specified tosca service template or section Json Schema
343 * @throws PfModelException on errors with retrieving the classes
345 public String getToscaServiceTemplateSchema(String section) throws PfModelException {
346 return sections.getOrDefault(section, sections.get("all"));
349 private List<ToscaServiceTemplate> filterToscaNodeTemplateInstance(List<ToscaServiceTemplate> serviceTemplates) {
351 List<ToscaServiceTemplate> toscaServiceTemplates = new ArrayList<>();
353 serviceTemplates.stream().forEach(serviceTemplate -> {
355 Map<String, ToscaNodeTemplate> toscaNodeTemplates = new HashMap<>();
357 serviceTemplate.getToscaTopologyTemplate().getNodeTemplates().forEach((key, nodeTemplate) -> {
358 if (!nodeTemplate.getName().contains(HYPHEN)) {
359 toscaNodeTemplates.put(key, nodeTemplate);
363 serviceTemplate.getToscaTopologyTemplate().getNodeTemplates().clear();
364 serviceTemplate.getToscaTopologyTemplate().setNodeTemplates(toscaNodeTemplates);
366 toscaServiceTemplates.add(serviceTemplate);
369 return toscaServiceTemplates;
373 * Validates to see if there is any instance properties saved.
375 * @return true if exists instance properties
377 private boolean verifyIfInstancePropertiesExists() {
378 return acProvider.getAllNodeTemplates().stream()
379 .anyMatch(nodeTemplate -> nodeTemplate.getKey().getName().contains(HYPHEN));