Coverage Report - org.openpermis.policy.io.xml.PermisXmlWriter
 
Classes in this File Line Coverage Branch Coverage Complexity
PermisXmlWriter
91%
288/316
82%
117/142
4.522
PermisXmlWriter$1
100%
2/2
N/A
4.522
 
 1  
 /*
 2  
  * Copyright (c) 2009, Swiss Federal Department of Defence Civil Protection and Sport
 3  
  *                     (http://www.vbs.admin.ch)
 4  
  * Copyright (c) 2009, Ergon Informatik AG (http://www.ergon.ch)
 5  
  * All rights reserved.
 6  
  *
 7  
  * Licensed under the Open Permis License which accompanies this distribution,
 8  
  * and is available at http://www.openpermis.org/BSDlicenceKent.txt
 9  
  */
 10  
 package org.openpermis.policy.io.xml;
 11  
 
 12  
 import static org.openpermis.policy.io.xml.PermisXmlTags.ABSOLUTE_PERIOD_ELEMENT;
 13  
 import static org.openpermis.policy.io.xml.PermisXmlTags.ACTION_POLICY_ELEMENT;
 14  
 import static org.openpermis.policy.io.xml.PermisXmlTags.ACTION_REF_ELEMENT;
 15  
 import static org.openpermis.policy.io.xml.PermisXmlTags.ACTION_SPEC_ELEMENT;
 16  
 import static org.openpermis.policy.io.xml.PermisXmlTags.AND_ELEMENT;
 17  
 import static org.openpermis.policy.io.xml.PermisXmlTags.ARGUMENT_REF_ELEMENT;
 18  
 import static org.openpermis.policy.io.xml.PermisXmlTags.ARGUMENT_SPEC_ELEMENT;
 19  
 import static org.openpermis.policy.io.xml.PermisXmlTags.BOOLEAN_TYPE;
 20  
 import static org.openpermis.policy.io.xml.PermisXmlTags.CONSTANT_ELEMENT;
 21  
 import static org.openpermis.policy.io.xml.PermisXmlTags.CURRENT_TIME_ELEMENT;
 22  
 import static org.openpermis.policy.io.xml.PermisXmlTags.DELEGATE_ELEMENT;
 23  
 import static org.openpermis.policy.io.xml.PermisXmlTags.DEPTH_ATTRIBUTE;
 24  
 import static org.openpermis.policy.io.xml.PermisXmlTags.DOUBLE_TYPE;
 25  
 import static org.openpermis.policy.io.xml.PermisXmlTags.DURATION_TYPE;
 26  
 import static org.openpermis.policy.io.xml.PermisXmlTags.END_ATTRIBUTE;
 27  
 import static org.openpermis.policy.io.xml.PermisXmlTags.EQUAL_ELEMENT;
 28  
 import static org.openpermis.policy.io.xml.PermisXmlTags.GREATER_EQUAL_ELEMENT;
 29  
 import static org.openpermis.policy.io.xml.PermisXmlTags.GREATER_THAN_ELEMENT;
 30  
 import static org.openpermis.policy.io.xml.PermisXmlTags.ID_ATTRIBUTE;
 31  
 import static org.openpermis.policy.io.xml.PermisXmlTags.IF_ELEMENT;
 32  
 import static org.openpermis.policy.io.xml.PermisXmlTags.INCLUDE_ELEMENT;
 33  
 import static org.openpermis.policy.io.xml.PermisXmlTags.INTEGER_TYPE;
 34  
 import static org.openpermis.policy.io.xml.PermisXmlTags.LDAPDN_ATTRIBUTE;
 35  
 import static org.openpermis.policy.io.xml.PermisXmlTags.LESS_EQUAL_ELEMENT;
 36  
 import static org.openpermis.policy.io.xml.PermisXmlTags.LESS_THAN_ELEMENT;
 37  
 import static org.openpermis.policy.io.xml.PermisXmlTags.MAXIMUM_VALID_UP_TO_ELEMENT;
 38  
 import static org.openpermis.policy.io.xml.PermisXmlTags.MINIMUM_VALID_FROM_ELEMENT;
 39  
 import static org.openpermis.policy.io.xml.PermisXmlTags.MINIMUM_VALID_UP_TO_ELEMENT;
 40  
 import static org.openpermis.policy.io.xml.PermisXmlTags.NAME_ATTRIBUTE;
 41  
 import static org.openpermis.policy.io.xml.PermisXmlTags.NON_NULL_INTERSECTION_ELEMENT;
 42  
 import static org.openpermis.policy.io.xml.PermisXmlTags.NOT_ELEMENT;
 43  
 import static org.openpermis.policy.io.xml.PermisXmlTags.OR_ELEMENT;
 44  
 import static org.openpermis.policy.io.xml.PermisXmlTags.PERMIS_POLICY_ELEMENT;
 45  
 import static org.openpermis.policy.io.xml.PermisXmlTags.PRESENT_ELEMENT;
 46  
 import static org.openpermis.policy.io.xml.PermisXmlTags.RESOURCE_DOMAIN_POLICY_ELEMENT;
 47  
 import static org.openpermis.policy.io.xml.PermisXmlTags.RESOURCE_DOMAIN_REF_ELEMENT;
 48  
 import static org.openpermis.policy.io.xml.PermisXmlTags.RESOURCE_DOMAIN_SPEC_ELEMENT;
 49  
 import static org.openpermis.policy.io.xml.PermisXmlTags.ROLE_ASSIGNMENT_POLICY_ELEMENT;
 50  
 import static org.openpermis.policy.io.xml.PermisXmlTags.ROLE_ASSIGNMENT_RULE_ELEMENT;
 51  
 import static org.openpermis.policy.io.xml.PermisXmlTags.ROLE_ELEMENT;
 52  
 import static org.openpermis.policy.io.xml.PermisXmlTags.ROLE_HIERARCHY_ELEMENT;
 53  
 import static org.openpermis.policy.io.xml.PermisXmlTags.ROLE_HIERARCHY_POLICY_ELEMENT;
 54  
 import static org.openpermis.policy.io.xml.PermisXmlTags.ROLE_LIST_ELEMENT;
 55  
 import static org.openpermis.policy.io.xml.PermisXmlTags.SET_ELEMENT;
 56  
 import static org.openpermis.policy.io.xml.PermisXmlTags.SOA_ELEMENT;
 57  
 import static org.openpermis.policy.io.xml.PermisXmlTags.SOA_SPEC_ELEMENT;
 58  
 import static org.openpermis.policy.io.xml.PermisXmlTags.START_ATTRIBUTE;
 59  
 import static org.openpermis.policy.io.xml.PermisXmlTags.STRING_TYPE;
 60  
 import static org.openpermis.policy.io.xml.PermisXmlTags.SUBJECT_DOMAIN_POLICY_ELEMENT;
 61  
 import static org.openpermis.policy.io.xml.PermisXmlTags.SUBJECT_DOMAIN_REF_ELEMENT;
 62  
 import static org.openpermis.policy.io.xml.PermisXmlTags.SUBJECT_DOMAIN_SPEC_ELEMENT;
 63  
 import static org.openpermis.policy.io.xml.PermisXmlTags.SUBSET_ELEMENT;
 64  
 import static org.openpermis.policy.io.xml.PermisXmlTags.SUBSTRING_OF_ELEMENT;
 65  
 import static org.openpermis.policy.io.xml.PermisXmlTags.SUB_ROLE_ELEMENT;
 66  
 import static org.openpermis.policy.io.xml.PermisXmlTags.SUPERSET_ELEMENT;
 67  
 import static org.openpermis.policy.io.xml.PermisXmlTags.SUPER_ROLE_ELEMENT;
 68  
 import static org.openpermis.policy.io.xml.PermisXmlTags.TARGET_ACCESS_POLICY_ELEMENT;
 69  
 import static org.openpermis.policy.io.xml.PermisXmlTags.TARGET_ACCESS_RULE_ELEMENT;
 70  
 import static org.openpermis.policy.io.xml.PermisXmlTags.TARGET_LIST_ELEMENT;
 71  
 import static org.openpermis.policy.io.xml.PermisXmlTags.TARGET_POLICY_ELEMENT;
 72  
 import static org.openpermis.policy.io.xml.PermisXmlTags.TARGET_REF_ELEMENT;
 73  
 import static org.openpermis.policy.io.xml.PermisXmlTags.TARGET_SPEC_ELEMENT;
 74  
 import static org.openpermis.policy.io.xml.PermisXmlTags.TIME_TYPE;
 75  
 import static org.openpermis.policy.io.xml.PermisXmlTags.TIME_ZONE_ATTRIBUTE;
 76  
 import static org.openpermis.policy.io.xml.PermisXmlTags.TYPE_ATTRIBUTE;
 77  
 import static org.openpermis.policy.io.xml.PermisXmlTags.VALIDITY_ELEMENT;
 78  
 import static org.openpermis.policy.io.xml.PermisXmlTags.VALUE_ATTRIBUTE;
 79  
 import static org.openpermis.policy.io.xml.PermisXmlTags.OBLIGATION_POLICY_ELEMENT;
 80  
 import static org.openpermis.policy.io.xml.PermisXmlTags.OBLIGATION_LIST_ELEMENT;
 81  
 import static org.openpermis.policy.io.xml.PermisXmlTags.OBLIGATION_REF_ELEMENT;
 82  
 import static org.openpermis.policy.io.xml.PermisXmlTags.OBLIGATION_SPEC_ELEMENT;
 83  
 import static org.openpermis.policy.io.xml.PermisXmlTags.TEXT_ATTRIBUTE;
 84  
 
 85  
 import java.io.IOException;
 86  
 import java.io.Writer;
 87  
 import java.net.URI;
 88  
 import java.util.HashMap;
 89  
 import java.util.List;
 90  
 import java.util.Map;
 91  
 
 92  
 import org.joda.time.DateTime;
 93  
 
 94  
 import com.generationjava.io.xml.PrettyPrinterXmlWriter;
 95  
 import com.generationjava.io.xml.SimpleXmlWriter;
 96  
 import com.generationjava.io.xml.XmlWriter;
 97  
 
 98  
 import org.openpermis.basic.AbsoluteTimePeriod;
 99  
 import org.openpermis.basic.TimePeriodConstraint;
 100  
 import org.openpermis.policy.Obligation;
 101  
 import org.openpermis.policy.ParameterList;
 102  
 import org.openpermis.policy.Predicate;
 103  
 import org.openpermis.policy.Role;
 104  
 import org.openpermis.policy.ParameterList.Parameter;
 105  
 import org.openpermis.policy.bean.ActionBean;
 106  
 import org.openpermis.policy.bean.DomainBean;
 107  
 import org.openpermis.policy.bean.PolicyBean;
 108  
 import org.openpermis.policy.bean.RoleAssignmentRuleBean;
 109  
 import org.openpermis.policy.bean.RoleAssignmentRuleBeanCollection;
 110  
 import org.openpermis.policy.bean.RoleHierarchyBean;
 111  
 import org.openpermis.policy.bean.RoleHierarchyBeanCollection;
 112  
 import org.openpermis.policy.bean.TargetAccessRuleBean;
 113  
 import org.openpermis.policy.bean.TargetAccessRuleBeanCollection;
 114  
 import org.openpermis.policy.bean.TargetBean;
 115  
 import org.openpermis.policy.io.PolicyException;
 116  
 import org.openpermis.policy.io.PolicyWriter;
 117  
 import org.openpermis.policy.predicate.AbstractPredicate;
 118  
 import org.openpermis.policy.predicate.And;
 119  
 import org.openpermis.policy.predicate.Argument;
 120  
 import org.openpermis.policy.predicate.Constant;
 121  
 import org.openpermis.policy.predicate.CurrentTime;
 122  
 import org.openpermis.policy.predicate.Not;
 123  
 import org.openpermis.policy.predicate.Or;
 124  
 import org.openpermis.policy.predicate.Present;
 125  
 import org.openpermis.policy.predicate.SubstringOf;
 126  
 import org.openpermis.policy.predicate.TimeConstant;
 127  
 import org.openpermis.policy.predicate.Value;
 128  
 import org.openpermis.policy.predicate.ValueRelationalPredicate;
 129  
 import org.openpermis.policy.predicate.ValueSet;
 130  
 import org.openpermis.policy.predicate.ValueSetRelationalPredicate;
 131  
 
 132  
 
 133  
 /**
 134  
  * Policy writer implementation for Permis XML policies.
 135  
  * @since 0.1.0
 136  
  */
 137  
 public final class PermisXmlWriter
 138  
         implements PolicyWriter
 139  
 {
 140  
 
 141  
         //---- Static
 142  
 
 143  
         /**
 144  
          * The default output encoding written to the XML file.
 145  
          */
 146  
         private static final String DEFAULT_ENCODING = "UTF-8";
 147  
 
 148  
         /**
 149  
          * The DOCTYPE of Permis XML files.
 150  
          */
 151  
         private static final String PERMIS_DOCTYPE = "<!DOCTYPE " + PERMIS_POLICY_ELEMENT + ">\n";
 152  
 
 153  
         //---- State
 154  
 
 155  
         /**
 156  
          * The underlying writer used by this policy writer.
 157  
          */
 158  
         private final Writer writer;
 159  
 
 160  
         /**
 161  
          * The output encoding to write.
 162  
          */
 163  
         private final String encoding;
 164  
 
 165  
         /**
 166  
          * The id counter.
 167  
          */
 168  11
         private int id = 0;
 169  
 
 170  
 
 171  
         //---- Constructors
 172  
 
 173  
         /**
 174  
          * Creates a new policy writer that uses the specified writer.
 175  
          * @note Uses the default XML encoding {@code UTF-8}.
 176  
          * @param writer the writer to write the policy to.
 177  
          * @since 0.1.0
 178  
          */
 179  
         public PermisXmlWriter (Writer writer) {
 180  11
                 this(writer, DEFAULT_ENCODING);
 181  11
         }
 182  
 
 183  
         /**
 184  
          * Creates a new policy writer that uses the specified writer and output encoding.
 185  
          * @param writer the writer to write the policy to.
 186  
          * @param encoding the encoding to write to the generated XML output.
 187  
          * @since 0.1.0
 188  
          */
 189  11
         public PermisXmlWriter (Writer writer, String encoding) {
 190  11
                 this.writer = writer;
 191  11
                 this.encoding = encoding;
 192  11
         }
 193  
 
 194  
         //---- Methods
 195  
 
 196  
         /**
 197  
          * @since 0.1.0
 198  
          */
 199  
         protected Map<String, String> buildSubjectDomainIdMap (
 200  
                 RoleAssignmentRuleBeanCollection roleAssignmentRules
 201  
         ) {
 202  11
                 final Map<String, String> subjectDomainMap = new HashMap<String, String>();
 203  11
                 for (RoleAssignmentRuleBean rule : roleAssignmentRules) {
 204  5
                         final String subjectDomainUri = rule.getSubjectDomain().getIdentity().toString();
 205  5
                         final String subjectDomainId = "SubjectDomain_" + this.id++;
 206  5
                         if (!subjectDomainMap.containsKey(subjectDomainUri)) {
 207  5
                                 subjectDomainMap.put(subjectDomainUri, subjectDomainId);
 208  
                         }
 209  5
                 }
 210  11
                 return subjectDomainMap;
 211  
         }
 212  
 
 213  
         /**
 214  
          * @since 0.1.0
 215  
          */
 216  
         protected Map<String, String> buildSoaIdMap (
 217  
                 RoleAssignmentRuleBeanCollection roleAssignmentRules
 218  
         ) {
 219  11
                 final Map<String, String> soaIdMap = new HashMap<String, String>();
 220  11
                 for (RoleAssignmentRuleBean rule : roleAssignmentRules) {
 221  5
                         final String soaUri        = rule.getAuthority().getIdentity().toString();
 222  5
                         final String soaID = "Soa_" + this.id++;
 223  5
                         if (!soaIdMap.containsKey(soaUri)) {
 224  5
                                 soaIdMap.put(soaUri, soaID);
 225  
                         }
 226  5
                 }
 227  11
                 return soaIdMap;
 228  
         }
 229  
 
 230  
         /**
 231  
          * @since 0.3.0
 232  
          */
 233  
         protected Map<String, String> buildDomainIdMap (
 234  
                 TargetAccessRuleBeanCollection targetAccessRules
 235  
         ) {
 236  11
                 final Map<String, String> domainIdMap = new HashMap<String, String>();
 237  11
                 for (TargetAccessRuleBean rule : targetAccessRules) {
 238  14
                         for (TargetBean target : rule.getTargets()) {
 239  13
                                 DomainBean domain = target.getResourceDomain();
 240  13
                                 if (domain != null) {
 241  10
                                         URI uri = domain.getIdentity();
 242  10
                                         if (uri != null) {
 243  10
                                                 final String targetDomainUri =
 244  
                                                 uri.toString();
 245  10
                                                 final String targetDomainID = "Domain_" + this.id++;
 246  10
                                                 if (!domainIdMap.containsKey(targetDomainUri)) {
 247  5
                                                         domainIdMap.put(targetDomainUri, targetDomainID);
 248  
                                                 }
 249  
                                         }
 250  
                                 }
 251  13
                         }
 252  
                 }
 253  11
                 return domainIdMap;
 254  
         }
 255  
 
 256  
         /**
 257  
          * @since 0.3.0
 258  
          */
 259  
         protected Map<Obligation, String> buildObligationIdMap (
 260  
                 TargetAccessRuleBeanCollection targetAccessRules
 261  
         ) {
 262  11
                 final Map<Obligation, String> obligationIdMap = new HashMap<Obligation, String>();
 263  11
                 for (TargetAccessRuleBean rule : targetAccessRules) {
 264  14
                         for (Obligation obligation : rule.getObligations()) {
 265  
 
 266  3
                                 final String obligationID = "Obligation_" + this.id++;
 267  3
                                 if (!obligationIdMap.containsKey(obligation)) {
 268  2
                                         obligationIdMap.put(obligation, obligationID);
 269  
                                 }
 270  3
                         }
 271  
                 }
 272  11
                 return obligationIdMap;
 273  
         }
 274  
         
 275  
         /**
 276  
          * @since 0.3.0
 277  
          */
 278  
         protected Map<ActionBean, String> buildActionIdMap (
 279  
                 TargetAccessRuleBeanCollection targetAccessRules
 280  
         ) {
 281  11
                 final Map<ActionBean, String> result = new HashMap<ActionBean, String>();
 282  11
                 for (TargetAccessRuleBean rule : targetAccessRules) {
 283  14
                         for (TargetBean target : rule.getTargets()) {
 284  13
                                 for (ActionBean action : target.getActions()) {
 285  11
                                         result.put(action, action.getName() + "_" + this.id++);
 286  
                                 }
 287  
                         }
 288  
                 }
 289  11
                 return result;
 290  
         }
 291  
 
 292  
         /**
 293  
          * @since 0.3.0
 294  
          */
 295  
         protected Map<TargetBean, String> buildTargetIdMap (
 296  
                 TargetAccessRuleBeanCollection targetAccessRules
 297  
         ) {
 298  11
                 final Map<TargetBean, String> result = new HashMap<TargetBean, String>();
 299  11
                 for (TargetAccessRuleBean rule : targetAccessRules) {
 300  14
                         for (TargetBean target : rule.getTargets()) {
 301  13
                                 result.put(target, "Target_" + "_" + this.id++);
 302  
                         }
 303  
                 }
 304  11
                 return result;
 305  
         }
 306  
 
 307  
         /**
 308  
          * @since 0.3.0
 309  
          */
 310  
         protected Map<RoleHierarchyBean, String> buildHierachyIdMap (
 311  
                 RoleHierarchyBeanCollection roleHierarchies
 312  
         ) {
 313  11
                 final Map<RoleHierarchyBean, String> result = new HashMap<RoleHierarchyBean, String>();
 314  11
                 for (RoleHierarchyBean hierarchy : roleHierarchies) {
 315  7
                         result.put(hierarchy, "RoleHierarchy_" + "_" + this.id++);
 316  
                 }
 317  11
                 return result;
 318  
         }
 319  
 
 320  
         /**
 321  
          * @since 0.1.0
 322  
          */
 323  
         protected void writeSubjectPolicy (
 324  
                 RoleAssignmentRuleBeanCollection roleAssignmentRules,
 325  
                 Map<String, String> subjectDomainIdMap,
 326  
                 XmlWriter xmlWriter
 327  
         )
 328  
                 throws IOException
 329  
         {
 330  11
                 xmlWriter.writeEntity(SUBJECT_DOMAIN_POLICY_ELEMENT);
 331  
 
 332  11
                 for (RoleAssignmentRuleBean rule : roleAssignmentRules) {
 333  5
                         final String subjectDomainUri = rule.getSubjectDomain().getIdentity().toString();
 334  5
                         final String subjectDomainId = subjectDomainIdMap.get(subjectDomainUri);
 335  
 
 336  5
                         xmlWriter.writeEntity(SUBJECT_DOMAIN_SPEC_ELEMENT).
 337  
                                 writeAttribute(ID_ATTRIBUTE, subjectDomainId);
 338  5
                         xmlWriter.writeEntity(INCLUDE_ELEMENT).
 339  
                                 writeAttribute(LDAPDN_ATTRIBUTE, subjectDomainUri).
 340  
                                 endEntity();
 341  5
                         xmlWriter.endEntity();
 342  5
                 }
 343  
 
 344  11
                 xmlWriter.endEntity();
 345  11
         }
 346  
 
 347  
         /**
 348  
          * @since 0.1.0
 349  
          */
 350  
         protected void writeRoleHierarchyPolicy (
 351  
                 Map<RoleHierarchyBean, String> hierarchyIdMap,
 352  
                 XmlWriter xmlWriter
 353  
         )
 354  
                 throws IOException
 355  
         {
 356  11
                 xmlWriter.writeEntity(ROLE_HIERARCHY_POLICY_ELEMENT);
 357  11
                 for (Map.Entry<RoleHierarchyBean, String> entry : hierarchyIdMap.entrySet()) {
 358  7
                         final RoleHierarchyBean hierarchy = entry.getKey();
 359  7
                         xmlWriter.writeEntity(ROLE_HIERARCHY_ELEMENT).
 360  
                                 writeAttribute(ID_ATTRIBUTE, entry.getValue()).
 361  
                                 writeAttribute(TYPE_ATTRIBUTE, hierarchy.getIdentity());
 362  7
                         for (String role : hierarchy.getRoles()) {
 363  11
                                 xmlWriter.writeEntity(SUPER_ROLE_ELEMENT).
 364  
                                         writeAttribute(VALUE_ATTRIBUTE, role);
 365  11
                                 for (String subRole : hierarchy.getChildRoles(role)) {
 366  1
                                         xmlWriter.writeEntity(SUB_ROLE_ELEMENT).
 367  
                                                 writeAttribute(VALUE_ATTRIBUTE, subRole).
 368  
                                                 endEntity();
 369  
                                 }
 370  11
                                 xmlWriter.endEntity();
 371  
                         }
 372  7
                         xmlWriter.endEntity();
 373  7
                 }
 374  11
                 xmlWriter.endEntity();
 375  11
         }
 376  
 
 377  
         /**
 378  
          * @since 0.1.0
 379  
          */
 380  
         protected void writeSoaPolicy (
 381  
                 RoleAssignmentRuleBeanCollection roleAssignmentRules,
 382  
                 Map<String, String> soaIdMap,
 383  
                 XmlWriter xmlWriter
 384  
         )
 385  
                 throws IOException
 386  
         {
 387  11
                 xmlWriter.writeEntity(PermisXmlTags.SOA_POLICY_ELEMENT);
 388  11
                 for (Map.Entry<String, String> entry : soaIdMap.entrySet()) {
 389  5
                         xmlWriter.writeEntity(SOA_SPEC_ELEMENT).
 390  
                                 writeAttribute(ID_ATTRIBUTE, entry.getValue()).
 391  
                                 writeAttribute(LDAPDN_ATTRIBUTE, entry.getKey()).
 392  
                                 endEntity();
 393  
                 }
 394  11
                 xmlWriter.endEntity();
 395  11
         }
 396  
 
 397  
         /**
 398  
          * @since 0.1.0
 399  
          */
 400  
         protected void writeRoleAssignmentPolicy (
 401  
                 final RoleAssignmentRuleBeanCollection roleAssignmentRules,
 402  
                 final Map<String, String> subjectDomainIdsMap,
 403  
                 final Map<String, String> soaIdMap,
 404  
                 final Map<RoleHierarchyBean, String> hierarchyIdMap,
 405  
                 XmlWriter xmlWriter
 406  
         )
 407  
                 throws IOException
 408  
         {
 409  11
                 xmlWriter.writeEntity(ROLE_ASSIGNMENT_POLICY_ELEMENT);
 410  
 
 411  11
                 for (RoleAssignmentRuleBean rule : roleAssignmentRules) {
 412  5
                         xmlWriter.writeEntity(ROLE_ASSIGNMENT_RULE_ELEMENT);
 413  
 
 414  5
                         final String subjectDomainId =
 415  
                                 subjectDomainIdsMap.get(rule.getSubjectDomain().getIdentity().toString());
 416  5
                         xmlWriter.writeEntity(SUBJECT_DOMAIN_REF_ELEMENT).
 417  
                                 writeAttribute(ID_ATTRIBUTE, subjectDomainId).endEntity();
 418  
 
 419  5
                         xmlWriter.writeEntity(ROLE_LIST_ELEMENT);
 420  5
                         for (Role role : rule.getRoles()) {
 421  10
                                 xmlWriter.writeEntity(ROLE_ELEMENT).
 422  
                                         writeAttribute(ID_ATTRIBUTE, hierarchyIdMap.get(role.getRoleHierarchy())).
 423  
                                         writeAttribute(VALUE_ATTRIBUTE, role.getName()).
 424  
                                         endEntity();
 425  
                         }
 426  5
                         xmlWriter.endEntity();
 427  
 
 428  5
                         xmlWriter.writeEntity(DELEGATE_ELEMENT).
 429  
                                 writeAttribute(DEPTH_ATTRIBUTE, Integer.valueOf(rule.getDelegationDepth()))
 430  
                                         .endEntity();
 431  
 
 432  5
                         final String soaId = soaIdMap.get(rule.getAuthority().getIdentity().toString());
 433  5
                         xmlWriter.writeEntity(SOA_ELEMENT).
 434  
                                 writeAttribute(ID_ATTRIBUTE, soaId).
 435  
                                 endEntity();
 436  
 
 437  5
                         writeValidity(rule.getConstraint(), xmlWriter);
 438  
 
 439  5
                         xmlWriter.endEntity();
 440  5
                 }
 441  
 
 442  11
                 xmlWriter.endEntity();
 443  11
         }
 444  
 
 445  
         /**
 446  
          * @since 0.3.0
 447  
          */
 448  
         protected void writeDomainPolicy (Map<String, String> targetDomainIDMap, XmlWriter xmlWriter)
 449  
                 throws IOException
 450  
         {
 451  11
                 xmlWriter.writeEntity(RESOURCE_DOMAIN_POLICY_ELEMENT);
 452  
 
 453  11
                 for (Map.Entry<String, String> entry : targetDomainIDMap.entrySet()) {
 454  5
                         xmlWriter.writeEntity(RESOURCE_DOMAIN_SPEC_ELEMENT).
 455  
                                 writeAttribute(ID_ATTRIBUTE, entry.getValue());
 456  5
                         xmlWriter.writeEntity(INCLUDE_ELEMENT).
 457  
                                 writeAttribute(LDAPDN_ATTRIBUTE, entry.getKey()).endEntity();
 458  5
                         xmlWriter.endEntity();
 459  
                 }
 460  11
                 xmlWriter.endEntity();
 461  11
         }
 462  
 
 463  
         /**
 464  
          * @since 0.3.0
 465  
          */
 466  
         protected void writeActionPolicy (Map<ActionBean, String> actionIdMap, XmlWriter xmlWriter)
 467  
                 throws IOException
 468  
         {
 469  11
                 xmlWriter.writeEntity(ACTION_POLICY_ELEMENT);
 470  11
                 for (Map.Entry<ActionBean, String> entry : actionIdMap.entrySet()) {
 471  11
                         xmlWriter.writeEntity(ACTION_SPEC_ELEMENT).
 472  
                                 writeAttribute(ID_ATTRIBUTE, entry.getValue()).
 473  
                                 writeAttribute(NAME_ATTRIBUTE, entry.getKey().getName());
 474  
 
 475  11
                         final ParameterList parameters = entry.getKey().getParameters();
 476  11
                         for (Parameter parameter : parameters) {
 477  
                                 final String type;
 478  8
                                 if (DateTime.class.equals(parameter.getType())) {
 479  0
                                         type = TIME_TYPE;
 480  
                                 } else {
 481  8
                                         type = parameter.getType().getSimpleName();
 482  
                                 }
 483  8
                                 xmlWriter.writeEntity(ARGUMENT_SPEC_ELEMENT).
 484  
                                         writeAttribute(NAME_ATTRIBUTE, parameter.getName()).
 485  
                                         writeAttribute(TYPE_ATTRIBUTE, type).
 486  
                                         endEntity();
 487  8
                         }
 488  11
                         xmlWriter.endEntity();
 489  11
                 }
 490  11
                 xmlWriter.endEntity();
 491  11
         }
 492  
         
 493  
         /**
 494  
          * @since 0.3.0
 495  
          */
 496  
         protected void writeObligationPolicy (
 497  
                 Map<Obligation, String> obligationIdMap, XmlWriter xmlWriter
 498  
         )        
 499  
                 throws IOException
 500  
         {
 501  11
                 xmlWriter.writeEntity(OBLIGATION_POLICY_ELEMENT);
 502  11
                 for (Map.Entry<Obligation, String> entry : obligationIdMap.entrySet()) {
 503  2
                         xmlWriter.writeEntity(OBLIGATION_SPEC_ELEMENT).
 504  
                                 writeAttribute(ID_ATTRIBUTE, entry.getValue()).
 505  
                                 writeAttribute(TEXT_ATTRIBUTE, entry.getKey().getText()).
 506  
                         endEntity();
 507  
                 }
 508  11
                 xmlWriter.endEntity();
 509  11
         }
 510  
 
 511  
         /**
 512  
          * @since 0.3.0
 513  
          */
 514  
         protected void writeTargetPolicy (
 515  
                 Map<String, String> domainIdMap,
 516  
                 Map<ActionBean, String> actionIdMap,
 517  
                 Map<TargetBean, String> targetIdMap,
 518  
                 XmlWriter xmlWriter
 519  
         )
 520  
                 throws IOException
 521  
         {
 522  11
                 xmlWriter.writeEntity(TARGET_POLICY_ELEMENT);
 523  11
                 for (Map.Entry<TargetBean, String> entry : targetIdMap.entrySet()) {
 524  13
                         xmlWriter.writeEntity(TARGET_SPEC_ELEMENT).
 525  
                                 writeAttribute(ID_ATTRIBUTE, entry.getValue());
 526  13
                         DomainBean domain = entry.getKey().getResourceDomain();
 527  13
                         if (domain != null) {
 528  10
                                 URI uri = domain.getIdentity();
 529  10
                                 if (uri != null) {
 530  10
                                         final String domainId =
 531  
                                                 domain.getIdentity().toString();
 532  10
                                         xmlWriter.writeEntity(RESOURCE_DOMAIN_REF_ELEMENT).
 533  
                                         writeAttribute(ID_ATTRIBUTE, domainIdMap.get(domainId)).
 534  
                                         endEntity();
 535  
                                 }
 536  
                         }
 537  13
                         for (ActionBean action : entry.getKey().getActions()) {
 538  11
                                 xmlWriter.writeEntity(ACTION_REF_ELEMENT).
 539  
                                         writeAttribute(ID_ATTRIBUTE, actionIdMap.get(action)).
 540  
                                         endEntity();
 541  
                         }
 542  13
                         xmlWriter.endEntity();
 543  13
                 }
 544  11
                 xmlWriter.endEntity();
 545  11
         }
 546  
 
 547  
         /**
 548  
          * @since 0.1.0
 549  
          */
 550  
         protected void writeTargetAccessPolicy (
 551  
                 TargetAccessRuleBeanCollection targetAccessRules,
 552  
                 Map<String, String> targetDomainIDMap,
 553  
                 Map<ActionBean, String> actionIdMap,
 554  
                 Map<TargetBean, String> targetIdMap,
 555  
                 Map<RoleHierarchyBean, String> hierarchyIdMap,
 556  
                 Map<Obligation, String> obligationIdMap,
 557  
                 XmlWriter xmlWriter
 558  
         )
 559  
                 throws IOException
 560  
         {
 561  11
                 xmlWriter.writeEntity(TARGET_ACCESS_POLICY_ELEMENT);
 562  
 
 563  11
                 for (TargetAccessRuleBean rule : targetAccessRules) {
 564  14
                         xmlWriter.writeEntity(TARGET_ACCESS_RULE_ELEMENT);
 565  14
                         xmlWriter.writeEntity(ROLE_LIST_ELEMENT);
 566  14
                         for (Role role : rule.getRoles()) {
 567  10
                                 xmlWriter.writeEntity(ROLE_ELEMENT).
 568  
                                         writeAttribute(ID_ATTRIBUTE, hierarchyIdMap.get(role.getRoleHierarchy())).
 569  
                                         writeAttribute(VALUE_ATTRIBUTE, role.getName()).
 570  
                                         endEntity();
 571  
                         }
 572  14
                         xmlWriter.endEntity();
 573  
 
 574  14
                         xmlWriter.writeEntity(TARGET_LIST_ELEMENT);
 575  14
                         for (TargetBean target : rule.getTargets()) {
 576  13
                                 xmlWriter.writeEntity(TARGET_REF_ELEMENT).
 577  
                                 writeAttribute(ID_ATTRIBUTE, targetIdMap.get(target)).
 578  
                                 endEntity();
 579  
                         }
 580  14
                         xmlWriter.endEntity();
 581  
 
 582  14
                         if (rule.getCondition() instanceof AbstractPredicate) {
 583  2
                                 xmlWriter.writeEntity(IF_ELEMENT);
 584  2
                                 writeCondition(rule.getCondition(), xmlWriter);
 585  2
                                 xmlWriter.endEntity();
 586  
                         }
 587  
                         
 588  14
                         if (rule.getObligations().toList().size() > 0) {
 589  2
                                 xmlWriter.writeEntity(OBLIGATION_LIST_ELEMENT);
 590  2
                                 for (Obligation obligation : rule.getObligations()) {
 591  3
                                         xmlWriter.writeEntity(OBLIGATION_REF_ELEMENT).
 592  
                                                 writeAttribute(ID_ATTRIBUTE, obligationIdMap.get(obligation)).
 593  
                                         endEntity();
 594  
                                 }
 595  2
                                 xmlWriter.endEntity();
 596  
                         }
 597  14
                         xmlWriter.endEntity();
 598  
                 }
 599  11
                 xmlWriter.endEntity();
 600  11
         }
 601  
 
 602  
         /**
 603  
          * @since 0.3.0
 604  
          */
 605  
         protected void writeValidity (TimePeriodConstraint validity, XmlWriter xmlWriter)
 606  
                 throws IOException
 607  
         {
 608  5
                 if (validity.equals(TimePeriodConstraint.UNCONSTRAINED)) {
 609  4
                         xmlWriter.writeEmptyEntity(VALIDITY_ELEMENT);
 610  
                 } else {
 611  1
                         xmlWriter.writeEntity(VALIDITY_ELEMENT);
 612  1
                         if (validity.getAbsolutePeriod() instanceof AbsoluteTimePeriod) {
 613  1
                                 final AbsoluteTimePeriod period = (AbsoluteTimePeriod) validity.getAbsolutePeriod();
 614  1
                                 xmlWriter.writeEntity(ABSOLUTE_PERIOD_ELEMENT).
 615  
                                         writeAttribute(START_ATTRIBUTE, period.getStart()).
 616  
                                         writeAttribute(END_ATTRIBUTE, period.getEnd()).
 617  
                                 endEntity();
 618  
                         }
 619  1
                         if (validity.getMinimumValidFrom() != null) {
 620  1
                                 xmlWriter.writeEntity(MINIMUM_VALID_FROM_ELEMENT).
 621  
                                         writeAttribute(
 622  
                                                 DURATION_TYPE,
 623  
                                                 TimeUtility.toString(validity.getMinimumValidFrom())
 624  
                                         )
 625  
                                 .endEntity();
 626  
                         }
 627  1
                         if (validity.getMaximumValidUpTo() != null) {
 628  1
                                 xmlWriter.writeEntity(MAXIMUM_VALID_UP_TO_ELEMENT).
 629  
                                         writeAttribute(
 630  
                                                 DURATION_TYPE,
 631  
                                                 TimeUtility.toString(validity.getMaximumValidUpTo())
 632  
                                         )
 633  
                                 .endEntity();
 634  
                         }
 635  1
                         if (validity.getMinimumValidUpTo() != null) {
 636  1
                                 xmlWriter.writeEntity(MINIMUM_VALID_UP_TO_ELEMENT).
 637  
                                         writeAttribute(
 638  
                                                 DURATION_TYPE,
 639  
                                                 TimeUtility.toString(validity.getMinimumValidUpTo())
 640  
                                         )
 641  
                                 .endEntity();
 642  
                         }
 643  1
                         xmlWriter.endEntity();
 644  
                 }
 645  
 
 646  5
         }
 647  
 
 648  
         /**
 649  
          * @since 0.1.0
 650  
          */
 651  
         public void writeCondition (Predicate condition, XmlWriter xmlWriter) throws IOException {
 652  
 
 653  16
                 if (condition instanceof And) {
 654  2
                         final And and = (And) condition;
 655  2
                         xmlWriter.writeEntity(AND_ELEMENT);
 656  2
                         for (Predicate predicate : and.getOperands()) {
 657  11
                                 writeCondition(predicate, xmlWriter);
 658  
                         }
 659  2
                         xmlWriter.endEntity();
 660  
 
 661  2
                 } else if (condition instanceof Or) {
 662  1
                         final Or or = (Or) condition;
 663  1
                         xmlWriter.writeEntity(OR_ELEMENT);
 664  1
                         for (Predicate predicate : or.getOperands()) {
 665  3
                                 writeCondition(predicate, xmlWriter);
 666  
                         }
 667  1
                         xmlWriter.endEntity();
 668  
 
 669  1
                 } else if (condition instanceof Not) {
 670  0
                         final Not not = (Not) condition;
 671  0
                         xmlWriter.writeEntity(NOT_ELEMENT);
 672  0
                         for (Predicate predicate : not.getOperands()) {
 673  0
                                 writeCondition(predicate, xmlWriter);
 674  
                         }
 675  0
                         xmlWriter.endEntity();
 676  
 
 677  0
                 } else if (condition instanceof Present) {
 678  1
                         final Present gt = (Present) condition;
 679  1
                         xmlWriter.writeEntity(PRESENT_ELEMENT);
 680  1
                         writeValues(gt.getOperands(), xmlWriter);
 681  1
                         xmlWriter.endEntity();
 682  
 
 683  1
                 } else if (condition instanceof ValueRelationalPredicate) {
 684  9
                         final ValueRelationalPredicate operation = (ValueRelationalPredicate) condition;
 685  
 
 686  1
                         switch (operation.getRelation()) {
 687  
                                 case Equal:
 688  1
                                         xmlWriter.writeEntity(EQUAL_ELEMENT);
 689  1
                                         writeValues(operation.getOperands(), xmlWriter);
 690  1
                                         break;
 691  
                                 case GreaterEqual:
 692  3
                                         xmlWriter.writeEntity(GREATER_EQUAL_ELEMENT);
 693  3
                                         writeValues(operation.getOperands(), xmlWriter);
 694  3
                                         break;
 695  
                                 case GreaterThan:
 696  3
                                         xmlWriter.writeEntity(GREATER_THAN_ELEMENT);
 697  3
                                         writeValues(operation.getOperands(), xmlWriter);
 698  3
                                         break;
 699  
                                 case LessThan:
 700  1
                                         xmlWriter.writeEntity(LESS_THAN_ELEMENT);
 701  1
                                         writeValues(operation.getOperands(), xmlWriter);
 702  1
                                         break;
 703  
                                 case LessEqual:
 704  1
                                         xmlWriter.writeEntity(LESS_EQUAL_ELEMENT);
 705  1
                                         writeValues(operation.getOperands(), xmlWriter);
 706  1
                                         break;
 707  
                                 default:
 708  0
                                         throw new IllegalStateException("Never.");
 709  
                         }
 710  9
                         xmlWriter.endEntity();
 711  
 
 712  9
                 } else if (condition instanceof ValueSetRelationalPredicate) {
 713  3
                         final ValueSetRelationalPredicate operation = (ValueSetRelationalPredicate) condition;
 714  
 
 715  1
                         switch (operation.getRelation()) {
 716  
                                 case Subset:
 717  1
                                         xmlWriter.writeEntity(SUBSET_ELEMENT);
 718  1
                                         writeValueSets(operation.getOperands(), xmlWriter);
 719  1
                                         break;
 720  
                                 case Superset:
 721  1
                                         xmlWriter.writeEntity(SUPERSET_ELEMENT);
 722  1
                                         writeValueSets(operation.getOperands(), xmlWriter);
 723  1
                                         break;
 724  
                                 case NonNullIntersection:
 725  1
                                         xmlWriter.writeEntity(NON_NULL_INTERSECTION_ELEMENT);
 726  1
                                         writeValueSets(operation.getOperands(), xmlWriter);
 727  1
                                         break;
 728  
                                 default:
 729  0
                                         throw new IllegalStateException("Never.");
 730  
                         }
 731  3
                         xmlWriter.endEntity();
 732  
 
 733  3
                 } else if (condition instanceof SubstringOf) {
 734  0
                         final SubstringOf substringOf = (SubstringOf) condition;
 735  0
                         xmlWriter.writeEntity(SUBSTRING_OF_ELEMENT);
 736  0
                         writeValues(substringOf.getOperands(), xmlWriter);
 737  0
                         xmlWriter.endEntity();
 738  0
                 } else {
 739  0
                         throw new IllegalStateException("Not yet implemented.");
 740  
                 }
 741  16
         }
 742  
 
 743  
         /**
 744  
          * @since 0.3.0
 745  
          */
 746  
         private void writeValueSets (List<ValueSet> valuesets, XmlWriter xmlWriter) throws IOException {
 747  3
                 for (ValueSet valueset : valuesets) {
 748  6
                         xmlWriter.writeEntity(SET_ELEMENT);
 749  6
                         writeValues(valueset.getValues(), xmlWriter);
 750  6
                         xmlWriter.endEntity();
 751  
                 }
 752  3
         }
 753  
 
 754  
         /**
 755  
          * @since 0.1.0
 756  
          */
 757  
         private void writeValues (List<Value<?>> values, XmlWriter xmlWriter) throws IOException {
 758  16
                 for (Value<?> value : values) {
 759  
 
 760  
                         // Constant
 761  28
                         if (value instanceof Constant) {
 762  10
                                 final Constant<?> constant = (Constant<?>) value;
 763  10
                                 xmlWriter.writeEntity(CONSTANT_ELEMENT);
 764  
 
 765  10
                                 if (constant.getValue() instanceof Integer) {
 766  10
                                         xmlWriter.writeAttribute(TYPE_ATTRIBUTE, INTEGER_TYPE);
 767  10
                                         xmlWriter.writeAttribute(VALUE_ATTRIBUTE, constant.getValue().toString());
 768  
 
 769  0
                                 } else if (constant.getValue() instanceof Double) {
 770  0
                                         xmlWriter.writeAttribute(TYPE_ATTRIBUTE, DOUBLE_TYPE);
 771  0
                                         xmlWriter.writeAttribute(VALUE_ATTRIBUTE, constant.getValue().toString());
 772  
 
 773  0
                                 } else if (constant.getValue() instanceof String) {
 774  0
                                         xmlWriter.writeAttribute(TYPE_ATTRIBUTE, STRING_TYPE);
 775  0
                                         xmlWriter.writeAttribute(VALUE_ATTRIBUTE, constant.getValue().toString());
 776  
 
 777  0
                                 } else if (constant.getValue() instanceof Boolean) {
 778  0
                                         xmlWriter.writeAttribute(TYPE_ATTRIBUTE, BOOLEAN_TYPE);
 779  0
                                         xmlWriter.writeAttribute(VALUE_ATTRIBUTE, constant.getValue().toString());
 780  
 
 781  
                                 } else {
 782  0
                                         throw new IOException("Unknown value type.");
 783  
                                 }
 784  10
                                 xmlWriter.endEntity();
 785  
 
 786  
                         // TimeConstant
 787  10
                         } else if (value instanceof TimeConstant) {
 788  8
                                 xmlWriter.writeEntity(CONSTANT_ELEMENT);
 789  8
                                 xmlWriter.writeAttribute(TYPE_ATTRIBUTE, TIME_TYPE);
 790  8
                                 xmlWriter.writeAttribute(VALUE_ATTRIBUTE, value.toString());
 791  8
                                 xmlWriter.endEntity();
 792  
 
 793  
                         // ArgumentRef
 794  10
                         } else if (value instanceof Argument) {
 795  8
                                 final Argument<?> argument = (Argument<?>) value;
 796  8
                                 xmlWriter.writeEntity(ARGUMENT_REF_ELEMENT);
 797  8
                                 xmlWriter.writeAttribute(NAME_ATTRIBUTE, argument.getName());
 798  8
                                 xmlWriter.endEntity();
 799  
 
 800  
                         // CurrentTime
 801  8
                         } else if (value instanceof CurrentTime) {
 802  2
                                         xmlWriter.writeEntity(CURRENT_TIME_ELEMENT);
 803  2
                                         xmlWriter.endEntity();
 804  
 
 805  
                         } else {
 806  0
                                 throw new IOException("Unknown value.");
 807  
                         }
 808  
                 }
 809  16
         }
 810  
 
 811  
         //---- PolicyWriter
 812  
 
 813  
         /**
 814  
          * @since 0.1.0
 815  
          */
 816  
         public void writePolicy (PolicyBean policy) throws PolicyException {
 817  11
                 this.id = 1;
 818  11
                 final RoleAssignmentRuleBeanCollection roleAssignmentRules =
 819  
                         policy.getRoleAssignmentRules();
 820  11
                 final Map<String, String> subjectDomainIdMap = buildSubjectDomainIdMap(roleAssignmentRules);
 821  11
                 final TargetAccessRuleBeanCollection targetAccessRules = policy.getTargetAccessRules();
 822  11
                 final Map<String, String> soaIdMap = buildSoaIdMap(roleAssignmentRules);
 823  11
                 final Map<String, String> domainIDMap = buildDomainIdMap(targetAccessRules);
 824  11
                 final Map<ActionBean, String> actionsIdMap = buildActionIdMap(targetAccessRules);
 825  11
                 final Map<TargetBean, String> targetIdMap = buildTargetIdMap(targetAccessRules);
 826  11
                 final Map<Obligation, String> obligationIDMap = buildObligationIdMap(targetAccessRules);
 827  11
                 final Map<RoleHierarchyBean, String> hierarchyIdMap =
 828  
                         buildHierachyIdMap(policy.getRoleHierarchies());
 829  
 
 830  
                 try {
 831  11
                         final XmlWriter xmlWriter =
 832  
                                 new PrettyPrinterXmlWriter(new SimpleXmlWriter(this.writer));
 833  11
                         xmlWriter.writeXmlVersion("1.0", this.encoding);
 834  
 
 835  
                         // Unfortunately XmlWriter doesn't allow us to cleanly write the document type.
 836  11
                         this.writer.append(PERMIS_DOCTYPE);
 837  11
                         xmlWriter.writeEntity(PERMIS_POLICY_ELEMENT);
 838  11
                                 if (policy.getDateTimeZone() != null) {
 839  2
                                         xmlWriter.writeAttribute(TIME_ZONE_ATTRIBUTE, policy.getDateTimeZone());
 840  
                                 }
 841  
 
 842  11
                         writeSubjectPolicy(roleAssignmentRules, subjectDomainIdMap, xmlWriter);
 843  11
                         writeRoleHierarchyPolicy(hierarchyIdMap, xmlWriter);
 844  11
                         writeSoaPolicy(roleAssignmentRules, soaIdMap, xmlWriter);
 845  11
                         writeRoleAssignmentPolicy(
 846  
                                 roleAssignmentRules, subjectDomainIdMap, soaIdMap, hierarchyIdMap, xmlWriter
 847  
                         );
 848  11
                         writeDomainPolicy(domainIDMap, xmlWriter);
 849  11
                         writeActionPolicy(actionsIdMap, xmlWriter);
 850  11
                         writeTargetPolicy(domainIDMap, actionsIdMap, targetIdMap, xmlWriter);
 851  11
                         writeObligationPolicy(obligationIDMap, xmlWriter);
 852  11
                         writeTargetAccessPolicy(
 853  
                                 targetAccessRules,
 854  
                                 domainIDMap,
 855  
                                 actionsIdMap,
 856  
                                 targetIdMap,
 857  
                                 hierarchyIdMap,
 858  
                                 obligationIDMap,
 859  
                                 xmlWriter
 860  
                         );
 861  
 
 862  11
                         xmlWriter.endEntity();
 863  
 
 864  
                         // Close the XmlWriter, note that this will not close the underlying writer.
 865  11
                         xmlWriter.close();
 866  0
                 } catch (IOException e) {
 867  0
                         throw new PolicyException("I/O Error writing policy.", e);
 868  11
                 }
 869  11
         }
 870  
 
 871  
 }