Search in sources :

Example 1 with QNodeDefinition

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

the class NodeImpl method setPrimaryType.

/**
 * {@inheritDoc}
 */
public void setPrimaryType(String nodeTypeName) throws NoSuchNodeTypeException, VersionException, ConstraintViolationException, LockException, RepositoryException {
    // check state of this instance
    sanityCheck();
    // make sure this node is checked-out, neither protected nor locked and
    // the editing session has sufficient permission to change the primary type.
    int options = ItemValidator.CHECK_CHECKED_OUT | ItemValidator.CHECK_LOCK | ItemValidator.CHECK_CONSTRAINTS | ItemValidator.CHECK_HOLD;
    sessionContext.getItemValidator().checkModify(this, options, Permission.NODE_TYPE_MNGMT);
    final NodeState state = data.getNodeState();
    if (state.getParentId() == null) {
        String msg = "changing the primary type of the root node is not supported";
        log.debug(msg);
        throw new RepositoryException(msg);
    }
    Name ntName = sessionContext.getQName(nodeTypeName);
    if (ntName.equals(state.getNodeTypeName())) {
        log.debug("Node already has " + nodeTypeName + " as primary node type.");
        return;
    }
    NodeTypeManagerImpl ntMgr = sessionContext.getNodeTypeManager();
    NodeType nt = ntMgr.getNodeType(ntName);
    if (nt.isMixin()) {
        throw new ConstraintViolationException(nodeTypeName + ": not a primary node type.");
    } else if (nt.isAbstract()) {
        throw new ConstraintViolationException(nodeTypeName + ": is an abstract node type.");
    }
    // build effective node type of new primary type & existing mixin's
    // in order to detect conflicts
    NodeTypeRegistry ntReg = ntMgr.getNodeTypeRegistry();
    EffectiveNodeType entNew, entOld, entAll;
    try {
        entNew = ntReg.getEffectiveNodeType(ntName);
        entOld = ntReg.getEffectiveNodeType(state.getNodeTypeName());
        // try to build new effective node type (will throw in case of conflicts)
        entAll = ntReg.getEffectiveNodeType(ntName, state.getMixinTypeNames());
    } catch (NodeTypeConflictException ntce) {
        throw new ConstraintViolationException(ntce.getMessage());
    }
    // get applicable definition for this node using new primary type
    QNodeDefinition nodeDef;
    try {
        NodeImpl parent = (NodeImpl) getParent();
        nodeDef = parent.getApplicableChildNodeDefinition(getQName(), ntName).unwrap();
    } catch (RepositoryException re) {
        String msg = this + ": no applicable definition found in parent node's node type";
        log.debug(msg);
        throw new ConstraintViolationException(msg, re);
    }
    if (!nodeDef.equals(itemMgr.getDefinition(state).unwrap())) {
        onRedefine(nodeDef);
    }
    Set<QItemDefinition> oldDefs = new HashSet<QItemDefinition>(Arrays.asList(entOld.getAllItemDefs()));
    Set<QItemDefinition> newDefs = new HashSet<QItemDefinition>(Arrays.asList(entNew.getAllItemDefs()));
    Set<QItemDefinition> allDefs = new HashSet<QItemDefinition>(Arrays.asList(entAll.getAllItemDefs()));
    // added child item definitions
    Set<QItemDefinition> addedDefs = new HashSet<QItemDefinition>(newDefs);
    addedDefs.removeAll(oldDefs);
    // referential integrity check
    boolean referenceableOld = entOld.includesNodeType(NameConstants.MIX_REFERENCEABLE);
    boolean referenceableNew = entNew.includesNodeType(NameConstants.MIX_REFERENCEABLE);
    if (referenceableOld && !referenceableNew) {
        // node would become non-referenceable;
        // make sure no references exist
        PropertyIterator iter = getReferences();
        if (iter.hasNext()) {
            throw new ConstraintViolationException("the new primary type cannot be set as it would render " + "this node 'non-referenceable' while it is still being " + "referenced through at least one property of type REFERENCE");
        }
    }
    // do the actual modifications in content as mandated by the new primary type
    // modify the state of this node
    NodeState thisState = (NodeState) getOrCreateTransientItemState();
    thisState.setNodeTypeName(ntName);
    // set jcr:primaryType property
    internalSetProperty(NameConstants.JCR_PRIMARYTYPE, InternalValue.create(ntName));
    // walk through properties and child nodes and change definition as necessary
    // use temp set to avoid ConcurrentModificationException
    HashSet<Name> set = new HashSet<Name>(thisState.getPropertyNames());
    for (Name propName : set) {
        try {
            PropertyState propState = (PropertyState) stateMgr.getItemState(new PropertyId(thisState.getNodeId(), propName));
            if (!allDefs.contains(itemMgr.getDefinition(propState).unwrap())) {
                // redefine property if possible
                try {
                    PropertyImpl prop = (PropertyImpl) itemMgr.getItem(propState.getId());
                    if (prop.getDefinition().isProtected()) {
                        // remove 'orphaned' protected properties immediately
                        removeChildProperty(propName);
                        continue;
                    }
                    PropertyDefinitionImpl pdi = getApplicablePropertyDefinition(propName, propState.getType(), propState.isMultiValued(), false);
                    if (pdi.getRequiredType() != PropertyType.UNDEFINED && pdi.getRequiredType() != propState.getType()) {
                        // value conversion required
                        if (propState.isMultiValued()) {
                            // convert value
                            Value[] values = ValueHelper.convert(prop.getValues(), pdi.getRequiredType(), getSession().getValueFactory());
                            // redefine property
                            prop.onRedefine(pdi.unwrap());
                            // set converted values
                            prop.setValue(values);
                        } else {
                            // convert value
                            Value value = ValueHelper.convert(prop.getValue(), pdi.getRequiredType(), getSession().getValueFactory());
                            // redefine property
                            prop.onRedefine(pdi.unwrap());
                            // set converted values
                            prop.setValue(value);
                        }
                    } else {
                        // redefine property
                        prop.onRedefine(pdi.unwrap());
                    }
                    // update collection of added definitions
                    addedDefs.remove(pdi.unwrap());
                } catch (ValueFormatException vfe) {
                    // value conversion failed, remove it
                    removeChildProperty(propName);
                } catch (ConstraintViolationException cve) {
                    // no suitable definition found for this property,
                    // remove it
                    removeChildProperty(propName);
                }
            }
        } catch (ItemStateException ise) {
            String msg = propName + ": failed to retrieve property state";
            log.error(msg, ise);
            throw new RepositoryException(msg, ise);
        }
    }
    // use temp array to avoid ConcurrentModificationException
    ArrayList<ChildNodeEntry> list = new ArrayList<ChildNodeEntry>(thisState.getChildNodeEntries());
    // start from tail to avoid problems with same-name siblings
    for (int i = list.size() - 1; i >= 0; i--) {
        ChildNodeEntry entry = list.get(i);
        try {
            NodeState nodeState = (NodeState) stateMgr.getItemState(entry.getId());
            if (!allDefs.contains(itemMgr.getDefinition(nodeState).unwrap())) {
                // redefine node if possible
                try {
                    NodeImpl node = (NodeImpl) itemMgr.getItem(nodeState.getId());
                    if (node.getDefinition().isProtected()) {
                        // remove 'orphaned' protected child node immediately
                        removeChildNode(entry.getId());
                        continue;
                    }
                    NodeDefinitionImpl ndi = getApplicableChildNodeDefinition(entry.getName(), nodeState.getNodeTypeName());
                    // redefine node
                    node.onRedefine(ndi.unwrap());
                    // update collection of added definitions
                    addedDefs.remove(ndi.unwrap());
                } catch (ConstraintViolationException cve) {
                    // no suitable definition found for this child node,
                    // remove it
                    removeChildNode(entry.getId());
                }
            }
        } catch (ItemStateException ise) {
            String msg = entry.getName() + ": failed to retrieve node state";
            log.error(msg, ise);
            throw new RepositoryException(msg, ise);
        }
    }
    // type and at the same time were not present with the old nt
    for (QItemDefinition def : addedDefs) {
        if (def.isAutoCreated()) {
            if (def.definesNode()) {
                NodeDefinitionImpl ndi = ntMgr.getNodeDefinition((QNodeDefinition) def);
                createChildNode(def.getName(), (NodeTypeImpl) ndi.getDefaultPrimaryType(), null);
            } else {
                PropertyDefinitionImpl pdi = ntMgr.getPropertyDefinition((QPropertyDefinition) def);
                createChildProperty(pdi.unwrap().getName(), pdi.getRequiredType(), pdi);
            }
        }
    }
}
Also used : NodeState(org.apache.jackrabbit.core.state.NodeState) NodeTypeConflictException(org.apache.jackrabbit.core.nodetype.NodeTypeConflictException) ArrayList(java.util.ArrayList) Name(org.apache.jackrabbit.spi.Name) NodeDefinitionImpl(org.apache.jackrabbit.spi.commons.nodetype.NodeDefinitionImpl) ConstraintViolationException(javax.jcr.nodetype.ConstraintViolationException) NodeTypeManagerImpl(org.apache.jackrabbit.core.nodetype.NodeTypeManagerImpl) HashSet(java.util.HashSet) ChildNodeEntry(org.apache.jackrabbit.core.state.ChildNodeEntry) PropertyIterator(javax.jcr.PropertyIterator) PropertyDefinitionImpl(org.apache.jackrabbit.spi.commons.nodetype.PropertyDefinitionImpl) RepositoryException(javax.jcr.RepositoryException) QNodeDefinition(org.apache.jackrabbit.spi.QNodeDefinition) QItemDefinition(org.apache.jackrabbit.spi.QItemDefinition) PropertyState(org.apache.jackrabbit.core.state.PropertyState) PropertyId(org.apache.jackrabbit.core.id.PropertyId) InvalidItemStateException(javax.jcr.InvalidItemStateException) ItemStateException(org.apache.jackrabbit.core.state.ItemStateException) EffectiveNodeType(org.apache.jackrabbit.core.nodetype.EffectiveNodeType) EffectiveNodeType(org.apache.jackrabbit.core.nodetype.EffectiveNodeType) NodeType(javax.jcr.nodetype.NodeType) Value(javax.jcr.Value) InternalValue(org.apache.jackrabbit.core.value.InternalValue) ValueFormatException(javax.jcr.ValueFormatException) NodeTypeRegistry(org.apache.jackrabbit.core.nodetype.NodeTypeRegistry)

