Search in sources :

Example 41 with QPropertyDefinition

use of org.apache.jackrabbit.spi.QPropertyDefinition in project jackrabbit by apache.

the class NodeTypeReader method getNodeTypeDef.

/**
     * Returns the node type definition specified by the current element.
     *
     * @return node type definition
     * @throws InvalidNodeTypeDefException if the definition is invalid
     * @throws NameException               if the definition contains an
     *                                     illegal name
     * @throws NamespaceException if a namespace is not defined
     */
private QNodeTypeDefinition getNodeTypeDef() throws InvalidNodeTypeDefException, NameException, NamespaceException {
    QNodeTypeDefinitionBuilder type = new QNodeTypeDefinitionBuilder();
    type.setName(resolver.getQName(walker.getAttribute(Constants.NAME_ATTRIBUTE)));
    type.setMixin(Boolean.valueOf(walker.getAttribute(Constants.ISMIXIN_ATTRIBUTE)));
    type.setOrderableChildNodes(Boolean.valueOf(walker.getAttribute(Constants.HASORDERABLECHILDNODES_ATTRIBUTE)));
    type.setAbstract(Boolean.valueOf(walker.getAttribute(Constants.ISABSTRACT_ATTRIBUTE)));
    if (walker.getAttribute(Constants.ISQUERYABLE_ATTRIBUTE) != null) {
        type.setQueryable(Boolean.valueOf(walker.getAttribute(Constants.ISQUERYABLE_ATTRIBUTE)));
    }
    String primaryItemName = walker.getAttribute(Constants.PRIMARYITEMNAME_ATTRIBUTE);
    if (primaryItemName != null && primaryItemName.length() > 0) {
        type.setPrimaryItemName(resolver.getQName(primaryItemName));
    }
    // supertype declarations
    if (walker.enterElement(Constants.SUPERTYPES_ELEMENT)) {
        List<Name> supertypes = new ArrayList<Name>();
        while (walker.iterateElements(Constants.SUPERTYPE_ELEMENT)) {
            supertypes.add(resolver.getQName(walker.getContent()));
        }
        type.setSupertypes(supertypes.toArray(new Name[supertypes.size()]));
        walker.leaveElement();
    }
    // property definitions
    List<QPropertyDefinition> properties = new ArrayList<QPropertyDefinition>();
    while (walker.iterateElements(Constants.PROPERTYDEFINITION_ELEMENT)) {
        QPropertyDefinitionBuilder def = getPropDef();
        def.setDeclaringNodeType(type.getName());
        properties.add(def.build());
    }
    type.setPropertyDefs(properties.toArray(new QPropertyDefinition[properties.size()]));
    // child node definitions
    List<QNodeDefinition> nodes = new ArrayList<QNodeDefinition>();
    while (walker.iterateElements(Constants.CHILDNODEDEFINITION_ELEMENT)) {
        QNodeDefinitionBuilder def = getChildNodeDef();
        def.setDeclaringNodeType(type.getName());
        nodes.add(def.build());
    }
    type.setChildNodeDefs(nodes.toArray(new QNodeDefinition[nodes.size()]));
    return type.build();
}
Also used : QNodeDefinitionBuilder(org.apache.jackrabbit.spi.commons.nodetype.QNodeDefinitionBuilder) QPropertyDefinitionBuilder(org.apache.jackrabbit.spi.commons.nodetype.QPropertyDefinitionBuilder) QPropertyDefinition(org.apache.jackrabbit.spi.QPropertyDefinition) ArrayList(java.util.ArrayList) QNodeDefinition(org.apache.jackrabbit.spi.QNodeDefinition) QNodeTypeDefinitionBuilder(org.apache.jackrabbit.spi.commons.nodetype.QNodeTypeDefinitionBuilder) Name(org.apache.jackrabbit.spi.Name)

Example 42 with QPropertyDefinition

use of org.apache.jackrabbit.spi.QPropertyDefinition in project jackrabbit by apache.

the class EffectiveNodeType method create.

