f3634b3c968a511ca74fe4456c2daf52f80b311e
[policy/api.git] / main / src / main / java / org / onap / policy / api / main / rest / provider / CommonModelProvider.java
1 /*-\r
2  * ============LICENSE_START=======================================================\r
3  * ONAP Policy API\r
4  * ================================================================================\r
5  * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.\r
6  * ================================================================================\r
7  * Licensed under the Apache License, Version 2.0 (the "License");\r
8  * you may not use this file except in compliance with the License.\r
9  * You may obtain a copy of the License at\r
10  *\r
11  *      http://www.apache.org/licenses/LICENSE-2.0\r
12  *\r
13  * Unless required by applicable law or agreed to in writing, software\r
14  * distributed under the License is distributed on an "AS IS" BASIS,\r
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
16  * See the License for the specific language governing permissions and\r
17  * limitations under the License.\r
18  *\r
19  * SPDX-License-Identifier: Apache-2.0\r
20  * ============LICENSE_END=========================================================\r
21  */\r
22 \r
23 package org.onap.policy.api.main.rest.provider;\r
24 \r
25 import java.util.ArrayList;\r
26 import java.util.HashMap;\r
27 import java.util.List;\r
28 import java.util.Map;\r
29 import java.util.function.BiConsumer;\r
30 import javax.ws.rs.core.Response;\r
31 \r
32 import org.apache.commons.lang3.tuple.Pair;\r
33 import org.onap.policy.api.main.parameters.ApiParameterGroup;\r
34 import org.onap.policy.common.parameters.ParameterService;\r
35 import org.onap.policy.models.base.PfConceptKey;\r
36 import org.onap.policy.models.base.PfModelException;\r
37 import org.onap.policy.models.pdp.concepts.PdpGroup;\r
38 import org.onap.policy.models.pdp.concepts.PdpGroupFilter;\r
39 import org.onap.policy.models.pdp.concepts.PdpSubGroup;\r
40 import org.onap.policy.models.pdp.enums.PdpState;\r
41 import org.onap.policy.models.provider.PolicyModelsProvider;\r
42 import org.onap.policy.models.provider.PolicyModelsProviderFactory;\r
43 import org.onap.policy.models.provider.PolicyModelsProviderParameters;\r
44 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;\r
45 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyIdentifier;\r
46 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyTypeIdentifier;\r
47 import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;\r
48 \r
49 /**\r
50  * Super class for providers that use a model provider.\r
51  */\r
52 public class CommonModelProvider implements AutoCloseable {\r
53 \r
54     protected final PolicyModelsProvider modelsProvider;\r
55 \r
56     /**\r
57      * Constructs the object, populating {@link #modelsProvider}.\r
58      *\r
59      * @throws PfModelException if an error occurs\r
60      */\r
61     public CommonModelProvider() throws PfModelException {\r
62 \r
63         ApiParameterGroup parameterGroup = ParameterService.get("ApiGroup");\r
64         PolicyModelsProviderParameters providerParameters = parameterGroup.getDatabaseProviderParameters();\r
65         modelsProvider = new PolicyModelsProviderFactory().createPolicyModelsProvider(providerParameters);\r
66     }\r
67 \r
68     /**\r
69      * Closes the connection to database.\r
70      *\r
71      * @throws PfModelException the PfModel parsing exception\r
72      */\r
73     @Override\r
74     public void close() throws PfModelException {\r
75 \r
76         modelsProvider.close();\r
77     }\r
78 \r
79     /**\r
80      * Checks if service template contains any policy.\r
81      *\r
82      * @param serviceTemplate the service template to check against\r
83      *\r
84      * @return boolean whether service template contains any policy\r
85      */\r
86     protected boolean hasPolicy(ToscaServiceTemplate serviceTemplate) {\r
87 \r
88         return hasData(serviceTemplate.getToscaTopologyTemplate().getPolicies());\r
89     }\r
90 \r
91     /**\r
92      * Checks if service template contains any policy type.\r
93      *\r
94      * @param serviceTemplate the service template to check against\r
95      *\r
96      * @return boolean whether service template contains any policy type\r
97      */\r
98     protected boolean hasPolicyType(ToscaServiceTemplate serviceTemplate) {\r
99 \r
100         return hasData(serviceTemplate.getPolicyTypes());\r
101     }\r
102 \r
103     /**\r
104      * Checks if the first element of a list contains data.\r
105      *\r
106      * @param list list to be examined\r
107      * @return {@code true} if the list contains data, {@code false} otherwise\r
108      */\r
109     protected <T> boolean hasData(List<Map<String, T>> list) {\r
110 \r
111         return (list != null && !list.isEmpty() && !list.get(0).isEmpty());\r
112     }\r
113 \r
114     /**\r
115      * Validates that some text represents a number.\r
116      *\r
117      * @param text text to be validated\r
118      * @param errorMsg error message included in the exception, if the text is not a valid\r
119      *        number\r
120      * @throws PfModelException if the text is not a valid number\r
121      */\r
122     protected void validNumber(String text, String errorMsg) throws PfModelException {\r
123         try {\r
124             Integer.parseInt(text);\r
125 \r
126         } catch (NumberFormatException exc) {\r
127             throw new PfModelException(Response.Status.BAD_REQUEST, errorMsg, exc);\r
128         }\r
129     }\r
130 \r
131     /**\r
132      * Constructs returned message for policy delete rule violation.\r
133      *\r
134      * @param policyId the ID of policy\r
135      * @param policyVersion the version of policy\r
136      * @param pdpGroups the list of pdp groups\r
137      *\r
138      * @return the constructed message\r
139      */\r
140     protected String constructDeletePolicyViolationMessage(String policyId, String policyVersion,\r
141                     List<PdpGroup> pdpGroups) {\r
142 \r
143         List<String> pdpGroupNameVersionList = new ArrayList<>(pdpGroups.size());\r
144         for (PdpGroup pdpGroup : pdpGroups) {\r
145             pdpGroupNameVersionList.add(pdpGroup.getName() + ":" + pdpGroup.getVersion());\r
146         }\r
147         String deployedPdpGroups = String.join(",", pdpGroupNameVersionList);\r
148         return "policy with ID " + policyId + ":" + policyVersion\r
149                         + " cannot be deleted as it is deployed in pdp groups " + deployedPdpGroups;\r
150     }\r
151 \r
152     /**\r
153      * Constructs returned message for policy type delete rule violation.\r
154      *\r
155      * @param policyTypeId the ID of policy type\r
156      * @param policyTypeVersion the version of policy type\r
157      * @param policies the list of policies that parameterizes specified policy type\r
158      *\r
159      * @return the constructed message\r
160      */\r
161     protected String constructDeletePolicyTypeViolationMessage(String policyTypeId, String policyTypeVersion,\r
162                     List<ToscaPolicy> policies) {\r
163 \r
164         List<String> policyNameVersionList = new ArrayList<>(policies.size());\r
165         for (ToscaPolicy policy : policies) {\r
166             policyNameVersionList.add(policy.getName() + ":" + policy.getVersion());\r
167         }\r
168         String parameterizedPolicies = String.join(",", policyNameVersionList);\r
169         return "policy type with ID " + policyTypeId + ":" + policyTypeVersion\r
170                         + " cannot be deleted as it is parameterized by policies " + parameterizedPolicies;\r
171     }\r
172 \r
173     /**\r
174      * Collects all deployed versions of specified policy in all pdp groups.\r
175      *\r
176      * @param policyId the ID of policy\r
177      * @param policyType the concept key of policy type\r
178      * @param getter the custom generic getter Bifunction\r
179      * @param consumer the BiConsumer\r
180      * @param data the data structure storing retrieved deployed policies\r
181      *\r
182      * @return a map between pdp group and deployed versions of specified policy in that group\r
183      *\r
184      * @throws PfModelException the PfModel parsing exception\r
185      */\r
186     protected <T, R> Map<Pair<String, String>, T> collectDeployedPolicies(String policyId, PfConceptKey policyType,\r
187             BiFunctionWithEx<String, String, R> getter, BiConsumer<T, R> consumer, T data) throws PfModelException {\r
188 \r
189         List<PdpGroup> pdpGroups = getPolicyTypeFilteredPdpGroups(policyType);\r
190         hasActivePdpGroup(pdpGroups, policyType, policyId);\r
191         return constructDeployedPolicyMap(pdpGroups, policyId, policyType, getter, consumer, data);\r
192     }\r
193 \r
194     @FunctionalInterface\r
195     protected interface BiFunctionWithEx<T,U,R> {\r
196         public R apply(T value1, U value2) throws PfModelException;\r
197     }\r
198 \r
199     /**\r
200      * Checks if the list of pdp groups is empty.\r
201      * If so, throws exception saying specified policy deployment is not found in all existing pdp groups.\r
202      *\r
203      * @param pdpGroups the list of pdp groups to check against\r
204      * @param policyType the concept key of policy type\r
205      * @param policyId the ID of policy\r
206      *\r
207      * @throws PfModelException the PfModel parsing exception\r
208      */\r
209     private void hasActivePdpGroup(List<PdpGroup> pdpGroups, PfConceptKey policyType, String policyId)\r
210             throws PfModelException {\r
211 \r
212         if (pdpGroups.isEmpty()) {\r
213             throw new PfModelException(Response.Status.NOT_FOUND,\r
214                     constructDeploymentNotFoundMessage(policyType, policyId));\r
215         }\r
216     }\r
217 \r
218     /**\r
219      * Retrieves all pdp groups supporting specified policy type.\r
220      *\r
221      * @param policyTypeId the ID of policy type\r
222      * @param policyTypeVersion the version of policy type\r
223      *\r
224      * @return a list of pdp groups supporting specified policy type\r
225      *\r
226      * @throws PfModelException the PfModel parsing exception\r
227      */\r
228     private List<PdpGroup> getPolicyTypeFilteredPdpGroups(PfConceptKey policyType)\r
229             throws PfModelException {\r
230 \r
231         List<ToscaPolicyTypeIdentifier> policyTypes = new ArrayList<>();\r
232         policyTypes.add(new ToscaPolicyTypeIdentifier(policyType.getName(), policyType.getVersion()));\r
233         PdpGroupFilter pdpGroupFilter = PdpGroupFilter.builder().policyTypeList(policyTypes)\r
234                 .groupState(PdpState.ACTIVE).pdpState(PdpState.ACTIVE).build();\r
235         return modelsProvider.getFilteredPdpGroups(pdpGroupFilter);\r
236     }\r
237 \r
238     /**\r
239      * Constructs the map of deployed pdp groups and deployed policies.\r
240      *\r
241      * @param pdpGroups the list of pdp groups that contain the specified policy\r
242      * @param policyId the ID of policy\r
243      * @param policyType the concept key of policy type\r
244      * @param getter the custom generic getter BiFunction\r
245      * @param consumer the BiConsumer\r
246      * @param data the data structure storing retrieved deployed policies\r
247      *\r
248      * @return the constructed map of pdp groups and deployed policies\r
249      *\r
250      * @throws PfModelException the PfModel parsing exception\r
251      */\r
252     private <T, R> Map<Pair<String, String>, T> constructDeployedPolicyMap(List<PdpGroup> pdpGroups, String policyId,\r
253             PfConceptKey policyType, BiFunctionWithEx<String, String, R> getter, BiConsumer<T, R> consumer, T data)\r
254                     throws PfModelException {\r
255 \r
256         Map<Pair<String, String>, T> deployedPolicyMap = new HashMap<>();\r
257         for (PdpGroup pdpGroup : pdpGroups) {\r
258             List<ToscaPolicyIdentifier> policyIdentifiers = extractPolicyIdentifiers(policyId, pdpGroup, policyType);\r
259             T deployedPolicies = getDeployedPolicies(policyIdentifiers, policyType, getter, consumer, data);\r
260             deployedPolicyMap.put(Pair.of(pdpGroup.getName(), pdpGroup.getVersion()), deployedPolicies);\r
261         }\r
262         return deployedPolicyMap;\r
263     }\r
264 \r
265     /**\r
266      * Extracts policy identifiers matching specified policy ID from specified pdp group.\r
267      *\r
268      * @param policyId the ID of policy to match\r
269      * @param pdpGroup the target pdp group to search\r
270      * @param policyType the concept key of policy type\r
271      *\r
272      * @return the list of policy identifiers\r
273      *\r
274      * @throws PfModelException the PfModel parsing exception\r
275      */\r
276     private List<ToscaPolicyIdentifier> extractPolicyIdentifiers(String policyId, PdpGroup pdpGroup,\r
277             PfConceptKey policyType) throws PfModelException {\r
278 \r
279         List<ToscaPolicyIdentifier> policyIdentifiers = new ArrayList<>();\r
280         for (PdpSubGroup pdpSubGroup : pdpGroup.getPdpSubgroups()) {\r
281             for (ToscaPolicyIdentifier policyIdentifier : pdpSubGroup.getPolicies()) {\r
282                 if (policyId.equalsIgnoreCase(policyIdentifier.getName())) {\r
283                     policyIdentifiers.add(policyIdentifier);\r
284                 }\r
285             }\r
286         }\r
287         if (policyIdentifiers.isEmpty()) {\r
288             throw new PfModelException(Response.Status.NOT_FOUND,\r
289                     constructDeploymentNotFoundMessage(policyType, policyId));\r
290         }\r
291         return policyIdentifiers;\r
292     }\r
293 \r
294     /**\r
295      * Retrieves deployed policies in a generic way.\r
296      *\r
297      * @param policyIdentifiers the identifiers of the policies to return\r
298      * @param policyType the concept key of current policy type\r
299      * @param getter the method reference of getting deployed policies\r
300      * @param consumer the method reference of consuming the returned policies\r
301      * @param data the data structure of deployed policies to return\r
302      *\r
303      * @return the generic type of policy data structure to return\r
304      *\r
305      * @throws PfModelException the PfModel parsing exception\r
306      */\r
307     private <T, R> T getDeployedPolicies(List<ToscaPolicyIdentifier> policyIdentifiers, PfConceptKey policyType,\r
308             BiFunctionWithEx<String, String, R> getter, BiConsumer<T, R> consumer, T data) throws PfModelException {\r
309 \r
310         for (ToscaPolicyIdentifier policyIdentifier : policyIdentifiers) {\r
311             R result = getter.apply(policyIdentifier.getName(),\r
312                     getTrimedVersionForLegacyType(policyIdentifier.getVersion(), policyType));\r
313             consumer.accept(data, result);\r
314         }\r
315         return data;\r
316     }\r
317 \r
318     /**\r
319      * Trims the version for legacy policies.\r
320      *\r
321      * @param fullVersion the full version format with major, minor, patch\r
322      * @param policyType the concept key of policy type\r
323      *\r
324      * @return the trimmed version\r
325      */\r
326     private String getTrimedVersionForLegacyType(String fullVersion, PfConceptKey policyType) {\r
327         return (policyType.getName().contains("guard")\r
328                 || policyType.getName().contains("Operational")) ? fullVersion.split("\\.")[0] : fullVersion;\r
329     }\r
330 \r
331     /**\r
332      * Constructs returned message for not found policy deployment.\r
333      *\r
334      * @param policyType the concept key of policy type\r
335      * @param policyId the ID of policy\r
336      *\r
337      * @return constructed message\r
338      */\r
339     private String constructDeploymentNotFoundMessage(PfConceptKey policyType, String policyId) {\r
340 \r
341         return "could not find policy with ID " + policyId + " and type "\r
342                 + policyType.getName() + ":" + policyType.getVersion() + " deployed in any pdp group";\r
343     }\r
344 }