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 + -
显示快捷键?