shareditemstatemanager.java

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

JAVA
1,450
字号
    /**     * Checks if this item state manager has the given item state without     * considering the virtual item state managers.     */    private boolean hasNonVirtualItemState(ItemId id) {        if (cache.isCached(id)) {            return true;        }        try {            if (id.denotesNode()) {                return persistMgr.exists((NodeId) id);            } else {                return persistMgr.exists((PropertyId) id);            }        } catch (ItemStateException ise) {            return false;        }    }    /**     * Create a new item state instance     *     * @param other other state associated with new instance     * @return new node state instance     */    private ItemState createInstance(ItemState other) {        if (other.isNode()) {            NodeState ns = (NodeState) other;            return createInstance(ns.getNodeId(), ns.getNodeTypeName(), ns.getParentId());        } else {            PropertyState ps = (PropertyState) other;            return createInstance(ps.getName(), ps.getParentId());        }    }    /**     * Create a new property state instance     *     * @param propName   property name     * @param parentId parent Id     * @return new property state instance     */    private PropertyState createInstance(QName propName, NodeId parentId) {        PropertyState state = persistMgr.createNew(new PropertyId(parentId, propName));        state.setStatus(ItemState.STATUS_NEW);        state.setContainer(this);        return state;    }    /**     * Load item state from persistent storage.     *     * @param id item id     * @return item state     */    private ItemState loadItemState(ItemId id)            throws NoSuchItemStateException, ItemStateException {        ItemState state;        if (id.denotesNode()) {            state = persistMgr.load((NodeId) id);        } else {            state = persistMgr.load((PropertyId) id);        }        return state;    }    /**     * Determines whether the specified node is <i>referenceable</i>, i.e.     * whether the mixin type <code>mix:referenceable</code> is either     * directly assigned or indirectly inherited.     *     * @param state node state to check     * @return true if the specified node is <i>referenceable</i>, false otherwise.     * @throws ItemStateException if an error occurs     */    private boolean isReferenceable(NodeState state) throws ItemStateException {        // shortcut: check some wellknown built-in types first        QName primary = state.getNodeTypeName();        Set mixins = state.getMixinTypeNames();        if (mixins.contains(QName.MIX_REFERENCEABLE)                || mixins.contains(QName.MIX_VERSIONABLE)                || primary.equals(QName.NT_RESOURCE)) {            return true;        }        // build effective node type        QName[] types = new QName[mixins.size() + 1];        mixins.toArray(types);        // primary type        types[types.length - 1] = primary;        try {            return ntReg.getEffectiveNodeType(types).includesNodeType(QName.MIX_REFERENCEABLE);        } catch (NodeTypeConflictException ntce) {            String msg = "internal error: failed to build effective node type for node "                    + state.getNodeId();            log.debug(msg);            throw new ItemStateException(msg, ntce);        } catch (NoSuchNodeTypeException nsnte) {            String msg = "internal error: failed to build effective node type for node "                    + state.getNodeId();            log.debug(msg);            throw new ItemStateException(msg, nsnte);        }    }    /**     * Updates the target node references collections based on the modifications     * in the change log (i.e. added/removed/modified <code>REFERENCE</code>     * properties).     * <p/>     * <b>Important node:</b> For consistency reasons this method must only be     * called <i>once</i> per change log and the change log should not be modified     * anymore afterwards.     *     * @param changes change log     * @param virtualProvider virtual provider that may already contain a     *                        node references object     * @throws ItemStateException if an error occurs     */    protected void updateReferences(ChangeLog changes,                                    VirtualItemStateProvider virtualProvider)            throws ItemStateException {        // process added REFERENCE properties        for (Iterator iter = changes.addedStates(); iter.hasNext();) {            ItemState state = (ItemState) iter.next();            if (!state.isNode()) {                PropertyState prop = (PropertyState) state;                if (prop.getType() == PropertyType.REFERENCE) {                    // this is a new REFERENCE property:                    // add the new 'reference'                    InternalValue[] vals = prop.getValues();                    for (int i = 0; vals != null && i < vals.length; i++) {                        NodeReferencesId refsId = new NodeReferencesId(                                (UUID) vals[i].internalValue());                        if (virtualProvider != null                                && virtualProvider.hasNodeReferences(refsId)) {                            continue;                        }                        NodeReferences refs =                                getOrCreateNodeReferences(refsId, changes);                        // add reference                        refs.addReference(prop.getPropertyId());                        // update change log                        changes.modified(refs);                    }                }            }        }        // process modified REFERENCE properties        for (Iterator iter = changes.modifiedStates(); iter.hasNext();) {            ItemState state = (ItemState) iter.next();            if (!state.isNode()) {                PropertyState newProp = (PropertyState) state;                PropertyState oldProp =                        (PropertyState) getItemState(state.getId());                // check old type                if (oldProp.getType() == PropertyType.REFERENCE) {                    // this is a modified REFERENCE property:                    // remove the old 'reference' from the target                    InternalValue[] vals = oldProp.getValues();                    for (int i = 0; vals != null && i < vals.length; i++) {                        NodeReferencesId refsId = new NodeReferencesId(                                (UUID) vals[i].internalValue());                        if (virtualProvider != null                                && virtualProvider.hasNodeReferences(refsId)) {                            continue;                        }                        // either get node references from change log or load from                        // persistence manager                        NodeReferences refs = changes.get(refsId);                        if (refs == null) {                            refs = getNodeReferences(refsId);                        }                        // remove reference                        refs.removeReference(oldProp.getPropertyId());                        // update change log                        changes.modified(refs);                    }                }                // check new type                if (newProp.getType() == PropertyType.REFERENCE) {                    // this is a modified REFERENCE property:                    // add the new 'reference' to the target                    InternalValue[] vals = newProp.getValues();                    for (int i = 0; vals != null && i < vals.length; i++) {                        NodeReferencesId refsId = new NodeReferencesId(                                (UUID) vals[i].internalValue());                        if (virtualProvider != null                                && virtualProvider.hasNodeReferences(refsId)) {                            continue;                        }                        NodeReferences refs =                                getOrCreateNodeReferences(refsId, changes);                        // add reference                        refs.addReference(newProp.getPropertyId());                        // update change log                        changes.modified(refs);                    }                }            }        }        // process removed REFERENCE properties        for (Iterator iter = changes.deletedStates(); iter.hasNext();) {            ItemState state = (ItemState) iter.next();            if (!state.isNode()) {                PropertyState prop = (PropertyState) state;                if (prop.getType() == PropertyType.REFERENCE) {                    // this is a removed REFERENCE property:                    // remove the 'reference' from the target                    InternalValue[] vals = prop.getValues();                    for (int i = 0; vals != null && i < vals.length; i++) {                        NodeReferencesId refsId = new NodeReferencesId(                                (UUID) vals[i].internalValue());                        if (virtualProvider != null                                && virtualProvider.hasNodeReferences(refsId)) {                            continue;                        }                        // either get node references from change log or                        // load from persistence manager                        NodeReferences refs = changes.get(refsId);                        if (refs == null) {                            refs = getNodeReferences(refsId);                        }                        // remove reference                        refs.removeReference(prop.getPropertyId());                        // update change log                        changes.modified(refs);                    }                }            }        }    }    /**     * Returns a node references object using the following rules:<p/>     * <ul>     * <li>1. return a modified instance from the change log (if one exists)</li>     * <li>2. return an existing instance from <i>this</i> item state manager     * (if one exists)</li>     * <li>3. create and return a new instance</li>     * </ul>     *     * @param refsId  node references id     * @param changes change log     * @return a node references object     * @throws ItemStateException if an error occurs     */    private NodeReferences getOrCreateNodeReferences(NodeReferencesId refsId,                                                     ChangeLog changes)            throws ItemStateException {        // check change log        NodeReferences refs = changes.get(refsId);        if (refs == null) {            // not yet in change log:            // either load existing or create new            if (hasNodeReferences(refsId)) {                refs = getNodeReferences(refsId);            } else {                refs = new NodeReferences(refsId);            }        }        return refs;    }    /**     * Verifies that     * <ul>     * <li>no referenceable nodes are deleted if they are still being referenced</li>     * <li>targets of modified node references exist</li>     * </ul>     *     * @param changes change log     * @throws ReferentialIntegrityException if a new or modified REFERENCE     *                                       property refers to a non-existent     *                                       target or if a removed node is still     *                                       being referenced     * @throws ItemStateException            if another error occurs     */    protected void checkReferentialIntegrity(ChangeLog changes)            throws ReferentialIntegrityException, ItemStateException {        // check whether removed referenceable nodes are still being referenced        for (Iterator iter = changes.deletedStates(); iter.hasNext();) {            ItemState state = (ItemState) iter.next();            if (state.isNode()) {                NodeState node = (NodeState) state;                if (isReferenceable(node)) {                    NodeReferencesId refsId = new NodeReferencesId(node.getNodeId());                    // either get node references from change log or                    // load from persistence manager                    NodeReferences refs = changes.get(refsId);                    if (refs == null) {                        if (!hasNodeReferences(refsId)) {                            continue;                        }                        refs = getNodeReferences(refsId);                    }                    // in some versioning operations (such as restore) a node                    // may actually be deleted and then again added with the                    // same UUID, i.e. the node is still referenceable.                    if (refs.hasReferences() && !changes.has(node.getNodeId())) {                        String msg = node.getNodeId()                                + ": the node cannot be removed because it is still being referenced.";                        log.debug(msg);                        throw new ReferentialIntegrityException(msg);                    }                }            }        }        // check whether targets of modified node references exist        for (Iterator iter = changes.modifiedRefs(); iter.hasNext();) {            NodeReferences refs = (NodeReferences) iter.next();            NodeId id = refs.getTargetId();            // no need to check existence of target if there are no references            if (refs.hasReferences()) {                // please note:                // virtual providers are indirectly checked via 'hasItemState()'                if (!changes.has(id) && !hasItemState(id)) {                    String msg = "Target node " + id                            + " of REFERENCE property does not exist";                    log.debug(msg);                    throw new ReferentialIntegrityException(msg);                }            }        }    }    /**     * Acquires the read lock on this item state manager.     *     * @throws ItemStateException if the read lock cannot be acquired.     */    private void acquireReadLock() throws ItemStateException {        try {            rwLock.readLock().acquire();        } catch (InterruptedException e) {            throw new ItemStateException("Interrupted while acquiring read lock");        }    }    /**     * Acquires the write lock on this item state manager.     *     * @throws ItemStateException if the write lock cannot be acquired.     */    private void acquireWriteLock() throws ItemStateException {        try {            rwLock.writeLock().acquire();        } catch (InterruptedException e) {            throw new ItemStateException("Interrupted while acquiring write lock");        }    }}

⌨️ 快捷键说明

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