Add safe entity delete, fix multiple entity get
[policy/models.git] / models-tosca / src / main / java / org / onap / policy / models / tosca / simple / provider / SimpleToscaProvider.java
1 /*-
2  * ============LICENSE_START=======================================================
3  *  Copyright (C) 2019-2020 Nordix Foundation.
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
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
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.
16  *
17  * SPDX-License-Identifier: Apache-2.0
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.onap.policy.models.tosca.simple.provider;
22
23 import java.util.ArrayList;
24 import java.util.Collection;
25 import java.util.List;
26
27 import javax.ws.rs.core.Response;
28
29 import lombok.NonNull;
30
31 import org.apache.commons.collections4.CollectionUtils;
32 import org.onap.policy.models.base.PfConcept;
33 import org.onap.policy.models.base.PfConceptFilter;
34 import org.onap.policy.models.base.PfConceptKey;
35 import org.onap.policy.models.base.PfKey;
36 import org.onap.policy.models.base.PfModelException;
37 import org.onap.policy.models.base.PfModelRuntimeException;
38 import org.onap.policy.models.base.PfValidationResult;
39 import org.onap.policy.models.dao.PfDao;
40 import org.onap.policy.models.tosca.authorative.concepts.ToscaEntity;
41 import org.onap.policy.models.tosca.simple.concepts.JpaToscaDataType;
42 import org.onap.policy.models.tosca.simple.concepts.JpaToscaDataTypes;
43 import org.onap.policy.models.tosca.simple.concepts.JpaToscaEntityType;
44 import org.onap.policy.models.tosca.simple.concepts.JpaToscaPolicies;
45 import org.onap.policy.models.tosca.simple.concepts.JpaToscaPolicy;
46 import org.onap.policy.models.tosca.simple.concepts.JpaToscaPolicyType;
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.utils.ToscaServiceTemplateUtils;
50 import org.onap.policy.models.tosca.utils.ToscaUtils;
51 import org.slf4j.Logger;
52 import org.slf4j.LoggerFactory;
53
54 /**
55  * This class provides the provision of information on TOSCA concepts in the database to callers.
56  *
57  * @author Liam Fallon (liam.fallon@est.tech)
58  */
59 public class SimpleToscaProvider {
60     private static final Logger LOGGER = LoggerFactory.getLogger(SimpleToscaProvider.class);
61
62     // Recurring string constants
63     private static final String DATA_TYPE = "data type ";
64     private static final String POLICY_TYPE = "policy type ";
65     private static final String SERVICE_TEMPLATE_NOT_FOUND_IN_DATABASE = "service template not found in database";
66     private static final String DO_NOT_EXIST = " do not exist";
67     private static final String NOT_FOUND = " not found";
68
69     /**
70      * Get Service Template.
71      *
72      * @param dao the DAO to use to access the database
73      * @return the service template
74      * @throws PfModelException on errors getting the service template
75      */
76     public JpaToscaServiceTemplate getServiceTemplate(@NonNull final PfDao dao) throws PfModelException {
77         LOGGER.debug("->getServiceTemplate");
78
79         JpaToscaServiceTemplate serviceTemplate = new SimpleToscaServiceTemplateProvider().read(dao);
80         if (serviceTemplate == null) {
81             throw new PfModelRuntimeException(Response.Status.NOT_FOUND, SERVICE_TEMPLATE_NOT_FOUND_IN_DATABASE);
82         }
83
84         LOGGER.debug("<-getServiceTemplate: serviceTemplate={}", serviceTemplate);
85         return serviceTemplate;
86     }
87
88     /**
89      * Append a service template fragment to the service template in the database.
90      *
91      * @param dao the DAO to use to access the database
92      * @param incomingServiceTemplateFragment the service template containing the definition of the entities to be
93      *        created
94      * @return the TOSCA service template in the database after the operation
95      * @throws PfModelException on errors appending a service template to the template in the database
96      */
97     public JpaToscaServiceTemplate appendToServiceTemplate(@NonNull final PfDao dao,
98             @NonNull final JpaToscaServiceTemplate incomingServiceTemplateFragment) throws PfModelException {
99         LOGGER.debug("->appendServiceTemplateFragment: incomingServiceTemplateFragment={}",
100                 incomingServiceTemplateFragment);
101
102         JpaToscaServiceTemplate dbServiceTemplate = new SimpleToscaServiceTemplateProvider().read(dao);
103
104         JpaToscaServiceTemplate serviceTemplateToWrite;
105         if (dbServiceTemplate == null) {
106             serviceTemplateToWrite = incomingServiceTemplateFragment;
107         } else {
108             serviceTemplateToWrite =
109                     ToscaServiceTemplateUtils.addFragment(dbServiceTemplate, incomingServiceTemplateFragment);
110         }
111
112         PfValidationResult result = serviceTemplateToWrite.validate(new PfValidationResult());
113         if (!result.isValid()) {
114             throw new PfModelRuntimeException(Response.Status.NOT_ACCEPTABLE, result.toString());
115         }
116
117         new SimpleToscaServiceTemplateProvider().write(dao, serviceTemplateToWrite);
118
119         LOGGER.debug("<-appendServiceTemplateFragment: returnServiceTempalate={}", serviceTemplateToWrite);
120         return serviceTemplateToWrite;
121     }
122
123     /**
124      * Get data types.
125      *
126      * @param dao the DAO to use to access the database
127      * @param name the name of the data type to get, set to null to get all policy types
128      * @param version the version of the data type to get, set to null to get all versions
129      * @return the data types found
130      * @throws PfModelException on errors getting data types
131      */
132     public JpaToscaServiceTemplate getDataTypes(@NonNull final PfDao dao, final String name, final String version)
133             throws PfModelException {
134         LOGGER.debug("->getDataTypes: name={}, version={}", name, version);
135
136         JpaToscaServiceTemplate serviceTemplate = getServiceTemplate(dao);
137
138         if (!ToscaUtils.doDataTypesExist(serviceTemplate)) {
139             throw new PfModelRuntimeException(Response.Status.NOT_FOUND,
140                     "data types for " + name + ":" + version + DO_NOT_EXIST);
141         }
142
143         serviceTemplate.setPolicyTypes(null);
144         serviceTemplate.setTopologyTemplate(null);
145
146         ToscaUtils.getEntityTree(serviceTemplate.getDataTypes(), name, version);
147
148         if (!ToscaUtils.doDataTypesExist(serviceTemplate)) {
149             throw new PfModelRuntimeException(Response.Status.NOT_FOUND,
150                     "data types for " + name + ":" + version + DO_NOT_EXIST);
151         }
152
153         for (JpaToscaDataType dataType : serviceTemplate.getDataTypes().getConceptMap().values()) {
154             Collection<PfConceptKey> referencedDataTypeKeys = dataType.getReferencedDataTypes();
155
156             for (PfConceptKey referencedDataTypeKey : referencedDataTypeKeys) {
157                 JpaToscaServiceTemplate dataTypeEntityTreeServiceTemplate =
158                         getDataTypes(dao, referencedDataTypeKey.getName(), referencedDataTypeKey.getVersion());
159
160                 serviceTemplate =
161                         ToscaServiceTemplateUtils.addFragment(serviceTemplate, dataTypeEntityTreeServiceTemplate);
162             }
163         }
164
165         LOGGER.debug("<-getDataTypes: name={}, version={}, serviceTemplate={}", name, version, serviceTemplate);
166         return serviceTemplate;
167     }
168
169     /**
170      * Create data types.
171      *
172      * @param dao the DAO to use to access the database
173      * @param incomingServiceTemplate the service template containing the definition of the data types to be created
174      * @return the TOSCA service template containing the created data types
175      * @throws PfModelException on errors creating data types
176      */
177     public JpaToscaServiceTemplate createDataTypes(@NonNull final PfDao dao,
178             @NonNull final JpaToscaServiceTemplate incomingServiceTemplate) throws PfModelException {
179         LOGGER.debug("->createDataTypes: incomingServiceTemplate={}", incomingServiceTemplate);
180
181         ToscaUtils.assertDataTypesExist(incomingServiceTemplate);
182
183         JpaToscaServiceTemplate writtenServiceTemplate = appendToServiceTemplate(dao, incomingServiceTemplate);
184
185         LOGGER.debug("<-createDataTypes: returnServiceTempalate={}", writtenServiceTemplate);
186         return writtenServiceTemplate;
187     }
188
189     /**
190      * Update Data types.
191      *
192      * @param dao the DAO to use to access the database
193      * @param serviceTemplate the service template containing the definition of the data types to be modified
194      * @return the TOSCA service template containing the modified data types
195      * @throws PfModelException on errors updating Data types
196      */
197     public JpaToscaServiceTemplate updateDataTypes(@NonNull final PfDao dao,
198             @NonNull final JpaToscaServiceTemplate serviceTemplate) throws PfModelException {
199         LOGGER.debug("->updateDataTypes: serviceTempalate={}", serviceTemplate);
200
201         ToscaUtils.assertDataTypesExist(serviceTemplate);
202
203         for (JpaToscaDataType dataType : serviceTemplate.getDataTypes().getAll(null)) {
204             dao.update(dataType);
205         }
206
207         // Return the created data types
208         JpaToscaDataTypes returnDataTypes = new JpaToscaDataTypes();
209
210         for (PfConceptKey dataTypeKey : serviceTemplate.getDataTypes().getConceptMap().keySet()) {
211             returnDataTypes.getConceptMap().put(dataTypeKey, dao.get(JpaToscaDataType.class, dataTypeKey));
212         }
213
214         JpaToscaServiceTemplate returnServiceTemplate = new JpaToscaServiceTemplate();
215         returnServiceTemplate.setDataTypes(returnDataTypes);
216
217         LOGGER.debug("<-updateDataTypes: returnServiceTempalate={}", returnServiceTemplate);
218         return returnServiceTemplate;
219     }
220
221     /**
222      * Delete Data types.
223      *
224      * @param dao the DAO to use to access the database
225      * @param dataTypeKey the data type key for the Data types to be deleted, if the version of the key is null, all
226      *        versions of the data type are deleted.
227      * @return the TOSCA service template containing the data types that were deleted
228      * @throws PfModelException on errors deleting data types
229      */
230     public JpaToscaServiceTemplate deleteDataType(@NonNull final PfDao dao, @NonNull final PfConceptKey dataTypeKey)
231             throws PfModelException {
232         LOGGER.debug("->deleteDataType: key={}", dataTypeKey);
233
234         JpaToscaServiceTemplate serviceTemplate = getServiceTemplate(dao);
235
236         if (!ToscaUtils.doDataTypesExist(serviceTemplate)) {
237             throw new PfModelRuntimeException(Response.Status.NOT_FOUND, "no data types found");
238         }
239
240         JpaToscaDataType dataType4Deletion = serviceTemplate.getDataTypes().get(dataTypeKey);
241         if (dataType4Deletion == null) {
242             throw new PfModelRuntimeException(Response.Status.NOT_FOUND, DATA_TYPE + dataTypeKey.getId() + NOT_FOUND);
243         }
244
245         for (JpaToscaDataType dataType : serviceTemplate.getDataTypes().getAll(null)) {
246             if (dataType.getReferencedDataTypes().contains(dataTypeKey)) {
247                 throw new PfModelRuntimeException(Response.Status.NOT_ACCEPTABLE, DATA_TYPE + dataTypeKey.getId()
248                         + " is in use, it is referenced in data type " + dataType.getId());
249             }
250         }
251
252         if (ToscaUtils.doPolicyTypesExist(serviceTemplate)) {
253             for (JpaToscaPolicyType policyType : serviceTemplate.getPolicyTypes().getAll(null)) {
254                 if (policyType.getReferencedDataTypes().contains(dataTypeKey)) {
255                     throw new PfModelRuntimeException(Response.Status.NOT_ACCEPTABLE, DATA_TYPE + dataTypeKey.getId()
256                             + " is in use, it is referenced in policy type " + policyType.getId());
257                 }
258             }
259         }
260
261         dao.delete(JpaToscaDataType.class, dataTypeKey);
262
263         LOGGER.debug("<-deleteDataType: key={}, serviceTempalate={}", dataTypeKey, serviceTemplate);
264         return serviceTemplate;
265     }
266
267     /**
268      * Get policy types.
269      *
270      * @param dao the DAO to use to access the database
271      * @param name the name of the policy type to get, set to null to get all policy types
272      * @param version the version of the policy type to get, set to null to get all versions
273      * @return the policy types found
274      * @throws PfModelException on errors getting policy types
275      */
276     public JpaToscaServiceTemplate getPolicyTypes(@NonNull final PfDao dao, final String name, final String version)
277             throws PfModelException {
278         LOGGER.debug("->getPolicyTypes: name={}, version={}", name, version);
279
280         JpaToscaServiceTemplate serviceTemplate = getServiceTemplate(dao);
281
282         serviceTemplate.setDataTypes(null);
283         serviceTemplate.setTopologyTemplate(null);
284
285         if (!ToscaUtils.doPolicyTypesExist(serviceTemplate)) {
286             throw new PfModelRuntimeException(Response.Status.NOT_FOUND,
287                     "policy types for " + name + ":" + version + DO_NOT_EXIST);
288         }
289
290         ToscaUtils.getEntityTree(serviceTemplate.getPolicyTypes(), name, version);
291
292         if (!ToscaUtils.doPolicyTypesExist(serviceTemplate)) {
293             throw new PfModelRuntimeException(Response.Status.NOT_FOUND,
294                     "policy types for " + name + ":" + version + DO_NOT_EXIST);
295         }
296
297         JpaToscaServiceTemplate dataTypeServiceTemplate = new JpaToscaServiceTemplate(serviceTemplate);
298         dataTypeServiceTemplate.setPolicyTypes(null);
299
300         for (JpaToscaPolicyType policyType : serviceTemplate.getPolicyTypes().getConceptMap().values()) {
301             Collection<PfConceptKey> referencedDataTypeKeys = policyType.getReferencedDataTypes();
302
303             for (PfConceptKey referencedDataTypeKey : referencedDataTypeKeys) {
304                 JpaToscaServiceTemplate dataTypeEntityTreeServiceTemplate =
305                         getDataTypes(dao, referencedDataTypeKey.getName(), referencedDataTypeKey.getVersion());
306
307                 dataTypeServiceTemplate = ToscaServiceTemplateUtils.addFragment(dataTypeServiceTemplate,
308                         dataTypeEntityTreeServiceTemplate);
309             }
310         }
311
312         serviceTemplate = ToscaServiceTemplateUtils.addFragment(serviceTemplate, dataTypeServiceTemplate);
313
314         LOGGER.debug("<-getPolicyTypes: name={}, version={}, serviceTemplate={}", name, version, serviceTemplate);
315         return serviceTemplate;
316     }
317
318     /**
319      * Create policy types.
320      *
321      * @param dao the DAO to use to access the database
322      * @param incomingServiceTemplate the service template containing the definition of the policy types to be created
323      * @return the TOSCA service template containing the created policy types
324      * @throws PfModelException on errors creating policy types
325      */
326     public JpaToscaServiceTemplate createPolicyTypes(@NonNull final PfDao dao,
327             @NonNull final JpaToscaServiceTemplate incomingServiceTemplate) throws PfModelException {
328         LOGGER.debug("->createPolicyTypes: serviceTempalate={}", incomingServiceTemplate);
329
330         ToscaUtils.assertPolicyTypesExist(incomingServiceTemplate);
331
332         JpaToscaServiceTemplate writtenServiceTemplate = appendToServiceTemplate(dao, incomingServiceTemplate);
333
334         LOGGER.debug("<-createPolicyTypes: returnServiceTempalate={}", writtenServiceTemplate);
335         return writtenServiceTemplate;
336     }
337
338     /**
339      * Update policy types.
340      *
341      * @param dao the DAO to use to access the database
342      * @param serviceTemplate the service template containing the definition of the policy types to be modified
343      * @return the TOSCA service template containing the modified policy types
344      * @throws PfModelException on errors updating policy types
345      */
346     public JpaToscaServiceTemplate updatePolicyTypes(@NonNull final PfDao dao,
347             @NonNull final JpaToscaServiceTemplate serviceTemplate) throws PfModelException {
348         LOGGER.debug("->updatePolicyTypes: serviceTempalate={}", serviceTemplate);
349
350         ToscaUtils.assertPolicyTypesExist(serviceTemplate);
351
352         // Update the data types on the policy type
353         if (ToscaUtils.doDataTypesExist(serviceTemplate)) {
354             updateDataTypes(dao, serviceTemplate);
355         }
356
357         for (JpaToscaPolicyType policyType : serviceTemplate.getPolicyTypes().getAll(null)) {
358             dao.update(policyType);
359         }
360
361         // Return the created policy types
362         JpaToscaPolicyTypes returnPolicyTypes = new JpaToscaPolicyTypes();
363
364         for (PfConceptKey policyTypeKey : serviceTemplate.getPolicyTypes().getConceptMap().keySet()) {
365             returnPolicyTypes.getConceptMap().put(policyTypeKey, dao.get(JpaToscaPolicyType.class, policyTypeKey));
366         }
367
368         JpaToscaServiceTemplate returnServiceTemplate = new JpaToscaServiceTemplate();
369         returnServiceTemplate.setPolicyTypes(returnPolicyTypes);
370
371         LOGGER.debug("<-updatePolicyTypes: returnServiceTempalate={}", returnServiceTemplate);
372         return returnServiceTemplate;
373     }
374
375     /**
376      * Delete policy types.
377      *
378      * @param dao the DAO to use to access the database
379      * @param policyTypeKey the policy type key for the policy types to be deleted, if the version of the key is null,
380      *        all versions of the policy type are deleted.
381      * @return the TOSCA service template containing the policy types that were deleted
382      * @throws PfModelException on errors deleting policy types
383      */
384     public JpaToscaServiceTemplate deletePolicyType(@NonNull final PfDao dao, @NonNull final PfConceptKey policyTypeKey)
385             throws PfModelException {
386         LOGGER.debug("->deletePolicyType: key={}", policyTypeKey);
387
388         JpaToscaServiceTemplate serviceTemplate = getServiceTemplate(dao);
389
390         if (!ToscaUtils.doPolicyTypesExist(serviceTemplate)) {
391             throw new PfModelRuntimeException(Response.Status.NOT_FOUND, "no policy types found");
392         }
393
394         JpaToscaEntityType<? extends ToscaEntity> policyType4Deletion =
395                 serviceTemplate.getPolicyTypes().get(policyTypeKey);
396         if (policyType4Deletion == null) {
397             throw new PfModelRuntimeException(Response.Status.NOT_FOUND,
398                     POLICY_TYPE + policyTypeKey.getId() + NOT_FOUND);
399         }
400
401         for (JpaToscaPolicyType policyType : serviceTemplate.getPolicyTypes().getAll(null)) {
402             Collection<JpaToscaEntityType<ToscaEntity>> ancestorList = ToscaUtils
403                     .getEntityTypeAncestors(serviceTemplate.getPolicyTypes(), policyType, new PfValidationResult());
404
405             if (ancestorList.contains(policyType4Deletion)) {
406                 throw new PfModelRuntimeException(Response.Status.NOT_ACCEPTABLE, POLICY_TYPE + policyTypeKey.getId()
407                         + " is in use, it is referenced in policy type " + policyType.getId());
408             }
409         }
410
411         if (ToscaUtils.doPoliciesExist(serviceTemplate)) {
412             for (JpaToscaPolicy policy : serviceTemplate.getTopologyTemplate().getPolicies().getAll(null)) {
413                 if (policyTypeKey.equals(policy.getType())) {
414                     throw new PfModelRuntimeException(Response.Status.NOT_ACCEPTABLE, POLICY_TYPE
415                             + policyTypeKey.getId() + " is in use, it is referenced in policy " + policy.getId());
416                 }
417             }
418         }
419
420         dao.delete(JpaToscaPolicyType.class, policyTypeKey);
421
422         LOGGER.debug("<-deletePolicyType: key={}, serviceTempalate={}", policyTypeKey, serviceTemplate);
423         return serviceTemplate;
424     }
425
426     /**
427      * Get policies.
428      *
429      * @param dao the DAO to use to access the database
430      * @param name the name of the policy to get, set to null to get all policy types
431      * @param version the version of the policy to get, set to null to get all versions
432      * @return the policies found
433      * @throws PfModelException on errors getting policies
434      */
435     public JpaToscaServiceTemplate getPolicies(@NonNull final PfDao dao, final String name, final String version)
436             throws PfModelException {
437         LOGGER.debug("->getPolicies: name={}, version={}", name, version);
438
439         JpaToscaServiceTemplate dbServiceTemplate = getServiceTemplate(dao);
440
441         JpaToscaServiceTemplate serviceTemplate = new JpaToscaServiceTemplate(dbServiceTemplate);
442         serviceTemplate.setDataTypes(new JpaToscaDataTypes());
443         serviceTemplate.setPolicyTypes(new JpaToscaPolicyTypes());
444
445         if (!ToscaUtils.doPoliciesExist(serviceTemplate)) {
446             throw new PfModelRuntimeException(Response.Status.NOT_FOUND,
447                     "policies for " + name + ":" + version + DO_NOT_EXIST);
448         }
449
450         ToscaUtils.getEntityTree(serviceTemplate.getTopologyTemplate().getPolicies(), name, version);
451
452         if (!ToscaUtils.doPoliciesExist(serviceTemplate)) {
453             throw new PfModelRuntimeException(Response.Status.NOT_FOUND,
454                     "policies for " + name + ":" + version + DO_NOT_EXIST);
455         }
456
457         JpaToscaServiceTemplate returnServiceTemplate = new JpaToscaServiceTemplate(serviceTemplate);
458         returnServiceTemplate.getTopologyTemplate().setPolicies(new JpaToscaPolicies());
459
460         for (JpaToscaPolicy policy : serviceTemplate.getTopologyTemplate().getPolicies().getConceptMap().values()) {
461             JpaToscaServiceTemplate referencedEntitiesServiceTemplate =
462                     getPolicyTypes(dao, policy.getType().getName(), policy.getType().getVersion());
463
464             returnServiceTemplate.getTopologyTemplate().getPolicies().getConceptMap().put(policy.getKey(), policy);
465             returnServiceTemplate =
466                     ToscaServiceTemplateUtils.addFragment(returnServiceTemplate, referencedEntitiesServiceTemplate);
467         }
468
469         LOGGER.debug("<-getPolicies: name={}, version={}, serviceTemplate={}", name, version, returnServiceTemplate);
470         return returnServiceTemplate;
471     }
472
473     /**
474      * Create policies.
475      *
476      * @param dao the DAO to use to access the database
477      * @param incomingServiceTemplate the service template containing the definitions of the new policies to be created.
478      * @return the TOSCA service template containing the policy types that were created
479      * @throws PfModelException on errors creating policies
480      */
481     public JpaToscaServiceTemplate createPolicies(@NonNull final PfDao dao,
482             @NonNull final JpaToscaServiceTemplate incomingServiceTemplate) throws PfModelException {
483         LOGGER.debug("->createPolicies: incomingServiceTemplate={}", incomingServiceTemplate);
484
485         ToscaUtils.assertPoliciesExist(incomingServiceTemplate);
486
487         JpaToscaServiceTemplate writtenServiceTemplate = appendToServiceTemplate(dao, incomingServiceTemplate);
488
489         LOGGER.debug("<-createPolicies: serviceTemplate={}", writtenServiceTemplate);
490         return writtenServiceTemplate;
491     }
492
493     /**
494      * Update policies.
495      *
496      * @param dao the DAO to use to access the database
497      * @param serviceTemplate the service template containing the definitions of the policies to be updated.
498      * @return the TOSCA service template containing the policies that were updated
499      * @throws PfModelException on errors updating policies
500      */
501     public JpaToscaServiceTemplate updatePolicies(@NonNull final PfDao dao,
502             @NonNull final JpaToscaServiceTemplate serviceTemplate) throws PfModelException {
503         LOGGER.debug("->updatePolicies: serviceTempalate={}", serviceTemplate);
504
505         ToscaUtils.assertPoliciesExist(serviceTemplate);
506
507         for (JpaToscaPolicy policy : serviceTemplate.getTopologyTemplate().getPolicies().getAll(null)) {
508             verifyPolicyTypeForPolicy(dao, policy);
509             dao.update(policy);
510         }
511
512         // Return the created policy types
513         JpaToscaPolicies returnPolicies = new JpaToscaPolicies();
514         returnPolicies.setKey(serviceTemplate.getTopologyTemplate().getPolicies().getKey());
515
516         for (PfConceptKey policyKey : serviceTemplate.getTopologyTemplate().getPolicies().getConceptMap().keySet()) {
517             returnPolicies.getConceptMap().put(policyKey, dao.get(JpaToscaPolicy.class, policyKey));
518         }
519
520         serviceTemplate.getTopologyTemplate().setPolicies(returnPolicies);
521
522         LOGGER.debug("<-updatePolicies: serviceTemplate={}", serviceTemplate);
523         return serviceTemplate;
524     }
525
526     /**
527      * Delete policies.
528      *
529      * @param dao the DAO to use to access the database
530      * @param policyKey the policy key
531      * @return the TOSCA service template containing the policies that were deleted
532      * @throws PfModelException on errors deleting policies
533      */
534     public JpaToscaServiceTemplate deletePolicy(@NonNull final PfDao dao, @NonNull final PfConceptKey policyKey)
535             throws PfModelException {
536         LOGGER.debug("->deletePolicy: key={}", policyKey);
537
538         JpaToscaServiceTemplate serviceTemplate = getServiceTemplate(dao);
539
540         if (!ToscaUtils.doPoliciesExist(serviceTemplate)) {
541             throw new PfModelRuntimeException(Response.Status.NOT_FOUND, "no policies found");
542         }
543
544         JpaToscaPolicy policy4Deletion = serviceTemplate.getTopologyTemplate().getPolicies().get(policyKey);
545         if (policy4Deletion == null) {
546             throw new PfModelRuntimeException(Response.Status.NOT_FOUND, "policy " + policyKey.getId() + NOT_FOUND);
547         }
548
549         dao.delete(JpaToscaPolicy.class, policyKey);
550
551         LOGGER.debug("<-deletePolicy: key={}, serviceTempalate={}", policyKey, serviceTemplate);
552         return serviceTemplate;
553     }
554
555     /**
556      * Verify the policy type for a policy exists.
557      *
558      * @param dao the DAO to use to access policy types in the database
559      * @param policy the policy to check the policy type for
560      */
561     private void verifyPolicyTypeForPolicy(final PfDao dao, final JpaToscaPolicy policy) {
562         PfConceptKey policyTypeKey = policy.getType();
563
564         JpaToscaPolicyType policyType = null;
565
566         if (PfKey.NULL_KEY_VERSION.equals(policyTypeKey.getVersion())) {
567             policyType = getLatestPolicyTypeVersion(dao, policyTypeKey.getName());
568
569             if (policyType != null) {
570                 policy.getType().setVersion(policyType.getKey().getVersion());
571             }
572         } else {
573             policyType = dao.get(JpaToscaPolicyType.class, policyTypeKey);
574         }
575
576         if (policyType == null) {
577             String errorMessage =
578                     POLICY_TYPE + policyTypeKey.getId() + " for policy " + policy.getId() + " does not exist";
579             throw new PfModelRuntimeException(Response.Status.NOT_ACCEPTABLE, errorMessage);
580         }
581     }
582
583     /**
584      * Get the latest version of the policy type for the given policy type name.
585      *
586      * @param dao the DAO to use to access policy types in the database
587      * @param policyTypeName the name of the policy type
588      * @return the latest policy type
589      */
590     private JpaToscaPolicyType getLatestPolicyTypeVersion(final PfDao dao, final String policyTypeName) {
591         // Policy type version is not specified, get the latest version from the database
592         List<JpaToscaPolicyType> jpaPolicyTypeList = dao.getFiltered(JpaToscaPolicyType.class, policyTypeName, null);
593
594         if (CollectionUtils.isEmpty(jpaPolicyTypeList)) {
595             return null;
596         }
597
598         // Create a filter to get the latest version of the policy type
599         PfConceptFilter pfConceptFilter = PfConceptFilter.builder().version(PfConceptFilter.LATEST_VERSION).build();
600
601         // FIlter the returned policy type list
602         List<PfConcept> policyTypeKeyList = new ArrayList<>(jpaPolicyTypeList);
603         List<PfConcept> filterdPolicyTypeList = pfConceptFilter.filter(policyTypeKeyList);
604
605         // We should have one and only one returned entry
606         if (filterdPolicyTypeList.size() != 1) {
607             String errorMessage = "search for latest policy type " + policyTypeName + " returned more than one entry";
608             throw new PfModelRuntimeException(Response.Status.CONFLICT, errorMessage);
609         }
610
611         return (JpaToscaPolicyType) filterdPolicyTypeList.get(0);
612     }
613 }