Fix cascaded get filtering and speed
[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         final JpaToscaServiceTemplate dbServiceTemplate = getServiceTemplate(dao);
137
138         if (!ToscaUtils.doDataTypesExist(dbServiceTemplate)) {
139             throw new PfModelRuntimeException(Response.Status.NOT_FOUND,
140                     "data types for " + name + ":" + version + DO_NOT_EXIST);
141         }
142
143         JpaToscaServiceTemplate serviceTemplate = getCascadedDataTypes(dbServiceTemplate, name, version);
144
145         LOGGER.debug("<-getDataTypes: name={}, version={}, serviceTemplate={}", name, version, serviceTemplate);
146         return serviceTemplate;
147     }
148
149     /**
150      * Get the cascaded data types for a data type name and version.
151      *
152      * @param dbServiceTemplate the service template to search for the cascaded data types
153      * @param name the data type name we are searching for
154      * @param version the data type version we are searching for
155      * @return a service template containing the cascaded data types
156      * @throws PfModelException on errors getting the data types
157      */
158     public JpaToscaServiceTemplate getCascadedDataTypes(@NonNull final JpaToscaServiceTemplate dbServiceTemplate,
159             final String name, final String version) throws PfModelException {
160
161         JpaToscaServiceTemplate serviceTemplate = new JpaToscaServiceTemplate(dbServiceTemplate);
162         serviceTemplate.setPolicyTypes(null);
163         serviceTemplate.setTopologyTemplate(null);
164
165         ToscaUtils.getEntityTree(serviceTemplate.getDataTypes(), name, version);
166
167         if (!ToscaUtils.doDataTypesExist(serviceTemplate)) {
168             throw new PfModelRuntimeException(Response.Status.NOT_FOUND,
169                     "data types for " + name + ":" + version + DO_NOT_EXIST);
170         }
171
172         for (JpaToscaDataType dataType : serviceTemplate.getDataTypes().getConceptMap().values()) {
173             Collection<PfConceptKey> referencedDataTypeKeys = dataType.getReferencedDataTypes();
174
175             for (PfConceptKey referencedDataTypeKey : referencedDataTypeKeys) {
176                 JpaToscaServiceTemplate dataTypeEntityTreeServiceTemplate = getCascadedDataTypes(dbServiceTemplate,
177                         referencedDataTypeKey.getName(), referencedDataTypeKey.getVersion());
178
179                 serviceTemplate =
180                         ToscaServiceTemplateUtils.addFragment(serviceTemplate, dataTypeEntityTreeServiceTemplate);
181             }
182         }
183         return serviceTemplate;
184     }
185
186     /**
187      * Create data types.
188      *
189      * @param dao the DAO to use to access the database
190      * @param incomingServiceTemplate the service template containing the definition of the data types to be created
191      * @return the TOSCA service template containing the created data types
192      * @throws PfModelException on errors creating data types
193      */
194     public JpaToscaServiceTemplate createDataTypes(@NonNull final PfDao dao,
195             @NonNull final JpaToscaServiceTemplate incomingServiceTemplate) throws PfModelException {
196         LOGGER.debug("->createDataTypes: incomingServiceTemplate={}", incomingServiceTemplate);
197
198         ToscaUtils.assertDataTypesExist(incomingServiceTemplate);
199
200         JpaToscaServiceTemplate writtenServiceTemplate = appendToServiceTemplate(dao, incomingServiceTemplate);
201
202         LOGGER.debug("<-createDataTypes: returnServiceTempalate={}", writtenServiceTemplate);
203         return writtenServiceTemplate;
204     }
205
206     /**
207      * Update Data types.
208      *
209      * @param dao the DAO to use to access the database
210      * @param serviceTemplate the service template containing the definition of the data types to be modified
211      * @return the TOSCA service template containing the modified data types
212      * @throws PfModelException on errors updating Data types
213      */
214     public JpaToscaServiceTemplate updateDataTypes(@NonNull final PfDao dao,
215             @NonNull final JpaToscaServiceTemplate serviceTemplate) throws PfModelException {
216         LOGGER.debug("->updateDataTypes: serviceTempalate={}", serviceTemplate);
217
218         ToscaUtils.assertDataTypesExist(serviceTemplate);
219
220         for (JpaToscaDataType dataType : serviceTemplate.getDataTypes().getAll(null)) {
221             dao.update(dataType);
222         }
223
224         // Return the created data types
225         JpaToscaDataTypes returnDataTypes = new JpaToscaDataTypes();
226
227         for (PfConceptKey dataTypeKey : serviceTemplate.getDataTypes().getConceptMap().keySet()) {
228             returnDataTypes.getConceptMap().put(dataTypeKey, dao.get(JpaToscaDataType.class, dataTypeKey));
229         }
230
231         JpaToscaServiceTemplate returnServiceTemplate = new JpaToscaServiceTemplate();
232         returnServiceTemplate.setDataTypes(returnDataTypes);
233
234         LOGGER.debug("<-updateDataTypes: returnServiceTempalate={}", returnServiceTemplate);
235         return returnServiceTemplate;
236     }
237
238     /**
239      * Delete Data types.
240      *
241      * @param dao the DAO to use to access the database
242      * @param dataTypeKey the data type key for the Data types to be deleted, if the version of the key is null, all
243      *        versions of the data type are deleted.
244      * @return the TOSCA service template containing the data types that were deleted
245      * @throws PfModelException on errors deleting data types
246      */
247     public JpaToscaServiceTemplate deleteDataType(@NonNull final PfDao dao, @NonNull final PfConceptKey dataTypeKey)
248             throws PfModelException {
249         LOGGER.debug("->deleteDataType: key={}", dataTypeKey);
250
251         JpaToscaServiceTemplate serviceTemplate = getServiceTemplate(dao);
252
253         if (!ToscaUtils.doDataTypesExist(serviceTemplate)) {
254             throw new PfModelRuntimeException(Response.Status.NOT_FOUND, "no data types found");
255         }
256
257         JpaToscaDataType dataType4Deletion = serviceTemplate.getDataTypes().get(dataTypeKey);
258         if (dataType4Deletion == null) {
259             throw new PfModelRuntimeException(Response.Status.NOT_FOUND, DATA_TYPE + dataTypeKey.getId() + NOT_FOUND);
260         }
261
262         for (JpaToscaDataType dataType : serviceTemplate.getDataTypes().getAll(null)) {
263             if (dataType.getReferencedDataTypes().contains(dataTypeKey)) {
264                 throw new PfModelRuntimeException(Response.Status.NOT_ACCEPTABLE, DATA_TYPE + dataTypeKey.getId()
265                         + " is in use, it is referenced in data type " + dataType.getId());
266             }
267         }
268
269         if (ToscaUtils.doPolicyTypesExist(serviceTemplate)) {
270             for (JpaToscaPolicyType policyType : serviceTemplate.getPolicyTypes().getAll(null)) {
271                 if (policyType.getReferencedDataTypes().contains(dataTypeKey)) {
272                     throw new PfModelRuntimeException(Response.Status.NOT_ACCEPTABLE, DATA_TYPE + dataTypeKey.getId()
273                             + " is in use, it is referenced in policy type " + policyType.getId());
274                 }
275             }
276         }
277
278         dao.delete(JpaToscaDataType.class, dataTypeKey);
279
280         LOGGER.debug("<-deleteDataType: key={}, serviceTempalate={}", dataTypeKey, serviceTemplate);
281         return serviceTemplate;
282     }
283
284     /**
285      * Get policy types.
286      *
287      * @param dao the DAO to use to access the database
288      * @param name the name of the policy type to get, set to null to get all policy types
289      * @param version the version of the policy type to get, set to null to get all versions
290      * @return the policy types found
291      * @throws PfModelException on errors getting policy types
292      */
293     public JpaToscaServiceTemplate getPolicyTypes(@NonNull final PfDao dao, final String name, final String version)
294             throws PfModelException {
295         LOGGER.debug("->getPolicyTypes: name={}, version={}", name, version);
296
297         final JpaToscaServiceTemplate dbServiceTemplate = getServiceTemplate(dao);
298
299         if (!ToscaUtils.doPolicyTypesExist(dbServiceTemplate)) {
300             throw new PfModelRuntimeException(Response.Status.NOT_FOUND,
301                     "policy types for " + name + ":" + version + DO_NOT_EXIST);
302         }
303
304         JpaToscaServiceTemplate serviceTemplate = getCascadedPolicyTypes(dbServiceTemplate, name, version);
305
306         LOGGER.debug("<-getPolicyTypes: name={}, version={}, serviceTemplate={}", name, version, serviceTemplate);
307         return serviceTemplate;
308     }
309
310     /**
311      * Get the cascaded policy types for a policy type name and version.
312      *
313      * @param dbServiceTemplate the service template to search for the cascaded policy types
314      * @param name the policy type name we are searching for
315      * @param version the policy type version we are searching for
316      * @return a service template containing the cascaded policy types
317      * @throws PfModelException on errors getting the policy types
318      */
319     public JpaToscaServiceTemplate getCascadedPolicyTypes(final JpaToscaServiceTemplate dbServiceTemplate,
320             final String name, final String version) throws PfModelException {
321
322         JpaToscaServiceTemplate serviceTemplate = new JpaToscaServiceTemplate(dbServiceTemplate);
323
324         serviceTemplate.setDataTypes(null);
325         serviceTemplate.setTopologyTemplate(null);
326
327         ToscaUtils.getEntityTree(serviceTemplate.getPolicyTypes(), name, version);
328
329         if (!ToscaUtils.doPolicyTypesExist(serviceTemplate)) {
330             throw new PfModelRuntimeException(Response.Status.NOT_FOUND,
331                     "policy types for " + name + ":" + version + DO_NOT_EXIST);
332         }
333
334         JpaToscaServiceTemplate dataTypeServiceTemplate = new JpaToscaServiceTemplate(serviceTemplate);
335         dataTypeServiceTemplate.setPolicyTypes(null);
336
337         for (JpaToscaPolicyType policyType : serviceTemplate.getPolicyTypes().getConceptMap().values()) {
338             Collection<PfConceptKey> referencedDataTypeKeys = policyType.getReferencedDataTypes();
339
340             for (PfConceptKey referencedDataTypeKey : referencedDataTypeKeys) {
341                 JpaToscaServiceTemplate dataTypeEntityTreeServiceTemplate = getCascadedDataTypes(dbServiceTemplate,
342                         referencedDataTypeKey.getName(), referencedDataTypeKey.getVersion());
343
344                 dataTypeServiceTemplate = ToscaServiceTemplateUtils.addFragment(dataTypeServiceTemplate,
345                         dataTypeEntityTreeServiceTemplate);
346             }
347         }
348
349         serviceTemplate = ToscaServiceTemplateUtils.addFragment(serviceTemplate, dataTypeServiceTemplate);
350         return serviceTemplate;
351     }
352
353     /**
354      * Create policy types.
355      *
356      * @param dao the DAO to use to access the database
357      * @param incomingServiceTemplate the service template containing the definition of the policy types to be created
358      * @return the TOSCA service template containing the created policy types
359      * @throws PfModelException on errors creating policy types
360      */
361     public JpaToscaServiceTemplate createPolicyTypes(@NonNull final PfDao dao,
362             @NonNull final JpaToscaServiceTemplate incomingServiceTemplate) throws PfModelException {
363         LOGGER.debug("->createPolicyTypes: serviceTempalate={}", incomingServiceTemplate);
364
365         ToscaUtils.assertPolicyTypesExist(incomingServiceTemplate);
366
367         JpaToscaServiceTemplate writtenServiceTemplate = appendToServiceTemplate(dao, incomingServiceTemplate);
368
369         LOGGER.debug("<-createPolicyTypes: returnServiceTempalate={}", writtenServiceTemplate);
370         return writtenServiceTemplate;
371     }
372
373     /**
374      * Update policy types.
375      *
376      * @param dao the DAO to use to access the database
377      * @param serviceTemplate the service template containing the definition of the policy types to be modified
378      * @return the TOSCA service template containing the modified policy types
379      * @throws PfModelException on errors updating policy types
380      */
381     public JpaToscaServiceTemplate updatePolicyTypes(@NonNull final PfDao dao,
382             @NonNull final JpaToscaServiceTemplate serviceTemplate) throws PfModelException {
383         LOGGER.debug("->updatePolicyTypes: serviceTempalate={}", serviceTemplate);
384
385         ToscaUtils.assertPolicyTypesExist(serviceTemplate);
386
387         // Update the data types on the policy type
388         if (ToscaUtils.doDataTypesExist(serviceTemplate)) {
389             updateDataTypes(dao, serviceTemplate);
390         }
391
392         for (JpaToscaPolicyType policyType : serviceTemplate.getPolicyTypes().getAll(null)) {
393             dao.update(policyType);
394         }
395
396         // Return the created policy types
397         JpaToscaPolicyTypes returnPolicyTypes = new JpaToscaPolicyTypes();
398
399         for (PfConceptKey policyTypeKey : serviceTemplate.getPolicyTypes().getConceptMap().keySet()) {
400             returnPolicyTypes.getConceptMap().put(policyTypeKey, dao.get(JpaToscaPolicyType.class, policyTypeKey));
401         }
402
403         JpaToscaServiceTemplate returnServiceTemplate = new JpaToscaServiceTemplate();
404         returnServiceTemplate.setPolicyTypes(returnPolicyTypes);
405
406         LOGGER.debug("<-updatePolicyTypes: returnServiceTempalate={}", returnServiceTemplate);
407         return returnServiceTemplate;
408     }
409
410     /**
411      * Delete policy types.
412      *
413      * @param dao the DAO to use to access the database
414      * @param policyTypeKey the policy type key for the policy types to be deleted, if the version of the key is null,
415      *        all versions of the policy type are deleted.
416      * @return the TOSCA service template containing the policy types that were deleted
417      * @throws PfModelException on errors deleting policy types
418      */
419     public JpaToscaServiceTemplate deletePolicyType(@NonNull final PfDao dao, @NonNull final PfConceptKey policyTypeKey)
420             throws PfModelException {
421         LOGGER.debug("->deletePolicyType: key={}", policyTypeKey);
422
423         JpaToscaServiceTemplate serviceTemplate = getServiceTemplate(dao);
424
425         if (!ToscaUtils.doPolicyTypesExist(serviceTemplate)) {
426             throw new PfModelRuntimeException(Response.Status.NOT_FOUND, "no policy types found");
427         }
428
429         JpaToscaEntityType<? extends ToscaEntity> policyType4Deletion =
430                 serviceTemplate.getPolicyTypes().get(policyTypeKey);
431         if (policyType4Deletion == null) {
432             throw new PfModelRuntimeException(Response.Status.NOT_FOUND,
433                     POLICY_TYPE + policyTypeKey.getId() + NOT_FOUND);
434         }
435
436         for (JpaToscaPolicyType policyType : serviceTemplate.getPolicyTypes().getAll(null)) {
437             Collection<JpaToscaEntityType<ToscaEntity>> ancestorList = ToscaUtils
438                     .getEntityTypeAncestors(serviceTemplate.getPolicyTypes(), policyType, new PfValidationResult());
439
440             if (ancestorList.contains(policyType4Deletion)) {
441                 throw new PfModelRuntimeException(Response.Status.NOT_ACCEPTABLE, POLICY_TYPE + policyTypeKey.getId()
442                         + " is in use, it is referenced in policy type " + policyType.getId());
443             }
444         }
445
446         if (ToscaUtils.doPoliciesExist(serviceTemplate)) {
447             for (JpaToscaPolicy policy : serviceTemplate.getTopologyTemplate().getPolicies().getAll(null)) {
448                 if (policyTypeKey.equals(policy.getType())) {
449                     throw new PfModelRuntimeException(Response.Status.NOT_ACCEPTABLE, POLICY_TYPE
450                             + policyTypeKey.getId() + " is in use, it is referenced in policy " + policy.getId());
451                 }
452             }
453         }
454
455         dao.delete(JpaToscaPolicyType.class, policyTypeKey);
456
457         LOGGER.debug("<-deletePolicyType: key={}, serviceTempalate={}", policyTypeKey, serviceTemplate);
458         return serviceTemplate;
459     }
460
461     /**
462      * Get policies.
463      *
464      * @param dao the DAO to use to access the database
465      * @param name the name of the policy to get, set to null to get all policy types
466      * @param version the version of the policy to get, set to null to get all versions
467      * @return the policies found
468      * @throws PfModelException on errors getting policies
469      */
470     public JpaToscaServiceTemplate getPolicies(@NonNull final PfDao dao, final String name, final String version)
471             throws PfModelException {
472         LOGGER.debug("->getPolicies: name={}, version={}", name, version);
473
474         JpaToscaServiceTemplate dbServiceTemplate = getServiceTemplate(dao);
475
476         if (!ToscaUtils.doPoliciesExist(dbServiceTemplate)) {
477             throw new PfModelRuntimeException(Response.Status.NOT_FOUND,
478                     "policies for " + name + ":" + version + DO_NOT_EXIST);
479         }
480
481         JpaToscaServiceTemplate returnServiceTemplate = getCascadedPolicies(dbServiceTemplate, name, version);
482
483         LOGGER.debug("<-getPolicies: name={}, version={}, serviceTemplate={}", name, version, returnServiceTemplate);
484         return returnServiceTemplate;
485     }
486
487     /**
488      * Get the cascaded policies for a policy name and version.
489      *
490      * @param dbServiceTemplate the service template to search for the cascaded policy
491      * @param name the policy name we are searching for
492      * @param version the policy version we are searching for
493      * @return a service template containing the cascaded policy
494      * @throws PfModelException on errors getting the policy
495      */
496     public JpaToscaServiceTemplate getCascadedPolicies(final JpaToscaServiceTemplate dbServiceTemplate,
497             final String name, final String version) throws PfModelException {
498
499         JpaToscaServiceTemplate serviceTemplate = new JpaToscaServiceTemplate(dbServiceTemplate);
500         serviceTemplate.setDataTypes(new JpaToscaDataTypes());
501         serviceTemplate.setPolicyTypes(new JpaToscaPolicyTypes());
502
503         ToscaUtils.getEntityTree(serviceTemplate.getTopologyTemplate().getPolicies(), name, version);
504
505         if (!ToscaUtils.doPoliciesExist(serviceTemplate)) {
506             throw new PfModelRuntimeException(Response.Status.NOT_FOUND,
507                     "policies for " + name + ":" + version + DO_NOT_EXIST);
508         }
509
510         JpaToscaServiceTemplate returnServiceTemplate = new JpaToscaServiceTemplate(serviceTemplate);
511         returnServiceTemplate.getTopologyTemplate().setPolicies(new JpaToscaPolicies());
512
513         for (JpaToscaPolicy policy : serviceTemplate.getTopologyTemplate().getPolicies().getConceptMap().values()) {
514             JpaToscaServiceTemplate referencedEntitiesServiceTemplate = getCascadedPolicyTypes(dbServiceTemplate,
515                     policy.getType().getName(), policy.getType().getVersion());
516
517             returnServiceTemplate.getTopologyTemplate().getPolicies().getConceptMap().put(policy.getKey(), policy);
518             returnServiceTemplate =
519                     ToscaServiceTemplateUtils.addFragment(returnServiceTemplate, referencedEntitiesServiceTemplate);
520         }
521
522         return returnServiceTemplate;
523     }
524
525     /**
526      * Create policies.
527      *
528      * @param dao the DAO to use to access the database
529      * @param incomingServiceTemplate the service template containing the definitions of the new policies to be created.
530      * @return the TOSCA service template containing the policy types that were created
531      * @throws PfModelException on errors creating policies
532      */
533     public JpaToscaServiceTemplate createPolicies(@NonNull final PfDao dao,
534             @NonNull final JpaToscaServiceTemplate incomingServiceTemplate) throws PfModelException {
535         LOGGER.debug("->createPolicies: incomingServiceTemplate={}", incomingServiceTemplate);
536
537         ToscaUtils.assertPoliciesExist(incomingServiceTemplate);
538
539         JpaToscaServiceTemplate writtenServiceTemplate = appendToServiceTemplate(dao, incomingServiceTemplate);
540
541         LOGGER.debug("<-createPolicies: serviceTemplate={}", writtenServiceTemplate);
542         return writtenServiceTemplate;
543     }
544
545     /**
546      * Update policies.
547      *
548      * @param dao the DAO to use to access the database
549      * @param serviceTemplate the service template containing the definitions of the policies to be updated.
550      * @return the TOSCA service template containing the policies that were updated
551      * @throws PfModelException on errors updating policies
552      */
553     public JpaToscaServiceTemplate updatePolicies(@NonNull final PfDao dao,
554             @NonNull final JpaToscaServiceTemplate serviceTemplate) throws PfModelException {
555         LOGGER.debug("->updatePolicies: serviceTempalate={}", serviceTemplate);
556
557         ToscaUtils.assertPoliciesExist(serviceTemplate);
558
559         for (JpaToscaPolicy policy : serviceTemplate.getTopologyTemplate().getPolicies().getAll(null)) {
560             verifyPolicyTypeForPolicy(dao, policy);
561             dao.update(policy);
562         }
563
564         // Return the created policy types
565         JpaToscaPolicies returnPolicies = new JpaToscaPolicies();
566         returnPolicies.setKey(serviceTemplate.getTopologyTemplate().getPolicies().getKey());
567
568         for (PfConceptKey policyKey : serviceTemplate.getTopologyTemplate().getPolicies().getConceptMap().keySet()) {
569             returnPolicies.getConceptMap().put(policyKey, dao.get(JpaToscaPolicy.class, policyKey));
570         }
571
572         serviceTemplate.getTopologyTemplate().setPolicies(returnPolicies);
573
574         LOGGER.debug("<-updatePolicies: serviceTemplate={}", serviceTemplate);
575         return serviceTemplate;
576     }
577
578     /**
579      * Delete policies.
580      *
581      * @param dao the DAO to use to access the database
582      * @param policyKey the policy key
583      * @return the TOSCA service template containing the policies that were deleted
584      * @throws PfModelException on errors deleting policies
585      */
586     public JpaToscaServiceTemplate deletePolicy(@NonNull final PfDao dao, @NonNull final PfConceptKey policyKey)
587             throws PfModelException {
588         LOGGER.debug("->deletePolicy: key={}", policyKey);
589
590         JpaToscaServiceTemplate serviceTemplate = getServiceTemplate(dao);
591
592         if (!ToscaUtils.doPoliciesExist(serviceTemplate)) {
593             throw new PfModelRuntimeException(Response.Status.NOT_FOUND, "no policies found");
594         }
595
596         JpaToscaPolicy policy4Deletion = serviceTemplate.getTopologyTemplate().getPolicies().get(policyKey);
597         if (policy4Deletion == null) {
598             throw new PfModelRuntimeException(Response.Status.NOT_FOUND, "policy " + policyKey.getId() + NOT_FOUND);
599         }
600
601         dao.delete(JpaToscaPolicy.class, policyKey);
602
603         LOGGER.debug("<-deletePolicy: key={}, serviceTempalate={}", policyKey, serviceTemplate);
604         return serviceTemplate;
605     }
606
607     /**
608      * Verify the policy type for a policy exists.
609      *
610      * @param dao the DAO to use to access policy types in the database
611      * @param policy the policy to check the policy type for
612      */
613     private void verifyPolicyTypeForPolicy(final PfDao dao, final JpaToscaPolicy policy) {
614         PfConceptKey policyTypeKey = policy.getType();
615
616         JpaToscaPolicyType policyType = null;
617
618         if (PfKey.NULL_KEY_VERSION.equals(policyTypeKey.getVersion())) {
619             policyType = getLatestPolicyTypeVersion(dao, policyTypeKey.getName());
620
621             if (policyType != null) {
622                 policy.getType().setVersion(policyType.getKey().getVersion());
623             }
624         } else {
625             policyType = dao.get(JpaToscaPolicyType.class, policyTypeKey);
626         }
627
628         if (policyType == null) {
629             String errorMessage =
630                     POLICY_TYPE + policyTypeKey.getId() + " for policy " + policy.getId() + " does not exist";
631             throw new PfModelRuntimeException(Response.Status.NOT_ACCEPTABLE, errorMessage);
632         }
633     }
634
635     /**
636      * Get the latest version of the policy type for the given policy type name.
637      *
638      * @param dao the DAO to use to access policy types in the database
639      * @param policyTypeName the name of the policy type
640      * @return the latest policy type
641      */
642     private JpaToscaPolicyType getLatestPolicyTypeVersion(final PfDao dao, final String policyTypeName) {
643         // Policy type version is not specified, get the latest version from the database
644         List<JpaToscaPolicyType> jpaPolicyTypeList = dao.getFiltered(JpaToscaPolicyType.class, policyTypeName, null);
645
646         if (CollectionUtils.isEmpty(jpaPolicyTypeList)) {
647             return null;
648         }
649
650         // Create a filter to get the latest version of the policy type
651         PfConceptFilter pfConceptFilter = PfConceptFilter.builder().version(PfConceptFilter.LATEST_VERSION).build();
652
653         // FIlter the returned policy type list
654         List<PfConcept> policyTypeKeyList = new ArrayList<>(jpaPolicyTypeList);
655         List<PfConcept> filterdPolicyTypeList = pfConceptFilter.filter(policyTypeKeyList);
656
657         // We should have one and only one returned entry
658         if (filterdPolicyTypeList.size() != 1) {
659             String errorMessage = "search for latest policy type " + policyTypeName + " returned more than one entry";
660             throw new PfModelRuntimeException(Response.Status.CONFLICT, errorMessage);
661         }
662
663         return (JpaToscaPolicyType) filterdPolicyTypeList.get(0);
664     }
665 }