Example 2 with QNodeDefinition

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

the class ItemValidator method validate.

/**
 * Checks whether the given node state satisfies the constraints specified
 * by its primary and mixin node types. The following validations/checks are
 * performed:
 * <ul>
 * <li>check if its node type satisfies the 'required node types' constraint
 * specified in its definition</li>
 * <li>check if all 'mandatory' child items exist</li>
 * <li>for every property: check if the property value satisfies the
 * value constraints specified in the property's definition</li>
 * </ul>
 *
 * @param nodeState state of node to be validated
 * @throws ConstraintViolationException if any of the validations fail
 * @throws RepositoryException          if another error occurs
 */
public void validate(NodeState nodeState) throws ConstraintViolationException, RepositoryException {
    // effective primary node type
    NodeTypeRegistry registry = context.getNodeTypeRegistry();
    EffectiveNodeType entPrimary = registry.getEffectiveNodeType(nodeState.getNodeTypeName());
    // effective node type (primary type incl. mixins)
    EffectiveNodeType entPrimaryAndMixins = getEffectiveNodeType(nodeState);
    QNodeDefinition def = context.getItemManager().getDefinition(nodeState).unwrap();
    // check if primary type satisfies the 'required node types' constraint
    for (Name requiredPrimaryType : def.getRequiredPrimaryTypes()) {
        if (!entPrimary.includesNodeType(requiredPrimaryType)) {
            String msg = safeGetJCRPath(nodeState.getNodeId()) + ": missing required primary type " + requiredPrimaryType;
            log.debug(msg);
            throw new ConstraintViolationException(msg);
        }
    }
    // mandatory properties
    for (QPropertyDefinition pd : entPrimaryAndMixins.getMandatoryPropDefs()) {
        if (!nodeState.hasPropertyName(pd.getName())) {
            String msg = safeGetJCRPath(nodeState.getNodeId()) + ": mandatory property " + pd.getName() + " does not exist";
            log.debug(msg);
            throw new ConstraintViolationException(msg);
        }
    }
    // mandatory child nodes
    for (QItemDefinition cnd : entPrimaryAndMixins.getMandatoryNodeDefs()) {
        if (!nodeState.hasChildNodeEntry(cnd.getName())) {
            String msg = safeGetJCRPath(nodeState.getNodeId()) + ": mandatory child node " + cnd.getName() + " does not exist";
            log.debug(msg);
            throw new ConstraintViolationException(msg);
        }
    }
}
Also used : EffectiveNodeType(org.apache.jackrabbit.core.nodetype.EffectiveNodeType) QPropertyDefinition(org.apache.jackrabbit.spi.QPropertyDefinition) ConstraintViolationException(javax.jcr.nodetype.ConstraintViolationException) NodeTypeRegistry(org.apache.jackrabbit.core.nodetype.NodeTypeRegistry) QNodeDefinition(org.apache.jackrabbit.spi.QNodeDefinition) QItemDefinition(org.apache.jackrabbit.spi.QItemDefinition) Name(org.apache.jackrabbit.spi.Name)

