2 * ============LICENSE_START=======================================================
\r
4 * ================================================================================
\r
5 * Copyright (C) 2019-2020 AT&T Intellectual Property. All rights reserved.
\r
6 * Modifications Copyright (C) 2019 Nordix Foundation.
\r
7 * ================================================================================
\r
8 * Licensed under the Apache License, Version 2.0 (the "License");
\r
9 * you may not use this file except in compliance with the License.
\r
10 * You may obtain a copy of the License at
\r
12 * http://www.apache.org/licenses/LICENSE-2.0
\r
14 * Unless required by applicable law or agreed to in writing, software
\r
15 * distributed under the License is distributed on an "AS IS" BASIS,
\r
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
\r
17 * See the License for the specific language governing permissions and
\r
18 * limitations under the License.
\r
20 * SPDX-License-Identifier: Apache-2.0
\r
21 * ============LICENSE_END=========================================================
\r
24 package org.onap.policy.api.main.rest.provider;
\r
26 import java.util.ArrayList;
\r
27 import java.util.HashMap;
\r
28 import java.util.List;
\r
29 import java.util.Map;
\r
30 import java.util.function.BiConsumer;
\r
31 import javax.ws.rs.core.Response;
\r
33 import org.apache.commons.lang3.tuple.Pair;
\r
34 import org.onap.policy.api.main.parameters.ApiParameterGroup;
\r
35 import org.onap.policy.common.parameters.ParameterService;
\r
36 import org.onap.policy.models.base.PfConceptKey;
\r
37 import org.onap.policy.models.base.PfModelException;
\r
38 import org.onap.policy.models.pdp.concepts.PdpGroup;
\r
39 import org.onap.policy.models.pdp.concepts.PdpGroupFilter;
\r
40 import org.onap.policy.models.pdp.concepts.PdpSubGroup;
\r
41 import org.onap.policy.models.pdp.enums.PdpState;
\r
42 import org.onap.policy.models.provider.PolicyModelsProvider;
\r
43 import org.onap.policy.models.provider.PolicyModelsProviderFactory;
\r
44 import org.onap.policy.models.provider.PolicyModelsProviderParameters;
\r
45 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
\r
46 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyIdentifier;
\r
47 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyTypeIdentifier;
\r
48 import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;
\r
51 * Super class for providers that use a model provider.
\r
53 public class CommonModelProvider implements AutoCloseable {
\r
55 protected final PolicyModelsProvider modelsProvider;
\r
58 * Constructs the object, populating {@link #modelsProvider}.
\r
60 * @throws PfModelException if an error occurs
\r
62 public CommonModelProvider() throws PfModelException {
\r
64 ApiParameterGroup parameterGroup = ParameterService.get("ApiGroup");
\r
65 PolicyModelsProviderParameters providerParameters = parameterGroup.getDatabaseProviderParameters();
\r
66 modelsProvider = new PolicyModelsProviderFactory().createPolicyModelsProvider(providerParameters);
\r
70 * Closes the connection to database.
\r
72 * @throws PfModelException the PfModel parsing exception
\r
75 public void close() throws PfModelException {
\r
77 modelsProvider.close();
\r
81 * Checks if service template contains any policy.
\r
83 * @param serviceTemplate the service template to check against
\r
85 * @return boolean whether service template contains any policy
\r
87 protected boolean hasPolicy(ToscaServiceTemplate serviceTemplate) {
\r
89 return hasData(serviceTemplate.getToscaTopologyTemplate().getPolicies());
\r
93 * Checks if service template contains any policy type.
\r
95 * @param serviceTemplate the service template to check against
\r
97 * @return boolean whether service template contains any policy type
\r
99 protected boolean hasPolicyType(ToscaServiceTemplate serviceTemplate) {
\r
101 return hasData(serviceTemplate.getPolicyTypes());
\r
105 * Checks if the first element of a list of maps contains data.
\r
107 * @param listOfMapsToCheck list of maps to be examined
\r
108 * @return {@code true} if the list contains data, {@code false} otherwise
\r
110 protected <T> boolean hasData(List<Map<String, T>> listOfMapsToCheck) {
\r
112 return (listOfMapsToCheck != null && !listOfMapsToCheck.isEmpty() && !listOfMapsToCheck.get(0).isEmpty());
\r
117 * Checks if a maps contains data.
\r
119 * @param mapToCheck map to be examined
\r
120 * @return {@code true} if the list contains data, {@code false} otherwise
\r
122 protected <T> boolean hasData(Map<String, T> mapToCheck) {
\r
124 // We don't allow a null or empty map as well as a map entry with a valid key but null value
\r
125 return (mapToCheck != null && !mapToCheck.isEmpty() && !mapToCheck.containsValue(null));
\r
129 * Validates that some text represents a number.
\r
131 * @param text text to be validated
\r
132 * @param errorMsg error message included in the exception, if the text is not a valid
\r
134 * @throws PfModelException if the text is not a valid number
\r
136 protected void validNumber(String text, String errorMsg) throws PfModelException {
\r
138 Integer.parseInt(text);
\r
140 } catch (NumberFormatException exc) {
\r
141 throw new PfModelException(Response.Status.BAD_REQUEST, errorMsg, exc);
\r
146 * Constructs returned message for policy delete rule violation.
\r
148 * @param policyId the ID of policy
\r
149 * @param policyVersion the version of policy
\r
150 * @param pdpGroups the list of pdp groups
\r
152 * @return the constructed message
\r
154 protected String constructDeletePolicyViolationMessage(String policyId, String policyVersion,
\r
155 List<PdpGroup> pdpGroups) {
\r
157 List<String> pdpGroupNameVersionList = new ArrayList<>(pdpGroups.size());
\r
158 for (PdpGroup pdpGroup : pdpGroups) {
\r
159 pdpGroupNameVersionList.add(pdpGroup.getName() + ":" + pdpGroup.getVersion());
\r
161 String deployedPdpGroups = String.join(",", pdpGroupNameVersionList);
\r
162 return "policy with ID " + policyId + ":" + policyVersion
\r
163 + " cannot be deleted as it is deployed in pdp groups " + deployedPdpGroups;
\r
167 * Constructs returned message for policy type delete rule violation.
\r
169 * @param policyTypeId the ID of policy type
\r
170 * @param policyTypeVersion the version of policy type
\r
171 * @param policies the list of policies that parameterizes specified policy type
\r
173 * @return the constructed message
\r
175 protected String constructDeletePolicyTypeViolationMessage(String policyTypeId, String policyTypeVersion,
\r
176 List<ToscaPolicy> policies) {
\r
178 List<String> policyNameVersionList = new ArrayList<>(policies.size());
\r
179 for (ToscaPolicy policy : policies) {
\r
180 policyNameVersionList.add(policy.getName() + ":" + policy.getVersion());
\r
182 String parameterizedPolicies = String.join(",", policyNameVersionList);
\r
183 return "policy type with ID " + policyTypeId + ":" + policyTypeVersion
\r
184 + " cannot be deleted as it is parameterized by policies " + parameterizedPolicies;
\r
188 * Collects all deployed versions of specified policy in all pdp groups.
\r
190 * @param policyId the ID of policy
\r
191 * @param policyType the concept key of policy type
\r
192 * @param getter the custom generic getter Bifunction
\r
193 * @param consumer the BiConsumer
\r
194 * @param data the data structure storing retrieved deployed policies
\r
196 * @return a map between pdp group and deployed versions of specified policy in that group
\r
198 * @throws PfModelException the PfModel parsing exception
\r
200 protected <T, R> Map<Pair<String, String>, T> collectDeployedPolicies(String policyId, PfConceptKey policyType,
\r
201 BiFunctionWithEx<String, String, R> getter, BiConsumer<T, R> consumer, T data) throws PfModelException {
\r
203 List<PdpGroup> pdpGroups = getPolicyTypeFilteredPdpGroups(policyType);
\r
204 hasActivePdpGroup(pdpGroups, policyType, policyId);
\r
205 return constructDeployedPolicyMap(pdpGroups, policyId, policyType, getter, consumer, data);
\r
208 @FunctionalInterface
\r
209 protected interface BiFunctionWithEx<T,U,R> {
\r
210 public R apply(T value1, U value2) throws PfModelException;
\r
214 * Checks if the list of pdp groups is empty.
\r
215 * If so, throws exception saying specified policy deployment is not found in all existing pdp groups.
\r
217 * @param pdpGroups the list of pdp groups to check against
\r
218 * @param policyType the concept key of policy type
\r
219 * @param policyId the ID of policy
\r
221 * @throws PfModelException the PfModel parsing exception
\r
223 private void hasActivePdpGroup(List<PdpGroup> pdpGroups, PfConceptKey policyType, String policyId)
\r
224 throws PfModelException {
\r
226 if (pdpGroups.isEmpty()) {
\r
227 throw new PfModelException(Response.Status.NOT_FOUND,
\r
228 constructDeploymentNotFoundMessage(policyType, policyId));
\r
233 * Retrieves all pdp groups supporting specified policy type.
\r
235 * @param policyTypeId the ID of policy type
\r
236 * @param policyTypeVersion the version of policy type
\r
238 * @return a list of pdp groups supporting specified policy type
\r
240 * @throws PfModelException the PfModel parsing exception
\r
242 private List<PdpGroup> getPolicyTypeFilteredPdpGroups(PfConceptKey policyType)
\r
243 throws PfModelException {
\r
245 List<ToscaPolicyTypeIdentifier> policyTypes = new ArrayList<>();
\r
246 policyTypes.add(new ToscaPolicyTypeIdentifier(policyType.getName(), policyType.getVersion()));
\r
247 PdpGroupFilter pdpGroupFilter = PdpGroupFilter.builder().policyTypeList(policyTypes)
\r
248 .groupState(PdpState.ACTIVE).pdpState(PdpState.ACTIVE).build();
\r
249 return modelsProvider.getFilteredPdpGroups(pdpGroupFilter);
\r
253 * Constructs the map of deployed pdp groups and deployed policies.
\r
255 * @param pdpGroups the list of pdp groups that contain the specified policy
\r
256 * @param policyId the ID of policy
\r
257 * @param policyType the concept key of policy type
\r
258 * @param getter the custom generic getter BiFunction
\r
259 * @param consumer the BiConsumer
\r
260 * @param data the data structure storing retrieved deployed policies
\r
262 * @return the constructed map of pdp groups and deployed policies
\r
264 * @throws PfModelException the PfModel parsing exception
\r
266 private <T, R> Map<Pair<String, String>, T> constructDeployedPolicyMap(List<PdpGroup> pdpGroups, String policyId,
\r
267 PfConceptKey policyType, BiFunctionWithEx<String, String, R> getter, BiConsumer<T, R> consumer, T data)
\r
268 throws PfModelException {
\r
270 Map<Pair<String, String>, T> deployedPolicyMap = new HashMap<>();
\r
271 for (PdpGroup pdpGroup : pdpGroups) {
\r
272 List<ToscaPolicyIdentifier> policyIdentifiers = extractPolicyIdentifiers(policyId, pdpGroup, policyType);
\r
273 T deployedPolicies = getDeployedPolicies(policyIdentifiers, policyType, getter, consumer, data);
\r
274 deployedPolicyMap.put(Pair.of(pdpGroup.getName(), pdpGroup.getVersion()), deployedPolicies);
\r
276 return deployedPolicyMap;
\r
280 * Extracts policy identifiers matching specified policy ID from specified pdp group.
\r
282 * @param policyId the ID of policy to match
\r
283 * @param pdpGroup the target pdp group to search
\r
284 * @param policyType the concept key of policy type
\r
286 * @return the list of policy identifiers
\r
288 * @throws PfModelException the PfModel parsing exception
\r
290 private List<ToscaPolicyIdentifier> extractPolicyIdentifiers(String policyId, PdpGroup pdpGroup,
\r
291 PfConceptKey policyType) throws PfModelException {
\r
293 List<ToscaPolicyIdentifier> policyIdentifiers = new ArrayList<>();
\r
294 for (PdpSubGroup pdpSubGroup : pdpGroup.getPdpSubgroups()) {
\r
295 for (ToscaPolicyIdentifier policyIdentifier : pdpSubGroup.getPolicies()) {
\r
296 if (policyId.equalsIgnoreCase(policyIdentifier.getName())) {
\r
297 policyIdentifiers.add(policyIdentifier);
\r
301 if (policyIdentifiers.isEmpty()) {
\r
302 throw new PfModelException(Response.Status.NOT_FOUND,
\r
303 constructDeploymentNotFoundMessage(policyType, policyId));
\r
305 return policyIdentifiers;
\r
309 * Retrieves deployed policies in a generic way.
\r
311 * @param policyIdentifiers the identifiers of the policies to return
\r
312 * @param policyType the concept key of current policy type
\r
313 * @param getter the method reference of getting deployed policies
\r
314 * @param consumer the method reference of consuming the returned policies
\r
315 * @param data the data structure of deployed policies to return
\r
317 * @return the generic type of policy data structure to return
\r
319 * @throws PfModelException the PfModel parsing exception
\r
321 private <T, R> T getDeployedPolicies(List<ToscaPolicyIdentifier> policyIdentifiers, PfConceptKey policyType,
\r
322 BiFunctionWithEx<String, String, R> getter, BiConsumer<T, R> consumer, T data) throws PfModelException {
\r
324 for (ToscaPolicyIdentifier policyIdentifier : policyIdentifiers) {
\r
325 R result = getter.apply(policyIdentifier.getName(),
\r
326 getTrimedVersionForLegacyType(policyIdentifier.getVersion(), policyType));
\r
327 consumer.accept(data, result);
\r
333 * Trims the version for legacy policies.
\r
335 * @param fullVersion the full version format with major, minor, patch
\r
336 * @param policyType the concept key of policy type
\r
338 * @return the trimmed version
\r
340 private String getTrimedVersionForLegacyType(String fullVersion, PfConceptKey policyType) {
\r
341 return (policyType.getName().contains("guard")
\r
342 || policyType.getName().contains("Operational")) ? fullVersion.split("\\.")[0] : fullVersion;
\r
346 * Constructs returned message for not found policy deployment.
\r
348 * @param policyType the concept key of policy type
\r
349 * @param policyId the ID of policy
\r
351 * @return constructed message
\r
353 private String constructDeploymentNotFoundMessage(PfConceptKey policyType, String policyId) {
\r
355 return "could not find policy with ID " + policyId + " and type "
\r
356 + policyType.getName() + ":" + policyType.getVersion() + " deployed in any pdp group";
\r