/**
     * Package private factory method.
     * <p>
     * Creates an effective node type representation of a node type definition.
     * Note that the definitions of all referenced node types must be contained
     * in <code>ntdCache</code>.
     *
     * @param ntd      node type definition
     * @param entCache cache of already-built effective node types
     * @param ntdCache cache of node type definitions, used to resolve dependencies
     * @return an effective node type representation of the given node type definition.
     * @throws NodeTypeConflictException if the node type definition is invalid,
     *                                   e.g. due to ambiguous child definitions.
     * @throws NoSuchNodeTypeException if a node type reference (e.g. a supertype)
     *                                 could not be resolved.
     */
static EffectiveNodeType create(QNodeTypeDefinition ntd, EffectiveNodeTypeCache entCache, Map<Name, QNodeTypeDefinition> ntdCache) throws NodeTypeConflictException, NoSuchNodeTypeException {
    // create empty effective node type instance
    EffectiveNodeType ent = new EffectiveNodeType();
    Name ntName = ntd.getName();
    // prepare new instance
    ent.mergedNodeTypes.add(ntName);
    ent.allNodeTypes.add(ntName);
    // map of all item definitions (maps id to definition)
    // used to effectively detect ambiguous child definitions where
    // ambiguity is defined in terms of definition identity
    Set<QItemDefinition> itemDefs = new HashSet<QItemDefinition>();
    QNodeDefinition[] cnda = ntd.getChildNodeDefs();
    for (QNodeDefinition aCnda : cnda) {
        // this node type definition
        if (itemDefs.contains(aCnda)) {
            // conflict
            String msg;
            if (aCnda.definesResidual()) {
                msg = ntName + " contains ambiguous residual child node definitions";
            } else {
                msg = ntName + " contains ambiguous definitions for child node named " + aCnda.getName();
            }
            log.debug(msg);
            throw new NodeTypeConflictException(msg);
        } else {
            itemDefs.add(aCnda);
        }
        if (aCnda.definesResidual()) {
            // residual node definition
            ent.unnamedItemDefs.add(aCnda);
        } else {
            // named node definition
            Name name = aCnda.getName();
            List<QItemDefinition> defs = ent.namedItemDefs.get(name);
            if (defs == null) {
                defs = new ArrayList<QItemDefinition>();
                ent.namedItemDefs.put(name, defs);
            }
            if (defs.size() > 0) {
                /**
                     * there already exists at least one definition with that
                     * name; make sure none of them is auto-create
                     */
                for (QItemDefinition def : defs) {
                    if (aCnda.isAutoCreated() || def.isAutoCreated()) {
                        // conflict
                        String msg = "There are more than one 'auto-create' item definitions for '" + name + "' in node type '" + ntName + "'";
                        log.debug(msg);
                        throw new NodeTypeConflictException(msg);
                    }
                }
            }
            defs.add(aCnda);
        }
    }
    QPropertyDefinition[] pda = ntd.getPropertyDefs();
    for (QPropertyDefinition aPda : pda) {
        // this node type definition
        if (itemDefs.contains(aPda)) {
            // conflict
            String msg;
            if (aPda.definesResidual()) {
                msg = ntName + " contains ambiguous residual property definitions";
            } else {
                msg = ntName + " contains ambiguous definitions for property named " + aPda.getName();
            }
            log.debug(msg);
            throw new NodeTypeConflictException(msg);
        } else {
            itemDefs.add(aPda);
        }
        if (aPda.definesResidual()) {
            // residual property definition
            ent.unnamedItemDefs.add(aPda);
        } else {
            // named property definition
            Name name = aPda.getName();
            List<QItemDefinition> defs = ent.namedItemDefs.get(name);
            if (defs == null) {
                defs = new ArrayList<QItemDefinition>();
                ent.namedItemDefs.put(name, defs);
            }
            if (defs.size() > 0) {
                /**
                     * there already exists at least one definition with that
                     * name; make sure none of them is auto-create
                     */
                for (QItemDefinition def : defs) {
                    if (aPda.isAutoCreated() || def.isAutoCreated()) {
                        // conflict
                        String msg = "There are more than one 'auto-create' item definitions for '" + name + "' in node type '" + ntName + "'";
                        log.debug(msg);
                        throw new NodeTypeConflictException(msg);
                    }
                }
            }
            defs.add(aPda);
        }
    }
    // resolve supertypes recursively
    Name[] supertypes = ntd.getSupertypes();
    if (supertypes.length > 0) {
        EffectiveNodeType base = NodeTypeRegistry.getEffectiveNodeType(supertypes, entCache, ntdCache);
        ent.internalMerge(base, true);
    }
    // resolve 'orderable child nodes' attribute value (JCR-1947)
    if (ntd.hasOrderableChildNodes()) {
        ent.orderableChildNodes = true;
    } else {
        Name[] nta = ent.getInheritedNodeTypes();
        for (Name aNta : nta) {
            QNodeTypeDefinition def = ntdCache.get(aNta);
            if (def.hasOrderableChildNodes()) {
                ent.orderableChildNodes = true;
                break;
            }
        }
    }
    // resolve 'primary item' attribute value (JCR-1947)
    if (ntd.getPrimaryItemName() != null) {
        ent.primaryItemName = ntd.getPrimaryItemName();
    } else {
        Name[] nta = ent.getInheritedNodeTypes();
        for (Name aNta : nta) {
            QNodeTypeDefinition def = ntdCache.get(aNta);
            if (def.getPrimaryItemName() != null) {
                ent.primaryItemName = def.getPrimaryItemName();
                break;
            }
        }
    }
    // we're done
    return ent;
}
Also used : QItemDefinition(org.apache.jackrabbit.spi.QItemDefinition) QNodeDefinition(org.apache.jackrabbit.spi.QNodeDefinition) Name(org.apache.jackrabbit.spi.Name) QNodeTypeDefinition(org.apache.jackrabbit.spi.QNodeTypeDefinition) QPropertyDefinition(org.apache.jackrabbit.spi.QPropertyDefinition) HashSet(java.util.HashSet)