Example 3 with QNodeDefinition

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

the class NodeStateEx method moveFrom.

/**
 * Moves the source node to this node using the given name.
 * @param src shareable source node
 * @param name name of new node
 * @param createShare if <code>true</code> a share is created instead.
 * @return child node
 * @throws RepositoryException if an error occurs
 */
public NodeStateEx moveFrom(NodeStateEx src, Name name, boolean createShare) throws RepositoryException {
    if (name == null) {
        name = src.getName();
    }
    EffectiveNodeType ent = getEffectiveNodeType();
    // (4) check for name collisions
    QNodeDefinition def;
    try {
        def = ent.getApplicableChildNodeDef(name, nodeState.getNodeTypeName(), ntReg);
    } catch (RepositoryException re) {
        String msg = "no definition found in parent node's node type for new node";
        throw new ConstraintViolationException(msg, re);
    }
    ChildNodeEntry cne = nodeState.getChildNodeEntry(name, 1);
    if (cne != null) {
        // check same-name sibling setting of new node
        if (!def.allowsSameNameSiblings()) {
            throw new ItemExistsException(getNodeId() + "/" + name);
        }
        NodeState existingChild;
        try {
            // check same-name sibling setting of existing node
            existingChild = (NodeState) stateMgr.getItemState(cne.getId());
        } catch (ItemStateException e) {
            throw new RepositoryException(e);
        }
        QNodeDefinition existingChildDef = ent.getApplicableChildNodeDef(cne.getName(), existingChild.getNodeTypeName(), ntReg);
        if (!existingChildDef.allowsSameNameSiblings()) {
            throw new ItemExistsException(existingChild.toString());
        }
    } else {
        // check if 'add' is allowed
        if (getDefinition().isProtected()) {
            String msg = "not allowed to modify a protected node";
            throw new ConstraintViolationException(msg);
        }
    }
    if (createShare) {
        // (5) do clone operation
        NodeId parentId = getNodeId();
        src.addShareParent(parentId);
        // attach to this parent
        nodeState.addChildNodeEntry(name, src.getNodeId());
        if (nodeState.getStatus() == ItemState.STATUS_EXISTING) {
            nodeState.setStatus(ItemState.STATUS_EXISTING_MODIFIED);
        }
        return new NodeStateEx(stateMgr, ntReg, src.getState(), name);
    } else {
        // detach from parent
        NodeStateEx parent = getNode(src.getParentId());
        parent.nodeState.removeChildNodeEntry(src.getNodeId());
        if (parent.nodeState.getStatus() == ItemState.STATUS_EXISTING) {
            parent.nodeState.setStatus(ItemState.STATUS_EXISTING_MODIFIED);
        }
        // attach to this parent
        nodeState.addChildNodeEntry(name, src.getNodeId());
        if (nodeState.getStatus() == ItemState.STATUS_EXISTING) {
            nodeState.setStatus(ItemState.STATUS_EXISTING_MODIFIED);
        }
        NodeState srcState = src.getState();
        srcState.setParentId(getNodeId());
        if (srcState.getStatus() == ItemState.STATUS_EXISTING) {
            srcState.setStatus(ItemState.STATUS_EXISTING_MODIFIED);
        }
        return new NodeStateEx(stateMgr, ntReg, srcState, name);
    }
}
Also used : EffectiveNodeType(org.apache.jackrabbit.core.nodetype.EffectiveNodeType) NodeState(org.apache.jackrabbit.core.state.NodeState) ItemExistsException(javax.jcr.ItemExistsException) ChildNodeEntry(org.apache.jackrabbit.core.state.ChildNodeEntry) NodeId(org.apache.jackrabbit.core.id.NodeId) ConstraintViolationException(javax.jcr.nodetype.ConstraintViolationException) RepositoryException(javax.jcr.RepositoryException) QNodeDefinition(org.apache.jackrabbit.spi.QNodeDefinition) ItemStateException(org.apache.jackrabbit.core.state.ItemStateException)

