private boolean doHasAccess(
      Subject subject,
      List<? extends Authorizable> authorizables,
      Set<? extends Action> actions,
      ActiveRoleSet roleSet) {
    Set<String> groups = getGroups(subject);
    Set<String> hierarchy = new HashSet<String>();
    for (Authorizable authorizable : authorizables) {
      hierarchy.add(KV_JOINER.join(authorizable.getTypeName(), authorizable.getName()));
    }
    List<String> requestPrivileges = buildPermissions(authorizables, actions);
    Iterable<Privilege> privileges =
        getPrivileges(groups, roleSet, authorizables.toArray(new Authorizable[0]));
    lastFailedPrivileges.get().clear();

    for (String requestPrivilege : requestPrivileges) {
      for (Privilege permission : privileges) {
        /*
         * Does the permission granted in the policy file imply the requested action?
         */
        boolean result = permission.implies(privilegeFactory.createPrivilege(requestPrivilege));
        if (LOGGER.isDebugEnabled()) {
          LOGGER.debug(
              "ProviderPrivilege {}, RequestPrivilege {}, RoleSet, {}, Result {}",
              new Object[] {permission, requestPrivilege, roleSet, result});
        }
        if (result) {
          return true;
        }
      }
    }

    lastFailedPrivileges.get().addAll(requestPrivileges);
    return false;
  }
 @Test
 public void testUnexpected() throws Exception {
   Privilege p =
       new Privilege() {
         @Override
         public boolean implies(Privilege p) {
           return false;
         }
       };
   Privilege collection1 = create(new KeyValue("collection", "coll1"));
   assertFalse(collection1.implies(null));
   assertFalse(collection1.implies(p));
   assertFalse(collection1.equals(null));
   assertFalse(collection1.equals(p));
 }
  @Test
  public void testRoleShorterThanRequest() throws Exception {
    Privilege collection1 = create(new KeyValue("collection", "coll1"));
    Privilege query = create(new KeyValue("collection", "coll1"), new KeyValue("action", "query"));
    Privilege update =
        create(new KeyValue("collection", "coll1"), new KeyValue("action", "update"));
    Privilege all = create(new KeyValue("collection", "coll1"), new KeyValue("action", ALL));

    assertTrue(collection1.implies(query));
    assertTrue(collection1.implies(update));
    assertTrue(collection1.implies(all));

    assertFalse(query.implies(collection1));
    assertFalse(update.implies(collection1));
    assertTrue(all.implies(collection1));
  }
  @Test
  public void testCollectionAll() throws Exception {
    Privilege collectionAll = create(new KeyValue("collection", ALL));
    Privilege collection1 = create(new KeyValue("collection", "coll1"));
    assertTrue(collectionAll.implies(collection1));
    assertTrue(collection1.implies(collectionAll));

    Privilege allUpdate = create(new KeyValue("collection", ALL), new KeyValue("action", "update"));
    Privilege allQuery = create(new KeyValue("collection", ALL), new KeyValue("action", "query"));
    Privilege coll1Update =
        create(new KeyValue("collection", "coll1"), new KeyValue("action", "update"));
    Privilege coll1Query =
        create(new KeyValue("collection", "coll1"), new KeyValue("action", "query"));
    assertTrue(allUpdate.implies(coll1Update));
    assertTrue(allQuery.implies(coll1Query));
    assertTrue(coll1Update.implies(allUpdate));
    assertTrue(coll1Query.implies(allQuery));
    assertFalse(allUpdate.implies(coll1Query));
    assertFalse(coll1Update.implies(coll1Query));
    assertFalse(allQuery.implies(coll1Update));
    assertFalse(coll1Query.implies(allUpdate));
    assertFalse(allUpdate.implies(allQuery));
    assertFalse(allQuery.implies(allUpdate));
    assertFalse(coll1Update.implies(coll1Query));
    assertFalse(coll1Query.implies(coll1Update));

    // test different length paths
    assertTrue(collectionAll.implies(allUpdate));
    assertTrue(collectionAll.implies(allQuery));
    assertTrue(collectionAll.implies(coll1Update));
    assertTrue(collectionAll.implies(coll1Query));
    assertFalse(allUpdate.implies(collectionAll));
    assertFalse(allQuery.implies(collectionAll));
    assertFalse(coll1Update.implies(collectionAll));
    assertFalse(coll1Query.implies(collectionAll));
  }
  @Test
  public void testSimpleAction() throws Exception {
    Privilege query = create(new KeyValue("collection", "coll1"), new KeyValue("action", "query"));
    Privilege update =
        create(new KeyValue("collection", "coll1"), new KeyValue("action", "update"));
    Privilege queryCase =
        create(new KeyValue("colleCtIon", "coLl1"), new KeyValue("AcTiOn", "QuERy"));

    assertTrue(query.implies(query));
    assertTrue(update.implies(update));
    assertTrue(query.implies(queryCase));
    assertTrue(queryCase.implies(query));

    assertFalse(query.implies(update));
    assertFalse(queryCase.implies(update));
    assertFalse(update.implies(query));
    assertFalse(update.implies(queryCase));
  }
  @Test
  public void testSimpleNoAction() throws Exception {
    Privilege collection1 = create(new KeyValue("collection", "coll1"));
    Privilege collection2 = create(new KeyValue("collection", "coll2"));
    Privilege collection1Case = create(new KeyValue("colleCtIon", "coLl1"));

    assertTrue(collection1.implies(collection1));
    assertTrue(collection2.implies(collection2));
    assertTrue(collection1.implies(collection1Case));
    assertTrue(collection1Case.implies(collection1));

    assertFalse(collection1.implies(collection2));
    assertFalse(collection1Case.implies(collection2));
    assertFalse(collection2.implies(collection1));
    assertFalse(collection2.implies(collection1Case));
  }