/**
   * Tests if <code>NodeType.canAddChildNode(String childNodeName, String nodeTypeName)</code>
   * returns false if <code>nodeTypeName</code> represents an abstract node type.
   */
  public void testCanAddAbstractType() throws NotExecutableException, RepositoryException {

    NodeDefinition nodeDef = NodeTypeUtil.locateChildNodeDef(session, false, false, false);

    if (nodeDef == null) {
      throw new NotExecutableException("No testable node type found.");
    }

    NodeType nodeType = nodeDef.getDeclaringNodeType();
    String childNodeName = nodeDef.getName();
    String abstractName = null;
    NodeTypeIterator it = manager.getPrimaryNodeTypes();
    while (it.hasNext() && abstractName == null) {
      NodeType nt = it.nextNodeType();
      if (nt.isAbstract()) {
        abstractName = nt.getName();
      }
    }
    if (abstractName == null) {
      throw new NotExecutableException("No abstract type found.");
    }

    assertFalse(
        "NodeType.canAddChildNode(String childNodeName, String nodeTypeName) "
            + "must return false if nodeTypeName represents an abstract node type.",
        nodeType.canAddChildNode(childNodeName, abstractName));
  }
 /**
  * Map query types.
  *
  * @param queryCriteria the query criteria
  * @param queryBuilder the query builder
  * @throws Exception the exception
  */
 private void mapQueryTypes(final QueryCriteria queryCriteria, final SQLQueryBuilder queryBuilder)
     throws Exception {
   queryBuilder.selectTypes(null);
   // Searh on nt:base
   queryBuilder.fromNodeTypes(queryCriteria.getNodeTypes());
   ManageableRepository currentRepository = repositoryService.getCurrentRepository();
   NodeTypeManager manager = currentRepository.getNodeTypeManager();
   // Query all documents for specific content types
   String[] contentTypes = queryCriteria.getContentTypes();
   if ((contentTypes != null && contentTypes.length > 0 && queryCriteria.getKeyword() == null)
       || queryCriteria.isSearchWebpage()) {
     mapQuerySpecificNodeTypes(queryCriteria, queryBuilder, manager);
     return;
   }
   List<String> selectedNodeTypes = templateService.getDocumentTemplates();
   queryBuilder.openGroup(LOGICAL.AND);
   queryBuilder.equal("jcr:primaryType", "nt:resource", LOGICAL.NULL);
   // query on exo:rss-enable nodetypes for title, summary field
   queryBuilder.equal("jcr:mixinTypes", "exo:rss-enable", LOGICAL.OR);
   // query on metadata nodetype
   List<String> publicatioTypes = new ArrayList<String>(4);
   for (NodeTypeIterator iterator = manager.getAllNodeTypes(); iterator.hasNext(); ) {
     NodeType nodeType = iterator.nextNodeType();
     if (nodeType.isNodeType("publication:webpagesPublication")) {
       publicatioTypes.add(nodeType.getName());
       continue;
     }
     if (!nodeType.isNodeType("exo:metadata")) continue;
     if (nodeType.isMixin()) {
       queryBuilder.equal("jcr:mixinTypes", nodeType.getName(), LOGICAL.OR);
     } else {
       queryBuilder.equal("jcr:primaryType", nodeType.getName(), LOGICAL.OR);
     }
   }
   for (String type : selectedNodeTypes) {
     NodeType nodetype = manager.getNodeType(type);
     if (nodetype.isMixin()) {
       queryBuilder.like("jcr:mixinTypes", type, LOGICAL.OR);
     } else {
       queryBuilder.equal("jcr:primaryType", type, LOGICAL.OR);
     }
   }
   queryBuilder.closeGroup();
   // unwanted document types: exo:cssFile, exo:jsFile
   if (excludeMimeTypes.size() < 1) return;
   queryBuilder.openGroup(LOGICAL.AND_NOT);
   String[] mimetypes = excludeMimeTypes.toArray(new String[] {});
   queryBuilder.equal("jcr:mimeType", mimetypes[0], LOGICAL.NULL);
   for (int i = 1; i < mimetypes.length; i++) {
     queryBuilder.equal("jcr:mimeType", mimetypes[i], LOGICAL.OR);
   }
   queryBuilder.closeGroup();
   // Unwanted document by mixin nodetypes
   queryBuilder.openGroup(LOGICAL.AND_NOT);
   queryBuilder.like("jcr:mixinTypes", "exo:cssFile", LOGICAL.NULL);
   queryBuilder.like("jcr:mixinTypes", "exo:jsFile", LOGICAL.OR);
   queryBuilder.closeGroup();
 }
  @SuppressWarnings("unchecked")
  public List<ChoiceListValue> getChoiceListValues(
      ExtendedPropertyDefinition epd,
      String param,
      List<ChoiceListValue> values,
      Locale locale,
      Map<String, Object> context) {
    final SortedSet<ChoiceListValue> listValues = new TreeSet<ChoiceListValue>();
    if (StringUtils.isEmpty(param)) {
      param = "jmix:editorialContent";
    }
    try {
      String includedTypes = StringUtils.substringBefore(param, ";");

      Set<String> excludedTypes = new HashSet<String>();
      String exclusion = StringUtils.substringAfter(param, ";");
      if (StringUtils.isNotBlank(exclusion)) {
        excludedTypes.addAll(
            CollectionUtils.collect(
                Arrays.asList(StringUtils.substringAfter(param, ";").split(",")),
                new Transformer() {
                  public Object transform(Object input) {
                    return ((String) input).trim();
                  }
                }));
      }

      for (String nodeTypeName : includedTypes.split(",")) {
        nodeTypeName = nodeTypeName.trim();
        ExtendedNodeType nodeType = NodeTypeRegistry.getInstance().getNodeType(nodeTypeName);
        if (!isExcludedType(nodeType, excludedTypes)) {
          listValues.add(new ChoiceListValue(nodeType.getLabel(locale), nodeType.getName()));
        }
        NodeTypeIterator nti = nodeType.getSubtypes();
        while (nti.hasNext()) {
          ExtendedNodeType type = (ExtendedNodeType) nti.next();
          if (!isExcludedType(type, excludedTypes)) {
            listValues.add(new ChoiceListValue(type.getLabel(locale), type.getName()));
          }
        }
      }
    } catch (NoSuchNodeTypeException e) {
      logger.error("Cannot get type", e);
    }

    return new LinkedList<ChoiceListValue>(listValues);
  }
 @Override
 public String[] getMixinTypes(boolean allowAbstract) throws RemoteException {
   ArrayList<String> list = new ArrayList();
   try {
     NodeTypeManager mgr = session().getWorkspace().getNodeTypeManager();
     NodeTypeIterator it = mgr.getMixinNodeTypes();
     while (it.hasNext()) {
       NodeType nodeType = it.nextNodeType();
       if (!nodeType.isAbstract() || allowAbstract) {
         list.add(nodeType.getName());
       }
     }
     String[] res = new String[list.size()];
     list.toArray(res);
     return res;
   } catch (RepositoryException e) {
     throw new RemoteException(e.getMessage());
   }
 }
  @Override
  public Collection<JcrNodeType> nodeTypes() throws RemoteException {
    ArrayList<JcrNodeType> list = new ArrayList();
    try {
      NodeTypeManager mgr = session().getWorkspace().getNodeTypeManager();

      NodeTypeIterator it = mgr.getAllNodeTypes();
      while (it.hasNext()) {
        NodeType type = it.nextNodeType();
        JcrNodeType jcrType = new JcrNodeType();
        jcrType.setName(type.getName());
        jcrType.setAbstract(type.isAbstract());
        jcrType.setPrimary(!type.isMixin());
        jcrType.setMixin(type.isMixin());
        list.add(jcrType);
      }
    } catch (Exception e) {
      throw new RemoteException(e.getMessage());
    }
    return list;
  }
  /**
   * Tests if <code>NodeType.canAddChildNode(String childNodeName, String nodeTypeName)</code>
   * returns false if <code>nodeTypeName</code> represents a mixin.
   */
  public void testCanAddMixinType() throws NotExecutableException, RepositoryException {

    NodeDefinition nodeDef = NodeTypeUtil.locateChildNodeDef(session, false, false, false);

    if (nodeDef == null) {
      throw new NotExecutableException("No testable node type found.");
    }

    NodeType nodeType = nodeDef.getDeclaringNodeType();
    String childNodeName = nodeDef.getName();
    String mixinName;
    NodeTypeIterator it = manager.getMixinNodeTypes();
    if (it.hasNext()) {
      mixinName = it.nextNodeType().getName();
    } else {
      throw new NotExecutableException("No mixin type found.");
    }

    assertFalse(
        "NodeType.canAddChildNode(String childNodeName, String nodeTypeName) "
            + "must return false if nodeTypeName represents a mixin type.",
        nodeType.canAddChildNode(childNodeName, mixinName));
  }