You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by st...@apache.org on 2009/06/10 18:10:18 UTC
svn commit: r783412 - in
/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core:
BatchedItemOperations.java NodeImpl.java
Author: stefan
Date: Wed Jun 10 16:10:16 2009
New Revision: 783412
URL: http://svn.apache.org/viewvc?rev=783412&view=rev
Log:
JCR-2130: Node.removeMixin() should not remove valid items
Modified:
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/BatchedItemOperations.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/NodeImpl.java
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/BatchedItemOperations.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/BatchedItemOperations.java?rev=783412&r1=783411&r2=783412&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/BatchedItemOperations.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/BatchedItemOperations.java Wed Jun 10 16:10:16 2009
@@ -1524,6 +1524,7 @@
// compute system generated values
Name declaringNT = def.getDeclaringNodeType();
Name name = def.getName();
+ // TODO JCR-2116: Built-In Node Types; => adapt to JCR 2.0 built-in node types (mix:created, etc)
if (NameConstants.MIX_REFERENCEABLE.equals(declaringNT)) {
// mix:referenceable node type
if (NameConstants.JCR_UUID.equals(name)) {
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/NodeImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/NodeImpl.java?rev=783412&r1=783411&r2=783412&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/NodeImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/NodeImpl.java Wed Jun 10 16:10:16 2009
@@ -300,6 +300,7 @@
// compute system generated values
NodeTypeImpl nt = (NodeTypeImpl) def.getDeclaringNodeType();
+ // TODO JCR-2116: Built-In Node Types; => adapt to JCR 2.0 built-in node types (mix:created, etc)
if (nt.getQName().equals(NameConstants.MIX_REFERENCEABLE)) {
// mix:referenceable node type
if (name.equals(NameConstants.JCR_UUID)) {
@@ -1132,13 +1133,13 @@
NodeTypeRegistry ntReg = ntMgr.getNodeTypeRegistry();
// build effective node type of remaining mixin's & primary type
- Set remainingMixins = new HashSet(state.getMixinTypeNames());
+ Set remainingMixins = new HashSet<Name>(state.getMixinTypeNames());
// remove name of target mixin
remainingMixins.remove(mixinName);
- EffectiveNodeType entRemaining;
+ EffectiveNodeType entResulting;
try {
// build effective node type representing primary type including remaining mixin's
- entRemaining = ntReg.getEffectiveNodeType(
+ entResulting = ntReg.getEffectiveNodeType(
state.getNodeTypeName(), remainingMixins);
} catch (NodeTypeConflictException e) {
throw new ConstraintViolationException(e.getMessage(), e);
@@ -1152,7 +1153,7 @@
NodeTypeImpl mixin = ntMgr.getNodeType(mixinName);
if ((NameConstants.MIX_REFERENCEABLE.equals(mixinName)
|| mixin.isDerivedFrom(NameConstants.MIX_REFERENCEABLE))
- && !entRemaining.includesNodeType(NameConstants.MIX_REFERENCEABLE)) {
+ && !entResulting.includesNodeType(NameConstants.MIX_REFERENCEABLE)) {
// removing this mixin would effectively remove mix:referenceable:
// make sure no references exist
PropertyIterator iter = getReferences();
@@ -1168,7 +1169,7 @@
*/
if ((NameConstants.MIX_LOCKABLE.equals(mixinName)
|| mixin.isDerivedFrom(NameConstants.MIX_LOCKABLE))
- && !entRemaining.includesNodeType(NameConstants.MIX_LOCKABLE)
+ && !entResulting.includesNodeType(NameConstants.MIX_LOCKABLE)
&& isLocked()) {
throw new ConstraintViolationException(mixinName + " can not be removed: the node is locked.");
}
@@ -1189,27 +1190,76 @@
return;
}
- // walk through properties and child nodes and remove those that have
- // been defined by the specified mixin type
+ // walk through properties and child nodes and remove those that aren't
+ // accomodated by the resulting new effective node type (see JCR-2130)
boolean success = false;
try {
// use temp set to avoid ConcurrentModificationException
- HashSet set = new HashSet(thisState.getPropertyNames());
+ HashSet set = new HashSet<Name>(thisState.getPropertyNames());
for (Iterator iter = set.iterator(); iter.hasNext();) {
Name propName = (Name) iter.next();
PropertyState propState = (PropertyState) stateMgr.getItemState(new PropertyId(thisState.getNodeId(), propName));
// check if property has been defined by mixin type (or one of its supertypes)
PropertyDefinition def = ntMgr.getPropertyDefinition(propState.getDefinitionId());
NodeTypeImpl declaringNT = (NodeTypeImpl) def.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);
+ if (!entResulting.includesNodeType(declaringNT.getQName())) {
+ // the resulting effective node type doesn't include the
+ // node type that declared this property
+
+ // try to find new applicable definition first and
+ // redefine property if possible (JCR-2130)
+ 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(),
+ session.getValueFactory());
+ // redefine property
+ prop.onRedefine(pdi.unwrap().getId());
+ // set converted values
+ prop.setValue(values);
+ } else {
+ // convert value
+ Value value =
+ ValueHelper.convert(
+ prop.getValue(),
+ pdi.getRequiredType(),
+ session.getValueFactory());
+ // redefine property
+ prop.onRedefine(pdi.unwrap().getId());
+ // set converted values
+ prop.setValue(value);
+ }
+ } else {
+ // redefine property
+ prop.onRedefine(pdi.unwrap().getId());
+ }
+ } catch (ValueFormatException vfe) {
+ // value conversion failed, remove it
+ removeChildProperty(propName);
+ } catch (ConstraintViolationException cve) {
+ // no suitable definition found for this property,
+ // remove it
+ removeChildProperty(propName);
+ }
}
}
// use temp array to avoid ConcurrentModificationException
- ArrayList list = new ArrayList(thisState.getChildNodeEntries());
+ ArrayList 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 = (ChildNodeEntry) list.get(i);
@@ -1217,11 +1267,27 @@
NodeDefinition def = ntMgr.getNodeDefinition(nodeState.getDefinitionId());
// check if node has been defined by mixin type (or one of its supertypes)
NodeTypeImpl declaringNT = (NodeTypeImpl) def.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());
+ if (!entResulting.includesNodeType(declaringNT.getQName())) {
+ // the resulting effective node type doesn't include the
+ // node type that declared this child node
+
+ try {
+ NodeImpl node = (NodeImpl) itemMgr.getItem(nodeState.getId());
+ if (node.getDefinition().isProtected()) {
+ // remove 'orphaned' protected child node immediately
+ removeChildNode(entry.getName(), entry.getIndex());
+ continue;
+ }
+ NodeDefinitionImpl ndi = getApplicableChildNodeDefinition(
+ entry.getName(),
+ nodeState.getNodeTypeName());
+ // redefine node
+ node.onRedefine(ndi.unwrap().getId());
+ } catch (ConstraintViolationException cve) {
+ // no suitable definition found for this child node,
+ // remove it
+ removeChildNode(entry.getName(), entry.getIndex());
+ }
}
}
success = true;
@@ -4768,6 +4834,11 @@
// 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);
@@ -4830,11 +4901,16 @@
// try to find new applicable definition first and
// redefine node if possible
try {
+ NodeImpl node = (NodeImpl) itemMgr.getItem(nodeState.getId());
+ if (node.getDefinition().isProtected()) {
+ // remove 'orphaned' protected child node immediately
+ removeChildNode(entry.getName(), entry.getIndex());
+ continue;
+ }
NodeDefinitionImpl ndi = getApplicableChildNodeDefinition(
entry.getName(),
nodeState.getNodeTypeName());
// redefine node
- NodeImpl node = (NodeImpl) itemMgr.getItem(nodeState.getId());
node.onRedefine(ndi.unwrap().getId());
// update collection of added definitions
addedDefs.remove(ndi.unwrap());