2 * ============LICENSE_START=======================================================
3 * Copyright (C) 2022 Bell Canada. All rights reserved.
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.api.main.service;
23 import java.util.List;
24 import javax.ws.rs.core.Response;
25 import lombok.NonNull;
26 import lombok.RequiredArgsConstructor;
27 import org.apache.commons.collections4.CollectionUtils;
28 import org.onap.policy.api.main.repository.ToscaServiceTemplateRepository;
29 import org.onap.policy.api.main.rest.PolicyFetchMode;
30 import org.onap.policy.common.parameters.BeanValidationResult;
31 import org.onap.policy.models.base.PfConceptKey;
32 import org.onap.policy.models.base.PfModelException;
33 import org.onap.policy.models.base.PfModelRuntimeException;
34 import org.onap.policy.models.tosca.authorative.concepts.ToscaEntityFilter;
35 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
36 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyType;
37 import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;
38 import org.onap.policy.models.tosca.authorative.concepts.ToscaTypedEntityFilter;
39 import org.onap.policy.models.tosca.simple.concepts.JpaToscaPolicies;
40 import org.onap.policy.models.tosca.simple.concepts.JpaToscaPolicyTypes;
41 import org.onap.policy.models.tosca.simple.concepts.JpaToscaServiceTemplate;
42 import org.onap.policy.models.tosca.simple.concepts.JpaToscaTopologyTemplate;
43 import org.onap.policy.models.tosca.simple.provider.SimpleToscaProvider;
44 import org.onap.policy.models.tosca.utils.ToscaServiceTemplateUtils;
45 import org.onap.policy.models.tosca.utils.ToscaUtils;
46 import org.slf4j.Logger;
47 import org.slf4j.LoggerFactory;
48 import org.springframework.stereotype.Service;
49 import org.springframework.transaction.annotation.Transactional;
53 @RequiredArgsConstructor
54 public class ToscaServiceTemplateService {
56 private static final Logger LOGGER = LoggerFactory.getLogger(ToscaServiceTemplateService.class);
58 // Recurring string constants
59 private static final String POLICY_TYPE = "policy type ";
60 private static final String NOT_FOUND = " not found";
61 public static final String SERVICE_TEMPLATE_NOT_FOUND_MSG = "service template not found in database";
62 public static final String DO_NOT_EXIST_MSG = " do not exist";
64 private final ToscaServiceTemplateRepository toscaServiceTemplateRepository;
65 private final PdpGroupService pdpGroupService;
66 private final PolicyTypeService policyTypeService;
67 private final PolicyService policyService;
70 * Retrieves a list of policy types matching specified policy type name and version.
72 * @param policyTypeName the name of policy type
73 * @param policyTypeVersion the version of policy type
74 * @return the ToscaServiceTemplate object
76 public ToscaServiceTemplate fetchPolicyTypes(final String policyTypeName, final String policyTypeVersion)
77 throws PfModelException {
78 return getFilteredPolicyTypes(policyTypeName, policyTypeVersion);
82 * Retrieves a list of policy types with the latest versions.
84 * @param policyTypeName the name of policy type
85 * @return the ToscaServiceTemplate object
87 public ToscaServiceTemplate fetchLatestPolicyTypes(final String policyTypeName) throws PfModelException {
88 return getFilteredPolicyTypes(policyTypeName, ToscaEntityFilter.LATEST_VERSION);
92 * Creates a new policy type.
94 * @param body the entity body of policy type
95 * @return the TOSCA service template containing the created policy types
96 * @throws PfModelRuntimeException on errors creating policy types
98 public ToscaServiceTemplate createPolicyType(@NonNull final ToscaServiceTemplate body)
99 throws PfModelRuntimeException {
100 final var incomingServiceTemplate = new JpaToscaServiceTemplate(body);
101 LOGGER.debug("->createPolicyType: serviceTemplate={}", incomingServiceTemplate);
103 // assert incoming body contains policyTypes
104 ToscaUtils.assertPolicyTypesExist(incomingServiceTemplate);
106 // append the incoming fragment to the DB TOSCA service template
107 final var serviceTemplateToWrite =
108 ToscaServiceTemplateUtils.addFragment(getDefaultJpaToscaServiceTemplate(), incomingServiceTemplate);
110 final var result = serviceTemplateToWrite.validate("service template");
111 if (!result.isValid()) {
112 throw new PfModelRuntimeException(Response.Status.NOT_ACCEPTABLE, result.getResult());
114 toscaServiceTemplateRepository.save(serviceTemplateToWrite);
115 LOGGER.debug("<-createPolicyType: writtenServiceTemplate={}", serviceTemplateToWrite);
121 * Delete the policy type matching specified policy type name and version.
123 * @param policyTypeName the name of policy type
124 * @param policyTypeVersion the version of policy type, if the version of the key is null,
125 * all versions of the policy type are deleted.
126 * @return the TOSCA service template containing the policy types that were deleted
127 * @throws PfModelRuntimeException on errors deleting policy types
129 public ToscaServiceTemplate deletePolicyType(final String policyTypeName, final String policyTypeVersion)
130 throws PfModelRuntimeException {
131 final var policyTypeKey = new PfConceptKey(policyTypeName, policyTypeVersion);
132 LOGGER.debug("->deletePolicyType: name={}, version={}", policyTypeName, policyTypeVersion);
134 // terminate deletion if supported in a PdpGroup
135 pdpGroupService.assertPolicyTypeNotSupportedInPdpGroup(policyTypeName, policyTypeVersion);
137 final var serviceTemplate = getDefaultJpaToscaServiceTemplate();
139 // terminate deletion if not found
140 if (!ToscaUtils.doPolicyTypesExist(serviceTemplate)) {
141 throw new PfModelRuntimeException(Response.Status.NOT_FOUND, "no policy types found");
144 final var policyTypeForDeletion = serviceTemplate.getPolicyTypes().get(policyTypeKey);
145 if (policyTypeForDeletion == null) {
146 throw new PfModelRuntimeException(Response.Status.NOT_FOUND,
147 POLICY_TYPE + policyTypeKey.getId() + NOT_FOUND);
150 final var result = new BeanValidationResult("policy types", serviceTemplate);
152 for (final var policyType : serviceTemplate.getPolicyTypes().getAll(null)) {
153 final var ancestorList = ToscaUtils
154 .getEntityTypeAncestors(serviceTemplate.getPolicyTypes(), policyType, result);
155 // terminate deletion if referenced by another via derived_from property
156 if (ancestorList.contains(policyTypeForDeletion)) {
157 throw new PfModelRuntimeException(Response.Status.NOT_ACCEPTABLE, POLICY_TYPE + policyTypeKey.getId()
158 + " is in use, it is referenced in policy type " + policyType.getId());
161 if (ToscaUtils.doPoliciesExist(serviceTemplate)) {
162 for (final var policy : serviceTemplate.getTopologyTemplate().getPolicies().getAll(null)) {
163 // terminate deletion if referenced by a policy
164 if (policyTypeKey.equals(policy.getType())) {
165 throw new PfModelRuntimeException(Response.Status.NOT_ACCEPTABLE, POLICY_TYPE
166 + policyTypeKey.getId() + " is in use, it is referenced in policy " + policy.getId());
171 // remove policyType from service template and write to DB
172 serviceTemplate.getPolicyTypes().getConceptMap().remove(policyTypeKey);
173 toscaServiceTemplateRepository.save(serviceTemplate);
175 // remove the entry from the Policy table
176 policyTypeService.deletePolicyType(policyTypeKey);
178 // prepare return service template object
179 var deletedServiceTemplate = new JpaToscaServiceTemplate();
180 deletedServiceTemplate.setPolicyTypes(new JpaToscaPolicyTypes());
181 deletedServiceTemplate.getPolicyTypes().getConceptMap().put(policyTypeKey, policyTypeForDeletion);
183 LOGGER.debug("<-deletePolicyType: key={}, serviceTemplate={}", policyTypeKey, deletedServiceTemplate);
184 return deletedServiceTemplate.toAuthorative();
188 * Retrieves a list of policies matching specified name and version of both policy type and policy.
190 * @param policyTypeName the name of policy type
191 * @param policyTypeVersion the version of policy type
192 * @param policyName the name of policy
193 * @param policyVersion the version of policy
194 * @param mode the fetch mode for policies
195 * @return the ToscaServiceTemplate object with the policies found
196 * @throws PfModelException on errors getting the policy
198 public ToscaServiceTemplate fetchPolicies(final String policyTypeName, final String policyTypeVersion,
199 final String policyName, final String policyVersion, final PolicyFetchMode mode) throws PfModelException {
200 return getFilteredPolicies(policyTypeName, policyTypeVersion, policyName, policyVersion, mode);
204 * Retrieves a list of policies with the latest versions that match specified policy type id and version.
206 * @param policyTypeName the name of policy type
207 * @param policyTypeVersion the version of policy type
208 * @param policyName the name of the policy
209 * @param mode the fetch mode for policies
210 * @return the ToscaServiceTemplate object with the policies found
211 * @throws PfModelException on errors getting the policy
213 public ToscaServiceTemplate fetchLatestPolicies(final String policyTypeName, final String policyTypeVersion,
214 final String policyName, final PolicyFetchMode mode) throws PfModelException {
215 return getFilteredPolicies(policyTypeName, policyTypeVersion, policyName, ToscaTypedEntityFilter.LATEST_VERSION,
220 * Creates one or more new policies for the same policy type name and version.
222 * @param policyTypeName the name of policy type
223 * @param policyTypeVersion the version of policy type
224 * @param body the entity body of polic(ies)
225 * @return the ToscaServiceTemplate object containing the policy types that were created
226 * @throws PfModelRuntimeException on errors creating the policy
228 public ToscaServiceTemplate createPolicy(final String policyTypeName, final String policyTypeVersion,
229 final ToscaServiceTemplate body) throws PfModelRuntimeException {
230 return createPolicies(body);
234 * Creates one or more new policies.
236 * @param body the entity body of policy
237 * @return the ToscaServiceTemplate object containing the policy types that were created
238 * @throws PfModelRuntimeException on errors creating the policy
240 public ToscaServiceTemplate createPolicies(final ToscaServiceTemplate body) throws PfModelRuntimeException {
241 final var incomingServiceTemplate = new JpaToscaServiceTemplate(body);
243 // assert incoming body contains policies
244 ToscaUtils.assertPoliciesExist(incomingServiceTemplate);
246 // append the incoming fragment to the DB TOSCA service template
247 final var serviceTemplateToWrite =
248 ToscaServiceTemplateUtils.addFragment(getDefaultJpaToscaServiceTemplate(), incomingServiceTemplate);
250 final var result = serviceTemplateToWrite.validate("Policies CRUD service template.");
251 if (!result.isValid()) {
252 throw new PfModelRuntimeException(Response.Status.NOT_ACCEPTABLE, result.getResult());
255 toscaServiceTemplateRepository.save(serviceTemplateToWrite);
257 LOGGER.debug("<-appendServiceTemplateFragment: returnServiceTempalate={}", serviceTemplateToWrite);
262 * Deletes the policy matching specified name and version of both policy type and policy.
264 * @param policyTypeName the name of policy type
265 * @param policyTypeVersion the version of policy type
266 * @param policyName the name of policy
267 * @param policyVersion the version of policy
268 * @return the ToscaServiceTemplate object containing the policies that were deleted
269 * @throws PfModelRuntimeException on errors deleting the policy
271 public ToscaServiceTemplate deletePolicy(final String policyTypeName, final String policyTypeVersion,
272 final String policyName, final String policyVersion) throws PfModelRuntimeException {
273 final var policyKey = new PfConceptKey(policyName, policyVersion);
274 LOGGER.debug("->deletePolicy: name={}, version={}", policyName, policyVersion);
276 // terminate if deployed in a PdpGroup
277 pdpGroupService.assertPolicyNotDeployedInPdpGroup(policyName, policyVersion);
279 final var serviceTemplate = getDefaultJpaToscaServiceTemplate();
281 // terminate deletion if not found
282 if (!ToscaUtils.doPoliciesExist(serviceTemplate)) {
283 throw new PfModelRuntimeException(Response.Status.NOT_FOUND, "no policies found");
286 final var policyForDeletion = serviceTemplate.getTopologyTemplate().getPolicies().get(policyKey);
287 if (policyForDeletion == null) {
288 throw new PfModelRuntimeException(Response.Status.NOT_FOUND, "policy " + policyKey.getId() + NOT_FOUND);
291 // remove policy from service template and write to DB
292 serviceTemplate.getTopologyTemplate().getPolicies().getConceptMap().remove(policyKey);
293 toscaServiceTemplateRepository.save(serviceTemplate);
295 // remove the entry from the Policy table
296 policyService.deletePolicy(policyKey);
298 // prepare return service template object
299 var deletedServiceTemplate = new JpaToscaServiceTemplate();
300 deletedServiceTemplate.setTopologyTemplate(new JpaToscaTopologyTemplate());
301 deletedServiceTemplate.getTopologyTemplate().setPolicies(new JpaToscaPolicies());
302 deletedServiceTemplate.getTopologyTemplate().getPolicies().getConceptMap().put(policyKey, policyForDeletion);
304 LOGGER.debug("<-deletePolicy: key={}, serviceTemplate={}", policyKey, deletedServiceTemplate);
305 return deletedServiceTemplate.toAuthorative();
309 * Retrieves TOSCA service template with the specified version of the policy type.
311 * @param policyTypeName the name of the policy type
312 * @param policyTypeVersion the version of the policy type
313 * @return the TOSCA service template containing the specified version of the policy type
314 * @throws PfModelException on errors getting the policy type
316 private ToscaServiceTemplate getFilteredPolicyTypes(final String policyTypeName, final String policyTypeVersion)
317 throws PfModelException {
318 final var dbServiceTemplate = getDefaultJpaToscaServiceTemplate();
319 final var policyTypeFilter =
320 ToscaEntityFilter.<ToscaPolicyType>builder().name(policyTypeName).version(policyTypeVersion).build();
321 LOGGER.debug("->getFilteredPolicyTypes: filter={}, serviceTemplate={}", policyTypeFilter, dbServiceTemplate);
323 // validate that policyTypes exist in db
324 if (!ToscaUtils.doPolicyTypesExist(dbServiceTemplate)) {
325 throw new PfModelRuntimeException(Response.Status.NOT_FOUND,
326 "policy types for filter " + policyTypeFilter + DO_NOT_EXIST_MSG);
329 // fetch all polices and filter by policyType, policy name and version
330 final var serviceTemplate = new SimpleToscaProvider()
331 .getCascadedPolicyTypes(dbServiceTemplate, policyTypeName, policyTypeVersion);
332 var simpleToscaProvider = new SimpleToscaProvider();
334 List<ToscaPolicyType> filteredPolicyTypes = serviceTemplate.getPolicyTypes().toAuthorativeList();
335 filteredPolicyTypes = policyTypeFilter.filter(filteredPolicyTypes);
337 // validate that filtered policyTypes exist
338 if (CollectionUtils.isEmpty(filteredPolicyTypes)) {
339 throw new PfModelRuntimeException(Response.Status.NOT_FOUND,
340 "policy types for filter " + policyTypeFilter + DO_NOT_EXIST_MSG);
343 // prepare return service template object
344 var returnServiceTemplate = new JpaToscaServiceTemplate();
345 for (var policyType : filteredPolicyTypes) {
346 final var cascadedServiceTemplate = simpleToscaProvider
347 .getCascadedPolicyTypes(dbServiceTemplate, policyType.getName(), policyType.getVersion());
348 returnServiceTemplate =
349 ToscaServiceTemplateUtils.addFragment(returnServiceTemplate, cascadedServiceTemplate);
352 LOGGER.debug("<-getFilteredPolicyTypes: filter={}, serviceTemplate={}", policyTypeFilter,
353 returnServiceTemplate);
354 return returnServiceTemplate.toAuthorative();
359 * Retrieves TOSCA service template with the specified version of the policy.
361 * @param policyName the name of the policy
362 * @param policyVersion the version of the policy
363 * @param mode the fetch mode for policies
364 * @return the TOSCA service template containing the specified version of the policy
365 * @throws PfModelException on errors getting the policy
367 private ToscaServiceTemplate getFilteredPolicies(final String policyTypeName, final String policyTypeVersion,
368 final String policyName, final String policyVersion, final PolicyFetchMode mode) throws PfModelException {
369 final var policyFilter = ToscaTypedEntityFilter.<ToscaPolicy>builder()
370 .name(policyName).version(policyVersion).type(policyTypeName).typeVersion(policyTypeVersion).build();
371 final var dbServiceTemplate = getDefaultJpaToscaServiceTemplate();
372 LOGGER.debug("<-getFilteredPolicies: filter={}, serviceTemplate={}", policyFilter, dbServiceTemplate);
374 // validate that policies exist in db
375 if (!ToscaUtils.doPolicyTypesExist(dbServiceTemplate)) {
376 throw new PfModelRuntimeException(Response.Status.NOT_FOUND,
377 "policies for filter " + policyFilter + DO_NOT_EXIST_MSG);
381 ToscaTypedEntityFilter.LATEST_VERSION.equals(policyFilter.getVersion()) ? null : policyFilter.getVersion();
383 // fetch all polices and filter by policyType, policy name and version
384 final var simpleToscaProvider = new SimpleToscaProvider();
385 final var serviceTemplate =
386 simpleToscaProvider.getCascadedPolicies(dbServiceTemplate, policyFilter.getName(), version);
388 var filteredPolicies = serviceTemplate.getTopologyTemplate()
389 .getPolicies().toAuthorativeList();
390 filteredPolicies = policyFilter.filter(filteredPolicies);
392 // validate that filtered policies exist
393 if (CollectionUtils.isEmpty(filteredPolicies)) {
394 throw new PfModelRuntimeException(Response.Status.NOT_FOUND,
395 "policies for filter " + policyFilter + DO_NOT_EXIST_MSG);
398 // prepare return service template object
399 var returnServiceTemplate = new JpaToscaServiceTemplate();
400 for (var policy : filteredPolicies) {
401 final var cascadedServiceTemplate = simpleToscaProvider
402 .getCascadedPolicies(dbServiceTemplate, policy.getName(), policy.getVersion());
403 returnServiceTemplate =
404 ToscaServiceTemplateUtils.addFragment(returnServiceTemplate, cascadedServiceTemplate);
407 if (mode == null || PolicyFetchMode.BARE.equals(mode)) {
408 returnServiceTemplate.setPolicyTypes(null);
409 returnServiceTemplate.setDataTypes(null);
411 LOGGER.debug("<-getFilteredPolicies: filter={}, , serviceTemplate={}", policyFilter, returnServiceTemplate);
412 return returnServiceTemplate.toAuthorative();
416 * Get Service Template.
417 * @return the Service Template read from the database
419 private JpaToscaServiceTemplate getDefaultJpaToscaServiceTemplate() {
420 final var defaultServiceTemplateOpt = toscaServiceTemplateRepository
421 .findById(new PfConceptKey(JpaToscaServiceTemplate.DEFAULT_NAME, JpaToscaServiceTemplate.DEFAULT_VERSION));
422 if (defaultServiceTemplateOpt.isEmpty()) {
423 throw new PfModelRuntimeException(Response.Status.NOT_FOUND, SERVICE_TEMPLATE_NOT_FOUND_MSG);
425 LOGGER.debug("<-getDefaultJpaToscaServiceTemplate: serviceTemplate={}", defaultServiceTemplateOpt.get());
426 return defaultServiceTemplateOpt.get();