nodeimpl.java

来自「jsr170接口的java实现。是个apache的开源项目。」· Java 代码 · 共 1,586 行 · 第 1/5 页

JAVA
1,586
字号
        NodeState transientState = (NodeState) state;        NodeState persistentState = (NodeState) transientState.getOverlayedState();        if (persistentState == null) {            // this node is 'new'            persistentState = stateMgr.createNew(transientState);        }        synchronized (persistentState) {            // check staleness of transient state first            if (transientState.isStale()) {                String msg = safeGetJCRPath()                        + ": the node cannot be saved because it has been modified externally.";                log.debug(msg);                throw new InvalidItemStateException(msg);            }            // copy state from transient state:            // parent id's            persistentState.setParentId(transientState.getParentId());            // mixin types            persistentState.setMixinTypeNames(transientState.getMixinTypeNames());            // id of definition            persistentState.setDefinitionId(transientState.getDefinitionId());            // child node entries            persistentState.setChildNodeEntries(transientState.getChildNodeEntries());            // property entries            persistentState.setPropertyNames(transientState.getPropertyNames());            // make state persistent            stateMgr.store(persistentState);        }        // tell state manager to disconnect item state        stateMgr.disconnectTransientItemState(transientState);        // swap transient state with persistent state        state = persistentState;        // reset status        status = STATUS_NORMAL;    }    protected void restoreTransient(NodeState transientState)            throws RepositoryException {        NodeState thisState = (NodeState) getOrCreateTransientItemState();        if (transientState.getStatus() == ItemState.STATUS_NEW                && thisState.getStatus() != ItemState.STATUS_NEW) {            thisState.setStatus(ItemState.STATUS_NEW);            stateMgr.disconnectTransientItemState(thisState);        }        // reapply transient changes        thisState.setParentId(transientState.getParentId());        thisState.setMixinTypeNames(transientState.getMixinTypeNames());        thisState.setDefinitionId(transientState.getDefinitionId());        thisState.setChildNodeEntries(transientState.getChildNodeEntries());        thisState.setPropertyNames(transientState.getPropertyNames());    }    /**     * Same as {@link Node#addMixin(String)} except that it takes a     * <code>QName</code> instead of a <code>String</code>.     *     * @see Node#addMixin(String)     */    public void addMixin(QName mixinName)            throws NoSuchNodeTypeException, VersionException,            ConstraintViolationException, LockException, RepositoryException {        // check state of this instance        sanityCheck();        // make sure this node is checked-out        if (!internalIsCheckedOut()) {            String msg = safeGetJCRPath() + ": cannot add a mixin node type to a checked-in node";            log.debug(msg);            throw new VersionException(msg);        }        // check protected flag        if (definition.isProtected()) {            String msg = safeGetJCRPath() + ": cannot add a mixin node type to a protected node";            log.debug(msg);            throw new ConstraintViolationException(msg);        }        // check lock status        checkLock();        NodeTypeManagerImpl ntMgr = session.getNodeTypeManager();        NodeTypeImpl mixin = ntMgr.getNodeType(mixinName);        if (!mixin.isMixin()) {            throw new RepositoryException(mixinName + ": not a mixin node type");        }        NodeTypeImpl primaryType = ntMgr.getNodeType(primaryTypeName);        if (primaryType.isDerivedFrom(mixinName)) {            throw new RepositoryException(mixinName + ": already contained in primary node type");        }        // build effective node type of mixin's & primary type in order to detect conflicts        NodeTypeRegistry ntReg = ntMgr.getNodeTypeRegistry();        EffectiveNodeType entExisting;        try {            // existing mixin's            HashSet set = new HashSet(((NodeState) state).getMixinTypeNames());            // primary type            set.add(primaryTypeName);            // build effective node type representing primary type including existing mixin's            entExisting = ntReg.getEffectiveNodeType((QName[]) set.toArray(new QName[set.size()]));            if (entExisting.includesNodeType(mixinName)) {                throw new RepositoryException(mixinName + ": already contained in mixin types");            }            // add new mixin            set.add(mixinName);            // try to build new effective node type (will throw in case of conflicts)            ntReg.getEffectiveNodeType((QName[]) set.toArray(new QName[set.size()]));        } catch (NodeTypeConflictException ntce) {            throw new ConstraintViolationException(ntce.getMessage());        }        // do the actual modifications implied by the new mixin;        // try to revert the changes in case an exception occurs        try {            // modify the state of this node            NodeState thisState = (NodeState) getOrCreateTransientItemState();            // add mixin name            Set mixins = new HashSet(thisState.getMixinTypeNames());            mixins.add(mixinName);            thisState.setMixinTypeNames(mixins);            // set jcr:mixinTypes property            setMixinTypesProperty(mixins);            // add 'auto-create' properties defined in mixin type            PropertyDefinition[] pda = mixin.getAutoCreatedPropertyDefinitions();            for (int i = 0; i < pda.length; i++) {                PropertyDefinitionImpl pd = (PropertyDefinitionImpl) pda[i];                // make sure that the property is not already defined by primary type                // or existing mixin's                NodeTypeImpl declaringNT = (NodeTypeImpl) pd.getDeclaringNodeType();                if (!entExisting.includesNodeType(declaringNT.getQName())) {                    createChildProperty(pd.getQName(), pd.getRequiredType(), pd);                }            }            // recursively add 'auto-create' child nodes defined in mixin type            NodeDefinition[] nda = mixin.getAutoCreatedNodeDefinitions();            for (int i = 0; i < nda.length; i++) {                NodeDefinitionImpl nd = (NodeDefinitionImpl) nda[i];                // make sure that the child node is not already defined by primary type                // or existing mixin's                NodeTypeImpl declaringNT = (NodeTypeImpl) nd.getDeclaringNodeType();                if (!entExisting.includesNodeType(declaringNT.getQName())) {                    createChildNode(nd.getQName(), nd, (NodeTypeImpl) nd.getDefaultPrimaryType(), null);                }            }        } catch (RepositoryException re) {            // try to undo the modifications by removing the mixin            try {                removeMixin(mixinName);            } catch (RepositoryException re1) {                // silently ignore & fall through            }            throw re;        }    }    /**     * Same as {@link Node#removeMixin(String)} except that it takes a     * <code>QName</code> instead of a <code>String</code>.     *     * @see Node#removeMixin(String)     */    public void removeMixin(QName mixinName)            throws NoSuchNodeTypeException, VersionException,            ConstraintViolationException, LockException, RepositoryException {        // check state of this instance        sanityCheck();        // make sure this node is checked-out        if (!internalIsCheckedOut()) {            String msg = safeGetJCRPath()                    + ": cannot remove a mixin node type from a checked-in node";            log.debug(msg);            throw new VersionException(msg);        }        // check protected flag        if (definition.isProtected()) {            String msg = safeGetJCRPath()                    + ": cannot remove a mixin node type from a protected node";            log.debug(msg);            throw new ConstraintViolationException(msg);        }        // check lock status        checkLock();        // check if mixin is assigned        if (!((NodeState) state).getMixinTypeNames().contains(mixinName)) {            throw new NoSuchNodeTypeException();        }        NodeTypeManagerImpl ntMgr = session.getNodeTypeManager();        NodeTypeRegistry ntReg = ntMgr.getNodeTypeRegistry();        // build effective node type of remaining mixin's & primary type        Set remainingMixins = new HashSet(((NodeState) state).getMixinTypeNames());        // remove name of target mixin        remainingMixins.remove(mixinName);        EffectiveNodeType entRemaining;        try {            // remaining mixin's            HashSet set = new HashSet(remainingMixins);            // primary type            set.add(primaryTypeName);            // build effective node type representing primary type including remaining mixin's            entRemaining = ntReg.getEffectiveNodeType((QName[]) set.toArray(new QName[set.size()]));        } catch (NodeTypeConflictException ntce) {            throw new ConstraintViolationException(ntce.getMessage());        }        /**         * mix:referenceable needs special handling because it has         * special semantics:         * it can only be removed if there no more references to this node         */        NodeTypeImpl mixin = ntMgr.getNodeType(mixinName);        if ((QName.MIX_REFERENCEABLE.equals(mixinName)                || mixin.isDerivedFrom(QName.MIX_REFERENCEABLE))                && !entRemaining.includesNodeType(QName.MIX_REFERENCEABLE)) {            // removing this mixin would effectively remove mix:referenceable:            // make sure no references exist            PropertyIterator iter = getReferences();            if (iter.hasNext()) {                throw new ConstraintViolationException(mixinName + " can not be removed: the node is being referenced"                        + " through at least one property of type REFERENCE");            }        }        // modify the state of this node        NodeState thisState = (NodeState) getOrCreateTransientItemState();        thisState.setMixinTypeNames(remainingMixins);        // set jcr:mixinTypes property        setMixinTypesProperty(remainingMixins);        // shortcut        if (mixin.getChildNodeDefinitions().length == 0                && mixin.getPropertyDefinitions().length == 0) {            // the node type has neither property nor child node definitions,            // i.e. we're done            return;        }        // walk through properties and child nodes and remove those that have been        // defined by the specified mixin type        // use temp set to avoid ConcurrentModificationException        HashSet set = new HashSet(thisState.getPropertyNames());        for (Iterator iter = set.iterator(); iter.hasNext();) {            QName propName = (QName) iter.next();            PropertyImpl prop = (PropertyImpl) itemMgr.getItem(                    new PropertyId(thisState.getNodeId(), propName));            // check if property has been defined by mixin type (or one of its supertypes)            NodeTypeImpl declaringNT = (NodeTypeImpl) prop.getDefinition().getDeclaringNodeType();            if (!entRemaining.includesNodeType(declaringNT.getQName())) {                // the remaining effective node type doesn't include the                // node type that declared this property, it is thus safe                // to remove it                removeChildProperty(propName);            }        }        // use temp array to avoid ConcurrentModificationException        ArrayList list = new ArrayList(thisState.getChildNodeEntries());        // start from tail to avoid problems with same-name siblings        for (int i = list.size() - 1; i >= 0; i--) {            NodeState.ChildNodeEntry entry = (NodeState.ChildNodeEntry) list.get(i);            NodeImpl node = (NodeImpl) itemMgr.getItem(entry.getId());            // check if node has been defined by mixin type (or one of its supertypes)            NodeTypeImpl declaringNT = (NodeTypeImpl) node.getDefinition().getDeclaringNodeType();            if (!entRemaining.includesNodeType(declaringNT.getQName())) {                // the remaining effective node type doesn't include the                // node type that declared this child node, it is thus safe                // to remove it                removeChildNode(entry.getName(), entry.getIndex());            }        }    }    /**     * Same as {@link Node#isNodeType(String)} except that it takes a     * <code>QName</code> instead of a <code>String</code>.     *     * @param ntName name of node type     * @return <code>true</code> if this node is of the specified node type;     *         otherwise <code>false</code>     */    public boolean isNodeType(QName ntName) throws RepositoryException {        // check state of this instance        sanityCheck();        // first do trivial checks without using type hierarchy        if (ntName.equals(primaryTypeName)) {            return true;        }        Set mixins = ((NodeState) state).getMixinTypeNames();        if (mixins.contains(ntName)) {            return true;        }        // check effective node type        return getEffectiveNodeType(mixins).includesNodeType(ntName);    }    /**     * Returns the (internal) uuid of this node.     *     * @return the uuid of this node     */    public UUID internalGetUUID() {        return ((NodeId) id).getUUID();

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?