a4440dafeda0290998d5d6c4780ffb3afef44baf
[policy/api.git] / main / src / main / java / org / onap / policy / api / main / rest / provider / PolicyProvider.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 javax.ws.rs.core.Response;\r
30 import org.apache.commons.lang3.tuple.Pair;\r
31 import org.onap.policy.models.base.PfModelException;\r
32 import org.onap.policy.models.pdp.concepts.PdpGroup;\r
33 import org.onap.policy.models.pdp.concepts.PdpGroupFilter;\r
34 import org.onap.policy.models.pdp.concepts.PdpSubGroup;\r
35 import org.onap.policy.models.pdp.enums.PdpState;\r
36 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;\r
37 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyFilter;\r
38 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyIdentifier;\r
39 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyTypeIdentifier;\r
40 import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;\r
41 \r
42 /**\r
43  * Class to provide all kinds of policy operations.\r
44  *\r
45  * @author Chenfei Gao (cgao@research.att.com)\r
46  */\r
47 public class PolicyProvider extends CommonModelProvider {\r
48 \r
49     /**\r
50      * Default constructor.\r
51      */\r
52     public PolicyProvider() throws PfModelException {\r
53         super();\r
54     }\r
55 \r
56     /**\r
57      * Retrieves a list of policies matching specified ID and version of both policy type and policy.\r
58      *\r
59      * @param policyTypeId the ID of policy type\r
60      * @param policyTypeVersion the version of policy type\r
61      * @param policyId the ID of policy\r
62      * @param policyVersion the version of policy\r
63      *\r
64      * @return the ToscaServiceTemplate object\r
65      *\r
66      * @throws PfModelException the PfModel parsing exception\r
67      */\r
68     public ToscaServiceTemplate fetchPolicies(String policyTypeId, String policyTypeVersion,\r
69             String policyId, String policyVersion) throws PfModelException {\r
70 \r
71         ToscaPolicyFilter policyFilter = ToscaPolicyFilter.builder()\r
72                 .name(policyId).version(policyVersion)\r
73                 .type(policyTypeId).typeVersion(policyTypeVersion).build();\r
74         ToscaServiceTemplate serviceTemplate = modelsProvider.getFilteredPolicies(policyFilter);\r
75 \r
76         if (!hasPolicy(serviceTemplate)) {\r
77             throw new PfModelException(Response.Status.NOT_FOUND,\r
78                     constructResourceNotFoundMessage(policyTypeId, policyTypeVersion, policyId, policyVersion));\r
79         }\r
80 \r
81         return serviceTemplate;\r
82     }\r
83 \r
84     /**\r
85      * Retrieves a list of policies with the latest versions that match specified policy type id and version.\r
86      *\r
87      * @param policyTypeId the ID of policy type\r
88      * @param policyTypeVersion the version of policy type\r
89      * @param policyId the ID of the policy\r
90      *\r
91      * @return the ToscaServiceTemplate object\r
92      *\r
93      * @throws PfModelException the PfModel parsing exception\r
94      */\r
95     public ToscaServiceTemplate fetchLatestPolicies(String policyTypeId, String policyTypeVersion,\r
96             String policyId) throws PfModelException {\r
97 \r
98         ToscaPolicyFilter policyFilter = ToscaPolicyFilter.builder()\r
99                 .name(policyId).version(ToscaPolicyFilter.LATEST_VERSION)\r
100                 .type(policyTypeId).typeVersion(policyTypeVersion).build();\r
101         ToscaServiceTemplate serviceTemplate = modelsProvider.getFilteredPolicies(policyFilter);\r
102 \r
103         if (!hasPolicy(serviceTemplate)) {\r
104             throw new PfModelException(Response.Status.NOT_FOUND,\r
105                     constructResourceNotFoundMessage(policyTypeId, policyTypeVersion, policyId, null));\r
106         }\r
107 \r
108         return serviceTemplate;\r
109     }\r
110 \r
111     /**\r
112      * Retrieves a list of deployed policies in each pdp group.\r
113      *\r
114      * @param policyTypeId the ID of policy type\r
115      * @param policyTypeVersion the version of policy type\r
116      * @param policyId the ID of the policy\r
117      *\r
118      * @return a list of deployed policies in each pdp group\r
119      *\r
120      * @throws PfModelException the PfModel parsing exception\r
121      */\r
122     public Map<Pair<String, String>, List<ToscaPolicy>> fetchDeployedPolicies(\r
123             String policyTypeId, String policyTypeVersion, String policyId) throws PfModelException {\r
124 \r
125         List<ToscaPolicyTypeIdentifier> policyTypes = new ArrayList<>();\r
126         policyTypes.add(new ToscaPolicyTypeIdentifier(policyTypeId, policyTypeVersion));\r
127         PdpGroupFilter pdpGroupFilter = PdpGroupFilter.builder().policyTypeList(policyTypes)\r
128                 .groupState(PdpState.ACTIVE).pdpState(PdpState.ACTIVE).build();\r
129         List<PdpGroup> pdpGroups = modelsProvider.getFilteredPdpGroups(pdpGroupFilter);\r
130 \r
131         if (pdpGroups.isEmpty()) {\r
132             throw new PfModelException(Response.Status.NOT_FOUND,\r
133                     constructDeploymentNotFoundMessage(policyTypeId, policyTypeVersion, policyId));\r
134         }\r
135 \r
136         Map<Pair<String, String>, List<ToscaPolicy>> deployedPolicyMap =\r
137                 constructDeployedPolicyMap(pdpGroups, policyId);\r
138         if (deployedPolicyMap.isEmpty()) {\r
139             throw new PfModelException(Response.Status.NOT_FOUND,\r
140                     constructDeploymentNotFoundMessage(policyTypeId, policyTypeVersion, policyId));\r
141         }\r
142 \r
143         return deployedPolicyMap;\r
144     }\r
145 \r
146     /**\r
147      * Creates a new policy for a policy type ID and version.\r
148      *\r
149      * @param policyTypeId the ID of policy type\r
150      * @param policyTypeVersion the version of policy type\r
151      * @param body the entity body of policy\r
152      *\r
153      * @return the ToscaServiceTemplate object\r
154      *\r
155      * @throws PfModelException the PfModel parsing exception\r
156      */\r
157     public ToscaServiceTemplate createPolicy(String policyTypeId, String policyTypeVersion,\r
158                                              ToscaServiceTemplate body) throws PfModelException {\r
159 \r
160         validatePolicyTypeExist(policyTypeId, policyTypeVersion);\r
161         validatePolicyTypeMatch(policyTypeId, policyTypeVersion, body);\r
162 \r
163         return modelsProvider.createPolicies(body);\r
164     }\r
165 \r
166     /**\r
167      * Deletes the policy matching specified ID and version of both policy type and policy.\r
168      *\r
169      * @param policyTypeId the ID of policy type\r
170      * @param policyTypeVersion the version of policy type\r
171      * @param policyId the ID of policy\r
172      * @param policyVersion the version of policy\r
173      *\r
174      * @return the ToscaServiceTemplate object\r
175      *\r
176      * @throws PfModelException the PfModel parsing exception\r
177      */\r
178     public ToscaServiceTemplate deletePolicy(String policyTypeId, String policyTypeVersion,\r
179                                  String policyId, String policyVersion) throws PfModelException {\r
180 \r
181         validateDeleteEligibility(policyTypeId, policyTypeVersion, policyId, policyVersion);\r
182 \r
183         ToscaServiceTemplate serviceTemplate = modelsProvider.deletePolicy(policyId, policyVersion);\r
184 \r
185         if (!hasPolicy(serviceTemplate)) {\r
186             throw new PfModelException(Response.Status.NOT_FOUND,\r
187                     constructResourceNotFoundMessage(policyTypeId, policyTypeVersion, policyId, policyVersion));\r
188         }\r
189 \r
190         return serviceTemplate;\r
191     }\r
192 \r
193     /**\r
194      * Validates whether policy type exists.\r
195      *\r
196      * @param policyTypeId the ID of policy type\r
197      * @param policyTypeVersion the version of policy type\r
198      *\r
199      * @throws PfModelException the PfModel parsing exception\r
200      */\r
201     private void validatePolicyTypeExist(String policyTypeId, String policyTypeVersion) throws PfModelException {\r
202 \r
203         ToscaServiceTemplate serviceTemplate = modelsProvider.getPolicyTypes(policyTypeId, policyTypeVersion);\r
204         if (!hasPolicyType(serviceTemplate)) {\r
205             throw new PfModelException(Response.Status.NOT_FOUND,\r
206                     "policy type with ID " + policyTypeId + ":" + policyTypeVersion + " does not exist");\r
207         }\r
208     }\r
209 \r
210     /**\r
211      * Validates the match between policy type specified in path and the one specified in type of policy.\r
212      *\r
213      * @param policyTypeId the ID of policy type\r
214      * @param policyTypeVersion the version of policy type\r
215      * @param serviceTemplate the ToscaServiceTemplate to validate\r
216      *\r
217      * @throws PfModelException the PfModel parsing exception\r
218      */\r
219     private void validatePolicyTypeMatch(String policyTypeId, String policyTypeVersion,\r
220             ToscaServiceTemplate serviceTemplate) throws PfModelException {\r
221 \r
222         List<Map<String, ToscaPolicy>> policies = serviceTemplate.getToscaTopologyTemplate().getPolicies();\r
223         for (Map<String, ToscaPolicy> policy : policies) {\r
224             if (policy.size() > 1) {\r
225                 throw new PfModelException(Response.Status.BAD_REQUEST,\r
226                         "one policy block contains more than one policies");\r
227             }\r
228             ToscaPolicy policyContent = policy.values().iterator().next();\r
229             if (!policyTypeId.equalsIgnoreCase(policyContent.getType())) {\r
230                 throw new PfModelException(Response.Status.BAD_REQUEST, "policy type id does not match");\r
231             }\r
232             if (policyContent.getTypeVersion() != null\r
233                     && !policyTypeVersion.equalsIgnoreCase(policyContent.getTypeVersion())) {\r
234                 throw new PfModelException(Response.Status.BAD_REQUEST, "policy type version does not match");\r
235             }\r
236         }\r
237     }\r
238 \r
239     /**\r
240      * Validates whether specified policy can be deleted based on the rule that deployed policy cannot be deleted.\r
241      *\r
242      * @param policyTypeId the ID of policy type\r
243      * @param policyTypeVersion the version of policy type\r
244      * @param policyId the ID of policy\r
245      * @param policyVersion the version of policy\r
246      *\r
247      * @throws PfModelException the PfModel parsing exception\r
248      */\r
249     private void validateDeleteEligibility(String policyTypeId, String policyTypeVersion,\r
250             String policyId, String policyVersion) throws PfModelException {\r
251 \r
252         List<ToscaPolicyTypeIdentifier> policyTypes = new ArrayList<>();\r
253         policyTypes.add(new ToscaPolicyTypeIdentifier(policyTypeId, policyTypeVersion));\r
254         List<ToscaPolicyIdentifier> policies = new ArrayList<>();\r
255         policies.add(new ToscaPolicyIdentifier(policyId, policyVersion));\r
256         PdpGroupFilter pdpGroupFilter = PdpGroupFilter.builder()\r
257                 .policyTypeList(policyTypes).policyList(policies).build();\r
258 \r
259         List<PdpGroup> pdpGroups = modelsProvider.getFilteredPdpGroups(pdpGroupFilter);\r
260 \r
261         if (!pdpGroups.isEmpty()) {\r
262             throw new PfModelException(Response.Status.CONFLICT,\r
263                     constructDeletePolicyViolationMessage(policyId, policyVersion, pdpGroups));\r
264         }\r
265     }\r
266 \r
267     /**\r
268      * Constructs the map of deployed pdp groups and deployed policies.\r
269      *\r
270      * @param pdpGroups the list of pdp groups that contain the specified policy\r
271      * @param policyId the ID of policy\r
272      *\r
273      * @return the constructed map of pdp groups and deployed policies\r
274      *\r
275      * @throws PfModelException the PfModel parsing exception\r
276      */\r
277     private Map<Pair<String, String>, List<ToscaPolicy>> constructDeployedPolicyMap(\r
278             List<PdpGroup> pdpGroups, String policyId) throws PfModelException {\r
279 \r
280         Map<Pair<String, String>, List<ToscaPolicy>> deployedPolicyMap = new HashMap<>();\r
281         for (PdpGroup pdpGroup : pdpGroups) {\r
282             List<ToscaPolicyIdentifier> policyIdentifiers = extractPolicyIdentifiers(policyId, pdpGroup);\r
283             List<ToscaPolicy> deployedPolicies = getDeployedPolicies(policyIdentifiers);\r
284             if (!deployedPolicies.isEmpty()) {\r
285                 deployedPolicyMap.put(Pair.of(pdpGroup.getName(), pdpGroup.getVersion()), deployedPolicies);\r
286             }\r
287         }\r
288         return deployedPolicyMap;\r
289     }\r
290 \r
291     private List<ToscaPolicyIdentifier> extractPolicyIdentifiers(String policyId, PdpGroup pdpGroup) {\r
292         List<ToscaPolicyIdentifier> policyIdentifiers = new ArrayList<>();\r
293         for (PdpSubGroup pdpSubGroup : pdpGroup.getPdpSubgroups()) {\r
294             for (ToscaPolicyIdentifier policyIdentifier : pdpSubGroup.getPolicies()) {\r
295                 if (policyId.equalsIgnoreCase(policyIdentifier.getName())) {\r
296                     policyIdentifiers.add(policyIdentifier);\r
297                 }\r
298             }\r
299         }\r
300         return policyIdentifiers;\r
301     }\r
302 \r
303     private List<ToscaPolicy> getDeployedPolicies(List<ToscaPolicyIdentifier> policyIdentifiers)\r
304                     throws PfModelException {\r
305 \r
306         List<ToscaPolicy> deployedPolicies = new ArrayList<>();\r
307         if (!policyIdentifiers.isEmpty()) {\r
308             for (ToscaPolicyIdentifier policyIdentifier : policyIdentifiers) {\r
309                 deployedPolicies.addAll(\r
310                         modelsProvider.getPolicyList(policyIdentifier.getName(), policyIdentifier.getVersion()));\r
311             }\r
312         }\r
313         return deployedPolicies;\r
314     }\r
315 \r
316     /**\r
317      * Constructs returned message for not found resource.\r
318      *\r
319      * @param policyTypeId the ID of policy type\r
320      * @param policyTypeVersion the version of policy type\r
321      * @param policyId the ID of policy\r
322      * @param policyVersion the version of policy\r
323      *\r
324      * @return constructed message\r
325      */\r
326     private String constructResourceNotFoundMessage(String policyTypeId, String policyTypeVersion,\r
327             String policyId, String policyVersion) {\r
328 \r
329         return "policy with ID " + policyId + ":" + policyVersion\r
330                 + " and type " + policyTypeId + ":" + policyTypeVersion + " does not exist";\r
331     }\r
332 \r
333     /**\r
334      * Constructs returned message for not found policy deployment.\r
335      *\r
336      * @param policyTypeId the ID of policy type\r
337      * @param policyTypeVersion the version of policy type\r
338      * @param policyId the ID of policy\r
339      * @param policyVersion the version of policy\r
340      *\r
341      * @return constructed message\r
342      */\r
343     private String constructDeploymentNotFoundMessage(String policyTypeId, String policyTypeVersion,\r
344             String policyId) {\r
345 \r
346         return "could not find policy with ID " + policyId + " and type "\r
347                 + policyTypeId + ":" + policyTypeVersion + " deployed in any pdp group";\r
348     }\r
349 }\r