Example 4 with QNodeDefinition

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

the class TestAll method testRequiredTypeNode.

/**
 * Test for the <code>requiredPrimaryTypes</code> child node attributes.
 */
public void testRequiredTypeNode() {
    QNodeDefinition def = getChildNode("childNodeType", "requiredTypeNode");
    assertEquals("requiredTypeNode requiredPrimaryTypes", 2, def.getRequiredPrimaryTypes().length);
    Name[] types = def.getRequiredPrimaryTypes();
    Arrays.sort(types);
    assertEquals("requiredTypeNode requiredPrimaryTypes[0]", FACTORY.create(Name.NS_NT_URI, "base"), types[0]);
    assertEquals("requiredTypeNode requiredPrimaryTypes[1]", FACTORY.create(Name.NS_NT_URI, "unstructured"), types[1]);
}
Also used : QNodeDefinition(org.apache.jackrabbit.spi.QNodeDefinition) Name(org.apache.jackrabbit.spi.Name)

Example 5 with QNodeDefinition

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

the class TestAll method testSiblingNode.

/**
 * Test for the <code>allowsSameNameSiblings</code> child node attribute.
 */
public void testSiblingNode() {
    QNodeDefinition def = getChildNode("childNodeType", "siblingNode");
    assertEquals("siblingNode allowsSameNameSiblings", true, def.allowsSameNameSiblings());
}
Also used : QNodeDefinition(org.apache.jackrabbit.spi.QNodeDefinition)

