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