Fix sonars in xacml-pdp
[policy/xacml-pdp.git] / applications / optimization / src / main / java / org / onap / policy / xacml / pdp / application / optimization / OptimizationPdpApplicationTranslator.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP
4  * ================================================================================
5  * Copyright (C) 2019-2021 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  * SPDX-License-Identifier: Apache-2.0
20  * ============LICENSE_END=========================================================
21  */
22
23 package org.onap.policy.xacml.pdp.application.optimization;
24
25 import com.att.research.xacml.api.Advice;
26 import com.att.research.xacml.api.AttributeAssignment;
27 import com.att.research.xacml.api.Identifier;
28 import com.att.research.xacml.api.XACML3;
29 import com.att.research.xacml.util.XACMLPolicyWriter;
30 import java.io.ByteArrayOutputStream;
31 import java.io.IOException;
32 import java.util.ArrayList;
33 import java.util.Arrays;
34 import java.util.Collection;
35 import java.util.HashMap;
36 import java.util.List;
37 import java.util.Map;
38 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AdviceExpressionType;
39 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AdviceExpressionsType;
40 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AnyOfType;
41 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeAssignmentExpressionType;
42 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeValueType;
43 import oasis.names.tc.xacml._3_0.core.schema.wd_17.EffectType;
44 import oasis.names.tc.xacml._3_0.core.schema.wd_17.ObjectFactory;
45 import oasis.names.tc.xacml._3_0.core.schema.wd_17.PolicyType;
46 import org.apache.commons.lang3.StringUtils;
47 import org.onap.policy.models.decisions.concepts.DecisionResponse;
48 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
49 import org.onap.policy.pdp.xacml.application.common.ToscaDictionary;
50 import org.onap.policy.pdp.xacml.application.common.ToscaPolicyConversionException;
51 import org.onap.policy.pdp.xacml.application.common.ToscaPolicyTranslatorUtils;
52 import org.onap.policy.pdp.xacml.application.common.std.StdMatchableTranslator;
53 import org.slf4j.Logger;
54 import org.slf4j.LoggerFactory;
55
56 public class OptimizationPdpApplicationTranslator extends StdMatchableTranslator {
57     private static final Logger LOGGER = LoggerFactory.getLogger(OptimizationPdpApplicationTranslator.class);
58
59     private static final String OPTIMIZATION_POLICYTYPE_SUBSCRIBER =
60             "onap.policies.optimization.service.SubscriberPolicy";
61
62     private static final String FIELD_SUBSCRIBER_ROLE = "subscriberRole";
63     private static final String FIELD_PROV_STATUS = "provStatus";
64
65     @SuppressWarnings("unchecked")
66     @Override
67     public Object convertPolicy(ToscaPolicy toscaPolicy) throws ToscaPolicyConversionException {
68         //
69         // Have our superclass do the work - NOTE we are assuming
70         // that we are getting a PolicyType converted.
71         //
72         PolicyType policy = (PolicyType) super.convertPolicy(toscaPolicy);
73         //
74         // Check if this is the subscriber policy
75         //
76         if (OPTIMIZATION_POLICYTYPE_SUBSCRIBER.equals(toscaPolicy.getType())) {
77             //
78             // Ensure the policy has the subscriber properties
79             //
80             Map<String, Object> subscriberProperties = (Map<String, Object>) toscaPolicy.getProperties()
81                     .get("subscriberProperties");
82             if (subscriberProperties == null) {
83                 throw new ToscaPolicyConversionException("Missing subscriberProperties from subscriber policy");
84             }
85             //
86             // Add subscriber name to the target so the policy
87             // only matches for the given subscriberName.
88             //
89             addSubscriberNameIntoTarget(policy, subscriberProperties);
90             //
91             // Add subscriber advice
92             //
93             policy.setAdviceExpressions(generateSubscriberAdvice(subscriberProperties));
94             //
95             // Dump our revised policy out
96             //
97             try (var os = new ByteArrayOutputStream()) {
98                 XACMLPolicyWriter.writePolicyFile(os, policy);
99                 LOGGER.info("{}", os);
100             } catch (IOException e) {
101                 LOGGER.error("Failed to create byte array stream", e);
102             }
103         }
104         return policy;
105     }
106
107     @Override
108     protected void scanAdvice(Collection<Advice> advice, DecisionResponse decisionResponse) {
109         for (Advice adv : advice) {
110             if (! ToscaDictionary.ID_ADVICE_OPTIMIZATION_SUBSCRIBER.equals(adv.getId())) {
111                 LOGGER.warn("Unknown advice id {}", adv.getId());
112                 continue;
113             }
114             //
115             // Get the existing advice if any, we are appending to it.
116             //
117             Map<String, Object> mapAdvice = decisionResponse.getAdvice();
118             //
119             // If there's nothing, create a map
120             //
121             if (mapAdvice == null) {
122                 mapAdvice = new HashMap<>();
123             }
124             for (AttributeAssignment assignment : adv.getAttributeAssignments()) {
125                 if (ToscaDictionary.ID_ADVICE_OPTIMIZATION_SUBSCRIBER_ROLE.equals(assignment.getAttributeId())) {
126                     addValuesToMap(assignment.getAttributeValue().getValue(), FIELD_SUBSCRIBER_ROLE, mapAdvice);
127                 } else if (ToscaDictionary.ID_ADVICE_OPTIMIZATION_SUBSCRIBER_STATUS.equals(
128                         assignment.getAttributeId())) {
129                     addValuesToMap(assignment.getAttributeValue().getValue(), FIELD_PROV_STATUS, mapAdvice);
130                 }
131             }
132             if (! mapAdvice.isEmpty()) {
133                 decisionResponse.setAdvice(mapAdvice);
134             }
135         }
136     }
137
138     @SuppressWarnings("unchecked")
139     private static void addValuesToMap(Object values, String key, Map<String, Object> mapAdvice) {
140         if (values instanceof Collection) {
141             List<String> valueList = new ArrayList<>();
142             ((Collection<Object>) values).forEach(val -> valueList.add(val.toString()));
143             mapAdvice.put(key, valueList);
144         } else {
145             mapAdvice.put(key, values.toString());
146         }
147
148     }
149
150     @SuppressWarnings("unchecked")
151     private static PolicyType addSubscriberNameIntoTarget(PolicyType policy,
152             Map<String, Object> subscriberProperties) throws ToscaPolicyConversionException {
153         //
154         // Find the subscriber names
155         //
156         Object subscriberNames = subscriberProperties.get("subscriberName");
157         if (subscriberNames == null) {
158             throw new ToscaPolicyConversionException("Missing subscriberName property");
159         }
160         //
161         // Iterate through all the subscriber names
162         //
163         var anyOf = new AnyOfType();
164         for (Object subscriberName : subscriberNames instanceof Collection ? (List<Object>) subscriberNames :
165             Arrays.asList(subscriberNames)) {
166
167             var match = ToscaPolicyTranslatorUtils.buildMatchTypeDesignator(
168                     XACML3.ID_FUNCTION_STRING_EQUAL,
169                     subscriberName,
170                     XACML3.ID_DATATYPE_STRING,
171                     ToscaDictionary.ID_SUBJECT_OPTIMIZATION_SUBSCRIBER_NAME,
172                     XACML3.ID_SUBJECT_CATEGORY_ACCESS_SUBJECT);
173
174             anyOf.getAllOf().add(ToscaPolicyTranslatorUtils.buildAllOf(match));
175         }
176         //
177         // Add to the target
178         //
179         policy.getTarget().getAnyOf().add(anyOf);
180         //
181         // Return for convenience
182         //
183         return policy;
184     }
185
186     @SuppressWarnings("unchecked")
187     private static AdviceExpressionsType generateSubscriberAdvice(Map<String, Object> subscriberProperties)
188             throws ToscaPolicyConversionException {
189         //
190         // Get the subscriber role
191         //
192         Object role = subscriberProperties.get(FIELD_SUBSCRIBER_ROLE);
193         if (role == null || StringUtils.isBlank(role.toString())) {
194             throw new ToscaPolicyConversionException("Missing subscriberRole");
195         }
196         //
197         // Create our subscriber advice expression
198         //
199         var adviceExpression = new AdviceExpressionType();
200         adviceExpression.setAppliesTo(EffectType.PERMIT);
201         adviceExpression.setAdviceId(ToscaDictionary.ID_ADVICE_OPTIMIZATION_SUBSCRIBER.stringValue());
202         //
203         // Add in subscriber role advice attributes
204         //
205         generateSubscriberAdviceAttributes(
206                 adviceExpression,
207                 ToscaDictionary.ID_ADVICE_OPTIMIZATION_SUBSCRIBER_ROLE,
208                 role instanceof Collection ? (List<Object>) role : Arrays.asList(role));
209         //
210         // Get the provision status
211         //
212         Object provision = subscriberProperties.get(FIELD_PROV_STATUS);
213         if (provision == null || StringUtils.isBlank(provision.toString())) {
214             throw new ToscaPolicyConversionException("Missing provStatus");
215         }
216         adviceExpression = generateSubscriberAdviceAttributes(
217                 adviceExpression,
218                 ToscaDictionary.ID_ADVICE_OPTIMIZATION_SUBSCRIBER_STATUS,
219                 role instanceof Collection ? (List<Object>) provision : Arrays.asList(role));
220         //
221         // Add it to the overall expressions
222         //
223         var adviceExpressions = new AdviceExpressionsType();
224         adviceExpressions.getAdviceExpression().add(adviceExpression);
225         //
226         // Done return our advice expressions
227         //
228         return adviceExpressions;
229     }
230
231     private static AdviceExpressionType generateSubscriberAdviceAttributes(AdviceExpressionType adviceExpression,
232             Identifier attributeId, Collection<Object> adviceAttribute) {
233         for (Object attribute : adviceAttribute) {
234             var value = new AttributeValueType();
235             value.setDataType(XACML3.ID_DATATYPE_STRING.stringValue());
236             value.getContent().add(attribute.toString());
237
238             var assignment = new AttributeAssignmentExpressionType();
239             assignment.setAttributeId(attributeId.stringValue());
240             assignment.setCategory(XACML3.ID_SUBJECT_CATEGORY_ACCESS_SUBJECT.stringValue());
241             assignment.setExpression(new ObjectFactory().createAttributeValue(value));
242
243             adviceExpression.getAttributeAssignmentExpression().add(assignment);
244         }
245         //
246         // Return for convenience
247         //
248         return adviceExpression;
249     }
250 }