2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 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
11 * http://www.apache.org/licenses/LICENSE-2.0
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 * ============LICENSE_END=========================================================
21 package org.onap.policy.components;
24 import java.io.ByteArrayOutputStream;
26 import java.io.FileInputStream;
27 import java.io.IOException;
28 import java.io.PrintWriter;
29 import java.io.StringWriter;
30 import java.nio.file.Path;
31 import java.nio.file.Paths;
32 import java.util.Collection;
33 import java.util.HashMap;
34 import java.util.Iterator;
35 import java.util.List;
38 import javax.xml.bind.JAXBElement;
40 import org.apache.commons.io.FilenameUtils;
41 import org.json.JSONObject;
42 import org.onap.policy.common.logging.flexlogger.FlexLogger;
43 import org.onap.policy.common.logging.flexlogger.Logger;
44 import org.onap.policy.controller.PolicyController;
45 import org.onap.policy.rest.jpa.FunctionDefinition;
46 import org.onap.policy.utils.XACMLPolicyWriterWithPapNotify;
47 import org.onap.policy.xacml.api.XACMLErrorConstants;
48 import org.onap.policy.xacml.util.XACMLPolicyScanner;
50 import com.att.research.xacml.api.AttributeValue;
51 import com.att.research.xacml.std.IdentifierImpl;
52 import com.att.research.xacml.std.StdAttribute;
53 import com.att.research.xacml.std.StdAttributeValue;
54 import com.att.research.xacml.util.XACMLPolicyScanner.CallbackResult;
55 import com.att.research.xacml.util.XACMLPolicyScanner.SimpleCallback;
57 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AdviceExpressionType;
58 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AdviceExpressionsType;
59 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AllOfType;
60 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AnyOfType;
61 import oasis.names.tc.xacml._3_0.core.schema.wd_17.ApplyType;
62 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeAssignmentExpressionType;
63 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeDesignatorType;
64 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeSelectorType;
65 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeValueType;
66 import oasis.names.tc.xacml._3_0.core.schema.wd_17.ConditionType;
67 import oasis.names.tc.xacml._3_0.core.schema.wd_17.MatchType;
68 import oasis.names.tc.xacml._3_0.core.schema.wd_17.ObligationExpressionType;
69 import oasis.names.tc.xacml._3_0.core.schema.wd_17.ObligationExpressionsType;
70 import oasis.names.tc.xacml._3_0.core.schema.wd_17.PolicySetType;
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.VariableReferenceType;
77 public class HumanPolicyComponent{
79 private static final Logger LOGGER = FlexLogger.getLogger(HumanPolicyComponent.class);
81 // Constants Used in XML Creation
82 public static final String CATEGORY_RECIPIENT_SUBJECT = "urn:oasis:names:tc:xacml:1.0:subject-category:recipient-subject";
83 public static final String CATEGORY_RESOURCE = "urn:oasis:names:tc:xacml:3.0:attribute-category:resource";
84 public static final String CATEGORY_ACTION = "urn:oasis:names:tc:xacml:3.0:attribute-category:action";
85 public static final String CATEGORY_ACCESS_SUBJECT = "urn:oasis:names:tc:xacml:1.0:subject-category:access-subject";
86 public static final String ACTION_ID = "urn:oasis:names:tc:xacml:1.0:action:action-id";
87 public static final String SUBJECT_ID = "urn:oasis:names:tc:xacml:1.0:subject:subject-id";
88 public static final String RESOURCE_ID = "urn:oasis:names:tc:xacml:1.0:resource:resource-id";
89 public static final String FUNTION_INTEGER_ONE_AND_ONLY = "urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only";
90 public static final String FUNCTION_STRING_ONE_AND_ONLY = "urn:oasis:names:tc:xacml:1.0:function:string-one-and-only";
91 public static final String FUNCTION_STRING_EQUAL = "urn:oasis:names:tc:xacml:1.0:function:string-equal";
92 public static final String FUNCTION_STRING_REGEX_MATCH = "org.onap.function.regex-match";
93 public static final String FUNCTION_STRING_EQUAL_IGNORE = "urn:oasis:names:tc:xacml:3.0:function:string-equal-ignore-case";
94 public static final String INTEGER_DATATYPE = "http://www.w3.org/2001/XMLSchema#integer";
95 public static final String BOOLEAN_DATATYPE = "http://www.w3.org/2001/XMLSchema#boolean";
96 public static final String STRING_DATATYPE = "http://www.w3.org/2001/XMLSchema#string";
97 public static final String URI_DATATYPE = "http://www.w3.org/2001/XMLSchema#anyURI";
98 public static final String RULE_VARIABLE = "var:";
99 public static final String EMPTY_STRING = "";
101 private static HtmlProcessor htmlProcessor;
103 private static File policyFile;
105 private HumanPolicyComponent(){
106 //Default Constructor
109 public static JSONObject DescribePolicy(final File policyFile) {
110 if (LOGGER.isTraceEnabled())
111 LOGGER.trace("ENTER");
113 HumanPolicyComponent.policyFile = policyFile;
114 return humanPolicyLayout();
118 private static JSONObject humanPolicyLayout() {
119 if (LOGGER.isTraceEnabled())
120 LOGGER.trace("ENTER");
123 String html = processPolicy();
124 JSONObject result = new JSONObject();
125 result.put("html", html);
128 } catch (IllegalArgumentException e) {
129 LOGGER.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "cannot build html area por policy", e);
134 private static String processPolicy() throws IllegalArgumentException {
135 if (LOGGER.isTraceEnabled())
136 LOGGER.trace("ENTER");
138 FileInputStream pIS = null;
140 pIS = new FileInputStream(policyFile);
141 Object policy = XACMLPolicyScanner.readPolicy(pIS);
143 throw new IllegalArgumentException("Policy File " + policyFile.getName() +
144 " cannot be unmarshalled");
146 HumanPolicyComponent.htmlProcessor =
147 new HtmlProcessor(HumanPolicyComponent.policyFile, policy);
149 Path policyPath = Paths.get(policyFile.getAbsolutePath());
150 XACMLPolicyScanner xacmlScanner = new XACMLPolicyScanner(policyPath, htmlProcessor);
152 String html = htmlProcessor.html();
153 if (LOGGER.isDebugEnabled())
154 LOGGER.debug(policyPath + System.lineSeparator() + html);
158 } catch (Exception e) {
159 String msg = "Exception reading policy: " + policyFile.getAbsolutePath() +
160 ": " + e.getMessage();
161 LOGGER.error(XACMLErrorConstants.ERROR_DATA_ISSUE + msg, e);
162 throw new IllegalArgumentException(msg);
167 } catch (IOException e) {
168 LOGGER.warn(e.getMessage(), e);
176 class HtmlProcessor extends SimpleCallback {
178 private static final Logger LOGGER = FlexLogger.getLogger(HtmlProcessor.class);
180 private static Map<String, String> function2human;
182 function2human = new HashMap<>();
183 function2human.put(HumanPolicyComponent.FUNCTION_STRING_EQUAL, "equal");
184 function2human.put(HumanPolicyComponent.FUNCTION_STRING_EQUAL_IGNORE, "equal");
185 function2human.put(HumanPolicyComponent.FUNCTION_STRING_ONE_AND_ONLY, "one-and-only");
186 function2human.put(HumanPolicyComponent.FUNCTION_STRING_REGEX_MATCH, "matching regular expression");
187 function2human.put(HumanPolicyComponent.FUNTION_INTEGER_ONE_AND_ONLY, "one-and-only");
190 private static Map<String, String> combiningAlgo2human;
192 combiningAlgo2human = new HashMap<>();
193 combiningAlgo2human.put("deny-overrides", "to deny if any $placeholder$ below evaluates to <i>deny</i>");
194 combiningAlgo2human.put("permit-overrides", "to permit if any $placeholder$ below evaluates to <i>permit</i>");
196 combiningAlgo2human.put("ordered-deny-overrides", "to deny if any $placeholder$ below evaluates to <i>deny</i>");
197 combiningAlgo2human.put("ordered-permit-overrides", "to permit if any $placeholder$ below evaluates to <i>permit</i>");
198 combiningAlgo2human.put("deny-unless-permit", "to permit if any $placeholder$ below evaluates to <i>deny</i> and not <i>indeterminate</i>");
200 combiningAlgo2human.put("permit-unless-deny", "to deny if any $placeholder$ below evaluates to is <i>permit</i> and not <i>indeterminate</i>");
201 combiningAlgo2human.put("first-applicable", "to honour the result of the first successfully evaluated $placeholder$ in order");
202 combiningAlgo2human.put("only-one-applicable", "to honour the result of the first successfully evaluated $placeholder$ in order");
205 private Map<String, AttributeIdentifiers> attributeIdentifiersMap = new HashMap<String, AttributeIdentifiers>();
207 private final StringWriter stringWriter = new StringWriter();
208 private final PrintWriter htmlOut = new PrintWriter(stringWriter);
209 private final String policyName;
210 private final Object rootPolicyObject;
212 public HtmlProcessor(File policyFile, Object policyObject)
213 throws IllegalArgumentException {
214 if (LOGGER.isTraceEnabled())
215 LOGGER.trace("ENTER");
217 if (policyFile == null) {
218 LOGGER.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "Null Policy File");
219 throw new IllegalArgumentException("Null Policy File");
222 if (!policyFile.exists() || !policyFile.canRead()) {
223 String msg = "Can't access " + policyFile.getAbsolutePath();
224 LOGGER.error(XACMLErrorConstants.ERROR_PERMISSIONS + msg);
225 throw new IllegalArgumentException(msg);
228 if (policyObject == null ||
229 (!(policyObject instanceof PolicySetType) && !(policyObject instanceof PolicyType))) {
230 String msg = "Invalid unmarshalled object: " + policyObject;
231 LOGGER.error(XACMLErrorConstants.ERROR_SCHEMA_INVALID + msg);
232 throw new IllegalArgumentException(msg);
235 this.policyName = FilenameUtils.removeExtension(policyFile.getName());
236 this.rootPolicyObject = policyObject;
238 String version = "-";
239 if (policyObject instanceof PolicyType) {
240 PolicyType policy = (PolicyType) policyObject;
241 version = policy.getVersion();
242 htmlOut.println("<h1>Policy: " + policyName +
243 " (version " + version + ") </h1>");
246 PolicySetType policySet = (PolicySetType) policyObject;
247 version = policySet.getVersion();
248 htmlOut.println("<h1>Policy Set: " + policyName +
249 " (v" + version + ") </h1>");
252 htmlOut.println("<h3><b>Location: </b>" + policyFile.getPath() + "</h3>");
253 htmlOut.println("<hr>");
255 if (rootPolicyObject instanceof PolicySetType) {
256 if (policyName.startsWith("Config_")) {
257 htmlOut.println("<p>This is a <b>config</b> policy set.</p>");
258 } else if (policyName.startsWith("Action_")) {
259 htmlOut.println("<p>This is an <b>action</b> policy set.</p>");
261 htmlOut.println("<dl>");
263 if (policyName.startsWith("Config_")) {
264 htmlOut.println("<p>This is a <b>config</b> policy.</p>");
265 } else if (policyName.startsWith("Action_")) {
266 htmlOut.println("<p>This is an <b>action</b> policy.</p>");
268 htmlOut.println("<ol>");
273 * @return the attributeIdentifiersMap
275 public Map<String, AttributeIdentifiers> getAttributeIdentifiersMap() {
276 return attributeIdentifiersMap;
280 public void onFinishScan(Object root) {
281 if (LOGGER.isTraceEnabled())
282 LOGGER.trace("ENTER");
284 if (rootPolicyObject instanceof PolicySetType) {
285 htmlOut.println("</dl>");
287 htmlOut.println("</ol>");
290 htmlOut.println("<hr>");
292 htmlOut.println("<h3>Attribute Table:</h3>");
294 htmlOut.println("<table border=\"3\" style=\"width:100%\">");
295 htmlOut.println("<tr>");
296 htmlOut.print("<th>Category</th>");
297 htmlOut.print("<th>Type</th>");
298 htmlOut.print("<th>Identifier</th>");
299 htmlOut.println("</tr>");
300 for(Map.Entry<String, AttributeIdentifiers> entry : this.attributeIdentifiersMap.entrySet()){
301 AttributeIdentifiers value = entry.getValue();
302 htmlOut.println("<tr>");
303 htmlOut.print("<td><a name=\"" + entry.getKey() + "\"></a>" + value.category + "</td>");
304 htmlOut.print("<td>" + value.getType() + "</td>");
305 htmlOut.print("<td>" + value.id + "</td>");
306 htmlOut.println("</tr>");
308 htmlOut.println("</table>");
310 htmlOut.println("<p></p>");
312 // Not necessary for the user, uncomment if desired at some point
315 super.onFinishScan(root);
318 @SuppressWarnings("unused")
319 private void writeRawXACML() {
320 if (LOGGER.isTraceEnabled())
321 LOGGER.trace("ENTER");
323 htmlOut.println("<hr>");
324 htmlOut.println("<h3>Raw XACML:</h3>");
326 ByteArrayOutputStream bos = new ByteArrayOutputStream();
327 if (rootPolicyObject instanceof PolicySetType) {
328 XACMLPolicyWriterWithPapNotify.writePolicyFile(bos, (PolicySetType) rootPolicyObject);
329 } else if (rootPolicyObject instanceof PolicyType) {
330 XACMLPolicyWriterWithPapNotify.writePolicyFile(bos, (PolicyType) rootPolicyObject);
333 String xacml = bos.toString();
334 xacml = xacml.replaceAll("<", "<");
335 xacml = xacml.replaceAll(">", ">");
336 htmlOut.println("<pre>");
337 htmlOut.println(xacml);
338 htmlOut.println("</pre>");
342 public CallbackResult onPreVisitPolicySet(PolicySetType parent, PolicySetType policySet) {
343 if (LOGGER.isTraceEnabled())
344 LOGGER.trace("PolicySet: " + policySet.getPolicySetId() + " Version: " + policySet.getVersion());
346 if (parent != null && LOGGER.isTraceEnabled())
347 LOGGER.trace("PolicySet: " + policySet.getPolicySetId() +
348 "Parent PolicySet: " + parent.getPolicySetId() + " Version: " + parent.getVersion());
350 String description = policySet.getDescription();
351 if (description != null && LOGGER.isTraceEnabled())
352 LOGGER.trace("PolicySet: " + policySet.getPolicySetId() +
353 " Description: " + policySet.getDescription());
355 if (parent == null) // root
356 policySet(policySet, "dl");
358 policySet(policySet, "li");
360 if (policySet.getPolicySetOrPolicyOrPolicySetIdReference().size() > 0)
361 htmlOut.println("<ol>");
363 return super.onPreVisitPolicySet(parent, policySet);
367 public CallbackResult onPostVisitPolicySet(PolicySetType parent, PolicySetType policySet) {
368 if (LOGGER.isTraceEnabled())
369 LOGGER.trace("PolicySet: " + policySet.getPolicySetId() + " Version: " + policySet.getVersion());
371 if (parent != null && LOGGER.isTraceEnabled())
372 LOGGER.trace("PolicySet: " + policySet.getPolicySetId() +
373 "Parent PolicySet: " + parent.getPolicySetId() + " Version: " + parent.getVersion());
375 String description = policySet.getDescription();
376 if (description != null && LOGGER.isTraceEnabled())
377 LOGGER.trace("PolicySet: " + policySet.getPolicySetId() +
378 " Description: " + policySet.getDescription());
380 if (policySet.getPolicySetOrPolicyOrPolicySetIdReference().size() > 0)
381 htmlOut.println("</ol>");
383 htmlOut.println("<p></p>");
385 return super.onPostVisitPolicySet(parent, policySet);
388 public void policySet(PolicySetType policySet, String htmlListElement) {
389 if (LOGGER.isTraceEnabled())
390 LOGGER.trace("PolicySet: " + policySet.getPolicySetId());
392 String combiningAlgorithm = "-";
394 String version = "-";
397 if (policySet.getPolicyCombiningAlgId() != null)
398 combiningAlgorithm = extractLastIdentifier(policySet.getPolicyCombiningAlgId(), ":");
400 if (policySet.getPolicySetId() != null)
401 id = extractLastIdentifier(policySet.getPolicySetId(), ":");
403 if (policySet.getVersion() != null)
404 version = policySet.getVersion();
407 htmlOut.println("<" + htmlListElement + "><b>Policy Set ID</b>: <i>" + id +
408 "</i> (v" + version + ") " + "</" + htmlListElement + ">");
410 if (policySet.getTarget() == null ||
411 policySet.getTarget().getAnyOf() == null ||
412 policySet.getTarget().getAnyOf().size() <= 0) {
413 htmlOut.println("<p>This policy set applies to all requests.</p>");
415 htmlOut.print("<p>");
416 htmlOut.print("This policy set applies to requests with attributes ");
418 List<AnyOfType> anyOf_s = policySet.getTarget().getAnyOf();
420 htmlOut.println(".</p>");
423 if (policySet.getPolicySetOrPolicyOrPolicySetIdReference() != null &&
424 policySet.getPolicySetOrPolicyOrPolicySetIdReference().size() > 0) {
425 String algoDesc = combiningAlgo2human.get(combiningAlgorithm);
426 if (algoDesc != null) {
427 algoDesc = algoDesc.replace("$placeholder$", "policy") + " (" + "<i>" + combiningAlgorithm + "</i>)";
429 algoDesc = combiningAlgorithm;
432 htmlOut.println("<p>The result is " + algoDesc + ": </p>");
437 public CallbackResult onPreVisitPolicy(PolicySetType parent, PolicyType policy) {
438 if (LOGGER.isTraceEnabled())
439 LOGGER.trace("PolicySet: " + policy.getPolicyId() + " Version: " + policy.getVersion());
441 if (parent != null && LOGGER.isTraceEnabled())
442 LOGGER.trace("PolicySet: " + policy.getPolicyId() +
443 "Parent PolicySet: " + parent.getPolicySetId() + " Version: " + parent.getVersion());
445 String description = policy.getDescription();
446 if (description != null && LOGGER.isTraceEnabled())
447 LOGGER.trace("PolicySet: " + policy.getPolicyId() +
448 " Description: " + policy.getDescription());
452 if (policy.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition().size() > 0)
453 htmlOut.println("<ol type=\"i\">");
455 return super.onPreVisitPolicy(parent, policy);
459 public CallbackResult onPostVisitPolicy(PolicySetType parent, PolicyType policy) {
460 if (LOGGER.isTraceEnabled())
461 LOGGER.trace("PolicySet: " + policy.getPolicyId() + " Version: " + policy.getVersion());
463 if (parent != null && LOGGER.isTraceEnabled())
464 LOGGER.trace("PolicySet: " + policy.getPolicyId() +
465 "Parent PolicySet: " + parent.getPolicySetId() + " Version: " + parent.getVersion());
467 if (policy.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition().size() > 0)
468 htmlOut.println("</ol>");
470 htmlOut.println("<p></p>");
471 return super.onPostVisitPolicy(parent, policy);
474 public void policy(PolicyType policy) {
475 if (LOGGER.isTraceEnabled())
476 LOGGER.trace("Policy: " + policy.getPolicyId());
478 String combiningAlgorithm = "-";
480 String version = "-";
483 if (policy.getRuleCombiningAlgId() != null)
484 combiningAlgorithm = extractLastIdentifier(policy.getRuleCombiningAlgId(), ":");
486 if (policy.getPolicyId() != null)
487 id = extractLastIdentifier(policy.getPolicyId(), ":");
489 if (policy.getVersion() != null)
490 version = policy.getVersion();
492 htmlOut.println("<li><b>Policy ID</b>: <i>" + id +
493 "</i> (v" + version + ") " + "</li>");
495 if (policy.getTarget() == null ||
496 policy.getTarget().getAnyOf() == null ||
497 policy.getTarget().getAnyOf().size() <= 0) {
498 htmlOut.println("<p>This policy applies to all requests.</p>");
500 htmlOut.print("<p>");
501 htmlOut.print("This policy applies to requests with attributes ");
503 List<AnyOfType> anyOf_s = policy.getTarget().getAnyOf();
505 htmlOut.println(".</p>");
508 if (policy.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition() != null &&
509 policy.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition().size() > 0) {
510 String algoDesc = combiningAlgo2human.get(combiningAlgorithm);
511 if (algoDesc != null) {
512 algoDesc = algoDesc.replace("$placeholder$", "rule") + " (<i>" + combiningAlgorithm + "</i>)";
514 algoDesc = combiningAlgorithm;
516 htmlOut.println("<p>The result is " + algoDesc + ": </p>");
522 public CallbackResult onPreVisitRule(PolicyType parent, RuleType rule) {
523 if (LOGGER.isTraceEnabled())
524 LOGGER.trace("Rule: " + rule.getRuleId());
526 if (parent != null && LOGGER.isTraceEnabled())
527 LOGGER.trace("Parent Policy: " + parent.getPolicyId() + " Version: " + parent.getVersion());
529 String description = rule.getDescription();
530 if (description != null && LOGGER.isTraceEnabled()) {
531 LOGGER.trace("Rule: " + rule.getRuleId() +
532 " Description: " + rule.getDescription());
537 return super.onPreVisitRule(parent, rule);
541 public CallbackResult onPostVisitRule(PolicyType parent, RuleType rule) {
542 if (LOGGER.isTraceEnabled())
543 LOGGER.trace("Rule: " + rule.getRuleId());
545 if (parent != null && LOGGER.isTraceEnabled())
546 LOGGER.trace("Parent Policy: " + parent.getPolicyId() + " Version: " + parent.getVersion());
548 return super.onPostVisitRule(parent, rule);
551 public void rule(RuleType rule) {
552 if (LOGGER.isTraceEnabled())
553 LOGGER.trace("Rule: " + rule.getRuleId());
557 if (rule.getRuleId() != null)
558 id = extractLastIdentifier(rule.getRuleId(), ":");
560 htmlOut.println("<li><b>Rule ID</b>: <i>" + id + "</i></li>");
562 htmlOut.println("<dl>");
564 htmlOut.print("<p>");
565 htmlOut.print(rule.getEffect().value());
567 if (rule.getTarget() == null ||
568 rule.getTarget().getAnyOf() == null ||
569 rule.getTarget().getAnyOf().size() <= 0) {
570 htmlOut.print(" for all requests");
572 List<AnyOfType> anyOf_s = rule.getTarget().getAnyOf();
573 htmlOut.print(" for requests with attributes ");
577 if (rule.getCondition() != null) {
578 htmlOut.print(" when ");
579 htmlOut.println(this.stringifyCondition(rule.getCondition()) + " ");
581 htmlOut.print(" with no conditions ");
584 if (rule.getAdviceExpressions() != null) {
585 advice(rule.getAdviceExpressions());
586 if (rule.getObligationExpressions() != null)
587 htmlOut.println(" and ");
590 if (rule.getObligationExpressions() != null) {
591 obligation(rule.getObligationExpressions());
594 htmlOut.println("</p>");
597 private void advice(AdviceExpressionsType adviceExpressions) {
598 if (LOGGER.isTraceEnabled())
599 LOGGER.trace("ENTER");
601 List<AdviceExpressionType> ae = adviceExpressions.getAdviceExpression();
602 for (AdviceExpressionType expression : ae) {
603 htmlOut.println(" with <b>advice</b> (<i>" + expression.getAdviceId() + "</i>) on <i>" +
604 expression.getAppliesTo().value() + "</i>:" );
605 htmlOut.println("<ol type=\"a\">");
606 List<AttributeAssignmentExpressionType> assignments = expression.getAttributeAssignmentExpression();
607 if (assignments != null) {
608 processAttributeAssignments(assignments);
610 htmlOut.println("</ol>");
614 private void obligation(ObligationExpressionsType obligationExpressions) {
615 if (LOGGER.isTraceEnabled())
616 LOGGER.trace("ENTER");
618 List<ObligationExpressionType> oe = obligationExpressions.getObligationExpression();
619 for (ObligationExpressionType expression : oe) {
620 htmlOut.println(" with <b>obligations</b> (<i>" + expression.getObligationId() + "</i>) to be fullfilled on <i>" +
621 expression.getFulfillOn().value() + "</i>:" );
622 htmlOut.println("<ol type=\"a\">");
623 List<AttributeAssignmentExpressionType> assignments = expression.getAttributeAssignmentExpression();
624 if (assignments != null) {
625 processAttributeAssignments(assignments);
627 htmlOut.println("</ol>");
634 private void processAttributeAssignments(List<AttributeAssignmentExpressionType> assignments) {
635 if (LOGGER.isTraceEnabled())
636 LOGGER.trace("ENTER");
638 for (AttributeAssignmentExpressionType assignment : assignments) {
639 String succintIdentifier = extractLastIdentifier(assignment.getCategory(), ":") +
640 ":" + extractLastIdentifier(assignment.getAttributeId(), ":");
641 AttributeIdentifiers attributeIdentifiers = null;
642 if (!this.attributeIdentifiersMap.containsKey(succintIdentifier)) {
643 // Note Attribute Assignments do not have an Attribute Type, assume string
644 // but note this case is unlikely since attributeMap should have been populated
645 // during parsing of target and conditions, and not in this case for Advice and
647 attributeIdentifiers = new AttributeIdentifiers(assignment.getCategory(),
649 assignment.getAttributeId());
650 this.attributeIdentifiersMap.put(succintIdentifier, attributeIdentifiers);
653 htmlOut.print("<li><i><a href=\"#" + succintIdentifier + "\">" + succintIdentifier + "</a></i> is ");
654 // AttributeValueType
655 JAXBElement<?> jaxbExp = assignment.getExpression();
656 Object assignmentObject = jaxbExp.getValue();
657 if (assignmentObject instanceof AttributeValueType) {
658 AttributeValueType avt = (AttributeValueType) assignmentObject;
659 if (attributeIdentifiers != null) {
660 attributeIdentifiers.setType(avt.getDataType());
662 int numContent = avt.getContent().size();
663 int countContent = 0;
664 for (Object c: avt.getContent()) {
666 htmlOut.print("<i>" + c + "</i>");
667 if (countContent < numContent)
668 htmlOut.print(" or ");
670 htmlOut.println("</li>");
671 } else if (assignmentObject instanceof AttributeDesignatorType) {
672 htmlOut.println("NA");
673 } else if (assignmentObject instanceof AttributeSelectorType) {
674 htmlOut.println("NA");
675 } else if (assignmentObject instanceof ApplyType) {
676 htmlOut.println("NA");
678 htmlOut.println("Unexpected");
687 public void target(List<AnyOfType> anyOfList) {
688 if (LOGGER.isTraceEnabled())
689 LOGGER.trace("ENTER");
691 if (anyOfList != null) {
692 Iterator<AnyOfType> iterAnyOf = anyOfList.iterator();
693 String targetInHuman = "";
694 while (iterAnyOf.hasNext()) {
695 AnyOfType anyOf = iterAnyOf.next();
696 List<AllOfType> allOfList = anyOf.getAllOf();
697 if (allOfList != null) {
698 Iterator<AllOfType> iterAllOf = allOfList.iterator();
699 while (iterAllOf.hasNext()) {
700 AllOfType allOf = iterAllOf.next();
701 List<MatchType> matchList = allOf.getMatch();
702 if (matchList != null) {
703 Iterator<MatchType> iterMatch = matchList.iterator();
704 if (matchList.size() > 1)
705 targetInHuman += "(";
706 while (iterMatch.hasNext()) {
707 MatchType match = iterMatch.next();
709 // Finally down to the actual attribute
711 StdAttribute attribute = null;
712 AttributeValueType value = match.getAttributeValue();
713 String attributeDataType = null;
714 if (match.getAttributeDesignator() != null && value != null) {
715 AttributeDesignatorType designator = match.getAttributeDesignator();
716 attribute = new StdAttribute(new IdentifierImpl(designator.getCategory()),
717 new IdentifierImpl(designator.getAttributeId()),
718 new StdAttributeValue<List<?>>(new IdentifierImpl(value.getDataType()), value.getContent()),
719 designator.getIssuer(),
721 attributeDataType = designator.getDataType();
722 } else if (match.getAttributeSelector() != null && value != null) {
723 AttributeSelectorType selector = match.getAttributeSelector();
724 attribute = new StdAttribute(new IdentifierImpl(selector.getCategory()),
725 new IdentifierImpl(selector.getContextSelectorId()),
726 new StdAttributeValue<List<?>>(new IdentifierImpl(value.getDataType()), value.getContent()),
729 attributeDataType = selector.getDataType();
731 LOGGER.warn("NULL designator/selector or value for match.");
732 attributeDataType = "NA";
735 String functionName = getHumanFunction(match.getMatchId());
736 if(attribute != null){
737 String succintIdentifier = extractLastIdentifier(attribute.getCategory().stringValue(), ":") +
738 ":" + extractLastIdentifier(attribute.getAttributeId().stringValue(), ":");
739 AttributeIdentifiers ai = new AttributeIdentifiers(attribute.getCategory().stringValue(),
741 attribute.getAttributeId().stringValue());
742 this.attributeIdentifiersMap.put(succintIdentifier,ai);
744 targetInHuman += "<i><a href=\"#" + succintIdentifier + "\">" + succintIdentifier + "</a></i> " + functionName + " ";
746 int numAttributes = attribute.getValues().size();
748 for (AttributeValue<?> v: attribute.getValues()) {
750 if (v.getValue() instanceof Collection<?>) {
751 Collection<?> value_s = (Collection<?>) v.getValue();
752 int numValues = value_s.size();
754 for (Object o : value_s) {
756 targetInHuman += " <I>" + o + "</I>";
757 if (countValues < numValues) {
758 targetInHuman += ", or";
762 targetInHuman += " <I>" + v.getValue() + "</I>";
763 if (count < numAttributes) {
764 targetInHuman += ", or ";
770 if (iterMatch.hasNext()) {
771 targetInHuman += " and ";
774 if (matchList.size() > 1) {
775 targetInHuman += ")";
778 if (iterAllOf.hasNext()) {
779 targetInHuman += " or ";
783 if (iterAnyOf.hasNext()) {
784 targetInHuman = "(" + targetInHuman + ")" + " or ";
786 if (anyOfList.size() > 1) {
787 targetInHuman += ")";
791 htmlOut.println(targetInHuman);
795 private String getHumanFunction(String matchId) {
796 if (HtmlProcessor.function2human.containsKey(matchId)) {
797 return HtmlProcessor.function2human.get(matchId);
800 FunctionDefinition function = PolicyController.getFunctionIDMap().get(matchId);
801 String functionName = function.getShortname();
803 if (LOGGER.isDebugEnabled()) {
804 LOGGER.debug(functionName +
805 ": #args[" + function.getArgLb() + "," + function.getArgUb() +"]");
808 return extractLastIdentifier(removePrimitives(functionName), ":");
811 public String html() {
812 this.htmlOut.flush();
813 return this.stringWriter.toString();
816 private String extractLastIdentifier(String in, String separator) {
817 int lastIndex = in.lastIndexOf(separator);
821 return in.substring(lastIndex+1);
824 private String removePrimitives(String in) {
825 in = in.replace("string-", "");
826 in = in.replace("integer-", "");
827 in = in.replace("double-", "");
828 in = in.replace("boolean-", "");
832 private String stringifyCondition(ConditionType condition) {
833 if (condition.getExpression() == null) {
837 return stringifyExpression(condition.getExpression().getValue());
840 private String stringifyExpression(Object expression) {
841 if (expression instanceof ApplyType) {
842 ApplyType apply = (ApplyType) expression;
843 FunctionDefinition function = PolicyController.getFunctionIDMap().get(apply.getFunctionId());
844 String functionName = function.getShortname();
846 if (LOGGER.isDebugEnabled()) {
847 LOGGER.debug(functionName +
848 ": #args[" + function.getArgLb() + "," + function.getArgUb() +"]");
851 if (functionName.contains("one-and-only")) {
852 if (LOGGER.isDebugEnabled()) {
853 LOGGER.debug("one-and-only found: " + functionName);
856 List<JAXBElement<?>> exps = apply.getExpression();
857 if (exps == null || exps.size() == 0)
860 String forResult = "";
861 for (JAXBElement<?> e : exps) {
862 Object v = e.getValue();
863 if (LOGGER.isDebugEnabled()) {
864 LOGGER.debug("one-and-only children: " + v);
867 // C: return stringifyExpression(v, result);
868 forResult += stringifyExpression(v);
875 final int numExpr = (apply.getExpression() == null) ? -1 : apply.getExpression().size();
877 if (LOGGER.isDebugEnabled()) {
878 LOGGER.debug(functionName + " 0 expressions: " + numExpr);
881 } else if (numExpr == 1) {
883 if (LOGGER.isDebugEnabled()) {
884 LOGGER.debug(functionName + " 1 expression: " + numExpr);
886 String applySubresult = "";
887 for (JAXBElement<?> e : apply.getExpression()) {
888 Object v = e.getValue();
890 applySubresult += this.stringifyExpression(e.getValue());
893 return " " + removePrimitives(functionName) + " (" + applySubresult + ")";
896 if (LOGGER.isDebugEnabled()) {
897 LOGGER.debug(functionName + " > 1 expressions: " + numExpr);
899 String applySubresult = "";
901 for (JAXBElement<?> e : apply.getExpression()) {
903 Object ev = e.getValue();
905 if (ev instanceof ApplyType) {
906 if (((ApplyType) ev).getFunctionId().contains("one-and-only")) {
907 applySubresult += this.stringifyExpression(e.getValue());
909 applySubresult += "(" + this.stringifyExpression(e.getValue()) + ")";
912 applySubresult += this.stringifyExpression(e.getValue());
915 if (exprCount < numExpr) {
916 applySubresult += " " + removePrimitives(functionName) + " ";
920 return applySubresult;
923 if (expression instanceof AttributeDesignatorType) {
924 AttributeDesignatorType adt = (AttributeDesignatorType) expression;
926 String succintIdentifier = extractLastIdentifier(adt.getCategory(), ":") +
927 ":" + extractLastIdentifier(adt.getAttributeId(), ":");
928 AttributeIdentifiers ai = new AttributeIdentifiers(adt.getCategory(),
930 adt.getAttributeId());
931 this.attributeIdentifiersMap.put(succintIdentifier,ai);
933 return "<a href=\"#" + succintIdentifier + "\">" + succintIdentifier + "</a>";
935 if (expression instanceof AttributeSelectorType) {
936 AttributeSelectorType ast = (AttributeSelectorType) expression;
938 String attrName = ast.getPath();
939 if (attrName == null || (attrName.length() == 0)) {
943 String textSelector = "/text()";
944 if (attrName.endsWith(textSelector)) {
945 attrName = attrName.substring(0, attrName.length() - textSelector.length());
948 attrName = extractLastIdentifier(attrName, "/");
949 attrName = extractLastIdentifier(attrName, ":");
950 return " " + attrName;
952 if (expression instanceof AttributeValueType) {
953 AttributeValueType avt = (AttributeValueType) expression;
954 List<Object> content = avt.getContent();
956 for (Object o: content) {
957 value_s += " " + o.toString();
959 return " " + value_s;
961 if (expression instanceof VariableReferenceType) {
963 // Really unknown - the variable may or may not have been defined
965 return " VARIABLEREF-NOT-HANDLED";
967 throw new IllegalArgumentException("Unexpected input expression");
973 class AttributeIdentifiers {
974 public final String category;
976 public final String id;
978 public AttributeIdentifiers(String category, String type, String id) {
979 this.category = category;
984 public String getType() {
988 public void setType(String type) {