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