2 * ============LICENSE_START=======================================================
3 * Copyright (C) 2021-2022 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 java.util.ArrayList;
25 import java.util.Collections;
26 import java.util.HashMap;
27 import java.util.List;
29 import java.util.stream.Collectors;
30 import javax.ws.rs.core.Response.Status;
31 import org.apache.commons.collections4.CollectionUtils;
32 import org.apache.commons.collections4.MapUtils;
33 import org.apache.commons.lang3.StringUtils;
34 import org.onap.policy.clamp.acm.runtime.supervision.SupervisionHandler;
35 import org.onap.policy.clamp.models.acm.concepts.Participant;
36 import org.onap.policy.clamp.models.acm.messages.rest.commissioning.CommissioningResponse;
37 import org.onap.policy.clamp.models.acm.persistence.provider.AutomationCompositionProvider;
38 import org.onap.policy.clamp.models.acm.persistence.provider.ParticipantProvider;
39 import org.onap.policy.clamp.models.acm.persistence.provider.ServiceTemplateProvider;
40 import org.onap.policy.common.utils.coder.Coder;
41 import org.onap.policy.common.utils.coder.CoderException;
42 import org.onap.policy.common.utils.coder.StandardCoder;
43 import org.onap.policy.models.base.PfModelException;
44 import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
45 import org.onap.policy.models.tosca.authorative.concepts.ToscaNodeTemplate;
46 import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;
47 import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplates;
48 import org.onap.policy.models.tosca.authorative.concepts.ToscaTypedEntityFilter;
49 import org.springframework.stereotype.Service;
50 import org.springframework.transaction.annotation.Transactional;
53 * This class provides the create, read and delete actions on Commissioning of automation composition concepts in the
54 * database to the callers.
58 public class CommissioningProvider {
59 public static final String AUTOMATION_COMPOSITION_NODE_TYPE = "org.onap.policy.clamp.acm.AutomationComposition";
60 private static final String HYPHEN = "-";
62 private final ServiceTemplateProvider serviceTemplateProvider;
63 private final AutomationCompositionProvider acProvider;
64 private static final Coder CODER = new StandardCoder();
65 private final ParticipantProvider participantProvider;
66 private final SupervisionHandler supervisionHandler;
69 * Create a commissioning provider.
71 * @param serviceTemplateProvider the ServiceTemplate Provider
72 * @param acProvider the AutomationComposition Provider
73 * @param supervisionHandler the Supervision Handler
74 * @param participantProvider the Participant Provider
76 public CommissioningProvider(ServiceTemplateProvider serviceTemplateProvider,
77 AutomationCompositionProvider acProvider, SupervisionHandler supervisionHandler,
78 ParticipantProvider participantProvider) {
79 this.serviceTemplateProvider = serviceTemplateProvider;
80 this.acProvider = acProvider;
81 this.supervisionHandler = supervisionHandler;
82 this.participantProvider = participantProvider;
86 * Create automation compositions from a service template.
88 * @param serviceTemplate the service template
89 * @return the result of the commissioning operation
90 * @throws PfModelException on creation errors
92 public CommissioningResponse createAutomationCompositionDefinitions(ToscaServiceTemplate serviceTemplate)
93 throws PfModelException {
95 if (verifyIfInstancePropertiesExists()) {
96 throw new PfModelException(Status.BAD_REQUEST,
97 "Delete instances, to commission automation composition definitions");
99 serviceTemplate = serviceTemplateProvider.createServiceTemplate(serviceTemplate);
100 List<Participant> participantList = participantProvider.getParticipants();
101 if (!participantList.isEmpty()) {
102 supervisionHandler.handleSendCommissionMessage(serviceTemplate.getName(), serviceTemplate.getVersion());
104 var response = new CommissioningResponse();
106 response.setAffectedAutomationCompositionDefinitions(
107 serviceTemplate.getToscaTopologyTemplate().getNodeTemplates()
110 .map(template -> template.getKey().asIdentifier())
111 .collect(Collectors.toList()));
118 * Delete the automation composition definition with the given name and version.
120 * @param name the name of the automation composition definition to delete
121 * @param version the version of the automation composition to delete
122 * @return the result of the deletion
123 * @throws PfModelException on deletion errors
125 public CommissioningResponse deleteAutomationCompositionDefinition(String name, String version)
126 throws PfModelException {
128 if (verifyIfInstancePropertiesExists()) {
129 throw new PfModelException(Status.BAD_REQUEST,
130 "Delete instances, to commission automation composition definitions");
132 List<Participant> participantList = participantProvider.getParticipants();
133 if (!participantList.isEmpty()) {
134 supervisionHandler.handleSendDeCommissionMessage();
136 serviceTemplateProvider.deleteServiceTemplate(name, version);
137 var response = new CommissioningResponse();
138 response.setAffectedAutomationCompositionDefinitions(List.of(new ToscaConceptIdentifier(name, version)));
144 * Get automation composition node templates.
146 * @param acName the name of the automation composition, null for all
147 * @param acVersion the version of the automation composition, null for all
148 * @return list of automation composition node templates
149 * @throws PfModelException on errors getting automation composition definitions
151 @Transactional(readOnly = true)
152 public List<ToscaNodeTemplate> getAutomationCompositionDefinitions(String acName, String acVersion)
153 throws PfModelException {
156 ToscaTypedEntityFilter<ToscaNodeTemplate> nodeTemplateFilter = ToscaTypedEntityFilter
157 .<ToscaNodeTemplate>builder()
160 .type(AUTOMATION_COMPOSITION_NODE_TYPE)
164 return acProvider.getFilteredNodeTemplates(nodeTemplateFilter);
168 * Get the automation composition elements from a automation composition node template.
170 * @param automationCompositionNodeTemplate the automation composition node template
171 * @return a list of the automation composition element node templates in a automation composition node template
172 * @throws PfModelException on errors get automation composition element node templates
174 @Transactional(readOnly = true)
175 public List<ToscaNodeTemplate> getAutomationCompositionElementDefinitions(
176 ToscaNodeTemplate automationCompositionNodeTemplate) throws PfModelException {
177 if (!AUTOMATION_COMPOSITION_NODE_TYPE.equals(automationCompositionNodeTemplate.getType())) {
178 return Collections.emptyList();
181 if (MapUtils.isEmpty(automationCompositionNodeTemplate.getProperties())) {
182 return Collections.emptyList();
185 @SuppressWarnings("unchecked")
186 List<Map<String, String>> automationCompositionElements =
187 (List<Map<String, String>>) automationCompositionNodeTemplate.getProperties().get("elements");
189 if (CollectionUtils.isEmpty(automationCompositionElements)) {
190 return Collections.emptyList();
193 List<ToscaNodeTemplate> automationCompositionElementList = new ArrayList<>();
195 automationCompositionElementList.addAll(
196 automationCompositionElements
198 .map(elementMap -> acProvider.getNodeTemplates(elementMap.get("name"),
199 elementMap.get("version")))
200 .flatMap(List::stream)
201 .collect(Collectors.toList())
205 return automationCompositionElementList;
209 * Get node templates with common properties added.
211 * @param name the name of the definition to use, null for all definitions
212 * @param version the version of the definition to use, null for all definitions
213 * @param instanceName automation composition name
214 * @param common boolean indicating common or instance properties to be used
215 * @return the nodes templates with common or instance properties
216 * @throws PfModelException on errors getting common or instance properties from node_templates
218 @Transactional(readOnly = true)
219 public Map<String, ToscaNodeTemplate> getNodeTemplatesWithCommonOrInstanceProperties(
220 final String name, final String version, final String instanceName, final boolean common)
221 throws PfModelException {
223 if (common && verifyIfInstancePropertiesExists()) {
224 throw new PfModelException(Status.BAD_REQUEST,
225 "Cannot create or edit common properties, delete all the instantiations first");
228 var serviceTemplateList = serviceTemplateProvider.getServiceTemplateList(name, version);
230 if (serviceTemplateList.isEmpty()) {
231 throw new PfModelException(Status.BAD_REQUEST,
232 "Tosca service template has to be commissioned before saving instance properties");
235 var commonOrInstanceNodeTypeProps =
236 serviceTemplateProvider.getCommonOrInstancePropertiesFromNodeTypes(common, serviceTemplateList.get(0));
238 var serviceTemplates = new ToscaServiceTemplates();
239 serviceTemplates.setServiceTemplates(filterToscaNodeTemplateInstance(serviceTemplateList, instanceName));
241 return serviceTemplateProvider.getDerivedCommonOrInstanceNodeTemplates(
242 serviceTemplates.getServiceTemplates().get(0).getToscaTopologyTemplate().getNodeTemplates(),
243 commonOrInstanceNodeTypeProps);
247 * Get the requested automation composition definitions.
249 * @param name the name of the definition to get, null for all definitions
250 * @param version the version of the definition to get, null for all definitions
251 * @return the automation composition definitions
252 * @throws PfModelException on errors getting automation composition definitions
254 @Transactional(readOnly = true)
255 public ToscaServiceTemplate getToscaServiceTemplate(String name, String version) throws PfModelException {
256 return serviceTemplateProvider.getToscaServiceTemplate(name, version);
260 * Get All the requested automation composition definitions.
262 * @return the automation composition definitions
263 * @throws PfModelException on errors getting automation composition definitions
265 @Transactional(readOnly = true)
266 public List<ToscaServiceTemplate> getAllToscaServiceTemplate() throws PfModelException {
267 return serviceTemplateProvider.getAllServiceTemplates();
271 * Get the tosca service template with only required sections.
273 * @param name the name of the template to get, null for all definitions
274 * @param version the version of the template to get, null for all definitions
275 * @param instanceName automation composition name
276 * @return the tosca service template
277 * @throws PfModelException on errors getting tosca service template
279 @Transactional(readOnly = true)
280 public String getToscaServiceTemplateReduced(
281 final String name, final String version, final String instanceName)
282 throws PfModelException {
284 var serviceTemplateList = serviceTemplateProvider.getServiceTemplateList(name, version);
286 List<ToscaServiceTemplate> filteredServiceTemplateList =
287 filterToscaNodeTemplateInstance(serviceTemplateList, instanceName);
289 if (filteredServiceTemplateList.isEmpty()) {
290 throw new PfModelException(Status.BAD_REQUEST, "Invalid Service Template");
293 ToscaServiceTemplate fullTemplate = filteredServiceTemplateList.get(0);
295 var template = new HashMap<String, Object>();
296 template.put("tosca_definitions_version", fullTemplate.getToscaDefinitionsVersion());
297 template.put("data_types", fullTemplate.getDataTypes());
298 template.put("policy_types", fullTemplate.getPolicyTypes());
299 template.put("node_types", fullTemplate.getNodeTypes());
300 template.put("topology_template", fullTemplate.getToscaTopologyTemplate());
303 return CODER.encode(template);
305 } catch (CoderException e) {
306 throw new PfModelException(Status.BAD_REQUEST, "Converion to Json Schema failed", e);
311 * Filters service templates if is not an instantiation type.
313 * @param serviceTemplates tosca service template
314 * @param instanceName automation composition name
315 * @return List of tosca service templates
317 private List<ToscaServiceTemplate> filterToscaNodeTemplateInstance(
318 List<ToscaServiceTemplate> serviceTemplates, String instanceName) {
320 List<ToscaServiceTemplate> toscaServiceTemplates = new ArrayList<>();
322 serviceTemplates.forEach(serviceTemplate -> {
324 Map<String, ToscaNodeTemplate> toscaNodeTemplates = new HashMap<>();
326 serviceTemplate.getToscaTopologyTemplate().getNodeTemplates().forEach((key, nodeTemplate) -> {
327 if (StringUtils.isNotEmpty(instanceName) && nodeTemplate.getName().contains(instanceName)) {
328 toscaNodeTemplates.put(key, nodeTemplate);
329 } else if (!nodeTemplate.getName().contains(HYPHEN)) {
330 toscaNodeTemplates.put(key, nodeTemplate);
334 serviceTemplate.getToscaTopologyTemplate().getNodeTemplates().clear();
335 serviceTemplate.getToscaTopologyTemplate().setNodeTemplates(toscaNodeTemplates);
337 toscaServiceTemplates.add(serviceTemplate);
340 return toscaServiceTemplates;
344 * Validates to see if there is any instance properties saved.
346 * @return true if exists instance properties
348 private boolean verifyIfInstancePropertiesExists() {
349 return acProvider.getAllNodeTemplates().stream()
350 .anyMatch(nodeTemplate -> nodeTemplate.getKey().getName().contains(HYPHEN));