use of org.apache.jackrabbit.spi.QItemDefinition in project jackrabbit by apache.
the class EffectiveNodeType method getApplicableChildNodeDef.
/**
* Returns the applicable child node definition for a child node with the
* specified name and node type. If there are multiple applicable definitions
* named definitions will take precedence over residual definitions.
*
* @param name
* @param nodeTypeName
* @param ntReg
* @return
* @throws NoSuchNodeTypeException
* @throws ConstraintViolationException if no applicable child node definition
* could be found
*/
public QNodeDefinition getApplicableChildNodeDef(Name name, Name nodeTypeName, NodeTypeRegistry ntReg) throws NoSuchNodeTypeException, ConstraintViolationException {
EffectiveNodeType entTarget;
if (nodeTypeName != null) {
entTarget = ntReg.getEffectiveNodeType(nodeTypeName);
} else {
entTarget = null;
}
// try named node definitions first
QItemDefinition[] defs = getNamedItemDefs(name);
for (QItemDefinition def : defs) {
if (def.definesNode()) {
QNodeDefinition nd = (QNodeDefinition) def;
Name[] types = nd.getRequiredPrimaryTypes();
// node definition with that name exists
if (entTarget != null && types != null) {
// check 'required primary types' constraint
if (entTarget.includesNodeTypes(types)) {
// found named node definition
return nd;
}
} else if (nd.getDefaultPrimaryType() != null) {
// found node definition with default node type
return nd;
}
}
}
// no item with that name defined;
// try residual node definitions
QNodeDefinition[] nda = getUnnamedNodeDefs();
for (QNodeDefinition nd : nda) {
if (entTarget != null && nd.getRequiredPrimaryTypes() != null) {
// check 'required primary types' constraint
if (!entTarget.includesNodeTypes(nd.getRequiredPrimaryTypes())) {
continue;
}
// found residual node definition
return nd;
} else {
// it must be determined from the default node type;
if (nd.getDefaultPrimaryType() != null) {
// found residual node definition with default node type
return nd;
}
}
}
// no applicable definition found
throw new ConstraintViolationException("no matching child node definition found for " + name);
}
use of org.apache.jackrabbit.spi.QItemDefinition in project jackrabbit by apache.
the class ItemSaveOperation method validateTransientItems.
/**
* the following validations/checks are performed on transient items:
*
* for every transient item:
* - if it is 'modified' or 'new' check the corresponding write permission.
* - if it is 'removed' check the REMOVE permission
*
* for every transient node:
* - if it is 'new' check that its node type satisfies the
* 'required node type' constraint specified in its definition
* - check if 'mandatory' child items exist
*
* for every transient property:
* - check if the property value satisfies the value constraints
* specified in the property's definition
*
* note that the protected flag is checked in Node.addNode/Node.remove
* (for adding/removing child entries of a node), in
* Node.addMixin/removeMixin/setPrimaryType (for type changes on nodes)
* and in Property.setValue (for properties to be modified).
*/
private void validateTransientItems(SessionContext context, Iterable<ItemState> dirty, Iterable<ItemState> removed) throws RepositoryException {
SessionImpl session = context.getSessionImpl();
ItemManager itemMgr = context.getItemManager();
SessionItemStateManager stateMgr = context.getItemStateManager();
AccessManager accessMgr = context.getAccessManager();
NodeTypeManagerImpl ntMgr = context.getNodeTypeManager();
// walk through list of dirty transient items and validate each
for (ItemState itemState : dirty) {
ItemDefinition def;
if (itemState.isNode()) {
def = itemMgr.getDefinition((NodeState) itemState);
} else {
def = itemMgr.getDefinition((PropertyState) itemState);
}
/* check permissions for non-protected items. protected items are
only added through API methods which need to assert that
permissions are not violated.
*/
if (!def.isProtected()) {
/* detect the effective set of modification:
- new added node -> add_node perm on the child
- new property added -> set_property permission
- property modified -> set_property permission
- modified nodes can be ignored for changes only included
child-item addition or removal or changes of protected
properties such as mixin-types which are covered separately
note: removed items are checked later on.
note: reordering of child nodes has been covered upfront as
this information isn't available here.
*/
Path path = stateMgr.getHierarchyMgr().getPath(itemState.getId());
boolean isGranted = true;
if (itemState.isNode()) {
if (itemState.getStatus() == ItemState.STATUS_NEW) {
isGranted = accessMgr.isGranted(path, Permission.ADD_NODE);
}
// else: modified node (see comment above)
} else {
// modified or new property: set_property permission
isGranted = accessMgr.isGranted(path, Permission.SET_PROPERTY);
}
if (!isGranted) {
String msg = itemMgr.safeGetJCRPath(path) + ": not allowed to add or modify item";
log.debug(msg);
throw new AccessDeniedException(msg);
}
}
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(context.getRepositoryContext().getNodeTypeRegistry(), 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
*/
boolean primaryTypeChanged = nodeState.getStatus() == ItemState.STATUS_NEW;
if (!primaryTypeChanged) {
NodeState overlaid = (NodeState) nodeState.getOverlayedState();
if (overlaid != null) {
Name newName = nodeState.getNodeTypeName();
Name oldName = overlaid.getNodeTypeName();
primaryTypeChanged = !newName.equals(oldName);
}
}
if (primaryTypeChanged) {
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
* as those are set by the implementation only, i.e. they
* cannot be set by the user through the api)
*/
if (!def.isProtected()) {
String[] constraints = propDef.getValueConstraints();
if (constraints != null) {
InternalValue[] values = propState.getValues();
try {
EffectiveNodeType.checkSetPropertyValueConstraints(propDef.unwrap(), values);
} catch (RepositoryException e) {
// repack exception for providing more verbose error message
String msg = itemMgr.safeGetJCRPath(propId) + ": " + e.getMessage();
log.debug(msg);
throw new ConstraintViolationException(msg);
}
/**
* need to manually check REFERENCE value constraints
* as this requires a session (target node needs to
* be checked)
*/
if (constraints.length > 0 && (propDef.getRequiredType() == PropertyType.REFERENCE || propDef.getRequiredType() == PropertyType.WEAKREFERENCE)) {
for (InternalValue internalV : values) {
boolean satisfied = false;
String constraintViolationMsg = null;
try {
NodeId targetId = internalV.getNodeId();
if (propDef.getRequiredType() == PropertyType.WEAKREFERENCE && !itemMgr.itemExists(targetId)) {
// target of weakref doesn;t exist, skip
continue;
}
Node targetNode = session.getNodeById(targetId);
/**
* constraints are OR-ed, i.e. at least one
* has to be satisfied
*/
for (String constrNtName : constraints) {
/**
* a [WEAK]REFERENCE value constraint specifies
* the name of the required node type of
* the target node
*/
if (targetNode.isNodeType(constrNtName)) {
satisfied = true;
break;
}
}
if (!satisfied) {
NodeType[] mixinNodeTypes = targetNode.getMixinNodeTypes();
String[] targetMixins = new String[mixinNodeTypes.length];
for (int j = 0; j < mixinNodeTypes.length; j++) {
targetMixins[j] = mixinNodeTypes[j].getName();
}
String targetMixinsString = Text.implode(targetMixins, ", ");
String constraintsString = Text.implode(constraints, ", ");
constraintViolationMsg = itemMgr.safeGetJCRPath(propId) + ": is constraint to [" + constraintsString + "] but references [primaryType=" + targetNode.getPrimaryNodeType().getName() + ", mixins=" + targetMixinsString + "]";
}
} catch (RepositoryException re) {
String msg = itemMgr.safeGetJCRPath(propId) + ": failed to check " + ((propDef.getRequiredType() == PropertyType.REFERENCE) ? "REFERENCE" : "WEAKREFERENCE") + " value constraint";
log.debug(msg);
throw new ConstraintViolationException(msg, re);
}
if (!satisfied) {
log.debug(constraintViolationMsg);
throw new ConstraintViolationException(constraintViolationMsg);
}
}
}
}
}
/**
* no need to check the protected flag as this is checked
* in PropertyImpl.setValue(Value)
*/
}
}
// walk through list of removed transient items and check REMOVE permission
for (ItemState itemState : removed) {
QItemDefinition def;
try {
if (itemState.isNode()) {
def = itemMgr.getDefinition((NodeState) itemState).unwrap();
} else {
def = itemMgr.getDefinition((PropertyState) itemState).unwrap();
}
} catch (ConstraintViolationException e) {
// of a mixin (see also JCR-2130 & JCR-2408)
continue;
}
if (!def.isProtected()) {
Path path = stateMgr.getAtticAwareHierarchyMgr().getPath(itemState.getId());
// check REMOVE permission
int permission = (itemState.isNode()) ? Permission.REMOVE_NODE : Permission.REMOVE_PROPERTY;
if (!accessMgr.isGranted(path, permission)) {
String msg = itemMgr.safeGetJCRPath(path) + ": not allowed to remove item";
log.debug(msg);
throw new AccessDeniedException(msg);
}
}
}
}
use of org.apache.jackrabbit.spi.QItemDefinition in project jackrabbit by apache.
the class ItemValidator method validate.
/**
* Checks whether the given node state satisfies the constraints specified
* by its primary and mixin node types. The following validations/checks are
* performed:
* <ul>
* <li>check if its node type satisfies the 'required node types' constraint
* specified in its definition</li>
* <li>check if all 'mandatory' child items exist</li>
* <li>for every property: check if the property value satisfies the
* value constraints specified in the property's definition</li>
* </ul>
*
* @param nodeState state of node to be validated
* @throws ConstraintViolationException if any of the validations fail
* @throws RepositoryException if another error occurs
*/
public void validate(NodeState nodeState) throws ConstraintViolationException, RepositoryException {
// effective primary node type
NodeTypeRegistry registry = context.getNodeTypeRegistry();
EffectiveNodeType entPrimary = registry.getEffectiveNodeType(nodeState.getNodeTypeName());
// effective node type (primary type incl. mixins)
EffectiveNodeType entPrimaryAndMixins = getEffectiveNodeType(nodeState);
QNodeDefinition def = context.getItemManager().getDefinition(nodeState).unwrap();
// check if primary type satisfies the 'required node types' constraint
for (Name requiredPrimaryType : def.getRequiredPrimaryTypes()) {
if (!entPrimary.includesNodeType(requiredPrimaryType)) {
String msg = safeGetJCRPath(nodeState.getNodeId()) + ": missing required primary type " + requiredPrimaryType;
log.debug(msg);
throw new ConstraintViolationException(msg);
}
}
// mandatory properties
for (QPropertyDefinition pd : entPrimaryAndMixins.getMandatoryPropDefs()) {
if (!nodeState.hasPropertyName(pd.getName())) {
String msg = safeGetJCRPath(nodeState.getNodeId()) + ": mandatory property " + pd.getName() + " does not exist";
log.debug(msg);
throw new ConstraintViolationException(msg);
}
}
// mandatory child nodes
for (QItemDefinition cnd : entPrimaryAndMixins.getMandatoryNodeDefs()) {
if (!nodeState.hasChildNodeEntry(cnd.getName())) {
String msg = safeGetJCRPath(nodeState.getNodeId()) + ": mandatory child node " + cnd.getName() + " does not exist";
log.debug(msg);
throw new ConstraintViolationException(msg);
}
}
}
use of org.apache.jackrabbit.spi.QItemDefinition in project jackrabbit by apache.
the class NodeImpl method setPrimaryType.
/**
* {@inheritDoc}
*/
public void setPrimaryType(String nodeTypeName) throws NoSuchNodeTypeException, VersionException, ConstraintViolationException, LockException, RepositoryException {
// check state of this instance
sanityCheck();
// make sure this node is checked-out, neither protected nor locked and
// the editing session has sufficient permission to change the primary type.
int options = ItemValidator.CHECK_CHECKED_OUT | ItemValidator.CHECK_LOCK | ItemValidator.CHECK_CONSTRAINTS | ItemValidator.CHECK_HOLD;
sessionContext.getItemValidator().checkModify(this, options, Permission.NODE_TYPE_MNGMT);
final NodeState state = data.getNodeState();
if (state.getParentId() == null) {
String msg = "changing the primary type of the root node is not supported";
log.debug(msg);
throw new RepositoryException(msg);
}
Name ntName = sessionContext.getQName(nodeTypeName);
if (ntName.equals(state.getNodeTypeName())) {
log.debug("Node already has " + nodeTypeName + " as primary node type.");
return;
}
NodeTypeManagerImpl ntMgr = sessionContext.getNodeTypeManager();
NodeType nt = ntMgr.getNodeType(ntName);
if (nt.isMixin()) {
throw new ConstraintViolationException(nodeTypeName + ": not a primary node type.");
} else if (nt.isAbstract()) {
throw new ConstraintViolationException(nodeTypeName + ": is an abstract node type.");
}
// build effective node type of new primary type & existing mixin's
// in order to detect conflicts
NodeTypeRegistry ntReg = ntMgr.getNodeTypeRegistry();
EffectiveNodeType entNew, entOld, entAll;
try {
entNew = ntReg.getEffectiveNodeType(ntName);
entOld = ntReg.getEffectiveNodeType(state.getNodeTypeName());
// try to build new effective node type (will throw in case of conflicts)
entAll = ntReg.getEffectiveNodeType(ntName, state.getMixinTypeNames());
} catch (NodeTypeConflictException ntce) {
throw new ConstraintViolationException(ntce.getMessage());
}
// get applicable definition for this node using new primary type
QNodeDefinition nodeDef;
try {
NodeImpl parent = (NodeImpl) getParent();
nodeDef = parent.getApplicableChildNodeDefinition(getQName(), ntName).unwrap();
} catch (RepositoryException re) {
String msg = this + ": no applicable definition found in parent node's node type";
log.debug(msg);
throw new ConstraintViolationException(msg, re);
}
if (!nodeDef.equals(itemMgr.getDefinition(state).unwrap())) {
onRedefine(nodeDef);
}
Set<QItemDefinition> oldDefs = new HashSet<QItemDefinition>(Arrays.asList(entOld.getAllItemDefs()));
Set<QItemDefinition> newDefs = new HashSet<QItemDefinition>(Arrays.asList(entNew.getAllItemDefs()));
Set<QItemDefinition> allDefs = new HashSet<QItemDefinition>(Arrays.asList(entAll.getAllItemDefs()));
// added child item definitions
Set<QItemDefinition> addedDefs = new HashSet<QItemDefinition>(newDefs);
addedDefs.removeAll(oldDefs);
// referential integrity check
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(itemMgr.getDefinition(propState).unwrap())) {
// 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(), getSession().getValueFactory());
// redefine property
prop.onRedefine(pdi.unwrap());
// set converted values
prop.setValue(values);
} else {
// convert value
Value value = ValueHelper.convert(prop.getValue(), pdi.getRequiredType(), getSession().getValueFactory());
// redefine property
prop.onRedefine(pdi.unwrap());
// set converted values
prop.setValue(value);
}
} else {
// redefine property
prop.onRedefine(pdi.unwrap());
}
// 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(itemMgr.getDefinition(nodeState).unwrap())) {
// redefine node if possible
try {
NodeImpl node = (NodeImpl) itemMgr.getItem(nodeState.getId());
if (node.getDefinition().isProtected()) {
// remove 'orphaned' protected child node immediately
removeChildNode(entry.getId());
continue;
}
NodeDefinitionImpl ndi = getApplicableChildNodeDefinition(entry.getName(), nodeState.getNodeTypeName());
// redefine node
node.onRedefine(ndi.unwrap());
// update collection of added definitions
addedDefs.remove(ndi.unwrap());
} catch (ConstraintViolationException cve) {
// no suitable definition found for this child node,
// remove it
removeChildNode(entry.getId());
}
}
} catch (ItemStateException ise) {
String msg = entry.getName() + ": failed to retrieve node state";
log.error(msg, ise);
throw new RepositoryException(msg, ise);
}
}
// type and at the same time were not present with the old nt
for (QItemDefinition def : addedDefs) {
if (def.isAutoCreated()) {
if (def.definesNode()) {
NodeDefinitionImpl ndi = ntMgr.getNodeDefinition((QNodeDefinition) def);
createChildNode(def.getName(), (NodeTypeImpl) ndi.getDefaultPrimaryType(), null);
} else {
PropertyDefinitionImpl pdi = ntMgr.getPropertyDefinition((QPropertyDefinition) def);
createChildProperty(pdi.unwrap().getName(), pdi.getRequiredType(), pdi);
}
}
}
}
use of org.apache.jackrabbit.spi.QItemDefinition in project jackrabbit by apache.
the class NodeTypeRegistryImpl method getEffectiveNodeType.
/**
* @see EffectiveNodeTypeProvider#getEffectiveNodeType(QNodeTypeDefinition, Map)
*/
public EffectiveNodeType getEffectiveNodeType(QNodeTypeDefinition ntd, Map<Name, QNodeTypeDefinition> ntdMap) throws ConstraintViolationException, NoSuchNodeTypeException {
TreeSet<Name> mergedNodeTypes = new TreeSet<Name>();
TreeSet<Name> inheritedNodeTypes = new TreeSet<Name>();
TreeSet<Name> allNodeTypes = new TreeSet<Name>();
Map<Name, List<QItemDefinition>> namedItemDefs = new HashMap<Name, List<QItemDefinition>>();
List<QItemDefinition> unnamedItemDefs = new ArrayList<QItemDefinition>();
Set<Name> supportedMixins = null;
Name ntName = ntd.getName();
// prepare new instance
mergedNodeTypes.add(ntName);
allNodeTypes.add(ntName);
Name[] smixins = ntd.getSupportedMixinTypes();
if (smixins != null) {
supportedMixins = new HashSet<Name>();
supportedMixins.addAll(Arrays.asList(smixins));
}
// map of all item definitions (maps id to definition)
// used to effectively detect ambiguous child definitions where
// ambiguity is defined in terms of definition identity
Set<QItemDefinition> itemDefIds = new HashSet<QItemDefinition>();
for (QNodeDefinition nd : ntd.getChildNodeDefs()) {
// this node type definition
if (itemDefIds.contains(nd)) {
// conflict
String msg;
if (nd.definesResidual()) {
msg = ntName + " contains ambiguous residual child node definitions";
} else {
msg = ntName + " contains ambiguous definitions for child node named " + nd.getName();
}
log.debug(msg);
throw new ConstraintViolationException(msg);
} else {
itemDefIds.add(nd);
}
if (nd.definesResidual()) {
// residual node definition
unnamedItemDefs.add(nd);
} else {
// named node definition
Name name = nd.getName();
List<QItemDefinition> defs = namedItemDefs.get(name);
if (defs == null) {
defs = new ArrayList<QItemDefinition>();
namedItemDefs.put(name, defs);
}
if (defs.size() > 0) {
/**
* there already exists at least one definition with that
* name; make sure none of them is auto-create
*/
for (QItemDefinition qDef : defs) {
if (nd.isAutoCreated() || qDef.isAutoCreated()) {
// conflict
String msg = "There are more than one 'auto-create' item definitions for '" + name + "' in node type '" + ntName + "'";
log.debug(msg);
throw new ConstraintViolationException(msg);
}
}
}
defs.add(nd);
}
}
for (QPropertyDefinition pd : ntd.getPropertyDefs()) {
// this node type definition
if (itemDefIds.contains(pd)) {
// conflict
String msg;
if (pd.definesResidual()) {
msg = ntName + " contains ambiguous residual property definitions";
} else {
msg = ntName + " contains ambiguous definitions for property named " + pd.getName();
}
log.debug(msg);
throw new ConstraintViolationException(msg);
} else {
itemDefIds.add(pd);
}
if (pd.definesResidual()) {
// residual property definition
unnamedItemDefs.add(pd);
} else {
// named property definition
Name name = pd.getName();
List<QItemDefinition> defs = namedItemDefs.get(name);
if (defs == null) {
defs = new ArrayList<QItemDefinition>();
namedItemDefs.put(name, defs);
}
if (defs.size() > 0) {
/**
* there already exists at least one definition with that
* name; make sure none of them is auto-create
*/
for (QItemDefinition qDef : defs) {
if (pd.isAutoCreated() || qDef.isAutoCreated()) {
// conflict
String msg = "There are more than one 'auto-create' item definitions for '" + name + "' in node type '" + ntName + "'";
log.debug(msg);
throw new ConstraintViolationException(msg);
}
}
}
defs.add(pd);
}
}
// create empty effective node type instance
EffectiveNodeTypeImpl ent = new EffectiveNodeTypeImpl(mergedNodeTypes, inheritedNodeTypes, allNodeTypes, namedItemDefs, unnamedItemDefs, supportedMixins);
// resolve supertypes recursively
Name[] supertypes = ntd.getSupertypes();
if (supertypes.length > 0) {
EffectiveNodeTypeImpl effSuperType = (EffectiveNodeTypeImpl) getEffectiveNodeType(supertypes, ntdMap);
ent.internalMerge(effSuperType, true);
}
return ent;
}
Aggregations