Example 43 with QPropertyDefinition

use of org.apache.jackrabbit.spi.QPropertyDefinition in project jackrabbit by apache.

the class EffectiveNodeType method getApplicablePropertyDef.

/**
     * Returns the applicable property definition for a property with the
     * specified name and type. The multiValued flag is not taken into account
     * in the selection algorithm. Other than
     * <code>{@link #getApplicablePropertyDef(Name, int, boolean)}</code>
     * this method does not take the multiValued flag into account in the
     * selection algorithm. If there more than one applicable definitions then
     * the following rules are applied:
     * <ul>
     * <li>named definitions are preferred to residual definitions</li>
     * <li>definitions with specific required type are preferred to definitions
     * with required type UNDEFINED</li>
     * <li>single-value definitions are preferred to multiple-value definitions</li>
     * </ul>
     *
     * @param name
     * @param type
     * @return
     * @throws ConstraintViolationException if no applicable property definition
     *                                      could be found
     */
public QPropertyDefinition getApplicablePropertyDef(Name name, int type) throws ConstraintViolationException {
    // try named property definitions first
    QPropertyDefinition match = getMatchingPropDef(getNamedPropDefs(name), type);
    if (match != null) {
        return match;
    }
    // no item with that name defined;
    // try residual property definitions
    match = getMatchingPropDef(getUnnamedPropDefs(), type);
    if (match != null) {
        return match;
    }
    // no applicable definition found
    throw new ConstraintViolationException("no matching property definition found for " + name);
}
Also used : QPropertyDefinition(org.apache.jackrabbit.spi.QPropertyDefinition) ConstraintViolationException(javax.jcr.nodetype.ConstraintViolationException)

Example 44 with QPropertyDefinition

use of org.apache.jackrabbit.spi.QPropertyDefinition in project jackrabbit by apache.

the class EffectiveNodeType method internalMerge.

/**
     * Internal helper method which merges another <code>EffectiveNodeType</code>
     * instance with <i>this</i> instance.
     * <p>
     * Warning: This instance might be in an inconsistent state if an exception
     * is thrown.
     *
     * @param other
     * @param supertype true if the merge is a result of inheritance, i.e. <code>other</code>
     *                  represents one or more supertypes of this instance; otherwise false, i.e.
     *                  the merge is the result of an explicit aggregation
     * @throws NodeTypeConflictException
     */
