NodeTypeDef holds the definition of a node type.
@@ -31,7 +33,13 @@
public class NodeTypeDef implements Cloneable {
private QName name;
- private HashSet supertypes;
+
+ /**
+ * Ordered array of supertype names. Empty if no supertypes have been
+ * specified. Never null.
+ */
+ private QName[] supertypes;
+
private boolean mixin;
private boolean orderableChildNodes;
private QName primaryItemName;
@@ -48,7 +56,7 @@
primaryItemName = null;
nodeDefs = new HashSet();
propDefs = new HashSet();
- supertypes = new HashSet();
+ supertypes = QName.EMPTY_ARRAY;
mixin = false;
orderableChildNodes = false;
}
@@ -69,7 +77,7 @@
if (dependencies == null) {
dependencies = new HashSet();
// supertypes
- dependencies.addAll(supertypes);
+ dependencies.addAll(Arrays.asList(supertypes));
// child node definitions
for (Iterator iter = nodeDefs.iterator(); iter.hasNext();) {
NodeDef nd = (NodeDef) iter.next();
@@ -127,8 +135,17 @@
*/
public void setSupertypes(QName[] names) {
resetDependencies();
- supertypes.clear();
- supertypes.addAll(Arrays.asList(names));
+ // Optimize common cases (zero or one supertypes)
+ if (names.length == 0) {
+ supertypes = QName.EMPTY_ARRAY;
+ } else if (names.length == 1) {
+ supertypes = new QName[] { names[0] };
+ } else {
+ // Sort and remove duplicates
+ SortedSet types = new TreeSet();
+ types.addAll(Arrays.asList(names));
+ supertypes = (QName[]) types.toArray(new QName[types.size()]);
+ }
}
/**
@@ -192,17 +209,22 @@
}
/**
- * Returns an array containing the names of the supertypes or
- * null if not set.
+ * Returns an array containing the names of the supertypes. If no
+ * supertypes have been specified, then an empty array is returned
+ * for mixin types and the nt:base primary type and
+ * an array containing just nt:base for other primary types.
+ *
+ * The returned array must not be modified by the application.
*
- * @return an array listing the names of the supertypes or
- * null if not set.
+ * @return a sorted array of supertype names
*/
public QName[] getSupertypes() {
- if (supertypes.isEmpty()) {
- return QName.EMPTY_ARRAY;
+ if (supertypes.length > 0
+ || isMixin() || QName.NT_BASE.equals(getName())) {
+ return supertypes;
+ } else {
+ return new QName[] { QName.NT_BASE };
}
- return (QName[]) supertypes.toArray(new QName[supertypes.size()]);
}
/**
@@ -266,7 +288,7 @@
NodeTypeDef clone = new NodeTypeDef();
clone.name = name;
clone.primaryItemName = primaryItemName;
- clone.supertypes = (HashSet) supertypes.clone();
+ clone.supertypes = supertypes; // immutable, thus ok to share
clone.mixin = mixin;
clone.orderableChildNodes = orderableChildNodes;
clone.nodeDefs = (HashSet) nodeDefs.clone();
@@ -282,7 +304,7 @@
NodeTypeDef other = (NodeTypeDef) obj;
return (name == null ? other.name == null : name.equals(other.name))
&& (primaryItemName == null ? other.primaryItemName == null : primaryItemName.equals(other.primaryItemName))
- && supertypes.equals(other.supertypes)
+ && Arrays.equals(getSupertypes(), other.getSupertypes())
&& mixin == other.mixin
&& orderableChildNodes == other.orderableChildNodes
&& propDefs.equals(other.propDefs)
Index: src/main/java/org/apache/jackrabbit/core/nodetype/EffectiveNodeType.java
===================================================================
--- src/main/java/org/apache/jackrabbit/core/nodetype/EffectiveNodeType.java (revision 418787)
+++ src/main/java/org/apache/jackrabbit/core/nodetype/EffectiveNodeType.java (working copy)
@@ -198,7 +198,7 @@
// resolve supertypes recursively
QName[] supertypes = ntd.getSupertypes();
- if (supertypes != null && supertypes.length > 0) {
+ if (supertypes.length > 0) {
ent.internalMerge(NodeTypeRegistry.getEffectiveNodeType(supertypes, entCache, ntdCache), true);
}
Index: src/main/java/org/apache/jackrabbit/core/nodetype/xml/NodeTypeWriter.java
===================================================================
--- src/main/java/org/apache/jackrabbit/core/nodetype/xml/NodeTypeWriter.java (revision 418787)
+++ src/main/java/org/apache/jackrabbit/core/nodetype/xml/NodeTypeWriter.java (working copy)
@@ -135,7 +135,7 @@
// supertype declarations
QName[] supertypes = def.getSupertypes();
- if (supertypes != null && supertypes.length > 0) {
+ if (supertypes.length > 0) {
builder.startElement(Constants.SUPERTYPES_ELEMENT);
for (int i = 0; i < supertypes.length; i++) {
builder.addContentElement(
Index: src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeRegistry.java
===================================================================
--- src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeRegistry.java (revision 418787)
+++ src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeRegistry.java (working copy)
@@ -1026,7 +1026,7 @@
NodeTypeDef ntd = (NodeTypeDef) ntDefCache.get(nt);
QName[] sta = ntd.getSupertypes();
- if (sta != null && sta.length > 0) {
+ if (sta.length > 0) {
// check recursively
inheritanceChain.push(nt);
checkForCircularInheritance(sta, inheritanceChain, ntDefCache);
@@ -1307,7 +1307,7 @@
// validate supertypes
QName[] supertypes = ntd.getSupertypes();
- if (supertypes != null && supertypes.length > 0) {
+ if (supertypes.length > 0) {
for (int i = 0; i < supertypes.length; i++) {
checkNamespace(supertypes[i], nsReg);
/**
@@ -1348,7 +1348,7 @@
* build effective (i.e. merged and resolved) node type from supertypes
* and check for conflicts
*/
- if (supertypes != null && supertypes.length > 0) {
+ if (supertypes.length > 0) {
try {
EffectiveNodeType est = getEffectiveNodeType(supertypes, entCache, ntdCache);
// make sure that all primary types except nt:base extend from nt:base
@@ -1368,14 +1368,6 @@
log.debug(msg);
throw new InvalidNodeTypeDefException(msg, nsnte);
}
- } else {
- // no supertypes specified: has to be either a mixin type or nt:base
- if (!ntd.isMixin() && !QName.NT_BASE.equals(ntd.getName())) {
- String msg = "[" + name
- + "] all primary node types except nt:base itself must be (directly or indirectly) derived from nt:base";
- log.debug(msg);
- throw new InvalidNodeTypeDefException(msg);
- }
}
checkNamespace(ntd.getPrimaryItemName(), nsReg);