Java 17 / Spring 6 / Spring Boot 3 Upgrade
[policy/api.git] / main / src / main / java / org / onap / policy / api / main / service / ToscaServiceTemplateService.java
1 /*-
2  * ============LICENSE_START=======================================================
3  *  Copyright (C) 2022 Bell Canada. All rights reserved.
4  *  Modifications Copyright (C) 2022-2023 Nordix Foundation.
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.api.main.service;
23
24 import jakarta.ws.rs.core.Response;
25 import java.util.ArrayList;
26 import java.util.List;
27 import java.util.Optional;
28 import lombok.NonNull;
29 import lombok.RequiredArgsConstructor;
30 import org.apache.commons.collections4.CollectionUtils;
31 import org.onap.policy.api.main.repository.ToscaServiceTemplateRepository;
32 import org.onap.policy.api.main.rest.PolicyFetchMode;
33 import org.onap.policy.common.parameters.BeanValidationResult;
34 import org.onap.policy.models.base.PfConceptKey;
35 import org.onap.policy.models.base.PfModelException;
36 import org.onap.policy.models.base.PfModelRuntimeException;
37 import org.onap.policy.models.tosca.authorative.concepts.ToscaEntityFilter;
38 import org.onap.policy.models.tosca.authorative.concepts.ToscaNodeTemplate;
39 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
40 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyType;
41 import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;
42 import org.onap.policy.models.tosca.authorative.concepts.ToscaTypedEntityFilter;
43 import org.onap.policy.models.tosca.simple.concepts.JpaToscaNodeTemplate;
44 import org.onap.policy.models.tosca.simple.concepts.JpaToscaNodeTemplates;
45 import org.onap.policy.models.tosca.simple.concepts.JpaToscaNodeTypes;
46 import org.onap.policy.models.tosca.simple.concepts.JpaToscaPolicies;
47 import org.onap.policy.models.tosca.simple.concepts.JpaToscaPolicyTypes;
48 import org.onap.policy.models.tosca.simple.concepts.JpaToscaServiceTemplate;
49 import org.onap.policy.models.tosca.simple.concepts.JpaToscaTopologyTemplate;
50 import org.onap.policy.models.tosca.simple.provider.SimpleToscaProvider;
51 import org.onap.policy.models.tosca.utils.ToscaServiceTemplateUtils;
52 import org.onap.policy.models.tosca.utils.ToscaUtils;
53 import org.slf4j.Logger;
54 import org.slf4j.LoggerFactory;
55 import org.springframework.stereotype.Service;
56 import org.springframework.transaction.annotation.Transactional;
57
58 @Service
59 @Transactional
60 @RequiredArgsConstructor
61 public class ToscaServiceTemplateService {
62
63     private static final Logger LOGGER = LoggerFactory.getLogger(ToscaServiceTemplateService.class);
64
65     // Recurring string constants
66     private static final String POLICY_TYPE = "policy type ";
67     private static final String NOT_FOUND = " not found";
68     public static final String SERVICE_TEMPLATE_NOT_FOUND_MSG = "service template not found in database";
69     public static final String DO_NOT_EXIST_MSG = " do not exist";
70
71     private final ToscaServiceTemplateRepository toscaServiceTemplateRepository;
72     private final NodeTemplateService nodeTemplateService;
73     private final PdpGroupService pdpGroupService;
74     private final PolicyTypeService policyTypeService;
75     private final PolicyService policyService;
76
77     /**
78      * Retrieves a list of policy types matching specified policy type name and version.
79      *
80      * @param policyTypeName the name of policy type
81      * @param policyTypeVersion the version of policy type
82      * @return the ToscaServiceTemplate object
83      */
84     public ToscaServiceTemplate fetchPolicyTypes(final String policyTypeName, final String policyTypeVersion)
85         throws PfModelException {
86         final var policyTypeFilter =
87             ToscaEntityFilter.<ToscaPolicyType>builder().name(policyTypeName).version(policyTypeVersion).build();
88         return getFilteredPolicyTypes(policyTypeFilter);
89     }
90
91     /**
92      * Retrieves a list of policy types with the latest versions.
93      *
94      * @param policyTypeName the name of policy type
95      * @return the ToscaServiceTemplate object
96      */
97     public ToscaServiceTemplate fetchLatestPolicyTypes(final String policyTypeName) throws PfModelException {
98         final var policyTypeFilter = ToscaEntityFilter.<ToscaPolicyType>builder()
99             .name(policyTypeName).version(ToscaEntityFilter.LATEST_VERSION).build();
100         return getFilteredPolicyTypes(policyTypeFilter);
101     }
102
103     /**
104      * Creates a new policy type.
105      *
106      * @param body the entity body of policy type
107      * @return the TOSCA service template containing the created policy types
108      * @throws PfModelRuntimeException on errors creating policy types
109      */
110     public ToscaServiceTemplate createPolicyType(@NonNull final ToscaServiceTemplate body)
111         throws PfModelRuntimeException {
112         final var incomingServiceTemplate = new JpaToscaServiceTemplate(body);
113         LOGGER.debug("->createPolicyType: serviceTemplate={}", incomingServiceTemplate);
114
115         // assert incoming body contains policyTypes
116         ToscaUtils.assertPolicyTypesExist(incomingServiceTemplate);
117
118         // append the incoming fragment to the DB TOSCA service template
119         var dbServiceTemplateOpt = getDefaultJpaToscaServiceTemplateOpt();
120         JpaToscaServiceTemplate serviceTemplateToWrite;
121         serviceTemplateToWrite = dbServiceTemplateOpt.map(
122             jpaToscaServiceTemplate -> ToscaServiceTemplateUtils.addFragment(jpaToscaServiceTemplate,
123                 incomingServiceTemplate)).orElse(incomingServiceTemplate);
124
125         final var result = serviceTemplateToWrite.validate("service template");
126         if (!result.isValid()) {
127             throw new PfModelRuntimeException(Response.Status.NOT_ACCEPTABLE, result.getResult());
128         } else {
129             toscaServiceTemplateRepository.save(serviceTemplateToWrite);
130             LOGGER.debug("<-createPolicyType: writtenServiceTemplate={}", serviceTemplateToWrite);
131         }
132         return body;
133     }
134
135     /**
136      * Delete the policy type matching specified policy type name and version.
137      *
138      * @param policyTypeName the name of policy type
139      * @param policyTypeVersion the version of policy type, if the version of the key is null,
140      *                          all versions of the policy type are deleted.
141      * @return the TOSCA service template containing the policy types that were deleted
142      * @throws PfModelRuntimeException on errors deleting policy types
143      */
144     public ToscaServiceTemplate deletePolicyType(final String policyTypeName, final String policyTypeVersion)
145         throws PfModelRuntimeException {
146         final var policyTypeKey = new PfConceptKey(policyTypeName, policyTypeVersion);
147         LOGGER.debug("->deletePolicyType: name={}, version={}", policyTypeName, policyTypeVersion);
148
149         // terminate deletion if supported in a PdpGroup
150         pdpGroupService.assertPolicyTypeNotSupportedInPdpGroup(policyTypeName, policyTypeVersion);
151
152         final var serviceTemplate = getDefaultJpaToscaServiceTemplate();
153
154         // terminate deletion if not found
155         if (!ToscaUtils.doPolicyTypesExist(serviceTemplate)) {
156             throw new PfModelRuntimeException(Response.Status.NOT_FOUND, "no policy types found");
157         }
158
159         final var policyTypeForDeletion = serviceTemplate.getPolicyTypes().get(policyTypeKey);
160         if (policyTypeForDeletion == null) {
161             throw new PfModelRuntimeException(Response.Status.NOT_FOUND,
162                 POLICY_TYPE + policyTypeKey.getId() + NOT_FOUND);
163         }
164
165         final var result = new BeanValidationResult("policy types", serviceTemplate);
166
167         for (final var policyType : serviceTemplate.getPolicyTypes().getAll(null)) {
168             final var ancestorList = ToscaUtils
169                 .getEntityTypeAncestors(serviceTemplate.getPolicyTypes(), policyType, result);
170             // terminate deletion if referenced by another via derived_from property
171             if (ancestorList.contains(policyTypeForDeletion)) {
172                 throw new PfModelRuntimeException(Response.Status.NOT_ACCEPTABLE, POLICY_TYPE + policyTypeKey.getId()
173                     + " is in use, it is referenced in policy type " + policyType.getId());
174             }
175         }
176         if (ToscaUtils.doPoliciesExist(serviceTemplate)) {
177             for (final var policy : serviceTemplate.getTopologyTemplate().getPolicies().getAll(null)) {
178                 // terminate deletion if referenced by a policy
179                 if (policyTypeKey.equals(policy.getType())) {
180                     throw new PfModelRuntimeException(Response.Status.NOT_ACCEPTABLE, POLICY_TYPE
181                         + policyTypeKey.getId() + " is in use, it is referenced in policy " + policy.getId());
182                 }
183             }
184         }
185
186         // remove policyType from service template and write to DB
187         serviceTemplate.getPolicyTypes().getConceptMap().remove(policyTypeKey);
188         toscaServiceTemplateRepository.save(serviceTemplate);
189
190         // remove the entry from the Policy table
191         policyTypeService.deletePolicyType(policyTypeKey);
192
193         // prepare return service template object
194         var deletedServiceTemplate = new JpaToscaServiceTemplate();
195         deletedServiceTemplate.setPolicyTypes(new JpaToscaPolicyTypes());
196         deletedServiceTemplate.getPolicyTypes().getConceptMap().put(policyTypeKey, policyTypeForDeletion);
197
198         LOGGER.debug("<-deletePolicyType: key={}, serviceTemplate={}", policyTypeKey, deletedServiceTemplate);
199         return deletedServiceTemplate.toAuthorative();
200     }
201
202     /**
203      * Retrieves a list of policies matching specified name and version of both policy type and policy.
204      *
205      * @param policyTypeName the name of policy type
206      * @param policyTypeVersion the version of policy type
207      * @param policyName the name of policy
208      * @param policyVersion the version of 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
212      */
213     public ToscaServiceTemplate fetchPolicies(final String policyTypeName, final String policyTypeVersion,
214         final String policyName, final String policyVersion, final PolicyFetchMode mode) throws PfModelException {
215         return getFilteredPolicies(policyTypeName, policyTypeVersion, policyName, policyVersion, mode);
216     }
217
218     /**
219      * Retrieves a list of policies with the latest versions that match specified policy type id and version.
220      *
221      * @param policyTypeName the name of policy type
222      * @param policyTypeVersion the version of policy type
223      * @param policyName the name of the policy
224      * @param mode the fetch mode for policies
225      * @return the ToscaServiceTemplate object with the policies found
226      * @throws PfModelException on errors getting the policy
227      */
228     public ToscaServiceTemplate fetchLatestPolicies(final String policyTypeName, final String policyTypeVersion,
229         final String policyName, final PolicyFetchMode mode) throws PfModelException {
230         return getFilteredPolicies(policyTypeName, policyTypeVersion, policyName, ToscaTypedEntityFilter.LATEST_VERSION,
231             mode);
232     }
233
234     /**
235      * Creates one or more new policies for the same policy type name and version.
236      *
237      * @param policyTypeName the name of policy type
238      * @param policyTypeVersion the version of policy type
239      * @param body the entity body of polic(ies)
240      * @return the ToscaServiceTemplate object containing the policy types that were created
241      * @throws PfModelRuntimeException on errors creating the policy
242      */
243     public ToscaServiceTemplate createPolicy(final String policyTypeName, final String policyTypeVersion,
244         final ToscaServiceTemplate body) throws PfModelRuntimeException {
245         return createPolicies(body);
246     }
247
248     /**
249      * Creates one or more new policies.
250      *
251      * @param body the entity body of policy
252      * @return the ToscaServiceTemplate object containing the policy types that were created
253      * @throws PfModelRuntimeException on errors creating the policy
254      */
255     public ToscaServiceTemplate createPolicies(final ToscaServiceTemplate body) throws PfModelRuntimeException {
256         final var incomingServiceTemplate = new JpaToscaServiceTemplate(body);
257
258         // assert incoming body contains policies
259         ToscaUtils.assertPoliciesExist(incomingServiceTemplate);
260
261         // append the incoming fragment to the DB TOSCA service template
262         var dbServiceTemplateOpt = getDefaultJpaToscaServiceTemplateOpt();
263         JpaToscaServiceTemplate serviceTemplateToWrite;
264         serviceTemplateToWrite = dbServiceTemplateOpt.map(
265             jpaToscaServiceTemplate -> ToscaServiceTemplateUtils.addFragment(jpaToscaServiceTemplate,
266                 incomingServiceTemplate)).orElse(incomingServiceTemplate);
267
268         final var result = serviceTemplateToWrite.validate("Policies CRUD service template.");
269         if (!result.isValid()) {
270             throw new PfModelRuntimeException(Response.Status.NOT_ACCEPTABLE, result.getResult());
271         }
272
273         toscaServiceTemplateRepository.save(serviceTemplateToWrite);
274
275         LOGGER.debug("<-appendServiceTemplateFragment: returnServiceTemplate={}", serviceTemplateToWrite);
276         return body;
277     }
278
279     /**
280      * Deletes the policy matching specified name and version of both policy type and policy.
281      *
282      * @param policyTypeName the name of policy type
283      * @param policyTypeVersion the version of policy type
284      * @param policyName the name of policy
285      * @param policyVersion the version of policy
286      * @return the ToscaServiceTemplate object containing the policies that were deleted
287      * @throws PfModelRuntimeException on errors deleting the policy
288      */
289     public ToscaServiceTemplate deletePolicy(final String policyTypeName, final String policyTypeVersion,
290         final String policyName, final String policyVersion) throws PfModelRuntimeException {
291         final var policyKey = new PfConceptKey(policyName, policyVersion);
292         LOGGER.debug("->deletePolicy: name={}, version={}", policyName, policyVersion);
293
294         // terminate if deployed in a PdpGroup
295         pdpGroupService.assertPolicyNotDeployedInPdpGroup(policyName, policyVersion);
296
297         final var serviceTemplate = getDefaultJpaToscaServiceTemplate();
298
299         // terminate deletion if not found
300         if (!ToscaUtils.doPoliciesExist(serviceTemplate)) {
301             throw new PfModelRuntimeException(Response.Status.NOT_FOUND, "no policies found");
302         }
303
304         final var policyForDeletion = serviceTemplate.getTopologyTemplate().getPolicies().get(policyKey);
305         if (policyForDeletion == null) {
306             throw new PfModelRuntimeException(Response.Status.NOT_FOUND, "policy " + policyKey.getId() + NOT_FOUND);
307         }
308
309         // remove policy from service template and write to DB
310         serviceTemplate.getTopologyTemplate().getPolicies().getConceptMap().remove(policyKey);
311         toscaServiceTemplateRepository.save(serviceTemplate);
312
313         // remove the entry from the Policy table
314         policyService.deletePolicy(policyKey);
315
316         // prepare return service template object
317         var deletedServiceTemplate = new JpaToscaServiceTemplate();
318         deletedServiceTemplate.setTopologyTemplate(new JpaToscaTopologyTemplate());
319         deletedServiceTemplate.getTopologyTemplate().setPolicies(new JpaToscaPolicies());
320         deletedServiceTemplate.getTopologyTemplate().getPolicies().getConceptMap().put(policyKey, policyForDeletion);
321
322         LOGGER.debug("<-deletePolicy: key={}, serviceTemplate={}", policyKey, deletedServiceTemplate);
323         return deletedServiceTemplate.toAuthorative();
324     }
325
326     /**
327      * Retrieves TOSCA service template with the specified version of the policy type.
328      *
329      * @param policyTypeFilter the policy type filter containing name and version of the policy type
330      * @return the TOSCA service template containing the specified version of the policy type
331      * @throws PfModelException on errors getting the policy type
332      */
333     public ToscaServiceTemplate getFilteredPolicyTypes(final ToscaEntityFilter<ToscaPolicyType> policyTypeFilter)
334         throws PfModelException {
335         final var dbServiceTemplate = getDefaultJpaToscaServiceTemplate();
336         LOGGER.debug("->getFilteredPolicyTypes: filter={}, serviceTemplate={}", policyTypeFilter, dbServiceTemplate);
337
338         // validate that policyTypes exist in db
339         if (!ToscaUtils.doPolicyTypesExist(dbServiceTemplate)) {
340             throw new PfModelRuntimeException(Response.Status.NOT_FOUND,
341                 "policy types for filter " + policyTypeFilter + DO_NOT_EXIST_MSG);
342         }
343
344         var version = ToscaTypedEntityFilter.LATEST_VERSION
345             .equals(policyTypeFilter.getVersion()) ? null : policyTypeFilter.getVersion();
346         // fetch all polices and filter by policyType, policy name and version
347         final var serviceTemplate = new SimpleToscaProvider()
348             .getCascadedPolicyTypes(dbServiceTemplate, policyTypeFilter.getName(), version);
349         var simpleToscaProvider = new SimpleToscaProvider();
350
351         List<ToscaPolicyType> filteredPolicyTypes = serviceTemplate.getPolicyTypes().toAuthorativeList();
352         filteredPolicyTypes = policyTypeFilter.filter(filteredPolicyTypes);
353
354         // validate that filtered policyTypes exist
355         if (CollectionUtils.isEmpty(filteredPolicyTypes)) {
356             throw new PfModelRuntimeException(Response.Status.NOT_FOUND,
357                 "policy types for filter " + policyTypeFilter + DO_NOT_EXIST_MSG);
358         }
359
360         // prepare return service template object
361         var returnServiceTemplate = new JpaToscaServiceTemplate();
362         for (var policyType : filteredPolicyTypes) {
363             final var cascadedServiceTemplate = simpleToscaProvider
364                 .getCascadedPolicyTypes(dbServiceTemplate, policyType.getName(), policyType.getVersion());
365             returnServiceTemplate =
366                 ToscaServiceTemplateUtils.addFragment(returnServiceTemplate, cascadedServiceTemplate);
367         }
368
369         LOGGER.debug("<-getFilteredPolicyTypes: filter={}, serviceTemplate={}", policyTypeFilter,
370             returnServiceTemplate);
371         return returnServiceTemplate.toAuthorative();
372
373     }
374
375     /**
376      * Retrieves TOSCA service template with the specified version of the policy.
377      *
378      * @param policyName the name of the policy
379      * @param policyVersion the version of the policy
380      * @param mode the fetch mode for policies
381      * @return the TOSCA service template containing the specified version of the policy
382      * @throws PfModelException on errors getting the policy
383      */
384     private ToscaServiceTemplate getFilteredPolicies(final String policyTypeName, final String policyTypeVersion,
385         final String policyName, final String policyVersion, final PolicyFetchMode mode) throws PfModelException {
386         final var policyFilter = ToscaTypedEntityFilter.<ToscaPolicy>builder()
387             .name(policyName).version(policyVersion).type(policyTypeName).typeVersion(policyTypeVersion).build();
388         final var dbServiceTemplate = getDefaultJpaToscaServiceTemplate();
389         LOGGER.debug("<-getFilteredPolicies: filter={}, serviceTemplate={}", policyFilter, dbServiceTemplate);
390
391         // validate that policies exist in db
392         if (!ToscaUtils.doPolicyTypesExist(dbServiceTemplate)) {
393             throw new PfModelRuntimeException(Response.Status.NOT_FOUND,
394                 "policies for filter " + policyFilter + DO_NOT_EXIST_MSG);
395         }
396
397         final var version =
398             ToscaTypedEntityFilter.LATEST_VERSION.equals(policyFilter.getVersion()) ? null : policyFilter.getVersion();
399
400         // fetch all polices and filter by policyType, policy name and version
401         final var simpleToscaProvider = new SimpleToscaProvider();
402         final var serviceTemplate =
403             simpleToscaProvider.getCascadedPolicies(dbServiceTemplate, policyFilter.getName(), version);
404
405         var filteredPolicies = serviceTemplate.getTopologyTemplate()
406             .getPolicies().toAuthorativeList();
407         filteredPolicies = policyFilter.filter(filteredPolicies);
408
409         // validate that filtered policies exist
410         if (CollectionUtils.isEmpty(filteredPolicies)) {
411             throw new PfModelRuntimeException(Response.Status.NOT_FOUND,
412                 "policies for filter " + policyFilter + DO_NOT_EXIST_MSG);
413         }
414
415         // prepare return service template object
416         var returnServiceTemplate = new JpaToscaServiceTemplate();
417         for (var policy : filteredPolicies) {
418             final var cascadedServiceTemplate = simpleToscaProvider
419                 .getCascadedPolicies(dbServiceTemplate, policy.getName(), policy.getVersion());
420             returnServiceTemplate =
421                 ToscaServiceTemplateUtils.addFragment(returnServiceTemplate, cascadedServiceTemplate);
422         }
423
424         if (mode == null || PolicyFetchMode.BARE.equals(mode)) {
425             returnServiceTemplate.setPolicyTypes(null);
426             returnServiceTemplate.setDataTypes(null);
427         }
428         LOGGER.debug("<-getFilteredPolicies: filter={}, , serviceTemplate={}", policyFilter, returnServiceTemplate);
429         return returnServiceTemplate.toAuthorative();
430     }
431
432     /**
433      * Write a node template to the database.
434      *
435      * @param serviceTemplate the service template to be written
436      * @return the service template created by this method
437      * @throws PfModelException on errors writing the metadataSets
438      */
439     public ToscaServiceTemplate createToscaNodeTemplates(@NonNull final ToscaServiceTemplate serviceTemplate)
440         throws PfModelException {
441
442         LOGGER.debug("->write: tosca nodeTemplates={}", serviceTemplate);
443         final var incomingServiceTemplate = new JpaToscaServiceTemplate(serviceTemplate);
444
445         ToscaUtils.assertNodeTemplatesExist(incomingServiceTemplate);
446
447         Optional<JpaToscaNodeTypes> nodeTypes = Optional.ofNullable(incomingServiceTemplate.getNodeTypes());
448         for (JpaToscaNodeTemplate nodeTemplate : incomingServiceTemplate.getTopologyTemplate().getNodeTemplates()
449             .getAll(null)) {
450             // verify node types in the db if mismatch/empty entities in the template
451             if (! (nodeTypes.isPresent() && nodeTypes.get().getKeys().contains(nodeTemplate.getType()))) {
452                 nodeTemplateService.verifyNodeTypeInDbTemplate(nodeTemplate);
453             }
454         }
455         // append the incoming fragment to the DB TOSCA service template
456         final var serviceTemplateToWrite =
457             ToscaServiceTemplateUtils.addFragment(getDefaultJpaToscaServiceTemplate(), incomingServiceTemplate);
458
459         final var result = serviceTemplateToWrite.validate("service template.");
460         if (!result.isValid()) {
461             throw new PfModelRuntimeException(Response.Status.NOT_ACCEPTABLE, result.getResult());
462         }
463         toscaServiceTemplateRepository.save(serviceTemplateToWrite);
464         LOGGER.debug("<-createdToscaNodeTemplates: writtenServiceTemplate={}", serviceTemplateToWrite);
465
466         return serviceTemplate;
467     }
468
469     /**
470      * Update tosca node template.
471      *
472      * @param serviceTemplate the service template containing the definitions of the node templates to be updated.
473      * @return the TOSCA service template containing the node templates that were updated
474      * @throws PfModelRuntimeException on errors updating node templates
475      */
476     public ToscaServiceTemplate updateToscaNodeTemplates(@NonNull final ToscaServiceTemplate serviceTemplate)
477         throws PfModelException {
478         LOGGER.debug("->updateToscaNodeTemplates: serviceTemplate={}", serviceTemplate);
479         final var incomingServiceTemplate = new JpaToscaServiceTemplate(serviceTemplate);
480
481         ToscaUtils.assertNodeTemplatesExist(incomingServiceTemplate);
482         nodeTemplateService.updateToscaNodeTemplates(incomingServiceTemplate);
483
484         LOGGER.debug("<-updatedToscaNodeTemplates: serviceTemplate={}", serviceTemplate);
485         return incomingServiceTemplate.toAuthorative();
486     }
487
488
489     /**
490      * Delete a tosca node template.
491      *
492      * @param name the name of node template
493      * @param version the version of node template
494      * @return the TOSCA service template containing the node template that were deleted
495      * @throws PfModelException on errors deleting node templates
496      */
497     public ToscaServiceTemplate deleteToscaNodeTemplate(@NonNull final String name, @NonNull final String version)
498         throws PfModelException {
499         LOGGER.debug("->deleteToscaNodeTemplate: name={}, version={}", name, version);
500
501         JpaToscaServiceTemplate dbServiceTemplate = getDefaultJpaToscaServiceTemplate();
502         final var nodeTemplateKey = new PfConceptKey(name, version);
503
504         if (!ToscaUtils.doNodeTemplatesExist(dbServiceTemplate)) {
505             throw new PfModelRuntimeException(Response.Status.NOT_FOUND, "no node templates found");
506         }
507         JpaToscaNodeTemplate nodeTemplate4Deletion = dbServiceTemplate.getTopologyTemplate().getNodeTemplates()
508             .get(new PfConceptKey(name, version));
509         if (nodeTemplate4Deletion == null) {
510             throw new PfModelRuntimeException(Response.Status.NOT_FOUND, "node template " + name + ":" + version
511                 + NOT_FOUND);
512         }
513         //Verify if the node template is referenced in the metadata of created policies
514         nodeTemplateService.assertNodeTemplateNotUsedInPolicy(name, version, dbServiceTemplate);
515
516         dbServiceTemplate.getTopologyTemplate().getNodeTemplates().getConceptMap().remove(nodeTemplateKey);
517         toscaServiceTemplateRepository.save(dbServiceTemplate);
518
519         // remove the entry from the tosca node template table
520         nodeTemplateService.deleteNodeTemplate(nodeTemplateKey);
521
522         // prepare the return service template
523         var deletedServiceTemplate = new JpaToscaServiceTemplate();
524         deletedServiceTemplate.setTopologyTemplate(new JpaToscaTopologyTemplate());
525         deletedServiceTemplate.getTopologyTemplate().setNodeTemplates(new JpaToscaNodeTemplates());
526         deletedServiceTemplate.getTopologyTemplate().getNodeTemplates().getConceptMap()
527             .put(nodeTemplateKey, nodeTemplate4Deletion);
528
529         LOGGER.debug("<-deleteToscaNodeTemplate: key={}, serviceTemplate={}", nodeTemplateKey, deletedServiceTemplate);
530         return deletedServiceTemplate.toAuthorative();
531     }
532
533
534     /**
535      * Get tosca node templates.
536      *
537      * @param name the name of the node template to get, set to null to get all node templates
538      * @param version the version of the node template to get, set to null to get all versions
539      * @return the node templates with the specified key
540      * @throws PfModelException on errors getting node templates
541      */
542     public List<ToscaNodeTemplate> fetchToscaNodeTemplates(final String name, final String version)
543         throws PfModelException {
544         LOGGER.debug("->getNodeTemplate: name={}, version={}", name, version);
545         List<ToscaNodeTemplate> nodeTemplates = new ArrayList<>();
546
547         var dbServiceTemplate = getDefaultJpaToscaServiceTemplate();
548         //Return empty if no nodeTemplates present in db
549         if (!ToscaUtils.doNodeTemplatesExist(dbServiceTemplate)) {
550             return nodeTemplates;
551         }
552         var jpaNodeTemplates = new JpaToscaNodeTemplates(dbServiceTemplate.getTopologyTemplate().getNodeTemplates());
553
554         //Filter specific nodeTemplates
555         if (name != null && version != null) {
556             var filterKey = new PfConceptKey(name, version);
557             jpaNodeTemplates.getConceptMap().entrySet().removeIf(entity -> !entity.getKey().equals(filterKey));
558         }
559         jpaNodeTemplates.getConceptMap().forEach((key, value) -> nodeTemplates.add(value.toAuthorative()));
560         LOGGER.debug("<-getNodeTemplateMetadataSet: name={}, version={}, nodeTemplates={}", name, version,
561             nodeTemplates);
562
563         return nodeTemplates;
564     }
565
566
567     /**
568      * Get Service Template.
569      *
570      * @return the Service Template read from the database
571      * @throws PfModelRuntimeException if service template if not found in database.
572      */
573     public JpaToscaServiceTemplate getDefaultJpaToscaServiceTemplate() throws PfModelRuntimeException {
574         final var defaultServiceTemplateOpt = getDefaultJpaToscaServiceTemplateOpt();
575         if (defaultServiceTemplateOpt.isEmpty()) {
576             throw new PfModelRuntimeException(Response.Status.NOT_FOUND, SERVICE_TEMPLATE_NOT_FOUND_MSG);
577         }
578         LOGGER.debug("<-getDefaultJpaToscaServiceTemplate: serviceTemplate={}", defaultServiceTemplateOpt.get());
579         return defaultServiceTemplateOpt.get();
580     }
581
582     /**
583      * Get Service Template Optional object.
584      *
585      * @return the Optional object for Service Template read from the database
586      */
587     private Optional<JpaToscaServiceTemplate> getDefaultJpaToscaServiceTemplateOpt() {
588         return toscaServiceTemplateRepository
589             .findById(new PfConceptKey(JpaToscaServiceTemplate.DEFAULT_NAME, JpaToscaServiceTemplate.DEFAULT_VERSION));
590     }
591 }