// 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