boolean referenceableOld = entOld.includesNodeType(NameConstants.MIX_REFERENCEABLE);
boolean referenceableNew = entNew.includesNodeType(NameConstants.MIX_REFERENCEABLE);
if (referenceableOld && !referenceableNew) {
// node would become non-referenceable;
// make sure no references exist
PropertyIterator iter = getReferences();
if (iter.hasNext()) {
throw new ConstraintViolationException(
"the new primary type cannot be set as it would render "
+ "this node 'non-referenceable' while it is still being "
+ "referenced through at least one property of type REFERENCE");
}
}
// do the actual modifications in content as mandated by the new primary type
// modify the state of this node
NodeState thisState = (NodeState) getOrCreateTransientItemState();
thisState.setNodeTypeName(ntName);
// set jcr:primaryType property
internalSetProperty(NameConstants.JCR_PRIMARYTYPE, InternalValue.create(ntName));
// walk through properties and child nodes and change definition as necessary
// use temp set to avoid ConcurrentModificationException
HashSet<Name> set = new HashSet<Name>(thisState.getPropertyNames());
for (Name propName : set) {
try {
PropertyState propState =
(PropertyState) stateMgr.getItemState(
new PropertyId(thisState.getNodeId(), propName));
if (!allDefs.contains(ntReg.getPropDef(propState.getDefinitionId()))) {
// try to find new applicable definition first and
// 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);
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());
}
// update collection of added definitions
addedDefs.remove(pdi.unwrap());
} catch (ValueFormatException vfe) {
// value conversion failed, remove it
removeChildProperty(propName);
} catch (ConstraintViolationException cve) {
// no suitable definition found for this property,
// remove it
removeChildProperty(propName);
}
}
} catch (ItemStateException ise) {
String msg = propName + ": failed to retrieve property state";
log.error(msg, ise);
throw new RepositoryException(msg, ise);
}
}
// use temp array to avoid ConcurrentModificationException
ArrayList<ChildNodeEntry> 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 = list.get(i);
try {
NodeState nodeState = (NodeState) stateMgr.getItemState(entry.getId());
if (!allDefs.contains(ntReg.getNodeDef(nodeState.getDefinitionId()))) {
// 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
node.onRedefine(ndi.unwrap().getId());
// update collection of added definitions
addedDefs.remove(ndi.unwrap());
} catch (ConstraintViolationException cve) {
// no suitable definition found for this child node,
// remove it
removeChildNode(entry.getName(), entry.getIndex());
}
}
} catch (ItemStateException ise) {
String msg = entry.getName() + ": failed to retrieve node state";
log.error(msg, ise);
throw new RepositoryException(msg, ise);
}
}
// create items that are defined as auto-created by the new primary node
// type and at the same time were not present with the old nt
for (Iterator<ItemDef> iter = addedDefs.iterator(); iter.hasNext();) {
ItemDef def = iter.next();
if (def.isAutoCreated()) {
if (def.definesNode()) {
NodeDefinitionImpl ndi = ntMgr.getNodeDefinition(((NodeDef) def).getId());
createChildNode(ndi.getQName(), ndi, (NodeTypeImpl) ndi.getDefaultPrimaryType(), null);
} else {