use of org.apache.jackrabbit.spi.QPropertyDefinition in project jackrabbit by apache.
the class NodeTypeReader method getNodeTypeDef.
/**
* Returns the node type definition specified by the current element.
*
* @return node type definition
* @throws InvalidNodeTypeDefException if the definition is invalid
* @throws NameException if the definition contains an
* illegal name
* @throws NamespaceException if a namespace is not defined
*/
private QNodeTypeDefinition getNodeTypeDef() throws InvalidNodeTypeDefException, NameException, NamespaceException {
QNodeTypeDefinitionBuilder type = new QNodeTypeDefinitionBuilder();
type.setName(resolver.getQName(walker.getAttribute(Constants.NAME_ATTRIBUTE)));
type.setMixin(Boolean.valueOf(walker.getAttribute(Constants.ISMIXIN_ATTRIBUTE)));
type.setOrderableChildNodes(Boolean.valueOf(walker.getAttribute(Constants.HASORDERABLECHILDNODES_ATTRIBUTE)));
type.setAbstract(Boolean.valueOf(walker.getAttribute(Constants.ISABSTRACT_ATTRIBUTE)));
if (walker.getAttribute(Constants.ISQUERYABLE_ATTRIBUTE) != null) {
type.setQueryable(Boolean.valueOf(walker.getAttribute(Constants.ISQUERYABLE_ATTRIBUTE)));
}
String primaryItemName = walker.getAttribute(Constants.PRIMARYITEMNAME_ATTRIBUTE);
if (primaryItemName != null && primaryItemName.length() > 0) {
type.setPrimaryItemName(resolver.getQName(primaryItemName));
}
// supertype declarations
if (walker.enterElement(Constants.SUPERTYPES_ELEMENT)) {
List<Name> supertypes = new ArrayList<Name>();
while (walker.iterateElements(Constants.SUPERTYPE_ELEMENT)) {
supertypes.add(resolver.getQName(walker.getContent()));
}
type.setSupertypes(supertypes.toArray(new Name[supertypes.size()]));
walker.leaveElement();
}
// property definitions
List<QPropertyDefinition> properties = new ArrayList<QPropertyDefinition>();
while (walker.iterateElements(Constants.PROPERTYDEFINITION_ELEMENT)) {
QPropertyDefinitionBuilder def = getPropDef();
def.setDeclaringNodeType(type.getName());
properties.add(def.build());
}
type.setPropertyDefs(properties.toArray(new QPropertyDefinition[properties.size()]));
// child node definitions
List<QNodeDefinition> nodes = new ArrayList<QNodeDefinition>();
while (walker.iterateElements(Constants.CHILDNODEDEFINITION_ELEMENT)) {
QNodeDefinitionBuilder def = getChildNodeDef();
def.setDeclaringNodeType(type.getName());
nodes.add(def.build());
}
type.setChildNodeDefs(nodes.toArray(new QNodeDefinition[nodes.size()]));
return type.build();
}
use of org.apache.jackrabbit.spi.QPropertyDefinition in project jackrabbit by apache.
the class EffectiveNodeType method create.
/**
* Package private factory method.
* <p>
* Creates an effective node type representation of a node type definition.
* Note that the definitions of all referenced node types must be contained
* in <code>ntdCache</code>.
*
* @param ntd node type definition
* @param entCache cache of already-built effective node types
* @param ntdCache cache of node type definitions, used to resolve dependencies
* @return an effective node type representation of the given node type definition.
* @throws NodeTypeConflictException if the node type definition is invalid,
* e.g. due to ambiguous child definitions.
* @throws NoSuchNodeTypeException if a node type reference (e.g. a supertype)
* could not be resolved.
*/
static EffectiveNodeType create(QNodeTypeDefinition ntd, EffectiveNodeTypeCache entCache, Map<Name, QNodeTypeDefinition> ntdCache) throws NodeTypeConflictException, NoSuchNodeTypeException {
// create empty effective node type instance
EffectiveNodeType ent = new EffectiveNodeType();
Name ntName = ntd.getName();
// prepare new instance
ent.mergedNodeTypes.add(ntName);
ent.allNodeTypes.add(ntName);
// 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> itemDefs = new HashSet<QItemDefinition>();
QNodeDefinition[] cnda = ntd.getChildNodeDefs();
for (QNodeDefinition aCnda : cnda) {
// this node type definition
if (itemDefs.contains(aCnda)) {
// conflict
String msg;
if (aCnda.definesResidual()) {
msg = ntName + " contains ambiguous residual child node definitions";
} else {
msg = ntName + " contains ambiguous definitions for child node named " + aCnda.getName();
}
log.debug(msg);
throw new NodeTypeConflictException(msg);
} else {
itemDefs.add(aCnda);
}
if (aCnda.definesResidual()) {
// residual node definition
ent.unnamedItemDefs.add(aCnda);
} else {
// named node definition
Name name = aCnda.getName();
List<QItemDefinition> defs = ent.namedItemDefs.get(name);
if (defs == null) {
defs = new ArrayList<QItemDefinition>();
ent.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 def : defs) {
if (aCnda.isAutoCreated() || def.isAutoCreated()) {
// conflict
String msg = "There are more than one 'auto-create' item definitions for '" + name + "' in node type '" + ntName + "'";
log.debug(msg);
throw new NodeTypeConflictException(msg);
}
}
}
defs.add(aCnda);
}
}
QPropertyDefinition[] pda = ntd.getPropertyDefs();
for (QPropertyDefinition aPda : pda) {
// this node type definition
if (itemDefs.contains(aPda)) {
// conflict
String msg;
if (aPda.definesResidual()) {
msg = ntName + " contains ambiguous residual property definitions";
} else {
msg = ntName + " contains ambiguous definitions for property named " + aPda.getName();
}
log.debug(msg);
throw new NodeTypeConflictException(msg);
} else {
itemDefs.add(aPda);
}
if (aPda.definesResidual()) {
// residual property definition
ent.unnamedItemDefs.add(aPda);
} else {
// named property definition
Name name = aPda.getName();
List<QItemDefinition> defs = ent.namedItemDefs.get(name);
if (defs == null) {
defs = new ArrayList<QItemDefinition>();
ent.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 def : defs) {
if (aPda.isAutoCreated() || def.isAutoCreated()) {
// conflict
String msg = "There are more than one 'auto-create' item definitions for '" + name + "' in node type '" + ntName + "'";
log.debug(msg);
throw new NodeTypeConflictException(msg);
}
}
}
defs.add(aPda);
}
}
// resolve supertypes recursively
Name[] supertypes = ntd.getSupertypes();
if (supertypes.length > 0) {
EffectiveNodeType base = NodeTypeRegistry.getEffectiveNodeType(supertypes, entCache, ntdCache);
ent.internalMerge(base, true);
}
// resolve 'orderable child nodes' attribute value (JCR-1947)
if (ntd.hasOrderableChildNodes()) {
ent.orderableChildNodes = true;
} else {
Name[] nta = ent.getInheritedNodeTypes();
for (Name aNta : nta) {
QNodeTypeDefinition def = ntdCache.get(aNta);
if (def.hasOrderableChildNodes()) {
ent.orderableChildNodes = true;
break;
}
}
}
// resolve 'primary item' attribute value (JCR-1947)
if (ntd.getPrimaryItemName() != null) {
ent.primaryItemName = ntd.getPrimaryItemName();
} else {
Name[] nta = ent.getInheritedNodeTypes();
for (Name aNta : nta) {
QNodeTypeDefinition def = ntdCache.get(aNta);
if (def.getPrimaryItemName() != null) {
ent.primaryItemName = def.getPrimaryItemName();
break;
}
}
}
// we're done
return ent;
}
use of org.apache.jackrabbit.spi.QPropertyDefinition in project jackrabbit by apache.
the class EffectiveNodeType method getApplicablePropertyDef.
/**
* Returns the applicable property definition for a property with the
* specified name and type. The multiValued flag is not taken into account
* in the selection algorithm. Other than
* <code>{@link #getApplicablePropertyDef(Name, int, boolean)}</code>
* this method does not take the multiValued flag into account in the
* selection algorithm. If there more than one applicable definitions then
* the following rules are applied:
* <ul>
* <li>named definitions are preferred to residual definitions</li>
* <li>definitions with specific required type are preferred to definitions
* with required type UNDEFINED</li>
* <li>single-value definitions are preferred to multiple-value definitions</li>
* </ul>
*
* @param name
* @param type
* @return
* @throws ConstraintViolationException if no applicable property definition
* could be found
*/
public QPropertyDefinition getApplicablePropertyDef(Name name, int type) throws ConstraintViolationException {
// try named property definitions first
QPropertyDefinition match = getMatchingPropDef(getNamedPropDefs(name), type);
if (match != null) {
return match;
}
// no item with that name defined;
// try residual property definitions
match = getMatchingPropDef(getUnnamedPropDefs(), type);
if (match != null) {
return match;
}
// no applicable definition found
throw new ConstraintViolationException("no matching property definition found for " + name);
}
use of org.apache.jackrabbit.spi.QPropertyDefinition in project jackrabbit by apache.
the class EffectiveNodeType method internalMerge.
/**
* Internal helper method which merges another <code>EffectiveNodeType</code>
* instance with <i>this</i> instance.
* <p>
* Warning: This instance might be in an inconsistent state if an exception
* is thrown.
*
* @param other
* @param supertype true if the merge is a result of inheritance, i.e. <code>other</code>
* represents one or more supertypes of this instance; otherwise false, i.e.
* the merge is the result of an explicit aggregation
* @throws NodeTypeConflictException
*/
private synchronized void internalMerge(EffectiveNodeType other, boolean supertype) throws NodeTypeConflictException {
Name[] nta = other.getAllNodeTypes();
int includedCount = 0;
for (Name aNta : nta) {
if (includesNodeType(aNta)) {
// redundant node type
log.debug("node type '" + aNta + "' is already contained.");
includedCount++;
}
}
if (includedCount == nta.length) {
// total overlap, ignore
return;
}
// named item definitions
QItemDefinition[] defs = other.getNamedItemDefs();
for (QItemDefinition def : defs) {
if (includesNodeType(def.getDeclaringNodeType())) {
// ignore redundant definitions
continue;
}
Name name = def.getName();
List<QItemDefinition> existingDefs = namedItemDefs.get(name);
if (existingDefs != null) {
if (existingDefs.size() > 0) {
// there already exists at least one definition with that name
for (QItemDefinition existingDef : existingDefs) {
// make sure none of them is auto-create
if (def.isAutoCreated() || existingDef.isAutoCreated()) {
// conflict
String msg = "The item definition for '" + name + "' in node type '" + def.getDeclaringNodeType() + "' conflicts with node type '" + existingDef.getDeclaringNodeType() + "': name collision with auto-create definition";
log.debug(msg);
throw new NodeTypeConflictException(msg);
}
// check ambiguous definitions
if (def.definesNode() == existingDef.definesNode()) {
if (!def.definesNode()) {
// property definition
QPropertyDefinition pd = (QPropertyDefinition) def;
QPropertyDefinition epd = (QPropertyDefinition) existingDef;
// compare type & multiValued flag
if (pd.getRequiredType() == epd.getRequiredType() && pd.isMultiple() == epd.isMultiple()) {
// conflict
String msg = "The property definition for '" + name + "' in node type '" + def.getDeclaringNodeType() + "' conflicts with node type '" + existingDef.getDeclaringNodeType() + "': ambiguous property definition";
log.debug(msg);
throw new NodeTypeConflictException(msg);
}
} else {
// child node definition
// conflict
String msg = "The child node definition for '" + name + "' in node type '" + def.getDeclaringNodeType() + "' conflicts with node type '" + existingDef.getDeclaringNodeType() + "': ambiguous child node definition";
log.debug(msg);
throw new NodeTypeConflictException(msg);
}
}
}
}
} else {
existingDefs = new ArrayList<QItemDefinition>();
namedItemDefs.put(name, existingDefs);
}
existingDefs.add(def);
}
// residual item definitions
defs = other.getUnnamedItemDefs();
for (QItemDefinition def : defs) {
if (includesNodeType(def.getDeclaringNodeType())) {
// ignore redundant definitions
continue;
}
for (QItemDefinition existing : unnamedItemDefs) {
// compare with existing definition
if (def.definesNode() == existing.definesNode()) {
if (!def.definesNode()) {
// property definition
QPropertyDefinition pd = (QPropertyDefinition) def;
QPropertyDefinition epd = (QPropertyDefinition) existing;
// compare type & multiValued flag
if (pd.getRequiredType() == epd.getRequiredType() && pd.isMultiple() == epd.isMultiple()) {
// conflict
String msg = "A property definition in node type '" + def.getDeclaringNodeType() + "' conflicts with node type '" + existing.getDeclaringNodeType() + "': ambiguous residual property definition";
log.debug(msg);
throw new NodeTypeConflictException(msg);
}
} else {
// child node definition
QNodeDefinition nd = (QNodeDefinition) def;
QNodeDefinition end = (QNodeDefinition) existing;
// compare required & default primary types
if (Arrays.equals(nd.getRequiredPrimaryTypes(), end.getRequiredPrimaryTypes()) && (nd.getDefaultPrimaryType() == null ? end.getDefaultPrimaryType() == null : nd.getDefaultPrimaryType().equals(end.getDefaultPrimaryType()))) {
// conflict
String msg = "A child node definition in node type '" + def.getDeclaringNodeType() + "' conflicts with node type '" + existing.getDeclaringNodeType() + "': ambiguous residual child node definition";
log.debug(msg);
throw new NodeTypeConflictException(msg);
}
}
}
}
unnamedItemDefs.add(def);
}
allNodeTypes.addAll(Arrays.asList(nta));
if (supertype) {
// implicit merge as result of inheritance
// add other merged node types as supertypes
nta = other.getMergedNodeTypes();
inheritedNodeTypes.addAll(Arrays.asList(nta));
// add supertypes of other merged node types as supertypes
nta = other.getInheritedNodeTypes();
inheritedNodeTypes.addAll(Arrays.asList(nta));
} else {
// explicit merge
// merge with other merged node types
nta = other.getMergedNodeTypes();
mergedNodeTypes.addAll(Arrays.asList(nta));
// add supertypes of other merged node types as supertypes
nta = other.getInheritedNodeTypes();
inheritedNodeTypes.addAll(Arrays.asList(nta));
}
// update 'orderable child nodes' attribute value (JCR-1947)
if (other.hasOrderableChildNodes()) {
orderableChildNodes = true;
}
// update 'primary item' attribute value (JCR-1947)
if (primaryItemName == null && other.getPrimaryItemName() != null) {
primaryItemName = other.getPrimaryItemName();
}
}
use of org.apache.jackrabbit.spi.QPropertyDefinition in project jackrabbit by apache.
the class EffectiveNodeType method getNamedPropDefs.
public QPropertyDefinition[] getNamedPropDefs(Name name) {
List<QItemDefinition> list = namedItemDefs.get(name);
if (list == null || list.size() == 0) {
return QPropertyDefinition.EMPTY_ARRAY;
}
ArrayList<QPropertyDefinition> defs = new ArrayList<QPropertyDefinition>(list.size());
for (QItemDefinition def : list) {
if (!def.definesNode()) {
defs.add((QPropertyDefinition) def);
}
}
if (defs.size() == 0) {
return QPropertyDefinition.EMPTY_ARRAY;
}
return defs.toArray(new QPropertyDefinition[defs.size()]);
}
Aggregations