Aggregations

QNodeDefinition (org.apache.jackrabbit.spi.QNodeDefinition)45 Name (org.apache.jackrabbit.spi.Name)25 QPropertyDefinition (org.apache.jackrabbit.spi.QPropertyDefinition)19 ConstraintViolationException (javax.jcr.nodetype.ConstraintViolationException)16 QItemDefinition (org.apache.jackrabbit.spi.QItemDefinition)9 QValueConstraint (org.apache.jackrabbit.spi.QValueConstraint)9 ArrayList (java.util.ArrayList)7 RepositoryException (javax.jcr.RepositoryException)7 EffectiveNodeType (org.apache.jackrabbit.core.nodetype.EffectiveNodeType)7 NodeId (org.apache.jackrabbit.core.id.NodeId)6 NodeState (org.apache.jackrabbit.core.state.NodeState)6 ItemExistsException (javax.jcr.ItemExistsException)5 ChildNodeEntry (org.apache.jackrabbit.core.state.ChildNodeEntry)5 HashSet (java.util.HashSet)4 ItemNotFoundException (javax.jcr.ItemNotFoundException)4 NoSuchNodeTypeException (javax.jcr.nodetype.NoSuchNodeTypeException)4 ItemStateException (org.apache.jackrabbit.core.state.ItemStateException)4 QValue (org.apache.jackrabbit.spi.QValue)4 ValueConstraint (org.apache.jackrabbit.spi.commons.nodetype.constraint.ValueConstraint)4 NodeDefinition (javax.jcr.nodetype.NodeDefinition)3