66fd7f0e31bad5a337f6115d5e2e1a50c508eb4f
[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.List;\r
27 import java.util.Map;\r
28 import javax.ws.rs.core.Response;\r
29 import org.apache.commons.lang3.tuple.Pair;\r
30 import org.onap.policy.models.base.PfConceptKey;\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.tosca.authorative.concepts.ToscaPolicy;\r
35 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyFilter;\r
36 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyIdentifier;\r
37 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyTypeIdentifier;\r
38 import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;\r
39 \r
40 /**\r
41  * Class to provide all kinds of policy operations.\r
42  *\r
43  * @author Chenfei Gao (cgao@research.att.com)\r
44  */\r
45 public class PolicyProvider extends CommonModelProvider {\r
46 \r
47     /**\r
48      * Default constructor.\r
49      */\r
50     public PolicyProvider() throws PfModelException {\r
51         super();\r
52     }\r
53 \r
54     /**\r
55      * Retrieves a list of policies matching specified ID and version of both policy type and policy.\r
56      *\r
57      * @param policyTypeId the ID of policy type\r
58      * @param policyTypeVersion the version of policy type\r
59      * @param policyId the ID of policy\r
60      * @param policyVersion the version of policy\r
61      *\r
62      * @return the ToscaServiceTemplate object\r
63      *\r
64      * @throws PfModelException the PfModel parsing exception\r
65      */\r
66     public ToscaServiceTemplate fetchPolicies(String policyTypeId, String policyTypeVersion,\r
67             String policyId, String policyVersion) throws PfModelException {\r
68 \r
69         ToscaPolicyFilter policyFilter = ToscaPolicyFilter.builder()\r
70                 .name(policyId).version(policyVersion)\r
71                 .type(policyTypeId).typeVersion(policyTypeVersion).build();\r
72         ToscaServiceTemplate serviceTemplate = modelsProvider.getFilteredPolicies(policyFilter);\r
73 \r
74         if (!hasPolicy(serviceTemplate)) {\r
75             throw new PfModelException(Response.Status.NOT_FOUND,\r
76                     constructResourceNotFoundMessage(policyTypeId, policyTypeVersion, policyId, policyVersion));\r
77         }\r
78 \r
79         return serviceTemplate;\r
80     }\r
81 \r
82     /**\r
83      * Retrieves a list of policies with the latest versions that match specified policy type id and version.\r
84      *\r
85      * @param policyTypeId the ID of policy type\r
86      * @param policyTypeVersion the version of policy type\r
87      * @param policyId the ID of the policy\r
88      *\r
89      * @return the ToscaServiceTemplate object\r
90      *\r
91      * @throws PfModelException the PfModel parsing exception\r
92      */\r
93     public ToscaServiceTemplate fetchLatestPolicies(String policyTypeId, String policyTypeVersion,\r
94             String policyId) throws PfModelException {\r
95 \r
96         ToscaPolicyFilter policyFilter = ToscaPolicyFilter.builder()\r
97                 .name(policyId).version(ToscaPolicyFilter.LATEST_VERSION)\r
98                 .type(policyTypeId).typeVersion(policyTypeVersion).build();\r
99         ToscaServiceTemplate serviceTemplate = modelsProvider.getFilteredPolicies(policyFilter);\r
100 \r
101         if (!hasPolicy(serviceTemplate)) {\r
102             throw new PfModelException(Response.Status.NOT_FOUND,\r
103                     constructResourceNotFoundMessage(policyTypeId, policyTypeVersion, policyId, null));\r
104         }\r
105 \r
106         return serviceTemplate;\r
107     }\r
108 \r
109     /**\r
110      * Retrieves a list of deployed policies in each pdp group.\r
111      *\r
112      * @param policyTypeId the ID of policy type\r
113      * @param policyTypeVersion the version of policy type\r
114      * @param policyId the ID of the policy\r
115      *\r
116      * @return a list of deployed policies in each pdp group\r
117      *\r
118      * @throws PfModelException the PfModel parsing exception\r
119      */\r
120     public Map<Pair<String, String>, List<ToscaPolicy>> fetchDeployedPolicies(\r
121             String policyTypeId, String policyTypeVersion, String policyId) throws PfModelException {\r
122 \r
123         return collectDeployedPolicies(policyId, new PfConceptKey(policyTypeId, policyTypeVersion),\r
124                 modelsProvider::getPolicyList, List::addAll, new ArrayList<>());\r
125     }\r
126 \r
127     /**\r
128      * Creates a new policy for a policy type ID and version.\r
129      *\r
130      * @param policyTypeId the ID of policy type\r
131      * @param policyTypeVersion the version of policy type\r
132      * @param body the entity body of policy\r
133      *\r
134      * @return the ToscaServiceTemplate object\r
135      *\r
136      * @throws PfModelException the PfModel parsing exception\r
137      */\r
138     public ToscaServiceTemplate createPolicy(String policyTypeId, String policyTypeVersion,\r
139                                              ToscaServiceTemplate body) throws PfModelException {\r
140 \r
141         validatePolicyTypeExist(policyTypeId, policyTypeVersion);\r
142         validatePolicyTypeMatch(policyTypeId, policyTypeVersion, body);\r
143 \r
144         return modelsProvider.createPolicies(body);\r
145     }\r
146 \r
147     /**\r
148      * Deletes the policy matching specified ID and version of both policy type and policy.\r
149      *\r
150      * @param policyTypeId the ID of policy type\r
151      * @param policyTypeVersion the version of policy type\r
152      * @param policyId the ID of policy\r
153      * @param policyVersion the version of policy\r
154      *\r
155      * @return the ToscaServiceTemplate object\r
156      *\r
157      * @throws PfModelException the PfModel parsing exception\r
158      */\r
159     public ToscaServiceTemplate deletePolicy(String policyTypeId, String policyTypeVersion,\r
160                                  String policyId, String policyVersion) throws PfModelException {\r
161 \r
162         validateDeleteEligibility(policyTypeId, policyTypeVersion, policyId, policyVersion);\r
163 \r
164         ToscaServiceTemplate serviceTemplate = modelsProvider.deletePolicy(policyId, policyVersion);\r
165 \r
166         if (!hasPolicy(serviceTemplate)) {\r
167             throw new PfModelException(Response.Status.NOT_FOUND,\r
168                     constructResourceNotFoundMessage(policyTypeId, policyTypeVersion, policyId, policyVersion));\r
169         }\r
170 \r
171         return serviceTemplate;\r
172     }\r
173 \r
174     /**\r
175      * Validates whether policy type exists.\r
176      *\r
177      * @param policyTypeId the ID of policy type\r
178      * @param policyTypeVersion the version of policy type\r
179      *\r
180      * @throws PfModelException the PfModel parsing exception\r
181      */\r
182     private void validatePolicyTypeExist(String policyTypeId, String policyTypeVersion) throws PfModelException {\r
183 \r
184         ToscaServiceTemplate serviceTemplate = modelsProvider.getPolicyTypes(policyTypeId, policyTypeVersion);\r
185         if (!hasPolicyType(serviceTemplate)) {\r
186             throw new PfModelException(Response.Status.NOT_FOUND,\r
187                     "policy type with ID " + policyTypeId + ":" + policyTypeVersion + " does not exist");\r
188         }\r
189     }\r
190 \r
191     /**\r
192      * Validates the match between policy type specified in path and the one specified in type of policy.\r
193      *\r
194      * @param policyTypeId the ID of policy type\r
195      * @param policyTypeVersion the version of policy type\r
196      * @param serviceTemplate the ToscaServiceTemplate to validate\r
197      *\r
198      * @throws PfModelException the PfModel parsing exception\r
199      */\r
200     private void validatePolicyTypeMatch(String policyTypeId, String policyTypeVersion,\r
201             ToscaServiceTemplate serviceTemplate) throws PfModelException {\r
202 \r
203         List<Map<String, ToscaPolicy>> policies = serviceTemplate.getToscaTopologyTemplate().getPolicies();\r
204         for (Map<String, ToscaPolicy> policy : policies) {\r
205             if (policy.size() > 1) {\r
206                 throw new PfModelException(Response.Status.BAD_REQUEST,\r
207                         "one policy block contains more than one policies");\r
208             }\r
209             ToscaPolicy policyContent = policy.values().iterator().next();\r
210             if (!policyTypeId.equalsIgnoreCase(policyContent.getType())) {\r
211                 throw new PfModelException(Response.Status.BAD_REQUEST, "policy type id does not match");\r
212             }\r
213             if (policyContent.getTypeVersion() != null\r
214                     && !policyTypeVersion.equalsIgnoreCase(policyContent.getTypeVersion())) {\r
215                 throw new PfModelException(Response.Status.BAD_REQUEST, "policy type version does not match");\r
216             }\r
217         }\r
218     }\r
219 \r
220     /**\r
221      * Validates whether specified policy can be deleted based on the rule that deployed policy cannot be deleted.\r
222      *\r
223      * @param policyTypeId the ID of policy type\r
224      * @param policyTypeVersion the version of policy type\r
225      * @param policyId the ID of policy\r
226      * @param policyVersion the version of policy\r
227      *\r
228      * @throws PfModelException the PfModel parsing exception\r
229      */\r
230     private void validateDeleteEligibility(String policyTypeId, String policyTypeVersion,\r
231             String policyId, String policyVersion) throws PfModelException {\r
232 \r
233         List<ToscaPolicyTypeIdentifier> policyTypes = new ArrayList<>();\r
234         policyTypes.add(new ToscaPolicyTypeIdentifier(policyTypeId, policyTypeVersion));\r
235         List<ToscaPolicyIdentifier> policies = new ArrayList<>();\r
236         policies.add(new ToscaPolicyIdentifier(policyId, policyVersion));\r
237         PdpGroupFilter pdpGroupFilter = PdpGroupFilter.builder()\r
238                 .policyTypeList(policyTypes).policyList(policies).build();\r
239 \r
240         List<PdpGroup> pdpGroups = modelsProvider.getFilteredPdpGroups(pdpGroupFilter);\r
241 \r
242         if (!pdpGroups.isEmpty()) {\r
243             throw new PfModelException(Response.Status.CONFLICT,\r
244                     constructDeletePolicyViolationMessage(policyId, policyVersion, pdpGroups));\r
245         }\r
246     }\r
247 \r
248     /**\r
249      * Constructs returned message for not found resource.\r
250      *\r
251      * @param policyTypeId the ID of policy type\r
252      * @param policyTypeVersion the version of policy type\r
253      * @param policyId the ID of policy\r
254      * @param policyVersion the version of policy\r
255      *\r
256      * @return constructed message\r
257      */\r
258     private String constructResourceNotFoundMessage(String policyTypeId, String policyTypeVersion,\r
259             String policyId, String policyVersion) {\r
260 \r
261         return "policy with ID " + policyId + ":" + policyVersion\r
262                 + " and type " + policyTypeId + ":" + policyTypeVersion + " does not exist";\r
263     }\r
264 }\r