private synchronized void internalMerge(EffectiveNodeType other, boolean supertype) throws NodeTypeConflictException {
    Name[] nta = other.getAllNodeTypes();
    int includedCount = 0;
    for (Name aNta : nta) {
        if (includesNodeType(aNta)) {
            // redundant node type
            log.debug("node type '" + aNta + "' is already contained.");
            includedCount++;
        }
    }
    if (includedCount == nta.length) {
        // total overlap, ignore
        return;
    }
    // named item definitions
    QItemDefinition[] defs = other.getNamedItemDefs();
    for (QItemDefinition def : defs) {
        if (includesNodeType(def.getDeclaringNodeType())) {
            // ignore redundant definitions
            continue;
        }
        Name name = def.getName();
        List<QItemDefinition> existingDefs = namedItemDefs.get(name);
        if (existingDefs != null) {
            if (existingDefs.size() > 0) {
                // there already exists at least one definition with that name
                for (QItemDefinition existingDef : existingDefs) {
                    // make sure none of them is auto-create
                    if (def.isAutoCreated() || existingDef.isAutoCreated()) {
                        // conflict
                        String msg = "The item definition for '" + name + "' in node type '" + def.getDeclaringNodeType() + "' conflicts with node type '" + existingDef.getDeclaringNodeType() + "': name collision with auto-create definition";
                        log.debug(msg);
                        throw new NodeTypeConflictException(msg);
                    }
                    // check ambiguous definitions
                    if (def.definesNode() == existingDef.definesNode()) {
                        if (!def.definesNode()) {
                            // property definition
                            QPropertyDefinition pd = (QPropertyDefinition) def;
                            QPropertyDefinition epd = (QPropertyDefinition) existingDef;
                            // compare type & multiValued flag
                            if (pd.getRequiredType() == epd.getRequiredType() && pd.isMultiple() == epd.isMultiple()) {
                                // conflict
                                String msg = "The property definition for '" + name + "' in node type '" + def.getDeclaringNodeType() + "' conflicts with node type '" + existingDef.getDeclaringNodeType() + "': ambiguous property definition";
                                log.debug(msg);
                                throw new NodeTypeConflictException(msg);
                            }
                        } else {
                            // child node definition
                            // conflict
                            String msg = "The child node definition for '" + name + "' in node type '" + def.getDeclaringNodeType() + "' conflicts with node type '" + existingDef.getDeclaringNodeType() + "': ambiguous child node definition";
                            log.debug(msg);
                            throw new NodeTypeConflictException(msg);
                        }
                    }
                }
            }
        } else {
            existingDefs = new ArrayList<QItemDefinition>();
            namedItemDefs.put(name, existingDefs);
        }
        existingDefs.add(def);
    }
    // residual item definitions
    defs = other.getUnnamedItemDefs();
    for (QItemDefinition def : defs) {
        if (includesNodeType(def.getDeclaringNodeType())) {
            // ignore redundant definitions
            continue;
        }
        for (QItemDefinition existing : unnamedItemDefs) {
            // compare with existing definition
            if (def.definesNode() == existing.definesNode()) {
                if (!def.definesNode()) {
                    // property definition
                    QPropertyDefinition pd = (QPropertyDefinition) def;
                    QPropertyDefinition epd = (QPropertyDefinition) existing;
                    // compare type & multiValued flag
                    if (pd.getRequiredType() == epd.getRequiredType() && pd.isMultiple() == epd.isMultiple()) {
                        // conflict
                        String msg = "A property definition in node type '" + def.getDeclaringNodeType() + "' conflicts with node type '" + existing.getDeclaringNodeType() + "': ambiguous residual property definition";
                        log.debug(msg);
                        throw new NodeTypeConflictException(msg);
                    }
                } else {
                    // child node definition
                    QNodeDefinition nd = (QNodeDefinition) def;
                    QNodeDefinition end = (QNodeDefinition) existing;
                    // compare required & default primary types
                    if (Arrays.equals(nd.getRequiredPrimaryTypes(), end.getRequiredPrimaryTypes()) && (nd.getDefaultPrimaryType() == null ? end.getDefaultPrimaryType() == null : nd.getDefaultPrimaryType().equals(end.getDefaultPrimaryType()))) {
                        // conflict
                        String msg = "A child node definition in node type '" + def.getDeclaringNodeType() + "' conflicts with node type '" + existing.getDeclaringNodeType() + "': ambiguous residual child node definition";
                        log.debug(msg);
                        throw new NodeTypeConflictException(msg);
                    }
                }
            }
        }
        unnamedItemDefs.add(def);
    }
    allNodeTypes.addAll(Arrays.asList(nta));
    if (supertype) {
        // implicit merge as result of inheritance
        // add other merged node types as supertypes
        nta = other.getMergedNodeTypes();
        inheritedNodeTypes.addAll(Arrays.asList(nta));
        // add supertypes of other merged node types as supertypes
        nta = other.getInheritedNodeTypes();
        inheritedNodeTypes.addAll(Arrays.asList(nta));
    } else {
        // explicit merge
        // merge with other merged node types
        nta = other.getMergedNodeTypes();
        mergedNodeTypes.addAll(Arrays.asList(nta));
        // add supertypes of other merged node types as supertypes
        nta = other.getInheritedNodeTypes();
        inheritedNodeTypes.addAll(Arrays.asList(nta));
    }
    // update 'orderable child nodes' attribute value (JCR-1947)
    if (other.hasOrderableChildNodes()) {
        orderableChildNodes = true;
    }
    // update 'primary item' attribute value (JCR-1947)
    if (primaryItemName == null && other.getPrimaryItemName() != null) {
        primaryItemName = other.getPrimaryItemName();
    }
}
Also used : QPropertyDefinition(org.apache.jackrabbit.spi.QPropertyDefinition) QItemDefinition(org.apache.jackrabbit.spi.QItemDefinition) QNodeDefinition(org.apache.jackrabbit.spi.QNodeDefinition) QValueConstraint(org.apache.jackrabbit.spi.QValueConstraint) Name(org.apache.jackrabbit.spi.Name)

