2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017-2019 AT&T Intellectual Property. All rights reserved.
6 * Modifications Copyright (C) 2019 Bell Canada
7 * ================================================================================
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 * ============LICENSE_END=========================================================
22 package org.onap.policy.components;
24 import com.att.research.xacml.api.AttributeValue;
25 import com.att.research.xacml.std.IdentifierImpl;
26 import com.att.research.xacml.std.StdAttribute;
27 import com.att.research.xacml.std.StdAttributeValue;
28 import com.att.research.xacml.util.XACMLPolicyScanner.CallbackResult;
29 import com.att.research.xacml.util.XACMLPolicyScanner.SimpleCallback;
32 import java.io.FileInputStream;
33 import java.io.PrintWriter;
34 import java.io.StringWriter;
35 import java.nio.file.Path;
36 import java.nio.file.Paths;
37 import java.util.Collection;
38 import java.util.HashMap;
39 import java.util.Iterator;
40 import java.util.List;
43 import javax.xml.bind.JAXBElement;
45 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AdviceExpressionType;
46 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AdviceExpressionsType;
47 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AllOfType;
48 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AnyOfType;
49 import oasis.names.tc.xacml._3_0.core.schema.wd_17.ApplyType;
50 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeAssignmentExpressionType;
51 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeDesignatorType;
52 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeSelectorType;
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.ConditionType;
55 import oasis.names.tc.xacml._3_0.core.schema.wd_17.MatchType;
56 import oasis.names.tc.xacml._3_0.core.schema.wd_17.ObligationExpressionType;
57 import oasis.names.tc.xacml._3_0.core.schema.wd_17.ObligationExpressionsType;
58 import oasis.names.tc.xacml._3_0.core.schema.wd_17.PolicySetType;
59 import oasis.names.tc.xacml._3_0.core.schema.wd_17.PolicyType;
60 import oasis.names.tc.xacml._3_0.core.schema.wd_17.RuleType;
61 import oasis.names.tc.xacml._3_0.core.schema.wd_17.VariableReferenceType;
63 import org.apache.commons.io.FilenameUtils;
64 import org.json.JSONObject;
65 import org.onap.policy.common.logging.flexlogger.FlexLogger;
66 import org.onap.policy.common.logging.flexlogger.Logger;
67 import org.onap.policy.controller.PolicyController;
68 import org.onap.policy.rest.jpa.FunctionDefinition;
69 import org.onap.policy.xacml.api.XACMLErrorConstants;
70 import org.onap.policy.xacml.util.XACMLPolicyScanner;
72 public class HumanPolicyComponent {
74 private static final Logger LOGGER = FlexLogger.getLogger(HumanPolicyComponent.class);
76 // Constants Used in XML Creation
77 public static final String CATEGORY_RECIPIENT_SUBJECT =
78 "urn:oasis:names:tc:xacml:1.0:subject-category:recipient-subject";
79 public static final String CATEGORY_RESOURCE = "urn:oasis:names:tc:xacml:3.0:attribute-category:resource";
80 public static final String CATEGORY_ACTION = "urn:oasis:names:tc:xacml:3.0:attribute-category:action";
81 public static final String CATEGORY_ACCESS_SUBJECT = "urn:oasis:names:tc:xacml:1.0:subject-category:access-subject";
82 public static final String ACTION_ID = "urn:oasis:names:tc:xacml:1.0:action:action-id";
83 public static final String SUBJECT_ID = "urn:oasis:names:tc:xacml:1.0:subject:subject-id";
84 public static final String RESOURCE_ID = "urn:oasis:names:tc:xacml:1.0:resource:resource-id";
85 public static final String FUNTION_INTEGER_ONE_AND_ONLY =
86 "urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only";
87 public static final String FUNCTION_STRING_ONE_AND_ONLY =
88 "urn:oasis:names:tc:xacml:1.0:function:string-one-and-only";
89 public static final String FUNCTION_STRING_EQUAL = "urn:oasis:names:tc:xacml:1.0:function:string-equal";
90 public static final String FUNCTION_STRING_REGEX_MATCH = "org.onap.function.regex-match";
91 public static final String FUNCTION_STRING_EQUAL_IGNORE =
92 "urn:oasis:names:tc:xacml:3.0:function:string-equal-ignore-case";
93 public static final String INTEGER_DATATYPE = "http://www.w3.org/2001/XMLSchema#integer";
94 public static final String BOOLEAN_DATATYPE = "http://www.w3.org/2001/XMLSchema#boolean";
95 public static final String STRING_DATATYPE = "http://www.w3.org/2001/XMLSchema#string";
96 public static final String URI_DATATYPE = "http://www.w3.org/2001/XMLSchema#anyURI";
97 public static final String RULE_VARIABLE = "var:";
98 public static final String EMPTY_STRING = "";
99 private static final String ENTER = "ENTER";
101 private static HtmlProcessor htmlProcessor;
103 private static File policyFile;
105 private HumanPolicyComponent() {
106 // Default Constructor
112 * @param policyFile File
115 public static JSONObject DescribePolicy(final File policyFile) {
116 if (LOGGER.isTraceEnabled()) {
120 HumanPolicyComponent.policyFile = policyFile;
121 return humanPolicyLayout();
125 private static JSONObject humanPolicyLayout() {
126 if (LOGGER.isTraceEnabled()) {
131 String html = processPolicy();
132 JSONObject result = new JSONObject();
133 result.put("html", html);
136 } catch (IllegalArgumentException e) {
137 LOGGER.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "cannot build html area por policy", e);
142 private static String processPolicy() {
143 if (LOGGER.isTraceEnabled()) {
146 try (FileInputStream pIS = new FileInputStream(policyFile)) {
147 Object policy = XACMLPolicyScanner.readPolicy(pIS);
148 if (policy == null) {
149 throw new IllegalArgumentException("Policy File " + policyFile.getName() + " cannot be unmarshalled");
152 HumanPolicyComponent.htmlProcessor = new HtmlProcessor(HumanPolicyComponent.policyFile, policy);
154 Path policyPath = Paths.get(policyFile.getAbsolutePath());
155 XACMLPolicyScanner xacmlScanner = new XACMLPolicyScanner(policyPath, htmlProcessor);
157 String html = htmlProcessor.html();
158 if (LOGGER.isDebugEnabled()) {
159 LOGGER.debug(policyPath + System.lineSeparator() + html);
164 } catch (Exception e) {
165 String msg = "Exception reading policy: " + policyFile.getAbsolutePath() + ": " + e.getMessage();
166 LOGGER.error(XACMLErrorConstants.ERROR_DATA_ISSUE + msg, e);
167 throw new IllegalArgumentException(msg);
174 class HtmlProcessor extends SimpleCallback {
176 private static final Logger LOGGER = FlexLogger.getLogger(HtmlProcessor.class);
178 private static final String ENTER = "ENTER";
179 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;
193 combiningAlgo2human = new HashMap<>();
194 combiningAlgo2human.put("deny-overrides", "to deny if any $placeholder$ below evaluates to <i>deny</i>");
195 combiningAlgo2human.put("permit-overrides", "to permit if any $placeholder$ below evaluates to <i>permit</i>");
197 combiningAlgo2human.put("ordered-deny-overrides",
198 "to deny if any $placeholder$ below evaluates to <i>deny</i>");
199 combiningAlgo2human.put("ordered-permit-overrides",
200 "to permit if any $placeholder$ below evaluates to <i>permit</i>");
201 combiningAlgo2human.put("deny-unless-permit",
202 "to permit if any $placeholder$ below evaluates to <i>deny</i> and not <i>indeterminate</i>");
204 combiningAlgo2human.put("permit-unless-deny",
205 "to deny if any $placeholder$ below evaluates to is <i>permit</i> and not <i>indeterminate</i>");
206 combiningAlgo2human.put("first-applicable",
207 "to honour the result of the first successfully evaluated $placeholder$ in order");
208 combiningAlgo2human.put("only-one-applicable",
209 "to honour the result of the first successfully evaluated $placeholder$ in order");
212 private Map<String, AttributeIdentifiers> attributeIdentifiersMap = new HashMap<>();
214 private final StringWriter stringWriter = new StringWriter();
215 private final PrintWriter htmlOut = new PrintWriter(stringWriter);
216 private final String policyName;
217 private final Object rootPolicyObject;
219 public HtmlProcessor(File policyFile, Object policyObject) {
220 if (LOGGER.isTraceEnabled()) {
224 if (policyFile == null) {
225 LOGGER.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "Null Policy File");
226 throw new IllegalArgumentException("Null Policy File");
229 if (!policyFile.exists() || !policyFile.canRead()) {
230 String msg = "Can't access " + policyFile.getAbsolutePath();
231 LOGGER.error(XACMLErrorConstants.ERROR_PERMISSIONS + msg);
232 throw new IllegalArgumentException(msg);
235 if ((!(policyObject instanceof PolicySetType) && !(policyObject instanceof PolicyType))) {
236 String msg = "Invalid unmarshalled object: " + policyObject;
237 LOGGER.error(XACMLErrorConstants.ERROR_SCHEMA_INVALID + msg);
238 throw new IllegalArgumentException(msg);
241 this.policyName = FilenameUtils.removeExtension(policyFile.getName());
242 this.rootPolicyObject = policyObject;
244 String version = "-";
245 if (policyObject instanceof PolicyType) {
246 PolicyType policy = (PolicyType) policyObject;
247 version = policy.getVersion();
248 htmlOut.println("<h1>Policy: " + policyName + " (version " + version + ") </h1>");
251 PolicySetType policySet = (PolicySetType) policyObject;
252 version = policySet.getVersion();
253 htmlOut.println("<h1>Policy Set: " + policyName + " (v" + version + ") </h1>");
256 htmlOut.println("<h3><b>Location: </b>" + policyFile.getPath() + "</h3>");
257 htmlOut.println("<hr>");
259 if (rootPolicyObject instanceof PolicySetType) {
260 if (policyName.startsWith("Config_")) {
261 htmlOut.println("<p>This is a <b>config</b> policy set.</p>");
262 } else if (policyName.startsWith("Action_")) {
263 htmlOut.println("<p>This is an <b>action</b> policy set.</p>");
265 htmlOut.println("<dl>");
267 if (policyName.startsWith("Config_")) {
268 htmlOut.println("<p>This is a <b>config</b> policy.</p>");
269 } else if (policyName.startsWith("Action_")) {
270 htmlOut.println("<p>This is an <b>action</b> policy.</p>");
272 htmlOut.println("<ol>");
277 * getAttributeIdentifiersMap.
279 * @return the attributeIdentifiersMap
281 public Map<String, AttributeIdentifiers> getAttributeIdentifiersMap() {
282 return attributeIdentifiersMap;
286 public void onFinishScan(Object root) {
287 if (LOGGER.isTraceEnabled()) {
291 if (rootPolicyObject instanceof PolicySetType) {
292 htmlOut.println("</dl>");
294 htmlOut.println("</ol>");
297 htmlOut.println("<hr>");
299 htmlOut.println("<h3>Attribute Table:</h3>");
301 htmlOut.println("<table border=\"3\" style=\"width:100%\">");
302 htmlOut.println("<tr>");
303 htmlOut.print("<th>Category</th>");
304 htmlOut.print("<th>Type</th>");
305 htmlOut.print("<th>Identifier</th>");
306 htmlOut.println("</tr>");
307 for (Map.Entry<String, AttributeIdentifiers> entry : this.attributeIdentifiersMap.entrySet()) {
308 AttributeIdentifiers value = entry.getValue();
309 htmlOut.println("<tr>");
310 htmlOut.print("<td><a name=\"" + entry.getKey() + "\"></a>" + value.category + "</td>");
311 htmlOut.print("<td>" + value.getType() + "</td>");
312 htmlOut.print("<td>" + value.id + "</td>");
313 htmlOut.println("</tr>");
315 htmlOut.println("</table>");
317 htmlOut.println("<p></p>");
319 // Not necessary for the user, uncomment if desired at some point
322 super.onFinishScan(root);
326 public CallbackResult onPreVisitPolicySet(PolicySetType parent, PolicySetType policySet) {
327 if (LOGGER.isTraceEnabled()) {
328 LOGGER.trace("PolicySet: " + policySet.getPolicySetId() + " Version: " + policySet.getVersion());
331 if (parent != null && LOGGER.isTraceEnabled()) {
332 LOGGER.trace("PolicySet: " + policySet.getPolicySetId() + "Parent PolicySet: " + parent.getPolicySetId()
333 + " Version: " + parent.getVersion());
336 String description = policySet.getDescription();
337 if (description != null && LOGGER.isTraceEnabled()) {
338 LOGGER.trace("PolicySet: " + policySet.getPolicySetId() + " Description: " + policySet.getDescription());
341 if (parent == null) { // root
342 policySet(policySet, "dl");
344 policySet(policySet, "li");
347 if (!policySet.getPolicySetOrPolicyOrPolicySetIdReference().isEmpty()) {
348 htmlOut.println("<ol>");
351 return super.onPreVisitPolicySet(parent, policySet);
355 public CallbackResult onPostVisitPolicySet(PolicySetType parent, PolicySetType policySet) {
356 if (LOGGER.isTraceEnabled()) {
357 LOGGER.trace("PolicySet: " + policySet.getPolicySetId() + " Version: " + policySet.getVersion());
360 if (parent != null && LOGGER.isTraceEnabled()) {
361 LOGGER.trace("PolicySet: " + policySet.getPolicySetId() + "Parent PolicySet: " + parent.getPolicySetId()
362 + " Version: " + parent.getVersion());
365 String description = policySet.getDescription();
366 if (description != null && LOGGER.isTraceEnabled()) {
367 LOGGER.trace("PolicySet: " + policySet.getPolicySetId() + " Description: " + policySet.getDescription());
370 if (!policySet.getPolicySetOrPolicyOrPolicySetIdReference().isEmpty()) {
371 htmlOut.println("</ol>");
374 htmlOut.println("<p></p>");
376 return super.onPostVisitPolicySet(parent, policySet);
379 public void policySet(PolicySetType policySet, String htmlListElement) {
380 if (LOGGER.isTraceEnabled()) {
381 LOGGER.trace("PolicySet: " + policySet.getPolicySetId());
384 String combiningAlgorithm = "-";
386 String version = "-";
388 if (policySet.getPolicyCombiningAlgId() != null) {
389 combiningAlgorithm = extractLastIdentifier(policySet.getPolicyCombiningAlgId(), ":");
392 if (policySet.getPolicySetId() != null) {
393 id = extractLastIdentifier(policySet.getPolicySetId(), ":");
396 if (policySet.getVersion() != null) {
397 version = policySet.getVersion();
400 htmlOut.println("<" + htmlListElement + "><b>Policy Set ID</b>: <i>" + id + "</i> (v" + version + ") " + "</"
401 + htmlListElement + ">");
403 if (policySet.getTarget() == null || policySet.getTarget().getAnyOf() == null
404 || policySet.getTarget().getAnyOf().isEmpty()) {
405 htmlOut.println("<p>This policy set applies to all requests.</p>");
407 htmlOut.print("<p>");
408 htmlOut.print("This policy set applies to requests with attributes ");
410 target(policySet.getTarget().getAnyOf());
411 htmlOut.println(".</p>");
414 if (policySet.getPolicySetOrPolicyOrPolicySetIdReference() != null
415 && !policySet.getPolicySetOrPolicyOrPolicySetIdReference().isEmpty()) {
416 String algoDesc = combiningAlgo2human.get(combiningAlgorithm);
417 if (algoDesc != null) {
418 algoDesc = algoDesc.replace("$placeholder$", "policy") + " (" + "<i>" + combiningAlgorithm + "</i>)";
420 algoDesc = combiningAlgorithm;
423 htmlOut.println("<p>The result is " + algoDesc + ": </p>");
428 public CallbackResult onPreVisitPolicy(PolicySetType parent, PolicyType policy) {
429 if (LOGGER.isTraceEnabled()) {
430 LOGGER.trace("PolicySet: " + policy.getPolicyId() + " Version: " + policy.getVersion());
433 if (parent != null && LOGGER.isTraceEnabled()) {
434 LOGGER.trace("PolicySet: " + policy.getPolicyId() + "Parent PolicySet: " + parent.getPolicySetId()
435 + " Version: " + parent.getVersion());
438 String description = policy.getDescription();
439 if (description != null && LOGGER.isTraceEnabled()) {
440 LOGGER.trace("PolicySet: " + policy.getPolicyId() + " Description: " + policy.getDescription());
445 if (!policy.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition().isEmpty()) {
446 htmlOut.println("<ol type=\"i\">");
449 return super.onPreVisitPolicy(parent, policy);
453 public CallbackResult onPostVisitPolicy(PolicySetType parent, PolicyType policy) {
454 if (LOGGER.isTraceEnabled()) {
455 LOGGER.trace("PolicySet: " + policy.getPolicyId() + " Version: " + policy.getVersion());
458 if (parent != null && LOGGER.isTraceEnabled()) {
459 LOGGER.trace("PolicySet: " + policy.getPolicyId() + "Parent PolicySet: " + parent.getPolicySetId()
460 + " Version: " + parent.getVersion());
463 if (!policy.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition().isEmpty()) {
464 htmlOut.println("</ol>");
467 htmlOut.println("<p></p>");
468 return super.onPostVisitPolicy(parent, policy);
471 public void policy(PolicyType policy) {
472 if (LOGGER.isTraceEnabled()) {
473 LOGGER.trace("Policy: " + policy.getPolicyId());
476 String combiningAlgorithm = "-";
478 String version = "-";
480 if (policy.getRuleCombiningAlgId() != null) {
481 combiningAlgorithm = extractLastIdentifier(policy.getRuleCombiningAlgId(), ":");
484 if (policy.getPolicyId() != null) {
485 id = extractLastIdentifier(policy.getPolicyId(), ":");
488 if (policy.getVersion() != null) {
489 version = policy.getVersion();
492 htmlOut.println("<li><b>Policy ID</b>: <i>" + id + "</i> (v" + version + ") " + "</li>");
494 if (policy.getTarget() == null || policy.getTarget().getAnyOf() == null
495 || policy.getTarget().getAnyOf().isEmpty()) {
496 htmlOut.println("<p>This policy applies to all requests.</p>");
498 htmlOut.print("<p>");
499 htmlOut.print("This policy applies to requests with attributes ");
501 target(policy.getTarget().getAnyOf());
502 htmlOut.println(".</p>");
505 if (policy.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition() != null
506 && !policy.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition().isEmpty()) {
507 String algoDesc = combiningAlgo2human.get(combiningAlgorithm);
508 if (algoDesc != null) {
509 algoDesc = algoDesc.replace("$placeholder$", "rule") + " (<i>" + combiningAlgorithm + "</i>)";
511 algoDesc = combiningAlgorithm;
513 htmlOut.println("<p>The result is " + algoDesc + ": </p>");
518 public CallbackResult onPreVisitRule(PolicyType parent, RuleType rule) {
519 if (LOGGER.isTraceEnabled()) {
520 LOGGER.trace("Rule: " + rule.getRuleId());
523 if (parent != null && LOGGER.isTraceEnabled()) {
524 LOGGER.trace("Parent Policy: " + parent.getPolicyId() + " Version: " + parent.getVersion());
527 String description = rule.getDescription();
528 if (description != null && LOGGER.isTraceEnabled()) {
529 LOGGER.trace("Rule: " + rule.getRuleId() + " Description: " + rule.getDescription());
534 return super.onPreVisitRule(parent, rule);
538 public CallbackResult onPostVisitRule(PolicyType parent, RuleType rule) {
540 if (parent != null && LOGGER.isTraceEnabled()) {
541 LOGGER.trace("Parent Policy: " + parent.getPolicyId() + " Version: " + parent.getVersion());
544 return super.onPostVisitRule(parent, rule);
547 public void rule(RuleType rule) {
551 if (rule.getRuleId() != null) {
552 id = extractLastIdentifier(rule.getRuleId(), ":");
555 htmlOut.println("<li><b>Rule ID</b>: <i>" + id + "</i></li>");
557 htmlOut.println("<dl>");
559 htmlOut.print("<p>");
560 htmlOut.print(rule.getEffect().value());
562 if (rule.getTarget() == null || rule.getTarget().getAnyOf() == null || rule.getTarget().getAnyOf().isEmpty()) {
563 htmlOut.print(" for all requests");
565 htmlOut.print(" for requests with attributes ");
566 target(rule.getTarget().getAnyOf());
569 if (rule.getCondition() != null) {
570 htmlOut.print(" when ");
571 htmlOut.println(this.stringifyCondition(rule.getCondition()) + " ");
573 htmlOut.print(" with no conditions ");
576 if (rule.getAdviceExpressions() != null) {
577 advice(rule.getAdviceExpressions());
578 if (rule.getObligationExpressions() != null) {
579 htmlOut.println(" and ");
583 if (rule.getObligationExpressions() != null) {
584 obligation(rule.getObligationExpressions());
587 htmlOut.println("</p>");
590 private void advice(AdviceExpressionsType adviceExpressions) {
591 if (LOGGER.isTraceEnabled()) {
595 List<AdviceExpressionType> ae = adviceExpressions.getAdviceExpression();
596 for (AdviceExpressionType expression : ae) {
597 htmlOut.println(" with <b>advice</b> (<i>" + expression.getAdviceId() + "</i>) on <i>"
598 + expression.getAppliesTo().value() + "</i>:");
599 htmlOut.println("<ol type=\"a\">");
600 List<AttributeAssignmentExpressionType> assignments = expression.getAttributeAssignmentExpression();
601 if (assignments != null) {
602 processAttributeAssignments(assignments);
604 htmlOut.println("</ol>");
608 private void obligation(ObligationExpressionsType obligationExpressions) {
609 if (LOGGER.isTraceEnabled()) {
613 List<ObligationExpressionType> oe = obligationExpressions.getObligationExpression();
614 for (ObligationExpressionType expression : oe) {
615 htmlOut.println(" with <b>obligations</b> (<i>" + expression.getObligationId()
616 + "</i>) to be fullfilled on <i>" + expression.getFulfillOn().value() + "</i>:");
617 htmlOut.println("<ol type=\"a\">");
618 List<AttributeAssignmentExpressionType> assignments = expression.getAttributeAssignmentExpression();
619 if (assignments != null) {
620 processAttributeAssignments(assignments);
622 htmlOut.println("</ol>");
627 * processAttributeAssignments.
629 * @param assignments List of AttributeAssignmentExpressionType
631 private void processAttributeAssignments(List<AttributeAssignmentExpressionType> assignments) {
632 if (LOGGER.isTraceEnabled()) {
636 for (AttributeAssignmentExpressionType assignment : assignments) {
637 String succintIdentifier = extractLastIdentifier(assignment.getCategory(), ":") + ":"
638 + extractLastIdentifier(assignment.getAttributeId(), ":");
639 AttributeIdentifiers attributeIdentifiers = null;
640 if (!this.attributeIdentifiersMap.containsKey(succintIdentifier)) {
641 // Note Attribute Assignments do not have an Attribute Type, assume string
642 // but note this case is unlikely since attributeMap should have been populated
643 // during parsing of target and conditions, and not in this case for Advice and
645 attributeIdentifiers =
646 new AttributeIdentifiers(assignment.getCategory(), "NA", assignment.getAttributeId());
647 this.attributeIdentifiersMap.put(succintIdentifier, attributeIdentifiers);
650 htmlOut.print("<li><i><a href=\"#" + succintIdentifier + "\">" + succintIdentifier + "</a></i> is ");
651 // AttributeValueType
652 JAXBElement<?> jaxbExp = assignment.getExpression();
653 Object assignmentObject = jaxbExp.getValue();
654 if (assignmentObject instanceof AttributeValueType) {
655 AttributeValueType avt = (AttributeValueType) assignmentObject;
656 if (attributeIdentifiers != null) {
657 attributeIdentifiers.setType(avt.getDataType());
659 int numContent = avt.getContent().size();
660 int countContent = 0;
661 for (Object c : avt.getContent()) {
663 htmlOut.print("<i>" + c + "</i>");
664 if (countContent < numContent) {
665 htmlOut.print(" or ");
668 htmlOut.println("</li>");
669 } else if (assignmentObject instanceof AttributeDesignatorType
670 || assignmentObject instanceof AttributeSelectorType || assignmentObject instanceof ApplyType) {
671 htmlOut.println("NA");
673 htmlOut.println("Unexpected");
681 * @param anyOfList List of AnyOfType's
683 public void target(List<AnyOfType> anyOfList) {
684 if (LOGGER.isTraceEnabled()) {
688 if (anyOfList == null) {
691 Iterator<AnyOfType> iterAnyOf = anyOfList.iterator();
692 StringBuilder targetInHuman = new StringBuilder();
693 while (iterAnyOf.hasNext()) {
694 AnyOfType anyOf = iterAnyOf.next();
695 List<AllOfType> allOfList = anyOf.getAllOf();
696 Iterator<AllOfType> iterAllOf = allOfList.iterator();
697 while (iterAllOf.hasNext()) {
698 AllOfType allOf = iterAllOf.next();
699 List<MatchType> matchList = allOf.getMatch();
700 Iterator<MatchType> iterMatch = matchList.iterator();
701 if (matchList.size() > 1) {
702 targetInHuman.append("(");
704 while (iterMatch.hasNext()) {
705 MatchType match = iterMatch.next();
707 // Finally down to the actual attribute
709 StdAttribute attribute = null;
710 AttributeValueType value = match.getAttributeValue();
711 String attributeDataType;
712 if (match.getAttributeDesignator() != null && value != null) {
713 AttributeDesignatorType designator = match.getAttributeDesignator();
714 attribute = new StdAttribute(new IdentifierImpl(designator.getCategory()),
715 new IdentifierImpl(designator.getAttributeId()),
716 new StdAttributeValue<List<?>>(new IdentifierImpl(value.getDataType()),
718 designator.getIssuer(), false);
719 attributeDataType = designator.getDataType();
720 } else if (match.getAttributeSelector() != null && value != null) {
721 AttributeSelectorType selector = match.getAttributeSelector();
722 attribute = new StdAttribute(new IdentifierImpl(selector.getCategory()),
723 new IdentifierImpl(selector.getContextSelectorId()),
724 new StdAttributeValue<List<?>>(new IdentifierImpl(value.getDataType()),
727 attributeDataType = selector.getDataType();
729 LOGGER.warn("NULL designator/selector or value for match.");
730 attributeDataType = "NA";
733 String functionName = getHumanFunction(match.getMatchId());
734 if (attribute != null) {
735 String succintIdentifier = extractLastIdentifier(
736 attribute.getCategory().stringValue(), ":") + ":"
737 + extractLastIdentifier(attribute.getAttributeId().stringValue(), ":");
738 AttributeIdentifiers ai =
739 new AttributeIdentifiers(attribute.getCategory().stringValue(),
740 attributeDataType, attribute.getAttributeId().stringValue());
741 this.attributeIdentifiersMap.put(succintIdentifier, ai);
743 targetInHuman.append("<i><a href=\"#" + succintIdentifier + "\">"
744 + succintIdentifier + "</a></i> " + functionName + " ");
746 int numAttributes = attribute.getValues().size();
748 for (AttributeValue<?> v : attribute.getValues()) {
750 if (v.getValue() instanceof Collection<?>) {
751 Collection<?> collectionValues = (Collection<?>) v.getValue();
752 int numValues = collectionValues.size();
754 for (Object o : collectionValues) {
756 targetInHuman.append(" <I>" + o + "</I>");
757 if (countValues < numValues) {
758 targetInHuman.append(", or");
762 targetInHuman.append(" <I>" + v.getValue() + "</I>");
763 if (count < numAttributes) {
764 targetInHuman.append(", or ");
770 if (iterMatch.hasNext()) {
771 targetInHuman.append(" and ");
774 if (matchList.size() > 1) {
775 targetInHuman.append(")");
778 if (iterAllOf.hasNext()) {
779 targetInHuman.append(" or ");
782 if (iterAnyOf.hasNext()) {
783 targetInHuman = new StringBuilder();
784 targetInHuman.append("(" + targetInHuman + ")" + " or ");
786 if (anyOfList.size() > 1) {
787 targetInHuman.append(")");
790 htmlOut.println(targetInHuman);
793 private String getHumanFunction(String matchId) {
794 if (HtmlProcessor.function2human.containsKey(matchId)) {
795 return HtmlProcessor.function2human.get(matchId);
798 FunctionDefinition function = PolicyController.getFunctionIdMap().get(matchId);
799 String functionName = function.getShortname();
801 if (LOGGER.isDebugEnabled()) {
802 LOGGER.debug(functionName + ": #args[" + function.getArgLb() + "," + function.getArgUb() + "]");
805 return extractLastIdentifier(removePrimitives(functionName), ":");
808 public String html() {
809 this.htmlOut.flush();
810 return this.stringWriter.toString();
813 private String extractLastIdentifier(String in, String separator) {
814 int lastIndex = in.lastIndexOf(separator);
818 return in.substring(lastIndex + 1);
822 private String removePrimitives(String in) {
824 newIn = newIn.replace("string-", "");
825 newIn = newIn.replace("integer-", "");
826 newIn = newIn.replace("double-", "");
827 newIn = newIn.replace("boolean-", "");
831 private String stringifyCondition(ConditionType condition) {
832 if (condition.getExpression() == null) {
836 return stringifyExpression(condition.getExpression().getValue());
839 private String stringifyExpression(Object expression) {
840 if (expression instanceof ApplyType) {
841 ApplyType apply = (ApplyType) expression;
842 FunctionDefinition function = PolicyController.getFunctionIdMap().get(apply.getFunctionId());
843 String functionName = function.getShortname();
845 if (LOGGER.isDebugEnabled()) {
846 LOGGER.debug(functionName + ": #args[" + function.getArgLb() + "," + function.getArgUb() + "]");
849 if (functionName.contains("one-and-only")) {
850 if (LOGGER.isDebugEnabled()) {
851 LOGGER.debug("one-and-only found: " + functionName);
854 List<JAXBElement<?>> exps = apply.getExpression();
855 if (exps == null || exps.isEmpty()) {
858 StringBuilder forResult = new StringBuilder();
859 for (JAXBElement<?> e : exps) {
860 Object theValue = e.getValue();
861 if (LOGGER.isDebugEnabled()) {
862 LOGGER.debug("one-and-only children: " + theValue);
864 if (theValue != null) {
865 forResult.append(stringifyExpression(theValue));
868 return forResult.toString();
872 final int numExpr = (apply.getExpression() == null) ? -1 : apply.getExpression().size();
874 if (LOGGER.isDebugEnabled()) {
875 LOGGER.debug(functionName + " 0 expressions: " + numExpr);
878 } else if (numExpr == 1) {
880 if (LOGGER.isDebugEnabled()) {
881 LOGGER.debug(functionName + " 1 expression: " + numExpr);
883 StringBuilder applySubresult = new StringBuilder();
884 for (JAXBElement<?> e : apply.getExpression()) {
885 Object theValue = e.getValue();
886 if (theValue != null) {
887 applySubresult.append(this.stringifyExpression(e.getValue()));
890 return " " + removePrimitives(functionName) + " (" + applySubresult.toString() + ")";
893 if (LOGGER.isDebugEnabled()) {
894 LOGGER.debug(functionName + " > 1 expressions: " + numExpr);
896 StringBuilder applySubresult = new StringBuilder();
898 for (JAXBElement<?> e : apply.getExpression()) {
900 Object ev = e.getValue();
902 if (ev instanceof ApplyType) {
903 if (((ApplyType) ev).getFunctionId().contains("one-and-only")) {
904 applySubresult.append(this.stringifyExpression(e.getValue()));
906 applySubresult.append("(" + this.stringifyExpression(e.getValue()) + ")");
909 applySubresult.append(this.stringifyExpression(e.getValue()));
912 if (exprCount < numExpr) {
913 applySubresult.append(" " + removePrimitives(functionName) + " ");
917 return applySubresult.toString();
920 if (expression instanceof AttributeDesignatorType) {
921 AttributeDesignatorType adt = (AttributeDesignatorType) expression;
923 String succintIdentifier = extractLastIdentifier(adt.getCategory(), ":") + ":"
924 + extractLastIdentifier(adt.getAttributeId(), ":");
925 AttributeIdentifiers ai =
926 new AttributeIdentifiers(adt.getCategory(), adt.getDataType(), adt.getAttributeId());
927 this.attributeIdentifiersMap.put(succintIdentifier, ai);
929 return "<a href=\"#" + succintIdentifier + "\">" + succintIdentifier + "</a>";
931 if (expression instanceof AttributeSelectorType) {
932 AttributeSelectorType ast = (AttributeSelectorType) expression;
934 String attrName = ast.getPath();
935 if (attrName == null || (attrName.length() == 0)) {
939 String textSelector = "/text()";
940 if (attrName.endsWith(textSelector)) {
941 attrName = attrName.substring(0, attrName.length() - textSelector.length());
944 attrName = extractLastIdentifier(attrName, "/");
945 attrName = extractLastIdentifier(attrName, ":");
946 return " " + attrName;
948 if (expression instanceof AttributeValueType) {
949 AttributeValueType avt = (AttributeValueType) expression;
950 List<Object> content = avt.getContent();
951 StringBuilder stringValue = new StringBuilder(" ");
952 for (Object o : content) {
953 stringValue.append(" ");
954 stringValue.append(o.toString());
956 return stringValue.toString();
958 if (expression instanceof VariableReferenceType) {
960 // Really unknown - the variable may or may not have been defined
962 return " VARIABLEREF-NOT-HANDLED";
964 throw new IllegalArgumentException("Unexpected input expression");
970 class AttributeIdentifiers {
971 public final String category;
973 public final String id;
975 public AttributeIdentifiers(String category, String type, String id) {
976 this.category = category;
981 public String getType() {
985 public void setType(String type) {