Sonar cleanup in controllers etc
[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-2019 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 com.fasterxml.jackson.databind.DeserializationFeature;
26 import com.fasterxml.jackson.databind.JsonNode;
27 import com.fasterxml.jackson.databind.ObjectMapper;
28
29 import java.util.ArrayList;
30 import java.util.Arrays;
31 import java.util.Collection;
32 import java.util.HashMap;
33 import java.util.Iterator;
34 import java.util.LinkedHashMap;
35 import java.util.List;
36 import java.util.Map;
37 import java.util.Map.Entry;
38 import java.util.Objects;
39 import java.util.Set;
40 import java.util.regex.Matcher;
41 import java.util.regex.Pattern;
42 import java.util.stream.Collectors;
43
44 import javax.servlet.http.HttpServletRequest;
45 import javax.servlet.http.HttpServletResponse;
46 import javax.xml.bind.JAXBElement;
47
48 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AdviceExpressionType;
49 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AdviceExpressionsType;
50 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AnyOfType;
51 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeAssignmentExpressionType;
52 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeDesignatorType;
53 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeValueType;
54 import oasis.names.tc.xacml._3_0.core.schema.wd_17.MatchType;
55 import oasis.names.tc.xacml._3_0.core.schema.wd_17.PolicyType;
56 import oasis.names.tc.xacml._3_0.core.schema.wd_17.RuleType;
57 import oasis.names.tc.xacml._3_0.core.schema.wd_17.TargetType;
58
59 import org.apache.commons.collections.CollectionUtils;
60 import org.json.JSONObject;
61 import org.onap.policy.common.logging.flexlogger.FlexLogger;
62 import org.onap.policy.common.logging.flexlogger.Logger;
63 import org.onap.policy.rest.adapter.PolicyRestAdapter;
64 import org.onap.policy.rest.dao.CommonClassDao;
65 import org.onap.policy.rest.jpa.BRMSParamTemplate;
66 import org.onap.policy.rest.jpa.PolicyEntity;
67 import org.onap.policy.xacml.api.XACMLErrorConstants;
68 import org.onap.portalsdk.core.controller.RestrictedBaseController;
69 import org.springframework.beans.factory.annotation.Autowired;
70 import org.springframework.stereotype.Controller;
71 import org.springframework.web.bind.annotation.RequestMapping;
72 import org.springframework.web.bind.annotation.RequestMethod;
73
74 @Controller
75 @RequestMapping("/")
76 public class CreateBRMSParamController extends RestrictedBaseController {
77
78     private static final Logger policyLogger = FlexLogger.getLogger(CreateBRMSParamController.class);
79
80     private static CommonClassDao commonClassDao;
81
82     public static CommonClassDao getCommonClassDao() {
83         return commonClassDao;
84     }
85
86     public static void setCommonClassDao(CommonClassDao commonClassDao) {
87         CreateBRMSParamController.commonClassDao = commonClassDao;
88     }
89
90     @Autowired
91     private CreateBRMSParamController(CommonClassDao commonClassDao) {
92         CreateBRMSParamController.commonClassDao = commonClassDao;
93     }
94
95     public CreateBRMSParamController() {
96         // Empty constructor
97     }
98
99     protected PolicyRestAdapter policyAdapter = null;
100
101     private HashMap<String, String> dynamicLayoutMap;
102
103     private static String brmsTemplateVlaue = "<$%BRMSParamTemplate=";
104     private static String string = "String";
105
106     /**
107      * getBRMSParamPolicyRuleData.
108      *
109      * @param request HttpServletRequest
110      * @param response HttpServletResponse
111      */
112     @RequestMapping(value = {"/policyController/getBRMSTemplateData.htm"}, method = {RequestMethod.POST})
113     public void getBRMSParamPolicyRuleData(HttpServletRequest request, HttpServletResponse response) {
114         try {
115             dynamicLayoutMap = new HashMap<>();
116             ObjectMapper mapper = new ObjectMapper();
117             mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
118             JsonNode root = mapper.readTree(request.getReader());
119             String rule = findRule(root.get(PolicyController.getPolicydata()).toString().replaceAll("^\"|\"$", ""));
120             generateUI(rule);
121             response.setCharacterEncoding(PolicyController.getCharacterencoding());
122             response.setContentType(PolicyController.getContenttype());
123             request.setCharacterEncoding(PolicyController.getCharacterencoding());
124
125             response.getWriter().write(new JSONObject("{policyData: " + mapper.writeValueAsString(dynamicLayoutMap)
126                 + "}").toString());
127         } catch (Exception e) {
128             policyLogger.error("Exception Occured while getting BRMS Rule data", e);
129         }
130     }
131
132     private String findRule(String ruleTemplate) {
133         List<Object> datas = commonClassDao.getDataById(BRMSParamTemplate.class, "ruleName", ruleTemplate);
134         if (CollectionUtils.isNotEmpty(datas)) {
135             return ((BRMSParamTemplate) datas.get(0)).getRule();
136         }
137         return null;
138     }
139
140     private void generateUI(String rule) {
141         if (rule == null) {
142             return;
143         }
144         try {
145             processRule(rule);
146         } catch (Exception e) {
147             policyLogger.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + e);
148         }
149
150     }
151
152     private void processRule(String rule) {
153         StringBuilder params = getParamsBuilderFromRule(rule);
154         params = new StringBuilder(
155                 params.toString().replace("declare Params", "").replace("end", "").replaceAll("\\s+", ""));
156         String[] components = params.toString().split(":");
157         String caption = "";
158         for (int i = 0; i < components.length; i++) {
159             String type;
160             if (i == 0) {
161                 caption = components[i];
162             }
163             if ("".equals(caption)) {
164                 break;
165             }
166             String nextComponent;
167             try {
168                 nextComponent = components[i + 1];
169             } catch (Exception e) {
170                 policyLogger.info("Error when procesing rule: " + e);
171                 nextComponent = components[i];
172             }
173             if (nextComponent.startsWith(string)) {
174                 type = "String";
175                 createField(caption, type);
176                 caption = nextComponent.replace(string, "");
177             } else if (nextComponent.startsWith("int")) {
178                 type = "int";
179                 createField(caption, type);
180                 caption = nextComponent.replace("int", "");
181             }
182         }
183     }
184
185     private StringBuilder getParamsBuilderFromRule(final String rule) {
186         StringBuilder params = new StringBuilder();
187         boolean flag = false;
188         boolean comment = false;
189         String[] lines = rule.split("\n");
190         for (String line : lines) {
191             if (line.isEmpty() || line.startsWith("//")) {
192                 continue;
193             }
194             if (line.startsWith("/*")) {
195                 comment = true;
196                 continue;
197             }
198             if (line.contains("//")) {
199                 line = splitSingleLineComment(line);
200             }
201             if (line.contains("/*")) {
202                 comment = true;
203                 if (line.contains("*/")) {
204                     comment = false;
205                     line = processMultiLineFullComment(line);
206                 } else {
207                     line = splitMultiLineStartComment(line);
208                 }
209             }
210             if (line.contains("*/")) {
211                 comment = false;
212                 line = processEndComment(line);
213             }
214             if (comment) {
215                 continue;
216             }
217             if (flag) {
218                 params.append(line);
219             }
220             if (line.contains("declare Params")) {
221                 params.append(line);
222                 flag = true;
223             }
224             if (line.contains("end") && flag) {
225                 break;
226             }
227         }
228         return params;
229     }
230
231     private String splitMultiLineStartComment(String line) {
232         return line.split("\\/\\*")[0];
233     }
234
235     private String splitMultiLineEndComment(String line) {
236         return line.split("\\*\\/")[1].replace("*/", "");
237     }
238
239     private String splitSingleLineComment(String line) {
240         return line.split("\\/\\/")[0];
241     }
242
243     private void createField(String caption, String type) {
244         dynamicLayoutMap.put(caption, type);
245     }
246
247     /*
248      * When the User Click Edit or View Policy the following method will get invoked for setting the data to
249      * PolicyRestAdapter.
250      * Which is used to bind the data in GUI
251      */
252     public void prePopulateBRMSParamPolicyData(PolicyRestAdapter policyAdapter, PolicyEntity entity) {
253         dynamicLayoutMap = new HashMap<>();
254         if (! (policyAdapter.getPolicyData() instanceof PolicyType)) {
255             return;
256         }
257         PolicyType policy = (PolicyType) policyAdapter.getPolicyData();
258         policyAdapter.setOldPolicyFileName(policyAdapter.getPolicyName());
259         // policy name value is the policy name without any prefix and
260         // Extensions.
261         String policyNameValue =
262                 policyAdapter.getPolicyName().substring(policyAdapter.getPolicyName().indexOf("BRMS_Param_") + 11);
263         if (policyLogger.isDebugEnabled()) {
264             policyLogger
265                     .debug("Prepopulating form data for BRMS RAW Policy selected:" + policyAdapter.getPolicyName());
266         }
267         policyAdapter.setPolicyName(policyNameValue);
268         String description;
269         try {
270             description = policy.getDescription().substring(0, policy.getDescription().indexOf("@CreatedBy:"));
271         } catch (Exception e) {
272             policyLogger.info("Error getting description: " + e);
273             description = policy.getDescription();
274         }
275         policyAdapter.setPolicyDescription(description);
276         setDataAdapterFromAdviceExpressions(policy, policyAdapter);
277
278         // Generate Param UI
279         try {
280             paramUiGenerate(policyAdapter, entity);
281         } catch (Exception e) {
282             policyLogger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + e.getMessage() + e);
283         }
284
285         // Get the target data under policy.
286         policyAdapter.setDynamicLayoutMap(dynamicLayoutMap);
287         if (policyAdapter.getDynamicLayoutMap().size() > 0) {
288             LinkedHashMap<String, String> drlRule = policyAdapter.getDynamicLayoutMap().keySet().stream()
289                     .collect(Collectors.toMap(String::toString,
290                         keyValue -> policyAdapter.getDynamicLayoutMap().get(keyValue), (a, b) -> b,
291                             LinkedHashMap::new));
292             policyAdapter.setRuleData(drlRule);
293         }
294         TargetType target = policy.getTarget();
295         if (target != null) {
296             setDataToAdapterFromTarget(target, policyAdapter);
297         }
298     }
299
300     private void setDataAdapterFromAdviceExpressions(PolicyType policy, PolicyRestAdapter policyAdapter) {
301         ArrayList<Object> attributeList = new ArrayList<>();
302         // Set Attributes.
303         AdviceExpressionsType expressionTypes =
304                 ((RuleType) policy.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition().get(0))
305                         .getAdviceExpressions();
306         for (AdviceExpressionType adviceExpression : expressionTypes.getAdviceExpression()) {
307             for (AttributeAssignmentExpressionType attributeAssignment : adviceExpression
308                     .getAttributeAssignmentExpression()) {
309                 if (attributeAssignment.getAttributeId().startsWith("key:")) {
310                     Map<String, String> attribute = new HashMap<>();
311                     String key = attributeAssignment.getAttributeId().replace("key:", "");
312                     attribute.put("key", key);
313                     @SuppressWarnings("unchecked")
314                     JAXBElement<AttributeValueType> attributeValue =
315                             (JAXBElement<AttributeValueType>) attributeAssignment.getExpression();
316                     String value = (String) attributeValue.getValue().getContent().get(0);
317                     attribute.put("value", value);
318                     attributeList.add(attribute);
319                 } else if (attributeAssignment.getAttributeId().startsWith("dependencies:")) {
320                     ArrayList<String> dependencies = new ArrayList<>(Arrays
321                             .asList(attributeAssignment.getAttributeId().replace("dependencies:", "").split(",")));
322                     dependencies.remove("");
323                     policyAdapter.setBrmsDependency(dependencies);
324                 } else if (attributeAssignment.getAttributeId().startsWith("controller:")) {
325                     policyAdapter.setBrmsController(attributeAssignment.getAttributeId().replace("controller:", ""));
326                 }
327             }
328             policyAdapter.setAttributes(attributeList);
329         }
330     }
331
332     private void setDataToAdapterFromTarget(TargetType target, PolicyRestAdapter policyAdapter) {
333         // Under target we have AnyOFType
334         if (target.getAnyOf() == null) {
335             return;
336         }
337         target.getAnyOf().stream().map(AnyOfType::getAllOf).filter(Objects::nonNull).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(
433                 params.toString().replaceAll("\\s+", "").replace("salience1000whenthenParamsparams=newParams();", "")
434                         .replace("insert(params);end", "").replace("params.set", ""));
435         updateCaptionToDynamicLayoutMap(params);
436     }
437
438     private void updateCaptionToDynamicLayoutMap(final StringBuilder params) {
439         String[] components = params.toString().split("\\);");
440         if (components.length > 0) {
441             for (int i = 0; i < components.length; i++) {
442                 String value;
443                 components[i] = components[i] + ")";
444                 String caption = components[i].substring(0, components[i].indexOf('('));
445                 caption = caption.substring(0, 1).toLowerCase() + caption.substring(1);
446                 if (components[i].contains("(\"")) {
447                     value = components[i].substring(components[i].indexOf("(\""), components[i].indexOf("\")"))
448                             .replace("(\"", "").replace("\")", "");
449                 } else {
450                     value = components[i].substring(components[i].indexOf('('), components[i].indexOf(')'))
451                             .replace("(", "").replace(")", "");
452                 }
453                 dynamicLayoutMap.put(caption, value);
454             }
455         }
456     }
457
458     private String processEndComment(String line) {
459         try {
460             line = splitMultiLineEndComment(line);
461         } catch (Exception e) {
462             policyLogger.info("Just for Logging" + e);
463             line = "";
464         }
465         return line;
466     }
467
468     private String processMultiLineFullComment(String line) {
469         try {
470             line = splitMultiLineStartComment(line) + splitMultiLineEndComment(line);
471         } catch (Exception e) {
472             policyLogger.info("Just for Logging" + e);
473             line = splitMultiLineStartComment(line);
474         }
475         return line;
476     }
477
478     /**
479      * setViewRule.
480      *
481      * @param request HttpServletRequest
482      * @param response HttpServletResponse
483      */
484     @SuppressWarnings("unchecked")
485     @RequestMapping(value = {"/policyController/ViewBRMSParamPolicyRule.htm"}, method = {RequestMethod.POST})
486     public void setViewRule(HttpServletRequest request, HttpServletResponse response) {
487         try {
488             ObjectMapper mapper = new ObjectMapper();
489             mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
490             JsonNode root = mapper.readTree(request.getReader());
491             PolicyRestAdapter policyData = mapper.readValue(
492                     root.get(PolicyController.getPolicydata()).get("policy").toString(), PolicyRestAdapter.class);
493             policyData.setDomainDir(
494                     root.get(PolicyController.getPolicydata()).get("model").get("name").toString().replace("\"", ""));
495             if (root.get(PolicyController.getPolicydata()).get("model").get("type").toString().replace("\"", "")
496                     .equals(PolicyController.getFile())) {
497                 policyData.setEditPolicy(true);
498             }
499
500             String body = findRule(policyData.getRuleName()) + "\n";
501             StringBuilder generatedMetadata = new StringBuilder().append(
502                     "/* Autogenerated Code Please Don't change/remove this comment section. "
503                             + "This is for the UI purpose. \n\t ")
504                     .append(brmsTemplateVlaue).append(policyData.getRuleName()).append("%$> \n */ \n");
505
506             if (policyData.getDynamicLayoutMap().size() > 0) {
507                 generatedMetadata.append("/* <%$Values=");
508                 for (Entry<?, ?> entry : policyData.getRuleData().entrySet()) {
509                     String uiKey = (String) entry.getKey();
510                     if (!"templateName".equals(uiKey)) {
511                         generatedMetadata.append(uiKey).append(":-:").append(entry.getValue()).append(":|:");
512                     }
513                 }
514                 generatedMetadata.append("$%> \n*/ \n");
515             }
516             policyLogger.info("Metadata generated with :" + generatedMetadata.toString());
517             body = generatedMetadata.toString() + body;
518             // Expand the body.
519             Map<String, String> copyMap =
520                     new HashMap<>((Map<? extends String, ? extends String>) policyData.getRuleData());
521             copyMap.put("policyName",
522                     policyData.getDomainDir().replace("\\", ".") + ".Config_BRMS_Param_" + policyData.getPolicyName());
523             copyMap.put("policyScope", policyData.getDomainDir().replace("\\", "."));
524             copyMap.put("policyVersion", "1");
525             // Finding all the keys in the Map data-structure.
526             Set<String> keySet = copyMap.keySet();
527             Iterator<String> iterator = keySet.iterator();
528             while (iterator.hasNext()) {
529                 // Converting the first character of the key into a lower case.
530                 String input = iterator.next();
531                 String output = Character.toLowerCase(input.charAt(0)) + (input.length() > 1 ? input.substring(1) : "");
532                 // Searching for a pattern in the String using the key.
533                 Pattern pattern = Pattern.compile("\\$\\{" + output + "\\}");
534                 Matcher matcher = pattern.matcher(body);
535                 // Replacing the value with the inputs provided by the user in the editor.
536                 body = matcher.replaceAll(copyMap.get(input));
537             }
538             response.setCharacterEncoding("UTF-8");
539             response.setContentType("application / json");
540             request.setCharacterEncoding("UTF-8");
541
542             response.getWriter().write(new JSONObject("{policyData: " + mapper.writeValueAsString(body)
543                 + "}").toString());
544         } catch (Exception e) {
545             policyLogger.error(XACMLErrorConstants.ERROR_PROCESS_FLOW + e);
546         }
547     }
548 }