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