Merge "Fix Sonar issues in org.onap.policy.controller pkg"
[policy/engine.git] / POLICY-SDK-APP / src / main / java / org / onap / policy / controller / CreateBRMSParamController.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP Policy Engine
4  * ================================================================================
5  * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
6  * Modified Copyright (C) 2018 Samsung Electronics Co., Ltd.
7  * Modifications Copyright (C) 2019 Bell Canada
8  * ================================================================================
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  * ============LICENSE_END=========================================================
21  */
22
23 package org.onap.policy.controller;
24
25 import java.io.PrintWriter;
26 import java.util.ArrayList;
27 import java.util.Arrays;
28 import java.util.Collection;
29 import java.util.HashMap;
30 import java.util.Iterator;
31 import java.util.LinkedHashMap;
32 import java.util.List;
33 import java.util.Map;
34 import java.util.Map.Entry;
35 import java.util.Objects;
36 import java.util.Set;
37 import java.util.regex.Matcher;
38 import java.util.regex.Pattern;
39
40 import java.util.stream.Collectors;
41 import javax.servlet.http.HttpServletRequest;
42 import javax.servlet.http.HttpServletResponse;
43 import javax.xml.bind.JAXBElement;
44
45 import org.apache.commons.collections.CollectionUtils;
46 import org.json.JSONObject;
47 import org.onap.policy.common.logging.flexlogger.FlexLogger;
48 import org.onap.policy.common.logging.flexlogger.Logger;
49 import org.onap.policy.rest.adapter.PolicyRestAdapter;
50 import org.onap.policy.rest.dao.CommonClassDao;
51 import org.onap.policy.rest.jpa.BRMSParamTemplate;
52 import org.onap.policy.rest.jpa.PolicyEntity;
53 import org.onap.policy.xacml.api.XACMLErrorConstants;
54 import org.onap.portalsdk.core.controller.RestrictedBaseController;
55 import org.springframework.beans.factory.annotation.Autowired;
56 import org.springframework.stereotype.Controller;
57 import org.springframework.web.bind.annotation.RequestMapping;
58 import org.springframework.web.bind.annotation.RequestMethod;
59
60 import com.fasterxml.jackson.databind.DeserializationFeature;
61 import com.fasterxml.jackson.databind.JsonNode;
62 import com.fasterxml.jackson.databind.ObjectMapper;
63
64 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AdviceExpressionType;
65 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AdviceExpressionsType;
66 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AnyOfType;
67 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeAssignmentExpressionType;
68 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeDesignatorType;
69 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeValueType;
70 import oasis.names.tc.xacml._3_0.core.schema.wd_17.MatchType;
71 import oasis.names.tc.xacml._3_0.core.schema.wd_17.PolicyType;
72 import oasis.names.tc.xacml._3_0.core.schema.wd_17.RuleType;
73 import oasis.names.tc.xacml._3_0.core.schema.wd_17.TargetType;
74
75 @Controller
76 @RequestMapping("/")
77 public class CreateBRMSParamController extends RestrictedBaseController {
78
79     private static final Logger policyLogger = FlexLogger.getLogger(CreateBRMSParamController.class);
80
81     private static CommonClassDao commonClassDao;
82
83     public static CommonClassDao getCommonClassDao() {
84         return commonClassDao;
85     }
86
87     public static void setCommonClassDao(CommonClassDao commonClassDao) {
88         CreateBRMSParamController.commonClassDao = commonClassDao;
89     }
90
91     @Autowired
92     private CreateBRMSParamController(CommonClassDao commonClassDao) {
93         CreateBRMSParamController.commonClassDao = commonClassDao;
94     }
95
96     public CreateBRMSParamController() {
97         // Empty constructor
98     }
99
100     protected PolicyRestAdapter policyAdapter = null;
101
102     private HashMap<String, String> dynamicLayoutMap;
103
104     private static String brmsTemplateVlaue = "<$%BRMSParamTemplate=";
105     private static String string = "String";
106
107
108     @RequestMapping(value = {"/policyController/getBRMSTemplateData.htm"}, method = { RequestMethod.POST})
109     public void getBRMSParamPolicyRuleData(HttpServletRequest request, HttpServletResponse response) {
110         try {
111             dynamicLayoutMap = new HashMap<>();
112             ObjectMapper mapper = new ObjectMapper();
113             mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
114             JsonNode root = mapper.readTree(request.getReader());
115             String rule = findRule(root.get(PolicyController.getPolicydata()).toString().replaceAll("^\"|\"$", ""));
116             generateUI(rule);
117             response.setCharacterEncoding(PolicyController.getCharacterencoding());
118             response.setContentType(PolicyController.getContenttype());
119             request.setCharacterEncoding(PolicyController.getCharacterencoding());
120
121             PrintWriter out = response.getWriter();
122             String responseString = mapper.writeValueAsString(dynamicLayoutMap);
123             JSONObject j = new JSONObject("{policyData: " + responseString + "}");
124             out.write(j.toString());
125         } catch (Exception e) {
126             policyLogger.error("Exception Occured while getting BRMS Rule data", e);
127         }
128     }
129
130     private String findRule(String ruleTemplate) {
131         List<Object> datas = commonClassDao.getDataById(BRMSParamTemplate.class, "ruleName", ruleTemplate);
132         if(CollectionUtils.isNotEmpty(datas)){
133             BRMSParamTemplate bRMSParamTemplate = (BRMSParamTemplate) datas.get(0);
134             return bRMSParamTemplate.getRule();
135         }
136         return null;
137     }
138
139     private void generateUI(String rule) {
140         if (rule == null) {
141             return;
142         }
143         try {
144             processRule(rule);
145         } catch (Exception e) {
146             policyLogger.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + e);
147         }
148
149     }
150
151     private void processRule(String rule) {
152         StringBuilder params = getParamsBuilderFromRule(rule);
153         params = new StringBuilder(
154             params.toString().replace("declare Params", "").replace("end", "").replaceAll("\\s+", ""));
155         String[] components = params.toString().split(":");
156         String caption = "";
157         for (int i = 0; i < components.length; i++) {
158             String type;
159             if (i == 0) {
160                 caption = components[i];
161             }
162             if ("".equals(caption)) {
163                 break;
164             }
165             String nextComponent;
166             try {
167                 nextComponent = components[i + 1];
168             } catch (Exception e) {
169                 policyLogger.info("Error when procesing rule: " + e);
170                 nextComponent = components[i];
171             }
172             if (nextComponent.startsWith(string)) {
173                 type = "String";
174                 createField(caption, type);
175                 caption = nextComponent.replace(string, "");
176             } else if (nextComponent.startsWith("int")) {
177                 type = "int";
178                 createField(caption, type);
179                 caption = nextComponent.replace("int", "");
180             }
181         }
182     }
183
184     private StringBuilder getParamsBuilderFromRule(final String rule) {
185         StringBuilder params = new StringBuilder();
186         boolean flag = false;
187         boolean comment = false;
188         String[] lines = rule.split("\n");
189         for (String line : lines) {
190             if (line.isEmpty() || line.startsWith("//")) {
191                 continue;
192             }
193             if (line.startsWith("/*")) {
194                 comment = true;
195                 continue;
196             }
197             if (line.contains("//")) {
198                 line = splitSingleLineComment(line);
199             }
200             if (line.contains("/*")) {
201                 comment = true;
202                 if (line.contains("*/")) {
203                     comment = false;
204                     line = processMultiLineFullComment(line);
205                 } else {
206                     line = splitMultiLineStartComment(line);
207                 }
208             }
209             if (line.contains("*/")) {
210                 comment = false;
211                 line = processEndComment(line);
212             }
213             if (comment) {
214                 continue;
215             }
216             if (flag) {
217                 params.append(line);
218             }
219             if (line.contains("declare Params")) {
220                 params.append(line);
221                 flag = true;
222             }
223             if (line.contains("end") && flag) {
224                 break;
225             }
226         }
227         return params;
228     }
229
230     private String splitMultiLineStartComment(String line) {
231         return line.split("\\/\\*")[0];
232     }
233
234     private String splitMultiLineEndComment(String line) {
235         return line.split("\\*\\/")[1].replace("*/", "");
236     }
237
238     private String splitSingleLineComment(String line) {
239         return line.split("\\/\\/")[0];
240     }
241
242     private void createField(String caption, String type) {
243         dynamicLayoutMap.put(caption, type);
244     }
245
246     /*
247      * When the User Click Edit or View Policy the following method will get invoked for setting the data to PolicyRestAdapter.
248      * Which is used to bind the data in GUI
249      */
250     public void prePopulateBRMSParamPolicyData(PolicyRestAdapter policyAdapter, PolicyEntity entity) {
251         dynamicLayoutMap = new HashMap<>();
252         if (policyAdapter.getPolicyData() instanceof PolicyType) {
253             PolicyType policy = (PolicyType) policyAdapter.getPolicyData();
254             policyAdapter.setOldPolicyFileName(policyAdapter.getPolicyName());
255             // policy name value is the policy name without any prefix and
256             // Extensions.
257             String policyNameValue = policyAdapter.getPolicyName()
258                 .substring(policyAdapter.getPolicyName().indexOf("BRMS_Param_") + 11);
259             if (policyLogger.isDebugEnabled()) {
260                 policyLogger
261                     .debug("Prepopulating form data for BRMS RAW Policy selected:" + policyAdapter.getPolicyName());
262             }
263             policyAdapter.setPolicyName(policyNameValue);
264             String description;
265             try {
266                 description = policy.getDescription().substring(0, policy.getDescription().indexOf("@CreatedBy:"));
267             } catch (Exception e) {
268                 policyLogger.info("Error getting description: " + e);
269                 description = policy.getDescription();
270             }
271             policyAdapter.setPolicyDescription(description);
272             setDataAdapterFromAdviceExpressions(policy, policyAdapter);
273
274             // Generate Param UI
275             try {
276                 paramUIGenerate(policyAdapter, entity);
277             } catch (Exception e) {
278                 policyLogger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + e.getMessage() + e);
279             }
280
281             // Get the target data under policy.
282             policyAdapter.setDynamicLayoutMap(dynamicLayoutMap);
283             if (policyAdapter.getDynamicLayoutMap().size() > 0) {
284                 LinkedHashMap<String, String> drlRule = policyAdapter.getDynamicLayoutMap()
285                     .keySet().stream()
286                     .collect(Collectors
287                         .toMap(String::toString, keyValue -> policyAdapter.getDynamicLayoutMap().get(keyValue),
288                             (a, b) -> b, LinkedHashMap::new));
289                 policyAdapter.setRuleData(drlRule);
290             }
291             TargetType target = policy.getTarget();
292             if (target != null) {
293                 setDataToAdapterFromTarget(target, policyAdapter);
294             }
295         }
296     }
297
298     private void setDataAdapterFromAdviceExpressions(PolicyType policy, PolicyRestAdapter policyAdapter) {
299         ArrayList<Object> attributeList = new ArrayList<>();
300         // Set Attributes.
301         AdviceExpressionsType expressionTypes = ((RuleType) policy
302             .getCombinerParametersOrRuleCombinerParametersOrVariableDefinition().get(0)).getAdviceExpressions();
303         for (AdviceExpressionType adviceExpression : expressionTypes.getAdviceExpression()) {
304             for (AttributeAssignmentExpressionType attributeAssignment : adviceExpression
305                 .getAttributeAssignmentExpression()) {
306                 if (attributeAssignment.getAttributeId().startsWith("key:")) {
307                     Map<String, String> attribute = new HashMap<>();
308                     String key = attributeAssignment.getAttributeId().replace("key:", "");
309                     attribute.put("key", key);
310                     @SuppressWarnings("unchecked")
311                     JAXBElement<AttributeValueType> attributeValue = (JAXBElement<AttributeValueType>) attributeAssignment
312                         .getExpression();
313                     String value = (String) attributeValue.getValue().getContent().get(0);
314                     attribute.put("value", value);
315                     attributeList.add(attribute);
316                 } else if (attributeAssignment.getAttributeId().startsWith("dependencies:")) {
317                     ArrayList<String> dependencies = new ArrayList<>(
318                         Arrays.asList(attributeAssignment.getAttributeId().replace("dependencies:", "").split(",")));
319                     dependencies.remove("");
320                     policyAdapter.setBrmsDependency(dependencies);
321                 } else if (attributeAssignment.getAttributeId().startsWith("controller:")) {
322                     policyAdapter.setBrmsController(attributeAssignment.getAttributeId().replace("controller:", ""));
323                 }
324             }
325             policyAdapter.setAttributes(attributeList);
326         }
327     }
328
329     private void setDataToAdapterFromTarget(TargetType target, PolicyRestAdapter policyAdapter) {
330         // Under target we have AnyOFType
331         List<AnyOfType> anyOfList = target.getAnyOf();
332         if (anyOfList == null) {
333             return;
334         }
335         anyOfList.stream().map(AnyOfType::getAllOf)
336             .filter(Objects::nonNull)
337             .flatMap(Collection::stream)
338             .forEach(allOf -> setDataToAdapterFromMatchList(allOf.getMatch(), policyAdapter));
339     }
340
341     private void setDataToAdapterFromMatchList(List<MatchType> matchList, PolicyRestAdapter policyAdapter) {
342         if (matchList == null) {
343             return;
344         }
345         for (final MatchType match : matchList) {
346             //
347             // Under the match we have attribute value and
348             // attributeDesignator. So,finally down to the actual attribute.
349             //
350             AttributeValueType attributeValue = match.getAttributeValue();
351             String value = (String) attributeValue.getContent().get(0);
352             AttributeDesignatorType designator = match.getAttributeDesignator();
353             String attributeId = designator.getAttributeId();
354             if ("RiskType".equals(attributeId)) {
355                 policyAdapter.setRiskType(value);
356             }
357             if ("RiskLevel".equals(attributeId)) {
358                 policyAdapter.setRiskLevel(value);
359             }
360             if ("guard".equals(attributeId)) {
361                 policyAdapter.setGuard(value);
362             }
363             if ("TTLDate".equals(attributeId) && !value.contains("NA")) {
364                 PolicyController controller = new PolicyController();
365                 String newDate = controller.convertDate(value);
366                 policyAdapter.setTtlDate(newDate);
367             }
368         }
369     }
370
371     // This method generates the UI from rule configuration
372     private void paramUIGenerate(PolicyRestAdapter policyAdapter, PolicyEntity entity) {
373         String data = entity.getConfigurationData().getConfigBody();
374         if (data == null) {
375             return;
376         }
377         StringBuilder params = new StringBuilder();
378         boolean flag = false;
379         boolean comment = false;
380         for (String line : data.split("\n")) {
381             if (line.isEmpty() || line.startsWith("//")) {
382                 continue;
383             }
384             if (line.contains(brmsTemplateVlaue)) {
385                 String value = line.substring(line.indexOf("<$%"), line.indexOf("%$>"));
386                 value = value.replace(brmsTemplateVlaue, "");
387                 policyAdapter.setRuleName(value);
388             }
389             if (line.contains("<%$Values=")) {
390                 String value = line.substring(line.indexOf("<%$"), line.indexOf("$%>"));
391                 value = value.replaceAll("<%\\$Values=", "");
392                 Arrays.stream(value.split(":\\|:")).map(keyValue -> keyValue.split(":-:"))
393                     .filter(pair -> pair.length > 0)
394                     .forEach(pair -> dynamicLayoutMap.put(pair[0], (pair.length > 1) ? pair[1] : ""));
395                 return;
396             }
397             if (line.startsWith("/*")) {
398                 comment = true;
399                 continue;
400             }
401             if ((line.contains("//")) && (!(line.contains("http://") || line.contains("https://")))) {
402                 line = splitSingleLineComment(line);
403             }
404             if (line.contains("/*")) {
405                 comment = true;
406                 if (line.contains("*/")) {
407                     comment = false;
408                     line = processMultiLineFullComment(line);
409                 } else {
410                     line = splitMultiLineStartComment(line);
411                 }
412             }
413             if (line.contains("*/")) {
414                 comment = false;
415                 line = processEndComment(line);
416             }
417             if (comment) {
418                 continue;
419             }
420             if (flag) {
421                 params.append(line);
422             }
423             if (line.contains("rule") && line.contains(".Params\"")) {
424                 params.append(line);
425                 flag = true;
426             }
427             if (line.contains("end") && flag) {
428                 break;
429             }
430         }
431         params = new StringBuilder(params.substring(params.indexOf(".Params\"") + 11));
432         params = new StringBuilder(params.toString().replaceAll("\\s+", "")
433             .replace("salience1000whenthenParamsparams=newParams();", "")
434             .replace("insert(params);end", "")
435             .replace("params.set", ""));
436         updateCaptionToDynamicLayoutMap(params);
437     }
438
439     private void updateCaptionToDynamicLayoutMap(final StringBuilder params) {
440         String[] components = params.toString().split("\\);");
441         if(components.length > 0){
442             for (int i = 0; i < components.length; i++) {
443                 String value;
444                 components[i] = components[i] + ")";
445                 String caption = components[i].substring(0,
446                     components[i].indexOf('('));
447                 caption = caption.substring(0, 1).toLowerCase() + caption.substring(1);
448                 if (components[i].contains("(\"")) {
449                     value = components[i]
450                         .substring(components[i].indexOf("(\""),
451                             components[i].indexOf("\")"))
452                         .replace("(\"", "").replace("\")", "");
453                 } else {
454                     value = components[i]
455                         .substring(components[i].indexOf('('),
456                             components[i].indexOf(')'))
457                         .replace("(", "").replace(")", "");
458                 }
459                 dynamicLayoutMap.put(caption, value);
460             }
461         }
462     }
463
464     private String processEndComment(String line) {
465         try {
466             line = splitMultiLineEndComment(line);
467         } catch (Exception e) {
468             policyLogger.info("Just for Logging" + e);
469             line = "";
470         }
471         return line;
472     }
473
474     private String processMultiLineFullComment(String line) {
475         try {
476             line = splitMultiLineStartComment(line)
477                 + splitMultiLineEndComment(line);
478         } catch (Exception e) {
479             policyLogger.info("Just for Logging" + e);
480             line = splitMultiLineStartComment(line);
481         }
482         return line;
483     }
484
485     // set View Rule
486     @SuppressWarnings("unchecked")
487     @RequestMapping(value = {"/policyController/ViewBRMSParamPolicyRule.htm"}, method = { RequestMethod.POST})
488     public void setViewRule(HttpServletRequest request, HttpServletResponse response) {
489         try {
490             ObjectMapper mapper = new ObjectMapper();
491             mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
492             JsonNode root = mapper.readTree(request.getReader());
493             PolicyRestAdapter policyData = mapper
494                 .readValue(root.get(PolicyController.getPolicydata()).get("policy").toString(),
495                     PolicyRestAdapter.class);
496             policyData.setDomainDir(
497                 root.get(PolicyController.getPolicydata()).get("model").get("name").toString().replace("\"", ""));
498             if (root.get(PolicyController.getPolicydata()).get("model").get("type").toString().replace("\"", "")
499                 .equals(PolicyController.getFile())) {
500                 policyData.setEditPolicy(true);
501             }
502
503             String body = findRule(policyData.getRuleName()) + "\n";
504             StringBuilder generatedMetadata = new StringBuilder().append(
505                 "/* Autogenerated Code Please Don't change/remove this comment section. This is for the UI purpose. \n\t ")
506                 .append(brmsTemplateVlaue).append(policyData.getRuleName()).append("%$> \n */ \n");
507
508             if (policyData.getDynamicLayoutMap().size() > 0) {
509                 generatedMetadata.append("/* <%$Values=");
510                 for (Entry<?, ?> entry : policyData.getRuleData().entrySet()) {
511                     String uiKey = (String) entry.getKey();
512                     if (!"templateName".equals(uiKey)) {
513                         generatedMetadata.append(uiKey).append(":-:").append(entry.getValue()).append(":|:");
514                     }
515                 }
516                 generatedMetadata.append("$%> \n*/ \n");
517             }
518             policyLogger.info("Metadata generated with :" + generatedMetadata.toString());
519             body = generatedMetadata.toString() + body;
520             // Expand the body.
521             Map<String, String> copyMap = new HashMap<>(
522                 (Map<? extends String, ? extends String>) policyData.getRuleData());
523             copyMap.put("policyName",
524                 policyData.getDomainDir().replace("\\", ".") + ".Config_BRMS_Param_" + policyData.getPolicyName());
525             copyMap.put("policyScope", policyData.getDomainDir().replace("\\", "."));
526             copyMap.put("policyVersion", "1");
527             //Finding all the keys in the Map data-structure.
528             Set<String> keySet = copyMap.keySet();
529             Iterator<String> iterator = keySet.iterator();
530             Pattern p;
531             Matcher m;
532             while (iterator.hasNext()) {
533                 //Converting the first character of the key into a lower case.
534                 String input = iterator.next();
535                 String output = Character.toLowerCase(input.charAt(0)) +
536                     (input.length() > 1 ? input.substring(1) : "");
537                 //Searching for a pattern in the String using the key.
538                 p = Pattern.compile("\\$\\{" + output + "\\}");
539                 m = p.matcher(body);
540                 //Replacing the value with the inputs provided by the user in the editor.
541                 body = m.replaceAll(copyMap.get(input));
542             }
543             response.setCharacterEncoding("UTF-8");
544             response.setContentType("application / json");
545             request.setCharacterEncoding("UTF-8");
546
547             PrintWriter out = response.getWriter();
548             String responseString = mapper.writeValueAsString(body);
549             JSONObject j = new JSONObject("{policyData: " + responseString + "}");
550             out.write(j.toString());
551         } catch (Exception e) {
552             policyLogger.error(XACMLErrorConstants.ERROR_PROCESS_FLOW + e);
553         }
554     }
555 }