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