public void setPolicy(String s, AccessControlPolicy accessControlPolicy)
      throws RepositoryException {
    boolean invalidPolicy = true;
    // Invalid policy may not be set by a READ-only session
    if (RegistryJCRSpecificStandardLoderUtil.isSessionReadOnly(registrySession.getUserID())) {
      if ((accessControlPolicy instanceof RegistryAccessControlList)) {
        invalidPolicy = false;
      } else if ((accessControlPolicy instanceof RegistryNamedAccessControlPolicy)) {
        invalidPolicy = false;
      }
      if (invalidPolicy) {
        throw new AccessControlException("Invalid policy may not be set by a READ-only session");
      }
    }

    if (accessCtrlPolicies.get(s) == null) {

      Set<AccessControlPolicy> policies = new HashSet<AccessControlPolicy>();
      policies.add(accessControlPolicy);
      accessCtrlPolicies.put(s, policies);
    } else {

      accessCtrlPolicies.get(s).add(accessControlPolicy);
      //            Set<AccessControlPolicy> temp = accessCtrlPolicies.get(s);
      //            temp.add(accessControlPolicy);
      //            accessCtrlPolicies.remove(s);
      //            accessCtrlPolicies.put(s, temp);

    }
  }
  public void removePolicy(String s, AccessControlPolicy accessControlPolicy)
      throws RepositoryException {

    Set<AccessControlPolicy> temp = accessCtrlPolicies.get(s);
    temp.remove(accessControlPolicy);
    accessCtrlPolicies.remove(s);
    accessCtrlPolicies.put(s, temp);
  }
  // only include non-mixin types
  public static String[] getNodeTypeNames() {
    // filter mixins out
    Set<String> keySet = allNodes.keySet();
    Set<String> copySet = new HashSet<String>();
    for (String s : keySet) copySet.add(s); // do I really need to do this, java?
    for (String s : keySet) {
      if (getDefinition(s).isMixin) copySet.remove(s);
    }

    String[] options = new String[copySet.size()];
    options = copySet.toArray(options);
    Arrays.sort(options);
    return options;
  }
  public Privilege[] getPrivileges(String s) throws RepositoryException {

    Item item = registrySession.getItem(s);
    if (item instanceof Property) {
      throw new PathNotFoundException("No privilages can be added for Properties");
    }

    Set<Privilege> privileges = new HashSet<Privilege>();

    if (accessCtrlPolicies.get(s) instanceof RegistryAccessControlList) {

      AccessControlEntry[] accessNtries =
          ((RegistryAccessControlList) accessCtrlPolicies.get(s)).getAccessControlEntries();

      for (AccessControlEntry ac : accessNtries) {
        if (ac != null) {
          privileges.addAll(Arrays.asList(ac.getPrivileges()));
        }
      }
    } else {
      // TODO check how to apply NamedAccessControlPolicy
    }

    // Read-only session must have READ privilege on test node
    if (RegistryJCRSpecificStandardLoderUtil.isSessionReadOnly(registrySession.getUserID())
        && !privileges.contains(privilegeRegistry.getPrivilegeFromName(Privilege.JCR_READ))) {
      privileges.add(privilegeRegistry.getPrivilegeFromName(Privilege.JCR_READ));
    }

    if (privileges.size() != 0) {
      return privileges.toArray(new Privilege[privileges.size()]);
    } else return new Privilege[0];
  }
  public boolean hasPrivileges(String s, Privilege[] privileges) throws RepositoryException {

    boolean hasPrivileges = true;
    Item item = registrySession.getItem(s);
    if (item instanceof Property) {
      throw new PathNotFoundException("No privilages can be added for Properties");
    }

    Set<Privilege> temp = new HashSet<Privilege>();
    temp.addAll(Arrays.asList(getPrivileges(s)));
    for (Privilege pv : privileges) {
      if (!temp.contains(pv)) {
        hasPrivileges = false;
      }
    }

    return hasPrivileges;
  }
  @Override
  public boolean hasPrivileges(final String absPath, final Privilege[] privileges)
      throws PathNotFoundException, RepositoryException {

    if (supportPrivileges) {
      // if the node is created in the same session, return true
      for (Item item : session.getNewItems()) {
        if (item.getPath().equals(absPath)) {
          return true;
        }
      }

      // check privilege names
      return hasPrivilegesLegacy(absPath, privileges);
    } else {
      // check ACLs
      Set<String> privs = new HashSet<>();
      for (Privilege privilege : privileges) {
        privs.add(privilege.getName());
      }
      String mountPoint = session.getRepository().getStoreProvider().getMountPoint();
      Session securitySession =
          JCRSessionFactory.getInstance()
              .getCurrentSystemSession(session.getWorkspace().getName(), null, null);
      PathWrapper pathWrapper =
          new ExternalPathWrapperImpl(
              StringUtils.equals(absPath, "/") ? mountPoint : mountPoint + absPath,
              securitySession);
      return AccessManagerUtils.isGranted(
          pathWrapper,
          privs,
          securitySession,
          jahiaPrincipal,
          workspaceName,
          false,
          pathPermissionCache,
          compiledAcls,
          registry);
    }
  }
  private static Privilege[] filterPrivileges(
      Privilege[] privileges, List<Privilege> privilegesToFilterOut) {

    Set<Privilege> filteredResult = new HashSet<Privilege>();
    for (Privilege privilege : privileges) {
      if (!privilegesToFilterOut.contains(privilege)) {
        if (privilege.isAggregate()
            && areIntersecting(privilege.getDeclaredAggregatePrivileges(), privilegesToFilterOut)) {
          // We de-aggregate a privilege in case any of its children are to be filtered out, since a
          // privilege is valid only if all its children are valid.
          filteredResult.addAll(
              Arrays.asList(
                  filterPrivileges(
                      privilege.getDeclaredAggregatePrivileges(), privilegesToFilterOut)));
        } else {
          filteredResult.add(privilege);
        }
      }
    }

    return filteredResult.toArray(new Privilege[filteredResult.size()]);
  }
  public VNodeDefinition(Node node) throws RepositoryException {
    name = node.getProperty(JCR_NODETYPENAME).getString();

    // do properties
    properties = new HashMap<String, VPropertyDefinitionI>();
    childSuggestions = new HashMap<String, String>();
    NodeIterator nodeIterator = node.getNodes();
    while (nodeIterator.hasNext()) {
      Node definitionNode = nodeIterator.nextNode();
      String nodeType = definitionNode.getProperty(AbstractProperty.JCR_PRIMARYTYPE).getString();

      // do a property
      if (NT_PROPERTYDEFINITION.equals(nodeType)) {
        String propertyName = "*"; // default to wildcard name
        if (definitionNode.hasProperty(JCR_NAME)) {

          // only add non-autogenerated properties
          if (!definitionNode.getProperty(JCR_AUTOCREATED).getBoolean()) {
            propertyName = definitionNode.getProperty(JCR_NAME).getString();
            properties.put(propertyName, new VPropertyDefinition(definitionNode));
          }
        } else {
          // property with no name means this node can accept custom properties
          canAddProperties = true;
        }
      }

      // do a child suggestion
      if (NT_CHILDNODEDEFINITION.equals(nodeType)) {
        String childName = "*";
        // only do well-defined childnodedefinitions with the following 2 jcr properties
        if (definitionNode.hasProperty(JCR_NAME)
            && definitionNode.hasProperty(JCR_DEFAULTPRIMARYTYPE)) {
          childSuggestions.put(
              definitionNode.getProperty(JCR_NAME).getString(),
              definitionNode.getProperty(JCR_DEFAULTPRIMARYTYPE).getString());
        }
      }
    }

    // do supertypes
    supertypes = new HashSet<String>();
    if (node.hasProperty(JCR_SUPERTYPES)) {
      for (Value value : node.getProperty(JCR_SUPERTYPES).getValues()) {
        supertypes.add(value.getString());
      }
    }

    // set mixin status
    isMixin = node.hasProperty(JCR_ISMIXIN) && node.getProperty(JCR_ISMIXIN).getBoolean();
  }
 public String[] getNamespacePrefixes() throws RepositoryException {
   Set<String> wsPrefixes =
       new HashSet<String>(Arrays.asList(getWorkspace().getNamespaceRegistry().getPrefixes()));
   wsPrefixes.addAll(prefixToNs.keySet());
   return wsPrefixes.toArray(new String[wsPrefixes.size()]);
 }