Java 17 Upgrade
[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, 2022-2023 Nordix Foundation.
4  *  Modifications Copyright (C) 2020-2021 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 jakarta.ws.rs.core.Response;
25 import java.util.ArrayList;
26 import java.util.Collection;
27 import java.util.List;
28 import java.util.Map;
29 import java.util.Optional;
30 import lombok.NonNull;
31 import org.apache.commons.collections4.CollectionUtils;
32 import org.onap.policy.common.parameters.BeanValidationResult;
33 import org.onap.policy.models.base.PfConcept;
34 import org.onap.policy.models.base.PfConceptFilter;
35 import org.onap.policy.models.base.PfConceptKey;
36 import org.onap.policy.models.base.PfKey;
37 import org.onap.policy.models.base.PfModelException;
38 import org.onap.policy.models.base.PfModelRuntimeException;
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.authorative.concepts.ToscaEntityKey;
42 import org.onap.policy.models.tosca.authorative.concepts.ToscaNodeTemplate;
43 import org.onap.policy.models.tosca.simple.concepts.JpaToscaDataType;
44 import org.onap.policy.models.tosca.simple.concepts.JpaToscaDataTypes;
45 import org.onap.policy.models.tosca.simple.concepts.JpaToscaEntityType;
46 import org.onap.policy.models.tosca.simple.concepts.JpaToscaNodeTemplate;
47 import org.onap.policy.models.tosca.simple.concepts.JpaToscaNodeTemplates;
48 import org.onap.policy.models.tosca.simple.concepts.JpaToscaNodeType;
49 import org.onap.policy.models.tosca.simple.concepts.JpaToscaNodeTypes;
50 import org.onap.policy.models.tosca.simple.concepts.JpaToscaPolicies;
51 import org.onap.policy.models.tosca.simple.concepts.JpaToscaPolicy;
52 import org.onap.policy.models.tosca.simple.concepts.JpaToscaPolicyType;
53 import org.onap.policy.models.tosca.simple.concepts.JpaToscaPolicyTypes;
54 import org.onap.policy.models.tosca.simple.concepts.JpaToscaServiceTemplate;
55 import org.onap.policy.models.tosca.simple.concepts.JpaToscaTopologyTemplate;
56 import org.onap.policy.models.tosca.utils.ToscaServiceTemplateUtils;
57 import org.onap.policy.models.tosca.utils.ToscaUtils;
58 import org.slf4j.Logger;
59 import org.slf4j.LoggerFactory;
60
61 /**
62  * This class provides the provision of information on TOSCA concepts in the database to callers.
63  *
64  * @author Liam Fallon (liam.fallon@est.tech)
65  */
66 public class SimpleToscaProvider {
67     private static final Logger LOGGER = LoggerFactory.getLogger(SimpleToscaProvider.class);
68
69     // Recurring string constants
70     private static final String DATA_TYPE = "data type ";
71     private static final String POLICY_TYPE = "policy type ";
72     private static final String SERVICE_TEMPLATE_NOT_FOUND_IN_DATABASE = "service template not found in database";
73     private static final String DO_NOT_EXIST = " do not exist";
74     private static final String NOT_FOUND = " not found";
75
76     /**
77      * Get Service Template.
78      *
79      * @param dao the DAO to use to access the database
80      * @return the service template
81      * @throws PfModelException on errors getting the service template
82      */
83     public JpaToscaServiceTemplate getServiceTemplate(@NonNull final PfDao dao) throws PfModelException {
84         LOGGER.debug("->getServiceTemplate");
85
86         JpaToscaServiceTemplate serviceTemplate = new SimpleToscaServiceTemplateProvider().read(dao);
87         if (serviceTemplate == null) {
88             throw new PfModelRuntimeException(Response.Status.NOT_FOUND, SERVICE_TEMPLATE_NOT_FOUND_IN_DATABASE);
89         }
90
91         LOGGER.debug("<-getServiceTemplate: serviceTemplate={}", serviceTemplate);
92         return serviceTemplate;
93     }
94
95     /**
96      * Append a service template fragment to the service template in the database.
97      *
98      * @param dao the DAO to use to access the database
99      * @param incomingServiceTemplateFragment the service template containing the definition of the entities to be
100      *        created
101      * @return the TOSCA service template in the database after the operation
102      * @throws PfModelException on errors appending a service template to the template in the database
103      */
104     public JpaToscaServiceTemplate appendToServiceTemplate(@NonNull final PfDao dao,
105         @NonNull final JpaToscaServiceTemplate incomingServiceTemplateFragment) throws PfModelException {
106         LOGGER.debug("->appendServiceTemplateFragment: incomingServiceTemplateFragment={}",
107             incomingServiceTemplateFragment);
108
109         JpaToscaServiceTemplate dbServiceTemplate = new SimpleToscaServiceTemplateProvider().read(dao);
110
111         JpaToscaServiceTemplate serviceTemplateToWrite;
112         if (dbServiceTemplate == null) {
113             serviceTemplateToWrite = incomingServiceTemplateFragment;
114         } else {
115             serviceTemplateToWrite =
116                 ToscaServiceTemplateUtils.addFragment(dbServiceTemplate, incomingServiceTemplateFragment);
117         }
118
119         BeanValidationResult result = serviceTemplateToWrite.validate("service template");
120         if (!result.isValid()) {
121             throw new PfModelRuntimeException(Response.Status.NOT_ACCEPTABLE, result.getResult());
122         }
123
124         new SimpleToscaServiceTemplateProvider().write(dao, serviceTemplateToWrite);
125
126         LOGGER.debug("<-appendServiceTemplateFragment: returnServiceTempalate={}", serviceTemplateToWrite);
127         return serviceTemplateToWrite;
128     }
129
130     /**
131      * Delete service template.
132      *
133      * @param dao the DAO to use to access the database
134      * @return the TOSCA service template that was deleted
135      * @throws PfModelException on errors deleting the service template
136      */
137     public JpaToscaServiceTemplate deleteServiceTemplate(@NonNull final PfDao dao) throws PfModelException {
138         LOGGER.debug("->deleteServiceTemplate");
139
140         JpaToscaServiceTemplate serviceTemplate = getServiceTemplate(dao);
141
142         dao.delete(serviceTemplate);
143
144         LOGGER.debug("->deleteServiceTemplate: serviceTemplate={}", serviceTemplate);
145         return serviceTemplate;
146     }
147
148     /**
149      * Get data types.
150      *
151      * @param dao the DAO to use to access the database
152      * @param name the name of the data type to get, set to null to get all policy types
153      * @param version the version of the data type to get, set to null to get all versions
154      * @return the data types found
155      * @throws PfModelException on errors getting data types
156      */
157     public JpaToscaServiceTemplate getDataTypes(@NonNull final PfDao dao, final String name, final String version)
158         throws PfModelException {
159         LOGGER.debug("->getDataTypes: name={}, version={}", name, version);
160
161         final JpaToscaServiceTemplate dbServiceTemplate = getServiceTemplate(dao);
162
163         if (!ToscaUtils.doDataTypesExist(dbServiceTemplate)) {
164             throw new PfModelRuntimeException(Response.Status.NOT_FOUND,
165                 "data types for " + name + ":" + version + DO_NOT_EXIST);
166         }
167
168         JpaToscaServiceTemplate serviceTemplate = getCascadedDataTypes(dbServiceTemplate, name, version);
169
170         LOGGER.debug("<-getDataTypes: name={}, version={}, serviceTemplate={}", name, version, serviceTemplate);
171         return serviceTemplate;
172     }
173
174     /**
175      * Get the cascaded data types for a data type name and version.
176      *
177      * @param dbServiceTemplate the service template to search for the cascaded data types
178      * @param name the data type name we are searching for
179      * @param version the data type version we are searching for
180      * @return a service template containing the cascaded data types
181      * @throws PfModelException on errors getting the data types
182      */
183     public JpaToscaServiceTemplate getCascadedDataTypes(@NonNull final JpaToscaServiceTemplate dbServiceTemplate,
184         final String name, final String version) throws PfModelException {
185
186         var serviceTemplate = new JpaToscaServiceTemplate(dbServiceTemplate);
187         serviceTemplate.setPolicyTypes(null);
188         serviceTemplate.setTopologyTemplate(null);
189
190         ToscaUtils.getEntityTree(serviceTemplate.getDataTypes(), name, version);
191
192         if (!ToscaUtils.doDataTypesExist(serviceTemplate)) {
193             throw new PfModelRuntimeException(Response.Status.NOT_FOUND,
194                 "data types for " + name + ":" + version + DO_NOT_EXIST);
195         }
196
197         for (JpaToscaDataType dataType : serviceTemplate.getDataTypes().getConceptMap().values()) {
198             Collection<PfConceptKey> referencedDataTypeKeys = dataType.getReferencedDataTypes();
199
200             for (PfConceptKey referencedDataTypeKey : referencedDataTypeKeys) {
201                 JpaToscaServiceTemplate dataTypeEntityTreeServiceTemplate = getCascadedDataTypes(dbServiceTemplate,
202                     referencedDataTypeKey.getName(), referencedDataTypeKey.getVersion());
203
204                 serviceTemplate =
205                     ToscaServiceTemplateUtils.addFragment(serviceTemplate, dataTypeEntityTreeServiceTemplate);
206             }
207         }
208         return serviceTemplate;
209     }
210
211     /**
212      * Create data types.
213      *
214      * @param dao the DAO to use to access the database
215      * @param incomingServiceTemplate the service template containing the definition of the data types to be created
216      * @return the TOSCA service template containing the created data types
217      * @throws PfModelException on errors creating data types
218      */
219     public JpaToscaServiceTemplate createDataTypes(@NonNull final PfDao dao,
220         @NonNull final JpaToscaServiceTemplate incomingServiceTemplate) throws PfModelException {
221         LOGGER.debug("->createDataTypes: incomingServiceTemplate={}", incomingServiceTemplate);
222
223         ToscaUtils.assertDataTypesExist(incomingServiceTemplate);
224
225         JpaToscaServiceTemplate writtenServiceTemplate = appendToServiceTemplate(dao, incomingServiceTemplate);
226
227         LOGGER.debug("<-createDataTypes: writtenServiceTemplate={}", writtenServiceTemplate);
228         return incomingServiceTemplate;
229     }
230
231     /**
232      * Update Data types.
233      *
234      * @param dao the DAO to use to access the database
235      * @param serviceTemplate the service template containing the definition of the data types to be modified
236      * @return the TOSCA service template containing the modified data types
237      * @throws PfModelException on errors updating Data types
238      */
239     public JpaToscaServiceTemplate updateDataTypes(@NonNull final PfDao dao,
240         @NonNull final JpaToscaServiceTemplate serviceTemplate) throws PfModelException {
241         LOGGER.debug("->updateDataTypes: serviceTempalate={}", serviceTemplate);
242
243         ToscaUtils.assertDataTypesExist(serviceTemplate);
244
245         for (JpaToscaDataType dataType : serviceTemplate.getDataTypes().getAll(null)) {
246             dao.update(dataType);
247         }
248
249         // Return the created data types
250         var returnDataTypes = new JpaToscaDataTypes();
251
252         for (PfConceptKey dataTypeKey : serviceTemplate.getDataTypes().getConceptMap().keySet()) {
253             returnDataTypes.getConceptMap().put(dataTypeKey, dao.get(JpaToscaDataType.class, dataTypeKey));
254         }
255
256         var returnServiceTemplate = new JpaToscaServiceTemplate();
257         returnServiceTemplate.setDataTypes(returnDataTypes);
258
259         LOGGER.debug("<-updateDataTypes: returnServiceTempalate={}", returnServiceTemplate);
260         return returnServiceTemplate;
261     }
262
263     /**
264      * Delete Data types.
265      *
266      * @param dao the DAO to use to access the database
267      * @param dataTypeKey the data type key for the Data types to be deleted, if the version of the key is null, all
268      *        versions of the data type are deleted.
269      * @return the TOSCA service template containing the data types that were deleted
270      * @throws PfModelException on errors deleting data types
271      */
272     public JpaToscaServiceTemplate deleteDataType(@NonNull final PfDao dao, @NonNull final PfConceptKey dataTypeKey)
273         throws PfModelException {
274         LOGGER.debug("->deleteDataType: key={}", dataTypeKey);
275
276         JpaToscaServiceTemplate serviceTemplate = getServiceTemplate(dao);
277
278         if (!ToscaUtils.doDataTypesExist(serviceTemplate)) {
279             throw new PfModelRuntimeException(Response.Status.NOT_FOUND, "no data types found");
280         }
281
282         JpaToscaDataType dataType4Deletion = serviceTemplate.getDataTypes().get(dataTypeKey);
283         if (dataType4Deletion == null) {
284             throw new PfModelRuntimeException(Response.Status.NOT_FOUND, DATA_TYPE + dataTypeKey.getId() + NOT_FOUND);
285         }
286
287         for (JpaToscaDataType dataType : serviceTemplate.getDataTypes().getAll(null)) {
288             if (dataType.getReferencedDataTypes().contains(dataTypeKey)) {
289                 throw new PfModelRuntimeException(Response.Status.NOT_ACCEPTABLE,
290                     DATA_TYPE + dataTypeKey.getId() + " is in use, it is referenced in data type " + dataType.getId());
291             }
292         }
293
294         if (ToscaUtils.doPolicyTypesExist(serviceTemplate)) {
295             for (JpaToscaPolicyType policyType : serviceTemplate.getPolicyTypes().getAll(null)) {
296                 if (policyType.getReferencedDataTypes().contains(dataTypeKey)) {
297                     throw new PfModelRuntimeException(Response.Status.NOT_ACCEPTABLE, DATA_TYPE + dataTypeKey.getId()
298                         + " is in use, it is referenced in policy type " + policyType.getId());
299                 }
300             }
301         }
302
303         serviceTemplate.getDataTypes().getConceptMap().remove(dataTypeKey);
304         new SimpleToscaServiceTemplateProvider().write(dao, serviceTemplate);
305         dao.delete(dataType4Deletion);
306
307         var deletedServiceTemplate = new JpaToscaServiceTemplate();
308         deletedServiceTemplate.setDataTypes(new JpaToscaDataTypes());
309         deletedServiceTemplate.getDataTypes().getConceptMap().put(dataTypeKey, dataType4Deletion);
310
311         LOGGER.debug("<-deleteDataType: key={}, serviceTempalate={}", dataTypeKey, deletedServiceTemplate);
312         return deletedServiceTemplate;
313     }
314
315     /**
316      * Get policy types.
317      *
318      * @param dao the DAO to use to access the database
319      * @param name the name of the policy type to get, set to null to get all policy types
320      * @param version the version of the policy type to get, set to null to get all versions
321      * @return the policy types found
322      * @throws PfModelException on errors getting policy types
323      */
324     public JpaToscaServiceTemplate getPolicyTypes(@NonNull final PfDao dao, final String name, final String version)
325         throws PfModelException {
326         LOGGER.debug("->getPolicyTypes: name={}, version={}", name, version);
327
328         final JpaToscaServiceTemplate dbServiceTemplate = getServiceTemplate(dao);
329
330         if (!ToscaUtils.doPolicyTypesExist(dbServiceTemplate)) {
331             throw new PfModelRuntimeException(Response.Status.NOT_FOUND,
332                 "policy types for " + name + ":" + version + DO_NOT_EXIST);
333         }
334
335         JpaToscaServiceTemplate serviceTemplate = getCascadedPolicyTypes(dbServiceTemplate, name, version);
336
337         LOGGER.debug("<-getPolicyTypes: name={}, version={}, serviceTemplate={}", name, version, serviceTemplate);
338         return serviceTemplate;
339     }
340
341     /**
342      * Get the cascaded policy types for a policy type name and version.
343      *
344      * @param dbServiceTemplate the service template to search for the cascaded policy types
345      * @param name the policy type name we are searching for
346      * @param version the policy type version we are searching for
347      * @return a service template containing the cascaded policy types
348      * @throws PfModelException on errors getting the policy types
349      */
350     public JpaToscaServiceTemplate getCascadedPolicyTypes(final JpaToscaServiceTemplate dbServiceTemplate,
351         final String name, final String version) throws PfModelException {
352
353         var serviceTemplate = new JpaToscaServiceTemplate(dbServiceTemplate);
354
355         serviceTemplate.setDataTypes(null);
356         serviceTemplate.setTopologyTemplate(null);
357
358         ToscaUtils.getEntityTree(serviceTemplate.getPolicyTypes(), name, version);
359
360         if (!ToscaUtils.doPolicyTypesExist(serviceTemplate)) {
361             throw new PfModelRuntimeException(Response.Status.NOT_FOUND,
362                 "policy types for " + name + ":" + version + DO_NOT_EXIST);
363         }
364
365         var dataTypeServiceTemplate = new JpaToscaServiceTemplate(serviceTemplate);
366         dataTypeServiceTemplate.setPolicyTypes(null);
367
368         for (JpaToscaPolicyType policyType : serviceTemplate.getPolicyTypes().getConceptMap().values()) {
369             Collection<PfConceptKey> referencedDataTypeKeys = policyType.getReferencedDataTypes();
370
371             for (PfConceptKey referencedDataTypeKey : referencedDataTypeKeys) {
372                 JpaToscaServiceTemplate dataTypeEntityTreeServiceTemplate = getCascadedDataTypes(dbServiceTemplate,
373                     referencedDataTypeKey.getName(), referencedDataTypeKey.getVersion());
374
375                 dataTypeServiceTemplate =
376                     ToscaServiceTemplateUtils.addFragment(dataTypeServiceTemplate, dataTypeEntityTreeServiceTemplate);
377             }
378         }
379
380         serviceTemplate = ToscaServiceTemplateUtils.addFragment(serviceTemplate, dataTypeServiceTemplate);
381         return serviceTemplate;
382     }
383
384     /**
385      * Create policy types.
386      *
387      * @param dao the DAO to use to access the database
388      * @param incomingServiceTemplate the service template containing the definition of the policy types to be created
389      * @return the TOSCA service template containing the created policy types
390      * @throws PfModelException on errors creating policy types
391      */
392     public JpaToscaServiceTemplate createPolicyTypes(@NonNull final PfDao dao,
393         @NonNull final JpaToscaServiceTemplate incomingServiceTemplate) throws PfModelException {
394         LOGGER.debug("->createPolicyTypes: serviceTempalate={}", incomingServiceTemplate);
395
396         ToscaUtils.assertPolicyTypesExist(incomingServiceTemplate);
397
398         JpaToscaServiceTemplate writtenServiceTemplate = appendToServiceTemplate(dao, incomingServiceTemplate);
399
400         LOGGER.debug("<-createPolicyTypes: writtenServiceTemplate={}", writtenServiceTemplate);
401         return incomingServiceTemplate;
402     }
403
404     /**
405      * Update policy types.
406      *
407      * @param dao the DAO to use to access the database
408      * @param serviceTemplate the service template containing the definition of the policy types to be modified
409      * @return the TOSCA service template containing the modified policy types
410      * @throws PfModelException on errors updating policy types
411      */
412     public JpaToscaServiceTemplate updatePolicyTypes(@NonNull final PfDao dao,
413         @NonNull final JpaToscaServiceTemplate serviceTemplate) throws PfModelException {
414         LOGGER.debug("->updatePolicyTypes: serviceTempalate={}", serviceTemplate);
415
416         ToscaUtils.assertPolicyTypesExist(serviceTemplate);
417
418         // Update the data types on the policy type
419         if (ToscaUtils.doDataTypesExist(serviceTemplate)) {
420             updateDataTypes(dao, serviceTemplate);
421         }
422
423         for (JpaToscaPolicyType policyType : serviceTemplate.getPolicyTypes().getAll(null)) {
424             dao.update(policyType);
425         }
426
427         // Return the created policy types
428         var returnPolicyTypes = new JpaToscaPolicyTypes();
429
430         for (PfConceptKey policyTypeKey : serviceTemplate.getPolicyTypes().getConceptMap().keySet()) {
431             returnPolicyTypes.getConceptMap().put(policyTypeKey, dao.get(JpaToscaPolicyType.class, policyTypeKey));
432         }
433
434         var returnServiceTemplate = new JpaToscaServiceTemplate();
435         returnServiceTemplate.setPolicyTypes(returnPolicyTypes);
436
437         LOGGER.debug("<-updatePolicyTypes: returnServiceTempalate={}", returnServiceTemplate);
438         return returnServiceTemplate;
439     }
440
441     /**
442      * Delete policy types.
443      *
444      * @param dao the DAO to use to access the database
445      * @param policyTypeKey the policy type key for the policy types to be deleted, if the version of the key is null,
446      *        all versions of the policy type are deleted.
447      * @return the TOSCA service template containing the policy types that were deleted
448      * @throws PfModelException on errors deleting policy types
449      */
450     public JpaToscaServiceTemplate deletePolicyType(@NonNull final PfDao dao, @NonNull final PfConceptKey policyTypeKey)
451         throws PfModelException {
452         LOGGER.debug("->deletePolicyType: key={}", policyTypeKey);
453
454         JpaToscaServiceTemplate serviceTemplate = getServiceTemplate(dao);
455
456         if (!ToscaUtils.doPolicyTypesExist(serviceTemplate)) {
457             throw new PfModelRuntimeException(Response.Status.NOT_FOUND, "no policy types found");
458         }
459
460         JpaToscaPolicyType policyType4Deletion = serviceTemplate.getPolicyTypes().get(policyTypeKey);
461         if (policyType4Deletion == null) {
462             throw new PfModelRuntimeException(Response.Status.NOT_FOUND,
463                 POLICY_TYPE + policyTypeKey.getId() + NOT_FOUND);
464         }
465
466         var result = new BeanValidationResult("policy types", serviceTemplate);
467
468         for (JpaToscaPolicyType policyType : serviceTemplate.getPolicyTypes().getAll(null)) {
469             Collection<JpaToscaEntityType<ToscaEntity>> ancestorList = ToscaUtils
470                 .getEntityTypeAncestors(serviceTemplate.getPolicyTypes(), policyType, result);
471
472             if (ancestorList.contains(policyType4Deletion)) {
473                 throw new PfModelRuntimeException(Response.Status.NOT_ACCEPTABLE, POLICY_TYPE + policyTypeKey.getId()
474                     + " is in use, it is referenced in policy type " + policyType.getId());
475             }
476         }
477
478         if (ToscaUtils.doPoliciesExist(serviceTemplate)) {
479             for (JpaToscaPolicy policy : serviceTemplate.getTopologyTemplate().getPolicies().getAll(null)) {
480                 if (policyTypeKey.equals(policy.getType())) {
481                     throw new PfModelRuntimeException(Response.Status.NOT_ACCEPTABLE, POLICY_TYPE
482                         + policyTypeKey.getId() + " is in use, it is referenced in policy " + policy.getId());
483                 }
484             }
485         }
486
487         serviceTemplate.getPolicyTypes().getConceptMap().remove(policyTypeKey);
488         new SimpleToscaServiceTemplateProvider().write(dao, serviceTemplate);
489         dao.delete(policyType4Deletion);
490
491         var deletedServiceTemplate = new JpaToscaServiceTemplate();
492         deletedServiceTemplate.setPolicyTypes(new JpaToscaPolicyTypes());
493         deletedServiceTemplate.getPolicyTypes().getConceptMap().put(policyTypeKey, policyType4Deletion);
494
495         LOGGER.debug("<-deletePolicyType: key={}, serviceTemplate={}", policyTypeKey, deletedServiceTemplate);
496         return deletedServiceTemplate;
497     }
498
499     /**
500      * Get policies.
501      *
502      * @param dao the DAO to use to access the database
503      * @param name the name of the policy to get, set to null to get all policy types
504      * @param version the version of the policy to get, set to null to get all versions
505      * @return the policies found
506      * @throws PfModelException on errors getting policies
507      */
508     public JpaToscaServiceTemplate getPolicies(@NonNull final PfDao dao, final String name, final String version)
509         throws PfModelException {
510         LOGGER.debug("->getPolicies: name={}, version={}", name, version);
511
512         JpaToscaServiceTemplate dbServiceTemplate = getServiceTemplate(dao);
513
514         if (!ToscaUtils.doPoliciesExist(dbServiceTemplate)) {
515             throw new PfModelRuntimeException(Response.Status.NOT_FOUND,
516                 "policies for " + name + ":" + version + DO_NOT_EXIST);
517         }
518
519         JpaToscaServiceTemplate returnServiceTemplate = getCascadedPolicies(dbServiceTemplate, name, version);
520
521         LOGGER.debug("<-getPolicies: name={}, version={}, serviceTemplate={}", name, version, returnServiceTemplate);
522         return returnServiceTemplate;
523     }
524
525     /**
526      * Get the cascaded policies for a policy name and version.
527      *
528      * @param dbServiceTemplate the service template to search for the cascaded policy
529      * @param name the policy name we are searching for
530      * @param version the policy version we are searching for
531      * @return a service template containing the cascaded policy
532      * @throws PfModelException on errors getting the policy
533      */
534     public JpaToscaServiceTemplate getCascadedPolicies(final JpaToscaServiceTemplate dbServiceTemplate,
535         final String name, final String version) throws PfModelException {
536
537         var serviceTemplate = new JpaToscaServiceTemplate(dbServiceTemplate);
538         serviceTemplate.setDataTypes(new JpaToscaDataTypes());
539         serviceTemplate.setPolicyTypes(new JpaToscaPolicyTypes());
540
541         ToscaUtils.getEntityTree(serviceTemplate.getTopologyTemplate().getPolicies(), name, version);
542
543         if (!ToscaUtils.doPoliciesExist(serviceTemplate)) {
544             throw new PfModelRuntimeException(Response.Status.NOT_FOUND,
545                 "policies for " + name + ":" + version + DO_NOT_EXIST);
546         }
547
548         var returnServiceTemplate = new JpaToscaServiceTemplate(serviceTemplate);
549         returnServiceTemplate.getTopologyTemplate().setPolicies(new JpaToscaPolicies());
550
551         for (JpaToscaPolicy policy : serviceTemplate.getTopologyTemplate().getPolicies().getConceptMap().values()) {
552             JpaToscaServiceTemplate referencedEntitiesServiceTemplate =
553                 getCascadedPolicyTypes(dbServiceTemplate, policy.getType().getName(), policy.getType().getVersion());
554
555             returnServiceTemplate.getTopologyTemplate().getPolicies().getConceptMap().put(policy.getKey(), policy);
556             returnServiceTemplate =
557                 ToscaServiceTemplateUtils.addFragment(returnServiceTemplate, referencedEntitiesServiceTemplate);
558         }
559
560         return returnServiceTemplate;
561     }
562
563     /**
564      * Create policies.
565      *
566      * @param dao the DAO to use to access the database
567      * @param incomingServiceTemplate the service template containing the definitions of the new policies to be created.
568      * @return the TOSCA service template containing the policy types that were created
569      * @throws PfModelException on errors creating policies
570      */
571     public JpaToscaServiceTemplate createPolicies(@NonNull final PfDao dao,
572         @NonNull final JpaToscaServiceTemplate incomingServiceTemplate) throws PfModelException {
573         LOGGER.debug("->createPolicies: incomingServiceTemplate={}", incomingServiceTemplate);
574
575         ToscaUtils.assertPoliciesExist(incomingServiceTemplate);
576
577         JpaToscaServiceTemplate writtenServiceTemplate = appendToServiceTemplate(dao, incomingServiceTemplate);
578
579         LOGGER.debug("<-createPolicies: writtenServiceTemplate={}", writtenServiceTemplate);
580         return incomingServiceTemplate;
581     }
582
583     /**
584      * Update policies.
585      *
586      * @param dao the DAO to use to access the database
587      * @param serviceTemplate the service template containing the definitions of the policies to be updated.
588      * @return the TOSCA service template containing the policies that were updated
589      * @throws PfModelException on errors updating policies
590      */
591     public JpaToscaServiceTemplate updatePolicies(@NonNull final PfDao dao,
592         @NonNull final JpaToscaServiceTemplate serviceTemplate) throws PfModelException {
593         LOGGER.debug("->updatePolicies: serviceTempalate={}", serviceTemplate);
594
595         ToscaUtils.assertPoliciesExist(serviceTemplate);
596
597         for (JpaToscaPolicy policy : serviceTemplate.getTopologyTemplate().getPolicies().getAll(null)) {
598             verifyPolicyTypeForPolicy(dao, policy);
599             dao.update(policy);
600         }
601
602         // Return the created policy types
603         var returnPolicies = new JpaToscaPolicies();
604         returnPolicies.setKey(serviceTemplate.getTopologyTemplate().getPolicies().getKey());
605
606         for (PfConceptKey policyKey : serviceTemplate.getTopologyTemplate().getPolicies().getConceptMap().keySet()) {
607             returnPolicies.getConceptMap().put(policyKey, dao.get(JpaToscaPolicy.class, policyKey));
608         }
609
610         serviceTemplate.getTopologyTemplate().setPolicies(returnPolicies);
611
612         LOGGER.debug("<-updatePolicies: serviceTemplate={}", serviceTemplate);
613         return serviceTemplate;
614     }
615
616     /**
617      * Delete policies.
618      *
619      * @param dao the DAO to use to access the database
620      * @param policyKey the policy key
621      * @return the TOSCA service template containing the policies that were deleted
622      * @throws PfModelException on errors deleting policies
623      */
624     public JpaToscaServiceTemplate deletePolicy(@NonNull final PfDao dao, @NonNull final PfConceptKey policyKey)
625         throws PfModelException {
626         LOGGER.debug("->deletePolicy: key={}", policyKey);
627
628         JpaToscaServiceTemplate serviceTemplate = getServiceTemplate(dao);
629
630         if (!ToscaUtils.doPoliciesExist(serviceTemplate)) {
631             throw new PfModelRuntimeException(Response.Status.NOT_FOUND, "no policies found");
632         }
633
634         JpaToscaPolicy policy4Deletion = serviceTemplate.getTopologyTemplate().getPolicies().get(policyKey);
635         if (policy4Deletion == null) {
636             throw new PfModelRuntimeException(Response.Status.NOT_FOUND, "policy " + policyKey.getId() + NOT_FOUND);
637         }
638
639         serviceTemplate.getTopologyTemplate().getPolicies().getConceptMap().remove(policyKey);
640         new SimpleToscaServiceTemplateProvider().write(dao, serviceTemplate);
641         dao.delete(policy4Deletion);
642
643         var deletedServiceTemplate = new JpaToscaServiceTemplate();
644         deletedServiceTemplate.setTopologyTemplate(new JpaToscaTopologyTemplate());
645         deletedServiceTemplate.getTopologyTemplate().setPolicies(new JpaToscaPolicies());
646         deletedServiceTemplate.getTopologyTemplate().getPolicies().getConceptMap().put(policyKey, policy4Deletion);
647
648         LOGGER.debug("<-deletePolicy: key={}, serviceTempalate={}", policyKey, deletedServiceTemplate);
649         return deletedServiceTemplate;
650     }
651
652
653     /**
654      * Get metadata of tosca node templates.
655      *
656      * @param dao the DAO to use to access the database
657      * @param name the name of the nodeTemplate to get, set to null to get all node templates
658      * @param version the version of the metadataSet to get, set to null to get all versions
659      * @return the list of maps with node template key and metadata values found
660      * @throws PfModelException on errors getting metadataSets
661      */
662     public List<Map<ToscaEntityKey, Map<String, Object>>> getNodeTemplateMetadata(
663         @NonNull final PfDao dao, final String name, final String version)
664         throws PfModelException {
665         LOGGER.debug("->getNodeTemplateMetadataSet: name={}, version={}", name, version);
666
667         List<Map<ToscaEntityKey, Map<String, Object>>> metadataSets = new ArrayList<>();
668
669         JpaToscaServiceTemplate dbServiceTemplate = getServiceTemplate(dao);
670
671         //Return empty list if no node templates present in db
672         if (!ToscaUtils.doNodeTemplatesExist(dbServiceTemplate)) {
673             return metadataSets;
674         }
675         var returnServiceTemplate = new JpaToscaServiceTemplate(dbServiceTemplate);
676         List<ToscaNodeTemplate> toscaNodeTemplates = new ArrayList<>();
677         returnServiceTemplate.getTopologyTemplate()
678             .getNodeTemplates().getConceptMap().forEach((key, value) -> toscaNodeTemplates.add(value
679             .toAuthorative()));
680
681         //Filter metadataSet for specific node template
682         if (name != null && version != null) {
683             var filterKey = new ToscaEntityKey(name, version);
684             toscaNodeTemplates.removeIf(entity -> !entity.getKey().equals(filterKey));
685         }
686         toscaNodeTemplates.forEach(e -> metadataSets.add(Map.of(e.getKey(), e.getMetadata())));
687         LOGGER.debug("<-getNodeTemplateMetadataSet: name={}, version={}, metadataSets={}", name, version,
688             metadataSets);
689
690         return metadataSets;
691     }
692
693     /**
694      * Get tosca node templates.
695      *
696      * @param dao the DAO to use to access the database
697      * @param name the name of the node template to get, set to null to get all node templates
698      * @param version the version of the node template to get, set to null to get all versions
699      * @return the node templates with the specified key
700      * @throws PfModelException on errors getting node templates
701      */
702     public JpaToscaNodeTemplates getToscaNodeTemplates(@NonNull final PfDao dao, final String name,
703                                                        final String version)
704         throws PfModelException {
705         LOGGER.debug("->getNodeTemplate: name={}, version={}", name, version);
706
707         var nodeTemplates = new JpaToscaNodeTemplates();
708
709         JpaToscaServiceTemplate dbServiceTemplate = getServiceTemplate(dao);
710
711         //Return empty if no nodeTemplates present in db
712         if (!ToscaUtils.doNodeTemplatesExist(dbServiceTemplate)) {
713             return nodeTemplates;
714         }
715         var returnServiceTemplate = new JpaToscaServiceTemplate(dbServiceTemplate);
716         nodeTemplates = returnServiceTemplate.getTopologyTemplate().getNodeTemplates();
717
718         //Filter specific nodeTemplates
719         if (name != null && version != null) {
720             var filterKey = new PfConceptKey(name, version);
721             nodeTemplates.getConceptMap().entrySet().removeIf(entity -> !entity.getKey().equals(filterKey));
722         }
723         LOGGER.debug("<-getNodeTemplateMetadataSet: name={}, version={}, nodeTemplates={}", name, version,
724             nodeTemplates);
725
726         return nodeTemplates;
727     }
728
729
730     /**
731      * Update tosca node template.
732      *
733      * @param dao the DAO to use to access the database
734      * @param serviceTemplate the service template containing the definitions of the node templates to be updated.
735      * @return the TOSCA service template containing the node templates that were updated
736      * @throws PfModelRuntimeException on errors updating node templates
737      */
738     public JpaToscaServiceTemplate updateToscaNodeTemplates(@NonNull final PfDao dao,
739                                                             @NonNull final JpaToscaServiceTemplate serviceTemplate)
740         throws PfModelException {
741         LOGGER.debug("->updateToscaNodeTemplates: serviceTemplate={}", serviceTemplate);
742
743         ToscaUtils.assertNodeTemplatesExist(serviceTemplate);
744         for (JpaToscaNodeTemplate nodeTemplate : serviceTemplate.getTopologyTemplate().getNodeTemplates()
745             .getAll(null)) {
746
747             //verify if the node template is referenced in the metadata of created policies
748             assertNodeTemplateNotUsedInPolicy(dao, nodeTemplate.getName(), nodeTemplate.getVersion());
749             verifyNodeTypeInDbTemplate(dao, nodeTemplate);
750
751             dao.update(nodeTemplate);
752         }
753         // Return the service template with updated node templates
754         var updatedNodeTemplates = new JpaToscaNodeTemplates();
755         updatedNodeTemplates.setKey(serviceTemplate.getTopologyTemplate().getNodeTemplates().getKey());
756
757         for (PfConceptKey metadataSetKey : serviceTemplate.getTopologyTemplate().getNodeTemplates().getConceptMap()
758             .keySet()) {
759             updatedNodeTemplates.getConceptMap().put(metadataSetKey, dao.get(JpaToscaNodeTemplate.class,
760                 metadataSetKey));
761         }
762         serviceTemplate.getTopologyTemplate().setNodeTemplates(updatedNodeTemplates);
763
764         LOGGER.debug("<-updatedToscaNodeTemplates: serviceTemplate={}", serviceTemplate);
765         return serviceTemplate;
766     }
767
768     /**
769      * Delete a tosca node template.
770      *
771      * @param dao the DAO to use to access the database
772      * @param nodeTemplateKey the node template key
773      * @return the TOSCA service template containing the node templates that were deleted
774      * @throws PfModelException on errors deleting node templates
775      */
776     public JpaToscaServiceTemplate deleteToscaNodeTemplate(@NonNull final PfDao dao,
777                                                            @NonNull final PfConceptKey nodeTemplateKey)
778         throws PfModelException {
779         LOGGER.debug("->deleteToscaNodeTemplate: key={}", nodeTemplateKey);
780
781         JpaToscaServiceTemplate dbServiceTemplate = getServiceTemplate(dao);
782
783         if (!ToscaUtils.doNodeTemplatesExist(dbServiceTemplate)) {
784             throw new PfModelRuntimeException(Response.Status.NOT_FOUND, "no node templates found");
785         }
786         JpaToscaNodeTemplate nodeTemplate4Deletion = dbServiceTemplate.getTopologyTemplate().getNodeTemplates()
787             .get(nodeTemplateKey);
788         if (nodeTemplate4Deletion == null) {
789             throw new PfModelRuntimeException(Response.Status.NOT_FOUND, "node template " + nodeTemplateKey.getId()
790                 + NOT_FOUND);
791         }
792
793         //Verify if the node template is referenced in the metadata of created policies
794         assertNodeTemplateNotUsedInPolicy(dao, nodeTemplateKey.getName(), nodeTemplateKey.getVersion());
795
796         dbServiceTemplate.getTopologyTemplate().getNodeTemplates().getConceptMap().remove(nodeTemplateKey);
797         new SimpleToscaServiceTemplateProvider().write(dao, dbServiceTemplate);
798         dao.delete(nodeTemplate4Deletion);
799
800         var deletedServiceTemplate = new JpaToscaServiceTemplate();
801         deletedServiceTemplate.setTopologyTemplate(new JpaToscaTopologyTemplate());
802         deletedServiceTemplate.getTopologyTemplate().setNodeTemplates(new JpaToscaNodeTemplates());
803         deletedServiceTemplate.getTopologyTemplate().getNodeTemplates().getConceptMap()
804             .put(nodeTemplateKey, nodeTemplate4Deletion);
805
806         LOGGER.debug("<-deleteToscaNodeTemplate: key={}, serviceTemplate={}", nodeTemplateKey, deletedServiceTemplate);
807         return deletedServiceTemplate;
808     }
809
810     /**
811      * Write a node template to the database.
812      *
813      * @param dao the DAO to use to access the database
814      * @param serviceTemplate the service template to be written
815      * @return the service template created by this method
816      * @throws PfModelException on errors writing the metadataSets
817      */
818     public JpaToscaServiceTemplate createToscaNodeTemplates(@NonNull final PfDao dao,
819                                                             @NonNull final JpaToscaServiceTemplate serviceTemplate)
820         throws PfModelException {
821
822         LOGGER.debug("->write: tosca nodeTemplates={}", serviceTemplate);
823
824         ToscaUtils.assertNodeTemplatesExist(serviceTemplate);
825
826         Optional<JpaToscaNodeTypes> nodeTypes = Optional.ofNullable(serviceTemplate.getNodeTypes());
827         for (JpaToscaNodeTemplate nodeTemplate : serviceTemplate.getTopologyTemplate().getNodeTemplates()
828             .getAll(null)) {
829
830             // verify node types in the db if mismatch/empty entities in the template
831             if (! (nodeTypes.isPresent() && nodeTypes.get().getKeys().contains(nodeTemplate.getType()))) {
832                 verifyNodeTypeInDbTemplate(dao, nodeTemplate);
833             }
834         }
835         JpaToscaServiceTemplate writtenServiceTemplate = appendToServiceTemplate(dao, serviceTemplate);
836         LOGGER.debug("<-createdToscaNodeTemplates: writtenServiceTemplate={}", writtenServiceTemplate);
837
838         return serviceTemplate;
839     }
840
841     /**
842      * Verify the policy type for a policy exists.
843      *
844      * @param dao the DAO to use to access policy types in the database
845      * @param policy the policy to check the policy type for
846      */
847     private void verifyPolicyTypeForPolicy(final PfDao dao, final JpaToscaPolicy policy) {
848         PfConceptKey policyTypeKey = policy.getType();
849
850         JpaToscaPolicyType policyType = null;
851
852         if (PfKey.NULL_KEY_VERSION.equals(policyTypeKey.getVersion())) {
853             policyType = getLatestPolicyTypeVersion(dao, policyTypeKey.getName());
854
855             if (policyType != null) {
856                 policy.getType().setVersion(policyType.getKey().getVersion());
857             }
858         } else {
859             policyType = dao.get(JpaToscaPolicyType.class, policyTypeKey);
860         }
861
862         if (policyType == null) {
863             String errorMessage =
864                 POLICY_TYPE + policyTypeKey.getId() + " for policy " + policy.getId() + " does not exist";
865             throw new PfModelRuntimeException(Response.Status.NOT_ACCEPTABLE, errorMessage);
866         }
867     }
868
869     /**
870      * Verify the node type for a toscaNodeTemplate metadataSet.
871      *
872      * @param dao the DAO to use to access toscaNodeTemplate types in the database
873      * @param toscaNodeTemplate the toscaNodeTemplate to check the toscaNodeTemplate type for
874      */
875     private void verifyNodeTypeInDbTemplate(final PfDao dao, final JpaToscaNodeTemplate toscaNodeTemplate) throws
876         PfModelException {
877         PfConceptKey nodeTypeKey = toscaNodeTemplate.getType();
878
879         JpaToscaNodeType nodeType = null;
880
881         nodeType = dao.get(JpaToscaNodeType.class, nodeTypeKey);
882
883         if (nodeType == null) {
884             String errorMessage =
885                 "NODE_TYPE " + nodeTypeKey + " for toscaNodeTemplate " + toscaNodeTemplate.getId()
886                     + " does not exist";
887             throw new PfModelException(Response.Status.NOT_ACCEPTABLE, errorMessage);
888         }
889     }
890
891     /**
892      * Get the latest version of the policy type for the given policy type name.
893      *
894      * @param dao the DAO to use to access policy types in the database
895      * @param policyTypeName the name of the policy type
896      * @return the latest policy type
897      */
898     private JpaToscaPolicyType getLatestPolicyTypeVersion(final PfDao dao, final String policyTypeName) {
899         // Policy type version is not specified, get the latest version from the database
900         List<JpaToscaPolicyType> jpaPolicyTypeList = dao.getFiltered(JpaToscaPolicyType.class, policyTypeName, null);
901
902         if (CollectionUtils.isEmpty(jpaPolicyTypeList)) {
903             return null;
904         }
905
906         // Create a filter to get the latest version of the policy type
907         var pfConceptFilter = PfConceptFilter.builder().version(PfConceptFilter.LATEST_VERSION).build();
908
909         // FIlter the returned policy type list
910         List<PfConcept> policyTypeKeyList = new ArrayList<>(jpaPolicyTypeList);
911         List<PfConcept> filterdPolicyTypeList = pfConceptFilter.filter(policyTypeKeyList);
912
913         // We should have one and only one returned entry
914         if (filterdPolicyTypeList.size() != 1) {
915             String errorMessage = "search for latest policy type " + policyTypeName + " returned more than one entry";
916             throw new PfModelRuntimeException(Response.Status.CONFLICT, errorMessage);
917         }
918
919         return (JpaToscaPolicyType) filterdPolicyTypeList.get(0);
920     }
921
922     /**
923      * Assert that the node template is not referenced in any Tosca policy.
924      *
925      * @param name the name of node template
926      * @param version the version of node template
927      * @throws PfModelException if node template referenced in a policy
928      */
929     private void assertNodeTemplateNotUsedInPolicy(PfDao dao, String name, String version)
930         throws PfModelException {
931         JpaToscaServiceTemplate dbTemplate;
932         try {
933             //Retrieve all the policies from db, return if policies doesn't exist
934             dbTemplate = getPolicies(dao, null, null);
935         } catch (PfModelRuntimeException e) {
936             LOGGER.debug("Could not verify the node template reference in created policies ", e);
937             return;
938         }
939         for (JpaToscaPolicy policy : dbTemplate.getTopologyTemplate().getPolicies().getConceptMap().values()) {
940             if (policy.getMetadata().getOrDefault("metadataSetName", "").equals(name)
941                 && policy.getMetadata().getOrDefault("metadataSetVersion", "").equals(version)) {
942                 throw new PfModelException(Response.Status.NOT_ACCEPTABLE,
943                     "Node template is in use, it is referenced in Tosca Policy " + policy.getName() + " version "
944                         + policy.getVersion());
945             }
946         }
947     }
948 }