Coverage Report - org.openpermis.policy.bean.basic.BasicPolicy
 
Classes in this File Line Coverage Branch Coverage Complexity
BasicPolicy
46%
122/264
27%
55/198
3.474
 
 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.bean.basic;
 11  
 
 12  
 import static org.openpermis.policy.bean.basic.BasicUtilities.getIdentityDetails;
 13  
 import static org.openpermis.policy.bean.basic.BasicUtilities.getShortStringDetails;
 14  
 import static org.openpermis.policy.bean.basic.BasicUtilities.multiHashCode;
 15  
 
 16  
 import java.net.URI;
 17  
 import java.util.ArrayList;
 18  
 import java.util.Collections;
 19  
 import java.util.HashMap;
 20  
 import java.util.HashSet;
 21  
 import java.util.Iterator;
 22  
 import java.util.List;
 23  
 import java.util.Map;
 24  
 import java.util.Set;
 25  
 
 26  
 import org.joda.time.DateTimeZone;
 27  
 import org.slf4j.Logger;
 28  
 import org.slf4j.LoggerFactory;
 29  
 
 30  
 import org.openpermis.Subject;
 31  
 import org.openpermis.policy.AccessDecision;
 32  
 import org.openpermis.policy.AuthorizedRoles;
 33  
 import org.openpermis.policy.PartProblemReporter;
 34  
 import org.openpermis.policy.Role;
 35  
 import org.openpermis.policy.TimeStamp;
 36  
 import org.openpermis.policy.PartProblemReporter.ProblemMessage;
 37  
 import org.openpermis.policy.bean.ActionBean;
 38  
 import org.openpermis.policy.bean.DomainBean;
 39  
 import org.openpermis.policy.bean.ObligationBean;
 40  
 import org.openpermis.policy.bean.PartBean;
 41  
 import org.openpermis.policy.bean.PolicyBean;
 42  
 import org.openpermis.policy.bean.RoleAssignmentRuleBean;
 43  
 import org.openpermis.policy.bean.RoleAssignmentRuleBeanCollection;
 44  
 import org.openpermis.policy.bean.RoleHierarchyBean;
 45  
 import org.openpermis.policy.bean.RoleHierarchyBeanCollection;
 46  
 import org.openpermis.policy.bean.SerialNumber;
 47  
 import org.openpermis.policy.bean.TargetAccessRuleBean;
 48  
 import org.openpermis.policy.bean.TargetAccessRuleBeanCollection;
 49  
 import org.openpermis.policy.bean.TargetBean;
 50  
 
 51  
 /**
 52  
  * Basic implementation of a policy.
 53  
  * @since 0.1.0
 54  
  */
 55  1
 public class BasicPolicy
 56  
         extends BasicPartBean
 57  
         implements PolicyBean
 58  
 {
 59  
 
 60  
         //---- Static
 61  
 
 62  
         /**
 63  
          * @since 0.1.0
 64  
          */
 65  
         private static final long serialVersionUID = -8888013228359169599L;
 66  
 
 67  
         /**
 68  
          * @since 0.4.0
 69  
          */
 70  1
         private static final Logger LOGGER =
 71  
                 LoggerFactory.getLogger(BasicPolicy.class);
 72  
 
 73  
         //---- State
 74  
 
 75  
         /**
 76  
          * @since 0.1.0
 77  
          */
 78  
         private DateTimeZone dateTimeZone;
 79  
 
 80  
         /**
 81  
          * @since 0.1.0
 82  
          */
 83  
         private RoleAssignmentRuleBeanCollection roleAssignmentRules;
 84  
 
 85  
         /**
 86  
          * @since 0.1.0
 87  
          */
 88  
         private TargetAccessRuleBeanCollection targetAccessRules;
 89  
 
 90  
         /**
 91  
          * @since 0.1.0
 92  
          */
 93  
         private RoleHierarchyBeanCollection roleHierarchies;
 94  
 
 95  
         //---- Constructors
 96  
 
 97  
         /**
 98  
          * Creates a policy with the specified rules.
 99  
          * @since 0.1.0
 100  
          */
 101  
         protected BasicPolicy (SerialNumber serialNumber) {
 102  264
                 super(PolicyBean.class, serialNumber);
 103  264
                 this.roleAssignmentRules = new BasicRoleAssignmentRuleCollection(serialNumber.next());
 104  264
                 this.targetAccessRules = new BasicTargetAccessRuleCollection(serialNumber.next());
 105  264
                 this.roleHierarchies = new BasicRoleHierarchyCollection(serialNumber.next());
 106  264
         }
 107  
 
 108  
         //---- Methods
 109  
 
 110  
         /**
 111  
          * Check if there is at least one role assignment rule and all is correct.
 112  
          * of the role hierarchy is consistent.
 113  
          * @param reporter the reporter to use.
 114  
          * @return {@code true} if the role assignment rules are valid.
 115  
          * @since 0.1.0
 116  
          */
 117  
         private boolean areRoleAssignmentRulesValid (PartProblemReporter reporter) {
 118  
                 boolean valid;
 119  
 
 120  
                 // init
 121  3
                 valid = true;
 122  
                 
 123  
                 // check for role-assignment-rules
 124  3
                 if (!isChildCollectionValid(
 125  
                         reporter, getRoleAssignmentRules(), true, true, false, true, false)
 126  
                 ) {
 127  1
                         valid = false;
 128  1
                         reportProblem(reporter, ProblemMessage.invalidRoleAssignmentRules);
 129  
                 }
 130  
 
 131  
                 // check topology: references roles vs role-hierarchies
 132  3
                 if (getRoleAssignmentRules() != null) {
 133  3
                         for (RoleAssignmentRuleBean rule : getRoleAssignmentRules()) {
 134  2
                                 if (rule != null && rule.getRoles() != null) {
 135  2
                                         for (Role role : rule.getRoles()) {
 136  2
                                                 if (role != null) {
 137  2
                                                         if (!getRoleHierarchies().toList().contains(role.getRoleHierarchy())) {
 138  2
                                                                 valid = false;
 139  2
                                                                 reportProblem(reporter, ProblemMessage.illegalRoleTree);
 140  
                                                         }
 141  
                                                 }
 142  
                                         }
 143  
                                 }
 144  
                         }
 145  
                 }
 146  
 
 147  
                 // return
 148  3
                 return valid;
 149  
         }
 150  
 
 151  
         /**
 152  
          * Check if there is at least one target access rule and that the containment hierarchy
 153  
          * of the role hierarchy is consistent.
 154  
          * @param reporter the reporter to use.
 155  
          * @return {@code true} if the target access rules are valid.
 156  
          * @since 0.1.0
 157  
          */
 158  
         private boolean areTargetAccessRulesValid (PartProblemReporter reporter) {
 159  
                 boolean valid;
 160  
 
 161  
                 // init
 162  3
                 valid = true;
 163  
 
 164  
                 // check for target-access-rules
 165  3
                 if (!isChildCollectionValid(
 166  
                         reporter, getTargetAccessRules(), true, true, false, true, false)) {
 167  2
                         valid = false;
 168  2
                         reportProblem(reporter, ProblemMessage.invalidTargetAccessRules);
 169  
                 }
 170  
 
 171  
                 // check topology: references roles vs. role-hierarchies
 172  3
                 if (getTargetAccessRules() != null) {
 173  3
                         for (TargetAccessRuleBean rule : getTargetAccessRules()) {
 174  2
                                 if (rule != null && rule.getRoles() != null) {
 175  2
                                         for (Role role : rule.getRoles()) {
 176  1
                                                 if (role != null) {
 177  1
                                                         if (!getRoleHierarchies().toList().contains(role.getRoleHierarchy())) {
 178  1
                                                                 valid = false;
 179  1
                                                                 reportProblem(reporter, ProblemMessage.illegalRoleTree);
 180  
                                                         }
 181  
                                                 }
 182  
                                         }
 183  
                                 }
 184  
                         }
 185  
                 }
 186  
 
 187  
                 // return
 188  3
                 return valid;
 189  
         }
 190  
 
 191  
         /**
 192  
          * Check if there is at least one role-hierarchy,
 193  
          * check if their name are unique,
 194  
          * @param reporter the reporter to use.
 195  
          * @return {@code true} if the role hierarchies are valid.
 196  
          * @since 0.1.0
 197  
          */
 198  
         private boolean areRoleHierarchiesValid (PartProblemReporter reporter) {
 199  
                 boolean valid;
 200  
 
 201  
                 // init
 202  3
                 valid = true;
 203  
 
 204  
                 // check for role-hierarchies
 205  3
                 if (!isChildCollectionValid(
 206  
                         reporter, this.getRoleHierarchies(), true, true, false, false, true)) {
 207  3
                         valid = false;
 208  3
                         reportProblem(reporter, ProblemMessage.invalidRoleHierarchies);
 209  
                 }
 210  
 
 211  
                 // return
 212  3
                 return valid;
 213  
         }
 214  
 
 215  
         private <M extends PartBean> void addPartToMap (
 216  
                 Map<SerialNumber, PartBean> map,
 217  
                 Class<M> type,
 218  
                 PartBean part)
 219  
         {
 220  0
                 if (part != null && type.isAssignableFrom(part.getClass())) {
 221  0
                         map.put(part.getSerialNumber(), part);
 222  
                 }
 223  0
         }
 224  
 
 225  
         /**
 226  
          * Returns all parts of given type, unique by serial number.
 227  
          * @since 0.1.0
 228  
          */
 229  
         private <M extends PartBean> Map<SerialNumber, PartBean> getPartsMap (Class<M> type) {
 230  
 
 231  
                 // init
 232  0
                 Map<SerialNumber, PartBean> map = new HashMap<SerialNumber, PartBean>();
 233  
 
 234  
                 // get policy
 235  0
                 PolicyBean policy = this;
 236  
 
 237  
                 // add PolicyBean
 238  0
                 addPartToMap(map, type, policy);
 239  
 
 240  
                 // loop over RoleHierarchyBean's
 241  0
                 for (final RoleHierarchyBean rolehierarchy : policy.getRoleHierarchies()) {
 242  
 
 243  
                         // add RoleHierarchyBean
 244  0
                         addPartToMap(map, type, rolehierarchy);
 245  
                 }
 246  
                 
 247  0
                 for (final RoleAssignmentRuleBean rule : policy.getRoleAssignmentRules()) {
 248  0
                         addPartToMap(map, type, rule);
 249  0
                         addPartToMap(map, type, rule.getSubjectDomain());
 250  0
                         addPartToMap(map, type, rule.getAuthority());
 251  
                 }
 252  
 
 253  
                 // loop over TargetAccessRuleBean's
 254  0
                 for (final TargetAccessRuleBean rule : policy.getTargetAccessRules()) {
 255  
 
 256  
                         // add TargetAccessRuleBean
 257  0
                         addPartToMap(map, type, rule);
 258  
 
 259  0
                         for (final ObligationBean obligation : rule.getObligations()) {
 260  0
                                 if (obligation != null) {
 261  0
                                         addPartToMap(map, type, obligation);
 262  
                                 }
 263  
                         }
 264  
 
 265  
                         // loop over TargetBean's
 266  0
                         for (final TargetBean target : rule.getTargets()) {
 267  0
                                 if (target != null) {
 268  
                                         // add TargetBean
 269  0
                                         addPartToMap(map, type, target);
 270  
 
 271  
                                         // add resource domain
 272  0
                                         addPartToMap(map, type, target.getResourceDomain());
 273  
 
 274  
                                         // loop over actions
 275  0
                                         for (final ActionBean action : target.getActions()) {
 276  
                                                 // add Action
 277  0
                                                 addPartToMap(map, type, action);
 278  
                                         }
 279  
                                 }
 280  
                         }
 281  
                 }
 282  
 
 283  
                 // return
 284  0
                 return map;
 285  
         }
 286  
 
 287  
         //---- Policy
 288  
 
 289  
         /**
 290  
          * Find all roles that are eligible according the the authorized roles specified.
 291  
          * <p>Includes all super roles of the authorized roles passed in.</p>
 292  
          * @param authorizedRoles the list of authorized roles.
 293  
          * @return the roles eligible for access, empty if there are none, never {@code null}.
 294  
          * @since 0.4.0
 295  
          */
 296  
         private Set<Role> getEligibleRoles (List<AuthorizedRoles> authorizedRoles) {
 297  15
                 if (authorizedRoles.isEmpty()) {
 298  2
                         return Collections.emptySet();
 299  
                 }
 300  13
                 final Set<Role> eligibleRoles = new HashSet<Role>();
 301  13
                 for (AuthorizedRoles authorizedRoleSet : authorizedRoles) {
 302  13
                         for (Role role : authorizedRoleSet.getRoles()) {
 303  18
                                 eligibleRoles.addAll(role.getSuperRoles());
 304  
                         }
 305  
                 }
 306  13
                 return eligibleRoles;
 307  
         }
 308  
         
 309  
         /**
 310  
          * Retrieve all verified roles of a subject that are a subset of the eligible roles.
 311  
          * <p>Includes all inherited sub roles of the verified roles.</p>
 312  
          * @param subject the subject for which to retrieve the verified roles.
 313  
          * @param timeStamp the timestamp of verification.
 314  
          * @param eligibleRoles the set of eligible roles.
 315  
          * @return the set of verified roles, may be empty if there are none, never {@code null}.
 316  
          * @since 0.4.0
 317  
          */
 318  
         private Set<Role> getVerifiedRoles (
 319  
                 Subject subject, TimeStamp timeStamp, Set<Role> eligibleRoles
 320  
         ) {
 321  13
                 final Set<Role> subjectRoles = subject.getAssignedRoles(timeStamp, eligibleRoles);
 322  13
                 if (subjectRoles.isEmpty()) {
 323  2
                         return Collections.emptySet();
 324  
                 }
 325  11
                 LOGGER.debug("Eligible roles assigned to subject include {}.", subjectRoles);
 326  11
                 final Set<Role> verifiedRoles = 
 327  
                         getRoleAssignmentRules().verifyRoleAssignments(subject, subjectRoles, timeStamp);
 328  11
                 if (verifiedRoles.isEmpty()) {
 329  0
                         LOGGER.debug("No verified roles for subject found.");
 330  0
                         return Collections.emptySet();
 331  
                 }
 332  11
                 LOGGER.debug("Verified, eligible roles assigned to subject include {}.", verifiedRoles);
 333  11
                 final Set<Role> extendedVerifiedRoles = new HashSet<Role>();
 334  11
                 for (Role role : verifiedRoles) {
 335  12
                         extendedVerifiedRoles.addAll(role.getSubRoles());
 336  
                 }
 337  11
                 return extendedVerifiedRoles;
 338  
         }
 339  
 
 340  
         /**
 341  
          * Asserts that a value is not {@code null}.
 342  
          * @param type descriptive type of the value to check.
 343  
          * @param value the value to check.
 344  
          * @throws IllegalArgumentException in case the value is {@code null}.
 345  
          * @since 0.4.0
 346  
          */
 347  
         private final void assertNotNull (String type, Object value) {
 348  75
                 if (value == null) {
 349  0
                         final IllegalArgumentException exception = 
 350  
                                 new IllegalArgumentException("Access decision " + type + " must not be [null].");
 351  0
                         LOGGER.warn("Illegal call to PDP.", exception);
 352  0
                         throw exception;
 353  
                 }
 354  75
         }
 355  
         
 356  
         /**
 357  
          * Checks the access decision parameters.
 358  
          * @param subject a {@link Subject} to identify the user requesting access and to provide
 359  
          * the roles assigned to her.
 360  
          * @param resourceUri a {@link URI} to identify the resource that the subject wants to access.
 361  
          * @param actionName the name of the action that the subject wants to perform on the resource.
 362  
          * @param arguments an optional list of arguments for the action
 363  
          * that the subject wants to perform on the resource.
 364  
          * @param timeStamp the time at which the action is executed.
 365  
          * @throws IllegalArgumentException in case there is an invalid parameter.
 366  
          * @since 0.4.0
 367  
          */
 368  
         private void assertParameters (
 369  
                 Subject subject,
 370  
                 URI resourceUri,
 371  
                 String actionName,
 372  
                 List<?> arguments,
 373  
                 TimeStamp timeStamp
 374  
         ) {
 375  15
                 assertNotNull("subject", subject);
 376  15
                 assertNotNull("resource", resourceUri);
 377  15
                 assertNotNull("actionName", subject);
 378  15
                 assertNotNull("arguments", arguments);
 379  15
                 assertNotNull("timeStamp", timeStamp);
 380  15
         }
 381  
         
 382  
         /**
 383  
          * @since 0.1.0
 384  
          */
 385  
         public AccessDecision getAccessDecision (
 386  
                 Subject subject,
 387  
                 URI resourceUri,
 388  
                 String actionName,
 389  
                 List<?> arguments,
 390  
                 TimeStamp timeStamp
 391  
         ) {
 392  15
                 LOGGER.info(
 393  
                         "Access decision request for [" + 
 394  
                         "subject=[{}],resource=[{}],action=[{}],arguments={},timestamp=[{}]].",
 395  
                         new Object[] { subject, resourceUri, actionName, arguments, timeStamp }
 396  
                 );
 397  15
                 assertParameters(subject, resourceUri, actionName, arguments, timeStamp);
 398  
                 
 399  15
                 final List<AuthorizedRoles> authorizedRoleSets =
 400  
                         getTargetAccessRules().findAuthorizedRoleSets(
 401  
                                 resourceUri, actionName, arguments, timeStamp
 402  
                         );
 403  
 
 404  15
                 final Set<Role> eligibleRoles = getEligibleRoles(authorizedRoleSets);
 405  15
                 if (eligibleRoles.isEmpty()) {
 406  2
                         LOGGER.debug("Access denied, no eligible roles found.");
 407  2
                         return new AccessDecision(false);
 408  
                 }
 409  13
                 LOGGER.debug("Eligible target roles include {}.", eligibleRoles);
 410  
                 
 411  13
                 final Set<Role> verifiedRoles = getVerifiedRoles(subject, timeStamp, eligibleRoles);
 412  13
                 if (verifiedRoles.isEmpty()) {
 413  2
                         LOGGER.debug("Access denied, subject has no verified, eligible roles assigned.");
 414  2
                         return new AccessDecision(false);
 415  
                 }
 416  11
                 LOGGER.debug("Verified subject roles include {}.", eligibleRoles);
 417  
                 
 418  11
                 final AccessDecision decision = getAccessDecision(authorizedRoleSets, verifiedRoles);
 419  11
                 LOGGER.info("Access " + decision + ".");
 420  11
                 return decision;
 421  
         }
 422  
         
 423  
         /**
 424  
          * Determines the access decision according to the list of authorized roles and verified roles.
 425  
          * <p>If there is at least one authorized role set that matches the verified roles then a 
 426  
          * positive access decision is returned. The access decision includes the obligations of all
 427  
          * authorized role sets that match.</p>
 428  
          * @param authorizedRoleSets the authorized role sets for which to determine the decision.
 429  
          * @param verifiedRoles the verified roles to match.
 430  
          * @return the access decision requested.
 431  
          * @since 0.4.0
 432  
          */
 433  
         private AccessDecision getAccessDecision (
 434  
                 List<AuthorizedRoles> authorizedRoleSets, Set<Role> verifiedRoles
 435  
         ) {
 436  11
                 boolean granted = false;
 437  11
                 final List<Set<String>> obligations = new ArrayList<Set<String>>();
 438  11
                 for (AuthorizedRoles roles : authorizedRoleSets) {
 439  11
                         if (roles.match(verifiedRoles)) {
 440  8
                                 granted = true;
 441  8
                                 obligations.add(roles.getObligations());
 442  
                         }
 443  
                 }
 444  11
                 if (granted) {
 445  8
                         return new AccessDecision(true, obligations);
 446  
                 }
 447  3
                 return new AccessDecision(false);
 448  
         }
 449  
         
 450  
         //---- PolicyBean
 451  
 
 452  
         /**
 453  
          * @since 0.1.0
 454  
          */
 455  
         public DateTimeZone getDateTimeZone () {
 456  13
                 return this.dateTimeZone;
 457  
         }
 458  
 
 459  
         /**
 460  
          * @since 0.1.0
 461  
          */
 462  
         public void setDateTimeZone (DateTimeZone dateTimeZone) {
 463  235
                 this.dateTimeZone = dateTimeZone;
 464  235
         }
 465  
 
 466  
         /**
 467  
          * @since 0.3.0
 468  
          */
 469  
         public RoleAssignmentRuleBeanCollection getRoleAssignmentRules () {
 470  541
                 return this.roleAssignmentRules;
 471  
         }
 472  
 
 473  
         /**
 474  
          * @since 0.3.0
 475  
          */
 476  
         public void setRoleAssignmentRules (RoleAssignmentRuleBeanCollection roleAssignmentRules) {
 477  238
                 final RoleAssignmentRuleBeanCollection oldRoleAssignmentRules = getRoleAssignmentRules();
 478  238
                 if (roleAssignmentRules == null) {
 479  0
                         this.roleAssignmentRules =
 480  
                                 new BasicRoleAssignmentRuleCollection(getSerialNumber().next());
 481  
                 } else {
 482  238
                         this.roleAssignmentRules = roleAssignmentRules;
 483  
                 }
 484  238
                 firePropertyChange("roleAssignmentRules", oldRoleAssignmentRules, getRoleAssignmentRules());
 485  238
         }
 486  
 
 487  
         /**
 488  
          * @since 0.3.0
 489  
          */
 490  
         public TargetAccessRuleBeanCollection getTargetAccessRules () {
 491  543
                 return this.targetAccessRules;
 492  
         }
 493  
 
 494  
         /**
 495  
          * @since 0.3.0
 496  
          */
 497  
         public void setTargetAccessRules (TargetAccessRuleBeanCollection targetAccessRules) {
 498  238
                 final TargetAccessRuleBeanCollection oldTargetAccessRules = getTargetAccessRules();
 499  238
                 if (targetAccessRules == null) {
 500  0
                         this.targetAccessRules = new BasicTargetAccessRuleCollection(getSerialNumber().next());
 501  
                 } else {
 502  238
                         this.targetAccessRules = targetAccessRules;
 503  
                 }
 504  238
                 firePropertyChange("targetAccessRules", oldTargetAccessRules, getTargetAccessRules());
 505  238
         }
 506  
 
 507  
         /**
 508  
          * @since 0.3.0
 509  
          */
 510  
         public RoleHierarchyBeanCollection getRoleHierarchies () {
 511  523
                 return this.roleHierarchies;
 512  
         }
 513  
 
 514  
         /**
 515  
          * @since 0.3.0
 516  
          */
 517  
         public void setRoleHierarchies (RoleHierarchyBeanCollection roleHierarchies) {
 518  237
                 final RoleHierarchyBeanCollection oldRoleHierarchies = getRoleHierarchies();
 519  237
                 if (roleHierarchies == null) {
 520  0
                         this.roleHierarchies = new BasicRoleHierarchyCollection(getSerialNumber().next());
 521  
                 } else {
 522  237
                         this.roleHierarchies = roleHierarchies;
 523  
                 }
 524  237
                 firePropertyChange("roleHierarchies", oldRoleHierarchies, getRoleHierarchies());
 525  237
         }
 526  
 
 527  
         /**
 528  
          * Returns all parts of given type, unique by serial number.
 529  
          * @since 0.1.0
 530  
          */
 531  
         @SuppressWarnings("unchecked")
 532  
         public <M extends PartBean> List<M> getPartsList (Class<M> type) {
 533  0
                 Map<SerialNumber, PartBean> map = getPartsMap(type);
 534  0
                 List<M> list = new ArrayList<M>();
 535  0
                 Iterator<Map.Entry<SerialNumber, PartBean>> it = map.entrySet().iterator();
 536  0
                 while (it.hasNext()) {
 537  0
                         Map.Entry<SerialNumber, PartBean> pairs = it.next();
 538  0
                         PartBean part = pairs.getValue();
 539  0
                         list.add((M) part);
 540  0
                 }
 541  0
                 return list;
 542  
         }
 543  
 
 544  
         /**
 545  
          * Returns all rolerefs.
 546  
          * @since 0.3.0
 547  
          */
 548  
         public List<Role> getRoleRefList () {
 549  
 
 550  
                 // get policy
 551  0
                 PolicyBean policy = this;
 552  
 
 553  
                 // loop over RoleHierarchyBean's
 554  0
                 List<Role> list = new ArrayList<Role>();
 555  0
                 for (final RoleHierarchyBean rolehierarchy : policy.getRoleHierarchies()) {
 556  0
                         for (String role : rolehierarchy.getRoles()) {
 557  0
                                 list.add(Role.create(rolehierarchy, role));
 558  
                         }
 559  
                 }
 560  
 
 561  
                 // return
 562  0
                 return list;
 563  
         }
 564  
 
 565  
         /**
 566  
          * Returns the PartBean's containing the given part.
 567  
          * @return list of found parts in the policy
 568  
          * @since 0.1.0
 569  
          */
 570  
         public List<TargetAccessRuleBean> getParentTargetAccessRules (TargetBean searchPart) {
 571  0
                 List<TargetAccessRuleBean> list = new ArrayList<TargetAccessRuleBean>();
 572  0
                 for (final TargetAccessRuleBean currRule : getTargetAccessRules()) {
 573  0
                         for (final TargetBean currTarget : currRule.getTargets()) {
 574  0
                                 if (searchPart.equalSerialNumber(currTarget)) {
 575  0
                                         list.add(currRule);
 576  0
                                         break;
 577  
                                 }
 578  
                         }
 579  
                 }
 580  0
                 assert
 581  
                         BasicUtilities.findDuplicateSerialNumberInList(list) ==
 582  
                         BasicUtilities.NOT_FOUND;
 583  0
                 return list;
 584  
         }
 585  
 
 586  
         /**
 587  
          * Returns the PartBean's containing the given part.
 588  
          * @return list of found parts in the policy
 589  
          * @since 0.3.0
 590  
          */
 591  
         public List<TargetAccessRuleBean> getParentTargetAccessRules (ObligationBean searchPart) {
 592  0
                 List<TargetAccessRuleBean> list = new ArrayList<TargetAccessRuleBean>();
 593  0
                 for (final TargetAccessRuleBean currRule : getTargetAccessRules()) {
 594  0
                         for (final ObligationBean currObligation : currRule.getObligations()) {
 595  0
                                 if (searchPart.equalSerialNumber(currObligation)) {
 596  0
                                         list.add(currRule);
 597  0
                                         break;
 598  
                                 }
 599  
                         }
 600  
                 }
 601  0
                 assert
 602  
                         BasicUtilities.findDuplicateSerialNumberInList(list) ==
 603  
                         BasicUtilities.NOT_FOUND;
 604  0
                 return list;
 605  
         }
 606  
 
 607  
         /**
 608  
          * Returns the PartBean's containing the given part.
 609  
          * @return list of found parts in the policy
 610  
          * @since 0.1.0
 611  
          */
 612  
         public List<TargetAccessRuleBean> getParentTargetAccessRules (Role searchRule) {
 613  0
                 List<TargetAccessRuleBean> list = new ArrayList<TargetAccessRuleBean>();
 614  0
                 for (final TargetAccessRuleBean currRule : getTargetAccessRules()) {
 615  0
                         for (final Role currRole : currRule.getRoles()) {
 616  0
                                 if (searchRule.equals(currRole)) {
 617  0
                                         list.add(currRule);
 618  0
                                         break;
 619  
                                 }
 620  
                         }
 621  
                 }
 622  0
                 assert
 623  
                         BasicUtilities.findDuplicateSerialNumberInList(list) ==
 624  
                                 BasicUtilities.NOT_FOUND;
 625  0
                 return list;
 626  
         }
 627  
 
 628  
         /**
 629  
          * Returns the PartBean's containing the given part.
 630  
          * @return list of found parts in the policy
 631  
          * @since 0.3.0
 632  
          */
 633  
         public List<RoleHierarchyBean> getParentRoleHierarchies (Role role) {
 634  0
                 List<RoleHierarchyBean> list = new ArrayList<RoleHierarchyBean>();
 635  0
                 for (final RoleHierarchyBean currHierarchy : getRoleHierarchies()) {
 636  0
                         for (final String currRole : currHierarchy.getRoles()) {
 637  0
                                 if (role.getName().equals(currRole)) {
 638  0
                                         list.add(currHierarchy);
 639  0
                                         break;
 640  
                                 }
 641  
                         }
 642  
                 }
 643  0
                 assert
 644  
                         BasicUtilities.findDuplicateSerialNumberInList(list) ==
 645  
                                 BasicUtilities.NOT_FOUND;
 646  0
                 return list;
 647  
         }
 648  
 
 649  
         /**
 650  
          * Returns the PartBean's containing the given part.
 651  
          * @return list of found parts in the policy
 652  
          * @since 0.1.0
 653  
          */
 654  
         public List<TargetBean> getParentTargets (ActionBean searchPart) {
 655  0
                 List<TargetBean> parentsPossible = getPartsList(TargetBean.class);
 656  0
                 List<TargetBean> parentsFound = new ArrayList<TargetBean>();
 657  0
                 for (final TargetBean currTarget : parentsPossible) {
 658  0
                         for (final ActionBean currAction : currTarget.getActions()) {
 659  0
                                 if (searchPart.equalSerialNumber(currAction)) {
 660  0
                                         parentsFound.add(currTarget);
 661  0
                                         break;
 662  
                                 }
 663  
                         }
 664  
                 }
 665  0
                 assert
 666  
                         BasicUtilities.findDuplicateSerialNumberInList(parentsFound) ==
 667  
                         BasicUtilities.NOT_FOUND;
 668  0
                 return parentsFound;
 669  
         }        
 670  
 
 671  
         /**
 672  
          * Returns the PartBean's containing the given part.
 673  
          * @return list of found parts in the policy
 674  
          * @since 0.1.0
 675  
          */
 676  
         public List<TargetBean> getParentTargets (DomainBean searchPart) {
 677  0
                 List<TargetBean> parentsPossible = getPartsList(TargetBean.class);
 678  0
                 List<TargetBean> parentsFound = new ArrayList<TargetBean>();
 679  0
                 for (final TargetBean currTarget : parentsPossible) {
 680  0
                         if (
 681  
                                 currTarget.getResourceDomain() != null &&
 682  
                                 searchPart.equalSerialNumber(currTarget.getResourceDomain())
 683  
                         ) {
 684  0
                                 parentsFound.add(currTarget);
 685  
                         }
 686  
                 }
 687  0
                 assert
 688  
                         BasicUtilities.findDuplicateSerialNumberInList(parentsFound) ==
 689  
                         BasicUtilities.NOT_FOUND;
 690  0
                 return parentsFound;
 691  
         }
 692  
 
 693  
         /**
 694  
          * Returns all resource domains.
 695  
          * @return all resource domains.
 696  
          * @since 0.3.0
 697  
          */
 698  
         public List<DomainBean> getResourceDomains () {
 699  0
                 final Set<SerialNumber> serials = new HashSet<SerialNumber>();
 700  0
                 final List<DomainBean> result = new ArrayList<DomainBean>();
 701  0
                 for (TargetAccessRuleBean rule : getTargetAccessRules()) {
 702  0
                         for (TargetBean target : rule.getTargets()) {
 703  0
                                 final DomainBean domain = target.getResourceDomain();
 704  0
                                 if (domain != null && 
 705  
                                         !serials.contains(domain.getSerialNumber())
 706  
                                 ) {
 707  0
                                         serials.add(domain.getSerialNumber());
 708  0
                                         result.add(domain);
 709  
                                 }
 710  0
                         }
 711  
                 }
 712  0
                 return result;
 713  
         }
 714  
 
 715  
         /**
 716  
          * Returns all subject domains.
 717  
          * @return all subject domains.
 718  
          * @since 0.3.0
 719  
          */
 720  
         public List<DomainBean> getSubjectDomains () {
 721  0
                 final Set<SerialNumber> serials = new HashSet<SerialNumber>();
 722  0
                 final List<DomainBean> result = new ArrayList<DomainBean>();
 723  0
                 for (RoleAssignmentRuleBean rule : getRoleAssignmentRules()) {
 724  0
                         final DomainBean domain = rule.getSubjectDomain();
 725  0
                         if (domain != null && 
 726  
                                 !serials.contains(domain.getSerialNumber())
 727  
                         ) {
 728  0
                                 serials.add(domain.getSerialNumber());
 729  0
                                 result.add(domain);
 730  
                         }        
 731  0
                 }
 732  0
                 return result;
 733  
         }
 734  
 
 735  
         /**
 736  
          * Returns the PartBean's containing the given part.
 737  
          * @return list of found parts in the policy
 738  
          * @since 0.3.0
 739  
          */
 740  
         public List<RoleAssignmentRuleBean> getParentRoleAssignmentRules (DomainBean searchPart) {
 741  0
                 List<RoleAssignmentRuleBean> parentsPossible = getPartsList(RoleAssignmentRuleBean.class);
 742  0
                 List<RoleAssignmentRuleBean> parentsFound = new ArrayList<RoleAssignmentRuleBean>();
 743  0
                 for (final RoleAssignmentRuleBean currRule : parentsPossible) {
 744  0
                         if (currRule.getSubjectDomain() != null &&
 745  
                                 searchPart.equalSerialNumber(currRule.getSubjectDomain())) {
 746  0
                                 parentsFound.add(currRule);
 747  
                         }
 748  
                 }
 749  0
                 assert
 750  
                         BasicUtilities.findDuplicateSerialNumberInList(parentsFound) ==
 751  
                         BasicUtilities.NOT_FOUND;
 752  0
                 return parentsFound;
 753  
         }
 754  
 
 755  
         //---- BasicPart
 756  
 
 757  
         /**
 758  
          * @since 0.1.0
 759  
          */
 760  
         @Override
 761  
         public boolean isPartValid (PartProblemReporter reporter) {
 762  
                 boolean valid;
 763  
 
 764  
                 // init
 765  3
                 valid = true;
 766  
 
 767  
                 // check role-assignment-rules
 768  3
                 if (!areRoleAssignmentRulesValid(reporter)) {
 769  3
                         valid = false;
 770  
                 }
 771  
 
 772  
                 // check target-access-rules
 773  3
                 if (!areTargetAccessRulesValid(reporter)) {
 774  3
                         valid = false;
 775  
                 }
 776  
 
 777  
                 // check role-hierarchies
 778  3
                 if (!areRoleHierarchiesValid(reporter)) {
 779  3
                         valid = false;
 780  
                 }
 781  
 
 782  
                 // return
 783  3
                 return valid;
 784  
         }
 785  
 
 786  
         /**
 787  
          * @since 0.1.0
 788  
          */
 789  
         @Override
 790  
         protected boolean comparablePart (BasicPart part) {
 791  28
                 return part instanceof PolicyBean;
 792  
         }
 793  
 
 794  
         /**
 795  
          * @since 0.1.0
 796  
          */
 797  
         @Override
 798  
         protected boolean equalPart (BasicPart part) {
 799  14
                 final PolicyBean policy = (PolicyBean) part;
 800  14
                 return
 801  
                         getRoleAssignmentRules().equals(policy.getRoleAssignmentRules()) &&
 802  
                         getTargetAccessRules().equals(policy.getTargetAccessRules()) &&
 803  
                         getRoleHierarchies().equals(policy.getRoleHierarchies());
 804  
         }
 805  
 
 806  
         /**
 807  
          * @since 0.1.0
 808  
          */
 809  
         @Override
 810  
         protected int partHashCode () {
 811  4
                 return multiHashCode(
 812  
                         getRoleAssignmentRules().hashCode(),
 813  
                         getTargetAccessRules().hashCode(),
 814  
                         getRoleHierarchies().hashCode()
 815  
                 );
 816  
         }
 817  
 
 818  
         /**
 819  
          * @since 0.1.0
 820  
          */
 821  
         @Override
 822  
         protected String getSimpleClassName () {
 823  0
                 return PolicyBean.class.getSimpleName();
 824  
         }
 825  
 
 826  
         /**
 827  
          * @since 0.1.0
 828  
          */
 829  
         @Override
 830  
         protected void appendPartDetails (StringBuilder sb) {
 831  0
                 appendDetails(sb, "roleAssignmentRules", getShortStringDetails(getRoleAssignmentRules()));
 832  0
                 appendDetails(sb, "targetAccessRules", getShortStringDetails(getTargetAccessRules()));
 833  0
                 appendDetails(sb, "roleHierarchies", getIdentityDetails(getRoleHierarchies()));
 834  0
         }
 835  
 
 836  
         //---- BasicPartBean
 837  
 
 838  
         /**
 839  
          * @since 0.1.0
 840  
          */
 841  
         @Override
 842  
         public PartBean findBySerialNumber (SerialNumber partSerialNumber) {
 843  0
                 for (final RoleAssignmentRuleBean rule : getRoleAssignmentRules()) {
 844  0
                         final PartBean bean = rule.findBySerialNumber(partSerialNumber);
 845  0
                         if (bean != null) {
 846  0
                                 return bean;
 847  
                         }
 848  0
                 }
 849  
 
 850  0
                 for (final TargetAccessRuleBean rule : getTargetAccessRules()) {
 851  0
                         final PartBean bean = rule.findBySerialNumber(partSerialNumber);
 852  0
                         if (bean != null) {
 853  0
                                 return bean;
 854  
                         }
 855  0
                 }
 856  
 
 857  0
                 for (final RoleHierarchyBean hierarchy : getRoleHierarchies()) {
 858  0
                         final PartBean bean = hierarchy.findBySerialNumber(partSerialNumber);
 859  0
                         if (bean != null) {
 860  0
                                 return bean;
 861  
                         }
 862  0
                 }
 863  
 
 864  0
                 return super.findBySerialNumber(partSerialNumber);
 865  
         }
 866  
 
 867  
 }