2 * ============LICENSE_START=======================================================
\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
11 * http://www.apache.org/licenses/LICENSE-2.0
\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
19 * SPDX-License-Identifier: Apache-2.0
\r
20 * ============LICENSE_END=========================================================
\r
23 package org.onap.policy.api.main.rest.provider;
\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.api.main.parameters.ApiParameterGroup;
\r
32 import org.onap.policy.common.parameters.ParameterService;
\r
33 import org.onap.policy.models.base.PfModelException;
\r
34 import org.onap.policy.models.pdp.concepts.PdpGroup;
\r
35 import org.onap.policy.models.pdp.concepts.PdpGroupFilter;
\r
36 import org.onap.policy.models.pdp.concepts.PdpSubGroup;
\r
37 import org.onap.policy.models.pdp.enums.PdpState;
\r
38 import org.onap.policy.models.provider.PolicyModelsProvider;
\r
39 import org.onap.policy.models.provider.PolicyModelsProviderFactory;
\r
40 import org.onap.policy.models.provider.PolicyModelsProviderParameters;
\r
41 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
\r
42 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyFilter;
\r
43 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyIdentifier;
\r
44 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyTypeIdentifier;
\r
45 import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;
\r
48 * Class to provide all kinds of policy operations.
\r
50 * @author Chenfei Gao (cgao@research.att.com)
\r
52 public class PolicyProvider implements AutoCloseable {
\r
54 private PolicyModelsProvider modelsProvider;
\r
57 * Default constructor.
\r
59 public PolicyProvider() throws PfModelException {
\r
61 ApiParameterGroup parameterGroup = ParameterService.get("ApiGroup");
\r
62 PolicyModelsProviderParameters providerParameters = parameterGroup.getDatabaseProviderParameters();
\r
63 modelsProvider = new PolicyModelsProviderFactory().createPolicyModelsProvider(providerParameters);
\r
67 * Retrieves a list of policies matching specified ID and version of both policy type and policy.
\r
69 * @param policyTypeId the ID of policy type
\r
70 * @param policyTypeVersion the version of policy type
\r
71 * @param policyId the ID of policy
\r
72 * @param policyVersion the version of policy
\r
74 * @return the ToscaServiceTemplate object
\r
76 * @throws PfModelException the PfModel parsing exception
\r
78 public ToscaServiceTemplate fetchPolicies(String policyTypeId, String policyTypeVersion,
\r
79 String policyId, String policyVersion) throws PfModelException {
\r
81 ToscaPolicyFilter policyFilter = ToscaPolicyFilter.builder()
\r
82 .name(policyId).version(policyVersion)
\r
83 .type(policyTypeId).typeVersion(policyTypeVersion).build();
\r
84 ToscaServiceTemplate serviceTemplate = modelsProvider.getFilteredPolicies(policyFilter);
\r
86 if (!hasPolicy(serviceTemplate)) {
\r
87 throw new PfModelException(Response.Status.NOT_FOUND,
\r
88 constructResourceNotFoundMessage(policyTypeId, policyTypeVersion, policyId, policyVersion));
\r
91 return serviceTemplate;
\r
95 * Retrieves a list of policies with the latest versions that match specified policy type id and version.
\r
97 * @param policyTypeId the ID of policy type
\r
98 * @param policyTypeVersion the version of policy type
\r
99 * @param policyId the ID of the policy
\r
101 * @return the ToscaServiceTemplate object
\r
103 * @throws PfModelException the PfModel parsing exception
\r
105 public ToscaServiceTemplate fetchLatestPolicies(String policyTypeId, String policyTypeVersion,
\r
106 String policyId) throws PfModelException {
\r
108 ToscaPolicyFilter policyFilter = ToscaPolicyFilter.builder()
\r
109 .name(policyId).version(ToscaPolicyFilter.LATEST_VERSION)
\r
110 .type(policyTypeId).typeVersion(policyTypeVersion).build();
\r
111 ToscaServiceTemplate serviceTemplate = modelsProvider.getFilteredPolicies(policyFilter);
\r
113 if (!hasPolicy(serviceTemplate)) {
\r
114 throw new PfModelException(Response.Status.NOT_FOUND,
\r
115 constructResourceNotFoundMessage(policyTypeId, policyTypeVersion, policyId, null));
\r
118 return serviceTemplate;
\r
122 * Retrieves a list of deployed policies in each pdp group.
\r
124 * @param policyTypeId the ID of policy type
\r
125 * @param policyTypeVersion the version of policy type
\r
126 * @param policyId the ID of the policy
\r
128 * @return a list of deployed policies in each pdp group
\r
130 * @throws PfModelException the PfModel parsing exception
\r
132 public Map<Pair<String, String>, List<ToscaPolicy>> fetchDeployedPolicies(
\r
133 String policyTypeId, String policyTypeVersion, String policyId) throws PfModelException {
\r
135 List<ToscaPolicyTypeIdentifier> policyTypes = new ArrayList<>();
\r
136 policyTypes.add(new ToscaPolicyTypeIdentifier(policyTypeId, policyTypeVersion));
\r
137 PdpGroupFilter pdpGroupFilter = PdpGroupFilter.builder().policyTypeList(policyTypes)
\r
138 .groupState(PdpState.ACTIVE).pdpState(PdpState.ACTIVE).build();
\r
139 List<PdpGroup> pdpGroups = modelsProvider.getFilteredPdpGroups(pdpGroupFilter);
\r
141 if (pdpGroups.isEmpty()) {
\r
142 throw new PfModelException(Response.Status.NOT_FOUND,
\r
143 constructDeploymentNotFoundMessage(policyTypeId, policyTypeVersion, policyId));
\r
146 Map<Pair<String, String>, List<ToscaPolicy>> deployedPolicyMap =
\r
147 constructDeployedPolicyMap(pdpGroups, policyId);
\r
148 if (deployedPolicyMap.isEmpty()) {
\r
149 throw new PfModelException(Response.Status.NOT_FOUND,
\r
150 constructDeploymentNotFoundMessage(policyTypeId, policyTypeVersion, policyId));
\r
153 return deployedPolicyMap;
\r
157 * Creates a new policy for a policy type ID and version.
\r
159 * @param policyTypeId the ID of policy type
\r
160 * @param policyTypeVersion the version of policy type
\r
161 * @param body the entity body of policy
\r
163 * @return the ToscaServiceTemplate object
\r
165 * @throws PfModelException the PfModel parsing exception
\r
167 public ToscaServiceTemplate createPolicy(String policyTypeId, String policyTypeVersion,
\r
168 ToscaServiceTemplate body) throws PfModelException {
\r
170 validatePolicyTypeExist(policyTypeId, policyTypeVersion);
\r
171 validatePolicyTypeMatch(policyTypeId, policyTypeVersion, body);
\r
173 return modelsProvider.createPolicies(body);
\r
177 * Deletes the policy matching specified ID and version of both policy type and policy.
\r
179 * @param policyTypeId the ID of policy type
\r
180 * @param policyTypeVersion the version of policy type
\r
181 * @param policyId the ID of policy
\r
182 * @param policyVersion the version of policy
\r
184 * @return the ToscaServiceTemplate object
\r
186 * @throws PfModelException the PfModel parsing exception
\r
188 public ToscaServiceTemplate deletePolicy(String policyTypeId, String policyTypeVersion,
\r
189 String policyId, String policyVersion) throws PfModelException {
\r
191 validateDeleteEligibility(policyTypeId, policyTypeVersion, policyId, policyVersion);
\r
193 ToscaServiceTemplate serviceTemplate = modelsProvider.deletePolicy(policyId, policyVersion);
\r
195 if (!hasPolicy(serviceTemplate)) {
\r
196 throw new PfModelException(Response.Status.NOT_FOUND,
\r
197 constructResourceNotFoundMessage(policyTypeId, policyTypeVersion, policyId, policyVersion));
\r
200 return serviceTemplate;
\r
204 * Validates whether policy type exists.
\r
206 * @param policyTypeId the ID of policy type
\r
207 * @param policyTypeVersion the version of policy type
\r
209 * @throws PfModelException the PfModel parsing exception
\r
211 private void validatePolicyTypeExist(String policyTypeId, String policyTypeVersion) throws PfModelException {
\r
213 ToscaServiceTemplate serviceTemplate = modelsProvider.getPolicyTypes(policyTypeId, policyTypeVersion);
\r
214 if (!hasPolicyType(serviceTemplate)) {
\r
215 throw new PfModelException(Response.Status.NOT_FOUND,
\r
216 "policy type with ID " + policyTypeId + ":" + policyTypeVersion + " does not exist");
\r
221 * Validates the match between policy type specified in path and the one specified in type of policy.
\r
223 * @param policyTypeId the ID of policy type
\r
224 * @param policyTypeVersion the version of policy type
\r
225 * @param serviceTemplate the ToscaServiceTemplate to validate
\r
227 * @throws PfModelException the PfModel parsing exception
\r
229 private void validatePolicyTypeMatch(String policyTypeId, String policyTypeVersion,
\r
230 ToscaServiceTemplate serviceTemplate) throws PfModelException {
\r
232 List<Map<String, ToscaPolicy>> policies = serviceTemplate.getToscaTopologyTemplate().getPolicies();
\r
233 for (Map<String, ToscaPolicy> policy : policies) {
\r
234 if (policy.size() > 1) {
\r
235 throw new PfModelException(Response.Status.BAD_REQUEST,
\r
236 "one policy block contains more than one policies");
\r
238 ToscaPolicy policyContent = policy.values().iterator().next();
\r
239 if (!policyTypeId.equalsIgnoreCase(policyContent.getType())) {
\r
240 throw new PfModelException(Response.Status.BAD_REQUEST, "policy type id does not match");
\r
242 if (policyContent.getTypeVersion() != null
\r
243 && !policyTypeVersion.equalsIgnoreCase(policyContent.getTypeVersion())) {
\r
244 throw new PfModelException(Response.Status.BAD_REQUEST, "policy type version does not match");
\r
250 * Validates whether specified policy can be deleted based on the rule that deployed policy cannot be deleted.
\r
252 * @param policyTypeId the ID of policy type
\r
253 * @param policyTypeVersion the version of policy type
\r
254 * @param policyId the ID of policy
\r
255 * @param policyVersion the version of policy
\r
257 * @throws PfModelException the PfModel parsing exception
\r
259 private void validateDeleteEligibility(String policyTypeId, String policyTypeVersion,
\r
260 String policyId, String policyVersion) throws PfModelException {
\r
262 List<ToscaPolicyTypeIdentifier> policyTypes = new ArrayList<>();
\r
263 policyTypes.add(new ToscaPolicyTypeIdentifier(policyTypeId, policyTypeVersion));
\r
264 List<ToscaPolicyIdentifier> policies = new ArrayList<>();
\r
265 policies.add(new ToscaPolicyIdentifier(policyId, policyVersion));
\r
266 PdpGroupFilter pdpGroupFilter = PdpGroupFilter.builder()
\r
267 .policyTypeList(policyTypes).policyList(policies).build();
\r
269 List<PdpGroup> pdpGroups = modelsProvider.getFilteredPdpGroups(pdpGroupFilter);
\r
271 if (!pdpGroups.isEmpty()) {
\r
272 throw new PfModelException(Response.Status.CONFLICT,
\r
273 constructDeleteRuleViolationMessage(policyId, policyVersion, pdpGroups));
\r
278 * Constructs returned message for policy delete rule violation.
\r
280 * @param policyId the ID of policy
\r
281 * @param policyVersion the version of policy
\r
282 * @param pdpGroups the list of pdp groups
\r
284 * @return the constructed message
\r
286 private String constructDeleteRuleViolationMessage(
\r
287 String policyId, String policyVersion, List<PdpGroup> pdpGroups) {
\r
289 List<String> pdpGroupNameVersionList = new ArrayList<>();
\r
290 for (PdpGroup pdpGroup : pdpGroups) {
\r
291 pdpGroupNameVersionList.add(pdpGroup.getName() + ":" + pdpGroup.getVersion());
\r
293 String deployedPdpGroups = String.join(",", pdpGroupNameVersionList);
\r
294 return "policy with ID " + policyId + ":" + policyVersion
\r
295 + " cannot be deleted as it is deployed in pdp groups " + deployedPdpGroups;
\r
299 * Constructs the map of deployed pdp groups and deployed policies.
\r
301 * @param pdpGroups the list of pdp groups that contain the specified policy
\r
302 * @param policyId the ID of policy
\r
304 * @return the constructed map of pdp groups and deployed policies
\r
306 * @throws PfModelException the PfModel parsing exception
\r
308 private Map<Pair<String, String>, List<ToscaPolicy>> constructDeployedPolicyMap(
\r
309 List<PdpGroup> pdpGroups, String policyId) throws PfModelException {
\r
311 Map<Pair<String, String>, List<ToscaPolicy>> deployedPolicyMap = new HashMap<>();
\r
312 for (PdpGroup pdpGroup : pdpGroups) {
\r
313 List<ToscaPolicyIdentifier> policyIdentifiers = new ArrayList<>();
\r
314 for (PdpSubGroup pdpSubGroup : pdpGroup.getPdpSubgroups()) {
\r
315 for (ToscaPolicyIdentifier policyIdentifier : pdpSubGroup.getPolicies()) {
\r
316 if (policyId.equalsIgnoreCase(policyIdentifier.getName())) {
\r
317 policyIdentifiers.add(policyIdentifier);
\r
321 List<ToscaPolicy> deployedPolicies = new ArrayList<>();
\r
322 if (!policyIdentifiers.isEmpty()) {
\r
323 for (ToscaPolicyIdentifier policyIdentifier : policyIdentifiers) {
\r
324 deployedPolicies.addAll(
\r
325 modelsProvider.getPolicyList(policyIdentifier.getName(), policyIdentifier.getVersion()));
\r
328 if (!deployedPolicies.isEmpty()) {
\r
329 deployedPolicyMap.put(Pair.of(pdpGroup.getName(), pdpGroup.getVersion()), deployedPolicies);
\r
332 return deployedPolicyMap;
\r
336 * Constructs returned message for not found resource.
\r
338 * @param policyTypeId the ID of policy type
\r
339 * @param policyTypeVersion the version of policy type
\r
340 * @param policyId the ID of policy
\r
341 * @param policyVersion the version of policy
\r
343 * @return constructed message
\r
345 private String constructResourceNotFoundMessage(String policyTypeId, String policyTypeVersion,
\r
346 String policyId, String policyVersion) {
\r
348 return "policy with ID " + policyId + ":" + policyVersion
\r
349 + " and type " + policyTypeId + ":" + policyTypeVersion + " does not exist";
\r
353 * Constructs returned message for not found policy deployment.
\r
355 * @param policyTypeId the ID of policy type
\r
356 * @param policyTypeVersion the version of policy type
\r
357 * @param policyId the ID of policy
\r
358 * @param policyVersion the version of policy
\r
360 * @return constructed message
\r
362 private String constructDeploymentNotFoundMessage(String policyTypeId, String policyTypeVersion,
\r
365 return "could not find policy with ID " + policyId + " and type "
\r
366 + policyTypeId + ":" + policyTypeVersion + " deployed in any pdp group";
\r
370 * Checks if service template contains any policy.
\r
372 * @param serviceTemplate the service template to check against
\r
374 * @return boolean whether service template contains any policy
\r
376 private boolean hasPolicy(ToscaServiceTemplate serviceTemplate) {
\r
378 if (serviceTemplate.getToscaTopologyTemplate().getPolicies() == null) {
\r
380 } else if (serviceTemplate.getToscaTopologyTemplate().getPolicies().isEmpty()) {
\r
382 } else if (serviceTemplate.getToscaTopologyTemplate().getPolicies().get(0).isEmpty()) {
\r
390 * Checks if service template contains any policy type.
\r
392 * @param serviceTemplate the service template to check against
\r
394 * @return boolean whether service template contains any policy type
\r
396 private boolean hasPolicyType(ToscaServiceTemplate serviceTemplate) {
\r
398 if (serviceTemplate.getPolicyTypes() == null) {
\r
400 } else if (serviceTemplate.getPolicyTypes().isEmpty()) {
\r
402 } else if (serviceTemplate.getPolicyTypes().get(0).isEmpty()) {
\r
410 * Closes the connection to database.
\r
412 * @throws PfModelException the PfModel parsing exception
\r
415 public void close() throws PfModelException {
\r
417 modelsProvider.close();
\r