Example 45 with QPropertyDefinition

use of org.apache.jackrabbit.spi.QPropertyDefinition in project jackrabbit by apache.

the class EffectiveNodeType method getNamedPropDefs.

public QPropertyDefinition[] getNamedPropDefs(Name name) {
    List<QItemDefinition> list = namedItemDefs.get(name);
    if (list == null || list.size() == 0) {
        return QPropertyDefinition.EMPTY_ARRAY;
    }
    ArrayList<QPropertyDefinition> defs = new ArrayList<QPropertyDefinition>(list.size());
    for (QItemDefinition def : list) {
        if (!def.definesNode()) {
            defs.add((QPropertyDefinition) def);
        }
    }
    if (defs.size() == 0) {
        return QPropertyDefinition.EMPTY_ARRAY;
    }
    return defs.toArray(new QPropertyDefinition[defs.size()]);
}
Also used : QPropertyDefinition(org.apache.jackrabbit.spi.QPropertyDefinition) ArrayList(java.util.ArrayList) QItemDefinition(org.apache.jackrabbit.spi.QItemDefinition)

Aggregations

QPropertyDefinition (org.apache.jackrabbit.spi.QPropertyDefinition)81 Name (org.apache.jackrabbit.spi.Name)32 ConstraintViolationException (javax.jcr.nodetype.ConstraintViolationException)22 QNodeDefinition (org.apache.jackrabbit.spi.QNodeDefinition)19 RepositoryException (javax.jcr.RepositoryException)14 QValue (org.apache.jackrabbit.spi.QValue)12 QItemDefinition (org.apache.jackrabbit.spi.QItemDefinition)9 QValueConstraint (org.apache.jackrabbit.spi.QValueConstraint)9 ArrayList (java.util.ArrayList)8 Value (javax.jcr.Value)7 InternalValue (org.apache.jackrabbit.core.value.InternalValue)7 ItemExistsException (javax.jcr.ItemExistsException)6 NodeId (org.apache.jackrabbit.core.id.NodeId)6 PropertyDefinition (javax.jcr.nodetype.PropertyDefinition)5 EffectiveNodeType (org.apache.jackrabbit.core.nodetype.EffectiveNodeType)5 PropertyState (org.apache.jackrabbit.core.state.PropertyState)5 QNodeTypeDefinition (org.apache.jackrabbit.spi.QNodeTypeDefinition)5 ValueConstraint (org.apache.jackrabbit.spi.commons.nodetype.constraint.ValueConstraint)5 NodeState (org.apache.jackrabbit.core.state.NodeState)4 NameException (org.apache.jackrabbit.spi.commons.conversion.NameException)4