508b4706082906330156a4902b76fae68bf6677f
[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.LinkedHashMap;
25 import java.util.List;
26 import java.util.Map;
27
28 import javax.ws.rs.core.Response;
29
30 import lombok.NonNull;
31
32 import org.apache.commons.collections4.CollectionUtils;
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.simple.concepts.JpaToscaDataType;
41 import org.onap.policy.models.tosca.simple.concepts.JpaToscaDataTypes;
42 import org.onap.policy.models.tosca.simple.concepts.JpaToscaPolicies;
43 import org.onap.policy.models.tosca.simple.concepts.JpaToscaPolicy;
44 import org.onap.policy.models.tosca.simple.concepts.JpaToscaPolicyType;
45 import org.onap.policy.models.tosca.simple.concepts.JpaToscaPolicyTypes;
46 import org.onap.policy.models.tosca.simple.concepts.JpaToscaServiceTemplate;
47 import org.onap.policy.models.tosca.simple.concepts.JpaToscaTopologyTemplate;
48 import org.onap.policy.models.tosca.utils.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     /**
61      * Get data types.
62      *
63      * @param dao the DAO to use to access the database
64      * @param name the name of the data type to get, set to null to get all policy types
65      * @param version the version of the data type to get, set to null to get all versions
66      * @return the data types found
67      * @throws PfModelException on errors getting data types
68      */
69     public JpaToscaServiceTemplate getDataTypes(@NonNull final PfDao dao, final String name, final String version)
70             throws PfModelException {
71         LOGGER.debug("->getDataTypes: name={}, version={}", name, version);
72
73         // Create the structure of the TOSCA service template to contain the data type
74         JpaToscaServiceTemplate serviceTemplate = new JpaToscaServiceTemplate();
75         serviceTemplate.setDataTypes(new JpaToscaDataTypes());
76
77         // Add the data type to the TOSCA service template
78         List<JpaToscaDataType> jpaDataTypeList = dao.getFiltered(JpaToscaDataType.class, name, version);
79         serviceTemplate.getDataTypes().getConceptMap().putAll(asConceptMap(jpaDataTypeList));
80
81         LOGGER.debug("<-getDataTypes: name={}, version={}, serviceTemplate={}", name, version, serviceTemplate);
82         return serviceTemplate;
83     }
84
85     /**
86      * Create data types.
87      *
88      * @param dao the DAO to use to access the database
89      * @param serviceTemplate the service template containing the definition of the data types to be created
90      * @return the TOSCA service template containing the created data types
91      * @throws PfModelException on errors creating data types
92      */
93     public JpaToscaServiceTemplate createDataTypes(@NonNull final PfDao dao,
94             @NonNull final JpaToscaServiceTemplate serviceTemplate) throws PfModelException {
95         LOGGER.debug("->createDataTypes: serviceTempalate={}", serviceTemplate);
96
97         ToscaUtils.assertDataTypesExist(serviceTemplate);
98
99         for (JpaToscaDataType dataType : serviceTemplate.getDataTypes().getAll(null)) {
100             dao.create(dataType);
101         }
102
103         // Return the created Data types
104         JpaToscaDataTypes returnDataTypes = new JpaToscaDataTypes();
105
106         for (PfConceptKey dataTypeKey : serviceTemplate.getDataTypes().getConceptMap().keySet()) {
107             returnDataTypes.getConceptMap().put(dataTypeKey, dao.get(JpaToscaDataType.class, dataTypeKey));
108         }
109
110         JpaToscaServiceTemplate returnServiceTemplate = new JpaToscaServiceTemplate();
111         returnServiceTemplate.setDataTypes(returnDataTypes);
112
113         LOGGER.debug("<-createDataTypes: returnServiceTempalate={}", returnServiceTemplate);
114         return returnServiceTemplate;
115     }
116
117     /**
118      * Update Data types.
119      *
120      * @param dao the DAO to use to access the database
121      * @param serviceTemplate the service template containing the definition of the data types to be modified
122      * @return the TOSCA service template containing the modified data types
123      * @throws PfModelException on errors updating Data types
124      */
125     public JpaToscaServiceTemplate updateDataTypes(@NonNull final PfDao dao,
126             @NonNull final JpaToscaServiceTemplate serviceTemplate) throws PfModelException {
127         LOGGER.debug("->updateDataTypes: serviceTempalate={}", serviceTemplate);
128
129         ToscaUtils.assertDataTypesExist(serviceTemplate);
130
131         for (JpaToscaDataType dataType : serviceTemplate.getDataTypes().getAll(null)) {
132             dao.update(dataType);
133         }
134
135         // Return the created data types
136         JpaToscaDataTypes returnDataTypes = new JpaToscaDataTypes();
137
138         for (PfConceptKey dataTypeKey : serviceTemplate.getDataTypes().getConceptMap().keySet()) {
139             returnDataTypes.getConceptMap().put(dataTypeKey, dao.get(JpaToscaDataType.class, dataTypeKey));
140         }
141
142         JpaToscaServiceTemplate returnServiceTemplate = new JpaToscaServiceTemplate();
143         returnServiceTemplate.setDataTypes(returnDataTypes);
144
145         LOGGER.debug("<-updateDataTypes: returnServiceTempalate={}", returnServiceTemplate);
146         return returnServiceTemplate;
147     }
148
149     /**
150      * Delete Data types.
151      *
152      * @param dao the DAO to use to access the database
153      * @param dataTypeKey the data type key for the Data types to be deleted, if the version of the key is null, all
154      *        versions of the data type are deleted.
155      * @return the TOSCA service template containing the data types that were deleted
156      * @throws PfModelException on errors deleting data types
157      */
158     public JpaToscaServiceTemplate deleteDataType(@NonNull final PfDao dao, @NonNull final PfConceptKey dataTypeKey)
159             throws PfModelException {
160         LOGGER.debug("->deleteDataType: key={}", dataTypeKey);
161
162         JpaToscaServiceTemplate serviceTemplate = getDataTypes(dao, dataTypeKey.getName(), dataTypeKey.getVersion());
163
164         dao.delete(JpaToscaDataType.class, dataTypeKey);
165
166         LOGGER.debug("<-deleteDataType: key={}, serviceTempalate={}", dataTypeKey, serviceTemplate);
167         return serviceTemplate;
168     }
169
170     /**
171      * Get policy types.
172      *
173      * @param dao the DAO to use to access the database
174      * @param name the name of the policy type to get, set to null to get all policy types
175      * @param version the version of the policy type to get, set to null to get all versions
176      * @return the policy types found
177      * @throws PfModelException on errors getting policy types
178      */
179     public JpaToscaServiceTemplate getPolicyTypes(@NonNull final PfDao dao, final String name, final String version)
180             throws PfModelException {
181         LOGGER.debug("->getPolicyTypes: name={}, version={}", name, version);
182
183         // Create the structure of the TOSCA service template to contain the policy type
184         JpaToscaServiceTemplate serviceTemplate = new JpaToscaServiceTemplate();
185         serviceTemplate.setPolicyTypes(new JpaToscaPolicyTypes());
186
187         // Add the policy type to the TOSCA service template
188         List<JpaToscaPolicyType> jpaPolicyTypeList = dao.getFiltered(JpaToscaPolicyType.class, name, version);
189         serviceTemplate.getPolicyTypes().getConceptMap().putAll(asConceptMap(jpaPolicyTypeList));
190
191         // Return all data types
192         // TODO: In an upcoming review, return just the data types used by the policy types on the policy type list
193         List<JpaToscaDataType> jpaDataTypeList = dao.getFiltered(JpaToscaDataType.class, null, null);
194         if (!CollectionUtils.isEmpty(jpaDataTypeList)) {
195             serviceTemplate.setDataTypes(new JpaToscaDataTypes());
196             serviceTemplate.getDataTypes().getConceptMap().putAll(asConceptMap(jpaDataTypeList));
197         }
198
199         LOGGER.debug("<-getPolicyTypes: name={}, version={}, serviceTemplate={}", name, version, serviceTemplate);
200         return serviceTemplate;
201     }
202
203     /**
204      * Create policy types.
205      *
206      * @param dao the DAO to use to access the database
207      * @param serviceTemplate the service template containing the definition of the policy types to be created
208      * @return the TOSCA service template containing the created policy types
209      * @throws PfModelException on errors creating policy types
210      */
211     public JpaToscaServiceTemplate createPolicyTypes(@NonNull final PfDao dao,
212             @NonNull final JpaToscaServiceTemplate serviceTemplate) throws PfModelException {
213         LOGGER.debug("->createPolicyTypes: serviceTempalate={}", serviceTemplate);
214
215         ToscaUtils.assertPolicyTypesExist(serviceTemplate);
216
217         // Create the data types on the policy type
218         if (ToscaUtils.doDataTypesExist(serviceTemplate)) {
219             createDataTypes(dao, serviceTemplate);
220         }
221
222         for (JpaToscaPolicyType policyType : serviceTemplate.getPolicyTypes().getAll(null)) {
223             dao.create(policyType);
224         }
225
226         // Return the created policy types
227         JpaToscaPolicyTypes returnPolicyTypes = new JpaToscaPolicyTypes();
228
229         for (PfConceptKey policyTypeKey : serviceTemplate.getPolicyTypes().getConceptMap().keySet()) {
230             returnPolicyTypes.getConceptMap().put(policyTypeKey, dao.get(JpaToscaPolicyType.class, policyTypeKey));
231         }
232
233         JpaToscaServiceTemplate returnServiceTemplate = new JpaToscaServiceTemplate();
234         returnServiceTemplate.setPolicyTypes(returnPolicyTypes);
235
236         LOGGER.debug("<-createPolicyTypes: returnServiceTempalate={}", returnServiceTemplate);
237         return returnServiceTemplate;
238     }
239
240     /**
241      * Update policy types.
242      *
243      * @param dao the DAO to use to access the database
244      * @param serviceTemplate the service template containing the definition of the policy types to be modified
245      * @return the TOSCA service template containing the modified policy types
246      * @throws PfModelException on errors updating policy types
247      */
248     public JpaToscaServiceTemplate updatePolicyTypes(@NonNull final PfDao dao,
249             @NonNull final JpaToscaServiceTemplate serviceTemplate) throws PfModelException {
250         LOGGER.debug("->updatePolicyTypes: serviceTempalate={}", serviceTemplate);
251
252         ToscaUtils.assertPolicyTypesExist(serviceTemplate);
253
254         // Update the data types on the policy type
255         if (ToscaUtils.doDataTypesExist(serviceTemplate)) {
256             updateDataTypes(dao, serviceTemplate);
257         }
258
259         for (JpaToscaPolicyType policyType : serviceTemplate.getPolicyTypes().getAll(null)) {
260             dao.update(policyType);
261         }
262
263         // Return the created policy types
264         JpaToscaPolicyTypes returnPolicyTypes = new JpaToscaPolicyTypes();
265
266         for (PfConceptKey policyTypeKey : serviceTemplate.getPolicyTypes().getConceptMap().keySet()) {
267             returnPolicyTypes.getConceptMap().put(policyTypeKey, dao.get(JpaToscaPolicyType.class, policyTypeKey));
268         }
269
270         JpaToscaServiceTemplate returnServiceTemplate = new JpaToscaServiceTemplate();
271         returnServiceTemplate.setPolicyTypes(returnPolicyTypes);
272
273         LOGGER.debug("<-updatePolicyTypes: returnServiceTempalate={}", returnServiceTemplate);
274         return returnServiceTemplate;
275     }
276
277     /**
278      * Delete policy types.
279      *
280      * @param dao the DAO to use to access the database
281      * @param policyTypeKey the policy type key for the policy types to be deleted, if the version of the key is null,
282      *        all versions of the policy type are deleted.
283      * @return the TOSCA service template containing the policy types that were deleted
284      * @throws PfModelException on errors deleting policy types
285      */
286     public JpaToscaServiceTemplate deletePolicyType(@NonNull final PfDao dao, @NonNull final PfConceptKey policyTypeKey)
287             throws PfModelException {
288         LOGGER.debug("->deletePolicyType: key={}", policyTypeKey);
289
290         JpaToscaServiceTemplate serviceTemplate =
291                 getPolicyTypes(dao, policyTypeKey.getName(), policyTypeKey.getVersion());
292
293         dao.delete(JpaToscaPolicyType.class, policyTypeKey);
294
295         LOGGER.debug("<-deletePolicyType: key={}, serviceTempalate={}", policyTypeKey, serviceTemplate);
296         return serviceTemplate;
297     }
298
299     /**
300      * Get policies.
301      *
302      * @param dao the DAO to use to access the database
303      * @param name the name of the policy to get, set to null to get all policy types
304      * @param version the version of the policy to get, set to null to get all versions
305      * @return the policies found
306      * @throws PfModelException on errors getting policies
307      */
308     public JpaToscaServiceTemplate getPolicies(@NonNull final PfDao dao, final String name, final String version)
309             throws PfModelException {
310         LOGGER.debug("->getPolicies: name={}, version={}", name, version);
311
312         // Create the structure of the TOSCA service template to contain the policy type
313         JpaToscaServiceTemplate serviceTemplate = new JpaToscaServiceTemplate();
314         serviceTemplate.setTopologyTemplate(new JpaToscaTopologyTemplate());
315         serviceTemplate.getTopologyTemplate().setPolicies(new JpaToscaPolicies());
316
317         // Add the policy type to the TOSCA service template
318         List<JpaToscaPolicy> jpaPolicyList = dao.getFiltered(JpaToscaPolicy.class, name, version);
319         serviceTemplate.getTopologyTemplate().getPolicies().getConceptMap().putAll(asConceptMap(jpaPolicyList));
320
321         LOGGER.debug("<-getPolicies: name={}, version={}, serviceTemplate={}", name, version, serviceTemplate);
322         return serviceTemplate;
323     }
324
325     /**
326      * Create policies.
327      *
328      * @param dao the DAO to use to access the database
329      * @param serviceTemplate the service template containing the definitions of the new policies to be created.
330      * @return the TOSCA service template containing the policy types that were created
331      * @throws PfModelException on errors creating policies
332      */
333     public JpaToscaServiceTemplate createPolicies(@NonNull final PfDao dao,
334             @NonNull final JpaToscaServiceTemplate serviceTemplate) throws PfModelException {
335         LOGGER.debug("->createPolicies: serviceTempalate={}", serviceTemplate);
336
337         ToscaUtils.assertPoliciesExist(serviceTemplate);
338
339         for (JpaToscaPolicy policy : serviceTemplate.getTopologyTemplate().getPolicies().getAll(null)) {
340             verifyPolicyTypeForPolicy(dao, policy);
341             dao.create(policy);
342         }
343
344         // Return the created policy types
345         JpaToscaPolicies returnPolicies = new JpaToscaPolicies();
346         returnPolicies.setKey(serviceTemplate.getTopologyTemplate().getPolicies().getKey());
347
348         for (PfConceptKey policyKey : serviceTemplate.getTopologyTemplate().getPolicies().getConceptMap().keySet()) {
349             returnPolicies.getConceptMap().put(policyKey, dao.get(JpaToscaPolicy.class, policyKey));
350         }
351
352         serviceTemplate.getTopologyTemplate().setPolicies(returnPolicies);
353
354         LOGGER.debug("<-createPolicies: serviceTemplate={}", serviceTemplate);
355         return serviceTemplate;
356     }
357
358     /**
359      * Update policies.
360      *
361      * @param dao the DAO to use to access the database
362      * @param serviceTemplate the service template containing the definitions of the policies to be updated.
363      * @return the TOSCA service template containing the policies that were updated
364      * @throws PfModelException on errors updating policies
365      */
366     public JpaToscaServiceTemplate updatePolicies(@NonNull final PfDao dao,
367             @NonNull final JpaToscaServiceTemplate serviceTemplate) throws PfModelException {
368         LOGGER.debug("->updatePolicies: serviceTempalate={}", serviceTemplate);
369
370         ToscaUtils.assertPoliciesExist(serviceTemplate);
371
372         for (JpaToscaPolicy policy : serviceTemplate.getTopologyTemplate().getPolicies().getAll(null)) {
373             verifyPolicyTypeForPolicy(dao, policy);
374             dao.update(policy);
375         }
376
377         // Return the created policy types
378         JpaToscaPolicies returnPolicies = new JpaToscaPolicies();
379         returnPolicies.setKey(serviceTemplate.getTopologyTemplate().getPolicies().getKey());
380
381         for (PfConceptKey policyKey : serviceTemplate.getTopologyTemplate().getPolicies().getConceptMap().keySet()) {
382             returnPolicies.getConceptMap().put(policyKey, dao.get(JpaToscaPolicy.class, policyKey));
383         }
384
385         serviceTemplate.getTopologyTemplate().setPolicies(returnPolicies);
386
387         LOGGER.debug("<-updatePolicies: serviceTemplate={}", serviceTemplate);
388         return serviceTemplate;
389     }
390
391     /**
392      * Delete policies.
393      *
394      * @param dao the DAO to use to access the database
395      * @param policyKey the policy key
396      * @return the TOSCA service template containing the policies that were deleted
397      * @throws PfModelException on errors deleting policies
398      */
399     public JpaToscaServiceTemplate deletePolicy(@NonNull final PfDao dao, @NonNull final PfConceptKey policyKey)
400             throws PfModelException {
401         LOGGER.debug("->deletePolicy: key={}", policyKey);
402
403         JpaToscaServiceTemplate serviceTemplate = getPolicies(dao, policyKey.getName(), policyKey.getVersion());
404
405         dao.delete(JpaToscaPolicy.class, policyKey);
406
407         LOGGER.debug("<-deletePolicy: key={}, serviceTempalate={}", policyKey, serviceTemplate);
408         return serviceTemplate;
409     }
410
411     /**
412      * Convert a list of concepts to a map of concepts.
413      *
414      * @param conceptList the concept list
415      * @return the concept map
416      */
417     private <T extends PfConcept> Map<PfConceptKey, T> asConceptMap(List<T> conceptList) {
418         Map<PfConceptKey, T> conceptMap = new LinkedHashMap<>();
419         for (T concept : conceptList) {
420             conceptMap.put((PfConceptKey) concept.getKey(), concept);
421         }
422
423         return conceptMap;
424     }
425
426     /**
427      * Verify the policy type for a policy exists.
428      *
429      * @param dao the DAO to use to access policy types in the database
430      * @param policy the policy to check the policy type for
431      */
432     private void verifyPolicyTypeForPolicy(final PfDao dao, final JpaToscaPolicy policy) {
433         PfConceptKey policyTypeKey = policy.getType();
434
435         JpaToscaPolicyType policyType = null;
436
437         if (PfKey.NULL_KEY_VERSION.equals(policyTypeKey.getVersion())) {
438             policyType = getLatestPolicyTypeVersion(dao, policyTypeKey.getName());
439
440             if (policyType != null) {
441                 policy.getType().setVersion(policyType.getKey().getVersion());
442             }
443         } else {
444             policyType = dao.get(JpaToscaPolicyType.class, policyTypeKey);
445         }
446
447         if (policyType == null) {
448             String errorMessage =
449                     "policy type " + policyTypeKey.getId() + " for policy " + policy.getId() + " does not exist";
450             LOGGER.warn(errorMessage);
451             throw new PfModelRuntimeException(Response.Status.BAD_REQUEST, errorMessage);
452         }
453     }
454
455     /**
456      * Get the latest version of the policy type for the given policy type name.
457      *
458      * @param dao the DAO to use to access policy types in the database
459      * @param policyTypeName the name of the policy type
460      * @return the latest policy type
461      */
462     private JpaToscaPolicyType getLatestPolicyTypeVersion(final PfDao dao, final String policyTypeName) {
463         // Policy type version is not specified, get the latest version from the database
464         List<JpaToscaPolicyType> jpaPolicyTypeList = dao.getFiltered(JpaToscaPolicyType.class, policyTypeName, null);
465
466         if (CollectionUtils.isEmpty(jpaPolicyTypeList)) {
467             return null;
468         }
469
470         // Create a filter to get the latest version of the policy type
471         PfConceptFilter pfConceptFilter = PfConceptFilter.builder().version(PfConceptFilter.LATEST_VERSION).build();
472
473         // FIlter the returned policy type list
474         List<PfConcept> policyTypeKeyList = new ArrayList<>(jpaPolicyTypeList);
475         List<PfConcept> filterdPolicyTypeList = pfConceptFilter.filter(policyTypeKeyList);
476
477         // We should have one and only one returned entry
478         if (filterdPolicyTypeList.size() != 1) {
479             String errorMessage = "search for lates policy type " + policyTypeName + " returned more than one entry";
480             LOGGER.warn(errorMessage);
481             throw new PfModelRuntimeException(Response.Status.BAD_REQUEST, errorMessage);
482         }
483
484         return (JpaToscaPolicyType) filterdPolicyTypeList.get(0);
485     }
486 }