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.PrintWriter;
28 import java.io.StringWriter;
29 import java.nio.file.Path;
30 import java.nio.file.Paths;
31 import java.util.Collection;
32 import java.util.HashMap;
33 import java.util.Iterator;
34 import java.util.List;
37 import javax.xml.bind.JAXBElement;
39 import org.apache.commons.io.FilenameUtils;
40 import org.json.JSONObject;
41 import org.onap.policy.common.logging.flexlogger.FlexLogger;
42 import org.onap.policy.common.logging.flexlogger.Logger;
43 import org.onap.policy.controller.PolicyController;
44 import org.onap.policy.rest.jpa.FunctionDefinition;
45 import org.onap.policy.utils.XACMLPolicyWriterWithPapNotify;
46 import org.onap.policy.xacml.api.XACMLErrorConstants;
47 import org.onap.policy.xacml.util.XACMLPolicyScanner;
49 import com.att.research.xacml.api.AttributeValue;
50 import com.att.research.xacml.std.IdentifierImpl;
51 import com.att.research.xacml.std.StdAttribute;
52 import com.att.research.xacml.std.StdAttributeValue;
53 import com.att.research.xacml.util.XACMLPolicyScanner.CallbackResult;
54 import com.att.research.xacml.util.XACMLPolicyScanner.SimpleCallback;
56 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AdviceExpressionType;
57 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AdviceExpressionsType;
58 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AllOfType;
59 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AnyOfType;
60 import oasis.names.tc.xacml._3_0.core.schema.wd_17.ApplyType;
61 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeAssignmentExpressionType;
62 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeDesignatorType;
63 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeSelectorType;
64 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeValueType;
65 import oasis.names.tc.xacml._3_0.core.schema.wd_17.ConditionType;
66 import oasis.names.tc.xacml._3_0.core.schema.wd_17.MatchType;
67 import oasis.names.tc.xacml._3_0.core.schema.wd_17.ObligationExpressionType;
68 import oasis.names.tc.xacml._3_0.core.schema.wd_17.ObligationExpressionsType;
69 import oasis.names.tc.xacml._3_0.core.schema.wd_17.PolicySetType;
70 import oasis.names.tc.xacml._3_0.core.schema.wd_17.PolicyType;
71 import oasis.names.tc.xacml._3_0.core.schema.wd_17.RuleType;
72 import oasis.names.tc.xacml._3_0.core.schema.wd_17.VariableReferenceType;
76 public class HumanPolicyComponent{
78 private static final Logger LOGGER = FlexLogger.getLogger(HumanPolicyComponent.class);
80 // Constants Used in XML Creation
81 public static final String CATEGORY_RECIPIENT_SUBJECT = "urn:oasis:names:tc:xacml:1.0:subject-category:recipient-subject";
82 public static final String CATEGORY_RESOURCE = "urn:oasis:names:tc:xacml:3.0:attribute-category:resource";
83 public static final String CATEGORY_ACTION = "urn:oasis:names:tc:xacml:3.0:attribute-category:action";
84 public static final String CATEGORY_ACCESS_SUBJECT = "urn:oasis:names:tc:xacml:1.0:subject-category:access-subject";
85 public static final String ACTION_ID = "urn:oasis:names:tc:xacml:1.0:action:action-id";
86 public static final String SUBJECT_ID = "urn:oasis:names:tc:xacml:1.0:subject:subject-id";
87 public static final String RESOURCE_ID = "urn:oasis:names:tc:xacml:1.0:resource:resource-id";
88 public static final String FUNTION_INTEGER_ONE_AND_ONLY = "urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only";
89 public static final String FUNCTION_STRING_ONE_AND_ONLY = "urn:oasis:names:tc:xacml:1.0:function:string-one-and-only";
90 public static final String FUNCTION_STRING_EQUAL = "urn:oasis:names:tc:xacml:1.0:function:string-equal";
91 public static final String FUNCTION_STRING_REGEX_MATCH = "org.onap.function.regex-match";
92 public static final String FUNCTION_STRING_EQUAL_IGNORE = "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 = "";
100 private static HtmlProcessor htmlProcessor;
102 private static File policyFile;
104 private HumanPolicyComponent(){
105 //Default Constructor
108 public static JSONObject DescribePolicy(final File policyFile) {
109 if (LOGGER.isTraceEnabled())
110 LOGGER.trace("ENTER");
112 HumanPolicyComponent.policyFile = policyFile;
113 return humanPolicyLayout();
117 private static JSONObject humanPolicyLayout() {
118 if (LOGGER.isTraceEnabled())
119 LOGGER.trace("ENTER");
122 String html = processPolicy();
123 JSONObject result = new JSONObject();
124 result.put("html", html);
127 } catch (IllegalArgumentException e) {
128 LOGGER.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "cannot build html area por policy", e);
133 private static String processPolicy() {
134 if (LOGGER.isTraceEnabled()) {
135 LOGGER.trace("ENTER");
137 try (FileInputStream pIS = new FileInputStream(policyFile)){
138 Object policy = XACMLPolicyScanner.readPolicy(pIS);
140 throw new IllegalArgumentException("Policy File " + policyFile.getName() +
141 " cannot be unmarshalled");
143 HumanPolicyComponent.htmlProcessor =
144 new HtmlProcessor(HumanPolicyComponent.policyFile, policy);
146 Path policyPath = Paths.get(policyFile.getAbsolutePath());
147 XACMLPolicyScanner xacmlScanner = new XACMLPolicyScanner(policyPath, htmlProcessor);
149 String html = htmlProcessor.html();
150 if (LOGGER.isDebugEnabled())
151 LOGGER.debug(policyPath + System.lineSeparator() + html);
155 } catch (Exception e) {
156 String msg = "Exception reading policy: " + policyFile.getAbsolutePath() +
157 ": " + e.getMessage();
158 LOGGER.error(XACMLErrorConstants.ERROR_DATA_ISSUE + msg, e);
159 throw new IllegalArgumentException(msg);
165 class HtmlProcessor extends SimpleCallback {
167 private static final Logger LOGGER = FlexLogger.getLogger(HtmlProcessor.class);
169 private static Map<String, String> function2human;
171 function2human = new HashMap<>();
172 function2human.put(HumanPolicyComponent.FUNCTION_STRING_EQUAL, "equal");
173 function2human.put(HumanPolicyComponent.FUNCTION_STRING_EQUAL_IGNORE, "equal");
174 function2human.put(HumanPolicyComponent.FUNCTION_STRING_ONE_AND_ONLY, "one-and-only");
175 function2human.put(HumanPolicyComponent.FUNCTION_STRING_REGEX_MATCH, "matching regular expression");
176 function2human.put(HumanPolicyComponent.FUNTION_INTEGER_ONE_AND_ONLY, "one-and-only");
179 private static Map<String, String> combiningAlgo2human;
181 combiningAlgo2human = new HashMap<>();
182 combiningAlgo2human.put("deny-overrides", "to deny if any $placeholder$ below evaluates to <i>deny</i>");
183 combiningAlgo2human.put("permit-overrides", "to permit if any $placeholder$ below evaluates to <i>permit</i>");
185 combiningAlgo2human.put("ordered-deny-overrides", "to deny if any $placeholder$ below evaluates to <i>deny</i>");
186 combiningAlgo2human.put("ordered-permit-overrides", "to permit if any $placeholder$ below evaluates to <i>permit</i>");
187 combiningAlgo2human.put("deny-unless-permit", "to permit if any $placeholder$ below evaluates to <i>deny</i> and not <i>indeterminate</i>");
189 combiningAlgo2human.put("permit-unless-deny", "to deny if any $placeholder$ below evaluates to is <i>permit</i> and not <i>indeterminate</i>");
190 combiningAlgo2human.put("first-applicable", "to honour the result of the first successfully evaluated $placeholder$ in order");
191 combiningAlgo2human.put("only-one-applicable", "to honour the result of the first successfully evaluated $placeholder$ in order");
194 private Map<String, AttributeIdentifiers> attributeIdentifiersMap = new HashMap<>();
196 private final StringWriter stringWriter = new StringWriter();
197 private final PrintWriter htmlOut = new PrintWriter(stringWriter);
198 private final String policyName;
199 private final Object rootPolicyObject;
201 public HtmlProcessor(File policyFile, Object policyObject) {
202 if (LOGGER.isTraceEnabled())
203 LOGGER.trace("ENTER");
205 if (policyFile == null) {
206 LOGGER.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "Null Policy File");
207 throw new IllegalArgumentException("Null Policy File");
210 if (!policyFile.exists() || !policyFile.canRead()) {
211 String msg = "Can't access " + policyFile.getAbsolutePath();
212 LOGGER.error(XACMLErrorConstants.ERROR_PERMISSIONS + msg);
213 throw new IllegalArgumentException(msg);
216 if (policyObject == null ||
217 (!(policyObject instanceof PolicySetType) && !(policyObject instanceof PolicyType))) {
218 String msg = "Invalid unmarshalled object: " + policyObject;
219 LOGGER.error(XACMLErrorConstants.ERROR_SCHEMA_INVALID + msg);
220 throw new IllegalArgumentException(msg);
223 this.policyName = FilenameUtils.removeExtension(policyFile.getName());
224 this.rootPolicyObject = policyObject;
226 String version = "-";
227 if (policyObject instanceof PolicyType) {
228 PolicyType policy = (PolicyType) policyObject;
229 version = policy.getVersion();
230 htmlOut.println("<h1>Policy: " + policyName +
231 " (version " + version + ") </h1>");
234 PolicySetType policySet = (PolicySetType) policyObject;
235 version = policySet.getVersion();
236 htmlOut.println("<h1>Policy Set: " + policyName +
237 " (v" + version + ") </h1>");
240 htmlOut.println("<h3><b>Location: </b>" + policyFile.getPath() + "</h3>");
241 htmlOut.println("<hr>");
243 if (rootPolicyObject instanceof PolicySetType) {
244 if (policyName.startsWith("Config_")) {
245 htmlOut.println("<p>This is a <b>config</b> policy set.</p>");
246 } else if (policyName.startsWith("Action_")) {
247 htmlOut.println("<p>This is an <b>action</b> policy set.</p>");
249 htmlOut.println("<dl>");
251 if (policyName.startsWith("Config_")) {
252 htmlOut.println("<p>This is a <b>config</b> policy.</p>");
253 } else if (policyName.startsWith("Action_")) {
254 htmlOut.println("<p>This is an <b>action</b> policy.</p>");
256 htmlOut.println("<ol>");
261 * @return the attributeIdentifiersMap
263 public Map<String, AttributeIdentifiers> getAttributeIdentifiersMap() {
264 return attributeIdentifiersMap;
268 public void onFinishScan(Object root) {
269 if (LOGGER.isTraceEnabled())
270 LOGGER.trace("ENTER");
272 if (rootPolicyObject instanceof PolicySetType) {
273 htmlOut.println("</dl>");
275 htmlOut.println("</ol>");
278 htmlOut.println("<hr>");
280 htmlOut.println("<h3>Attribute Table:</h3>");
282 htmlOut.println("<table border=\"3\" style=\"width:100%\">");
283 htmlOut.println("<tr>");
284 htmlOut.print("<th>Category</th>");
285 htmlOut.print("<th>Type</th>");
286 htmlOut.print("<th>Identifier</th>");
287 htmlOut.println("</tr>");
288 for(Map.Entry<String, AttributeIdentifiers> entry : this.attributeIdentifiersMap.entrySet()){
289 AttributeIdentifiers value = entry.getValue();
290 htmlOut.println("<tr>");
291 htmlOut.print("<td><a name=\"" + entry.getKey() + "\"></a>" + value.category + "</td>");
292 htmlOut.print("<td>" + value.getType() + "</td>");
293 htmlOut.print("<td>" + value.id + "</td>");
294 htmlOut.println("</tr>");
296 htmlOut.println("</table>");
298 htmlOut.println("<p></p>");
300 // Not necessary for the user, uncomment if desired at some point
303 super.onFinishScan(root);
306 @SuppressWarnings("unused")
307 private void writeRawXACML() {
308 if (LOGGER.isTraceEnabled())
309 LOGGER.trace("ENTER");
311 htmlOut.println("<hr>");
312 htmlOut.println("<h3>Raw XACML:</h3>");
314 ByteArrayOutputStream bos = new ByteArrayOutputStream();
315 if (rootPolicyObject instanceof PolicySetType) {
316 XACMLPolicyWriterWithPapNotify.writePolicyFile(bos, (PolicySetType) rootPolicyObject);
317 } else if (rootPolicyObject instanceof PolicyType) {
318 XACMLPolicyWriterWithPapNotify.writePolicyFile(bos, (PolicyType) rootPolicyObject);
321 String xacml = bos.toString();
322 xacml = xacml.replaceAll("<", "<");
323 xacml = xacml.replaceAll(">", ">");
324 htmlOut.println("<pre>");
325 htmlOut.println(xacml);
326 htmlOut.println("</pre>");
330 public CallbackResult onPreVisitPolicySet(PolicySetType parent, PolicySetType policySet) {
331 if (LOGGER.isTraceEnabled())
332 LOGGER.trace("PolicySet: " + policySet.getPolicySetId() + " Version: " + policySet.getVersion());
334 if (parent != null && LOGGER.isTraceEnabled())
335 LOGGER.trace("PolicySet: " + policySet.getPolicySetId() +
336 "Parent PolicySet: " + parent.getPolicySetId() + " Version: " + parent.getVersion());
338 String description = policySet.getDescription();
339 if (description != null && LOGGER.isTraceEnabled())
340 LOGGER.trace("PolicySet: " + policySet.getPolicySetId() +
341 " Description: " + policySet.getDescription());
343 if (parent == null) // root
344 policySet(policySet, "dl");
346 policySet(policySet, "li");
348 if (!policySet.getPolicySetOrPolicyOrPolicySetIdReference().isEmpty())
349 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());
359 if (parent != null && LOGGER.isTraceEnabled())
360 LOGGER.trace("PolicySet: " + policySet.getPolicySetId() +
361 "Parent PolicySet: " + parent.getPolicySetId() + " Version: " + parent.getVersion());
363 String description = policySet.getDescription();
364 if (description != null && LOGGER.isTraceEnabled())
365 LOGGER.trace("PolicySet: " + policySet.getPolicySetId() +
366 " Description: " + policySet.getDescription());
368 if (!policySet.getPolicySetOrPolicyOrPolicySetIdReference().isEmpty())
369 htmlOut.println("</ol>");
371 htmlOut.println("<p></p>");
373 return super.onPostVisitPolicySet(parent, policySet);
376 public void policySet(PolicySetType policySet, String htmlListElement) {
377 if (LOGGER.isTraceEnabled())
378 LOGGER.trace("PolicySet: " + policySet.getPolicySetId());
380 String combiningAlgorithm = "-";
382 String version = "-";
385 if (policySet.getPolicyCombiningAlgId() != null)
386 combiningAlgorithm = extractLastIdentifier(policySet.getPolicyCombiningAlgId(), ":");
388 if (policySet.getPolicySetId() != null)
389 id = extractLastIdentifier(policySet.getPolicySetId(), ":");
391 if (policySet.getVersion() != null)
392 version = policySet.getVersion();
395 htmlOut.println("<" + htmlListElement + "><b>Policy Set ID</b>: <i>" + id +
396 "</i> (v" + version + ") " + "</" + htmlListElement + ">");
398 if (policySet.getTarget() == null ||
399 policySet.getTarget().getAnyOf() == null ||
400 policySet.getTarget().getAnyOf().isEmpty()) {
401 htmlOut.println("<p>This policy set applies to all requests.</p>");
403 htmlOut.print("<p>");
404 htmlOut.print("This policy set applies to requests with attributes ");
406 List<AnyOfType> anyOf_s = policySet.getTarget().getAnyOf();
408 htmlOut.println(".</p>");
411 if (policySet.getPolicySetOrPolicyOrPolicySetIdReference() != null &&
412 !policySet.getPolicySetOrPolicyOrPolicySetIdReference().isEmpty()) {
413 String algoDesc = combiningAlgo2human.get(combiningAlgorithm);
414 if (algoDesc != null) {
415 algoDesc = algoDesc.replace("$placeholder$", "policy") + " (" + "<i>" + combiningAlgorithm + "</i>)";
417 algoDesc = combiningAlgorithm;
420 htmlOut.println("<p>The result is " + algoDesc + ": </p>");
425 public CallbackResult onPreVisitPolicy(PolicySetType parent, PolicyType policy) {
426 if (LOGGER.isTraceEnabled())
427 LOGGER.trace("PolicySet: " + policy.getPolicyId() + " Version: " + policy.getVersion());
429 if (parent != null && LOGGER.isTraceEnabled())
430 LOGGER.trace("PolicySet: " + policy.getPolicyId() +
431 "Parent PolicySet: " + parent.getPolicySetId() + " Version: " + parent.getVersion());
433 String description = policy.getDescription();
434 if (description != null && LOGGER.isTraceEnabled())
435 LOGGER.trace("PolicySet: " + policy.getPolicyId() +
436 " Description: " + policy.getDescription());
440 if (!policy.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition().isEmpty())
441 htmlOut.println("<ol type=\"i\">");
443 return super.onPreVisitPolicy(parent, policy);
447 public CallbackResult onPostVisitPolicy(PolicySetType parent, PolicyType policy) {
448 if (LOGGER.isTraceEnabled())
449 LOGGER.trace("PolicySet: " + policy.getPolicyId() + " Version: " + policy.getVersion());
451 if (parent != null && LOGGER.isTraceEnabled())
452 LOGGER.trace("PolicySet: " + policy.getPolicyId() +
453 "Parent PolicySet: " + parent.getPolicySetId() + " Version: " + parent.getVersion());
455 if (!policy.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition().isEmpty())
456 htmlOut.println("</ol>");
458 htmlOut.println("<p></p>");
459 return super.onPostVisitPolicy(parent, policy);
462 public void policy(PolicyType policy) {
463 if (LOGGER.isTraceEnabled())
464 LOGGER.trace("Policy: " + policy.getPolicyId());
466 String combiningAlgorithm = "-";
468 String version = "-";
471 if (policy.getRuleCombiningAlgId() != null)
472 combiningAlgorithm = extractLastIdentifier(policy.getRuleCombiningAlgId(), ":");
474 if (policy.getPolicyId() != null)
475 id = extractLastIdentifier(policy.getPolicyId(), ":");
477 if (policy.getVersion() != null)
478 version = policy.getVersion();
480 htmlOut.println("<li><b>Policy ID</b>: <i>" + id +
481 "</i> (v" + version + ") " + "</li>");
483 if (policy.getTarget() == null ||
484 policy.getTarget().getAnyOf() == null ||
485 policy.getTarget().getAnyOf().isEmpty()) {
486 htmlOut.println("<p>This policy applies to all requests.</p>");
488 htmlOut.print("<p>");
489 htmlOut.print("This policy applies to requests with attributes ");
491 List<AnyOfType> anyOf_s = policy.getTarget().getAnyOf();
493 htmlOut.println(".</p>");
496 if (policy.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition() != null &&
497 !policy.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition().isEmpty()) {
498 String algoDesc = combiningAlgo2human.get(combiningAlgorithm);
499 if (algoDesc != null) {
500 algoDesc = algoDesc.replace("$placeholder$", "rule") + " (<i>" + combiningAlgorithm + "</i>)";
502 algoDesc = combiningAlgorithm;
504 htmlOut.println("<p>The result is " + algoDesc + ": </p>");
510 public CallbackResult onPreVisitRule(PolicyType parent, RuleType rule) {
511 if (LOGGER.isTraceEnabled())
512 LOGGER.trace("Rule: " + rule.getRuleId());
514 if (parent != null && LOGGER.isTraceEnabled())
515 LOGGER.trace("Parent Policy: " + parent.getPolicyId() + " Version: " + parent.getVersion());
517 String description = rule.getDescription();
518 if (description != null && LOGGER.isTraceEnabled()) {
519 LOGGER.trace("Rule: " + rule.getRuleId() +
520 " Description: " + rule.getDescription());
525 return super.onPreVisitRule(parent, rule);
529 public CallbackResult onPostVisitRule(PolicyType parent, RuleType rule) {
530 if (LOGGER.isTraceEnabled())
531 LOGGER.trace("Rule: " + rule.getRuleId());
533 if (parent != null && LOGGER.isTraceEnabled())
534 LOGGER.trace("Parent Policy: " + parent.getPolicyId() + " Version: " + parent.getVersion());
536 return super.onPostVisitRule(parent, rule);
539 public void rule(RuleType rule) {
540 if (LOGGER.isTraceEnabled())
541 LOGGER.trace("Rule: " + rule.getRuleId());
545 if (rule.getRuleId() != null)
546 id = extractLastIdentifier(rule.getRuleId(), ":");
548 htmlOut.println("<li><b>Rule ID</b>: <i>" + id + "</i></li>");
550 htmlOut.println("<dl>");
552 htmlOut.print("<p>");
553 htmlOut.print(rule.getEffect().value());
555 if (rule.getTarget() == null ||
556 rule.getTarget().getAnyOf() == null ||
557 rule.getTarget().getAnyOf().isEmpty()) {
558 htmlOut.print(" for all requests");
560 List<AnyOfType> anyOf_s = rule.getTarget().getAnyOf();
561 htmlOut.print(" for requests with attributes ");
565 if (rule.getCondition() != null) {
566 htmlOut.print(" when ");
567 htmlOut.println(this.stringifyCondition(rule.getCondition()) + " ");
569 htmlOut.print(" with no conditions ");
572 if (rule.getAdviceExpressions() != null) {
573 advice(rule.getAdviceExpressions());
574 if (rule.getObligationExpressions() != null)
575 htmlOut.println(" and ");
578 if (rule.getObligationExpressions() != null) {
579 obligation(rule.getObligationExpressions());
582 htmlOut.println("</p>");
585 private void advice(AdviceExpressionsType adviceExpressions) {
586 if (LOGGER.isTraceEnabled())
587 LOGGER.trace("ENTER");
589 List<AdviceExpressionType> ae = adviceExpressions.getAdviceExpression();
590 for (AdviceExpressionType expression : ae) {
591 htmlOut.println(" with <b>advice</b> (<i>" + expression.getAdviceId() + "</i>) on <i>" +
592 expression.getAppliesTo().value() + "</i>:" );
593 htmlOut.println("<ol type=\"a\">");
594 List<AttributeAssignmentExpressionType> assignments = expression.getAttributeAssignmentExpression();
595 if (assignments != null) {
596 processAttributeAssignments(assignments);
598 htmlOut.println("</ol>");
602 private void obligation(ObligationExpressionsType obligationExpressions) {
603 if (LOGGER.isTraceEnabled())
604 LOGGER.trace("ENTER");
606 List<ObligationExpressionType> oe = obligationExpressions.getObligationExpression();
607 for (ObligationExpressionType expression : oe) {
608 htmlOut.println(" with <b>obligations</b> (<i>" + expression.getObligationId() + "</i>) to be fullfilled on <i>" +
609 expression.getFulfillOn().value() + "</i>:" );
610 htmlOut.println("<ol type=\"a\">");
611 List<AttributeAssignmentExpressionType> assignments = expression.getAttributeAssignmentExpression();
612 if (assignments != null) {
613 processAttributeAssignments(assignments);
615 htmlOut.println("</ol>");
622 private void processAttributeAssignments(List<AttributeAssignmentExpressionType> assignments) {
623 if (LOGGER.isTraceEnabled())
624 LOGGER.trace("ENTER");
626 for (AttributeAssignmentExpressionType assignment : assignments) {
627 String succintIdentifier = extractLastIdentifier(assignment.getCategory(), ":") +
628 ":" + extractLastIdentifier(assignment.getAttributeId(), ":");
629 AttributeIdentifiers attributeIdentifiers = null;
630 if (!this.attributeIdentifiersMap.containsKey(succintIdentifier)) {
631 // Note Attribute Assignments do not have an Attribute Type, assume string
632 // but note this case is unlikely since attributeMap should have been populated
633 // during parsing of target and conditions, and not in this case for Advice and
635 attributeIdentifiers = new AttributeIdentifiers(assignment.getCategory(),
637 assignment.getAttributeId());
638 this.attributeIdentifiersMap.put(succintIdentifier, attributeIdentifiers);
641 htmlOut.print("<li><i><a href=\"#" + succintIdentifier + "\">" + succintIdentifier + "</a></i> is ");
642 // AttributeValueType
643 JAXBElement<?> jaxbExp = assignment.getExpression();
644 Object assignmentObject = jaxbExp.getValue();
645 if (assignmentObject instanceof AttributeValueType) {
646 AttributeValueType avt = (AttributeValueType) assignmentObject;
647 if (attributeIdentifiers != null) {
648 attributeIdentifiers.setType(avt.getDataType());
650 int numContent = avt.getContent().size();
651 int countContent = 0;
652 for (Object c: avt.getContent()) {
654 htmlOut.print("<i>" + c + "</i>");
655 if (countContent < numContent)
656 htmlOut.print(" or ");
658 htmlOut.println("</li>");
659 } else if (assignmentObject instanceof AttributeDesignatorType) {
660 htmlOut.println("NA");
661 } else if (assignmentObject instanceof AttributeSelectorType) {
662 htmlOut.println("NA");
663 } else if (assignmentObject instanceof ApplyType) {
664 htmlOut.println("NA");
666 htmlOut.println("Unexpected");
675 public void target(List<AnyOfType> anyOfList) {
676 if (LOGGER.isTraceEnabled())
677 LOGGER.trace("ENTER");
679 if (anyOfList != null) {
680 Iterator<AnyOfType> iterAnyOf = anyOfList.iterator();
681 StringBuilder targetInHuman = new StringBuilder();
682 while (iterAnyOf.hasNext()) {
683 AnyOfType anyOf = iterAnyOf.next();
684 List<AllOfType> allOfList = anyOf.getAllOf();
685 if (allOfList != null) {
686 Iterator<AllOfType> iterAllOf = allOfList.iterator();
687 while (iterAllOf.hasNext()) {
688 AllOfType allOf = iterAllOf.next();
689 List<MatchType> matchList = allOf.getMatch();
690 if (matchList != null) {
691 Iterator<MatchType> iterMatch = matchList.iterator();
692 if (matchList.size() > 1)
693 targetInHuman.append("(");
694 while (iterMatch.hasNext()) {
695 MatchType match = iterMatch.next();
697 // Finally down to the actual attribute
699 StdAttribute attribute = null;
700 AttributeValueType value = match.getAttributeValue();
701 String attributeDataType;
702 if (match.getAttributeDesignator() != null && value != null) {
703 AttributeDesignatorType designator = match.getAttributeDesignator();
704 attribute = new StdAttribute(new IdentifierImpl(designator.getCategory()),
705 new IdentifierImpl(designator.getAttributeId()),
706 new StdAttributeValue<List<?>>(new IdentifierImpl(value.getDataType()), value.getContent()),
707 designator.getIssuer(),
709 attributeDataType = designator.getDataType();
710 } else if (match.getAttributeSelector() != null && value != null) {
711 AttributeSelectorType selector = match.getAttributeSelector();
712 attribute = new StdAttribute(new IdentifierImpl(selector.getCategory()),
713 new IdentifierImpl(selector.getContextSelectorId()),
714 new StdAttributeValue<List<?>>(new IdentifierImpl(value.getDataType()), value.getContent()),
717 attributeDataType = selector.getDataType();
719 LOGGER.warn("NULL designator/selector or value for match.");
720 attributeDataType = "NA";
723 String functionName = getHumanFunction(match.getMatchId());
724 if(attribute != null){
725 String succintIdentifier = extractLastIdentifier(attribute.getCategory().stringValue(), ":") +
726 ":" + extractLastIdentifier(attribute.getAttributeId().stringValue(), ":");
727 AttributeIdentifiers ai = new AttributeIdentifiers(attribute.getCategory().stringValue(),
729 attribute.getAttributeId().stringValue());
730 this.attributeIdentifiersMap.put(succintIdentifier,ai);
732 targetInHuman.append("<i><a href=\"#" + succintIdentifier + "\">" + succintIdentifier + "</a></i> " + functionName + " ");
734 int numAttributes = attribute.getValues().size();
736 for (AttributeValue<?> v: attribute.getValues()) {
738 if (v.getValue() instanceof Collection<?>) {
739 Collection<?> value_s = (Collection<?>) v.getValue();
740 int numValues = value_s.size();
742 for (Object o : value_s) {
744 targetInHuman.append(" <I>" + o + "</I>");
745 if (countValues < numValues) {
746 targetInHuman.append(", or");
750 targetInHuman.append(" <I>" + v.getValue() + "</I>");
751 if (count < numAttributes) {
752 targetInHuman.append(", or ");
758 if (iterMatch.hasNext()) {
759 targetInHuman.append(" and ");
762 if (matchList.size() > 1) {
763 targetInHuman.append(")");
766 if (iterAllOf.hasNext()) {
767 targetInHuman.append(" or ");
771 if (iterAnyOf.hasNext()) {
772 targetInHuman = new StringBuilder();
773 targetInHuman.append("(" + targetInHuman + ")" + " or ");
775 if (anyOfList.size() > 1) {
776 targetInHuman.append(")");
780 htmlOut.println(targetInHuman);
784 private String getHumanFunction(String matchId) {
785 if (HtmlProcessor.function2human.containsKey(matchId)) {
786 return HtmlProcessor.function2human.get(matchId);
789 FunctionDefinition function = PolicyController.getFunctionIDMap().get(matchId);
790 String functionName = function.getShortname();
792 if (LOGGER.isDebugEnabled()) {
793 LOGGER.debug(functionName +
794 ": #args[" + function.getArgLb() + "," + function.getArgUb() +"]");
797 return extractLastIdentifier(removePrimitives(functionName), ":");
800 public String html() {
801 this.htmlOut.flush();
802 return this.stringWriter.toString();
805 private String extractLastIdentifier(String in, String separator) {
806 int lastIndex = in.lastIndexOf(separator);
810 return in.substring(lastIndex+1);
813 private String removePrimitives(String in) {
815 newIn = newIn.replace("string-", "");
816 newIn = newIn.replace("integer-", "");
817 newIn = newIn.replace("double-", "");
818 newIn = newIn.replace("boolean-", "");
822 private String stringifyCondition(ConditionType condition) {
823 if (condition.getExpression() == null) {
827 return stringifyExpression(condition.getExpression().getValue());
830 private String stringifyExpression(Object expression) {
831 if (expression instanceof ApplyType) {
832 ApplyType apply = (ApplyType) expression;
833 FunctionDefinition function = PolicyController.getFunctionIDMap().get(apply.getFunctionId());
834 String functionName = function.getShortname();
836 if (LOGGER.isDebugEnabled()) {
837 LOGGER.debug(functionName +
838 ": #args[" + function.getArgLb() + "," + function.getArgUb() +"]");
841 if (functionName.contains("one-and-only")) {
842 if (LOGGER.isDebugEnabled()) {
843 LOGGER.debug("one-and-only found: " + functionName);
846 List<JAXBElement<?>> exps = apply.getExpression();
847 if (exps == null || exps.isEmpty())
850 StringBuilder forResult = new StringBuilder();
851 for (JAXBElement<?> e : exps) {
852 Object v = e.getValue();
853 if (LOGGER.isDebugEnabled()) {
854 LOGGER.debug("one-and-only children: " + v);
857 forResult.append(stringifyExpression(v));
860 return forResult.toString();
864 final int numExpr = (apply.getExpression() == null) ? -1 : apply.getExpression().size();
866 if (LOGGER.isDebugEnabled()) {
867 LOGGER.debug(functionName + " 0 expressions: " + numExpr);
870 } else if (numExpr == 1) {
872 if (LOGGER.isDebugEnabled()) {
873 LOGGER.debug(functionName + " 1 expression: " + numExpr);
875 StringBuilder applySubresult = new StringBuilder();
876 for (JAXBElement<?> e : apply.getExpression()) {
877 Object v = e.getValue();
879 applySubresult.append(this.stringifyExpression(e.getValue()));
882 return " " + removePrimitives(functionName) + " (" + applySubresult.toString() + ")";
885 if (LOGGER.isDebugEnabled()) {
886 LOGGER.debug(functionName + " > 1 expressions: " + numExpr);
888 StringBuilder applySubresult = new StringBuilder();
890 for (JAXBElement<?> e : apply.getExpression()) {
892 Object ev = e.getValue();
894 if (ev instanceof ApplyType) {
895 if (((ApplyType) ev).getFunctionId().contains("one-and-only")) {
896 applySubresult.append(this.stringifyExpression(e.getValue()));
898 applySubresult.append("(" + this.stringifyExpression(e.getValue()) + ")");
901 applySubresult.append(this.stringifyExpression(e.getValue()));
904 if (exprCount < numExpr) {
905 applySubresult.append(" " + removePrimitives(functionName) + " ");
909 return applySubresult.toString();
912 if (expression instanceof AttributeDesignatorType) {
913 AttributeDesignatorType adt = (AttributeDesignatorType) expression;
915 String succintIdentifier = extractLastIdentifier(adt.getCategory(), ":") +
916 ":" + extractLastIdentifier(adt.getAttributeId(), ":");
917 AttributeIdentifiers ai = new AttributeIdentifiers(adt.getCategory(),
919 adt.getAttributeId());
920 this.attributeIdentifiersMap.put(succintIdentifier,ai);
922 return "<a href=\"#" + succintIdentifier + "\">" + succintIdentifier + "</a>";
924 if (expression instanceof AttributeSelectorType) {
925 AttributeSelectorType ast = (AttributeSelectorType) expression;
927 String attrName = ast.getPath();
928 if (attrName == null || (attrName.length() == 0)) {
932 String textSelector = "/text()";
933 if (attrName.endsWith(textSelector)) {
934 attrName = attrName.substring(0, attrName.length() - textSelector.length());
937 attrName = extractLastIdentifier(attrName, "/");
938 attrName = extractLastIdentifier(attrName, ":");
939 return " " + attrName;
941 if (expression instanceof AttributeValueType) {
942 AttributeValueType avt = (AttributeValueType) expression;
943 List<Object> content = avt.getContent();
944 StringBuilder value_s = new StringBuilder();
945 for (Object o: content) {
946 value_s.append(" " + o.toString());
948 return " " + value_s.toString();
950 if (expression instanceof VariableReferenceType) {
952 // Really unknown - the variable may or may not have been defined
954 return " VARIABLEREF-NOT-HANDLED";
956 throw new IllegalArgumentException("Unexpected input expression");
962 class AttributeIdentifiers {
963 public final String category;
965 public final String id;
967 public AttributeIdentifiers(String category, String type, String id) {
968 this.category = category;
973 public String getType() {
977 public void setType(String type) {