Author: rhauch
Date: 2009-04-02 15:02:05 -0400 (Thu, 02 Apr 2009)
New Revision: 804
Added:
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/RepositoryNodeTypeManagerTest.java
Modified:
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/DnaBuiltinNodeTypeSource.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/DnaLexicon.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrLexicon.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrWorkspace.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/RepositoryNodeTypeManager.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrWorkspaceTest.java
Log:
DNA-340 Projection of Node Types onto System View
Applied the patch, which stores the node type information in the repository graph, with
one exception. For various reasons (including those related to performance of running so
many TCK unit tests), we want to be able to have a JcrRepository configuration property
that says whether the node types should be stored in the graph. So, the
"batch.execute()" line was commented out at the end of the
RepositoryNodeTypeManager.projectOnto(Graph,Path) method. This essentially prevents the
node types from being added, but still ensures that the
"/jcr:system/dna:nodeTypes" node exists.
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/DnaBuiltinNodeTypeSource.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/DnaBuiltinNodeTypeSource.java 2009-04-02
18:52:26 UTC (rev 803)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/DnaBuiltinNodeTypeSource.java 2009-04-02
19:02:05 UTC (rev 804)
@@ -63,6 +63,14 @@
throw new IllegalStateException(JcrI18n.supertypeNotFound.text(baseTypeName,
namespaceTypeName));
}
+ JcrNodeType nodeType = findType(JcrNtLexicon.NODE_TYPE);
+
+ if (nodeType == null) {
+ String baseTypeName =
JcrNtLexicon.NODE_TYPE.getString(context.getNamespaceRegistry());
+ String namespaceTypeName =
DnaLexicon.NODE_TYPES.getString(context.getNamespaceRegistry());
+ throw new IllegalStateException(JcrI18n.supertypeNotFound.text(baseTypeName,
namespaceTypeName));
+ }
+
// Stubbing in child node and property definitions for now
JcrNodeType namespace = new JcrNodeType(
context,
@@ -104,25 +112,39 @@
new JcrNodeType[] {namespace})}),
NO_PROPERTIES, NOT_MIXIN,
UNORDERABLE_CHILD_NODES);
- JcrNodeType system = new JcrNodeType(
- context,
- NO_NODE_TYPE_MANAGER,
- DnaLexicon.SYSTEM,
- Arrays.asList(new JcrNodeType[] {base}),
- NO_PRIMARY_ITEM_NAME,
- Arrays.asList(new JcrNodeDefinition[] {new
JcrNodeDefinition(
-
context,
-
null,
-
DnaLexicon.NAMESPACES,
-
OnParentVersionBehavior.VERSION.getJcrValue(),
-
true,
-
true,
-
true,
-
false,
-
DnaLexicon.NAMESPACES,
-
new JcrNodeType[] {namespaces})}),
- NO_PROPERTIES, NOT_MIXIN,
UNORDERABLE_CHILD_NODES);
+ JcrNodeType dnaNodeTypes = new JcrNodeType(
+ context,
+ NO_NODE_TYPE_MANAGER,
+ DnaLexicon.NODE_TYPES,
+ Arrays.asList(new JcrNodeType[]
{base}),
+ NO_PRIMARY_ITEM_NAME,
+ Arrays.asList(new JcrNodeDefinition[]
{new JcrNodeDefinition(
+
context,
+
null,
+
null,
+
OnParentVersionBehavior.VERSION.getJcrValue(),
+
false,
+
false,
+
true,
+
true,
+
JcrNtLexicon.NODE_TYPE,
+
new JcrNodeType[] {nodeType})}),
+ NO_PROPERTIES, NOT_MIXIN,
UNORDERABLE_CHILD_NODES);
+ JcrNodeType system = new JcrNodeType(context, NO_NODE_TYPE_MANAGER,
DnaLexicon.SYSTEM,
+ Arrays.asList(new JcrNodeType[] {base}),
NO_PRIMARY_ITEM_NAME,
+ Arrays.asList(new JcrNodeDefinition[] {
+ new JcrNodeDefinition(context, null,
DnaLexicon.NAMESPACES,
+
OnParentVersionBehavior.VERSION.getJcrValue(), true, true,
+ true, false,
DnaLexicon.NAMESPACES,
+ new JcrNodeType[]
{namespaces}),
+
+ new JcrNodeDefinition(context, null,
JcrLexicon.NODE_TYPES,
+
OnParentVersionBehavior.VERSION.getJcrValue(), true, true,
+ true, false,
DnaLexicon.NODE_TYPES,
+ new JcrNodeType[]
{dnaNodeTypes})}), NO_PROPERTIES,
+ NOT_MIXIN, UNORDERABLE_CHILD_NODES);
+
JcrNodeType root = new JcrNodeType(context, NO_NODE_TYPE_MANAGER,
DnaLexicon.ROOT, Arrays.asList(new JcrNodeType[] {base,
referenceable}), NO_PRIMARY_ITEM_NAME, Arrays.asList(new JcrNodeDefinition[]
{
new JcrNodeDefinition(context, null, JcrLexicon.SYSTEM,
OnParentVersionBehavior.IGNORE.getJcrValue(), true, true,
@@ -137,8 +159,7 @@
NO_DEFAULT_VALUES, PropertyType.UNDEFINED,
NO_CONSTRAINTS, true),}), NOT_MIXIN,
ORDERABLE_CHILD_NODES);
- nodeTypes.addAll(Arrays.asList(new JcrNodeType[] {root, system, namespaces,
namespace,}));
- nodeTypes.addAll(Arrays.asList(new JcrNodeType[] {}));
+ nodeTypes.addAll(Arrays.asList(new JcrNodeType[] {root, system, dnaNodeTypes,
namespaces, namespace,}));
}
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/DnaLexicon.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/DnaLexicon.java 2009-04-02 18:52:26 UTC
(rev 803)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/DnaLexicon.java 2009-04-02 19:02:05 UTC
(rev 804)
@@ -33,6 +33,7 @@
public static final Name NAMESPACE = new BasicName(Namespace.URI,
"namespace");
public static final Name NODE_DEFINITON = new BasicName(Namespace.URI,
"nodeDefinition");
+ public static final Name NODE_TYPES = new BasicName(Namespace.URI,
"nodeTypes");
public static final Name ROOT = new BasicName(Namespace.URI, "root");
public static final Name SYSTEM = new BasicName(Namespace.URI, "system");
public static final Name URI = new BasicName(Namespace.URI, "uri");
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrLexicon.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrLexicon.java 2009-04-02 18:52:26 UTC
(rev 803)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrLexicon.java 2009-04-02 19:02:05 UTC
(rev 804)
@@ -55,6 +55,7 @@
public static final Name MERGE_FAILED = new BasicName(Namespace.URI,
"mergeFailed");
public static final Name MULTIPLE = new BasicName(Namespace.URI,
"multiple");
public static final Name NAME = new BasicName(Namespace.URI, "name");
+ public static final Name NODE_TYPES = new BasicName(Namespace.URI,
"nodeTypes");
public static final Name NODE_TYPE_NAME = new BasicName(Namespace.URI,
"nodeTypeName");
public static final Name ON_PARENT_VERSION = new BasicName(Namespace.URI,
"onParentVersion");
public static final Name PREDECESSORS = new BasicName(Namespace.URI,
"predecessors");
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrWorkspace.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrWorkspace.java 2009-04-02 18:52:26
UTC (rev 803)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrWorkspace.java 2009-04-02 19:02:05
UTC (rev 804)
@@ -110,7 +110,7 @@
* Reference to the JCR query manager for this workspace.
*/
private final JcrQueryManager queryManager;
-
+
/**
* The {@link Session} instance that this corresponds with this workspace.
*/
@@ -153,8 +153,14 @@
this.session = new JcrSession(this.repository, this, this.context,
sessionAttributes);
// This must be initialized after the session
- this.nodeTypeManager = new JcrNodeTypeManager(session.getExecutionContext(),
repository.getRepositoryTypeManager());
+ RepositoryNodeTypeManager repoTypeManager =
repository.getRepositoryTypeManager();
+ this.nodeTypeManager = new JcrNodeTypeManager(session.getExecutionContext(),
repoTypeManager);
this.queryManager = new JcrQueryManager(this.session);
+
+ Path parentOfTypeNodes =
context.getValueFactories().getPathFactory().create(root,
+
JcrLexicon.SYSTEM,
+
JcrLexicon.NODE_TYPES);
+ repoTypeManager.projectOnto(this.graph, parentOfTypeNodes);
}
final String getSourceName() {
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/RepositoryNodeTypeManager.java
===================================================================
---
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/RepositoryNodeTypeManager.java 2009-04-02
18:52:26 UTC (rev 803)
+++
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/RepositoryNodeTypeManager.java 2009-04-02
19:02:05 UTC (rev 804)
@@ -30,12 +30,22 @@
import java.util.List;
import java.util.Map;
import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
import javax.jcr.Value;
import javax.jcr.nodetype.NodeDefinition;
+import javax.jcr.nodetype.NodeType;
import javax.jcr.nodetype.PropertyDefinition;
+import javax.jcr.version.OnParentVersionAction;
import net.jcip.annotations.Immutable;
+import org.jboss.dna.common.text.XmlNameEncoder;
import org.jboss.dna.graph.ExecutionContext;
+import org.jboss.dna.graph.Graph;
import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.PathFactory;
+import org.jboss.dna.graph.property.PathNotFoundException;
+import org.jboss.dna.graph.property.Property;
+import org.jboss.dna.graph.property.PropertyFactory;
/**
* The {@link RepositoryNodeTypeManager} is the maintainer of node type information for
the entire repository at run-time. The
@@ -50,12 +60,19 @@
@Immutable
class RepositoryNodeTypeManager {
+ private final ExecutionContext context;
private final Map<Name, JcrNodeType> nodeTypes;
private final Map<PropertyDefinitionId, JcrPropertyDefinition>
propertyDefinitions;
private final Map<NodeDefinitionId, JcrNodeDefinition> childNodeDefinitions;
+ private final PropertyFactory propertyFactory;
+ private final PathFactory pathFactory;
RepositoryNodeTypeManager( ExecutionContext context,
JcrNodeTypeSource source ) {
+ this.context = context;
+ this.propertyFactory = context.getPropertyFactory();
+ this.pathFactory = context.getValueFactories().getPathFactory();
+
Collection<JcrNodeType> types = source.getNodeTypes();
propertyDefinitions = new HashMap<PropertyDefinitionId,
JcrPropertyDefinition>();
childNodeDefinitions = new HashMap<NodeDefinitionId, JcrNodeDefinition>();
@@ -78,21 +95,21 @@
public Collection<JcrNodeType> getMixinNodeTypes() {
List<JcrNodeType> types = new
ArrayList<JcrNodeType>(nodeTypes.size());
-
+
for (JcrNodeType nodeType : nodeTypes.values()) {
if (nodeType.isMixin()) types.add(nodeType);
}
-
+
return types;
}
public Collection<JcrNodeType> getPrimaryNodeTypes() {
List<JcrNodeType> types = new
ArrayList<JcrNodeType>(nodeTypes.size());
-
+
for (JcrNodeType nodeType : nodeTypes.values()) {
if (!nodeType.isMixin()) types.add(nodeType);
}
-
+
return types;
}
@@ -594,4 +611,211 @@
skipProtected);
return false;
}
+
+ /**
+ * Projects the node types onto the provided graph under the location of
<code>parentOfTypeNodes</code>. If no node currently
+ * exists at that path, one will be created and assigned a primary type of {@code
DnaLexicon.NODE_TYPES}.
+ * <p>
+ * All node creation is performed through the graph layer. If the primary type of the
node at <code>parentOfPathNodes</code>
+ * does not contain a residual definition that allows child nodes of type
<code>nt:nodeType</code>, this method will create
+ * nodes for which the JCR layer cannot determine the corresponding node definition.
This WILL corrupt the graph from a JCR
+ * standpoint and make it unusable through the DNA JCR layer.
+ * </p>
+ * <p>
+ * For each node type, a node is created as a child node of
<code>parentOfPathNodes</code>. The created node has a name that
+ * corresponds to the node types name and a primary type of
<code>nt:nodeType</code>. All other properties and child nodes for
+ * the newly created node are added in a manner consistent with the guidance provide
in section 6.7.22 of the JCR 1.0
+ * specification and section 4.7.24 of the (draft) JCR 2.0 specification where
possible.
+ * </p>
+ *
+ * @param graph the graph onto which the type information should be projected
+ * @param parentOfTypeNodes the path under which the type information should be
projected
+ */
+ void projectOnto( Graph graph,
+ Path parentOfTypeNodes ) {
+ assert graph != null;
+ assert parentOfTypeNodes != null;
+
+ // Make sure that the parent of the type nodes exists in the graph.
+ try {
+ graph.getNodeAt(parentOfTypeNodes);
+ } catch (PathNotFoundException pnfe) {
+ PropertyFactory propertyFactory = context.getPropertyFactory();
+ graph.create(parentOfTypeNodes,
+ propertyFactory.create(JcrLexicon.PRIMARY_TYPE,
+
DnaLexicon.NODE_TYPES.getString(context.getNamespaceRegistry())));
+ }
+
+ Graph.Batch batch = graph.batch();
+
+ for (JcrNodeType nodeType : nodeTypes.values()) {
+ projectNodeTypeOnto(nodeType, parentOfTypeNodes, batch);
+ }
+
+ // TODO: Add back in; see DNA-340 ...
+ // batch.execute();
+ }
+
+ /**
+ * Projects the node types onto the provided graph under the location of
<code>parentOfTypeNodes</code>. The operations needed
+ * to create the node (and any child nodes or properties) will be added to the batch
specified in <code>batch</code>.
+ *
+ * @param nodeType the node type to be projected
+ * @param parentOfTypeNodes the path under which the type information should be
projected
+ * @param batch the batch to which any required graph modification operations should
be added
+ * @see #projectOnto(Graph, Path)
+ */
+ private void projectNodeTypeOnto( JcrNodeType nodeType,
+ Path parentOfTypeNodes,
+ Graph.Batch batch ) {
+ assert nodeType != null;
+ assert parentOfTypeNodes != null;
+ assert batch != null;
+
+ Path nodeTypePath = pathFactory.create(parentOfTypeNodes,
nodeType.getInternalName());
+
+ NodeType[] supertypes = nodeType.getDeclaredSupertypes();
+ List<Name> supertypeNames = new ArrayList<Name>(supertypes.length);
+ for (int i = 0; i < supertypes.length; i++) {
+ supertypeNames.add(((JcrNodeType)supertypes[i]).getInternalName());
+ }
+
+ List<Property> propsList = new ArrayList<Property>();
+ propsList.add(propertyFactory.create(JcrLexicon.PRIMARY_TYPE,
JcrNtLexicon.NODE_TYPE));
+ propsList.add(propertyFactory.create(JcrLexicon.IS_MIXIN, nodeType.isMixin()));
+
+ if (nodeType.getPrimaryItemName() != null) {
+ propsList.add(propertyFactory.create(JcrLexicon.PRIMARY_ITEM_NAME,
nodeType.getPrimaryItemName()));
+ }
+
+ propsList.add(propertyFactory.create(JcrLexicon.NODE_TYPE_NAME,
nodeType.getName()));
+ propsList.add(propertyFactory.create(JcrLexicon.HAS_ORDERABLE_CHILD_NODES,
nodeType.hasOrderableChildNodes()));
+ propsList.add(propertyFactory.create(JcrLexicon.SUPERTYPES, supertypeNames));
+
+ batch.create(nodeTypePath).with(propsList).and();
+
+ PropertyDefinition[] propertyDefs = nodeType.getDeclaredPropertyDefinitions();
+ for (int i = 0; i < propertyDefs.length; i++) {
+ projectPropertyDefinitionOnto(propertyDefs[i], nodeTypePath, batch);
+ }
+
+ NodeDefinition[] childNodeDefs = nodeType.getDeclaredChildNodeDefinitions();
+ for (int i = 0; i < childNodeDefs.length; i++) {
+ projectChildNodeDefinitionOnto(childNodeDefs[i], nodeTypePath, batch);
+ }
+
+ }
+
+ /**
+ * Projects a single property definition onto the provided graph under the location
of <code>nodeTypePath</code>. The
+ * operations needed to create the property definition and any of its properties will
be added to the batch specified in
+ * <code>batch</code>.
+ * <p>
+ * All node creation is performed through the graph layer. If the primary type of the
node at <code>nodeTypePath</code> does
+ * not contain a residual definition that allows child nodes of type
<code>nt:propertyDefinition</code>, this method creates
+ * nodes for which the JCR layer cannot determine the corresponding node definition.
This WILL corrupt the graph from a JCR
+ * standpoint and make it unusable through the DNA JCR layer.
+ * </p>
+ *
+ * @param propertyDef the property definition to be projected
+ * @param nodeTypePath the path under which the property definition should be
projected
+ * @param batch the batch to which any required graph modification operations should
be added
+ * @see #projectOnto(Graph, Path)
+ */
+ private void projectPropertyDefinitionOnto( PropertyDefinition propertyDef,
+ Path nodeTypePath,
+ Graph.Batch batch ) {
+ assert propertyDef != null;
+ assert nodeTypePath != null;
+ assert batch != null;
+
+ JcrPropertyDefinition jcrPropDef = (JcrPropertyDefinition)propertyDef;
+ String propName =
jcrPropDef.getInternalName().getString(context.getNamespaceRegistry(), new
XmlNameEncoder());
+ Path propDefPath = pathFactory.create(nodeTypePath,
JcrLexicon.PROPERTY_DEFINITION);
+
+ List<Property> propsList = new ArrayList<Property>();
+ propsList.add(propertyFactory.create(JcrLexicon.PRIMARY_TYPE,
JcrNtLexicon.PROPERTY_DEFINITION));
+
+ if (!JcrNodeType.RESIDUAL_ITEM_NAME.equals(jcrPropDef.getName())) {
+ propsList.add(propertyFactory.create(JcrLexicon.NAME, propName));
+ }
+ propsList.add(propertyFactory.create(JcrLexicon.AUTO_CREATED,
jcrPropDef.isAutoCreated()));
+ propsList.add(propertyFactory.create(JcrLexicon.MANDATORY,
jcrPropDef.isMandatory()));
+ propsList.add(propertyFactory.create(JcrLexicon.MULTIPLE,
jcrPropDef.isMultiple()));
+ propsList.add(propertyFactory.create(JcrLexicon.PROTECTED,
jcrPropDef.isProtected()));
+ propsList.add(propertyFactory.create(JcrLexicon.ON_PARENT_VERSION,
+
OnParentVersionAction.nameFromValue(jcrPropDef.getOnParentVersion())));
+ propsList.add(propertyFactory.create(JcrLexicon.REQUIRED_TYPE,
PropertyType.nameFromValue(jcrPropDef.getRequiredType())));
+
+ Value[] defaultValues = jcrPropDef.getDefaultValues();
+ if (defaultValues.length > 0) {
+ String[] defaultsAsString = new String[defaultValues.length];
+
+ for (int i = 0; i < defaultValues.length; i++) {
+ try {
+ defaultsAsString[i] = defaultValues[i].getString();
+ } catch (RepositoryException re) {
+ // Really shouldn't get here as all values are convertible to
string
+ throw new IllegalStateException(re);
+ }
+ }
+ propsList.add(propertyFactory.create(JcrLexicon.DEFAULT_VALUES,
(Object[])defaultsAsString));
+ }
+
+ String[] valueConstraints = jcrPropDef.getValueConstraints();
+ if (valueConstraints.length > 0) {
+ propsList.add(propertyFactory.create(JcrLexicon.DEFAULT_VALUES,
(Object[])valueConstraints));
+ }
+ batch.create(propDefPath).with(propsList).and();
+ }
+
+ /**
+ * Projects a single child node definition onto the provided graph under the location
of <code>nodeTypePath</code>. The
+ * operations needed to create the child node definition and any of its properties
will be added to the batch specified in
+ * <code>batch</code>.
+ * <p>
+ * All node creation is performed through the graph layer. If the primary type of the
node at <code>nodeTypePath</code> does
+ * not contain a residual definition that allows child nodes of type
<code>nt:childNodeDefinition</code>, this method creates
+ * nodes for which the JCR layer cannot determine the corresponding node definition.
This WILL corrupt the graph from a JCR
+ * standpoint and make it unusable through the DNA JCR layer.
+ * </p>
+ *
+ * @param childNodeDef the child node definition to be projected
+ * @param nodeTypePath the path under which the child node definition should be
projected
+ * @param batch the batch to which any required graph modification operations should
be added
+ * @see #projectOnto(Graph, Path)
+ */
+ private void projectChildNodeDefinitionOnto( NodeDefinition childNodeDef,
+ Path nodeTypePath,
+ Graph.Batch batch ) {
+ assert childNodeDef != null;
+ assert nodeTypePath != null;
+ assert batch != null;
+
+ JcrNodeDefinition jcrNodeDef = (JcrNodeDefinition)childNodeDef;
+ String nodeName =
jcrNodeDef.getInternalName().getString(context.getNamespaceRegistry(), new
XmlNameEncoder());
+ Path nodeDefPath = pathFactory.create(nodeTypePath,
JcrLexicon.CHILD_NODE_DEFINITION);
+
+ List<Property> propsList = new ArrayList<Property>();
+ propsList.add(propertyFactory.create(JcrLexicon.PRIMARY_TYPE,
JcrNtLexicon.CHILD_NODE_DEFINITION));
+
+ if (!JcrNodeType.RESIDUAL_ITEM_NAME.equals(jcrNodeDef.getName())) {
+ propsList.add(propertyFactory.create(JcrLexicon.NAME, nodeName));
+ }
+
+ if (jcrNodeDef.getDefaultPrimaryType() != null) {
+ propsList.add(propertyFactory.create(JcrLexicon.DEFAULT_PRIMARY_TYPE,
jcrNodeDef.getDefaultPrimaryType().getName()));
+ }
+
+ propsList.add(propertyFactory.create(JcrLexicon.REQUIRED_PRIMARY_TYPES,
jcrNodeDef.getRequiredPrimaryTypeNames()));
+ propsList.add(propertyFactory.create(JcrLexicon.SAME_NAME_SIBLINGS,
jcrNodeDef.allowsSameNameSiblings()));
+ propsList.add(propertyFactory.create(JcrLexicon.ON_PARENT_VERSION,
+
OnParentVersionAction.nameFromValue(jcrNodeDef.getOnParentVersion())));
+ propsList.add(propertyFactory.create(JcrLexicon.AUTO_CREATED,
jcrNodeDef.isAutoCreated()));
+ propsList.add(propertyFactory.create(JcrLexicon.MANDATORY,
jcrNodeDef.isMandatory()));
+ propsList.add(propertyFactory.create(JcrLexicon.PROTECTED,
jcrNodeDef.isProtected()));
+
+ batch.create(nodeDefPath).with(propsList).and();
+ }
+
}
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrWorkspaceTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrWorkspaceTest.java 2009-04-02
18:52:26 UTC (rev 803)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrWorkspaceTest.java 2009-04-02
19:02:05 UTC (rev 804)
@@ -55,7 +55,8 @@
private Map<String, Object> sessionAttributes;
@Mock
private JcrRepository repository;
-
+ private RepositoryNodeTypeManager repoManager;
+
@Before
public void beforeEach() throws Exception {
final String repositorySourceName = "repository";
@@ -93,7 +94,14 @@
// Stub out the repository, since we only need a few methods ...
MockitoAnnotations.initMocks(this);
+
+ JcrNodeTypeSource source = null;
+ source = new JcrBuiltinNodeTypeSource(context, source);
+ source = new DnaBuiltinNodeTypeSource(context, source);
+ repoManager = new RepositoryNodeTypeManager(context, source);
+
stub(repository.getRepositorySourceName()).toReturn(repositorySourceName);
+ stub(repository.getRepositoryTypeManager()).toReturn(repoManager);
stub(repository.getConnectionFactory()).toReturn(connectionFactory);
// Now create the workspace ...
Added: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/RepositoryNodeTypeManagerTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/RepositoryNodeTypeManagerTest.java
(rev 0)
+++
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/RepositoryNodeTypeManagerTest.java 2009-04-02
19:02:05 UTC (rev 804)
@@ -0,0 +1,504 @@
+/*
+ * JBoss DNA (
http://www.jboss.org/dna)
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership. Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ * See the AUTHORS.txt file in the distribution for a full listing of
+ * individual contributors.
+ *
+ * JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
+ * is licensed to you under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * JBoss DNA is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.jboss.dna.jcr;
+
+import static org.hamcrest.Matchers.greaterThan;
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsNull.notNullValue;
+import static org.hamcrest.core.IsNull.nullValue;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.stub;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+import javax.jcr.PathNotFoundException;
+import javax.jcr.Property;
+import javax.jcr.PropertyType;
+import javax.jcr.Value;
+import javax.jcr.nodetype.NodeDefinition;
+import javax.jcr.nodetype.NodeType;
+import javax.jcr.nodetype.PropertyDefinition;
+import javax.jcr.version.OnParentVersionAction;
+import org.jboss.dna.graph.ExecutionContext;
+import org.jboss.dna.graph.Graph;
+import org.jboss.dna.graph.connector.RepositoryConnection;
+import org.jboss.dna.graph.connector.RepositoryConnectionFactory;
+import org.jboss.dna.graph.connector.RepositorySourceException;
+import org.jboss.dna.graph.connector.inmemory.InMemoryRepositorySource;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.NamespaceRegistry;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.MockitoAnnotations;
+import org.mockito.MockitoAnnotations.Mock;
+
+public class RepositoryNodeTypeManagerTest {
+
+ private String workspaceName;
+ private ExecutionContext context;
+ private InMemoryRepositorySource source;
+ private JcrWorkspace workspace;
+ private JcrSession session;
+ private Graph graph;
+ private RepositoryConnectionFactory connectionFactory;
+ private RepositoryNodeTypeManager repoTypeManager;
+ private Map<String, Object> sessionAttributes;
+ @Mock
+ private JcrRepository repository;
+
+ @Before
+ public void beforeEach() throws Exception {
+ MockitoAnnotations.initMocks(this);
+
+ workspaceName = "workspace1";
+ final String repositorySourceName = "repository";
+
+ // Set up the source ...
+ source = new InMemoryRepositorySource();
+ source.setName(workspaceName);
+ source.setDefaultWorkspaceName(workspaceName);
+
+ // Set up the execution context ...
+ context = new ExecutionContext();
+ // Register the test namespace
+ context.getNamespaceRegistry().register(TestLexicon.Namespace.PREFIX,
TestLexicon.Namespace.URI);
+
+ // Set up the initial content ...
+ graph = Graph.create(source, context);
+
+ // Make sure the path to the namespaces exists ...
+ graph.create("/jcr:system"); //
.and().create("/jcr:system/dna:namespaces");
+
graph.set("jcr:primaryType").on("/jcr:system").to(DnaLexicon.SYSTEM);
+
+
graph.create("/a").and().create("/a/b").and().create("/a/b/c");
+
graph.set("jcr:mixinTypes").on("/a").to(JcrMixLexicon.REFERENCEABLE);
+
+ // Stub out the connection factory ...
+ connectionFactory = new RepositoryConnectionFactory() {
+ /**
+ * {@inheritDoc}
+ *
+ * @see
org.jboss.dna.graph.connector.RepositoryConnectionFactory#createConnection(java.lang.String)
+ */
+ @SuppressWarnings( "synthetic-access" )
+ public RepositoryConnection createConnection( String sourceName ) throws
RepositorySourceException {
+ return repositorySourceName.equals(sourceName) ? source.getConnection() :
null;
+ }
+ };
+
+ // Stub out the repository, since we only need a few methods ...
+ JcrNodeTypeSource source = null;
+ source = new JcrBuiltinNodeTypeSource(this.context, source);
+ source = new DnaBuiltinNodeTypeSource(this.context, source);
+ repoTypeManager = new RepositoryNodeTypeManager(context, source);
+ stub(repository.getRepositoryTypeManager()).toReturn(repoTypeManager);
+ stub(repository.getRepositorySourceName()).toReturn(repositorySourceName);
+ stub(repository.getConnectionFactory()).toReturn(connectionFactory);
+
+ // Set up the session attributes ...
+ sessionAttributes = new HashMap<String, Object>();
+ sessionAttributes.put("attribute1", "value1");
+
+ // Now create the workspace ...
+ workspace = new JcrWorkspace(repository, workspaceName, context,
sessionAttributes);
+
+ // Create the session and log in ...
+ session = (JcrSession)workspace.getSession();
+
+
graph.set("jcr:primaryType").on("/jcr:system/dna:namespaces").to(DnaLexicon.NAMESPACES);
+
+ }
+
+ @After
+ public void after() throws Exception {
+ if (session != null && session.isLive()) {
+ session.logout();
+ }
+ }
+
+ @Test
+ public void shouldOnlyHaveOneDnaNamespacesNode() throws Exception {
+ NamespaceRegistry registry = context.getNamespaceRegistry();
+
+ Node rootNode = session.getRootNode();
+ assertThat(rootNode, is(notNullValue()));
+
+ Node systemNode = rootNode.getNode(JcrLexicon.SYSTEM.getString(registry));
+ assertThat(systemNode, is(notNullValue()));
+
+ NodeIterator namespacesNodes =
systemNode.getNodes(DnaLexicon.NAMESPACES.getString(registry));
+ assertEquals(namespacesNodes.getSize(), 1);
+ }
+
+ @Test
+ public void shouldOnlyHaveOneNodeTypesNode() throws Exception {
+ NamespaceRegistry registry = context.getNamespaceRegistry();
+
+ Node rootNode = session.getRootNode();
+ assertThat(rootNode, is(notNullValue()));
+
+ Node systemNode = rootNode.getNode(JcrLexicon.SYSTEM.getString(registry));
+ assertThat(systemNode, is(notNullValue()));
+
+ NodeIterator nodeTypesNodes =
systemNode.getNodes(JcrLexicon.NODE_TYPES.getString(registry));
+ assertEquals(nodeTypesNodes.getSize(), 1);
+ }
+
+ @Test
+ public void shouldAllowMultipleSiblingsDefinitionIfOneSibling() throws Exception {
+ NamespaceRegistry registry = context.getNamespaceRegistry();
+
+ // There's no definition for this node or for a * child node that does not
allow SNS
+ JcrNodeDefinition def =
repoTypeManager.findChildNodeDefinition(JcrNtLexicon.NODE_TYPE,
+
Collections.<Name>emptyList(),
+
JcrLexicon.PROPERTY_DEFINITION,
+
JcrNtLexicon.PROPERTY_DEFINITION,
+ 1,
+ false);
+
+ assertThat(def, is(notNullValue()));
+ assertEquals(def.getName(), JcrLexicon.PROPERTY_DEFINITION.getString(registry));
+ }
+
+ public void shouldProjectOntoWorkspaceGraph() throws Exception {
+ // projectOnto is called in the JcrWorkspace constructor... just test that the
nodes show up
+ NamespaceRegistry registry = context.getNamespaceRegistry();
+
+ Node rootNode = session.getRootNode();
+ assertThat(rootNode, is(notNullValue()));
+
+ Node systemNode = rootNode.getNode(JcrLexicon.SYSTEM.getString(registry));
+ assertThat(systemNode, is(notNullValue()));
+
+ Node typesNode = systemNode.getNode(JcrLexicon.NODE_TYPES.getString(registry));
+ assertThat(typesNode, is(notNullValue()));
+
+ Collection<JcrNodeType> allNodeTypes = repoTypeManager.getAllNodeTypes();
+ assertThat(allNodeTypes.size(), greaterThan(0));
+ for (JcrNodeType nodeType : allNodeTypes) {
+ Node typeNode = typesNode.getNode(nodeType.getName());
+
+ compareNodeTypes(nodeType, typeNode, registry);
+
+ }
+ }
+
+ private void compareNodeTypes( JcrNodeType nodeType,
+ Node typeNode,
+ NamespaceRegistry registry ) throws Exception {
+ assertThat(nodeType.isMixin(),
is(typeNode.getProperty(JcrLexicon.IS_MIXIN.getString(registry)).getBoolean()));
+ assertThat(nodeType.hasOrderableChildNodes(),
+
is(typeNode.getProperty(JcrLexicon.HAS_ORDERABLE_CHILD_NODES.getString(registry)).getBoolean()));
+ try {
+ assertThat(nodeType.getPrimaryItemName(),
is(typeNode.getProperty(JcrLexicon.PRIMARY_ITEM_NAME.getString(registry))
+ .getString()));
+ } catch (PathNotFoundException pnfe) {
+ assertThat(nodeType.getPrimaryItemName(), is(nullValue()));
+ }
+ assertThat(nodeType.getName(),
is(typeNode.getProperty(JcrLexicon.NODE_TYPE_NAME.getString(registry)).getString()));
+
+ NodeType[] supertypesFromManager = nodeType.getDeclaredSupertypes();
+ Value[] supertypesFromGraph = new Value[0];
+ try {
+ supertypesFromGraph =
typeNode.getProperty(JcrLexicon.SUPERTYPES.getString(registry)).getValues();
+ } catch (PathNotFoundException pnfe) {
+ // Not a mandatory property
+ }
+
+ assertThat(supertypesFromGraph.length, is(supertypesFromManager.length));
+ for (int i = 0; i < supertypesFromManager.length; i++) {
+ assertEquals(supertypesFromManager[i].getName(),
supertypesFromGraph[i].getString());
+ }
+
+ Map<PropertyDefinitionKey, Node> propertyDefsFromGraph = new
HashMap<PropertyDefinitionKey, Node>();
+ NodeIterator properties =
typeNode.getNodes(JcrLexicon.PROPERTY_DEFINITION.getString(registry));
+ while (properties.hasNext()) {
+ Node def = properties.nextNode();
+ propertyDefsFromGraph.put(new PropertyDefinitionKey(def, registry), def);
+ }
+
+ PropertyDefinition[] propertyDefs = nodeType.getDeclaredPropertyDefinitions();
+ for (int i = 0; i < propertyDefs.length; i++) {
+ JcrPropertyDefinition propertyDef = (JcrPropertyDefinition)propertyDefs[i];
+ Node propNode = propertyDefsFromGraph.get(new
PropertyDefinitionKey(propertyDef));
+ compareProperty(propertyDef, propNode, registry);
+ }
+
+ Map<NodeDefinitionKey, Node> nodeDefsFromGraph = new
HashMap<NodeDefinitionKey, Node>();
+ NodeIterator nodes =
typeNode.getNodes(JcrLexicon.CHILD_NODE_DEFINITION.getString(registry));
+ while (nodes.hasNext()) {
+ Node def = nodes.nextNode();
+ nodeDefsFromGraph.put(new NodeDefinitionKey(def, registry), def);
+ }
+
+ NodeDefinition[] nodeDefs = nodeType.getDeclaredChildNodeDefinitions();
+ for (int i = 0; i < nodeDefs.length; i++) {
+ JcrNodeDefinition childNodeDef = (JcrNodeDefinition)nodeDefs[i];
+ Node childNodeNode = nodeDefsFromGraph.get(new
NodeDefinitionKey(childNodeDef));
+
+ compareChildNode(childNodeDef, childNodeNode, registry);
+ }
+ }
+
+ private void compareChildNode( JcrNodeDefinition nodeDef,
+ Node childNodeNode,
+ NamespaceRegistry registry ) throws Exception {
+ assertThat(childNodeNode, is(notNullValue()));
+
+ try {
+ Property nameProp =
childNodeNode.getProperty(JcrLexicon.NAME.getString(registry));
+ assertEquals(nameProp.getString(), nodeDef.getName());
+ } catch (PathNotFoundException pnfe) {
+ assertThat(nodeDef.getName(), is(JcrNodeType.RESIDUAL_ITEM_NAME));
+ }
+
+ Set<Name> requiredPrimaryTypeNames =
nodeDef.getRequiredPrimaryTypeNames();
+ try {
+ Value[] requiredPrimaryTypes =
childNodeNode.getProperty(JcrLexicon.REQUIRED_PRIMARY_TYPES.getString(registry))
+ .getValues();
+ assertEquals(requiredPrimaryTypes.length, requiredPrimaryTypeNames.size());
+ for (int i = 0; i < requiredPrimaryTypes.length; i++) {
+ Name rptName =
context.getValueFactories().getNameFactory().create(requiredPrimaryTypes[i].getString());
+ assertEquals(requiredPrimaryTypeNames.contains(rptName), true);
+ }
+ } catch (PathNotFoundException pnfe) {
+ assertEquals(requiredPrimaryTypeNames.size(), 0);
+ }
+
+ try {
+ Property nameProp =
childNodeNode.getProperty(JcrLexicon.DEFAULT_PRIMARY_TYPE.getString(registry));
+ assertEquals(nameProp.getString(),
nodeDef.getDefaultPrimaryType().getName());
+ } catch (PathNotFoundException pnfe) {
+ assertThat(nodeDef.getDefaultPrimaryType(), is(nullValue()));
+ }
+
+ assertEquals(nodeDef.isAutoCreated(),
childNodeNode.getProperty(JcrLexicon.AUTO_CREATED.getString(registry)).getBoolean());
+ assertEquals(nodeDef.isMandatory(),
childNodeNode.getProperty(JcrLexicon.MANDATORY.getString(registry)).getBoolean());
+ assertEquals(nodeDef.isProtected(),
childNodeNode.getProperty(JcrLexicon.PROTECTED.getString(registry)).getBoolean());
+ assertEquals(nodeDef.allowsSameNameSiblings(),
+
childNodeNode.getProperty(JcrLexicon.SAME_NAME_SIBLINGS.getString(registry)).getBoolean());
+ assertEquals(nodeDef.getOnParentVersion(),
+
OnParentVersionAction.valueFromName(childNodeNode.getProperty(JcrLexicon.ON_PARENT_VERSION.getString(registry))
+ .getString()));
+
+ }
+
+ private void compareProperty( JcrPropertyDefinition propertyDef,
+ Node propNode,
+ NamespaceRegistry registry ) throws Exception {
+ assertThat(propNode, is(notNullValue()));
+
+ try {
+ Property nameProp =
propNode.getProperty(JcrLexicon.NAME.getString(registry));
+ assertEquals(nameProp.getString(), propertyDef.getName());
+ } catch (PathNotFoundException pnfe) {
+ assertThat(propertyDef.getName(), is(JcrNodeType.RESIDUAL_ITEM_NAME));
+ }
+
+ assertEquals(propertyDef.isAutoCreated(),
propNode.getProperty(JcrLexicon.AUTO_CREATED.getString(registry)).getBoolean());
+ assertEquals(propertyDef.isMandatory(),
propNode.getProperty(JcrLexicon.MANDATORY.getString(registry)).getBoolean());
+ assertEquals(propertyDef.isMultiple(),
propNode.getProperty(JcrLexicon.MULTIPLE.getString(registry)).getBoolean());
+ assertEquals(propertyDef.isProtected(),
propNode.getProperty(JcrLexicon.PROTECTED.getString(registry)).getBoolean());
+ assertEquals(propertyDef.getOnParentVersion(),
+
OnParentVersionAction.valueFromName(propNode.getProperty(JcrLexicon.ON_PARENT_VERSION.getString(registry))
+ .getString()));
+ assertEquals(propertyDef.getRequiredType(),
+
PropertyType.valueFromName(propNode.getProperty(JcrLexicon.REQUIRED_TYPE.getString(registry)).getString()));
+
+ Value[] defaultValues = propertyDef.getDefaultValues();
+ try {
+ Property defaultsProp =
propNode.getProperty(JcrLexicon.DEFAULT_VALUES.getString(registry));
+ Value[] defaultsFromGraph = defaultsProp.getValues();
+
+ assertEquals(defaultValues.length, defaultsFromGraph.length);
+ for (int i = 0; i < defaultValues.length; i++) {
+ assertEquals(defaultValues[i].getString(),
defaultsFromGraph[i].getString());
+ }
+ } catch (PathNotFoundException pnfe) {
+ assertEquals(defaultValues.length, 0);
+
+ }
+
+ String[] constraintValues = propertyDef.getValueConstraints();
+ try {
+ Property constraintsProp =
propNode.getProperty(JcrLexicon.VALUE_CONSTRAINTS.getString(registry));
+ Value[] constraintsFromGraph = constraintsProp.getValues();
+
+ assertEquals(constraintValues.length, constraintsFromGraph.length);
+ for (int i = 0; i < constraintValues.length; i++) {
+ assertEquals(constraintValues[i], constraintsFromGraph[i].getString());
+ }
+ } catch (PathNotFoundException pnfe) {
+ assertEquals(constraintValues.length, 0);
+ }
+ }
+
+ // @Test
+ // public void shouldInferEmptyFromBadPath() throws Exception {
+ // PathFactory pathFactory = context.getValueFactories().getPathFactory();
+ // assertThat(repoTypeManager.inferFrom(graph,
pathFactory.create("/a")).isEmpty(), is(true));
+ // }
+ //
+ // @Test
+ // public void shouldInferEmptyFromInvalidPath() throws Exception {
+ // PathFactory pathFactory = context.getValueFactories().getPathFactory();
+ // assertThat(repoTypeManager.inferFrom(graph,
pathFactory.create("/abc")).isEmpty(), is(true));
+ // }
+ //
+ // @Test
+ // public void shouldInferOwnTypesFromOwnProjection() throws Exception {
+ // PathFactory pathFactory = context.getValueFactories().getPathFactory();
+ // Path nodeTypePath = pathFactory.create(pathFactory.createRootPath(),
JcrLexicon.SYSTEM, JcrLexicon.NODE_TYPES);
+ //
+ // Collection<JcrNodeType> inferredTypes = repoTypeManager.inferFrom(graph,
nodeTypePath);
+ //
+ // Collection<JcrNodeType> allNodeTypes = repoTypeManager.getAllNodeTypes();
+ // assertThat(inferredTypes.size(), is(allNodeTypes.size()));
+ //
+ // Map<Name, JcrNodeType> allNodeTypesByName = new HashMap<Name,
JcrNodeType>();
+ // for (JcrNodeType jnt : allNodeTypes) {
+ // allNodeTypesByName.put(jnt.getInternalName(), jnt);
+ // }
+ //
+ // for (JcrNodeType nodeType : inferredTypes) {
+ // JcrNodeType other = allNodeTypesByName.get(nodeType.getInternalName());
+ //
+ // System.out.println("Checking: " + other.getName());
+ //
+ // assertThat(other, is(notNullValue()));
+ // assertThat(areSame(nodeType, other), is(true));
+ // }
+ // }
+
+ /**
+ * Internal class that encapsulates composite unique identifier for property
definitions
+ */
+ class PropertyDefinitionKey {
+ String keyString;
+
+ PropertyDefinitionKey( Node node,
+ NamespaceRegistry registry ) throws Exception {
+ String propertyName = JcrNodeType.RESIDUAL_ITEM_NAME;
+
+ try {
+ propertyName =
node.getProperty(JcrLexicon.NAME.getString(registry)).getString();
+ } catch (PathNotFoundException pnfe) {
+ // Ignorable, means name is not set.
+ }
+ String requiredType =
node.getProperty(JcrLexicon.REQUIRED_TYPE.getString(registry)).getString();
+ boolean allowsMultiple =
node.getProperty(JcrLexicon.MULTIPLE.getString(registry)).getBoolean();
+
+ this.keyString = propertyName + "-" + requiredType + "-"
+ allowsMultiple;
+ }
+
+ PropertyDefinitionKey( PropertyDefinition def ) {
+ String requiredType = PropertyType.nameFromValue(def.getRequiredType());
+
+ this.keyString = def.getName() + "-" + requiredType + "-"
+ def.isMultiple();
+ }
+
+ @Override
+ public boolean equals( Object ob ) {
+ if (!(ob instanceof PropertyDefinitionKey)) {
+ return false;
+ }
+
+ return keyString.equals(((PropertyDefinitionKey)ob).keyString);
+ }
+
+ @Override
+ public int hashCode() {
+ return keyString.hashCode();
+ }
+ }
+
+ /**
+ * Internal class that encapsulates composite unique identifier for child node
definitions
+ */
+ class NodeDefinitionKey {
+ String keyString;
+
+ NodeDefinitionKey( Node node,
+ NamespaceRegistry registry ) throws Exception {
+ StringBuffer buff = new StringBuffer();
+
+ try {
+ String nodeName =
node.getProperty(JcrLexicon.NAME.getString(registry)).getString();
+ buff.append(nodeName);
+ } catch (PathNotFoundException pnfe) {
+ // Ignorable, means name is not set.
+ buff.append(JcrNodeType.RESIDUAL_ITEM_NAME);
+ }
+
+ try {
+ Value[] requiredTypes =
node.getProperty(JcrLexicon.REQUIRED_PRIMARY_TYPES.getString(registry)).getValues();
+
+ for (int i = 0; i < requiredTypes.length; i++) {
+ buff.append('_').append(requiredTypes[i].getString());
+ }
+ } catch (PathNotFoundException pnfe) {
+ // No required types. Weird, but not debilitating.
+ }
+
+
buff.append('_').append(node.getProperty(JcrLexicon.SAME_NAME_SIBLINGS.getString(registry)).getBoolean());
+
+ this.keyString = buff.toString();
+ }
+
+ NodeDefinitionKey( NodeDefinition def ) {
+ StringBuffer buff = new StringBuffer();
+ buff.append(def.getName());
+
+ NodeType[] requiredTypes = def.getRequiredPrimaryTypes();
+ for (int i = 0; i < requiredTypes.length; i++) {
+ buff.append('_').append(requiredTypes[i].getName());
+ }
+
+ buff.append('_').append(def.allowsSameNameSiblings());
+
+ this.keyString = buff.toString();
+ }
+
+ @Override
+ public boolean equals( Object ob ) {
+ if (!(ob instanceof NodeDefinitionKey)) {
+ return false;
+ }
+
+ return keyString.equals(((NodeDefinitionKey)ob).keyString);
+ }
+
+ @Override
+ public int hashCode() {
+ return keyString.hashCode();
+ }
+ }
+
+}
Property changes on:
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/RepositoryNodeTypeManagerTest.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain