2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017-2018 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;
42 import javax.xml.bind.JAXBElement;
43 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AdviceExpressionType;
44 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AdviceExpressionsType;
45 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AllOfType;
46 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AnyOfType;
47 import oasis.names.tc.xacml._3_0.core.schema.wd_17.ApplyType;
48 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeAssignmentExpressionType;
49 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeDesignatorType;
50 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeSelectorType;
51 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeValueType;
52 import oasis.names.tc.xacml._3_0.core.schema.wd_17.ConditionType;
53 import oasis.names.tc.xacml._3_0.core.schema.wd_17.MatchType;
54 import oasis.names.tc.xacml._3_0.core.schema.wd_17.ObligationExpressionType;
55 import oasis.names.tc.xacml._3_0.core.schema.wd_17.ObligationExpressionsType;
56 import oasis.names.tc.xacml._3_0.core.schema.wd_17.PolicySetType;
57 import oasis.names.tc.xacml._3_0.core.schema.wd_17.PolicyType;
58 import oasis.names.tc.xacml._3_0.core.schema.wd_17.RuleType;
59 import oasis.names.tc.xacml._3_0.core.schema.wd_17.VariableReferenceType;
60 import org.apache.commons.io.FilenameUtils;
61 import org.json.JSONObject;
62 import org.onap.policy.common.logging.flexlogger.FlexLogger;
63 import org.onap.policy.common.logging.flexlogger.Logger;
64 import org.onap.policy.controller.PolicyController;
65 import org.onap.policy.rest.jpa.FunctionDefinition;
66 import org.onap.policy.xacml.api.XACMLErrorConstants;
67 import org.onap.policy.xacml.util.XACMLPolicyScanner;
69 public class HumanPolicyComponent {
71 private static final Logger LOGGER = FlexLogger.getLogger(HumanPolicyComponent.class);
73 // Constants Used in XML Creation
74 public static final String CATEGORY_RECIPIENT_SUBJECT =
75 "urn:oasis:names:tc:xacml:1.0:subject-category:recipient-subject";
76 public static final String CATEGORY_RESOURCE = "urn:oasis:names:tc:xacml:3.0:attribute-category:resource";
77 public static final String CATEGORY_ACTION = "urn:oasis:names:tc:xacml:3.0:attribute-category:action";
78 public static final String CATEGORY_ACCESS_SUBJECT = "urn:oasis:names:tc:xacml:1.0:subject-category:access-subject";
79 public static final String ACTION_ID = "urn:oasis:names:tc:xacml:1.0:action:action-id";
80 public static final String SUBJECT_ID = "urn:oasis:names:tc:xacml:1.0:subject:subject-id";
81 public static final String RESOURCE_ID = "urn:oasis:names:tc:xacml:1.0:resource:resource-id";
82 public static final String FUNTION_INTEGER_ONE_AND_ONLY =
83 "urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only";
84 public static final String FUNCTION_STRING_ONE_AND_ONLY =
85 "urn:oasis:names:tc:xacml:1.0:function:string-one-and-only";
86 public static final String FUNCTION_STRING_EQUAL = "urn:oasis:names:tc:xacml:1.0:function:string-equal";
87 public static final String FUNCTION_STRING_REGEX_MATCH = "org.onap.function.regex-match";
88 public static final String FUNCTION_STRING_EQUAL_IGNORE =
89 "urn:oasis:names:tc:xacml:3.0:function:string-equal-ignore-case";
90 public static final String INTEGER_DATATYPE = "http://www.w3.org/2001/XMLSchema#integer";
91 public static final String BOOLEAN_DATATYPE = "http://www.w3.org/2001/XMLSchema#boolean";
92 public static final String STRING_DATATYPE = "http://www.w3.org/2001/XMLSchema#string";
93 public static final String URI_DATATYPE = "http://www.w3.org/2001/XMLSchema#anyURI";
94 public static final String RULE_VARIABLE = "var:";
95 public static final String EMPTY_STRING = "";
96 private static final String ENTER = "ENTER";
99 private static HtmlProcessor htmlProcessor;
101 private static File policyFile;
103 private HumanPolicyComponent() {
104 // Default Constructor
107 public static JSONObject DescribePolicy(final File policyFile) {
108 if (LOGGER.isTraceEnabled())
111 HumanPolicyComponent.policyFile = policyFile;
112 return humanPolicyLayout();
116 private static JSONObject humanPolicyLayout() {
117 if (LOGGER.isTraceEnabled())
121 String html = processPolicy();
122 JSONObject result = new JSONObject();
123 result.put("html", html);
126 } catch (IllegalArgumentException e) {
127 LOGGER.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "cannot build html area por policy", e);
132 private static String processPolicy() {
133 if (LOGGER.isTraceEnabled()) {
136 try (FileInputStream pIS = new FileInputStream(policyFile)) {
137 Object policy = XACMLPolicyScanner.readPolicy(pIS);
139 throw new IllegalArgumentException("Policy File " + policyFile.getName() + " cannot be unmarshalled");
141 HumanPolicyComponent.htmlProcessor = new HtmlProcessor(HumanPolicyComponent.policyFile, policy);
143 Path policyPath = Paths.get(policyFile.getAbsolutePath());
144 XACMLPolicyScanner xacmlScanner = new XACMLPolicyScanner(policyPath, htmlProcessor);
146 String html = htmlProcessor.html();
147 if (LOGGER.isDebugEnabled())
148 LOGGER.debug(policyPath + System.lineSeparator() + html);
152 } catch (Exception e) {
153 String msg = "Exception reading policy: " + policyFile.getAbsolutePath() + ": " + e.getMessage();
154 LOGGER.error(XACMLErrorConstants.ERROR_DATA_ISSUE + msg, e);
155 throw new IllegalArgumentException(msg);
162 class HtmlProcessor extends SimpleCallback {
164 private static final Logger LOGGER = FlexLogger.getLogger(HtmlProcessor.class);
166 private static final String ENTER = "ENTER";
167 private static Map<String, String> function2human;
169 function2human = new HashMap<>();
170 function2human.put(HumanPolicyComponent.FUNCTION_STRING_EQUAL, "equal");
171 function2human.put(HumanPolicyComponent.FUNCTION_STRING_EQUAL_IGNORE, "equal");
172 function2human.put(HumanPolicyComponent.FUNCTION_STRING_ONE_AND_ONLY, "one-and-only");
173 function2human.put(HumanPolicyComponent.FUNCTION_STRING_REGEX_MATCH, "matching regular expression");
174 function2human.put(HumanPolicyComponent.FUNTION_INTEGER_ONE_AND_ONLY, "one-and-only");
177 private static Map<String, String> combiningAlgo2human;
179 combiningAlgo2human = new HashMap<>();
180 combiningAlgo2human.put("deny-overrides", "to deny if any $placeholder$ below evaluates to <i>deny</i>");
181 combiningAlgo2human.put("permit-overrides", "to permit if any $placeholder$ below evaluates to <i>permit</i>");
183 combiningAlgo2human.put("ordered-deny-overrides",
184 "to deny if any $placeholder$ below evaluates to <i>deny</i>");
185 combiningAlgo2human.put("ordered-permit-overrides",
186 "to permit if any $placeholder$ below evaluates to <i>permit</i>");
187 combiningAlgo2human.put("deny-unless-permit",
188 "to permit if any $placeholder$ below evaluates to <i>deny</i> and not <i>indeterminate</i>");
190 combiningAlgo2human.put("permit-unless-deny",
191 "to deny if any $placeholder$ below evaluates to is <i>permit</i> and not <i>indeterminate</i>");
192 combiningAlgo2human.put("first-applicable",
193 "to honour the result of the first successfully evaluated $placeholder$ in order");
194 combiningAlgo2human.put("only-one-applicable",
195 "to honour the result of the first successfully evaluated $placeholder$ in order");
198 private Map<String, AttributeIdentifiers> attributeIdentifiersMap = new HashMap<>();
200 private final StringWriter stringWriter = new StringWriter();
201 private final PrintWriter htmlOut = new PrintWriter(stringWriter);
202 private final String policyName;
203 private final Object rootPolicyObject;
205 public HtmlProcessor(File policyFile, Object policyObject) {
206 if (LOGGER.isTraceEnabled())
209 if (policyFile == null) {
210 LOGGER.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "Null Policy File");
211 throw new IllegalArgumentException("Null Policy File");
214 if (!policyFile.exists() || !policyFile.canRead()) {
215 String msg = "Can't access " + policyFile.getAbsolutePath();
216 LOGGER.error(XACMLErrorConstants.ERROR_PERMISSIONS + msg);
217 throw new IllegalArgumentException(msg);
220 if ((!(policyObject instanceof PolicySetType) && !(policyObject instanceof PolicyType))) {
221 String msg = "Invalid unmarshalled object: " + policyObject;
222 LOGGER.error(XACMLErrorConstants.ERROR_SCHEMA_INVALID + msg);
223 throw new IllegalArgumentException(msg);
226 this.policyName = FilenameUtils.removeExtension(policyFile.getName());
227 this.rootPolicyObject = policyObject;
229 String version = "-";
230 if (policyObject instanceof PolicyType) {
231 PolicyType policy = (PolicyType) policyObject;
232 version = policy.getVersion();
233 htmlOut.println("<h1>Policy: " + policyName + " (version " + version + ") </h1>");
236 PolicySetType policySet = (PolicySetType) policyObject;
237 version = policySet.getVersion();
238 htmlOut.println("<h1>Policy Set: " + policyName + " (v" + version + ") </h1>");
241 htmlOut.println("<h3><b>Location: </b>" + policyFile.getPath() + "</h3>");
242 htmlOut.println("<hr>");
244 if (rootPolicyObject instanceof PolicySetType) {
245 if (policyName.startsWith("Config_")) {
246 htmlOut.println("<p>This is a <b>config</b> policy set.</p>");
247 } else if (policyName.startsWith("Action_")) {
248 htmlOut.println("<p>This is an <b>action</b> policy set.</p>");
250 htmlOut.println("<dl>");
252 if (policyName.startsWith("Config_")) {
253 htmlOut.println("<p>This is a <b>config</b> policy.</p>");
254 } else if (policyName.startsWith("Action_")) {
255 htmlOut.println("<p>This is an <b>action</b> policy.</p>");
257 htmlOut.println("<ol>");
262 * @return the attributeIdentifiersMap
264 public Map<String, AttributeIdentifiers> getAttributeIdentifiersMap() {
265 return attributeIdentifiersMap;
269 public void onFinishScan(Object root) {
270 if (LOGGER.isTraceEnabled())
273 if (rootPolicyObject instanceof PolicySetType) {
274 htmlOut.println("</dl>");
276 htmlOut.println("</ol>");
279 htmlOut.println("<hr>");
281 htmlOut.println("<h3>Attribute Table:</h3>");
283 htmlOut.println("<table border=\"3\" style=\"width:100%\">");
284 htmlOut.println("<tr>");
285 htmlOut.print("<th>Category</th>");
286 htmlOut.print("<th>Type</th>");
287 htmlOut.print("<th>Identifier</th>");
288 htmlOut.println("</tr>");
289 for (Map.Entry<String, AttributeIdentifiers> entry : this.attributeIdentifiersMap.entrySet()) {
290 AttributeIdentifiers value = entry.getValue();
291 htmlOut.println("<tr>");
292 htmlOut.print("<td><a name=\"" + entry.getKey() + "\"></a>" + value.category + "</td>");
293 htmlOut.print("<td>" + value.getType() + "</td>");
294 htmlOut.print("<td>" + value.id + "</td>");
295 htmlOut.println("</tr>");
297 htmlOut.println("</table>");
299 htmlOut.println("<p></p>");
301 // Not necessary for the user, uncomment if desired at some point
304 super.onFinishScan(root);
308 public CallbackResult onPreVisitPolicySet(PolicySetType parent, PolicySetType policySet) {
309 if (LOGGER.isTraceEnabled())
310 LOGGER.trace("PolicySet: " + policySet.getPolicySetId() + " Version: " + policySet.getVersion());
312 if (parent != null && LOGGER.isTraceEnabled())
313 LOGGER.trace("PolicySet: " + policySet.getPolicySetId() + "Parent PolicySet: " + parent.getPolicySetId()
314 + " Version: " + parent.getVersion());
316 String description = policySet.getDescription();
317 if (description != null && LOGGER.isTraceEnabled())
318 LOGGER.trace("PolicySet: " + policySet.getPolicySetId() + " Description: " + policySet.getDescription());
320 if (parent == null) // root
321 policySet(policySet, "dl");
323 policySet(policySet, "li");
325 if (!policySet.getPolicySetOrPolicyOrPolicySetIdReference().isEmpty())
326 htmlOut.println("<ol>");
328 return super.onPreVisitPolicySet(parent, policySet);
332 public CallbackResult onPostVisitPolicySet(PolicySetType parent, PolicySetType policySet) {
333 if (LOGGER.isTraceEnabled())
334 LOGGER.trace("PolicySet: " + policySet.getPolicySetId() + " Version: " + policySet.getVersion());
336 if (parent != null && LOGGER.isTraceEnabled())
337 LOGGER.trace("PolicySet: " + policySet.getPolicySetId() + "Parent PolicySet: " + parent.getPolicySetId()
338 + " Version: " + parent.getVersion());
340 String description = policySet.getDescription();
341 if (description != null && LOGGER.isTraceEnabled())
342 LOGGER.trace("PolicySet: " + policySet.getPolicySetId() + " Description: " + policySet.getDescription());
344 if (!policySet.getPolicySetOrPolicyOrPolicySetIdReference().isEmpty())
345 htmlOut.println("</ol>");
347 htmlOut.println("<p></p>");
349 return super.onPostVisitPolicySet(parent, policySet);
352 public void policySet(PolicySetType policySet, String htmlListElement) {
353 if (LOGGER.isTraceEnabled())
354 LOGGER.trace("PolicySet: " + policySet.getPolicySetId());
356 String combiningAlgorithm = "-";
358 String version = "-";
361 if (policySet.getPolicyCombiningAlgId() != null)
362 combiningAlgorithm = extractLastIdentifier(policySet.getPolicyCombiningAlgId(), ":");
364 if (policySet.getPolicySetId() != null)
365 id = extractLastIdentifier(policySet.getPolicySetId(), ":");
367 if (policySet.getVersion() != null)
368 version = policySet.getVersion();
371 htmlOut.println("<" + htmlListElement + "><b>Policy Set ID</b>: <i>" + id + "</i> (v" + version + ") " + "</"
372 + htmlListElement + ">");
374 if (policySet.getTarget() == null || policySet.getTarget().getAnyOf() == null
375 || policySet.getTarget().getAnyOf().isEmpty()) {
376 htmlOut.println("<p>This policy set applies to all requests.</p>");
378 htmlOut.print("<p>");
379 htmlOut.print("This policy set applies to requests with attributes ");
381 List<AnyOfType> anyOf_s = policySet.getTarget().getAnyOf();
383 htmlOut.println(".</p>");
386 if (policySet.getPolicySetOrPolicyOrPolicySetIdReference() != null
387 && !policySet.getPolicySetOrPolicyOrPolicySetIdReference().isEmpty()) {
388 String algoDesc = combiningAlgo2human.get(combiningAlgorithm);
389 if (algoDesc != null) {
390 algoDesc = algoDesc.replace("$placeholder$", "policy") + " (" + "<i>" + combiningAlgorithm + "</i>)";
392 algoDesc = combiningAlgorithm;
395 htmlOut.println("<p>The result is " + algoDesc + ": </p>");
400 public CallbackResult onPreVisitPolicy(PolicySetType parent, PolicyType policy) {
401 if (LOGGER.isTraceEnabled())
402 LOGGER.trace("PolicySet: " + policy.getPolicyId() + " Version: " + policy.getVersion());
404 if (parent != null && LOGGER.isTraceEnabled())
405 LOGGER.trace("PolicySet: " + policy.getPolicyId() + "Parent PolicySet: " + parent.getPolicySetId()
406 + " Version: " + parent.getVersion());
408 String description = policy.getDescription();
409 if (description != null && LOGGER.isTraceEnabled())
410 LOGGER.trace("PolicySet: " + policy.getPolicyId() + " Description: " + policy.getDescription());
414 if (!policy.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition().isEmpty())
415 htmlOut.println("<ol type=\"i\">");
417 return super.onPreVisitPolicy(parent, policy);
421 public CallbackResult onPostVisitPolicy(PolicySetType parent, PolicyType policy) {
422 if (LOGGER.isTraceEnabled())
423 LOGGER.trace("PolicySet: " + policy.getPolicyId() + " Version: " + policy.getVersion());
425 if (parent != null && LOGGER.isTraceEnabled())
426 LOGGER.trace("PolicySet: " + policy.getPolicyId() + "Parent PolicySet: " + parent.getPolicySetId()
427 + " Version: " + parent.getVersion());
429 if (!policy.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition().isEmpty())
430 htmlOut.println("</ol>");
432 htmlOut.println("<p></p>");
433 return super.onPostVisitPolicy(parent, policy);
436 public void policy(PolicyType policy) {
437 if (LOGGER.isTraceEnabled())
438 LOGGER.trace("Policy: " + policy.getPolicyId());
440 String combiningAlgorithm = "-";
442 String version = "-";
445 if (policy.getRuleCombiningAlgId() != null)
446 combiningAlgorithm = extractLastIdentifier(policy.getRuleCombiningAlgId(), ":");
448 if (policy.getPolicyId() != null)
449 id = extractLastIdentifier(policy.getPolicyId(), ":");
451 if (policy.getVersion() != null)
452 version = policy.getVersion();
454 htmlOut.println("<li><b>Policy ID</b>: <i>" + id + "</i> (v" + version + ") " + "</li>");
456 if (policy.getTarget() == null || policy.getTarget().getAnyOf() == null
457 || policy.getTarget().getAnyOf().isEmpty()) {
458 htmlOut.println("<p>This policy applies to all requests.</p>");
460 htmlOut.print("<p>");
461 htmlOut.print("This policy applies to requests with attributes ");
463 List<AnyOfType> anyOf_s = policy.getTarget().getAnyOf();
465 htmlOut.println(".</p>");
468 if (policy.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition() != null
469 && !policy.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition().isEmpty()) {
470 String algoDesc = combiningAlgo2human.get(combiningAlgorithm);
471 if (algoDesc != null) {
472 algoDesc = algoDesc.replace("$placeholder$", "rule") + " (<i>" + combiningAlgorithm + "</i>)";
474 algoDesc = combiningAlgorithm;
476 htmlOut.println("<p>The result is " + algoDesc + ": </p>");
482 public CallbackResult onPreVisitRule(PolicyType parent, RuleType rule) {
483 if (LOGGER.isTraceEnabled())
484 LOGGER.trace("Rule: " + rule.getRuleId());
486 if (parent != null && LOGGER.isTraceEnabled())
487 LOGGER.trace("Parent Policy: " + parent.getPolicyId() + " Version: " + parent.getVersion());
489 String description = rule.getDescription();
490 if (description != null && LOGGER.isTraceEnabled()) {
491 LOGGER.trace("Rule: " + rule.getRuleId() + " Description: " + rule.getDescription());
496 return super.onPreVisitRule(parent, rule);
500 public CallbackResult onPostVisitRule(PolicyType parent, RuleType rule) {
501 if (LOGGER.isTraceEnabled())
502 LOGGER.trace("Rule: " + rule.getRuleId());
504 if (parent != null && LOGGER.isTraceEnabled())
505 LOGGER.trace("Parent Policy: " + parent.getPolicyId() + " Version: " + parent.getVersion());
507 return super.onPostVisitRule(parent, rule);
510 public void rule(RuleType rule) {
511 if (LOGGER.isTraceEnabled())
512 LOGGER.trace("Rule: " + rule.getRuleId());
516 if (rule.getRuleId() != null)
517 id = extractLastIdentifier(rule.getRuleId(), ":");
519 htmlOut.println("<li><b>Rule ID</b>: <i>" + id + "</i></li>");
521 htmlOut.println("<dl>");
523 htmlOut.print("<p>");
524 htmlOut.print(rule.getEffect().value());
526 if (rule.getTarget() == null || rule.getTarget().getAnyOf() == null || rule.getTarget().getAnyOf().isEmpty()) {
527 htmlOut.print(" for all requests");
529 List<AnyOfType> anyOf_s = rule.getTarget().getAnyOf();
530 htmlOut.print(" for requests with attributes ");
534 if (rule.getCondition() != null) {
535 htmlOut.print(" when ");
536 htmlOut.println(this.stringifyCondition(rule.getCondition()) + " ");
538 htmlOut.print(" with no conditions ");
541 if (rule.getAdviceExpressions() != null) {
542 advice(rule.getAdviceExpressions());
543 if (rule.getObligationExpressions() != null)
544 htmlOut.println(" and ");
547 if (rule.getObligationExpressions() != null) {
548 obligation(rule.getObligationExpressions());
551 htmlOut.println("</p>");
554 private void advice(AdviceExpressionsType adviceExpressions) {
555 if (LOGGER.isTraceEnabled())
558 List<AdviceExpressionType> ae = adviceExpressions.getAdviceExpression();
559 for (AdviceExpressionType expression : ae) {
560 htmlOut.println(" with <b>advice</b> (<i>" + expression.getAdviceId() + "</i>) on <i>"
561 + expression.getAppliesTo().value() + "</i>:");
562 htmlOut.println("<ol type=\"a\">");
563 List<AttributeAssignmentExpressionType> assignments = expression.getAttributeAssignmentExpression();
564 if (assignments != null) {
565 processAttributeAssignments(assignments);
567 htmlOut.println("</ol>");
571 private void obligation(ObligationExpressionsType obligationExpressions) {
572 if (LOGGER.isTraceEnabled())
575 List<ObligationExpressionType> oe = obligationExpressions.getObligationExpression();
576 for (ObligationExpressionType expression : oe) {
577 htmlOut.println(" with <b>obligations</b> (<i>" + expression.getObligationId()
578 + "</i>) to be fullfilled on <i>" + expression.getFulfillOn().value() + "</i>:");
579 htmlOut.println("<ol type=\"a\">");
580 List<AttributeAssignmentExpressionType> assignments = expression.getAttributeAssignmentExpression();
581 if (assignments != null) {
582 processAttributeAssignments(assignments);
584 htmlOut.println("</ol>");
591 private void processAttributeAssignments(List<AttributeAssignmentExpressionType> assignments) {
592 if (LOGGER.isTraceEnabled())
595 for (AttributeAssignmentExpressionType assignment : assignments) {
596 String succintIdentifier = extractLastIdentifier(assignment.getCategory(), ":") + ":"
597 + extractLastIdentifier(assignment.getAttributeId(), ":");
598 AttributeIdentifiers attributeIdentifiers = null;
599 if (!this.attributeIdentifiersMap.containsKey(succintIdentifier)) {
600 // Note Attribute Assignments do not have an Attribute Type, assume string
601 // but note this case is unlikely since attributeMap should have been populated
602 // during parsing of target and conditions, and not in this case for Advice and
604 attributeIdentifiers =
605 new AttributeIdentifiers(assignment.getCategory(), "NA", assignment.getAttributeId());
606 this.attributeIdentifiersMap.put(succintIdentifier, attributeIdentifiers);
609 htmlOut.print("<li><i><a href=\"#" + succintIdentifier + "\">" + succintIdentifier + "</a></i> is ");
610 // AttributeValueType
611 JAXBElement<?> jaxbExp = assignment.getExpression();
612 Object assignmentObject = jaxbExp.getValue();
613 if (assignmentObject instanceof AttributeValueType) {
614 AttributeValueType avt = (AttributeValueType) assignmentObject;
615 if (attributeIdentifiers != null) {
616 attributeIdentifiers.setType(avt.getDataType());
618 int numContent = avt.getContent().size();
619 int countContent = 0;
620 for (Object c : avt.getContent()) {
622 htmlOut.print("<i>" + c + "</i>");
623 if (countContent < numContent)
624 htmlOut.print(" or ");
626 htmlOut.println("</li>");
627 } else if (assignmentObject instanceof AttributeDesignatorType
628 || assignmentObject instanceof AttributeSelectorType || assignmentObject instanceof ApplyType) {
629 htmlOut.println("NA");
631 htmlOut.println("Unexpected");
640 public void target(List<AnyOfType> anyOfList) {
641 if (LOGGER.isTraceEnabled())
644 if (anyOfList != null) {
645 Iterator<AnyOfType> iterAnyOf = anyOfList.iterator();
646 StringBuilder targetInHuman = new StringBuilder();
647 while (iterAnyOf.hasNext()) {
648 AnyOfType anyOf = iterAnyOf.next();
649 List<AllOfType> allOfList = anyOf.getAllOf();
650 if (allOfList != null) {
651 Iterator<AllOfType> iterAllOf = allOfList.iterator();
652 while (iterAllOf.hasNext()) {
653 AllOfType allOf = iterAllOf.next();
654 List<MatchType> matchList = allOf.getMatch();
655 if (matchList != null) {
656 Iterator<MatchType> iterMatch = matchList.iterator();
657 if (matchList.size() > 1)
658 targetInHuman.append("(");
659 while (iterMatch.hasNext()) {
660 MatchType match = iterMatch.next();
662 // Finally down to the actual attribute
664 StdAttribute attribute = null;
665 AttributeValueType value = match.getAttributeValue();
666 String attributeDataType;
667 if (match.getAttributeDesignator() != null && value != null) {
668 AttributeDesignatorType designator = match.getAttributeDesignator();
669 attribute = new StdAttribute(new IdentifierImpl(designator.getCategory()),
670 new IdentifierImpl(designator.getAttributeId()),
671 new StdAttributeValue<List<?>>(new IdentifierImpl(value.getDataType()),
673 designator.getIssuer(), false);
674 attributeDataType = designator.getDataType();
675 } else if (match.getAttributeSelector() != null && value != null) {
676 AttributeSelectorType selector = match.getAttributeSelector();
677 attribute = new StdAttribute(new IdentifierImpl(selector.getCategory()),
678 new IdentifierImpl(selector.getContextSelectorId()),
679 new StdAttributeValue<List<?>>(new IdentifierImpl(value.getDataType()),
682 attributeDataType = selector.getDataType();
684 LOGGER.warn("NULL designator/selector or value for match.");
685 attributeDataType = "NA";
688 String functionName = getHumanFunction(match.getMatchId());
689 if (attribute != null) {
690 String succintIdentifier = extractLastIdentifier(
691 attribute.getCategory().stringValue(), ":") + ":"
692 + extractLastIdentifier(attribute.getAttributeId().stringValue(), ":");
693 AttributeIdentifiers ai =
694 new AttributeIdentifiers(attribute.getCategory().stringValue(),
695 attributeDataType, attribute.getAttributeId().stringValue());
696 this.attributeIdentifiersMap.put(succintIdentifier, ai);
698 targetInHuman.append("<i><a href=\"#" + succintIdentifier + "\">"
699 + succintIdentifier + "</a></i> " + functionName + " ");
701 int numAttributes = attribute.getValues().size();
703 for (AttributeValue<?> v : attribute.getValues()) {
705 if (v.getValue() instanceof Collection<?>) {
706 Collection<?> value_s = (Collection<?>) v.getValue();
707 int numValues = value_s.size();
709 for (Object o : value_s) {
711 targetInHuman.append(" <I>" + o + "</I>");
712 if (countValues < numValues) {
713 targetInHuman.append(", or");
717 targetInHuman.append(" <I>" + v.getValue() + "</I>");
718 if (count < numAttributes) {
719 targetInHuman.append(", or ");
725 if (iterMatch.hasNext()) {
726 targetInHuman.append(" and ");
729 if (matchList.size() > 1) {
730 targetInHuman.append(")");
733 if (iterAllOf.hasNext()) {
734 targetInHuman.append(" or ");
738 if (iterAnyOf.hasNext()) {
739 targetInHuman = new StringBuilder();
740 targetInHuman.append("(" + targetInHuman + ")" + " or ");
742 if (anyOfList.size() > 1) {
743 targetInHuman.append(")");
747 htmlOut.println(targetInHuman);
751 private String getHumanFunction(String matchId) {
752 if (HtmlProcessor.function2human.containsKey(matchId)) {
753 return HtmlProcessor.function2human.get(matchId);
756 FunctionDefinition function = PolicyController.getFunctionIdMap().get(matchId);
757 String functionName = function.getShortname();
759 if (LOGGER.isDebugEnabled()) {
760 LOGGER.debug(functionName + ": #args[" + function.getArgLb() + "," + function.getArgUb() + "]");
763 return extractLastIdentifier(removePrimitives(functionName), ":");
766 public String html() {
767 this.htmlOut.flush();
768 return this.stringWriter.toString();
771 private String extractLastIdentifier(String in, String separator) {
772 int lastIndex = in.lastIndexOf(separator);
776 return in.substring(lastIndex + 1);
780 private String removePrimitives(String in) {
782 newIn = newIn.replace("string-", "");
783 newIn = newIn.replace("integer-", "");
784 newIn = newIn.replace("double-", "");
785 newIn = newIn.replace("boolean-", "");
789 private String stringifyCondition(ConditionType condition) {
790 if (condition.getExpression() == null) {
794 return stringifyExpression(condition.getExpression().getValue());
797 private String stringifyExpression(Object expression) {
798 if (expression instanceof ApplyType) {
799 ApplyType apply = (ApplyType) expression;
800 FunctionDefinition function = PolicyController.getFunctionIdMap().get(apply.getFunctionId());
801 String functionName = function.getShortname();
803 if (LOGGER.isDebugEnabled()) {
804 LOGGER.debug(functionName + ": #args[" + function.getArgLb() + "," + function.getArgUb() + "]");
807 if (functionName.contains("one-and-only")) {
808 if (LOGGER.isDebugEnabled()) {
809 LOGGER.debug("one-and-only found: " + functionName);
812 List<JAXBElement<?>> exps = apply.getExpression();
813 if (exps == null || exps.isEmpty()) {
816 StringBuilder forResult = new StringBuilder();
817 for (JAXBElement<?> e : exps) {
818 Object v = e.getValue();
819 if (LOGGER.isDebugEnabled()) {
820 LOGGER.debug("one-and-only children: " + v);
823 forResult.append(stringifyExpression(v));
826 return forResult.toString();
830 final int numExpr = (apply.getExpression() == null) ? -1 : apply.getExpression().size();
832 if (LOGGER.isDebugEnabled()) {
833 LOGGER.debug(functionName + " 0 expressions: " + numExpr);
836 } else if (numExpr == 1) {
838 if (LOGGER.isDebugEnabled()) {
839 LOGGER.debug(functionName + " 1 expression: " + numExpr);
841 StringBuilder applySubresult = new StringBuilder();
842 for (JAXBElement<?> e : apply.getExpression()) {
843 Object v = e.getValue();
845 applySubresult.append(this.stringifyExpression(e.getValue()));
848 return " " + removePrimitives(functionName) + " (" + applySubresult.toString() + ")";
851 if (LOGGER.isDebugEnabled()) {
852 LOGGER.debug(functionName + " > 1 expressions: " + numExpr);
854 StringBuilder applySubresult = new StringBuilder();
856 for (JAXBElement<?> e : apply.getExpression()) {
858 Object ev = e.getValue();
860 if (ev instanceof ApplyType) {
861 if (((ApplyType) ev).getFunctionId().contains("one-and-only")) {
862 applySubresult.append(this.stringifyExpression(e.getValue()));
864 applySubresult.append("(" + this.stringifyExpression(e.getValue()) + ")");
867 applySubresult.append(this.stringifyExpression(e.getValue()));
870 if (exprCount < numExpr) {
871 applySubresult.append(" " + removePrimitives(functionName) + " ");
875 return applySubresult.toString();
878 if (expression instanceof AttributeDesignatorType) {
879 AttributeDesignatorType adt = (AttributeDesignatorType) expression;
881 String succintIdentifier = extractLastIdentifier(adt.getCategory(), ":") + ":"
882 + extractLastIdentifier(adt.getAttributeId(), ":");
883 AttributeIdentifiers ai =
884 new AttributeIdentifiers(adt.getCategory(), adt.getDataType(), adt.getAttributeId());
885 this.attributeIdentifiersMap.put(succintIdentifier, ai);
887 return "<a href=\"#" + succintIdentifier + "\">" + succintIdentifier + "</a>";
889 if (expression instanceof AttributeSelectorType) {
890 AttributeSelectorType ast = (AttributeSelectorType) expression;
892 String attrName = ast.getPath();
893 if (attrName == null || (attrName.length() == 0)) {
897 String textSelector = "/text()";
898 if (attrName.endsWith(textSelector)) {
899 attrName = attrName.substring(0, attrName.length() - textSelector.length());
902 attrName = extractLastIdentifier(attrName, "/");
903 attrName = extractLastIdentifier(attrName, ":");
904 return " " + attrName;
906 if (expression instanceof AttributeValueType) {
907 AttributeValueType avt = (AttributeValueType) expression;
908 List<Object> content = avt.getContent();
909 StringBuilder value_s = new StringBuilder();
910 for (Object o : content) {
911 value_s.append(" " + o.toString());
913 return " " + value_s.toString();
915 if (expression instanceof VariableReferenceType) {
917 // Really unknown - the variable may or may not have been defined
919 return " VARIABLEREF-NOT-HANDLED";
921 throw new IllegalArgumentException("Unexpected input expression");
927 class AttributeIdentifiers {
928 public final String category;
930 public final String id;
932 public AttributeIdentifiers(String category, String type, String id) {
933 this.category = category;
938 public String getType() {
942 public void setType(String type) {