}
if (itemState.isNode()) {
// the transient item is a node
NodeState nodeState = (NodeState) itemState;
ItemId id = nodeState.getNodeId();
NodeDefinition nodeDef = (NodeDefinition) def;
// primary type
NodeTypeImpl pnt = ntMgr.getNodeType(nodeState.getNodeTypeName());
// effective node type (primary type incl. mixins)
EffectiveNodeType ent = getEffectiveNodeType(nodeState);
/**
* if the transient node was added (i.e. if it is 'new') or if
* its primary type has changed, check its node type against the
* required node type in its definition
*/
if (nodeState.getStatus() == ItemState.STATUS_NEW
|| !nodeState.getNodeTypeName().equals(
((NodeState) nodeState.getOverlayedState()).getNodeTypeName())) {
for (NodeType ntReq : nodeDef.getRequiredPrimaryTypes()) {
Name ntName = ((NodeTypeImpl) ntReq).getQName();
if (!(pnt.getQName().equals(ntName)
|| pnt.isDerivedFrom(ntName))) {
/**
* the transient node's primary node type does not
* satisfy the 'required primary types' constraint
*/
String msg = itemMgr.safeGetJCRPath(id)
+ " must be of node type " + ntReq.getName();
log.debug(msg);
throw new ConstraintViolationException(msg);
}
}
}
// mandatory child properties
for (QPropertyDefinition pd : ent.getMandatoryPropDefs()) {
if (pd.getDeclaringNodeType().equals(NameConstants.MIX_VERSIONABLE)
|| pd.getDeclaringNodeType().equals(NameConstants.MIX_SIMPLE_VERSIONABLE)) {
/**
* todo FIXME workaround for mix:versionable:
* the mandatory properties are initialized at a
* later stage and might not exist yet
*/
continue;
}
String msg = itemMgr.safeGetJCRPath(id)
+ ": mandatory property " + pd.getName()
+ " does not exist";
if (!nodeState.hasPropertyName(pd.getName())) {
log.debug(msg);
throw new ConstraintViolationException(msg);
} else {
/*
there exists a property with the mandatory-name.
make sure the property really has the expected mandatory
property definition (and not another non-mandatory def,
such as e.g. multivalued residual instead of single-value
mandatory, named def).
*/
PropertyId pi = new PropertyId(nodeState.getNodeId(), pd.getName());
ItemData childData = itemMgr.getItemData(pi, null, false);
if (!childData.getDefinition().isMandatory()) {
throw new ConstraintViolationException(msg);
}
}
}
// mandatory child nodes
for (QItemDefinition cnd : ent.getMandatoryNodeDefs()) {
String msg = itemMgr.safeGetJCRPath(id)
+ ": mandatory child node " + cnd.getName()
+ " does not exist";
if (!nodeState.hasChildNodeEntry(cnd.getName())) {
log.debug(msg);
throw new ConstraintViolationException(msg);
} else {
/*
there exists a child node with the mandatory-name.
make sure the node really has the expected mandatory
node definition.
*/
boolean hasMandatoryChild = false;
for (ChildNodeEntry cne : nodeState.getChildNodeEntries(cnd.getName())) {
ItemData childData = itemMgr.getItemData(cne.getId(), null, false);
if (childData.getDefinition().isMandatory()) {
hasMandatoryChild = true;
break;
}
}
if (!hasMandatoryChild) {
throw new ConstraintViolationException(msg);
}
}
}
} else {
// the transient item is a property
PropertyState propState = (PropertyState) itemState;
ItemId propId = propState.getPropertyId();
org.apache.jackrabbit.spi.commons.nodetype.PropertyDefinitionImpl propDef = (org.apache.jackrabbit.spi.commons.nodetype.PropertyDefinitionImpl) def;
/**
* check value constraints
* (no need to check value constraints of protected properties