DNA SVN: r795 - in trunk/dna-jcr/src: test/java/org/jboss/dna/jcr and 1 other directory.
by dna-commits@lists.jboss.org
Author: rhauch
Date: 2009-03-24 18:33:26 -0400 (Tue, 24 Mar 2009)
New Revision: 795
Added:
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/PropertyTypeUtil.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/Vehicles.java
Modified:
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrProperty.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrMultiValueProperty.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSession.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSingleValueProperty.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/SessionCache.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/AbstractJcrPropertyTest.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrSessionTest.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/SessionCacheTest.java
Log:
DNA-194 Implement update JCR capability
Added (and tested) functionality to set properties and remove properties. However, none of the TCK unit tests could be run, however, since adding nodes appears to be a prerequisite of all of the Level 2 TCK unit tests.
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrProperty.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrProperty.java 2009-03-24 18:16:53 UTC (rev 794)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrProperty.java 2009-03-24 22:33:26 UTC (rev 795)
@@ -23,15 +23,12 @@
*/
package org.jboss.dna.jcr;
-import java.io.InputStream;
-import java.util.Calendar;
import javax.jcr.Item;
import javax.jcr.ItemVisitor;
import javax.jcr.Node;
import javax.jcr.PathNotFoundException;
import javax.jcr.Property;
import javax.jcr.RepositoryException;
-import javax.jcr.Value;
import javax.jcr.nodetype.PropertyDefinition;
import net.jcip.annotations.NotThreadSafe;
import org.jboss.dna.common.util.CheckArg;
@@ -45,7 +42,7 @@
@NotThreadSafe
abstract class AbstractJcrProperty extends AbstractJcrItem implements Property {
- private final PropertyId propertyId;
+ protected final PropertyId propertyId;
AbstractJcrProperty( SessionCache cache,
PropertyId propertyId ) {
@@ -81,6 +78,11 @@
return new JcrValue(context().getValueFactories(), this.cache, propertyInfo().getPropertyType(), value);
}
+ final JcrValue createValue( Object value,
+ int propertyType ) {
+ return new JcrValue(context().getValueFactories(), this.cache, propertyType, value);
+ }
+
@Override
Path path() throws RepositoryException {
return cache.getPathFor(propertyInfo());
@@ -168,106 +170,6 @@
* {@inheritDoc}
*
* @throws UnsupportedOperationException always
- * @see javax.jcr.Property#setValue(javax.jcr.Value)
- */
- public final void setValue( Value value ) {
- throw new UnsupportedOperationException();
- }
-
- /**
- * {@inheritDoc}
- *
- * @throws UnsupportedOperationException always
- * @see javax.jcr.Property#setValue(javax.jcr.Value[])
- */
- public final void setValue( Value[] values ) {
- throw new UnsupportedOperationException();
- }
-
- /**
- * {@inheritDoc}
- *
- * @throws UnsupportedOperationException always
- * @see javax.jcr.Property#setValue(java.lang.String)
- */
- public final void setValue( String value ) {
- throw new UnsupportedOperationException();
- }
-
- /**
- * {@inheritDoc}
- *
- * @throws UnsupportedOperationException always
- * @see javax.jcr.Property#setValue(java.lang.String[])
- */
- public final void setValue( String[] values ) {
- throw new UnsupportedOperationException();
- }
-
- /**
- * {@inheritDoc}
- *
- * @throws UnsupportedOperationException always
- * @see javax.jcr.Property#setValue(java.io.InputStream)
- */
- public final void setValue( InputStream value ) {
- throw new UnsupportedOperationException();
- }
-
- /**
- * {@inheritDoc}
- *
- * @throws UnsupportedOperationException always
- * @see javax.jcr.Property#setValue(long)
- */
- public final void setValue( long value ) {
- throw new UnsupportedOperationException();
- }
-
- /**
- * {@inheritDoc}
- *
- * @throws UnsupportedOperationException always
- * @see javax.jcr.Property#setValue(double)
- */
- public final void setValue( double value ) {
- throw new UnsupportedOperationException();
- }
-
- /**
- * {@inheritDoc}
- *
- * @throws UnsupportedOperationException always
- * @see javax.jcr.Property#setValue(java.util.Calendar)
- */
- public final void setValue( Calendar value ) {
- throw new UnsupportedOperationException();
- }
-
- /**
- * {@inheritDoc}
- *
- * @throws UnsupportedOperationException always
- * @see javax.jcr.Property#setValue(boolean)
- */
- public final void setValue( boolean value ) {
- throw new UnsupportedOperationException();
- }
-
- /**
- * {@inheritDoc}
- *
- * @throws UnsupportedOperationException always
- * @see javax.jcr.Property#setValue(javax.jcr.Node)
- */
- public final void setValue( Node value ) {
- throw new UnsupportedOperationException();
- }
-
- /**
- * {@inheritDoc}
- *
- * @throws UnsupportedOperationException always
* @see javax.jcr.Item#refresh(boolean)
*/
public void refresh( boolean keepChanges ) {
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrMultiValueProperty.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrMultiValueProperty.java 2009-03-24 18:16:53 UTC (rev 794)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrMultiValueProperty.java 2009-03-24 22:33:26 UTC (rev 795)
@@ -27,11 +27,16 @@
import java.util.Calendar;
import java.util.Iterator;
import javax.jcr.Node;
+import javax.jcr.PropertyType;
import javax.jcr.RepositoryException;
import javax.jcr.Value;
import javax.jcr.ValueFormatException;
+import javax.jcr.lock.LockException;
+import javax.jcr.nodetype.ConstraintViolationException;
+import javax.jcr.version.VersionException;
import net.jcip.annotations.NotThreadSafe;
import org.jboss.dna.graph.property.Property;
+import org.jboss.dna.graph.property.ValueFactory;
/**
* @author jverhaeg
@@ -140,16 +145,6 @@
/**
* {@inheritDoc}
- *
- * @throws ValueFormatException always
- * @see javax.jcr.Property#getValue()
- */
- public Value getValue() throws ValueFormatException {
- throw new ValueFormatException();
- }
-
- /**
- * {@inheritDoc}
* <p>
* Per the JCR specification, these values need to be created each time this method is called, since the Value cannot be used
* after {@link Value#getStream()} is called/processed. The spec says that the client simply needs to obtain a new Value (or
@@ -167,4 +162,176 @@
}
return values;
}
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see javax.jcr.Property#setValue(javax.jcr.Value[])
+ */
+ public final void setValue( Value[] values )
+ throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
+ JcrValue[] jcrValues = null;
+ if (values != null && values.length != 0) {
+ int numValues = values.length;
+ jcrValues = new JcrValue[numValues];
+ ValueFactory<?> factory = null;
+ for (int i = 0; i != numValues; ++i) {
+ Value value = values[i];
+ if (value instanceof JcrValue) {
+ // just use the value ...
+ jcrValues[i] = (JcrValue)value;
+ } else {
+ // This isn't our implementation, so create one for use
+ if (factory == null) {
+ int currentType = this.getType();
+ factory = context().getValueFactories().getValueFactory(PropertyTypeUtil.dnaPropertyTypeFor(currentType));
+ }
+ int type = value.getType();
+ Object data = null;
+ switch (value.getType()) {
+ case PropertyType.STRING:
+ data = value.getString();
+ break;
+ case PropertyType.BINARY:
+ data = value.getStream();
+ break;
+ case PropertyType.BOOLEAN:
+ data = value.getBoolean();
+ break;
+ case PropertyType.DATE:
+ data = value.getDate();
+ break;
+ case PropertyType.DOUBLE:
+ data = value.getDouble();
+ break;
+ case PropertyType.LONG:
+ data = value.getLong();
+ break;
+ case PropertyType.NAME:
+ data = value.getString();
+ break;
+ case PropertyType.PATH:
+ data = value.getString();
+ break;
+ case PropertyType.REFERENCE:
+ data = value.getString();
+ break;
+ default:
+ throw new RepositoryException();
+ }
+ jcrValues[i] = createValue(factory.create(data), type);
+ }
+ }
+ }
+ cache.getEditorFor(propertyId.getNodeId()).setProperty(propertyId.getPropertyName(), jcrValues);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see javax.jcr.Property#setValue(java.lang.String[])
+ */
+ public final void setValue( String[] values )
+ throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
+ JcrValue[] jcrValues = null;
+ if (values != null && values.length != 0) {
+ int numValues = values.length;
+ jcrValues = new JcrValue[numValues];
+ for (int i = 0; i != numValues; ++i) {
+ jcrValues[i] = createValue(values[i], PropertyType.STRING);
+ }
+ }
+ cache.getEditorFor(propertyId.getNodeId()).setProperty(propertyId.getPropertyName(), jcrValues);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @throws ValueFormatException always
+ * @see javax.jcr.Property#getValue()
+ */
+ public Value getValue() throws ValueFormatException {
+ throw new ValueFormatException();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @throws ValueFormatException always
+ * @see javax.jcr.Property#setValue(javax.jcr.Value)
+ */
+ public final void setValue( Value value ) throws ValueFormatException {
+ throw new ValueFormatException();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @throws ValueFormatException always
+ * @see javax.jcr.Property#setValue(java.lang.String)
+ */
+ public final void setValue( String value ) throws ValueFormatException {
+ throw new ValueFormatException();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @throws ValueFormatException always
+ * @see javax.jcr.Property#setValue(java.io.InputStream)
+ */
+ public final void setValue( InputStream value ) throws ValueFormatException {
+ throw new ValueFormatException();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @throws ValueFormatException always
+ * @see javax.jcr.Property#setValue(long)
+ */
+ public final void setValue( long value ) throws ValueFormatException {
+ throw new ValueFormatException();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @throws ValueFormatException always
+ * @see javax.jcr.Property#setValue(double)
+ */
+ public final void setValue( double value ) throws ValueFormatException {
+ throw new ValueFormatException();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @throws ValueFormatException always
+ * @see javax.jcr.Property#setValue(java.util.Calendar)
+ */
+ public final void setValue( Calendar value ) throws ValueFormatException {
+ throw new ValueFormatException();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @throws ValueFormatException always
+ * @see javax.jcr.Property#setValue(boolean)
+ */
+ public final void setValue( boolean value ) throws ValueFormatException {
+ throw new ValueFormatException();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @throws ValueFormatException always
+ * @see javax.jcr.Property#setValue(javax.jcr.Node)
+ */
+ public final void setValue( Node value ) throws ValueFormatException {
+ throw new ValueFormatException();
+ }
+
}
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSession.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSession.java 2009-03-24 18:16:53 UTC (rev 794)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSession.java 2009-03-24 22:33:26 UTC (rev 795)
@@ -573,53 +573,6 @@
}
/**
- * Compute the JCR {@link PropertyType} for the given DNA {@link org.jboss.dna.graph.property.PropertyType}.
- * <p>
- * See DNA-293 for complete discussion on why this method works the way it does. The best option appears to be basing the
- * PropertyType on the first value, since that should be compatible with the PropertyType that was used when the values were
- * set on the property in the first place.
- * </p>
- *
- * @param property the DNA property for which the {@link PropertyType} is to be determined; never null
- * @return the JCR property type; always a valid value and never {@link PropertyType#UNDEFINED}.
- */
- static final int jcrPropertyTypeFor( org.jboss.dna.graph.property.Property property ) {
- Object value = property.getFirstValue();
-
- // Get the DNA property type for this ...
- switch (org.jboss.dna.graph.property.PropertyType.discoverType(value)) {
- case STRING:
- return PropertyType.STRING;
- case NAME:
- return PropertyType.NAME;
- case LONG:
- return PropertyType.LONG;
- case UUID:
- return PropertyType.STRING; // JCR treats UUID properties as strings
- case URI:
- return PropertyType.STRING;
- case PATH:
- return PropertyType.PATH;
- case BOOLEAN:
- return PropertyType.BOOLEAN;
- case DATE:
- return PropertyType.DATE;
- case DECIMAL:
- return PropertyType.STRING; // better than losing information
- case DOUBLE:
- return PropertyType.DOUBLE;
- case BINARY:
- return PropertyType.BINARY;
- case OBJECT:
- return PropertyType.UNDEFINED;
- case REFERENCE:
- return PropertyType.REFERENCE;
- }
- assert false;
- return PropertyType.UNDEFINED;
- }
-
- /**
* {@inheritDoc}
*
* @see javax.jcr.Session#refresh(boolean)
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSingleValueProperty.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSingleValueProperty.java 2009-03-24 18:16:53 UTC (rev 794)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSingleValueProperty.java 2009-03-24 22:33:26 UTC (rev 795)
@@ -27,9 +27,13 @@
import java.util.Calendar;
import java.util.UUID;
import javax.jcr.Node;
+import javax.jcr.PropertyType;
import javax.jcr.RepositoryException;
import javax.jcr.Value;
import javax.jcr.ValueFormatException;
+import javax.jcr.lock.LockException;
+import javax.jcr.nodetype.ConstraintViolationException;
+import javax.jcr.version.VersionException;
import org.jboss.dna.graph.property.Binary;
import org.jboss.dna.graph.property.Reference;
import org.jboss.dna.graph.property.ValueFactories;
@@ -170,6 +174,129 @@
/**
* {@inheritDoc}
*
+ * @see javax.jcr.Property#setValue(javax.jcr.Value)
+ */
+ public void setValue( Value value )
+ throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
+ JcrValue jcrValue = null;
+ if (value instanceof JcrValue) {
+ jcrValue = (JcrValue)value;
+ cache.getEditorFor(propertyId.getNodeId()).setProperty(propertyId.getPropertyName(), jcrValue);
+ return;
+ }
+ // We have to convert from one Value implementation to ours ...
+ switch (value.getType()) {
+ case PropertyType.STRING:
+ setValue(value.getString());
+ break;
+ case PropertyType.BINARY:
+ setValue(value.getStream());
+ break;
+ case PropertyType.BOOLEAN:
+ setValue(value.getBoolean());
+ break;
+ case PropertyType.DATE:
+ setValue(value.getDate());
+ break;
+ case PropertyType.DOUBLE:
+ setValue(value.getDouble());
+ break;
+ case PropertyType.LONG:
+ setValue(value.getLong());
+ break;
+ case PropertyType.NAME:
+ setValue(value.getString());
+ break;
+ case PropertyType.PATH:
+ setValue(value.getString());
+ break;
+ case PropertyType.REFERENCE:
+ setValue(value.getString());
+ break;
+ default:
+ throw new RepositoryException();
+ }
+ }
+
+ protected void setValue( JcrValue jcrValue )
+ throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
+ cache.getEditorFor(propertyId.getNodeId()).setProperty(propertyId.getPropertyName(), jcrValue);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see javax.jcr.Property#setValue(java.lang.String)
+ */
+ public void setValue( String value )
+ throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
+ setValue(createValue(value, PropertyType.STRING));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see javax.jcr.Property#setValue(java.io.InputStream)
+ */
+ public void setValue( InputStream value )
+ throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
+ setValue(createValue(context().getValueFactories().getBinaryFactory().create(value), PropertyType.DATE));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see javax.jcr.Property#setValue(long)
+ */
+ public void setValue( long value )
+ throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
+ setValue(createValue(new Long(value), PropertyType.LONG));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see javax.jcr.Property#setValue(double)
+ */
+ public void setValue( double value )
+ throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
+ setValue(createValue(new Double(value), PropertyType.DOUBLE));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see javax.jcr.Property#setValue(java.util.Calendar)
+ */
+ public void setValue( Calendar value )
+ throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
+ setValue(createValue(context().getValueFactories().getDateFactory().create(value), PropertyType.DATE));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see javax.jcr.Property#setValue(boolean)
+ */
+ public void setValue( boolean value )
+ throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
+ setValue(createValue(new Boolean(value), PropertyType.BOOLEAN));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see javax.jcr.Property#setValue(javax.jcr.Node)
+ */
+ public void setValue( Node value )
+ throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
+ String uuid = value.getUUID();
+ setValue(createValue(uuid, PropertyType.REFERENCE));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
* @throws ValueFormatException always
* @see javax.jcr.Property#getValues()
*/
@@ -177,60 +304,21 @@
throw new ValueFormatException();
}
- /*
+ /**
* {@inheritDoc}
*
- * @throws IllegalArgumentException if <code>value</code> is <code>null</code>.
- * @see javax.jcr.Property#setValue(javax.jcr.Value)
- *
- @SuppressWarnings( "fallthrough" )
- public void setValue( Value value ) throws RepositoryException {
- CheckArg.isNotNull(value, "value");
- // TODOx: Check node type constraint
- try {
- jcrValue = JcrValue.class.cast(value);
- } catch (ClassCastException error) {
- // TODOx: not sure if this is even possible
- ValueFactories valueFactories = getExecutionContext().getValueFactories();
- int type = value.getType();
- switch (type) {
- case PropertyType.BINARY: {
- jcrValue = new JcrValue<InputStream>(valueFactories, type, value.getStream());
- break;
- }
- case PropertyType.BOOLEAN: {
- jcrValue = new JcrValue<Boolean>(valueFactories, type, value.getBoolean());
- break;
- }
- case PropertyType.DATE: {
- jcrValue = new JcrValue<Calendar>(valueFactories, type, value.getDate());
- break;
- }
- case PropertyType.DOUBLE: {
- jcrValue = new JcrValue<Double>(valueFactories, type, value.getDouble());
- break;
- }
- case PropertyType.LONG: {
- jcrValue = new JcrValue<Long>(valueFactories, type, value.getLong());
- break;
- }
- case PropertyType.REFERENCE: {
- try {
- jcrValue = new JcrValue<UUID>(valueFactories, type, UUID.fromString(value.getString()));
- } catch (IllegalArgumentException fallsThroughToString) {
- }
- }
- case PropertyType.NAME:
- case PropertyType.PATH:
- case PropertyType.STRING: {
- jcrValue = new JcrValue<String>(valueFactories, type, value.getString());
- break;
- }
- default: {
- throw new AssertionError("Unsupported PropertyType: " + value.getType());
- }
- }
- }
+ * @see javax.jcr.Property#setValue(javax.jcr.Value[])
+ */
+ public void setValue( Value[] values ) throws ValueFormatException {
+ throw new ValueFormatException();
}
- */
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see javax.jcr.Property#setValue(java.lang.String[])
+ */
+ public void setValue( String[] values ) throws ValueFormatException {
+ throw new ValueFormatException();
+ }
}
Added: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/PropertyTypeUtil.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/PropertyTypeUtil.java (rev 0)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/PropertyTypeUtil.java 2009-03-24 22:33:26 UTC (rev 795)
@@ -0,0 +1,112 @@
+/*
+ * 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.
+ *
+ * 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 javax.jcr.PropertyType;
+
+/**
+ *
+ */
+class PropertyTypeUtil {
+
+ /**
+ * Compute the JCR {@link PropertyType} for the given DNA {@link org.jboss.dna.graph.property.PropertyType}.
+ * <p>
+ * See DNA-293 for complete discussion on why this method works the way it does. The best option appears to be basing the
+ * PropertyType on the first value, since that should be compatible with the PropertyType that was used when the values were
+ * set on the property in the first place.
+ * </p>
+ *
+ * @param property the DNA property for which the {@link PropertyType} is to be determined; never null
+ * @return the JCR property type; always a valid value and never {@link PropertyType#UNDEFINED}.
+ */
+ static final int jcrPropertyTypeFor( org.jboss.dna.graph.property.Property property ) {
+ Object value = property.getFirstValue();
+
+ // Get the DNA property type for this ...
+ switch (org.jboss.dna.graph.property.PropertyType.discoverType(value)) {
+ case STRING:
+ return PropertyType.STRING;
+ case NAME:
+ return PropertyType.NAME;
+ case LONG:
+ return PropertyType.LONG;
+ case UUID:
+ return PropertyType.STRING; // JCR treats UUID properties as strings
+ case URI:
+ return PropertyType.STRING;
+ case PATH:
+ return PropertyType.PATH;
+ case BOOLEAN:
+ return PropertyType.BOOLEAN;
+ case DATE:
+ return PropertyType.DATE;
+ case DECIMAL:
+ return PropertyType.STRING; // better than losing information
+ case DOUBLE:
+ return PropertyType.DOUBLE;
+ case BINARY:
+ return PropertyType.BINARY;
+ case OBJECT:
+ return PropertyType.UNDEFINED;
+ case REFERENCE:
+ return PropertyType.REFERENCE;
+ }
+ assert false;
+ return PropertyType.UNDEFINED;
+ }
+
+ /**
+ * Compute the DNA {@link org.jboss.dna.graph.property.PropertyType} for the given JCR {@link PropertyType} value.
+ *
+ * @param jcrPropertyType the DNA property for which the {@link PropertyType} is to be determined; never null
+ * @return the JCR property type; always a valid value and never {@link PropertyType#UNDEFINED}.
+ */
+ static final org.jboss.dna.graph.property.PropertyType dnaPropertyTypeFor( int jcrPropertyType ) {
+ // Make sure the value is the correct type ...
+ switch (jcrPropertyType) {
+ case PropertyType.STRING:
+ return org.jboss.dna.graph.property.PropertyType.STRING;
+ case PropertyType.BINARY:
+ return org.jboss.dna.graph.property.PropertyType.BINARY;
+ case PropertyType.BOOLEAN:
+ return org.jboss.dna.graph.property.PropertyType.BOOLEAN;
+ case PropertyType.DOUBLE:
+ return org.jboss.dna.graph.property.PropertyType.DOUBLE;
+ case PropertyType.LONG:
+ return org.jboss.dna.graph.property.PropertyType.LONG;
+ case PropertyType.DATE:
+ return org.jboss.dna.graph.property.PropertyType.DATE;
+ case PropertyType.PATH:
+ return org.jboss.dna.graph.property.PropertyType.PATH;
+ case PropertyType.NAME:
+ return org.jboss.dna.graph.property.PropertyType.NAME;
+ case PropertyType.REFERENCE:
+ return org.jboss.dna.graph.property.PropertyType.REFERENCE;
+ }
+ assert false;
+ return org.jboss.dna.graph.property.PropertyType.STRING;
+ }
+
+}
Property changes on: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/PropertyTypeUtil.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/SessionCache.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/SessionCache.java 2009-03-24 18:16:53 UTC (rev 794)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/SessionCache.java 2009-03-24 22:33:26 UTC (rev 795)
@@ -431,16 +431,74 @@
* existing values will be replaced with the supplied value.
*
* @param name the property name; may not be null
- * @param propertyType the property type; must be a valid {@link PropertyType} value
- * @param value the new property values, which may be converted to the appropriate {@link PropertyType type}
+ * @param value the new property values; may not be null
* @throws ConstraintViolationException if the property could not be set because of a node type constraint or property
* definition constraint
*/
public void setProperty( Name name,
- int propertyType,
- Object value ) throws ConstraintViolationException {
- Property dnaProp = propertyFactory.create(name, value);
- setProperty(name, dnaProp, propertyType);
+ JcrValue value ) throws ConstraintViolationException {
+ assert name != null;
+ assert value != null;
+ JcrPropertyDefinition definition = null;
+ PropertyId id = null;
+
+ // Look for an existing property ...
+ PropertyInfo existing = node.getProperty(name);
+ if (existing != null) {
+ // Reuse the existing ID ...
+ id = existing.getPropertyId();
+
+ // We're replacing an existing property, but we still need to check that the property definition
+ // (still) defines a type. So, find the property definition for the existing property ...
+ definition = nodeTypes().getPropertyDefinition(existing.getDefinitionId());
+
+ if (definition != null) {
+ // The definition's require type must match the value's ...
+ if (definition.getRequiredType() != PropertyType.UNDEFINED && definition.getRequiredType() != value.getType()) {
+ // The property type is not right, so we have to check if we can cast.
+ // It's easier and could save more work if we just find a new property definition that works ...
+ definition = null;
+ } else {
+ // The types match, so see if the value satisfies the constraints ...
+ if (!definition.satisfiesConstraints(value)) definition = null;
+ }
+ }
+ } else {
+ // This is a new property, so create a new ID ...
+ id = new PropertyId(node.getUuid(), name);
+ }
+ if (definition == null) {
+ // Look for a definition ...
+ definition = nodeTypes().findPropertyDefinition(node.getPrimaryTypeName(),
+ node.getMixinTypeNames(),
+ name,
+ value,
+ true,
+ true);
+ if (definition == null) {
+ throw new ConstraintViolationException();
+ }
+ }
+ // Create the DNA property ...
+ Object objValue = value.value();
+ int propertyType = definition.getRequiredType();
+ if (propertyType == PropertyType.UNDEFINED || propertyType == value.getType()) {
+ // Can use the values as is ...
+ propertyType = value.getType();
+ } else {
+ // A cast is required ...
+ org.jboss.dna.graph.property.PropertyType dnaPropertyType = PropertyTypeUtil.dnaPropertyTypeFor(propertyType);
+ ValueFactory<?> factory = context.getValueFactories().getValueFactory(dnaPropertyType);
+ objValue = factory.create(value);
+ }
+ Property dnaProp = propertyFactory.create(name, objValue);
+
+ // Create the property info ...
+ PropertyInfo newProperty = new PropertyInfo(id, definition.getId(), propertyType, dnaProp, definition.isMultiple());
+
+ // Finally update the cached information and record the change ...
+ node.setProperty(newProperty, context().getValueFactories());
+ operations().set(dnaProp).on(currentLocation);
}
/**
@@ -448,63 +506,86 @@
* existing values will be replaced with those that are supplied.
*
* @param name the property name; may not be null
- * @param propertyType the property type; must be a valid {@link PropertyType} value
- * @param value the new property values, which may be converted to the appropriate {@link PropertyType type}
+ * @param values new property values, all of which must have the same {@link Value#getType() property type}; may not be
+ * null or empty
* @throws ConstraintViolationException if the property could not be set because of a node type constraint or property
* definition constraint
*/
public void setProperty( Name name,
- int propertyType,
- Object[] value ) throws ConstraintViolationException {
- Property dnaProp = propertyFactory.create(name, value);
- setProperty(name, dnaProp, propertyType);
- }
+ JcrValue[] values ) throws ConstraintViolationException {
+ assert name != null;
+ assert values != null;
+ int numValues = values.length;
+ assert numValues != 0;
+ JcrPropertyDefinition definition = null;
+ PropertyId id = null;
- protected final void setProperty( Name name,
- Property dnaProp,
- int propertyType ) throws ConstraintViolationException {
- assert propertyType != PropertyType.UNDEFINED;
+ // Look for an existing property ...
PropertyInfo existing = node.getProperty(name);
- PropertyInfo newProperty = null;
if (existing != null) {
+ // Reuse the existing ID ...
+ id = existing.getPropertyId();
+
// We're replacing an existing property, but we still need to check that the property definition
- // defines a type. So, find the property definition for the existing property ...
- JcrPropertyDefinition definition = nodeTypes().getPropertyDefinition(existing.getDefinitionId());
- if (definition == null && existing.getDefinitionId().allowsMultiple() && dnaProp.isSingle()) {
- // Look for a single-valued definition ...
- PropertyDefinitionId id = existing.getDefinitionId().asSingleValued();
- definition = nodeTypes().getPropertyDefinition(id);
+ // (still) defines a type. So, find the property definition for the existing property ...
+ definition = nodeTypes().getPropertyDefinition(existing.getDefinitionId());
+
+ if (definition != null) {
+ // The definition's require type must match the value's ...
+ if (numValues == 0) {
+ // Just use the definition as is ...
+ } else {
+ int type = values[0].getType();
+ if (definition.getRequiredType() != PropertyType.UNDEFINED && definition.getRequiredType() != type) {
+ // The property type is not right, so we have to check if we can cast.
+ // It's easier and could save more work if we just find a new property definition that works ...
+ definition = null;
+ } else {
+ // The types match, so see if the value satisfies the constraints ...
+ if (!definition.satisfiesConstraints(values)) definition = null;
+ }
+ }
}
+ } else {
+ // This is a new property, so create a new ID ...
+ id = new PropertyId(node.getUuid(), name);
+ }
+ if (definition == null) {
+ // Look for a definition ...
+ definition = nodeTypes().findPropertyDefinition(node.getPrimaryTypeName(),
+ node.getMixinTypeNames(),
+ name,
+ values,
+ true);
if (definition == null) {
- // Try to find a different (but existing) property definition ...
- definition = findBestPropertyDefintion(node.getPrimaryTypeName(),
- node.getMixinTypeNames(),
- dnaProp,
- propertyType,
- true);
- }
- if (definition == null) {
throw new ConstraintViolationException();
}
-
- // Create the property info ...
- newProperty = new PropertyInfo(existing.getPropertyId(), existing.getDefinitionId(), propertyType, dnaProp,
- existing.isMultiValued());
+ }
+ // Create the DNA property ...
+ int type = values.length != 0 ? values[0].getType() : definition.getRequiredType();
+ Object[] objValues = new Object[values.length];
+ int propertyType = definition.getRequiredType();
+ if (propertyType == PropertyType.UNDEFINED || propertyType == type) {
+ // Can use the values as is ...
+ propertyType = type;
+ for (int i = 0; i != numValues; ++i) {
+ objValues[i] = values[i].value();
+ }
} else {
- // It's a new property ...
- PropertyId id = new PropertyId(node.getUuid(), name);
- // Look find the property definition to use ...
- JcrPropertyDefinition definition = findBestPropertyDefintion(node.getPrimaryTypeName(),
- node.getMixinTypeNames(),
- dnaProp,
- propertyType,
- true);
- if (definition == null) {
- throw new ConstraintViolationException();
+ // A cast is required ...
+ assert propertyType != type;
+ org.jboss.dna.graph.property.PropertyType dnaPropertyType = PropertyTypeUtil.dnaPropertyTypeFor(propertyType);
+ ValueFactory<?> factory = context.getValueFactories().getValueFactory(dnaPropertyType);
+ for (int i = 0; i != numValues; ++i) {
+ objValues[i] = factory.create(values[i].value());
}
- // Create the property info ...
- newProperty = new PropertyInfo(id, definition.getId(), propertyType, dnaProp, definition.isMultiple());
}
+ Property dnaProp = propertyFactory.create(name, objValues);
+
+ // Create the property info ...
+ PropertyInfo newProperty = new PropertyInfo(id, definition.getId(), propertyType, dnaProp, definition.isMultiple());
+
+ // Finally update the cached information and record the change ...
node.setProperty(newProperty, context().getValueFactories());
operations().set(dnaProp).on(currentLocation);
}
@@ -571,7 +652,9 @@
if (!definition.getId().equals(node.getDefinitionId())) {
// The node definition changed, so try to set the property ...
try {
- setProperty(DnaLexicon.NODE_DEFINITON, PropertyType.STRING, definition.getId().getString());
+ JcrValue value = new JcrValue(context().getValueFactories(), SessionCache.this, PropertyType.STRING,
+ definition.getId().getString());
+ setProperty(DnaLexicon.NODE_DEFINITON, value);
} catch (ConstraintViolationException e) {
// We can't set this property on the node (according to the node definition).
// But we still want the node info to have the correct node definition.
@@ -1297,7 +1380,7 @@
Name name = dnaProp.getName();
// Figure out the JCR property type for this property ...
- int propertyType = JcrSession.jcrPropertyTypeFor(dnaProp);
+ int propertyType = PropertyTypeUtil.jcrPropertyTypeFor(dnaProp);
PropertyDefinition propertyDefinition = findBestPropertyDefintion(primaryTypeName,
mixinTypeNames,
dnaProp,
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/AbstractJcrPropertyTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/AbstractJcrPropertyTest.java 2009-03-24 18:16:53 UTC (rev 794)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/AbstractJcrPropertyTest.java 2009-03-24 22:33:26 UTC (rev 795)
@@ -39,7 +39,6 @@
import javax.jcr.Session;
import javax.jcr.Value;
import javax.jcr.Workspace;
-import org.jboss.dna.common.util.StringUtil;
import org.jboss.dna.graph.ExecutionContext;
import org.jboss.dna.graph.property.Name;
import org.jboss.dna.graph.property.Path;
@@ -277,56 +276,6 @@
assertThat(prop.isSame(otherProp), is(false));
}
- @Test( expected = UnsupportedOperationException.class )
- public void shouldNotAllowSetBooleanValue() {
- prop.setValue(false);
- }
-
- @Test( expected = UnsupportedOperationException.class )
- public void shouldNotAllowSetCalendarValue() {
- prop.setValue(Calendar.getInstance());
- }
-
- @Test( expected = UnsupportedOperationException.class )
- public void shouldNotAllowSetDoubleValue() {
- prop.setValue(0.0);
- }
-
- @Test( expected = UnsupportedOperationException.class )
- public void shouldNotAllowSetInputStreamValue() {
- prop.setValue(Mockito.mock(InputStream.class));
- }
-
- @Test( expected = UnsupportedOperationException.class )
- public void shouldNotAllowSetLongValue() {
- prop.setValue(0L);
- }
-
- @Test( expected = UnsupportedOperationException.class )
- public void shouldNotAllowSetNodeValue() {
- prop.setValue(Mockito.mock(Node.class));
- }
-
- @Test( expected = UnsupportedOperationException.class )
- public void shouldNotAllowSetStringValue() {
- prop.setValue("");
- }
-
- @Test( expected = UnsupportedOperationException.class )
- public void shouldNotAllowSetStringArrayValue() {
- prop.setValue(StringUtil.EMPTY_STRING_ARRAY);
- }
-
- @Test( expected = UnsupportedOperationException.class )
- public void shouldNotAllowSetValueValue() {
- prop.setValue(Mockito.mock(Value.class));
- }
-
- @Test( expected = UnsupportedOperationException.class )
- public void shouldNotAllowSetValueArrayValue() {
- prop.setValue(new Value[0]);
- }
-
private class MockAbstractJcrProperty extends AbstractJcrProperty {
MockAbstractJcrProperty( SessionCache cache,
@@ -433,5 +382,95 @@
public Value[] getValues() {
return null;
}
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see javax.jcr.Property#setValue(javax.jcr.Value)
+ */
+ public void setValue( Value value ) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see javax.jcr.Property#setValue(javax.jcr.Value[])
+ */
+ public void setValue( Value[] values ) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see javax.jcr.Property#setValue(java.lang.String)
+ */
+ public void setValue( String value ) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see javax.jcr.Property#setValue(java.lang.String[])
+ */
+ public void setValue( String[] values ) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see javax.jcr.Property#setValue(java.io.InputStream)
+ */
+ public void setValue( InputStream value ) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see javax.jcr.Property#setValue(long)
+ */
+ public void setValue( long value ) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see javax.jcr.Property#setValue(double)
+ */
+ public void setValue( double value ) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see javax.jcr.Property#setValue(java.util.Calendar)
+ */
+ public void setValue( Calendar value ) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see javax.jcr.Property#setValue(boolean)
+ */
+ public void setValue( boolean value ) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see javax.jcr.Property#setValue(javax.jcr.Node)
+ */
+ public void setValue( Node value ) {
+ throw new UnsupportedOperationException();
+ }
}
}
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrSessionTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrSessionTest.java 2009-03-24 18:16:53 UTC (rev 794)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrSessionTest.java 2009-03-24 22:33:26 UTC (rev 795)
@@ -32,6 +32,7 @@
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.stub;
+import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
@@ -325,12 +326,13 @@
@Test
public void shouldProvideValueFactory() throws Exception {
+ InputStream stream = new ByteArrayInputStream("something".getBytes());
ValueFactory factory = session.getValueFactory();
assertThat(factory, notNullValue());
assertThat(factory.createValue(false), notNullValue());
assertThat(factory.createValue(Calendar.getInstance()), notNullValue());
assertThat(factory.createValue(0.0), notNullValue());
- assertThat(factory.createValue(Mockito.mock(InputStream.class)), notNullValue());
+ assertThat(factory.createValue(stream), notNullValue());
assertThat(factory.createValue(0L), notNullValue());
Node node = Mockito.mock(Node.class);
stub(node.getUUID()).toReturn(UUID.randomUUID().toString());
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/SessionCacheTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/SessionCacheTest.java 2009-03-24 18:16:53 UTC (rev 794)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/SessionCacheTest.java 2009-03-24 22:33:26 UTC (rev 795)
@@ -23,6 +23,10 @@
*/
package org.jboss.dna.jcr;
+import static javax.jcr.PropertyType.DOUBLE;
+import static javax.jcr.PropertyType.LONG;
+import static javax.jcr.PropertyType.STRING;
+import static javax.jcr.PropertyType.UNDEFINED;
import static org.hamcrest.core.Is.is;
import static org.hamcrest.core.IsNull.notNullValue;
import static org.hamcrest.core.IsNull.nullValue;
@@ -34,15 +38,13 @@
import static org.mockito.Mockito.stub;
import java.io.File;
import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import javax.jcr.InvalidItemStateException;
+import javax.jcr.nodetype.ConstraintViolationException;
import org.jboss.dna.common.statistic.Stopwatch;
import org.jboss.dna.common.util.StringUtil;
import org.jboss.dna.graph.ExecutionContext;
@@ -54,7 +56,9 @@
import org.jboss.dna.graph.property.Path;
import org.jboss.dna.graph.property.PathNotFoundException;
import org.jboss.dna.graph.property.Property;
+import org.jboss.dna.graph.property.ValueFactory;
import org.jboss.dna.jcr.SessionCache.NodeEditor;
+import org.jboss.dna.jcr.Vehicles.Lexicon;
import org.jboss.dna.jcr.cache.Children;
import org.jboss.dna.jcr.cache.NodeInfo;
import org.jboss.dna.jcr.cache.PropertyInfo;
@@ -89,7 +93,7 @@
cachesByName = new HashMap<String, SessionCache>();
context = new ExecutionContext();
- context.getNamespaceRegistry().register("vehix", "http://example.com/vehicles");
+ context.getNamespaceRegistry().register(Vehicles.Lexicon.Namespace.PREFIX, Vehicles.Lexicon.Namespace.URI);
stub(session.getExecutionContext()).toReturn(context);
stub(session.namespaces()).toReturn(context.getNamespaceRegistry());
@@ -98,7 +102,7 @@
JcrNodeTypeSource nodeTypeSource = null;
nodeTypeSource = new JcrBuiltinNodeTypeSource(this.context, nodeTypeSource);
nodeTypeSource = new DnaBuiltinNodeTypeSource(this.context, nodeTypeSource);
- nodeTypeSource = new VehixNodeTypeSource(context, nodeTypeSource);
+ nodeTypeSource = new Vehicles.NodeTypeSource(context, nodeTypeSource);
repoTypes = new RepositoryNodeTypeManager(context, nodeTypeSource);
nodeTypes = new JcrNodeTypeManager(this.context, repoTypes);
stub(session.nodeTypeManager()).toReturn(nodeTypes);
@@ -108,46 +112,6 @@
cache = getCache("vehicles");
}
- /**
- * Define the node types for the "vehix" namespace.
- */
- public static class VehixNodeTypeSource extends AbstractJcrNodeTypeSource {
- private final List<JcrNodeType> nodeTypes;
-
- public VehixNodeTypeSource( ExecutionContext context,
- JcrNodeTypeSource predecessor ) {
- super(predecessor);
- this.nodeTypes = new ArrayList<JcrNodeType>();
-
- Name carName = context.getValueFactories().getNameFactory().create("vehix:car");
- Name aircraftName = context.getValueFactories().getNameFactory().create("vehix:aircraft");
- JcrNodeType unstructured = findType(JcrNtLexicon.UNSTRUCTURED);
-
- // Add in the "vehix:car" node type (which extends "nt:unstructured") ...
- JcrNodeType car = new JcrNodeType(context, (RepositoryNodeTypeManager)null, carName,
- Arrays.asList(new JcrNodeType[] {unstructured}), NO_PRIMARY_ITEM_NAME,
- NO_CHILD_NODES, NO_PROPERTIES, NOT_MIXIN, ORDERABLE_CHILD_NODES);
-
- // Add in the "vehix:aircraft" node type (which extends "nt:unstructured") ...
- JcrNodeType aircraft = new JcrNodeType(context, (RepositoryNodeTypeManager)null, aircraftName,
- Arrays.asList(new JcrNodeType[] {unstructured}), NO_PRIMARY_ITEM_NAME,
- NO_CHILD_NODES, NO_PROPERTIES, NOT_MIXIN, ORDERABLE_CHILD_NODES);
-
- nodeTypes.addAll(Arrays.asList(new JcrNodeType[] {car, aircraft,}));
- }
-
- /**
- * {@inheritDoc}
- *
- * @see org.jboss.dna.jcr.AbstractJcrNodeTypeSource#getDeclaredNodeTypes()
- */
- @Override
- public Collection<JcrNodeType> getDeclaredNodeTypes() {
- return nodeTypes;
- }
-
- }
-
protected Graph createFrom( String repositoryName,
String workspaceName,
File file ) throws IOException, SAXException {
@@ -231,6 +195,11 @@
}
}
+ protected JcrValue value( int propertyType,
+ Object value ) {
+ return new JcrValue(context.getValueFactories(), cache, propertyType, value);
+ }
+
protected void assertDoesExist( Graph graph,
Location location ) {
Node node = store.getNodeAt(location);
@@ -296,6 +265,52 @@
assertThat(info.getUuid(), is(uuid));
}
+ protected void assertProperty( NodeInfo info,
+ Name propertyName,
+ int type,
+ Name nodeTypeName,
+ Name propertyDefinitionName,
+ int definitionType,
+ Object value ) {
+ PropertyDefinitionId defnId = new PropertyDefinitionId(nodeTypeName, propertyDefinitionName, definitionType, false);
+ PropertyInfo propertyInfo = info.getProperty(propertyName);
+ assertThat(propertyInfo, is(notNullValue()));
+ assertThat(propertyInfo.getPropertyType(), is(type));
+ assertThat(propertyInfo.getDefinitionId(), is(defnId));
+ org.jboss.dna.graph.property.PropertyType dnaPropertyType = PropertyTypeUtil.dnaPropertyTypeFor(type);
+ // Check the value ...
+ ValueFactory<?> factory = context.getValueFactories().getValueFactory(dnaPropertyType);
+ Object actual = factory.create(propertyInfo.getProperty().getFirstValue());
+ assertThat(actual, is(value));
+ }
+
+ protected void assertProperty( NodeInfo info,
+ Name propertyName,
+ int type,
+ Name nodeTypeName,
+ Name propertyDefinitionName,
+ int definitionType,
+ Object... values ) {
+ PropertyDefinitionId defnId = new PropertyDefinitionId(nodeTypeName, propertyDefinitionName, definitionType, true);
+ PropertyInfo propertyInfo = info.getProperty(propertyName);
+ assertThat(propertyInfo, is(notNullValue()));
+ assertThat(propertyInfo.getPropertyType(), is(type));
+ assertThat(propertyInfo.getDefinitionId(), is(defnId));
+ org.jboss.dna.graph.property.PropertyType dnaPropertyType = PropertyTypeUtil.dnaPropertyTypeFor(type);
+ // Check the values ...
+ ValueFactory<?> factory = context.getValueFactories().getValueFactory(dnaPropertyType);
+ int i = 0;
+ for (Object value : propertyInfo.getProperty()) {
+ assertThat(factory.create(value), is(values[i++]));
+ }
+ }
+
+ protected void assertNoProperty( NodeInfo info,
+ Name propertyName ) {
+ PropertyInfo propertyInfo = info.getProperty(propertyName);
+ assertThat(propertyInfo, is(nullValue()));
+ }
+
@Test
public void shouldCreateWithValidParameters() {
assertThat(cache, is(notNullValue()));
@@ -631,4 +646,91 @@
assertDoesExist(store, sports.getLocation());
}
+ @Test
+ public void shouldGetExistingPropertyOnExistingNode() throws Exception {
+ NodeInfo root = cache.findNodeInfoForRoot();
+ NodeInfo lr3 = cache.findNodeInfo(root.getUuid(), path("/vehix:Vehicles/vehix:Cars/vehix:Utility/vehix:Land Rover LR3"));
+ assertProperty(lr3, Lexicon.MODEL, STRING, Lexicon.CAR, Lexicon.MODEL, STRING, "LR3");
+ assertProperty(lr3, Lexicon.MAKER, STRING, Lexicon.CAR, Lexicon.MAKER, STRING, "Land Rover");
+ assertProperty(lr3, Lexicon.YEAR, LONG, Lexicon.CAR, Lexicon.YEAR, LONG, 2008L);
+ assertProperty(lr3, Lexicon.MSRP, STRING, Lexicon.CAR, Lexicon.MSRP, STRING, "$48,525");
+
+ NodeInfo db9 = cache.findNodeInfo(root.getUuid(), path("/vehix:Vehicles/vehix:Cars/vehix:Sports/vehix:Aston Martin DB9"));
+ assertProperty(db9, Lexicon.MODEL, STRING, Lexicon.CAR, Lexicon.MODEL, STRING, "DB9");
+ assertProperty(db9, Lexicon.MAKER, STRING, Lexicon.CAR, Lexicon.MAKER, STRING, "Aston Martin");
+ assertProperty(db9, Lexicon.LENGTH_IN_INCHES, DOUBLE, Lexicon.CAR, Lexicon.LENGTH_IN_INCHES, DOUBLE, 185.5D);
+
+ NodeInfo b878 = cache.findNodeInfo(root.getUuid(),
+ path("/vehix:Vehicles/vehix:Aircraft/vehix:Commercial/vehix:Boeing 787"));
+ assertProperty(b878, Lexicon.MODEL, STRING, Lexicon.AIRCRAFT, Lexicon.MODEL, STRING, "787-3");
+ assertProperty(b878, Lexicon.MAKER, STRING, Lexicon.AIRCRAFT, Lexicon.MAKER, STRING, "Boeing");
+ assertProperty(b878, Lexicon.INTRODUCED, LONG, Lexicon.AIRCRAFT, Lexicon.INTRODUCED, LONG, 2009L);
+ assertProperty(b878, Lexicon.EMPTY_WEIGHT, STRING, JcrNtLexicon.UNSTRUCTURED, name("*"), UNDEFINED, "223000lb");
+
+ }
+
+ @Test
+ public void shouldNotFindNonExistantPropertyOnExistingNode() throws Exception {
+ NodeInfo root = cache.findNodeInfoForRoot();
+ NodeInfo lr3 = cache.findNodeInfo(root.getUuid(), path("/vehix:Vehicles/vehix:Cars/vehix:Utility/vehix:Land Rover LR3"));
+ assertProperty(lr3, Lexicon.MODEL, STRING, Lexicon.CAR, Lexicon.MODEL, STRING, "LR3");
+ assertProperty(lr3, Lexicon.MAKER, STRING, Lexicon.CAR, Lexicon.MAKER, STRING, "Land Rover");
+ assertNoProperty(lr3, Lexicon.LENGTH_IN_INCHES);
+ assertNoProperty(lr3, Lexicon.INTRODUCED);
+ }
+
+ @Test
+ public void shouldSetNewValueOnExistingPropertyOnExistingNode() throws Exception {
+ NodeInfo root = cache.findNodeInfoForRoot();
+ NodeInfo lr3 = cache.findNodeInfo(root.getUuid(), path("/vehix:Vehicles/vehix:Cars/vehix:Utility/vehix:Land Rover LR3"));
+ assertProperty(lr3, Lexicon.MODEL, STRING, Lexicon.CAR, Lexicon.MODEL, STRING, "LR3");
+ assertProperty(lr3, Lexicon.MAKER, STRING, Lexicon.CAR, Lexicon.MAKER, STRING, "Land Rover");
+ assertNoProperty(lr3, Lexicon.LENGTH_IN_INCHES);
+
+ SessionCache.NodeEditor editor = cache.getEditorFor(lr3.getUuid());
+ editor.setProperty(Lexicon.LENGTH_IN_INCHES, value(DOUBLE, 100.0D));
+ }
+
+ @Test
+ public void shouldSetNewPropertyOnExistingNode() throws Exception {
+ NodeInfo root = cache.findNodeInfoForRoot();
+ NodeInfo db9 = cache.findNodeInfo(root.getUuid(), path("/vehix:Vehicles/vehix:Cars/vehix:Sports/vehix:Aston Martin DB9"));
+ assertProperty(db9, Lexicon.MODEL, STRING, Lexicon.CAR, Lexicon.MODEL, STRING, "DB9");
+ assertProperty(db9, Lexicon.MAKER, STRING, Lexicon.CAR, Lexicon.MAKER, STRING, "Aston Martin");
+ assertProperty(db9, Lexicon.LENGTH_IN_INCHES, DOUBLE, Lexicon.CAR, Lexicon.LENGTH_IN_INCHES, DOUBLE, 185.5D);
+
+ SessionCache.NodeEditor editor = cache.getEditorFor(db9.getUuid());
+ editor.setProperty(Lexicon.LENGTH_IN_INCHES, value(DOUBLE, 100.0D));
+ }
+
+ @Test( expected = ConstraintViolationException.class )
+ public void shouldFailToSetPropertyToInvalidValuesOnExistingNode() throws Exception {
+ NodeInfo root = cache.findNodeInfoForRoot();
+ NodeInfo db9 = cache.findNodeInfo(root.getUuid(), path("/vehix:Vehicles/vehix:Cars/vehix:Sports/vehix:Aston Martin DB9"));
+ assertProperty(db9, Lexicon.MODEL, STRING, Lexicon.CAR, Lexicon.MODEL, STRING, "DB9");
+ assertProperty(db9, Lexicon.MAKER, STRING, Lexicon.CAR, Lexicon.MAKER, STRING, "Aston Martin");
+ assertProperty(db9, Lexicon.LENGTH_IN_INCHES, DOUBLE, Lexicon.CAR, Lexicon.LENGTH_IN_INCHES, DOUBLE, 185.5D);
+
+ SessionCache.NodeEditor editor = cache.getEditorFor(db9.getUuid());
+ editor.setProperty(Lexicon.LENGTH_IN_INCHES, value(STRING, "This is not a valid double"));
+ }
+
+ @Test
+ public void shouldRemoveExistingPropertyOnExistingNode() throws Exception {
+ NodeInfo root = cache.findNodeInfoForRoot();
+ NodeInfo db9 = cache.findNodeInfo(root.getUuid(), path("/vehix:Vehicles/vehix:Cars/vehix:Sports/vehix:Aston Martin DB9"));
+ assertProperty(db9, Lexicon.MODEL, STRING, Lexicon.CAR, Lexicon.MODEL, STRING, "DB9");
+ assertProperty(db9, Lexicon.MAKER, STRING, Lexicon.CAR, Lexicon.MAKER, STRING, "Aston Martin");
+ assertProperty(db9, Lexicon.LENGTH_IN_INCHES, DOUBLE, Lexicon.CAR, Lexicon.LENGTH_IN_INCHES, DOUBLE, 185.5D);
+
+ UUID db9uuid = db9.getUuid();
+ SessionCache.NodeEditor editor = cache.getEditorFor(db9uuid);
+ editor.removeProperty(Lexicon.LENGTH_IN_INCHES);
+
+ db9 = cache.findNodeInfo(db9uuid);
+ assertNoProperty(db9, Lexicon.LENGTH_IN_INCHES);
+
+ db9 = cache.findNodeInfo(root.getUuid(), path("/vehix:Vehicles/vehix:Cars/vehix:Sports/vehix:Aston Martin DB9"));
+ assertNoProperty(db9, Lexicon.LENGTH_IN_INCHES);
+ }
}
Added: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/Vehicles.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/Vehicles.java (rev 0)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/Vehicles.java 2009-03-24 22:33:26 UTC (rev 795)
@@ -0,0 +1,170 @@
+/*
+ * 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.
+ *
+ * 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 java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import javax.jcr.PropertyType;
+import org.jboss.dna.graph.ExecutionContext;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.basic.BasicName;
+
+/**
+ * Define the node types for the "vehix" namespace.
+ */
+public class Vehicles {
+
+ public static class Lexicon {
+ public static class Namespace {
+ public static final String URI = "http://example.com/vehicles";
+ public static final String PREFIX = "vehix";
+ }
+
+ public static final Name CAR = new BasicName(Namespace.URI, "car");
+ public static final Name AIRCRAFT = new BasicName(Namespace.URI, "aircraft");
+
+ public static final Name MAKER = new BasicName(Namespace.URI, "maker");
+ public static final Name MODEL = new BasicName(Namespace.URI, "model");
+ public static final Name INTRODUCED = new BasicName(Namespace.URI, "introduced");
+ public static final Name YEAR = new BasicName(Namespace.URI, "year");
+ public static final Name MSRP = new BasicName(Namespace.URI, "msrp");
+ public static final Name USER_RATING = new BasicName(Namespace.URI, "userRating");
+ public static final Name VALUE_RATING = new BasicName(Namespace.URI, "valueRating");
+ public static final Name MPG_CITY = new BasicName(Namespace.URI, "mpgCity");
+ public static final Name MPG_HIGHWAY = new BasicName(Namespace.URI, "mpgHighway");
+ public static final Name LENGTH_IN_INCHES = new BasicName(Namespace.URI, "lengthInInches");
+ public static final Name WHEELBASE_IN_INCHES = new BasicName(Namespace.URI, "wheelbaseInInches");
+ public static final Name ENGINE = new BasicName(Namespace.URI, "engine");
+
+ public static final Name EMPTY_WEIGHT = new BasicName(Namespace.URI, "emptyWeight");
+
+ }
+
+ public static class NodeTypeSource extends AbstractJcrNodeTypeSource {
+
+ private final List<JcrNodeType> nodeTypes;
+
+ public NodeTypeSource( ExecutionContext context,
+ JcrNodeTypeSource predecessor ) {
+ super(predecessor);
+ this.nodeTypes = new ArrayList<JcrNodeType>();
+
+ JcrNodeType base = findType(JcrNtLexicon.BASE);
+ JcrNodeType unstructured = findType(JcrNtLexicon.UNSTRUCTURED);
+
+ // Add in the "vehix:car" node type (which extends "nt:unstructured") ...
+ JcrNodeType car = new JcrNodeType(context, NO_NODE_TYPE_MANAGER, Lexicon.CAR,
+ Arrays.asList(new JcrNodeType[] {base}), NO_PRIMARY_ITEM_NAME, NO_CHILD_NODES,
+ Arrays.asList(new JcrPropertyDefinition[] {
+ new JcrPropertyDefinition(context, null, Lexicon.MAKER,
+ OnParentVersionBehavior.COMPUTE.getJcrValue(), false,
+ false, false, NO_DEFAULT_VALUES, PropertyType.STRING,
+ NO_CONSTRAINTS, false),
+ new JcrPropertyDefinition(context, null, Lexicon.MODEL,
+ OnParentVersionBehavior.COMPUTE.getJcrValue(), false,
+ false, false, NO_DEFAULT_VALUES, PropertyType.STRING,
+ NO_CONSTRAINTS, false),
+ new JcrPropertyDefinition(context, null, Lexicon.INTRODUCED,
+ OnParentVersionBehavior.COMPUTE.getJcrValue(), false,
+ false, false, NO_DEFAULT_VALUES, PropertyType.LONG,
+ NO_CONSTRAINTS, false),
+ /* Year IS mandatory for car */
+ new JcrPropertyDefinition(context, null, Lexicon.YEAR,
+ OnParentVersionBehavior.COMPUTE.getJcrValue(), false,
+ true, false, NO_DEFAULT_VALUES, PropertyType.LONG,
+ NO_CONSTRAINTS, false),
+ new JcrPropertyDefinition(context, null, Lexicon.MSRP,
+ OnParentVersionBehavior.COMPUTE.getJcrValue(), false,
+ false, false, NO_DEFAULT_VALUES, PropertyType.STRING,
+ NO_CONSTRAINTS, false),
+ new JcrPropertyDefinition(context, null, Lexicon.USER_RATING,
+ OnParentVersionBehavior.COMPUTE.getJcrValue(), false,
+ false, false, NO_DEFAULT_VALUES, PropertyType.DOUBLE,
+ NO_CONSTRAINTS, false),
+ new JcrPropertyDefinition(context, null, Lexicon.VALUE_RATING,
+ OnParentVersionBehavior.COMPUTE.getJcrValue(), false,
+ false, false, NO_DEFAULT_VALUES, PropertyType.DOUBLE,
+ NO_CONSTRAINTS, false),
+ new JcrPropertyDefinition(context, null, Lexicon.MPG_CITY,
+ OnParentVersionBehavior.COMPUTE.getJcrValue(), false,
+ false, false, NO_DEFAULT_VALUES, PropertyType.LONG,
+ NO_CONSTRAINTS, false),
+ new JcrPropertyDefinition(context, null, Lexicon.MPG_HIGHWAY,
+ OnParentVersionBehavior.COMPUTE.getJcrValue(), false,
+ false, false, NO_DEFAULT_VALUES, PropertyType.LONG,
+ NO_CONSTRAINTS, false),
+ new JcrPropertyDefinition(context, null, Lexicon.LENGTH_IN_INCHES,
+ OnParentVersionBehavior.COMPUTE.getJcrValue(), false,
+ false, false, NO_DEFAULT_VALUES, PropertyType.DOUBLE,
+ NO_CONSTRAINTS, false),
+ new JcrPropertyDefinition(context, null, Lexicon.WHEELBASE_IN_INCHES,
+ OnParentVersionBehavior.COMPUTE.getJcrValue(), false,
+ false, false, NO_DEFAULT_VALUES, PropertyType.DOUBLE,
+ NO_CONSTRAINTS, false),
+ new JcrPropertyDefinition(context, null, Lexicon.ENGINE,
+ OnParentVersionBehavior.COMPUTE.getJcrValue(), false,
+ false, false, NO_DEFAULT_VALUES, PropertyType.STRING,
+ NO_CONSTRAINTS, false),}), NOT_MIXIN,
+ ORDERABLE_CHILD_NODES);
+
+ // Add in the "vehix:aircraft" node type (which extends "nt:unstructured") ...
+ JcrNodeType aircraft = new JcrNodeType(context, NO_NODE_TYPE_MANAGER, Lexicon.AIRCRAFT,
+ Arrays.asList(new JcrNodeType[] {unstructured}), NO_PRIMARY_ITEM_NAME,
+ NO_CHILD_NODES, Arrays.asList(new JcrPropertyDefinition[] {
+ new JcrPropertyDefinition(context, null, Lexicon.MAKER,
+ OnParentVersionBehavior.COMPUTE.getJcrValue(),
+ false, false, false, NO_DEFAULT_VALUES,
+ PropertyType.STRING, NO_CONSTRAINTS, false),
+ new JcrPropertyDefinition(context, null, Lexicon.MODEL,
+ OnParentVersionBehavior.COMPUTE.getJcrValue(),
+ false, false, false, NO_DEFAULT_VALUES,
+ PropertyType.STRING, NO_CONSTRAINTS, false),
+ /* Year is NOT mandatory for aircraft */
+ new JcrPropertyDefinition(context, null, Lexicon.YEAR,
+ OnParentVersionBehavior.COMPUTE.getJcrValue(),
+ false, false, false, NO_DEFAULT_VALUES,
+ PropertyType.LONG, NO_CONSTRAINTS, false),
+ new JcrPropertyDefinition(context, null, Lexicon.INTRODUCED,
+ OnParentVersionBehavior.COMPUTE.getJcrValue(),
+ false, false, false, NO_DEFAULT_VALUES,
+ PropertyType.LONG, NO_CONSTRAINTS, false),}),
+ NOT_MIXIN, ORDERABLE_CHILD_NODES);
+
+ nodeTypes.addAll(Arrays.asList(new JcrNodeType[] {car, aircraft,}));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.jcr.AbstractJcrNodeTypeSource#getDeclaredNodeTypes()
+ */
+ @Override
+ public Collection<JcrNodeType> getDeclaredNodeTypes() {
+ return nodeTypes;
+ }
+
+ }
+}
Property changes on: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/Vehicles.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
15 years, 2 months
DNA SVN: r794 - in trunk: dna-jcr/src/main/java/org/jboss/dna/jcr and 1 other directory.
by dna-commits@lists.jboss.org
Author: rhauch
Date: 2009-03-24 14:16:53 -0400 (Tue, 24 Mar 2009)
New Revision: 794
Modified:
trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/NameValueFactory.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrValue.java
Log:
DNA-336 JcrValue.asType(int desiredPropertyType) skips a number of valid conversions and has duplicate logic
Changed the JcrValue.asType(int) logic to first ensure the value matches the current required type (in most cases this should just return the actual value if the type is correct), and to then convert to the desired property type. Corrected a number of conversions to include several combinations that was excluded.
Also added a check to the NameValueFactory to ensure that the relative path (of size 1) has no SNS index.
Modified: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/NameValueFactory.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/NameValueFactory.java 2009-03-24 14:31:24 UTC (rev 793)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/NameValueFactory.java 2009-03-24 18:16:53 UTC (rev 794)
@@ -265,7 +265,9 @@
if (value == null) return null;
if (!value.isAbsolute() && value.size() == 1) {
// A relative name of length 1 is converted to a name
- return value.getSegment(0).getName();
+ Path.Segment segment = value.getLastSegment();
+ // Can only convert if the path has no SNS index ...
+ if (!segment.hasIndex()) return segment.getName();
}
throw new ValueFormatException(value, getPropertyType(), GraphI18n.errorConvertingType.text(Path.class.getSimpleName(),
Name.class.getSimpleName(),
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrValue.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrValue.java 2009-03-24 14:31:24 UTC (rev 793)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrValue.java 2009-03-24 18:16:53 UTC (rev 794)
@@ -35,7 +35,6 @@
import org.jboss.dna.graph.property.Name;
import org.jboss.dna.graph.property.Path;
import org.jboss.dna.graph.property.ValueFactories;
-import org.jboss.dna.graph.property.Path.Segment;
/**
* @author jverhaeg
@@ -56,7 +55,7 @@
assert type == PropertyType.BINARY || type == PropertyType.BOOLEAN || type == PropertyType.DATE
|| type == PropertyType.DOUBLE || type == PropertyType.LONG || type == PropertyType.NAME
|| type == PropertyType.PATH || type == PropertyType.REFERENCE || type == PropertyType.STRING;
-
+
// Leaving this assertion out for now so that values can be created in node type sources, which are created outside
// the context of any particular session.
// assert sessionCache != null;
@@ -90,12 +89,13 @@
/**
* Returns the session cache for the session that created this value.
+ *
* @return the session cache for the session that created this value.
*/
final SessionCache sessionCache() {
return sessionCache;
}
-
+
/**
* {@inheritDoc}
*
@@ -226,91 +226,136 @@
* @see PropertyType
*/
JcrValue asType( int type ) throws ValueFormatException {
-
if (type == this.type) {
return this.withTypeAndValue(this.type, this.value);
}
+ Object value = this.value;
switch (type) {
case PropertyType.BOOLEAN:
+ // Make sure the existing value is valid per the current type.
+ // This is required if we rely upon the value factories to cast correctly.
+ if (this.type == PropertyType.STRING) {
+ value = valueFactories.getStringFactory().create(this.value);
+ } else if (this.type == PropertyType.BINARY) {
+ value = valueFactories.getBinaryFactory().create(this.value);
+ } else {
+ throw createValueFormatException(boolean.class);
+ }
try {
- if (this.type == PropertyType.STRING || this.type == PropertyType.BINARY) {
- return this.withTypeAndValue(type, valueFactories.getBooleanFactory().create(value));
- }
+ return this.withTypeAndValue(type, valueFactories.getBooleanFactory().create(value));
} catch (org.jboss.dna.graph.property.ValueFormatException vfe) {
throw createValueFormatException(vfe);
}
- throw createValueFormatException(boolean.class);
case PropertyType.DATE:
+ if (this.type == PropertyType.STRING) {
+ value = valueFactories.getStringFactory().create(this.value);
+ } else if (this.type == PropertyType.BINARY) {
+ value = valueFactories.getBinaryFactory().create(this.value);
+ } else if (this.type == PropertyType.DOUBLE) {
+ value = valueFactories.getDoubleFactory().create(this.value);
+ } else if (this.type == PropertyType.LONG) {
+ value = valueFactories.getLongFactory().create(this.value);
+ } else {
+ throw createValueFormatException(Calendar.class);
+ }
try {
- if (this.type == PropertyType.DOUBLE || this.type == PropertyType.LONG || this.type == PropertyType.STRING
- || this.type == PropertyType.BINARY) {
- return this.withTypeAndValue(type, valueFactories.getDateFactory().create(value));
- }
+ return this.withTypeAndValue(type, valueFactories.getDateFactory().create(value));
} catch (org.jboss.dna.graph.property.ValueFormatException vfe) {
throw createValueFormatException(vfe);
}
- throw createValueFormatException(Calendar.class);
-
case PropertyType.NAME:
+ if (this.type == PropertyType.STRING) {
+ value = valueFactories.getStringFactory().create(this.value);
+ } else if (this.type == PropertyType.BINARY) {
+ value = valueFactories.getBinaryFactory().create(this.value);
+ } else if (this.type == PropertyType.PATH) {
+ value = valueFactories.getPathFactory().create(this.value);
+ } else {
+ throw createValueFormatException(Name.class);
+ }
try {
- if (this.type == PropertyType.STRING) {
- return this.withTypeAndValue(type, valueFactories.getNameFactory().create(value));
- }
-
- String valueAsString = this.valueFactories.getStringFactory().create(value);
- if (this.type == PropertyType.BINARY) {
- return this.withTypeAndValue(type, valueFactories.getNameFactory().create(valueAsString));
-
- }
-
- if (this.type == PropertyType.PATH) {
- Path path = valueFactories.getPathFactory().create(valueAsString);
-
- Segment[] segments = path.getSegmentsArray();
- if (!path.isAbsolute() && segments.length == 1 && !segments[0].hasIndex()) {
- return this.withTypeAndValue(type, valueFactories.getNameFactory().create(valueAsString));
- }
- }
+ return this.withTypeAndValue(type, valueFactories.getNameFactory().create(value));
} catch (org.jboss.dna.graph.property.ValueFormatException vfe) {
throw createValueFormatException(vfe);
}
- throw createValueFormatException(Name.class);
-
case PropertyType.PATH:
+ if (this.type == PropertyType.STRING) {
+ value = valueFactories.getStringFactory().create(this.value);
+ } else if (this.type == PropertyType.BINARY) {
+ value = valueFactories.getBinaryFactory().create(this.value);
+ } else if (this.type == PropertyType.NAME) {
+ value = valueFactories.getNameFactory().create(this.value);
+ } else {
+ throw createValueFormatException(Path.class);
+ }
try {
- if (this.type == PropertyType.STRING) {
- return this.withTypeAndValue(type, valueFactories.getPathFactory().create(value));
-
- }
+ return this.withTypeAndValue(type, valueFactories.getPathFactory().create(value));
} catch (org.jboss.dna.graph.property.ValueFormatException vfe) {
throw createValueFormatException(vfe);
}
- throw createValueFormatException(Path.class);
- // Nothing can be converted to these types (except themselves)
case PropertyType.REFERENCE:
- throw createValueFormatException(Node.class);
+ if (this.type == PropertyType.STRING) {
+ value = valueFactories.getStringFactory().create(this.value);
+ } else if (this.type == PropertyType.BINARY) {
+ value = valueFactories.getBinaryFactory().create(this.value);
+ } else {
+ throw createValueFormatException(Node.class);
+ }
+ try {
+ return this.withTypeAndValue(type, valueFactories.getReferenceFactory().create(value));
+ } catch (org.jboss.dna.graph.property.ValueFormatException vfe) {
+ throw createValueFormatException(vfe);
+ }
case PropertyType.DOUBLE:
- throw createValueFormatException(double.class);
+ if (this.type == PropertyType.STRING) {
+ value = valueFactories.getStringFactory().create(this.value);
+ } else if (this.type == PropertyType.BINARY) {
+ value = valueFactories.getBinaryFactory().create(this.value);
+ } else if (this.type == PropertyType.LONG) {
+ value = valueFactories.getLongFactory().create(this.value);
+ } else if (this.type == PropertyType.DATE) {
+ value = valueFactories.getDateFactory().create(this.value);
+ } else {
+ throw createValueFormatException(double.class);
+ }
+ try {
+ return this.withTypeAndValue(type, valueFactories.getDoubleFactory().create(value));
+ } catch (org.jboss.dna.graph.property.ValueFormatException vfe) {
+ throw createValueFormatException(vfe);
+ }
case PropertyType.LONG:
- throw createValueFormatException(long.class);
+ if (this.type == PropertyType.STRING) {
+ value = valueFactories.getStringFactory().create(this.value);
+ } else if (this.type == PropertyType.BINARY) {
+ value = valueFactories.getBinaryFactory().create(this.value);
+ } else if (this.type == PropertyType.DOUBLE) {
+ value = valueFactories.getDoubleFactory().create(this.value);
+ } else if (this.type == PropertyType.DATE) {
+ value = valueFactories.getDateFactory().create(this.value);
+ } else {
+ throw createValueFormatException(long.class);
+ }
+ try {
+ return this.withTypeAndValue(type, valueFactories.getLongFactory().create(value));
+ } catch (org.jboss.dna.graph.property.ValueFormatException vfe) {
+ throw createValueFormatException(vfe);
+ }
// Anything can be converted to these types
case PropertyType.BINARY:
try {
return this.withTypeAndValue(type, valueFactories.getBinaryFactory().create(value));
-
} catch (org.jboss.dna.graph.property.ValueFormatException vfe) {
throw createValueFormatException(vfe);
}
case PropertyType.STRING:
try {
return this.withTypeAndValue(type, valueFactories.getStringFactory().create(value));
-
} catch (org.jboss.dna.graph.property.ValueFormatException vfe) {
throw createValueFormatException(vfe);
}
15 years, 2 months
DNA SVN: r793 - in trunk/dna-jcr/src: test/java/org/jboss/dna/jcr and 1 other directory.
by dna-commits@lists.jboss.org
Author: rhauch
Date: 2009-03-24 10:31:24 -0400 (Tue, 24 Mar 2009)
New Revision: 793
Added:
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/ItemDefinitionTest.java
Modified:
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/DefinitionCache.java
Log:
DNA-335 DNA's NodeTypeManager implementation does not allow multiple definitions with the same name
Applied the "DNA-335_overriding_definitions" patch that changes the behavior to be more consistent with the implications of section 4.7.7 in the JCR 2.0 spec. Subtypes can override definitions of their supertypes (or their super-supertypes, etc.). Included some very rudimentary test cases as a sanity check. A more complete test suite is forthcoming.
This patch retains the support for multiple inheritance but adds the assumption that any future type registration support will limit overriding to cases where the overriding property or child node definition is "more narrow" than the definition being overridden. In the case of properties, this implies that the required type of the property in the subtype's property definition can ALWAYS be cast to the required type of the property in the supertype's definition.
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/DefinitionCache.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/DefinitionCache.java 2009-03-24 03:18:34 UTC (rev 792)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/DefinitionCache.java 2009-03-24 14:31:24 UTC (rev 793)
@@ -24,6 +24,8 @@
package org.jboss.dna.jcr;
import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
import javax.jcr.nodetype.NodeType;
import net.jcip.annotations.Immutable;
import org.jboss.dna.graph.property.Name;
@@ -102,6 +104,7 @@
DefinitionCache( JcrNodeType primaryType,
Iterable<JcrNodeType> mixinTypes ) {
addDefinitionsForTypeAndAllSupertypes(primaryType);
+ // Assumption is that addMixin won't allow mixin types that conflict with primary types
if (mixinTypes != null) {
for (JcrNodeType mixinType : mixinTypes) {
addDefinitionsForTypeAndAllSupertypes(mixinType);
@@ -117,22 +120,47 @@
}
private final void addDefinitions( JcrNodeType nodeType ) {
+ Set<Name> namesFromThisType = new HashSet<Name>();
+
for (JcrNodeDefinition definition : nodeType.childNodeDefinitions()) {
Name name = definition.getInternalName();
+
+ /*
+ * If the child node was already defined in the type hierarchy at some other level, ignore the definition
+ * - it was overridden by the previous definition. This relies on the fact that TypeA.getTypeAndSupertypes()
+ * always returns TypeX before TypeY if TypeX is closer to TypeA on the inheritance graph than TypeY is.
+ */
+ if (allChildNodeDefinitions.containsKey(name) && !namesFromThisType.contains(name)) {
+ continue;
+ }
+
if (definition.allowsSameNameSiblings()) {
childNodeDefinitionsThatAllowSns.put(name, definition);
} else {
childNodeDefinitionsThatAllowNoSns.put(name, definition);
}
+ namesFromThisType.add(name);
allChildNodeDefinitions.put(name, definition);
}
+
+ namesFromThisType.clear();
for (JcrPropertyDefinition definition : nodeType.propertyDefinitions()) {
Name name = definition.getInternalName();
+
+ /*
+ * If the property was already defined in the type hierarchy at some other level, ignore the definition
+ * - it was overridden by the previous definition. This relies on the fact that TypeA.getTypeAndSupertypes()
+ * always returns TypeX before TypeY if TypeX is closer to TypeA on the inheritance graph than TypeY is.
+ */
+ if (allPropertyDefinitions.containsKey(name) && !namesFromThisType.contains(name)) {
+ continue;
+ }
if (definition.isMultiple()) {
multiValuedPropertyDefinitions.put(name, definition);
} else {
singleValuedPropertyDefinitions.put(name, definition);
}
+ namesFromThisType.add(name);
allPropertyDefinitions.put(name, definition);
}
}
Added: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/ItemDefinitionTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/ItemDefinitionTest.java (rev 0)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/ItemDefinitionTest.java 2009-03-24 14:31:24 UTC (rev 793)
@@ -0,0 +1,380 @@
+/*
+ * 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.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.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.jcr.PropertyType;
+import javax.jcr.Value;
+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.ValueFactory;
+import org.jboss.dna.graph.property.basic.BasicName;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.MockitoAnnotations;
+import org.mockito.MockitoAnnotations.Mock;
+
+/**
+ * BDD test cases for property and child node definition inheritance. Could be part of RepositoryNodeTypeManagerTest, but split
+ * off to isolate tests for this behavior vs. projection/inference and registration/unregistration behavior.
+ */
+public class ItemDefinitionTest {
+
+ 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;
+ private ValueFactory<Name> nameFactory;
+ @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");
+
+ // 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);
+ source = new TestNodeTypeSource(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>();
+
+ // Now create the workspace ...
+ workspace = new JcrWorkspace(repository, workspaceName, context, sessionAttributes);
+
+ // Create the session and log in ...
+ session = (JcrSession)workspace.getSession();
+
+ nameFactory = session.getExecutionContext().getValueFactories().getNameFactory();
+ }
+
+ @After
+ public void after() throws Exception {
+ if (session != null && session.isLive()) {
+ session.logout();
+ }
+ }
+
+ @Test
+ public void shouldNotFindInvalidPropertyDefinition() throws Exception {
+ // This property name is not defined for any of our test types
+ Name badName = nameFactory.create("undefinedName");
+ JcrPropertyDefinition propDef;
+
+ propDef = repoTypeManager.findPropertyDefinition(NODE_TYPE_A, Collections.<Name>emptyList(), badName, null, true, true);
+ assertThat(propDef, is(nullValue()));
+
+ propDef = repoTypeManager.findPropertyDefinition(NODE_TYPE_B, Collections.<Name>emptyList(), badName, null, true, true);
+ assertThat(propDef, is(nullValue()));
+
+ propDef = repoTypeManager.findPropertyDefinition(NODE_TYPE_C, Collections.<Name>emptyList(), badName, null, true, true);
+ assertThat(propDef, is(nullValue()));
+
+ propDef = repoTypeManager.findPropertyDefinition(NODE_TYPE_D, Collections.<Name>emptyList(), badName, null, true, true);
+ assertThat(propDef, is(nullValue()));
+ }
+
+ @Test
+ public void shouldUseNearestPropertyDefinition() {
+ // If a property is defined at multiple points in the type hierarchy, the property definition closest to the given type
+ // should be used.
+
+ JcrPropertyDefinition propDef;
+
+ propDef = repoTypeManager.findPropertyDefinition(NODE_TYPE_A,
+ Collections.<Name>emptyList(),
+ SINGLE_PROP1,
+ null,
+ true,
+ true);
+ assertThat(propDef, is(notNullValue()));
+ assertEquals(propDef.getRequiredType(), PropertyType.STRING);
+
+ propDef = repoTypeManager.findPropertyDefinition(NODE_TYPE_B,
+ Collections.<Name>emptyList(),
+ SINGLE_PROP1,
+ null,
+ true,
+ true);
+ assertThat(propDef, is(notNullValue()));
+ assertEquals(propDef.getRequiredType(), PropertyType.LONG);
+
+ propDef = repoTypeManager.findPropertyDefinition(NODE_TYPE_C,
+ Collections.<Name>emptyList(),
+ SINGLE_PROP1,
+ null,
+ true,
+ true);
+ assertThat(propDef, is(notNullValue()));
+ assertEquals(propDef.getRequiredType(), PropertyType.BOOLEAN);
+ }
+
+ @Test
+ public void shouldPreferLeftmostSupertypeForDefinition() {
+ /*
+ * This specification doesn't mandate this, but since DNA supports multiple inheritance, we
+ * have imposed the rule that property or child-node definitions should be preferred based on
+ * distance from the given node type in the hierarchy with the order of the supertypes in the declaration
+ * being the tiebreaker.
+ */
+ JcrPropertyDefinition propDef;
+
+ // Should prefer the inherited definition from NODE_TYPE_A since it was declared before NODE_TYPE_C in NODE_TYPE_D's list
+ // of supertypes
+ propDef = repoTypeManager.findPropertyDefinition(NODE_TYPE_D,
+ Collections.<Name>emptyList(),
+ SINGLE_PROP1,
+ null,
+ true,
+ true);
+ assertThat(propDef, is(notNullValue()));
+ assertEquals(propDef.getRequiredType(), PropertyType.STRING);
+
+ }
+
+ @Test
+ public void shouldFindBestMatchDefinition() {
+ /*
+ * In cases where there is more than one valid definition for the same property,
+ * the best match should be returned.
+ */
+ Value doubleValue = session.getValueFactory().createValue(0.7);
+ Value longValue = session.getValueFactory().createValue(10);
+ Value stringValue = session.getValueFactory().createValue("Should not work");
+
+ JcrPropertyDefinition propDef;
+
+ // Should prefer the double definition from NODE_TYPE_C since the value is of type double
+ propDef = repoTypeManager.findPropertyDefinition(NODE_TYPE_D,
+ Collections.<Name>emptyList(),
+ SINGLE_PROP2,
+ doubleValue,
+ true,
+ true);
+ assertThat(propDef, is(notNullValue()));
+ assertEquals(propDef.getRequiredType(), PropertyType.DOUBLE);
+
+ // Should prefer the long definition from NODE_TYPE_C since the value is of type long
+ propDef = repoTypeManager.findPropertyDefinition(NODE_TYPE_D,
+ Collections.<Name>emptyList(),
+ SINGLE_PROP2,
+ longValue,
+ true,
+ true);
+ assertThat(propDef, is(notNullValue()));
+ assertEquals(propDef.getRequiredType(), PropertyType.LONG);
+
+ // Should not allow a string though, since the NODE_TYPE_C definition narrows the acceptable types to double and long
+ propDef = repoTypeManager.findPropertyDefinition(NODE_TYPE_D,
+ Collections.<Name>emptyList(),
+ SINGLE_PROP2,
+ stringValue,
+ true,
+ true);
+ assertThat(propDef, is(nullValue()));
+
+ }
+
+ static final Name NODE_TYPE_A = new BasicName(TestLexicon.Namespace.URI, "nodeA");
+ static final Name NODE_TYPE_B = new BasicName(TestLexicon.Namespace.URI, "nodeB");
+ static final Name NODE_TYPE_C = new BasicName(TestLexicon.Namespace.URI, "nodeC");
+ static final Name NODE_TYPE_D = new BasicName(TestLexicon.Namespace.URI, "nodeD");
+
+ static final Name SINGLE_PROP1 = new BasicName(TestLexicon.Namespace.URI, "singleProp1");
+ static final Name SINGLE_PROP2 = new BasicName(TestLexicon.Namespace.URI, "singleProp2");
+
+ class TestNodeTypeSource extends AbstractJcrNodeTypeSource {
+
+ /** The list of primary node types. */
+ private final List<JcrNodeType> nodeTypes;
+
+ /*
+ * Build a hierarchy of node types with the following relationships:
+ *
+ * dnatest:nodeA extends nt:base
+ * dnatest:nodeB extends nt:base
+ * dnatest:nodeC extends dnatest:nodeB
+ * dnatest:nodeD extends dnatest:nodeA and dnatest:nodeC
+ *
+ * And the following single-valued property definitions
+ *
+ * dnatest:nodeA defines properties:
+ * dnatest:singleProp1 of type STRING
+ * dnatest:nodeB defines properties:
+ * dnatest:singleProp1 of type LONG
+ * dnatest:singleProp2 of type UNDEFINED
+ * dnatest:nodeC defines properties:
+ * dnatest:singleProp1 of type BOOLEAN
+ * dnatest:singleProp2 of type DOUBLE
+ * dnatest:singleProp2 of type LONG (note the double-definition)
+ * dnatest:nodeD defines properties:
+ * < NO PROPERTIES DEFINED IN THIS TYPE >
+ */
+
+ TestNodeTypeSource( ExecutionContext context,
+ JcrNodeTypeSource predecessor ) {
+ super(predecessor);
+
+ nodeTypes = new ArrayList<JcrNodeType>();
+
+ JcrNodeType base = findType(JcrNtLexicon.BASE);
+
+ if (base == null) {
+ String baseTypeName = JcrNtLexicon.BASE.getString(context.getNamespaceRegistry());
+ String namespaceTypeName = DnaLexicon.NAMESPACE.getString(context.getNamespaceRegistry());
+ throw new IllegalStateException(JcrI18n.supertypeNotFound.text(baseTypeName, namespaceTypeName));
+ }
+
+ // Stubbing in child node and property definitions for now
+ JcrNodeType nodeA = new JcrNodeType(
+ context,
+ NO_NODE_TYPE_MANAGER,
+ NODE_TYPE_A,
+ Arrays.asList(new JcrNodeType[] {base}),
+ NO_PRIMARY_ITEM_NAME,
+ NO_CHILD_NODES,
+ Arrays.asList(new JcrPropertyDefinition[] {new JcrPropertyDefinition(
+ context,
+ null,
+ SINGLE_PROP1,
+ OnParentVersionBehavior.IGNORE.getJcrValue(),
+ false,
+ false,
+ false,
+ NO_DEFAULT_VALUES,
+ PropertyType.STRING,
+ NO_CONSTRAINTS,
+ false),}),
+ NOT_MIXIN, UNORDERABLE_CHILD_NODES);
+
+ JcrNodeType nodeB = new JcrNodeType(context, NO_NODE_TYPE_MANAGER, NODE_TYPE_B,
+ Arrays.asList(new JcrNodeType[] {base}), NO_PRIMARY_ITEM_NAME, NO_CHILD_NODES,
+ Arrays.asList(new JcrPropertyDefinition[] {
+ new JcrPropertyDefinition(context, null, SINGLE_PROP1,
+ OnParentVersionBehavior.IGNORE.getJcrValue(),
+ false, false, false, NO_DEFAULT_VALUES,
+ PropertyType.LONG, NO_CONSTRAINTS, false),
+ new JcrPropertyDefinition(context, null, SINGLE_PROP2,
+ OnParentVersionBehavior.IGNORE.getJcrValue(),
+ false, false, false, NO_DEFAULT_VALUES,
+ PropertyType.UNDEFINED, NO_CONSTRAINTS, false),}),
+ NOT_MIXIN, UNORDERABLE_CHILD_NODES);
+ JcrNodeType nodeC = new JcrNodeType(context, NO_NODE_TYPE_MANAGER, NODE_TYPE_C,
+ Arrays.asList(new JcrNodeType[] {nodeB}), NO_PRIMARY_ITEM_NAME, NO_CHILD_NODES,
+ Arrays.asList(new JcrPropertyDefinition[] {
+ new JcrPropertyDefinition(context, null, SINGLE_PROP1,
+ OnParentVersionBehavior.IGNORE.getJcrValue(),
+ false, false, false, NO_DEFAULT_VALUES,
+ PropertyType.BOOLEAN, NO_CONSTRAINTS, false),
+ new JcrPropertyDefinition(context, null, SINGLE_PROP2,
+ OnParentVersionBehavior.IGNORE.getJcrValue(),
+ false, false, false, NO_DEFAULT_VALUES,
+ PropertyType.DOUBLE, NO_CONSTRAINTS, false),
+ new JcrPropertyDefinition(context, null, SINGLE_PROP2,
+ OnParentVersionBehavior.IGNORE.getJcrValue(),
+ false, false, false, NO_DEFAULT_VALUES,
+ PropertyType.LONG, NO_CONSTRAINTS, false),
+
+ }), NOT_MIXIN, UNORDERABLE_CHILD_NODES);
+
+ JcrNodeType nodeD = new JcrNodeType(context, NO_NODE_TYPE_MANAGER, NODE_TYPE_D, Arrays.asList(new JcrNodeType[] {
+ nodeA, nodeC}), NO_PRIMARY_ITEM_NAME, NO_CHILD_NODES, NO_PROPERTIES, NOT_MIXIN, UNORDERABLE_CHILD_NODES);
+
+ nodeTypes.addAll(Arrays.asList(new JcrNodeType[] {nodeA, nodeB, nodeC, nodeD}));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.jcr.AbstractJcrNodeTypeSource#getDeclaredNodeTypes()
+ */
+ @Override
+ public Collection<JcrNodeType> getDeclaredNodeTypes() {
+ return nodeTypes;
+ }
+
+ }
+
+}
\ No newline at end of file
Property changes on: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/ItemDefinitionTest.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
15 years, 2 months
DNA SVN: r792 - in trunk: dna-jcr-tck and 8 other directories.
by dna-commits@lists.jboss.org
Author: rhauch
Date: 2009-03-23 23:18:34 -0400 (Mon, 23 Mar 2009)
New Revision: 792
Added:
trunk/dna-jcr-tck/
trunk/dna-jcr-tck/.classpath
trunk/dna-jcr-tck/.project
trunk/dna-jcr-tck/pom.xml
trunk/dna-jcr-tck/src/
trunk/dna-jcr-tck/src/test/
trunk/dna-jcr-tck/src/test/java/
trunk/dna-jcr-tck/src/test/java/org/
trunk/dna-jcr-tck/src/test/java/org/jboss/
trunk/dna-jcr-tck/src/test/java/org/jboss/dna/
trunk/dna-jcr-tck/src/test/java/org/jboss/dna/jcr/
trunk/dna-jcr-tck/src/test/java/org/jboss/dna/jcr/InMemoryRepositoryStub.java
trunk/dna-jcr-tck/src/test/java/org/jboss/dna/jcr/Jsr170LevelOneTckTest.java
trunk/dna-jcr-tck/src/test/java/org/jboss/dna/jcr/Jsr170LevelTwoTckTest.java
trunk/dna-jcr-tck/src/test/java/org/jboss/dna/jcr/Jsr170OptionalLockingTckTest.java
trunk/dna-jcr-tck/src/test/java/org/jboss/dna/jcr/Jsr170OptionalObservationTckTest.java
trunk/dna-jcr-tck/src/test/java/org/jboss/dna/jcr/Jsr170OptionalSqlQueryTckTest.java
trunk/dna-jcr-tck/src/test/java/org/jboss/dna/jcr/Jsr170OptionalVersionTckTest.java
trunk/dna-jcr-tck/src/test/resources/
trunk/dna-jcr-tck/src/test/resources/log4j.properties
trunk/dna-jcr-tck/src/test/resources/repositoryForTckTests.xml
trunk/dna-jcr-tck/src/test/resources/repositoryStubImpl.properties
Modified:
trunk/pom.xml
Log:
DNA-306 Add ability to run all TCK unit tests within Hudson, showing success and failure rate
Applied the patch, which adds a 'dna-jcr-tck' project (which is no longer under 'extensions' but is at the top level) that shows how the project is doing relative to the JCR TCK unit tests. These unit tests are NOT the official TCK, but are reportedly some of the tests that comprise the TCK and are available via the Jackrabbit project. Also changed the parent POM to include this module only when using the 'jcr-tck' profile (e.g., 'mvn install -P jcr-tck').
Property changes on: trunk/dna-jcr-tck
___________________________________________________________________
Name: svn:ignore
+ target
Added: trunk/dna-jcr-tck/.classpath
===================================================================
--- trunk/dna-jcr-tck/.classpath (rev 0)
+++ trunk/dna-jcr-tck/.classpath 2009-03-24 03:18:34 UTC (rev 792)
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
+ <classpathentry kind="src" output="target/test-classes" path="src/test/resources"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+ <classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
+ <classpathentry kind="output" path="target/classes"/>
+</classpath>
Added: trunk/dna-jcr-tck/.project
===================================================================
--- trunk/dna-jcr-tck/.project (rev 0)
+++ trunk/dna-jcr-tck/.project 2009-03-24 03:18:34 UTC (rev 792)
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>dna-jcr-tck</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.wst.common.project.facet.core.builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.maven.ide.eclipse.maven2Builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ <nature>org.maven.ide.eclipse.maven2Nature</nature>
+ <nature>org.eclipse.wst.common.project.facet.core.nature</nature>
+ </natures>
+</projectDescription>
Added: trunk/dna-jcr-tck/pom.xml
===================================================================
--- trunk/dna-jcr-tck/pom.xml (rev 0)
+++ trunk/dna-jcr-tck/pom.xml 2009-03-24 03:18:34 UTC (rev 792)
@@ -0,0 +1,99 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.jboss.dna</groupId>
+ <artifactId>dna</artifactId>
+ <version>0.4-SNAPSHOT</version>
+ </parent>
+ <!-- The groupId and version values are inherited from parent -->
+ <artifactId>dna-jcr-tck</artifactId>
+ <packaging>jar</packaging>
+ <name>JBoss DNA JCR Compatibility Unit Tests</name>
+ <description>JBoss DNA unit tests to check compatibility with the JCR 1.0 API. This does NOT use the official TCK.</description>
+ <url>http://labs.jboss.org/dna</url>
+
+ <!--
+ Define the dependencies. Note that all version and scopes default to those
+ defined in the dependencyManagement section of the parent pom.
+ -->
+ <dependencies>
+ <dependency>
+ <groupId>org.jboss.dna</groupId>
+ <artifactId>dna-common</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.dna</groupId>
+ <artifactId>dna-common</artifactId>
+ <version>${pom.version}</version>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.dna</groupId>
+ <artifactId>dna-graph</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.dna</groupId>
+ <artifactId>dna-graph</artifactId>
+ <version>${pom.version}</version>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.dna</groupId>
+ <artifactId>dna-repository</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.dna</groupId>
+ <artifactId>dna-jcr</artifactId>
+ <version>${pom.version}</version>
+ </dependency>
+ <!--
+ Testing (note the scope)
+ -->
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <!--
+ Logging (require SLF4J API for compiling, but use Log4J and its SLF4J binding for testing)
+ -->
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-log4j12</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>log4j</groupId>
+ <artifactId>log4j</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <!--
+ Java Concurrency in Practice annotations
+ -->
+ <dependency>
+ <groupId>net.jcip</groupId>
+ <artifactId>jcip-annotations</artifactId>
+ </dependency>
+ <!--
+ Java Content Repository API
+ -->
+ <dependency>
+ <groupId>javax.jcr</groupId>
+ <artifactId>jcr</artifactId>
+ </dependency>
+ <!--
+ Apache JCR API unit tests (for any JCR implementation), which is a subset of the official TCK
+ -->
+ <dependency>
+ <groupId>org.apache.jackrabbit</groupId>
+ <artifactId>jackrabbit-jcr-tests</artifactId>
+ </dependency>
+ </dependencies>
+</project>
\ No newline at end of file
Added: trunk/dna-jcr-tck/src/test/java/org/jboss/dna/jcr/InMemoryRepositoryStub.java
===================================================================
--- trunk/dna-jcr-tck/src/test/java/org/jboss/dna/jcr/InMemoryRepositoryStub.java (rev 0)
+++ trunk/dna-jcr-tck/src/test/java/org/jboss/dna/jcr/InMemoryRepositoryStub.java 2009-03-24 03:18:34 UTC (rev 792)
@@ -0,0 +1,152 @@
+/*
+ * 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 java.io.File;
+import java.net.URI;
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.util.Collections;
+import java.util.Properties;
+import javax.jcr.Credentials;
+import javax.jcr.Repository;
+import org.apache.jackrabbit.test.RepositoryStub;
+import org.jboss.dna.graph.DnaLexicon;
+import org.jboss.dna.graph.ExecutionContext;
+import org.jboss.dna.graph.Graph;
+import org.jboss.dna.graph.GraphImporter;
+import org.jboss.dna.graph.JcrNtLexicon;
+import org.jboss.dna.graph.Location;
+import org.jboss.dna.graph.connector.RepositoryConnection;
+import org.jboss.dna.graph.connector.RepositoryConnectionFactory;
+import org.jboss.dna.graph.connector.inmemory.InMemoryRepositorySource;
+import org.jboss.dna.graph.property.Path;
+
+/**
+ * Class with TCK repository stub. This class does not contain any tests.
+ */
+public class InMemoryRepositoryStub extends RepositoryStub {
+ private Repository repository;
+ protected RepositoryConnection connection;
+ protected AccessControlContext accessControlContext = AccessController.getContext();
+
+ private Credentials credentials = new Credentials() {
+ private static final long serialVersionUID = 1L;
+
+ @SuppressWarnings( "unused" )
+ public AccessControlContext getAccessControlContext() {
+ return accessControlContext;
+ }
+ };
+
+ protected ExecutionContext executionContext = new ExecutionContext() {
+
+ @Override
+ public ExecutionContext create( AccessControlContext accessControlContext ) {
+ return executionContext;
+ }
+ };
+
+ protected RepositoryConnectionFactory connectionFactory = new RepositoryConnectionFactory() {
+ public RepositoryConnection createConnection( String sourceName ) {
+ return connection;
+ }
+ };
+
+ public InMemoryRepositoryStub( Properties env ) {
+ super(env);
+
+ // Create the in-memory (DNA) repository
+ InMemoryRepositorySource source = new InMemoryRepositorySource();
+
+ // Various calls will fail if you do not set a non-null name for the source
+ source.setName("TestRepositorySource");
+
+ // Wrap a connection to the in-memory (DNA) repository in a (JCR) repository
+ connection = source.getConnection();
+ repository = new JcrRepository(Collections.<String, String>emptyMap(), executionContext.create(accessControlContext),
+ connectionFactory, source.getName());
+
+ // Make sure the path to the namespaces exists ...
+ Graph graph = Graph.create(source.getName(), connectionFactory, executionContext);
+ graph.create("/jcr:system").and().create("/jcr:system/dna:namespaces");
+
+ // Set up some sample nodes in the graph to match the expected test configuration
+ try {
+
+ // TODO: Should there be an easier way to define these since they will be needed for all JCR repositories?
+ executionContext.getNamespaceRegistry().register(DnaLexicon.Namespace.PREFIX, DnaLexicon.Namespace.URI);
+ executionContext.getNamespaceRegistry().register(JcrLexicon.Namespace.PREFIX, JcrLexicon.Namespace.URI);
+ executionContext.getNamespaceRegistry().register(JcrNtLexicon.Namespace.PREFIX, JcrNtLexicon.Namespace.URI);
+ executionContext.getNamespaceRegistry().register("sv", "http://www.jcp.org/jcr/sv/1.0");
+
+ Path destinationPath = executionContext.getValueFactories().getPathFactory().create("/");
+ GraphImporter importer = new GraphImporter(graph);
+
+ URI xmlContent = new File("src/test/resources/repositoryForTckTests.xml").toURI();
+ Graph.Batch batch = importer.importXml(xmlContent, Location.create(destinationPath));
+ batch.execute();
+
+ } catch (Exception ex) {
+ // The TCK tries to quash this exception. Print it out to be more obvious.
+ ex.printStackTrace();
+ throw new IllegalStateException("Repository initialization failed.", ex);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.apache.jackrabbit.test.RepositoryStub#getSuperuserCredentials()
+ */
+ @Override
+ public Credentials getSuperuserCredentials() {
+ // TODO: Why must we override this method? The default TCK implementation just returns a particular instance of
+ // SimpleCredentials.
+ return credentials;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.apache.jackrabbit.test.RepositoryStub#getReadOnlyCredentials()
+ */
+ @Override
+ public Credentials getReadOnlyCredentials() {
+ // TODO: Why must we override this method? The default TCK implementation just returns a particular instance of
+ // SimpleCredentials.
+ return credentials;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.apache.jackrabbit.test.RepositoryStub#getRepository()
+ */
+ @Override
+ public Repository getRepository() {
+ return repository;
+ }
+
+}
Added: trunk/dna-jcr-tck/src/test/java/org/jboss/dna/jcr/Jsr170LevelOneTckTest.java
===================================================================
--- trunk/dna-jcr-tck/src/test/java/org/jboss/dna/jcr/Jsr170LevelOneTckTest.java (rev 0)
+++ trunk/dna-jcr-tck/src/test/java/org/jboss/dna/jcr/Jsr170LevelOneTckTest.java 2009-03-24 03:18:34 UTC (rev 792)
@@ -0,0 +1,127 @@
+/*
+ * 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 junit.framework.Test;
+import junit.framework.TestSuite;
+import org.apache.jackrabbit.test.JCRTestSuite;
+
+/**
+ * Test suite to wrap Apache Jackrabbit JCR technology compatibility kit (TCK) unit tests for Level 1 (L1) compliance. Note that
+ * technically these are not the actual TCK, but these are unit tests that happen to be similar to (or provided the basis for) a
+ * subset of the TCK.
+ */
+public class Jsr170LevelOneTckTest {
+
+ /**
+ *
+ */
+ public Jsr170LevelOneTckTest() {
+ }
+
+ /**
+ * Wrapper so that the Jackrabbit TCK test suite gets picked up by the DNA Maven test target.
+ *
+ * @return a new instance of {@link JCRTestSuite}.
+ */
+ public static Test suite() {
+ // Uncomment this to execute all tests
+ // return new JCRTestSuite();
+
+ // Or uncomment the following lines to execute the different sets/suites of tests ...
+ TestSuite suite = new TestSuite("JCR 1.0 Level 1 Compliance tests");
+
+ suite.addTest(new LevelOneFeatureTests());
+
+ return suite;
+ }
+
+ /**
+ * Test suite that includes the Level 1 JCR TCK API tests from the Jackrabbit project.
+ */
+ private static class LevelOneFeatureTests extends TestSuite {
+ protected LevelOneFeatureTests() {
+ super("JCR Level 1 API Tests");
+ // We currently don't pass the tests in those suites that are commented out
+ // See https://jira.jboss.org/jira/browse/DNA-285
+
+ addTestSuite(org.apache.jackrabbit.test.api.RootNodeTest.class);
+ addTestSuite(org.apache.jackrabbit.test.api.NodeReadMethodsTest.class);
+ addTestSuite(org.apache.jackrabbit.test.api.PropertyTypeTest.class);
+ addTestSuite(org.apache.jackrabbit.test.api.NodeDiscoveringNodeTypesTest.class);
+ addTestSuite(org.apache.jackrabbit.test.api.BinaryPropertyTest.class);
+ addTestSuite(org.apache.jackrabbit.test.api.BooleanPropertyTest.class);
+ addTestSuite(org.apache.jackrabbit.test.api.DatePropertyTest.class);
+ addTestSuite(org.apache.jackrabbit.test.api.DoublePropertyTest.class);
+ addTestSuite(org.apache.jackrabbit.test.api.LongPropertyTest.class);
+ addTestSuite(org.apache.jackrabbit.test.api.NamePropertyTest.class);
+ addTestSuite(org.apache.jackrabbit.test.api.PathPropertyTest.class);
+ addTestSuite(org.apache.jackrabbit.test.api.ReferencePropertyTest.class);
+ addTestSuite(org.apache.jackrabbit.test.api.StringPropertyTest.class);
+ addTestSuite(org.apache.jackrabbit.test.api.UndefinedPropertyTest.class);
+ addTestSuite(org.apache.jackrabbit.test.api.NamespaceRegistryReadMethodsTest.class);
+ addTestSuite(org.apache.jackrabbit.test.api.NamespaceRemappingTest.class);
+ addTestSuite(org.apache.jackrabbit.test.api.NodeIteratorTest.class);
+ addTestSuite(org.apache.jackrabbit.test.api.PropertyReadMethodsTest.class);
+ addTestSuite(org.apache.jackrabbit.test.api.RepositoryDescriptorTest.class);
+ addTestSuite(org.apache.jackrabbit.test.api.SessionReadMethodsTest.class);
+ addTestSuite(org.apache.jackrabbit.test.api.WorkspaceReadMethodsTest.class);
+ addTestSuite(org.apache.jackrabbit.test.api.ReferenceableRootNodesTest.class);
+ addTestSuite(org.apache.jackrabbit.test.api.ExportSysViewTest.class);
+ addTestSuite(org.apache.jackrabbit.test.api.ExportDocViewTest.class);
+ addTestSuite(org.apache.jackrabbit.test.api.RepositoryLoginTest.class);
+
+ // These might not all be level one tests
+ addTestSuite(org.apache.jackrabbit.test.api.query.XPathPosIndexTest.class);
+ addTestSuite(org.apache.jackrabbit.test.api.query.XPathDocOrderTest.class);
+ addTestSuite(org.apache.jackrabbit.test.api.query.XPathOrderByTest.class);
+ addTestSuite(org.apache.jackrabbit.test.api.query.XPathJcrPathTest.class);
+
+ addTestSuite(org.apache.jackrabbit.test.api.query.ElementTest.class);
+ addTestSuite(org.apache.jackrabbit.test.api.query.OrderByDateTest.class);
+ addTestSuite(org.apache.jackrabbit.test.api.query.OrderByDoubleTest.class);
+ addTestSuite(org.apache.jackrabbit.test.api.query.OrderByLongTest.class);
+ addTestSuite(org.apache.jackrabbit.test.api.query.OrderByMultiTypeTest.class);
+ addTestSuite(org.apache.jackrabbit.test.api.query.OrderByStringTest.class);
+ addTestSuite(org.apache.jackrabbit.test.api.query.QueryResultNodeIteratorTest.class);
+ addTestSuite(org.apache.jackrabbit.test.api.query.XPathDocOrderTest.class);
+ addTestSuite(org.apache.jackrabbit.test.api.query.XPathJcrPathTest.class);
+ addTestSuite(org.apache.jackrabbit.test.api.query.XPathOrderByTest.class);
+ addTestSuite(org.apache.jackrabbit.test.api.query.XPathPosIndexTest.class);
+
+ addTestSuite(org.apache.jackrabbit.test.api.query.DerefQueryLevel1Test.class);
+ addTestSuite(org.apache.jackrabbit.test.api.query.GetLanguageTest.class);
+ addTestSuite(org.apache.jackrabbit.test.api.query.GetPersistentQueryPathLevel1Test.class);
+ addTestSuite(org.apache.jackrabbit.test.api.query.GetStatementTest.class);
+ addTestSuite(org.apache.jackrabbit.test.api.query.GetSupportedQueryLanguagesTest.class);
+ addTestSuite(org.apache.jackrabbit.test.api.query.GetPropertyNamesTest.class);
+ addTestSuite(org.apache.jackrabbit.test.api.query.PredicatesTest.class);
+ addTestSuite(org.apache.jackrabbit.test.api.query.SimpleSelectionTest.class);
+
+ // The tests in this suite are level one
+ addTest(org.apache.jackrabbit.test.api.nodetype.TestAll.suite());
+ }
+ }
+
+}
Added: trunk/dna-jcr-tck/src/test/java/org/jboss/dna/jcr/Jsr170LevelTwoTckTest.java
===================================================================
--- trunk/dna-jcr-tck/src/test/java/org/jboss/dna/jcr/Jsr170LevelTwoTckTest.java (rev 0)
+++ trunk/dna-jcr-tck/src/test/java/org/jboss/dna/jcr/Jsr170LevelTwoTckTest.java 2009-03-24 03:18:34 UTC (rev 792)
@@ -0,0 +1,196 @@
+/*
+ * 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 junit.framework.Test;
+import junit.framework.TestSuite;
+import org.apache.jackrabbit.test.JCRTestSuite;
+import org.apache.jackrabbit.test.api.AddNodeTest;
+import org.apache.jackrabbit.test.api.CheckPermissionTest;
+import org.apache.jackrabbit.test.api.DocumentViewImportTest;
+import org.apache.jackrabbit.test.api.ImpersonateTest;
+import org.apache.jackrabbit.test.api.NamespaceRegistryTest;
+import org.apache.jackrabbit.test.api.NodeAddMixinTest;
+import org.apache.jackrabbit.test.api.NodeCanAddMixinTest;
+import org.apache.jackrabbit.test.api.NodeItemIsModifiedTest;
+import org.apache.jackrabbit.test.api.NodeItemIsNewTest;
+import org.apache.jackrabbit.test.api.NodeOrderableChildNodesTest;
+import org.apache.jackrabbit.test.api.NodeRemoveMixinTest;
+import org.apache.jackrabbit.test.api.NodeTest;
+import org.apache.jackrabbit.test.api.NodeUUIDTest;
+import org.apache.jackrabbit.test.api.PropertyItemIsModifiedTest;
+import org.apache.jackrabbit.test.api.PropertyItemIsNewTest;
+import org.apache.jackrabbit.test.api.PropertyTest;
+import org.apache.jackrabbit.test.api.ReferencesTest;
+import org.apache.jackrabbit.test.api.RepositoryLoginTest;
+import org.apache.jackrabbit.test.api.SerializationTest;
+import org.apache.jackrabbit.test.api.SessionTest;
+import org.apache.jackrabbit.test.api.SessionUUIDTest;
+import org.apache.jackrabbit.test.api.SetPropertyAssumeTypeTest;
+import org.apache.jackrabbit.test.api.SetPropertyBooleanTest;
+import org.apache.jackrabbit.test.api.SetPropertyCalendarTest;
+import org.apache.jackrabbit.test.api.SetPropertyConstraintViolationExceptionTest;
+import org.apache.jackrabbit.test.api.SetPropertyDoubleTest;
+import org.apache.jackrabbit.test.api.SetPropertyInputStreamTest;
+import org.apache.jackrabbit.test.api.SetPropertyLongTest;
+import org.apache.jackrabbit.test.api.SetPropertyNodeTest;
+import org.apache.jackrabbit.test.api.SetPropertyStringTest;
+import org.apache.jackrabbit.test.api.SetPropertyValueTest;
+import org.apache.jackrabbit.test.api.SetValueBinaryTest;
+import org.apache.jackrabbit.test.api.SetValueBooleanTest;
+import org.apache.jackrabbit.test.api.SetValueConstraintViolationExceptionTest;
+import org.apache.jackrabbit.test.api.SetValueDateTest;
+import org.apache.jackrabbit.test.api.SetValueDoubleTest;
+import org.apache.jackrabbit.test.api.SetValueLongTest;
+import org.apache.jackrabbit.test.api.SetValueReferenceTest;
+import org.apache.jackrabbit.test.api.SetValueStringTest;
+import org.apache.jackrabbit.test.api.SetValueValueFormatExceptionTest;
+import org.apache.jackrabbit.test.api.SetValueVersionExceptionTest;
+import org.apache.jackrabbit.test.api.ValueFactoryTest;
+import org.apache.jackrabbit.test.api.WorkspaceCloneReferenceableTest;
+import org.apache.jackrabbit.test.api.WorkspaceCloneSameNameSibsTest;
+import org.apache.jackrabbit.test.api.WorkspaceCloneTest;
+import org.apache.jackrabbit.test.api.WorkspaceCloneVersionableTest;
+import org.apache.jackrabbit.test.api.WorkspaceCopyBetweenWorkspacesReferenceableTest;
+import org.apache.jackrabbit.test.api.WorkspaceCopyBetweenWorkspacesSameNameSibsTest;
+import org.apache.jackrabbit.test.api.WorkspaceCopyBetweenWorkspacesTest;
+import org.apache.jackrabbit.test.api.WorkspaceCopyBetweenWorkspacesVersionableTest;
+import org.apache.jackrabbit.test.api.WorkspaceCopyReferenceableTest;
+import org.apache.jackrabbit.test.api.WorkspaceCopySameNameSibsTest;
+import org.apache.jackrabbit.test.api.WorkspaceCopyTest;
+import org.apache.jackrabbit.test.api.WorkspaceCopyVersionableTest;
+import org.apache.jackrabbit.test.api.WorkspaceMoveReferenceableTest;
+import org.apache.jackrabbit.test.api.WorkspaceMoveSameNameSibsTest;
+import org.apache.jackrabbit.test.api.WorkspaceMoveTest;
+import org.apache.jackrabbit.test.api.WorkspaceMoveVersionableTest;
+import org.apache.jackrabbit.test.api.query.GetPersistentQueryPathTest;
+import org.apache.jackrabbit.test.api.query.SaveTest;
+import org.apache.jackrabbit.test.api.query.XPathQueryLevel2Test;
+
+/**
+ * Test suite to wrap Apache Jackrabbit JCR technology compatibility kit (TCK) unit tests for Level 2 (L2) compliance. Note that
+ * technically these are not the actual TCK, but these are unit tests that happen to be similar to (or provided the basis for) a
+ * subset of the TCK.
+ */
+public class Jsr170LevelTwoTckTest {
+
+ /**
+ *
+ */
+ public Jsr170LevelTwoTckTest() {
+ }
+
+ /**
+ * Wrapper so that the Jackrabbit TCK test suite gets picked up by the DNA Maven test target.
+ *
+ * @return a new instance of {@link JCRTestSuite}.
+ */
+ public static Test suite() {
+ TestSuite suite = new TestSuite("JCR 1.0 Level 2 Compliance tests");
+
+ suite.addTest(new LevelTwoFeatureTests());
+
+ return suite;
+ }
+
+ /**
+ * Test suite that includes the Level 2 JCR TCK API tests from the Jackrabbit project.
+ */
+ private static class LevelTwoFeatureTests extends TestSuite {
+ protected LevelTwoFeatureTests() {
+ super("JCR Level 2 API Tests");
+ addTestSuite(AddNodeTest.class);
+ addTestSuite(NamespaceRegistryTest.class);
+ addTestSuite(ReferencesTest.class);
+ addTestSuite(SessionTest.class);
+ addTestSuite(SessionUUIDTest.class);
+ addTestSuite(NodeTest.class);
+ addTestSuite(NodeUUIDTest.class);
+ addTestSuite(NodeOrderableChildNodesTest.class);
+ addTestSuite(PropertyTest.class);
+
+ addTestSuite(SetValueBinaryTest.class);
+ addTestSuite(SetValueBooleanTest.class);
+ addTestSuite(SetValueDateTest.class);
+ addTestSuite(SetValueDoubleTest.class);
+ addTestSuite(SetValueLongTest.class);
+ addTestSuite(SetValueReferenceTest.class);
+ addTestSuite(SetValueStringTest.class);
+ addTestSuite(SetValueConstraintViolationExceptionTest.class);
+ addTestSuite(SetValueValueFormatExceptionTest.class);
+ addTestSuite(SetValueVersionExceptionTest.class);
+
+ addTestSuite(SetPropertyBooleanTest.class);
+ addTestSuite(SetPropertyCalendarTest.class);
+ addTestSuite(SetPropertyDoubleTest.class);
+ addTestSuite(SetPropertyInputStreamTest.class);
+ addTestSuite(SetPropertyLongTest.class);
+ addTestSuite(SetPropertyNodeTest.class);
+ addTestSuite(SetPropertyStringTest.class);
+ addTestSuite(SetPropertyValueTest.class);
+ addTestSuite(SetPropertyConstraintViolationExceptionTest.class);
+ addTestSuite(SetPropertyAssumeTypeTest.class);
+
+ addTestSuite(NodeItemIsModifiedTest.class);
+ addTestSuite(NodeItemIsNewTest.class);
+ addTestSuite(PropertyItemIsModifiedTest.class);
+ addTestSuite(PropertyItemIsNewTest.class);
+
+ addTestSuite(NodeAddMixinTest.class);
+ addTestSuite(NodeCanAddMixinTest.class);
+ addTestSuite(NodeRemoveMixinTest.class);
+
+ addTestSuite(WorkspaceCloneReferenceableTest.class);
+ addTestSuite(WorkspaceCloneSameNameSibsTest.class);
+ addTestSuite(WorkspaceCloneTest.class);
+ addTestSuite(WorkspaceCloneVersionableTest.class);
+ addTestSuite(WorkspaceCopyBetweenWorkspacesReferenceableTest.class);
+ addTestSuite(WorkspaceCopyBetweenWorkspacesSameNameSibsTest.class);
+ addTestSuite(WorkspaceCopyBetweenWorkspacesTest.class);
+ addTestSuite(WorkspaceCopyBetweenWorkspacesVersionableTest.class);
+ addTestSuite(WorkspaceCopyReferenceableTest.class);
+ addTestSuite(WorkspaceCopySameNameSibsTest.class);
+ addTestSuite(WorkspaceCopyTest.class);
+ addTestSuite(WorkspaceCopyVersionableTest.class);
+ addTestSuite(WorkspaceMoveReferenceableTest.class);
+ addTestSuite(WorkspaceMoveSameNameSibsTest.class);
+ addTestSuite(WorkspaceMoveTest.class);
+ addTestSuite(WorkspaceMoveVersionableTest.class);
+
+ addTestSuite(RepositoryLoginTest.class);
+ addTestSuite(ImpersonateTest.class);
+ addTestSuite(CheckPermissionTest.class);
+
+ addTestSuite(DocumentViewImportTest.class);
+ addTestSuite(SerializationTest.class);
+
+ addTestSuite(ValueFactoryTest.class);
+
+ addTestSuite(GetPersistentQueryPathTest.class);
+ addTestSuite(SaveTest.class);
+ addTestSuite(XPathQueryLevel2Test.class);
+
+ }
+ }
+}
Added: trunk/dna-jcr-tck/src/test/java/org/jboss/dna/jcr/Jsr170OptionalLockingTckTest.java
===================================================================
--- trunk/dna-jcr-tck/src/test/java/org/jboss/dna/jcr/Jsr170OptionalLockingTckTest.java (rev 0)
+++ trunk/dna-jcr-tck/src/test/java/org/jboss/dna/jcr/Jsr170OptionalLockingTckTest.java 2009-03-24 03:18:34 UTC (rev 792)
@@ -0,0 +1,67 @@
+/*
+ * 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 junit.framework.Test;
+import junit.framework.TestSuite;
+import org.apache.jackrabbit.test.JCRTestSuite;
+
+/**
+ * Test suite to wrap Apache Jackrabbit JCR technology compatibility kit (TCK) unit tests for the compliance of the optional
+ * locking feature. Note that technically these are not the actual TCK, but these are unit tests that happen to be similar to (or
+ * provided the basis for) a subset of the TCK.
+ */
+public class Jsr170OptionalLockingTckTest {
+
+ /**
+ *
+ */
+ public Jsr170OptionalLockingTckTest() {
+ }
+
+ /**
+ * Wrapper so that the Jackrabbit TCK test suite gets picked up by the DNA Maven test target.
+ *
+ * @return a new instance of {@link JCRTestSuite}.
+ */
+ public static Test suite() {
+ TestSuite suite = new TestSuite("JCR 1.0 Optional Feature (Locking) Compliance tests");
+
+ suite.addTest(new OptionalLockingFeatureTests());
+
+ return suite;
+ }
+
+ /**
+ * Test suite for the locking tests
+ */
+ private static class OptionalLockingFeatureTests extends TestSuite {
+ protected OptionalLockingFeatureTests() {
+ super("JCR Optional Feature (Locking) Tests");
+
+ addTest(org.apache.jackrabbit.test.api.lock.TestAll.suite());
+ }
+ }
+
+}
Added: trunk/dna-jcr-tck/src/test/java/org/jboss/dna/jcr/Jsr170OptionalObservationTckTest.java
===================================================================
--- trunk/dna-jcr-tck/src/test/java/org/jboss/dna/jcr/Jsr170OptionalObservationTckTest.java (rev 0)
+++ trunk/dna-jcr-tck/src/test/java/org/jboss/dna/jcr/Jsr170OptionalObservationTckTest.java 2009-03-24 03:18:34 UTC (rev 792)
@@ -0,0 +1,67 @@
+/*
+ * 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 junit.framework.Test;
+import junit.framework.TestSuite;
+import org.apache.jackrabbit.test.JCRTestSuite;
+
+/**
+ * Test suite to wrap Apache Jackrabbit JCR technology compatibility kit (TCK) unit tests for the compliance of the optional
+ * observation feature. Note that technically these are not the actual TCK, but these are unit tests that happen to be similar to (or
+ * provided the basis for) a subset of the TCK.
+ */
+public class Jsr170OptionalObservationTckTest {
+
+ /**
+ *
+ */
+ public Jsr170OptionalObservationTckTest() {
+ }
+
+ /**
+ * Wrapper so that the Jackrabbit TCK test suite gets picked up by the DNA Maven test target.
+ *
+ * @return a new instance of {@link JCRTestSuite}.
+ */
+ public static Test suite() {
+ TestSuite suite = new TestSuite("JCR 1.0 Optional Feature (Observation) Compliance tests");
+
+ suite.addTest(new OptionalObservationFeatureTests());
+
+ return suite;
+ }
+
+ /**
+ * Test suite for the observation tests
+ */
+ private static class OptionalObservationFeatureTests extends TestSuite {
+ protected OptionalObservationFeatureTests() {
+ super("JCR Optional Feature (Observation) Tests");
+
+ addTest(org.apache.jackrabbit.test.api.observation.TestAll.suite());
+ }
+ }
+
+}
Added: trunk/dna-jcr-tck/src/test/java/org/jboss/dna/jcr/Jsr170OptionalSqlQueryTckTest.java
===================================================================
--- trunk/dna-jcr-tck/src/test/java/org/jboss/dna/jcr/Jsr170OptionalSqlQueryTckTest.java (rev 0)
+++ trunk/dna-jcr-tck/src/test/java/org/jboss/dna/jcr/Jsr170OptionalSqlQueryTckTest.java 2009-03-24 03:18:34 UTC (rev 792)
@@ -0,0 +1,76 @@
+/*
+ * 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 junit.framework.Test;
+import junit.framework.TestSuite;
+import org.apache.jackrabbit.test.JCRTestSuite;
+import org.apache.jackrabbit.test.api.query.SQLJcrPathTest;
+import org.apache.jackrabbit.test.api.query.SQLJoinTest;
+import org.apache.jackrabbit.test.api.query.SQLOrderByTest;
+import org.apache.jackrabbit.test.api.query.SQLPathTest;
+import org.apache.jackrabbit.test.api.query.SQLQueryLevel2Test;
+
+/**
+ * Test suite to wrap Apache Jackrabbit JCR technology compatibility kit (TCK) unit tests for the compliance of the optional
+ * JCR-SQL query feature. Note that technically these are not the actual TCK, but these are unit tests that happen to be similar
+ * to (or provided the basis for) a subset of the TCK.
+ */
+public class Jsr170OptionalSqlQueryTckTest {
+
+ /**
+ *
+ */
+ public Jsr170OptionalSqlQueryTckTest() {
+ }
+
+ /**
+ * Wrapper so that the Jackrabbit TCK test suite gets picked up by the DNA Maven test target.
+ *
+ * @return a new instance of {@link JCRTestSuite}.
+ */
+ public static Test suite() {
+ TestSuite suite = new TestSuite("JCR 1.0 Optional Feature (JCR-SQL Query) Compliance tests");
+
+ suite.addTest(new OptionalSqlQueryFeatureTests());
+
+ return suite;
+ }
+
+ /**
+ * Test suite for the JCR-SQL query tests
+ */
+ private static class OptionalSqlQueryFeatureTests extends TestSuite {
+ protected OptionalSqlQueryFeatureTests() {
+ super("JCR Optional Feature (JCR-SQL Query) Tests");
+
+ addTestSuite(SQLOrderByTest.class);
+ addTestSuite(SQLQueryLevel2Test.class);
+ addTestSuite(SQLJoinTest.class);
+ addTestSuite(SQLJcrPathTest.class);
+ addTestSuite(SQLPathTest.class);
+ }
+ }
+
+}
Added: trunk/dna-jcr-tck/src/test/java/org/jboss/dna/jcr/Jsr170OptionalVersionTckTest.java
===================================================================
--- trunk/dna-jcr-tck/src/test/java/org/jboss/dna/jcr/Jsr170OptionalVersionTckTest.java (rev 0)
+++ trunk/dna-jcr-tck/src/test/java/org/jboss/dna/jcr/Jsr170OptionalVersionTckTest.java 2009-03-24 03:18:34 UTC (rev 792)
@@ -0,0 +1,67 @@
+/*
+ * 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 junit.framework.Test;
+import junit.framework.TestSuite;
+import org.apache.jackrabbit.test.JCRTestSuite;
+
+/**
+ * Test suite to wrap Apache Jackrabbit JCR technology compatibility kit (TCK) unit tests for the compliance of the optional
+ * version feature. Note that technically these are not the actual TCK, but these are unit tests that happen to be similar to (or
+ * provided the basis for) a subset of the TCK.
+ */
+public class Jsr170OptionalVersionTckTest {
+
+ /**
+ *
+ */
+ public Jsr170OptionalVersionTckTest() {
+ }
+
+ /**
+ * Wrapper so that the Jackrabbit TCK test suite gets picked up by the DNA Maven test target.
+ *
+ * @return a new instance of {@link JCRTestSuite}.
+ */
+ public static Test suite() {
+ TestSuite suite = new TestSuite("JCR 1.0 Optional Feature (Version) Compliance tests");
+
+ suite.addTest(new OptionalVersionFeatureTests());
+
+ return suite;
+ }
+
+ /**
+ * Test suite for the version tests.
+ */
+ private static class OptionalVersionFeatureTests extends TestSuite {
+ protected OptionalVersionFeatureTests() {
+ super("JCR Optional Feature (Version) Tests");
+
+ addTest(org.apache.jackrabbit.test.api.version.TestAll.suite());
+ }
+ }
+
+}
Added: trunk/dna-jcr-tck/src/test/resources/log4j.properties
===================================================================
--- trunk/dna-jcr-tck/src/test/resources/log4j.properties (rev 0)
+++ trunk/dna-jcr-tck/src/test/resources/log4j.properties 2009-03-24 03:18:34 UTC (rev 792)
@@ -0,0 +1,12 @@
+# Direct log messages to stdout
+log4j.appender.stdout=org.apache.log4j.ConsoleAppender
+log4j.appender.stdout.Target=System.out
+log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %m%n
+
+# Root logger option
+log4j.rootLogger=INFO, stdout
+
+# Set up the default logging to be INFO level, then override specific units
+log4j.logger.org.jboss.dna=INFO
+
Added: trunk/dna-jcr-tck/src/test/resources/repositoryForTckTests.xml
===================================================================
--- trunk/dna-jcr-tck/src/test/resources/repositoryForTckTests.xml (rev 0)
+++ trunk/dna-jcr-tck/src/test/resources/repositoryForTckTests.xml 2009-03-24 03:18:34 UTC (rev 792)
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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 distribution; if not, write to:
+ ~ Free Software Foundation, Inc.
+ ~ 51 Franklin Street, Fifth Floor
+ ~ Boston, MA 02110-1301 USA
+ -->
+<testroot xmlns:jcr="http://www.jcp.org/jcr/1.0"
+ xmlns:nt="http://www.jcp.org/jcr/nt/1.0"
+ xmlns:dna="http://www.jboss.org/dna/1.0"
+ jcr:primaryType="nt:unstructured">
+ <nt:unstructured jcr:name="node1" prop1="<foo&foo>" >
+ <!--
+ This stanza checks for the jcr:xmltext special case for export as per JCR 1.0.1 section 6.4.2.3
+ -->
+ <nt:unstructured jcr:name="jcr:xmltext" jcr:xmlcharacters="This is my "XML" text!" />
+ </nt:unstructured>
+ <nt:unstructured jcr:name="node2 has a multi-word name" multi-valued-property="bar baz blah">
+ <!--
+ This stanza checks that consecutive jcr:xmltext elements will be merged in the export as
+ per JCR 1.0.1 section 6.4.2.3
+ -->
+ <nt:unstructured jcr:name="jcr:xmltext" jcr:xmlcharacters="This is my "XML" text!" />
+ <nt:unstructured jcr:name="jcr:xmltext" jcr:xmlcharacters="This is my "other" text!" />
+ </nt:unstructured>
+ <!--
+ Test of unprintable character exports.
+ Cannot test \r character here on Windows as TCK XML Parser will replace it with \n and fail the comparison
+ -->
+ <nt:unstructured jcr:name="node3" multi-line-property="Line	1
Line 2"/>
+
+ <!-- Helps test date property conversion, mandatory properties (jcr:content), and primary items -->
+ <!--
+ <nt:folder jcr:name="hierarchyRoot" jcr:created="+2009-03-15T12:30:00.000Z">
+ <nt:file jcr:name="testFile" jcr:created="+2009-03-15T13:30:00.000Z">
+ <nt:unstructured jcr:name="jcr:content" />
+ </nt:file>
+ </nt:folder>
+ -->
+</testroot>
\ No newline at end of file
Added: trunk/dna-jcr-tck/src/test/resources/repositoryStubImpl.properties
===================================================================
--- trunk/dna-jcr-tck/src/test/resources/repositoryStubImpl.properties (rev 0)
+++ trunk/dna-jcr-tck/src/test/resources/repositoryStubImpl.properties 2009-03-24 03:18:34 UTC (rev 792)
@@ -0,0 +1,9 @@
+javax.jcr.tck.repository_stub_impl=org.jboss.dna.jcr.InMemoryRepositoryStub
+javax.jcr.tck.testroot=/testroot
+javax.jcr.tck.nodename1=node1
+javax.jcr.tck.nodename2=node2
+javax.jcr.tck.nodename3=node3
+javax.jcr.tck.nodename4=node4
+javax.jcr.tck.propertyname1=prop1
+javax.jcr.tck.propertyname2=prop2
+javax.jcr.tck.workspacename=
Modified: trunk/pom.xml
===================================================================
--- trunk/pom.xml 2009-03-24 02:51:24 UTC (rev 791)
+++ trunk/pom.xml 2009-03-24 03:18:34 UTC (rev 792)
@@ -142,10 +142,16 @@
<id>release</id>
<modules>
<module>docs</module>
- <module>docs/examples/gettingstarted</module>
+ <module>docs/examples/gettingstarted</module>
</modules>
</profile>
<profile>
+ <id>jcr-tck</id>
+ <modules>
+ <module>dna-jcr-tck</module>
+ </modules>
+ </profile>
+ <profile>
<!--
This profile is activated when the "generate.docs" property is set,
as in "mvn ... -Dgenerate.docs=true ..."
15 years, 2 months
DNA SVN: r791 - in trunk/dna-jcr/src: test/java/org/jboss/dna/jcr and 1 other directory.
by dna-commits@lists.jboss.org
Author: rhauch
Date: 2009-03-23 22:51:24 -0400 (Mon, 23 Mar 2009)
New Revision: 791
Modified:
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrNodeTypeSource.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/DnaBuiltinNodeTypeSource.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrBuiltinNodeTypeSource.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNodeTypeManager.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNodeTypeSource.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/RepositoryNodeTypeManager.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrPropertyDefinitionTest.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/SessionCacheTest.java
Log:
DNA-335 DNA's NodeTypeManager implementation does not allow multiple definitions with the same name
Applied the patch ("DNA-335_clean_type_source") that simplifies RepositoryTypeManager's internal type handling by combining the primaryNodeTypes and mixinNodeTypes into a single map under the assumption that lookups of types by name (which must check primary and mixin types) will be the most common option and retrieval of all primary or mixin types will be relatively rare.
This also allows for a simplification of the JcrNodeTypeSource hierarchy.
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrNodeTypeSource.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrNodeTypeSource.java 2009-03-24 02:34:43 UTC (rev 790)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrNodeTypeSource.java 2009-03-24 02:51:24 UTC (rev 791)
@@ -71,67 +71,38 @@
}
/**
- * Returns the list of mixin node types declared in this type source.
+ * Returns the list of node types declared in this type source.
*
- * @return the list of mixin node types declared in this type source.
- * @see org.jboss.dna.jcr.JcrNodeTypeSource#getMixinNodeTypes()
+ * @return the list of node types declared in this type source.
+ * @see org.jboss.dna.jcr.JcrNodeTypeSource#getNodeTypes()
*/
- public abstract Collection<JcrNodeType> getDeclaredMixinNodeTypes();
+ public abstract Collection<JcrNodeType> getDeclaredNodeTypes();
/**
- * Returns the list of primary node types declared in this type source.
+ * Returns the list of node types returned by this and any predecessor source.
*
- * @return the list of primary node types declared in this type source.
- * @see org.jboss.dna.jcr.JcrNodeTypeSource#getMixinNodeTypes()
+ * @return the list of node types returned by this and any predecessor source.
+ * @see org.jboss.dna.jcr.JcrNodeTypeSource#getNodeTypes()
*/
- public abstract Collection<JcrNodeType> getDeclaredPrimaryNodeTypes();
-
- /**
- * Returns the list of mixin node types returned by this and any predecessor source.
- *
- * @return the list of mixin node types returned by this and any predecessor source.
- * @see org.jboss.dna.jcr.JcrNodeTypeSource#getMixinNodeTypes()
- */
- public Collection<JcrNodeType> getMixinNodeTypes() {
+ public Collection<JcrNodeType> getNodeTypes() {
if (predecessor == null) {
- return getDeclaredMixinNodeTypes();
+ return getDeclaredNodeTypes();
}
- Collection<JcrNodeType> declaredMixins = getDeclaredMixinNodeTypes();
- Collection<JcrNodeType> predecessorMixins = predecessor.getMixinNodeTypes();
+ Collection<JcrNodeType> declaredTypes = getDeclaredNodeTypes();
+ Collection<JcrNodeType> predecessorTypes = predecessor.getNodeTypes();
- List<JcrNodeType> mixins = new ArrayList<JcrNodeType>(declaredMixins.size() + predecessorMixins.size());
- mixins.addAll(predecessorMixins);
- mixins.addAll(declaredMixins);
+ List<JcrNodeType> primaries = new ArrayList<JcrNodeType>(declaredTypes.size() + predecessorTypes.size());
+ primaries.addAll(predecessorTypes);
+ primaries.addAll(declaredTypes);
- return mixins;
- }
-
- /**
- * Returns the list of primary node types returned by this and any predecessor source.
- *
- * @return the list of primary node types returned by this and any predecessor source.
- * @see org.jboss.dna.jcr.JcrNodeTypeSource#getPrimaryNodeTypes()
- */
- public Collection<JcrNodeType> getPrimaryNodeTypes() {
- if (predecessor == null) {
- return getDeclaredPrimaryNodeTypes();
- }
-
- Collection<JcrNodeType> declaredPrimaries = getDeclaredPrimaryNodeTypes();
- Collection<JcrNodeType> predecessorPrimaries = predecessor.getPrimaryNodeTypes();
-
- List<JcrNodeType> primaries = new ArrayList<JcrNodeType>(declaredPrimaries.size() + predecessorPrimaries.size());
- primaries.addAll(predecessorPrimaries);
- primaries.addAll(declaredPrimaries);
-
return primaries;
}
/**
* Finds the type with the given name and returns its definition.
* <p>
- * This implementation delegates to the <code>predecessor</code> (if it exists) if the type is not found within the declareded
+ * This implementation delegates to the <code>predecessor</code> (if it exists) if the type is not found within the declared
* primary and mixin types.
* </p>
*
@@ -142,18 +113,12 @@
*/
public JcrNodeType findType( Name typeName ) {
CheckArg.isNotNull(typeName, "typeName");
- for (JcrNodeType type : getDeclaredPrimaryNodeTypes()) {
+ for (JcrNodeType type : getDeclaredNodeTypes()) {
if (typeName.equals(type.getInternalName())) {
return type;
}
}
- for (JcrNodeType type : getDeclaredMixinNodeTypes()) {
- if (typeName.equals(type.getInternalName())) {
- return type;
- }
- }
-
if (predecessor != null) {
return predecessor.findType(typeName);
}
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-03-24 02:34:43 UTC (rev 790)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/DnaBuiltinNodeTypeSource.java 2009-03-24 02:51:24 UTC (rev 791)
@@ -38,17 +38,14 @@
@Immutable
class DnaBuiltinNodeTypeSource extends AbstractJcrNodeTypeSource {
- /** The list of primary node types. */
- private final List<JcrNodeType> primaryNodeTypes;
- /** The list of mixin node types. */
- private final List<JcrNodeType> mixinNodeTypes;
+ /** The list of node types. */
+ private final List<JcrNodeType> nodeTypes;
DnaBuiltinNodeTypeSource( ExecutionContext context,
JcrNodeTypeSource predecessor ) {
super(predecessor);
- primaryNodeTypes = new ArrayList<JcrNodeType>();
- mixinNodeTypes = new ArrayList<JcrNodeType>();
+ nodeTypes = new ArrayList<JcrNodeType>();
JcrNodeType base = findType(JcrNtLexicon.BASE);
@@ -140,29 +137,19 @@
NO_DEFAULT_VALUES, PropertyType.UNDEFINED, NO_CONSTRAINTS, true),}), NOT_MIXIN,
ORDERABLE_CHILD_NODES);
- primaryNodeTypes.addAll(Arrays.asList(new JcrNodeType[] {root, system, namespaces, namespace,}));
- mixinNodeTypes.addAll(Arrays.asList(new JcrNodeType[] {}));
+ nodeTypes.addAll(Arrays.asList(new JcrNodeType[] {root, system, namespaces, namespace,}));
+ nodeTypes.addAll(Arrays.asList(new JcrNodeType[] {}));
}
/**
* {@inheritDoc}
*
- * @see org.jboss.dna.jcr.JcrNodeTypeSource#getMixinNodeTypes()
+ * @see org.jboss.dna.jcr.JcrNodeTypeSource#getNodeTypes()
*/
@Override
- public Collection<JcrNodeType> getDeclaredMixinNodeTypes() {
- return mixinNodeTypes;
+ public Collection<JcrNodeType> getDeclaredNodeTypes() {
+ return nodeTypes;
}
- /**
- * {@inheritDoc}
- *
- * @see org.jboss.dna.jcr.JcrNodeTypeSource#getPrimaryNodeTypes()
- */
- @Override
- public Collection<JcrNodeType> getDeclaredPrimaryNodeTypes() {
- return primaryNodeTypes;
- }
-
}
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrBuiltinNodeTypeSource.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrBuiltinNodeTypeSource.java 2009-03-24 02:34:43 UTC (rev 790)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrBuiltinNodeTypeSource.java 2009-03-24 02:51:24 UTC (rev 791)
@@ -41,9 +41,7 @@
class JcrBuiltinNodeTypeSource extends AbstractJcrNodeTypeSource {
/** The list of primary node types. */
- private final List<JcrNodeType> primaryNodeTypes;
- /** The list of mixin node types. */
- private final List<JcrNodeType> mixinNodeTypes;
+ private final List<JcrNodeType> nodeTypes;
JcrBuiltinNodeTypeSource( ExecutionContext context ) {
this(context, null);
@@ -53,7 +51,7 @@
JcrNodeTypeSource predecessor ) {
super(predecessor);
- primaryNodeTypes = new ArrayList<JcrNodeType>();
+ nodeTypes = new ArrayList<JcrNodeType>();
/*
* These values get created without a session cache, as they aren't tied to any particular session.
@@ -568,12 +566,10 @@
false),}),
NOT_MIXIN, UNORDERABLE_CHILD_NODES);
- primaryNodeTypes.addAll(Arrays.asList(new JcrNodeType[] {base, unstructured, childNodeDefinition, file, folder,
+ nodeTypes.addAll(Arrays.asList(new JcrNodeType[] {base, unstructured, childNodeDefinition, file, folder,
frozenNode, hierarchyNode, linkedFile, nodeType, propertyDefinition, query, resource, nodeType, version,
versionHistory, versionLabels, versionedChild}));
- mixinNodeTypes = new ArrayList<JcrNodeType>();
-
JcrNodeType lockable = new JcrNodeType(context, NO_NODE_TYPE_MANAGER, JcrMixLexicon.LOCKABLE, NO_SUPERTYPES,
NO_PRIMARY_ITEM_NAME, NO_CHILD_NODES, Arrays.asList(new JcrPropertyDefinition[] {
new JcrPropertyDefinition(context, null, JcrLexicon.LOCK_IS_DEEP,
@@ -616,28 +612,17 @@
PropertyType.REFERENCE, NO_CONSTRAINTS, false),}),
IS_A_MIXIN, UNORDERABLE_CHILD_NODES);
- mixinNodeTypes.addAll(Arrays.asList(new JcrNodeType[] {lockable, referenceable, versionable}));
+ nodeTypes.addAll(Arrays.asList(new JcrNodeType[] {lockable, referenceable, versionable}));
}
/**
* {@inheritDoc}
*
- * @see org.jboss.dna.jcr.JcrNodeTypeSource#getMixinNodeTypes()
+ * @see org.jboss.dna.jcr.JcrNodeTypeSource#getNodeTypes()
*/
@Override
- public Collection<JcrNodeType> getDeclaredMixinNodeTypes() {
- return mixinNodeTypes;
+ public Collection<JcrNodeType> getDeclaredNodeTypes() {
+ return nodeTypes;
}
-
- /**
- * {@inheritDoc}
- *
- * @see org.jboss.dna.jcr.JcrNodeTypeSource#getPrimaryNodeTypes()
- */
- @Override
- public Collection<JcrNodeType> getDeclaredPrimaryNodeTypes() {
- return primaryNodeTypes;
- }
-
}
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNodeTypeManager.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNodeTypeManager.java 2009-03-24 02:34:43 UTC (rev 790)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNodeTypeManager.java 2009-03-24 02:51:24 UTC (rev 791)
@@ -65,31 +65,7 @@
* @see javax.jcr.nodetype.NodeTypeManager#getAllNodeTypes()
*/
public NodeTypeIterator getAllNodeTypes() {
-
- Collection<JcrNodeType> mixinNodeTypes = repositoryTypeManager.getMixinNodeTypes();
- Collection<JcrNodeType> primaryNodeTypes = repositoryTypeManager.getPrimaryNodeTypes();
-
- // TODO: Can revisit this approach later if it becomes a performance issue
- /*
- * Note also that this creates a subtle difference in behavior for concurrent modification
- * between this method and the specific get*NodeTypes methods. That is, if a type is added
- * while an iterator from the corresponding specific get*NodeType method is being traversed,
- * a ConcurrentModificationException will be thrown. Because this iterator is based on a copy
- * of the underlying maps, no exception would be thrown in the same case.
- */
-
- List<NodeType> allTypes = new ArrayList<NodeType>(primaryNodeTypes.size() + mixinNodeTypes.size());
-
- // Need to return a version of the node type with the current context
- for (JcrNodeType type : primaryNodeTypes) {
- allTypes.add(type.with(context));
- }
-
- for (JcrNodeType type : mixinNodeTypes) {
- allTypes.add(type.with(context));
- }
-
- return new JcrNodeTypeIterator(allTypes);
+ return new JcrNodeTypeIterator(repositoryTypeManager.getAllNodeTypes());
}
/**
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNodeTypeSource.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNodeTypeSource.java 2009-03-24 02:34:43 UTC (rev 790)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNodeTypeSource.java 2009-03-24 02:51:24 UTC (rev 791)
@@ -13,20 +13,13 @@
public interface JcrNodeTypeSource {
/**
- * Returns the list of primary node types provided by this source
+ * Returns the list of node types provided by this source
*
- * @return the list of primary node types provided by this source
+ * @return the list of node types provided by this source
*/
- public Collection<JcrNodeType> getPrimaryNodeTypes();
+ public Collection<JcrNodeType> getNodeTypes();
/**
- * Returns the list of mixin node types provided by this source
- *
- * @return the list of mixin node types provided by this source
- */
- public Collection<JcrNodeType> getMixinNodeTypes();
-
- /**
* Finds the type with the given name and returns its definition.
* @param typeName the name of the type to return
* @return the type named <code>typeName</code> if it exists, otherwise <code>null</code>.
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-03-24 02:34:43 UTC (rev 790)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/RepositoryNodeTypeManager.java 2009-03-24 02:51:24 UTC (rev 791)
@@ -23,6 +23,7 @@
*/
package org.jboss.dna.jcr;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
@@ -49,21 +50,19 @@
@Immutable
class RepositoryNodeTypeManager {
- private final Map<Name, JcrNodeType> primaryNodeTypes;
- private final Map<Name, JcrNodeType> mixinNodeTypes;
+ private final Map<Name, JcrNodeType> nodeTypes;
private final Map<PropertyDefinitionId, JcrPropertyDefinition> propertyDefinitions;
private final Map<NodeDefinitionId, JcrNodeDefinition> childNodeDefinitions;
RepositoryNodeTypeManager( ExecutionContext context,
JcrNodeTypeSource source ) {
- Collection<JcrNodeType> primary = source.getPrimaryNodeTypes();
- Collection<JcrNodeType> mixins = source.getMixinNodeTypes();
+ Collection<JcrNodeType> types = source.getNodeTypes();
propertyDefinitions = new HashMap<PropertyDefinitionId, JcrPropertyDefinition>();
childNodeDefinitions = new HashMap<NodeDefinitionId, JcrNodeDefinition>();
- primaryNodeTypes = new HashMap<Name, JcrNodeType>(primary.size());
- for (JcrNodeType nodeType : primary) {
- primaryNodeTypes.put(nodeType.getInternalName(), nodeType.with(this));
+ nodeTypes = new HashMap<Name, JcrNodeType>(types.size());
+ for (JcrNodeType nodeType : types) {
+ nodeTypes.put(nodeType.getInternalName(), nodeType.with(this));
for (JcrNodeDefinition childDefinition : nodeType.childNodeDefinitions()) {
childNodeDefinitions.put(childDefinition.getId(), childDefinition);
}
@@ -71,25 +70,30 @@
propertyDefinitions.put(propertyDefinition.getId(), propertyDefinition);
}
}
+ }
- mixinNodeTypes = new HashMap<Name, JcrNodeType>(mixins.size());
- for (JcrNodeType nodeType : mixins) {
- mixinNodeTypes.put(nodeType.getInternalName(), nodeType.with(this));
- for (JcrNodeDefinition childDefinition : nodeType.childNodeDefinitions()) {
- childNodeDefinitions.put(childDefinition.getId(), childDefinition);
- }
- for (JcrPropertyDefinition propertyDefinition : nodeType.propertyDefinitions()) {
- propertyDefinitions.put(propertyDefinition.getId(), propertyDefinition);
- }
- }
+ public Collection<JcrNodeType> getAllNodeTypes() {
+ return nodeTypes.values();
}
public Collection<JcrNodeType> getMixinNodeTypes() {
- return mixinNodeTypes.values();
+ 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() {
- return primaryNodeTypes.values();
+ List<JcrNodeType> types = new ArrayList<JcrNodeType>(nodeTypes.size());
+
+ for (JcrNodeType nodeType : nodeTypes.values()) {
+ if (!nodeType.isMixin()) types.add(nodeType);
+ }
+
+ return types;
}
public JcrPropertyDefinition getPropertyDefinition( PropertyDefinitionId id ) {
@@ -101,12 +105,7 @@
}
JcrNodeType getNodeType( Name nodeTypeName ) {
-
- JcrNodeType nodeType = primaryNodeTypes.get(nodeTypeName);
- if (nodeType == null) {
- nodeType = mixinNodeTypes.get(nodeTypeName);
- }
- return nodeType;
+ return nodeTypes.get(nodeTypeName);
}
/**
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrPropertyDefinitionTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrPropertyDefinitionTest.java 2009-03-24 02:34:43 UTC (rev 790)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrPropertyDefinitionTest.java 2009-03-24 02:51:24 UTC (rev 791)
@@ -149,7 +149,7 @@
session.logout();
}
}
-
+
private JcrPropertyDefinition propertyDefinitionFor( NodeType nodeType,
Name propertyName ) {
PropertyDefinition propertyDefs[] = nodeType.getPropertyDefinitions();
@@ -637,16 +637,13 @@
class TestNodeTypeSource extends AbstractJcrNodeTypeSource {
/** The list of primary node types. */
- private final List<JcrNodeType> primaryNodeTypes;
- /** The list of mixin node types. */
- private final List<JcrNodeType> mixinNodeTypes;
+ private final List<JcrNodeType> nodeTypes;
TestNodeTypeSource( ExecutionContext context,
JcrNodeTypeSource predecessor ) {
super(predecessor);
- primaryNodeTypes = new ArrayList<JcrNodeType>();
- mixinNodeTypes = new ArrayList<JcrNodeType>();
+ nodeTypes = new ArrayList<JcrNodeType>();
JcrNodeType base = findType(JcrNtLexicon.BASE);
@@ -736,30 +733,19 @@
}), NOT_MIXIN, UNORDERABLE_CHILD_NODES);
- primaryNodeTypes.addAll(Arrays.asList(new JcrNodeType[] {constrainedType}));
- mixinNodeTypes.addAll(Arrays.asList(new JcrNodeType[] {}));
+ nodeTypes.addAll(Arrays.asList(new JcrNodeType[] {constrainedType}));
}
/**
* {@inheritDoc}
*
- * @see org.jboss.dna.jcr.AbstractJcrNodeTypeSource#getDeclaredMixinNodeTypes()
+ * @see org.jboss.dna.jcr.AbstractJcrNodeTypeSource#getDeclaredNodeTypes()
*/
@Override
- public Collection<JcrNodeType> getDeclaredMixinNodeTypes() {
- return primaryNodeTypes;
+ public Collection<JcrNodeType> getDeclaredNodeTypes() {
+ return nodeTypes;
}
- /**
- * {@inheritDoc}
- *
- * @see org.jboss.dna.jcr.AbstractJcrNodeTypeSource#getDeclaredPrimaryNodeTypes()
- */
- @Override
- public Collection<JcrNodeType> getDeclaredPrimaryNodeTypes() {
- return mixinNodeTypes;
- }
-
}
}
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/SessionCacheTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/SessionCacheTest.java 2009-03-24 02:34:43 UTC (rev 790)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/SessionCacheTest.java 2009-03-24 02:51:24 UTC (rev 791)
@@ -112,14 +112,13 @@
* Define the node types for the "vehix" namespace.
*/
public static class VehixNodeTypeSource extends AbstractJcrNodeTypeSource {
- private final List<JcrNodeType> primaryNodeTypes;
- private final List<JcrNodeType> mixinNodeTypes;
+ private final List<JcrNodeType> nodeTypes;
public VehixNodeTypeSource( ExecutionContext context,
JcrNodeTypeSource predecessor ) {
super(predecessor);
- this.primaryNodeTypes = new ArrayList<JcrNodeType>();
- this.mixinNodeTypes = new ArrayList<JcrNodeType>();
+ this.nodeTypes = new ArrayList<JcrNodeType>();
+
Name carName = context.getValueFactories().getNameFactory().create("vehix:car");
Name aircraftName = context.getValueFactories().getNameFactory().create("vehix:aircraft");
JcrNodeType unstructured = findType(JcrNtLexicon.UNSTRUCTURED);
@@ -134,29 +133,19 @@
Arrays.asList(new JcrNodeType[] {unstructured}), NO_PRIMARY_ITEM_NAME,
NO_CHILD_NODES, NO_PROPERTIES, NOT_MIXIN, ORDERABLE_CHILD_NODES);
- primaryNodeTypes.addAll(Arrays.asList(new JcrNodeType[] {car, aircraft,}));
+ nodeTypes.addAll(Arrays.asList(new JcrNodeType[] {car, aircraft,}));
}
/**
* {@inheritDoc}
*
- * @see org.jboss.dna.jcr.AbstractJcrNodeTypeSource#getDeclaredMixinNodeTypes()
+ * @see org.jboss.dna.jcr.AbstractJcrNodeTypeSource#getDeclaredNodeTypes()
*/
@Override
- public Collection<JcrNodeType> getDeclaredMixinNodeTypes() {
- return mixinNodeTypes;
+ public Collection<JcrNodeType> getDeclaredNodeTypes() {
+ return nodeTypes;
}
- /**
- * {@inheritDoc}
- *
- * @see org.jboss.dna.jcr.AbstractJcrNodeTypeSource#getDeclaredPrimaryNodeTypes()
- */
- @Override
- public Collection<JcrNodeType> getDeclaredPrimaryNodeTypes() {
- return primaryNodeTypes;
- }
-
}
protected Graph createFrom( String repositoryName,
15 years, 2 months
DNA SVN: r790 - in trunk/dna-jcr/src: test/java/org/jboss/dna/jcr and 1 other directory.
by dna-commits@lists.jboss.org
Author: rhauch
Date: 2009-03-23 22:34:43 -0400 (Mon, 23 Mar 2009)
New Revision: 790
Removed:
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/TestNodeTypeSource.java
Modified:
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrPropertyDefinition.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrPropertyDefinitionTest.java
Log:
DNA-305 JcrNodeType.canSetProperty Does Not Enforce Constraints
Applied the "DNA-305_path_namespace" patch that makes path constraints support transient namespace remapping, modifies the test cases to verify this, and moves the test node type into class to clean up the package and make JcrPropertyDefinitionTest more consistent with the approach in SessionCacheTest. This fix should allow the defect to be resolved.
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrPropertyDefinition.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrPropertyDefinition.java 2009-03-24 02:29:20 UTC (rev 789)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrPropertyDefinition.java 2009-03-24 02:34:43 UTC (rev 790)
@@ -642,15 +642,22 @@
}
public boolean matches( Value valueToMatch ) {
- assert valueToMatch != null;
+ assert valueToMatch instanceof JcrValue;
+
+ JcrValue jcrValue = (JcrValue) valueToMatch;
- PathFactory pathFactory = context.getValueFactories().getPathFactory();
- Path value = pathFactory.create(((JcrValue)valueToMatch).value());
+ /*
+ * Need two path factories here. One uses the permanent namespace mappings to parse the constraints.
+ * The other also looks at the transient mappings to parse the checked value
+ */
+ PathFactory repoPathFactory = context.getValueFactories().getPathFactory();
+ PathFactory sessionPathFactory = jcrValue.sessionCache().context().getValueFactories().getPathFactory();
+ Path value = sessionPathFactory.create(((JcrValue)valueToMatch).value());
value = value.getNormalizedPath();
for (int i = 0; i < constraints.length; i++) {
boolean matchesDescendants = constraints[i].endsWith("*");
- Path constraintPath = pathFactory.create(matchesDescendants ? constraints[i].substring(0,
+ Path constraintPath = repoPathFactory.create(matchesDescendants ? constraints[i].substring(0,
constraints[i].length() - 2) : constraints[i]);
if (matchesDescendants && value.isDecendantOf(constraintPath)) {
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrPropertyDefinitionTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrPropertyDefinitionTest.java 2009-03-24 02:29:20 UTC (rev 789)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrPropertyDefinitionTest.java 2009-03-24 02:34:43 UTC (rev 790)
@@ -27,8 +27,11 @@
import static org.hamcrest.core.IsNull.notNullValue;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.stub;
+import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collection;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import javax.jcr.PropertyType;
import javax.jcr.Value;
@@ -55,17 +58,15 @@
*/
public class JcrPropertyDefinitionTest {
- private final String[] EXPECTED_BINARY_CONSTRAINTS = new String[] {"[,5)", "[10, 20)", "(30,40]", "[50,]"};
- private final String[] EXPECTED_DATE_CONSTRAINTS = new String[] {"[,+1945-08-01T01:30:00.000Z]",
+ protected final String[] EXPECTED_BINARY_CONSTRAINTS = new String[] {"[,5)", "[10, 20)", "(30,40]", "[50,]"};
+ protected final String[] EXPECTED_DATE_CONSTRAINTS = new String[] {"[,+1945-08-01T01:30:00.000Z]",
"[+1975-08-01T01:30:00.000Z,)"};
- private final String[] EXPECTED_DOUBLE_CONSTRAINTS = new String[] {"[,5.0)", "[10.1, 20.2)", "(30.3,40.4]", "[50.5,]"};
- private final String[] EXPECTED_LONG_CONSTRAINTS = new String[] {"[,5)", "[10, 20)", "(30,40]", "[50,]"};
- private final String[] EXPECTED_NAME_CONSTRAINTS = new String[] {"jcr:system", "dnatest:constrainedType"};
- // private final String[] EXPECTED_PATH_CONSTRAINTS = new String[] {"/" + JcrLexicon.Namespace.URI + ":system/*", "b",
- // "/a/b/c" };
- private final String[] EXPECTED_PATH_CONSTRAINTS = new String[] {"/jcr:system/*", "b", "/a/b/c"};
- private final String[] EXPECTED_REFERENCE_CONSTRAINTS = new String[] {"dna:root"};
- private final String[] EXPECTED_STRING_CONSTRAINTS = new String[] {"foo", "bar*", ".*baz"};
+ protected final String[] EXPECTED_DOUBLE_CONSTRAINTS = new String[] {"[,5.0)", "[10.1, 20.2)", "(30.3,40.4]", "[50.5,]"};
+ protected final String[] EXPECTED_LONG_CONSTRAINTS = new String[] {"[,5)", "[10, 20)", "(30,40]", "[50,]"};
+ protected final String[] EXPECTED_NAME_CONSTRAINTS = new String[] {"jcr:system", "dnatest:constrainedType"};
+ protected final String[] EXPECTED_PATH_CONSTRAINTS = new String[] {"/jcr:system/*", "b", "/a/b/c"};
+ protected final String[] EXPECTED_REFERENCE_CONSTRAINTS = new String[] {"dna:root"};
+ protected final String[] EXPECTED_STRING_CONSTRAINTS = new String[] {"foo", "bar*", ".*baz"};
private String workspaceName;
private ExecutionContext context;
@@ -210,7 +211,7 @@
private Value valueFor( Object value,
int jcrType ) {
- return new JcrValue(context.getValueFactories(), session.cache(), jcrType, value);
+ return new JcrValue(session.getExecutionContext().getValueFactories(), session.cache(), jcrType, value);
}
private String stringOfLength( int length ) {
@@ -552,7 +553,11 @@
assertThat(prop.satisfiesConstraints(valueFor("/a/b/c", PropertyType.PATH)), is(true));
assertThat(prop.satisfiesConstraints(valueFor("/jcr:system/dna:namespace", PropertyType.PATH)), is(true));
assertThat(prop.satisfiesConstraints(valueFor("/a/b/c/", PropertyType.PATH)), is(true));
- assertThat(prop.satisfiesConstraints(valueFor("/jcr:system/dna:foo", PropertyType.PATH)), is(true));
+
+ // Test that constraints work after session rename
+ session.setNamespacePrefix("jcr2", JcrLexicon.Namespace.URI);
+
+ assertThat(prop.satisfiesConstraints(valueFor("/jcr2:system/dna:foo", PropertyType.PATH)), is(true));
}
@Test
@@ -575,6 +580,7 @@
assertThat(prop.satisfiesConstraints(valueFor("/a/b", PropertyType.PATH)), is(false));
assertThat(prop.satisfiesConstraints(valueFor("/jcr:system", PropertyType.PATH)), is(false));
assertThat(prop.satisfiesConstraints(valueFor("/a/b/c/d", PropertyType.PATH)), is(false));
+
}
@Test
@@ -628,4 +634,132 @@
assertThat(satisfiesConstraints(prop, new Value[] {value}), is(false));
}
+ class TestNodeTypeSource extends AbstractJcrNodeTypeSource {
+
+ /** The list of primary node types. */
+ private final List<JcrNodeType> primaryNodeTypes;
+ /** The list of mixin node types. */
+ private final List<JcrNodeType> mixinNodeTypes;
+
+ TestNodeTypeSource( ExecutionContext context,
+ JcrNodeTypeSource predecessor ) {
+ super(predecessor);
+
+ primaryNodeTypes = new ArrayList<JcrNodeType>();
+ mixinNodeTypes = new ArrayList<JcrNodeType>();
+
+ JcrNodeType base = findType(JcrNtLexicon.BASE);
+
+ if (base == null) {
+ String baseTypeName = JcrNtLexicon.BASE.getString(context.getNamespaceRegistry());
+ String namespaceTypeName = DnaLexicon.NAMESPACE.getString(context.getNamespaceRegistry());
+ throw new IllegalStateException(JcrI18n.supertypeNotFound.text(baseTypeName, namespaceTypeName));
+ }
+
+ // Stubbing in child node and property definitions for now
+ JcrNodeType constrainedType = new JcrNodeType(
+ context,
+ NO_NODE_TYPE_MANAGER,
+ TestLexicon.CONSTRAINED_TYPE,
+ Arrays.asList(new JcrNodeType[] {base}),
+ NO_PRIMARY_ITEM_NAME,
+ NO_CHILD_NODES,
+ Arrays.asList(new JcrPropertyDefinition[] {
+ new JcrPropertyDefinition(
+ context,
+ null,
+ TestLexicon.CONSTRAINED_BINARY,
+ OnParentVersionBehavior.IGNORE.getJcrValue(),
+ false, false, false, NO_DEFAULT_VALUES,
+ PropertyType.BINARY,
+ EXPECTED_BINARY_CONSTRAINTS, false),
+ new JcrPropertyDefinition(
+ context,
+ null,
+ TestLexicon.CONSTRAINED_DATE,
+ OnParentVersionBehavior.IGNORE.getJcrValue(),
+ false, false, false, NO_DEFAULT_VALUES,
+ PropertyType.DATE,
+ EXPECTED_DATE_CONSTRAINTS, false),
+ new JcrPropertyDefinition(
+ context,
+ null,
+ TestLexicon.CONSTRAINED_DOUBLE,
+ OnParentVersionBehavior.IGNORE.getJcrValue(),
+ false, false, false, NO_DEFAULT_VALUES,
+ PropertyType.DOUBLE,
+ EXPECTED_DOUBLE_CONSTRAINTS, false),
+
+ new JcrPropertyDefinition(
+ context,
+ null,
+ TestLexicon.CONSTRAINED_LONG,
+ OnParentVersionBehavior.IGNORE.getJcrValue(),
+ false, false, false, NO_DEFAULT_VALUES,
+ PropertyType.LONG,
+ EXPECTED_LONG_CONSTRAINTS, false),
+
+ new JcrPropertyDefinition(
+ context,
+ null,
+ TestLexicon.CONSTRAINED_NAME,
+ OnParentVersionBehavior.IGNORE.getJcrValue(),
+ false, false, false, NO_DEFAULT_VALUES,
+ PropertyType.NAME,
+ EXPECTED_NAME_CONSTRAINTS, false),
+
+ new JcrPropertyDefinition(
+ context,
+ null,
+ TestLexicon.CONSTRAINED_PATH,
+ OnParentVersionBehavior.IGNORE.getJcrValue(),
+ false, false, false, NO_DEFAULT_VALUES,
+ PropertyType.PATH,
+ EXPECTED_PATH_CONSTRAINTS, false),
+ new JcrPropertyDefinition(
+ context,
+ null,
+ TestLexicon.CONSTRAINED_REFERENCE,
+ OnParentVersionBehavior.IGNORE.getJcrValue(),
+ false, false, false, NO_DEFAULT_VALUES,
+ PropertyType.REFERENCE,
+ new String[] {"dna:root",}, false),
+
+ new JcrPropertyDefinition(
+ context,
+ null,
+ TestLexicon.CONSTRAINED_STRING,
+ OnParentVersionBehavior.IGNORE.getJcrValue(),
+ false, false, false, NO_DEFAULT_VALUES,
+ PropertyType.STRING,
+ EXPECTED_STRING_CONSTRAINTS, false),
+
+ }), NOT_MIXIN, UNORDERABLE_CHILD_NODES);
+
+ primaryNodeTypes.addAll(Arrays.asList(new JcrNodeType[] {constrainedType}));
+ mixinNodeTypes.addAll(Arrays.asList(new JcrNodeType[] {}));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.jcr.AbstractJcrNodeTypeSource#getDeclaredMixinNodeTypes()
+ */
+ @Override
+ public Collection<JcrNodeType> getDeclaredMixinNodeTypes() {
+ return primaryNodeTypes;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.jcr.AbstractJcrNodeTypeSource#getDeclaredPrimaryNodeTypes()
+ */
+ @Override
+ public Collection<JcrNodeType> getDeclaredPrimaryNodeTypes() {
+ return mixinNodeTypes;
+ }
+
+ }
+
}
Deleted: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/TestNodeTypeSource.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/TestNodeTypeSource.java 2009-03-24 02:29:20 UTC (rev 789)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/TestNodeTypeSource.java 2009-03-24 02:34:43 UTC (rev 790)
@@ -1,142 +0,0 @@
-/*
- * 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 java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
-import javax.jcr.PropertyType;
-import org.jboss.dna.graph.ExecutionContext;
-
-/**
- * Node type source with additional node types that can be used for testing. This class defines its own namespace for its types.
- */
-public class TestNodeTypeSource extends AbstractJcrNodeTypeSource {
-
- /** The list of primary node types. */
- private final List<JcrNodeType> primaryNodeTypes;
- /** The list of mixin node types. */
- private final List<JcrNodeType> mixinNodeTypes;
-
- TestNodeTypeSource( ExecutionContext context,
- JcrNodeTypeSource predecessor ) {
- super(predecessor);
-
- primaryNodeTypes = new ArrayList<JcrNodeType>();
- mixinNodeTypes = new ArrayList<JcrNodeType>();
-
- JcrNodeType base = findType(JcrNtLexicon.BASE);
-
- if (base == null) {
- String baseTypeName = JcrNtLexicon.BASE.getString(context.getNamespaceRegistry());
- String namespaceTypeName = DnaLexicon.NAMESPACE.getString(context.getNamespaceRegistry());
- throw new IllegalStateException(JcrI18n.supertypeNotFound.text(baseTypeName, namespaceTypeName));
- }
-
- // Stubbing in child node and property definitions for now
- JcrNodeType constrainedType = new JcrNodeType(context, NO_NODE_TYPE_MANAGER, TestLexicon.CONSTRAINED_TYPE,
- Arrays.asList(new JcrNodeType[] {base}), NO_PRIMARY_ITEM_NAME,
- NO_CHILD_NODES, Arrays.asList(new JcrPropertyDefinition[] {
- new JcrPropertyDefinition(context, null,
- TestLexicon.CONSTRAINED_BINARY,
- OnParentVersionBehavior.IGNORE.getJcrValue(),
- false, false, false, NO_DEFAULT_VALUES,
- PropertyType.BINARY, new String[] {"[,5)",
- "[10, 20)", "(30,40]", "[50,]"}, false),
- new JcrPropertyDefinition(context, null, TestLexicon.CONSTRAINED_DATE,
- OnParentVersionBehavior.IGNORE.getJcrValue(),
- false, false, false, NO_DEFAULT_VALUES,
- PropertyType.DATE, new String[] {
- "[,+1945-08-01T01:30:00.000Z]",
- "[+1975-08-01T01:30:00.000Z,)"}, false),
- new JcrPropertyDefinition(context, null,
- TestLexicon.CONSTRAINED_DOUBLE,
- OnParentVersionBehavior.IGNORE.getJcrValue(),
- false, false, false, NO_DEFAULT_VALUES,
- PropertyType.DOUBLE,
- new String[] {"[,5.0)", "[10.1, 20.2)",
- "(30.3,40.4]", "[50.5,]"}, false),
-
- new JcrPropertyDefinition(context, null, TestLexicon.CONSTRAINED_LONG,
- OnParentVersionBehavior.IGNORE.getJcrValue(),
- false, false, false, NO_DEFAULT_VALUES,
- PropertyType.LONG, new String[] {"[,5)",
- "[10, 20)", "(30,40]", "[50,]"}, false),
-
- new JcrPropertyDefinition(context, null, TestLexicon.CONSTRAINED_NAME,
- OnParentVersionBehavior.IGNORE.getJcrValue(),
- false, false, false, NO_DEFAULT_VALUES,
- PropertyType.NAME, new String[] {
- "jcr:system", "dnatest:constrainedType"},
- false),
-
- new JcrPropertyDefinition(context, null, TestLexicon.CONSTRAINED_PATH,
- OnParentVersionBehavior.IGNORE.getJcrValue(),
- false, false, false, NO_DEFAULT_VALUES,
- PropertyType.PATH, new String[] {
- // "/" + JcrLexicon.Namespace.URI +
- // ":system/*", "b", "/a/b/c"}, false),
- "/jcr:system/*", "b", "/a/b/c"}, false),
- new JcrPropertyDefinition(context, null,
- TestLexicon.CONSTRAINED_REFERENCE,
- OnParentVersionBehavior.IGNORE.getJcrValue(),
- false, false, false, NO_DEFAULT_VALUES,
- PropertyType.REFERENCE,
- new String[] {"dna:root",}, false),
-
- new JcrPropertyDefinition(context, null,
- TestLexicon.CONSTRAINED_STRING,
- OnParentVersionBehavior.IGNORE.getJcrValue(),
- false, false, false, NO_DEFAULT_VALUES,
- PropertyType.STRING, new String[] {"foo",
- "bar*", ".*baz",}, false),
-
- }), NOT_MIXIN, UNORDERABLE_CHILD_NODES);
-
- primaryNodeTypes.addAll(Arrays.asList(new JcrNodeType[] {constrainedType}));
- mixinNodeTypes.addAll(Arrays.asList(new JcrNodeType[] {}));
- }
-
- /**
- * {@inheritDoc}
- *
- * @see org.jboss.dna.jcr.AbstractJcrNodeTypeSource#getDeclaredMixinNodeTypes()
- */
- @Override
- public Collection<JcrNodeType> getDeclaredMixinNodeTypes() {
- return primaryNodeTypes;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see org.jboss.dna.jcr.AbstractJcrNodeTypeSource#getDeclaredPrimaryNodeTypes()
- */
- @Override
- public Collection<JcrNodeType> getDeclaredPrimaryNodeTypes() {
- return mixinNodeTypes;
- }
-
-}
15 years, 2 months
DNA SVN: r789 - in trunk/dna-jcr/src: main/resources/org/jboss/dna/jcr and 1 other directories.
by dna-commits@lists.jboss.org
Author: rhauch
Date: 2009-03-23 22:29:20 -0400 (Mon, 23 Mar 2009)
New Revision: 789
Added:
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrQueryManager.java
Modified:
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrI18n.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrWorkspace.java
trunk/dna-jcr/src/main/resources/org/jboss/dna/jcr/JcrI18n.properties
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckTest.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrWorkspaceTest.java
Log:
DNA-285 Pass all Level 1 TCK unit tests
Applied the patch that adds an implementation of the simplest query methods for an L1-compliant repository, and that uncommented the related TCK tests that now pass.
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrI18n.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrI18n.java 2009-03-24 02:16:34 UTC (rev 788)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrI18n.java 2009-03-24 02:29:20 UTC (rev 789)
@@ -97,6 +97,10 @@
public static I18n workspaceNameIsInvalid;
public static I18n errorVerifyingWorkspaceName;
+ // Query-related messages
+ public static I18n notStoredQuery;
+ public static I18n invalidQueryLanguage;
+
static {
try {
I18n.initialize(JcrI18n.class);
Added: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrQueryManager.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrQueryManager.java (rev 0)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrQueryManager.java 2009-03-24 02:29:20 UTC (rev 789)
@@ -0,0 +1,208 @@
+/*
+ * 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 java.util.Arrays;
+import javax.jcr.ItemNotFoundException;
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.UnsupportedRepositoryOperationException;
+import javax.jcr.query.InvalidQueryException;
+import javax.jcr.query.Query;
+import javax.jcr.query.QueryManager;
+import javax.jcr.query.QueryResult;
+import net.jcip.annotations.Immutable;
+import org.jboss.dna.graph.property.NamespaceRegistry;
+import org.jboss.dna.graph.property.Path;
+
+/**
+ * Place-holder implementation of {@link QueryManager} interface.
+ */
+@Immutable
+class JcrQueryManager implements QueryManager {
+
+ private final JcrSession session;
+
+ JcrQueryManager( JcrSession session ) {
+ this.session = session;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see javax.jcr.query.QueryManager#createQuery(java.lang.String, java.lang.String)
+ */
+ public Query createQuery( String statement,
+ String language ) throws InvalidQueryException {
+ return this.createQuery(statement, language, null);
+ }
+
+ /**
+ * Creates a new query by specifying the query statement itself, the language in which the query is stated, and, optionally,
+ * the node from which the query was loaded. If the query statement is syntactically invalid, given the language specified, an
+ * {@code InvalidQueryException} is thrown. The language must be a string from among those returned by {@code
+ * QueryManager#getSupportedQueryLanguages()}; if it is not, then an {@code InvalidQueryException} is thrown.
+ *
+ * @param statement
+ * @param language
+ * @param storedNode
+ * @return A {@code Query} object
+ * @throws InvalidQueryException if statement is invalid or language is unsupported.
+ * @see javax.jcr.query.QueryManager#createQuery(java.lang.String, java.lang.String)
+ */
+ private Query createQuery( String statement,
+ String language,
+ AbstractJcrNode storedNode ) throws InvalidQueryException {
+ if (Query.XPATH.equals(language)) {
+ return new XPathQuery(this.session, statement, storedNode);
+ }
+ throw new InvalidQueryException(JcrI18n.invalidQueryLanguage.text(language, Arrays.asList(getSupportedQueryLanguages())));
+
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see javax.jcr.query.QueryManager#getQuery(javax.jcr.Node)
+ */
+ public Query getQuery( Node node ) throws InvalidQueryException, RepositoryException {
+ assert node instanceof AbstractJcrNode;
+
+ JcrNodeType nodeType = (JcrNodeType)node.getPrimaryNodeType();
+ if (!nodeType.getInternalName().equals(JcrNtLexicon.QUERY)) {
+ throw new InvalidQueryException(JcrI18n.notStoredQuery.text());
+ }
+
+ // These are both mandatory properties for nodes of nt:query
+ NamespaceRegistry registry = session.getExecutionContext().getNamespaceRegistry();
+ String statement = node.getProperty(JcrLexicon.STATEMENT.getString(registry)).getString();
+ String language = node.getProperty(JcrLexicon.LANGUAGE.getString(registry)).getString();
+
+ return createQuery(statement, language, (AbstractJcrNode)node);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see javax.jcr.query.QueryManager#getSupportedQueryLanguages()
+ */
+ public String[] getSupportedQueryLanguages() {
+ return new String[] {Query.XPATH};
+ }
+
+ @Immutable
+ protected abstract class AbstractJcrQuery implements Query {
+ private final JcrSession session;
+ private final String language;
+ private final String statement;
+ private final Path storedPath;
+
+ protected AbstractJcrQuery( JcrSession session,
+ String statement,
+ String language,
+ AbstractJcrNode storedNode ) {
+ assert session != null;
+ assert statement != null;
+ assert language != null;
+
+ this.session = session;
+ this.language = language;
+ this.statement = statement;
+
+ try {
+ this.storedPath = storedNode != null ? storedNode.path() : null;
+ } catch (RepositoryException re) {
+ throw new IllegalStateException(re);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see javax.jcr.query.Query#execute()
+ */
+ public abstract QueryResult execute();
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see javax.jcr.query.Query#getLanguage()
+ */
+ public String getLanguage() {
+ return language;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see javax.jcr.query.Query#getStatement()
+ */
+ public String getStatement() {
+ return statement;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see javax.jcr.query.Query#getStoredQueryPath()
+ */
+ public String getStoredQueryPath() throws ItemNotFoundException {
+ if (storedPath == null) {
+ throw new ItemNotFoundException(JcrI18n.notStoredQuery.text());
+ }
+ return storedPath.getString(session.getExecutionContext().getNamespaceRegistry());
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see javax.jcr.query.Query#storeAsNode(java.lang.String)
+ */
+ public Node storeAsNode( java.lang.String absPath ) throws UnsupportedRepositoryOperationException {
+ throw new UnsupportedRepositoryOperationException();
+ }
+
+ }
+
+ @Immutable
+ protected class XPathQuery extends AbstractJcrQuery {
+
+ XPathQuery( JcrSession session,
+ String statement,
+ AbstractJcrNode storedNode ) {
+ super(session, statement, Query.XPATH, storedNode);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.jcr.JcrQueryManager.AbstractJcrQuery#execute()
+ */
+ @Override
+ public QueryResult execute() {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+}
Property changes on: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrQueryManager.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
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-03-24 02:16:34 UTC (rev 788)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrWorkspace.java 2009-03-24 02:29:20 UTC (rev 789)
@@ -107,6 +107,11 @@
private final JcrNodeTypeManager nodeTypeManager;
/**
+ * Reference to the JCR query manager for this workspace.
+ */
+ private final JcrQueryManager queryManager;
+
+ /**
* The {@link Session} instance that this corresponds with this workspace.
*/
private final JcrSession session;
@@ -149,6 +154,7 @@
// This must be initialized after the session
this.nodeTypeManager = new JcrNodeTypeManager(session.getExecutionContext(), repository.getRepositoryTypeManager());
+ this.queryManager = new JcrQueryManager(this.session);
}
final String getSourceName() {
@@ -212,7 +218,7 @@
* {@inheritDoc}
*/
public final QueryManager getQueryManager() {
- throw new UnsupportedOperationException();
+ return queryManager;
}
/**
Modified: trunk/dna-jcr/src/main/resources/org/jboss/dna/jcr/JcrI18n.properties
===================================================================
--- trunk/dna-jcr/src/main/resources/org/jboss/dna/jcr/JcrI18n.properties 2009-03-24 02:16:34 UTC (rev 788)
+++ trunk/dna-jcr/src/main/resources/org/jboss/dna/jcr/JcrI18n.properties 2009-03-24 02:29:20 UTC (rev 789)
@@ -83,3 +83,6 @@
noNegativeDepth=Depth parameter ({0}) cannot be negative
tooDeep=Depth parameter ({0}) cannot be greater than the result of getDepth() for this node
+
+notStoredQuery=This query has not been stored or loaded
+invalidQueryLanguage="{0}" is not a valid query langauge. Supported languages are: {1}
\ No newline at end of file
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckTest.java 2009-03-24 02:16:34 UTC (rev 788)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckTest.java 2009-03-24 02:29:20 UTC (rev 789)
@@ -107,7 +107,7 @@
addTestSuite(org.apache.jackrabbit.test.api.PropertyReadMethodsTest.class);
addTestSuite(org.apache.jackrabbit.test.api.RepositoryDescriptorTest.class);
addTestSuite(org.apache.jackrabbit.test.api.SessionReadMethodsTest.class);
- // addTestSuite(org.apache.jackrabbit.test.api.WorkspaceReadMethodsTest.class);
+ addTestSuite(org.apache.jackrabbit.test.api.WorkspaceReadMethodsTest.class);
addTestSuite(org.apache.jackrabbit.test.api.ReferenceableRootNodesTest.class);
addTestSuite(org.apache.jackrabbit.test.api.ExportSysViewTest.class);
addTestSuite(org.apache.jackrabbit.test.api.ExportDocViewTest.class);
@@ -118,13 +118,13 @@
// addTestSuite(org.apache.jackrabbit.test.api.query.XPathDocOrderTest.class);
// addTestSuite(org.apache.jackrabbit.test.api.query.XPathOrderByTest.class);
// addTestSuite(org.apache.jackrabbit.test.api.query.XPathJcrPathTest.class);
- // addTestSuite(org.apache.jackrabbit.test.api.query.DerefQueryLevel1Test.class);
- // addTestSuite(org.apache.jackrabbit.test.api.query.GetLanguageTest.class);
- // addTestSuite(org.apache.jackrabbit.test.api.query.GetPersistentQueryPathLevel1Test.class);
- // addTestSuite(org.apache.jackrabbit.test.api.query.GetStatementTest.class);
- // addTestSuite(org.apache.jackrabbit.test.api.query.GetSupportedQueryLanguagesTest.class);
+ addTestSuite(org.apache.jackrabbit.test.api.query.DerefQueryLevel1Test.class);
+ addTestSuite(org.apache.jackrabbit.test.api.query.GetLanguageTest.class);
+ addTestSuite(org.apache.jackrabbit.test.api.query.GetPersistentQueryPathLevel1Test.class);
+ addTestSuite(org.apache.jackrabbit.test.api.query.GetStatementTest.class);
+ addTestSuite(org.apache.jackrabbit.test.api.query.GetSupportedQueryLanguagesTest.class);
// addTestSuite(org.apache.jackrabbit.test.api.query.GetPropertyNamesTest.class);
- // addTestSuite(org.apache.jackrabbit.test.api.query.PredicatesTest.class);
+ addTestSuite(org.apache.jackrabbit.test.api.query.PredicatesTest.class);
// addTestSuite(org.apache.jackrabbit.test.api.query.SimpleSelectionTest.class);
// The tests in this suite are level one
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-03-24 02:16:34 UTC (rev 788)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrWorkspaceTest.java 2009-03-24 02:29:20 UTC (rev 789)
@@ -160,9 +160,9 @@
workspace.getObservationManager();
}
- @Test( expected = UnsupportedOperationException.class )
- public void shouldNotAllowGetQueryManager() throws Exception {
- workspace.getQueryManager();
+ @Test
+ public void shouldProvideQueryManager() throws Exception {
+ assertThat(workspace.getQueryManager(), notNullValue());
}
@Test
15 years, 2 months
DNA SVN: r788 - in trunk/dna-jcr/src: main/java/org/jboss/dna/jcr/cache and 2 other directories.
by dna-commits@lists.jboss.org
Author: rhauch
Date: 2009-03-23 22:16:34 -0400 (Mon, 23 Mar 2009)
New Revision: 788
Added:
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/DefinitionCache.java
Modified:
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrNodeTypeSource.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrProperty.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/DnaBuiltinNodeTypeSource.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrBuiltinNodeTypeSource.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNodeDefinition.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNodeType.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNodeTypeManager.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrPropertyDefinition.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/NodeDefinitionId.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/PropertyDefinitionId.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/RepositoryNodeTypeManager.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/SessionCache.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/cache/ChangedNodeInfo.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/cache/ImmutableNodeInfo.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/cache/NodeInfo.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrMultiValuePropertyTest.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrPropertyDefinitionTest.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrSessionTest.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrSingleValuePropertyTest.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/SessionCacheTest.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/TestNodeTypeSource.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/cache/ChangedNodeInfoTest.java
Log:
DNA-335 DNA's NodeTypeManager implementation does not allow multiple definitions with the same name
A large set of changes to handle multiple property definitions with the same name, and multiple child node definitions with the same name. Also corrects and centralizes the logic of selecting the "best" property definition (given the name, values, etc.) and "best" child node definition (given the names, primary type, number of children with the same name, etc.). The JcrNodeType now maintains a cache of various definitions keyed by their name, since searching by name is by far the most frequently used mechanism to access definitions.
This is slightly changed over the "dna-335-definitionsWithSameName" patch (see attached), including a correction to JcrNodeDefinition.allowsChildWithType(...), and a change to RepositoryNodeTypeManager.findPropertyDefinition(...) to not skip over property definitions that have an undefined property type.
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrNodeTypeSource.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrNodeTypeSource.java 2009-03-23 20:41:31 UTC (rev 787)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrNodeTypeSource.java 2009-03-24 02:16:34 UTC (rev 788)
@@ -28,7 +28,6 @@
import java.util.Collections;
import java.util.List;
import javax.jcr.Value;
-import javax.jcr.nodetype.NodeType;
import org.jboss.dna.common.util.CheckArg;
import org.jboss.dna.graph.property.Name;
@@ -40,7 +39,7 @@
// Convenience constants to help improve readability
protected static final Value[] NO_DEFAULT_VALUES = new Value[0];
protected static final String[] NO_CONSTRAINTS = new String[0];
- protected static final List<NodeType> NO_SUPERTYPES = Collections.<NodeType>emptyList();
+ protected static final List<JcrNodeType> NO_SUPERTYPES = Collections.<JcrNodeType>emptyList();
protected static final List<JcrNodeDefinition> NO_CHILD_NODES = Collections.<JcrNodeDefinition>emptyList();
protected static final List<JcrPropertyDefinition> NO_PROPERTIES = Collections.<JcrPropertyDefinition>emptyList();
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrProperty.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrProperty.java 2009-03-23 20:41:31 UTC (rev 787)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrProperty.java 2009-03-24 02:16:34 UTC (rev 788)
@@ -103,8 +103,7 @@
public final PropertyDefinition getDefinition() throws RepositoryException {
PropertyInfo info = propertyInfo();
PropertyDefinitionId definitionId = info.getDefinitionId();
- boolean multiValued = info.isMultiValued();
- return cache.session().nodeTypeManager().getPropertyDefinition(definitionId, multiValued);
+ return cache.session().nodeTypeManager().getPropertyDefinition(definitionId);
}
/**
Added: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/DefinitionCache.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/DefinitionCache.java (rev 0)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/DefinitionCache.java 2009-03-24 02:16:34 UTC (rev 788)
@@ -0,0 +1,179 @@
+/*
+ * 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.
+ *
+ * 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 java.util.Collection;
+import javax.jcr.nodetype.NodeType;
+import net.jcip.annotations.Immutable;
+import org.jboss.dna.graph.property.Name;
+import com.google.common.collect.LinkedListMultimap;
+import com.google.common.collect.Multimap;
+
+/**
+ * A utility class that maintains a quick-lookup cache of all the child node definitions and property definitions for a series of
+ * node types. This class is used with {@link JcrNodeType} to represent these definitions for defined on the node type as well as
+ * those inherited from supertypes. However, it also can be used as a quick-lookup cache for a node's primary type and mixin
+ * types.
+ */
+@Immutable
+final class DefinitionCache {
+
+ /**
+ * A local cache of all defined and inherited child node definitions, keyed by their name, that allow same-name-sibilings.
+ * This includes residual child node definitions, which are keyed by the {@link JcrNodeType#RESIDUAL_NAME}. The content of
+ * this map is used frequently to find the most appropriate node definition for children, and so it is computed once at
+ * construction time (recall that all definitions, including the supertypes, are immutable).
+ * <p>
+ * Note that a node type may have multiple child node definitions with the same name,
+ * "as long as they are distinguishable by the required primary types attribute." (Section 4.7.15 of the JSR-283 draft
+ * specification). The order of the node definitions stored for each name is such that this node's definitions are stored
+ * first, followed by those of the immediate supertypes, followed by those from those supertypes' supertypes, etc.
+ * </p>
+ */
+ private final Multimap<Name, JcrNodeDefinition> childNodeDefinitionsThatAllowSns = new LinkedListMultimap<Name, JcrNodeDefinition>();
+ /**
+ * A local cache of all defined and inherited child node definitions, keyed by their name, that do <i>not</i> allow
+ * same-name-sibilings. This includes residual child node definitions, which are keyed by the
+ * {@link JcrNodeType#RESIDUAL_NAME}. The content of this map is used requently to find the most appropriate node definition
+ * for children, and so it is computed once at construction time (recall that all definitions, including the supertypes, are
+ * immutable).
+ * <p>
+ * Note that a node type may have multiple child node definitions with the same name,
+ * "as long as they are distinguishable by the required primary types attribute." (Section 4.7.15 of the JSR-283 draft
+ * specification). The order of the node definitions stored for each name is such that this node's definitions are stored
+ * first, followed by those of the immediate supertypes, followed by those from those supertypes' supertypes, etc.
+ * </p>
+ */
+ private final Multimap<Name, JcrNodeDefinition> childNodeDefinitionsThatAllowNoSns = new LinkedListMultimap<Name, JcrNodeDefinition>();
+
+ /**
+ * A local cache of all defined and inherited property definitions, keyed by their name, that allow multiple values. This
+ * includes residual property definitions, which are keyed by the {@link JcrNodeType#RESIDUAL_NAME}. The content of this map
+ * is used frequently to find the most appropriate property definition for properties of nodes that use this node type, and so
+ * it is computed once at construction time (recall that all definitions, including supertypes, are immutable).
+ * <p>
+ * Note that a node type may have multiple property node definitions with the same name, "as long as the definitions are
+ * otherwise distinguishable by either the required type attribute (the value returned by PropertyDefinition.getRequiredType)
+ * or the multiple attribute" (Section 4.7.15 of the JSR-283 draft specification).
+ * </p>
+ */
+ private final Multimap<Name, JcrPropertyDefinition> multiValuedPropertyDefinitions = new LinkedListMultimap<Name, JcrPropertyDefinition>();
+ /**
+ * A local cache of all defined and inherited property definitions, keyed by their name, that allow single values. This
+ * includes residual property definitions, which are keyed by the {@link JcrNodeType#RESIDUAL_NAME}. The content of this map
+ * is used frequently to find the most appropriate property definition for properties of nodes that use this node type, and so
+ * it is computed once at construction time (recall that all definitions, including supertypes, are immutable).
+ * <p>
+ * Note that a node type may have multiple property node definitions with the same name, "as long as the definitions are
+ * otherwise distinguishable by either the required type attribute (the value returned by PropertyDefinition.getRequiredType)
+ * or the multiple attribute" (Section 4.7.15 of the JSR-283 draft specification).
+ * </p>
+ */
+ private final Multimap<Name, JcrPropertyDefinition> singleValuedPropertyDefinitions = new LinkedListMultimap<Name, JcrPropertyDefinition>();
+
+ private final Multimap<Name, JcrNodeDefinition> allChildNodeDefinitions = new LinkedListMultimap<Name, JcrNodeDefinition>();
+ private final Multimap<Name, JcrPropertyDefinition> allPropertyDefinitions = new LinkedListMultimap<Name, JcrPropertyDefinition>();
+
+ DefinitionCache( JcrNodeType nodeType ) {
+ addDefinitionsForTypeAndAllSupertypes(nodeType);
+ }
+
+ DefinitionCache( JcrNodeType primaryType,
+ Iterable<JcrNodeType> mixinTypes ) {
+ addDefinitionsForTypeAndAllSupertypes(primaryType);
+ if (mixinTypes != null) {
+ for (JcrNodeType mixinType : mixinTypes) {
+ addDefinitionsForTypeAndAllSupertypes(mixinType);
+ }
+ }
+ }
+
+ private final void addDefinitionsForTypeAndAllSupertypes( JcrNodeType nodeType ) {
+ // And the definitions from the type and all supertypes ...
+ for (NodeType superSuperType : nodeType.getTypeAndSupertypes()) {
+ addDefinitions((JcrNodeType)superSuperType);
+ }
+ }
+
+ private final void addDefinitions( JcrNodeType nodeType ) {
+ for (JcrNodeDefinition definition : nodeType.childNodeDefinitions()) {
+ Name name = definition.getInternalName();
+ if (definition.allowsSameNameSiblings()) {
+ childNodeDefinitionsThatAllowSns.put(name, definition);
+ } else {
+ childNodeDefinitionsThatAllowNoSns.put(name, definition);
+ }
+ allChildNodeDefinitions.put(name, definition);
+ }
+ for (JcrPropertyDefinition definition : nodeType.propertyDefinitions()) {
+ Name name = definition.getInternalName();
+ if (definition.isMultiple()) {
+ multiValuedPropertyDefinitions.put(name, definition);
+ } else {
+ singleValuedPropertyDefinitions.put(name, definition);
+ }
+ allPropertyDefinitions.put(name, definition);
+ }
+ }
+
+ public Collection<JcrPropertyDefinition> allSingleValuePropertyDefinitions( Name propertyName ) {
+ return this.singleValuedPropertyDefinitions.get(propertyName);
+ }
+
+ public Collection<JcrPropertyDefinition> allMultiValuePropertyDefinitions( Name propertyName ) {
+ return this.multiValuedPropertyDefinitions.get(propertyName);
+ }
+
+ public Collection<JcrPropertyDefinition> allPropertyDefinitions( Name propertyName ) {
+ return this.allPropertyDefinitions.get(propertyName);
+ }
+
+ public Collection<JcrPropertyDefinition> allPropertyDefinitions() {
+ return this.allPropertyDefinitions.values();
+ }
+
+ public Collection<JcrNodeDefinition> allChildNodeDefinitionsWithNoSns( Name childName ) {
+ return this.childNodeDefinitionsThatAllowNoSns.get(childName);
+ }
+
+ public Collection<JcrNodeDefinition> allChildNodeDefinitionsWithSns( Name childName ) {
+ return this.childNodeDefinitionsThatAllowSns.get(childName);
+ }
+
+ public Collection<JcrNodeDefinition> allChildNodeDefinitions( Name childName ) {
+ return this.allChildNodeDefinitions.get(childName);
+ }
+
+ Collection<JcrNodeDefinition> allChildNodeDefinitions( Name childName,
+ boolean requireSns ) {
+ if (requireSns) {
+ return childNodeDefinitionsThatAllowSns.get(childName);
+ }
+ return allChildNodeDefinitions.get(childName);
+ }
+
+ public Collection<JcrNodeDefinition> allChildNodeDefinitions() {
+ return this.allChildNodeDefinitions.values();
+ }
+}
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-03-23 20:41:31 UTC (rev 787)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/DnaBuiltinNodeTypeSource.java 2009-03-24 02:16:34 UTC (rev 788)
@@ -28,7 +28,6 @@
import java.util.Collection;
import java.util.List;
import javax.jcr.PropertyType;
-import javax.jcr.nodetype.NodeType;
import net.jcip.annotations.Immutable;
import org.jboss.dna.graph.ExecutionContext;
import org.jboss.dna.graph.JcrMixLexicon;
@@ -72,7 +71,7 @@
context,
NO_NODE_TYPE_MANAGER,
DnaLexicon.NAMESPACE,
- Arrays.asList(new NodeType[] {base}),
+ Arrays.asList(new JcrNodeType[] {base}),
DnaLexicon.URI,
NO_CHILD_NODES,
Arrays.asList(new JcrPropertyDefinition[] {new JcrPropertyDefinition(
@@ -93,7 +92,7 @@
context,
NO_NODE_TYPE_MANAGER,
DnaLexicon.NAMESPACES,
- Arrays.asList(new NodeType[] {base}),
+ Arrays.asList(new JcrNodeType[] {base}),
NO_PRIMARY_ITEM_NAME,
Arrays.asList(new JcrNodeDefinition[] {new JcrNodeDefinition(
context,
@@ -105,14 +104,14 @@
true,
false,
DnaLexicon.NAMESPACE,
- new NodeType[] {namespace})}),
+ new JcrNodeType[] {namespace})}),
NO_PROPERTIES, NOT_MIXIN, UNORDERABLE_CHILD_NODES);
JcrNodeType system = new JcrNodeType(
context,
NO_NODE_TYPE_MANAGER,
DnaLexicon.SYSTEM,
- Arrays.asList(new NodeType[] {base}),
+ Arrays.asList(new JcrNodeType[] {base}),
NO_PRIMARY_ITEM_NAME,
Arrays.asList(new JcrNodeDefinition[] {new JcrNodeDefinition(
context,
@@ -124,15 +123,15 @@
true,
false,
DnaLexicon.NAMESPACES,
- new NodeType[] {namespaces})}),
+ new JcrNodeType[] {namespaces})}),
NO_PROPERTIES, NOT_MIXIN, UNORDERABLE_CHILD_NODES);
- JcrNodeType root = new JcrNodeType(context, NO_NODE_TYPE_MANAGER, DnaLexicon.ROOT, Arrays.asList(new NodeType[] {base,
+ 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,
- true, false, DnaLexicon.SYSTEM, new NodeType[] {system}),
+ true, false, DnaLexicon.SYSTEM, new JcrNodeType[] {system}),
new JcrNodeDefinition(context, null, ALL_NODES, OnParentVersionBehavior.VERSION.getJcrValue(), false, false, false,
- true, JcrNtLexicon.UNSTRUCTURED, new NodeType[] {base}),
+ true, JcrNtLexicon.UNSTRUCTURED, new JcrNodeType[] {base}),
}), Arrays.asList(new JcrPropertyDefinition[] {
new JcrPropertyDefinition(context, null, ALL_NODES, OnParentVersionBehavior.COPY.getJcrValue(), false, false, false,
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrBuiltinNodeTypeSource.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrBuiltinNodeTypeSource.java 2009-03-23 20:41:31 UTC (rev 787)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrBuiltinNodeTypeSource.java 2009-03-24 02:16:34 UTC (rev 788)
@@ -29,7 +29,6 @@
import java.util.List;
import javax.jcr.PropertyType;
import javax.jcr.Value;
-import javax.jcr.nodetype.NodeType;
import net.jcip.annotations.Immutable;
import org.jboss.dna.graph.ExecutionContext;
import org.jboss.dna.graph.property.Name;
@@ -101,7 +100,7 @@
context,
NO_NODE_TYPE_MANAGER,
JcrNtLexicon.CHILD_NODE_DEFINITION,
- Arrays.asList(new NodeType[] {base}),
+ Arrays.asList(new JcrNodeType[] {base}),
NO_PRIMARY_ITEM_NAME,
NO_CHILD_NODES,
Arrays.asList(new JcrPropertyDefinition[] {
@@ -173,7 +172,7 @@
context,
NO_NODE_TYPE_MANAGER,
JcrNtLexicon.HIERARCHY_NODE,
- Arrays.asList(new NodeType[] {base}),
+ Arrays.asList(new JcrNodeType[] {base}),
NO_PRIMARY_ITEM_NAME,
NO_CHILD_NODES,
Arrays.asList(new JcrPropertyDefinition[] {new JcrPropertyDefinition(
@@ -194,7 +193,7 @@
context,
NO_NODE_TYPE_MANAGER,
JcrNtLexicon.FILE,
- Arrays.asList(new NodeType[] {hierarchyNode}),
+ Arrays.asList(new JcrNodeType[] {hierarchyNode}),
JcrLexicon.CONTENT,
Arrays.asList(new JcrNodeDefinition[] {new JcrNodeDefinition(
context,
@@ -203,14 +202,14 @@
OnParentVersionBehavior.COPY.getJcrValue(),
false, true, false,
false, null,
- new NodeType[] {base})}),
+ new JcrNodeType[] {base})}),
NO_PROPERTIES, NOT_MIXIN, UNORDERABLE_CHILD_NODES);
JcrNodeType folder = new JcrNodeType(
context,
NO_NODE_TYPE_MANAGER,
JcrNtLexicon.FOLDER,
- Arrays.asList(new NodeType[] {hierarchyNode}),
+ Arrays.asList(new JcrNodeType[] {hierarchyNode}),
NO_PRIMARY_ITEM_NAME,
Arrays.asList(new JcrNodeDefinition[] {new JcrNodeDefinition(
context,
@@ -222,14 +221,14 @@
false,
false,
null,
- new NodeType[] {hierarchyNode})}),
+ new JcrNodeType[] {hierarchyNode})}),
NO_PROPERTIES, NOT_MIXIN, UNORDERABLE_CHILD_NODES);
JcrNodeType frozenNode = new JcrNodeType(
context,
NO_NODE_TYPE_MANAGER,
JcrNtLexicon.FROZEN_NODE,
- Arrays.asList(new NodeType[] {base, referenceable}),
+ Arrays.asList(new JcrNodeType[] {base, referenceable}),
NO_PRIMARY_ITEM_NAME,
Arrays.asList(new JcrNodeDefinition[] {new JcrNodeDefinition(
context,
@@ -241,7 +240,7 @@
true,
true,
null,
- new NodeType[] {base})}),
+ new JcrNodeType[] {base})}),
Arrays.asList(new JcrPropertyDefinition[] {
new JcrPropertyDefinition(context, null, JcrLexicon.FROZEN_MIXIN_TYPES,
OnParentVersionBehavior.ABORT.getJcrValue(),
@@ -269,7 +268,7 @@
context,
NO_NODE_TYPE_MANAGER,
JcrNtLexicon.LINKED_FILE,
- Arrays.asList(new NodeType[] {hierarchyNode}),
+ Arrays.asList(new JcrNodeType[] {hierarchyNode}),
JcrLexicon.CONTENT,
NO_CHILD_NODES,
Arrays.asList(new JcrPropertyDefinition[] {new JcrPropertyDefinition(
@@ -291,7 +290,7 @@
context,
NO_NODE_TYPE_MANAGER,
JcrNtLexicon.PROPERTY_DEFINITION,
- Arrays.asList(new NodeType[] {base}),
+ Arrays.asList(new JcrNodeType[] {base}),
NO_PRIMARY_ITEM_NAME,
NO_CHILD_NODES,
Arrays.asList(new JcrPropertyDefinition[] {
@@ -366,16 +365,16 @@
NOT_MIXIN, UNORDERABLE_CHILD_NODES);
JcrNodeType nodeType = new JcrNodeType(context, NO_NODE_TYPE_MANAGER, JcrNtLexicon.NODE_TYPE,
- Arrays.asList(new NodeType[] {base}), NO_PRIMARY_ITEM_NAME,
+ Arrays.asList(new JcrNodeType[] {base}), NO_PRIMARY_ITEM_NAME,
Arrays.asList(new JcrNodeDefinition[] {
new JcrNodeDefinition(context, null, JcrLexicon.CHILD_NODE_DEFINITION,
OnParentVersionBehavior.VERSION.getJcrValue(), false,
false, false, true, JcrNtLexicon.CHILD_NODE_DEFINITION,
- new NodeType[] {childNodeDefinition}),
+ new JcrNodeType[] {childNodeDefinition}),
new JcrNodeDefinition(context, null, JcrLexicon.PROPERTY_DEFINITION,
OnParentVersionBehavior.VERSION.getJcrValue(), false,
false, false, true, JcrNtLexicon.PROPERTY_DEFINITION,
- new NodeType[] {propertyDefinition})}),
+ new JcrNodeType[] {propertyDefinition})}),
Arrays.asList(new JcrPropertyDefinition[] {
new JcrPropertyDefinition(context, null, JcrLexicon.HAS_ORDERABLE_CHILD_NODES,
OnParentVersionBehavior.COPY.getJcrValue(), false,
@@ -400,7 +399,7 @@
UNORDERABLE_CHILD_NODES);
JcrNodeType query = new JcrNodeType(context, NO_NODE_TYPE_MANAGER, JcrNtLexicon.QUERY,
- Arrays.asList(new NodeType[] {base}), NO_PRIMARY_ITEM_NAME, NO_CHILD_NODES,
+ Arrays.asList(new JcrNodeType[] {base}), NO_PRIMARY_ITEM_NAME, NO_CHILD_NODES,
Arrays.asList(new JcrPropertyDefinition[] {
new JcrPropertyDefinition(context, null, JcrLexicon.LANGUAGE,
OnParentVersionBehavior.COPY.getJcrValue(), false,
@@ -413,7 +412,7 @@
UNORDERABLE_CHILD_NODES);
JcrNodeType resource = new JcrNodeType(context, NO_NODE_TYPE_MANAGER, JcrNtLexicon.RESOURCE,
- Arrays.asList(new NodeType[] {base, referenceable}), JcrLexicon.DATA,
+ Arrays.asList(new JcrNodeType[] {base, referenceable}), JcrLexicon.DATA,
NO_CHILD_NODES, Arrays.asList(new JcrPropertyDefinition[] {
new JcrPropertyDefinition(context, null, JcrLexicon.DATA,
OnParentVersionBehavior.COPY.getJcrValue(), false,
@@ -437,7 +436,7 @@
context,
NO_NODE_TYPE_MANAGER,
JcrNtLexicon.UNSTRUCTURED,
- Arrays.asList(new NodeType[] {base}),
+ Arrays.asList(new JcrNodeType[] {base}),
NO_PRIMARY_ITEM_NAME,
Arrays.asList(new JcrNodeDefinition[] {new JcrNodeDefinition(
context,
@@ -449,7 +448,7 @@
false,
true,
JcrNtLexicon.UNSTRUCTURED,
- new NodeType[] {base}),}),
+ new JcrNodeType[] {base}),}),
Arrays.asList(new JcrPropertyDefinition[] {
new JcrPropertyDefinition(context, null, ALL_NODES,
OnParentVersionBehavior.COPY.getJcrValue(),
@@ -465,7 +464,7 @@
context,
NO_NODE_TYPE_MANAGER,
JcrNtLexicon.VERSION,
- Arrays.asList(new NodeType[] {base, referenceable}),
+ Arrays.asList(new JcrNodeType[] {base, referenceable}),
NO_PRIMARY_ITEM_NAME,
Arrays.asList(new JcrNodeDefinition[] {new JcrNodeDefinition(
context,
@@ -477,7 +476,7 @@
true,
false,
null,
- new NodeType[] {frozenNode}),}),
+ new JcrNodeType[] {frozenNode}),}),
Arrays.asList(new JcrPropertyDefinition[] {
new JcrPropertyDefinition(context, null, JcrLexicon.CREATED,
OnParentVersionBehavior.ABORT.getJcrValue(), true,
@@ -497,7 +496,7 @@
context,
NO_NODE_TYPE_MANAGER,
JcrNtLexicon.VERSION_LABELS,
- Arrays.asList(new NodeType[] {base}),
+ Arrays.asList(new JcrNodeType[] {base}),
NO_PRIMARY_ITEM_NAME,
NO_CHILD_NODES,
Arrays.asList(new JcrPropertyDefinition[] {new JcrPropertyDefinition(
@@ -518,21 +517,21 @@
context,
NO_NODE_TYPE_MANAGER,
JcrNtLexicon.VERSION_HISTORY,
- Arrays.asList(new NodeType[] {base, referenceable}),
+ Arrays.asList(new JcrNodeType[] {base, referenceable}),
NO_PRIMARY_ITEM_NAME,
Arrays.asList(new JcrNodeDefinition[] {
new JcrNodeDefinition(context, null, JcrLexicon.ROOT_VERSION,
OnParentVersionBehavior.ABORT.getJcrValue(), true,
true, true, false, JcrNtLexicon.VERSION,
- new NodeType[] {version}),
+ new JcrNodeType[] {version}),
new JcrNodeDefinition(context, null, JcrLexicon.VERSION_LABELS,
OnParentVersionBehavior.ABORT.getJcrValue(), true,
true, true, false, JcrNtLexicon.VERSION_LABELS,
- new NodeType[] {versionLabels}),
+ new JcrNodeType[] {versionLabels}),
new JcrNodeDefinition(context, null, ALL_NODES,
OnParentVersionBehavior.ABORT.getJcrValue(),
false, false, true, false, JcrNtLexicon.VERSION,
- new NodeType[] {version}),}),
+ new JcrNodeType[] {version}),}),
Arrays.asList(new JcrPropertyDefinition[] {new JcrPropertyDefinition(
context,
null,
@@ -552,7 +551,7 @@
context,
NO_NODE_TYPE_MANAGER,
JcrNtLexicon.VERSIONED_CHILD,
- Arrays.asList(new NodeType[] {base}),
+ Arrays.asList(new JcrNodeType[] {base}),
NO_PRIMARY_ITEM_NAME,
NO_CHILD_NODES,
Arrays.asList(new JcrPropertyDefinition[] {new JcrPropertyDefinition(
@@ -591,7 +590,7 @@
context,
NO_NODE_TYPE_MANAGER,
JcrMixLexicon.VERSIONABLE,
- Arrays.asList(new NodeType[] {referenceable}),
+ Arrays.asList(new JcrNodeType[] {referenceable}),
NO_PRIMARY_ITEM_NAME,
NO_CHILD_NODES,
Arrays.asList(new JcrPropertyDefinition[] {
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNodeDefinition.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNodeDefinition.java 2009-03-23 20:41:31 UTC (rev 787)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNodeDefinition.java 2009-03-24 02:16:34 UTC (rev 788)
@@ -23,6 +23,10 @@
*/
package org.jboss.dna.jcr;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
import javax.jcr.nodetype.NodeDefinition;
import javax.jcr.nodetype.NodeType;
import net.jcip.annotations.Immutable;
@@ -45,8 +49,12 @@
private final Name defaultPrimaryTypeName;
/** @see NodeDefinition#getRequiredPrimaryTypes() */
- private final NodeType[] requiredPrimaryTypes;
+ private final Map<Name, JcrNodeType> requiredPrimaryTypesByName;
+ private JcrNodeType[] requiredPrimaryTypes;
+
+ private Name[] requiredPrimaryTypeNames;
+
/** A durable identifier for this node definition. */
private NodeDefinitionId id;
@@ -62,12 +70,9 @@
boolean protectedItem,
boolean allowsSameNameSiblings,
Name defaultPrimaryTypeName,
- NodeType[] requiredPrimaryTypes ) {
- super(context, declaringNodeType, name, onParentVersion, autoCreated, mandatory, protectedItem);
- this.nodeTypeManager = null;
- this.allowsSameNameSiblings = allowsSameNameSiblings;
- this.defaultPrimaryTypeName = defaultPrimaryTypeName;
- this.requiredPrimaryTypes = requiredPrimaryTypes;
+ JcrNodeType[] requiredPrimaryTypes ) {
+ this(context, null, declaringNodeType, name, onParentVersion, autoCreated, mandatory, protectedItem,
+ allowsSameNameSiblings, defaultPrimaryTypeName, requiredPrimaryTypes);
}
JcrNodeDefinition( ExecutionContext context,
@@ -80,12 +85,22 @@
boolean protectedItem,
boolean allowsSameNameSiblings,
Name defaultPrimaryTypeName,
- NodeType[] requiredPrimaryTypes ) {
+ JcrNodeType[] requiredPrimaryTypes ) {
super(context, declaringNodeType, name, onParentVersion, autoCreated, mandatory, protectedItem);
this.nodeTypeManager = nodeTypeManager;
this.allowsSameNameSiblings = allowsSameNameSiblings;
this.defaultPrimaryTypeName = defaultPrimaryTypeName;
- this.requiredPrimaryTypes = requiredPrimaryTypes;
+ this.requiredPrimaryTypes = new JcrNodeType[requiredPrimaryTypes.length];
+ this.requiredPrimaryTypeNames = new Name[requiredPrimaryTypes.length];
+ for (int i = 0; i != requiredPrimaryTypes.length; ++i) {
+ this.requiredPrimaryTypes[i] = requiredPrimaryTypes[i];
+ this.requiredPrimaryTypeNames[i] = requiredPrimaryTypes[i].getInternalName();
+ }
+ Map<Name, JcrNodeType> requiredPrimaryTypesByName = new HashMap<Name, JcrNodeType>();
+ for (JcrNodeType requiredPrimaryType : requiredPrimaryTypes) {
+ requiredPrimaryTypesByName.put(requiredPrimaryType.getInternalName(), requiredPrimaryType);
+ }
+ this.requiredPrimaryTypesByName = Collections.unmodifiableMap(requiredPrimaryTypesByName);
}
/**
@@ -95,7 +110,8 @@
*/
public NodeDefinitionId getId() {
if (id == null) {
- id = new NodeDefinitionId(declaringNodeType.getInternalName(), name);
+ // This is idempotent, so no need to lock
+ id = new NodeDefinitionId(this.declaringNodeType.getInternalName(), this.name, this.requiredPrimaryTypeNames);
}
return id;
}
@@ -129,10 +145,48 @@
* @see javax.jcr.nodetype.NodeDefinition#getRequiredPrimaryTypes()
*/
public NodeType[] getRequiredPrimaryTypes() {
- return requiredPrimaryTypes;
+ // Make a copy so that the caller can't modify our content ...
+ NodeType[] result = new NodeType[requiredPrimaryTypes.length];
+ for (int i = 0; i != requiredPrimaryTypes.length; ++i) {
+ result[i] = requiredPrimaryTypes[i];
+ }
+ return result;
}
/**
+ * Get the set of names of the primary types.
+ *
+ * @return the required primary type names
+ */
+ Set<Name> getRequiredPrimaryTypeNames() {
+ return requiredPrimaryTypesByName.keySet();
+ }
+
+ /**
+ * Determine if this node definition will allow a child with the supplied primary type. This method checks this definition's
+ * {@link #getRequiredPrimaryTypes()} against the supplied primary type and its supertypes. The supplied primary type for the
+ * child must be or extend all of the types defined by the {@link #getRequiredPrimaryTypes() required primary types}.
+ *
+ * @param childPrimaryType the primary type of the child
+ * @return true if the primary type of the child (or one of its supertypes) is one of the types required by this definition,
+ * or false otherwise
+ */
+ final boolean allowsChildWithType( JcrNodeType childPrimaryType ) {
+ if (childPrimaryType == null) {
+ // The definition must have a default primary type ...
+ if (defaultPrimaryTypeName != null) {
+ return true;
+ }
+ return false;
+ }
+ // The supplied primary type must be or extend all of the required primary types ...
+ for (Name requiredPrimaryTypeName : requiredPrimaryTypesByName.keySet()) {
+ if (!childPrimaryType.isNodeType(requiredPrimaryTypeName)) return false;
+ }
+ return true;
+ }
+
+ /**
* Creates a new <code>JcrNodeDefinition</code> that is identical to the current object, but with the given
* <code>declaringNodeType</code>. Provided to support immutable pattern for this class.
*
@@ -141,15 +195,27 @@
* <code>declaringNodeType</code>.
*/
JcrNodeDefinition with( JcrNodeType declaringNodeType ) {
+ JcrNodeType[] required = requiredPrimaryTypesByName.values().toArray(new JcrNodeType[requiredPrimaryTypesByName.size()]);
return new JcrNodeDefinition(this.context, declaringNodeType.nodeTypeManager(), declaringNodeType, name,
getOnParentVersion(), isAutoCreated(), isMandatory(), isProtected(),
- allowsSameNameSiblings(), defaultPrimaryTypeName, requiredPrimaryTypes);
+ allowsSameNameSiblings(), defaultPrimaryTypeName, required);
}
JcrNodeDefinition with( ExecutionContext context ) {
+ JcrNodeType[] required = requiredPrimaryTypesByName.values().toArray(new JcrNodeType[requiredPrimaryTypesByName.size()]);
return new JcrNodeDefinition(context, this.nodeTypeManager, this.declaringNodeType, name, getOnParentVersion(),
isAutoCreated(), isMandatory(), isProtected(), allowsSameNameSiblings(),
- defaultPrimaryTypeName, requiredPrimaryTypes);
+ defaultPrimaryTypeName, required);
}
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ return getId().toString();
+ }
+
}
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNodeType.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNodeType.java 2009-03-23 20:41:31 UTC (rev 787)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNodeType.java 2009-03-24 02:16:34 UTC (rev 788)
@@ -23,12 +23,13 @@
*/
package org.jboss.dna.jcr;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
+import java.util.LinkedList;
import java.util.List;
import java.util.Set;
-import java.util.Stack;
import javax.jcr.PropertyType;
import javax.jcr.Value;
import javax.jcr.nodetype.NodeDefinition;
@@ -38,6 +39,7 @@
import org.jboss.dna.common.util.CheckArg;
import org.jboss.dna.graph.ExecutionContext;
import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.basic.BasicName;
/**
* DNA implementation of JCR {@link NodeType}s.
@@ -46,25 +48,52 @@
class JcrNodeType implements NodeType {
public static final String RESIDUAL_ITEM_NAME = "*";
+ public static final Name RESIDUAL_NAME = new BasicName("", RESIDUAL_ITEM_NAME);
/** The name of the node type (e.g., <code>{http://www.jcp.org/jcr/nt/1.0}base</code>) */
private final Name name;
/** The name of the node's primary item */
private final Name primaryItemName;
- /** The set of child node definitions for nodes of this type (possibly empty). */
- private final Set<JcrNodeDefinition> childNodeDefinitions;
- /** The set of property definitions for nodes of this type (possibly empty). */
- private final Set<JcrPropertyDefinition> propertyDefinitions;
/** The supertypes for this node. */
- private final List<NodeType> declaredSupertypes;
+ private final List<JcrNodeType> declaredSupertypes;
+ /**
+ * The list of all supertypes for this node, beginning with the immediate supertypes, followed by the supertypes of those
+ * supertypes, etc.
+ */
+ private final List<JcrNodeType> allSupertypes;
+
+ /**
+ * The list of this type and all supertypes for this node, beginning with this type, continuing with the immediate supertypes,
+ * followed by the supertypes of those supertypes, etc.
+ */
+ private final List<JcrNodeType> thisAndAllSupertypes;
+ private final Set<Name> thisAndAllSupertypesNames;
+
/** Indicates whether this node type is a mixin type (as opposed to a primary type). */
private boolean mixin;
/** Indicates whether the child nodes of nodes of this type can be ordered. */
private boolean orderableChildNodes;
/**
+ * The child node definitions that are defined on this node type.
+ */
+ private final List<JcrNodeDefinition> childNodeDefinitions;
+
+ /**
+ * The property definitions that are defined on this node type.
+ */
+ private final List<JcrPropertyDefinition> propertyDefinitions;
+
+ /**
+ * A local cache of all defined and inherited child node definitions and property definitions. Residual definitions are
+ * included. This class's methods to find a property definition and find child node definitions, and since they're frequently
+ * used by SessionCache this cache provides very quick access.
+ */
+ private final DefinitionCache allDefinitions;
+
+ /**
* A reference to the execution context in which this node type exists, used to remap the internal names to their appropriate
* prefixed version (e.g., <code>{http://www.jcp.org/jcr/nt/1.0}base</code> to <code>"nt:base"</code>.).
*/
@@ -76,7 +105,7 @@
JcrNodeType( ExecutionContext context,
RepositoryNodeTypeManager nodeTypeManager,
Name name,
- List<NodeType> declaredSupertypes,
+ List<JcrNodeType> declaredSupertypes,
Name primaryItemName,
Collection<JcrNodeDefinition> childNodeDefinitions,
Collection<JcrPropertyDefinition> propertyDefinitions,
@@ -86,214 +115,97 @@
this.nodeTypeManager = nodeTypeManager;
this.name = name;
this.primaryItemName = primaryItemName;
- this.declaredSupertypes = declaredSupertypes != null ? declaredSupertypes : Collections.<NodeType>emptyList();
+ this.declaredSupertypes = declaredSupertypes != null ? declaredSupertypes : Collections.<JcrNodeType>emptyList();
this.mixin = mixin;
this.orderableChildNodes = orderableChildNodes;
- this.propertyDefinitions = new HashSet<JcrPropertyDefinition>(propertyDefinitions.size());
+ this.propertyDefinitions = new ArrayList<JcrPropertyDefinition>(propertyDefinitions.size());
for (JcrPropertyDefinition property : propertyDefinitions) {
this.propertyDefinitions.add(property.with(this));
}
- this.childNodeDefinitions = new HashSet<JcrNodeDefinition>(childNodeDefinitions.size());
+ this.childNodeDefinitions = new ArrayList<JcrNodeDefinition>(childNodeDefinitions.size());
for (JcrNodeDefinition childNode : childNodeDefinitions) {
this.childNodeDefinitions.add(childNode.with(this));
}
- }
- /**
- * Returns the property definition with the given name. This method first checks the property definitions declared within this
- * type to see if any property definitions have the given name. If no matches are found, this method initiates a recursive
- * depth first search up the type hierarchy to attempt to find a definition in one of the supertypes (or one the supertypes of
- * the supertypes).
- *
- * @param propertyName the name of the property for which the definition should be retrieved. Use
- * {@link JcrNodeType#RESIDUAL_ITEM_NAME} to retrieve the residual property definition (if any).
- * @param preferMultiValued true if the property definition would prefer multiple values, or false if single-valued definition
- * is preferred
- * @return the property definition for the given name or <code>null</code> if no such definition exists.
- * @see JcrNodeType#RESIDUAL_ITEM_NAME
- */
- JcrPropertyDefinition getPropertyDefinition( String propertyName,
- boolean preferMultiValued ) {
- JcrPropertyDefinition result = null;
- for (JcrPropertyDefinition property : propertyDefinitions) {
- if (propertyName.equals(property.getName())) {
- result = property;
- if (property.isMultiple() == preferMultiValued) return result;
- // Otherwise, keep looking for a better match ...
+ // Build the list of all types, including supertypes ...
+ List<JcrNodeType> thisAndAllSupertypes = new LinkedList<JcrNodeType>();
+ Set<Name> typeNames = new HashSet<Name>();
+ thisAndAllSupertypes.add(this);
+ typeNames.add(this.name);
+ for (int i = 0; i != thisAndAllSupertypes.size(); ++i) {
+ JcrNodeType superType = thisAndAllSupertypes.get(i);
+ for (NodeType superSuperType : superType.getDeclaredSupertypes()) {
+ JcrNodeType jcrSuperSuperType = (JcrNodeType)superSuperType;
+ if (typeNames.add(jcrSuperSuperType.getInternalName())) {
+ thisAndAllSupertypes.add(jcrSuperSuperType);
+ }
}
}
+ this.thisAndAllSupertypes = Collections.unmodifiableList(thisAndAllSupertypes);
+ // Make the list of all supertypes to be a sublist of the first ...
+ this.allSupertypes = thisAndAllSupertypes.size() > 1 ? thisAndAllSupertypes.subList(1, thisAndAllSupertypes.size()) : Collections.<JcrNodeType>emptyList();
- for (NodeType nodeType : declaredSupertypes) {
- JcrPropertyDefinition definition = ((JcrNodeType)nodeType).getPropertyDefinition(propertyName, preferMultiValued);
- if (definition != null) {
- if (definition.isMultiple() == preferMultiValued) return definition;
- if (result == null) result = definition;
- }
- }
- return result; // may be null
+ // Set up the set of all supertype names ...
+ this.thisAndAllSupertypesNames = Collections.unmodifiableSet(typeNames);
+
+ this.allDefinitions = new DefinitionCache(this);
}
- /**
- * Returns the property definition with the given name. This method first checks the property definitions declared within this
- * type to see if any property definitions have the given name. If no matches are found, this method initiates a recursive
- * depth first search up the type hierarchy to attempt to find a definition in one of the supertypes (or one the supertypes of
- * the supertypes).
- *
- * @param propertyName the name of the property for which the definition should be retrieved. Use
- * {@link JcrNodeType#RESIDUAL_ITEM_NAME} to retrieve the residual property definition (if any).
- * @param preferMultiValued true if the property definition would prefer multiple values, or false if single-valued definition
- * is preferred
- * @return the property definition for the given name or <code>null</code> if no such definition exists.
- * @see JcrNodeType#RESIDUAL_ITEM_NAME
- */
- JcrPropertyDefinition getPropertyDefinition( Name propertyName,
- boolean preferMultiValued ) {
- JcrPropertyDefinition result = null;
- for (JcrPropertyDefinition property : propertyDefinitions) {
- if (propertyName.equals(property.getInternalName())) {
- result = property;
- if (property.isMultiple() == preferMultiValued) return result;
- // Otherwise, keep looking for a better match ...
- }
- }
-
- for (NodeType nodeType : declaredSupertypes) {
- JcrPropertyDefinition definition = ((JcrNodeType)nodeType).getPropertyDefinition(propertyName, preferMultiValued);
- if (definition != null) {
- if (definition.isMultiple() == preferMultiValued) return definition;
- if (result == null) result = definition;
- }
- }
- return result; // may be null
+ List<JcrNodeType> getTypeAndSupertypes() {
+ return thisAndAllSupertypes;
}
/**
- * Returns the child node definition with the given name. This method first checks the child node definitions declared within
- * this type to see if any child node definitions have the given name. If no matches are found, this method initiates a
- * recursive depth first search up the type hierarchy to attempt to find a definition in one of the supertypes (or one the
- * supertypes of the supertypes).
+ * Get the child definitions defined on this node type (excluding inherited definitions).
*
- * @param childDefinitionName the name of the child node definition to be retrieved, or a name containing
- * {@link JcrNodeType#RESIDUAL_ITEM_NAME '*'} to retrieve the residual child node definition (if any).
- * @return the child node definition with the given name or <code>null</code> if no such definition exists.
- * @see JcrNodeType#RESIDUAL_ITEM_NAME
- * @see #getChildNodeDefinition(Name)
+ * @return this node's child node definitions; never null
*/
- JcrNodeDefinition getChildNodeDefinition( String childDefinitionName ) {
- for (JcrNodeDefinition childNode : childNodeDefinitions) {
- if (childDefinitionName.equals(childNode.getName())) {
- return childNode;
- }
- }
-
- for (NodeType nodeType : declaredSupertypes) {
- JcrNodeDefinition definition = ((JcrNodeType)nodeType).getChildNodeDefinition(childDefinitionName);
- if (definition != null) return definition;
- }
- return null;
+ List<JcrNodeDefinition> childNodeDefinitions() {
+ return childNodeDefinitions;
}
/**
- * Returns the child node definition with the given name. This method first checks the child node definitions declared within
- * this type to see if any child node definitions have the given name. If no matches are found, this method initiates a
- * recursive depth first search up the type hierarchy to attempt to find a definition in one of the supertypes (or one the
- * supertypes of the supertypes).
+ * Get the property definitions defined on this node type (excluding inherited definitions).
*
- * @param childDefinitionName the name of the child node definition to be retrieved, or a name containing
- * {@link JcrNodeType#RESIDUAL_ITEM_NAME '*'} to retrieve the residual child node definition (if any).
- * @return the child node definition with the given name or <code>null</code> if no such definition exists.
- * @see JcrNodeType#RESIDUAL_ITEM_NAME
- * @see #getChildNodeDefinition(String)
+ * @return this node's property definitions; never null
*/
- JcrNodeDefinition getChildNodeDefinition( Name childDefinitionName ) {
- for (JcrNodeDefinition childNode : childNodeDefinitions) {
- if (childDefinitionName.equals(childNode.name)) {
- return childNode;
- }
- }
+ List<JcrPropertyDefinition> propertyDefinitions() {
+ return propertyDefinitions;
+ }
- for (NodeType nodeType : declaredSupertypes) {
- JcrNodeDefinition definition = ((JcrNodeType)nodeType).getChildNodeDefinition(childDefinitionName);
- if (definition != null) return definition;
- }
- return null;
+ Collection<JcrPropertyDefinition> allSingleValuePropertyDefinitions( Name propertyName ) {
+ return allDefinitions.allSingleValuePropertyDefinitions(propertyName);
}
- /**
- * Determine the best (most specific) {@link NodeDefinition} for a child with the supplied name and primary type. If the
- * primary type is not supplied, then only the name is considered when finding a best match.
- *
- * @param childName the name of the child
- * @param primaryNodeTypeName the name of the primary node type for the child
- * @return the {@link NodeDefinition} that best matches the child, or null if a child with the supplied name and primary type
- * are not allowed given this node type
- */
- JcrNodeDefinition findBestNodeDefinitionForChild( Name childName,
- Name primaryNodeTypeName ) {
- // First, try to find a child node definition with the given name
- JcrNodeDefinition childNode = getChildNodeDefinition(childName);
+ Collection<JcrPropertyDefinition> allMultiValuePropertyDefinitions( Name propertyName ) {
+ return allDefinitions.allMultiValuePropertyDefinitions(propertyName);
+ }
- // If there are no named definitions in the type hierarchy, try to find a residual node definition
- boolean checkResidual = true;
- if (childNode == null) {
- childNode = getChildNodeDefinition(RESIDUAL_ITEM_NAME);
- checkResidual = false;
- }
+ Collection<JcrPropertyDefinition> allPropertyDefinitions( Name propertyName ) {
+ return allDefinitions.allPropertyDefinitions(propertyName);
+ }
- // Check if the node can be added with the named child node definition
- if (childNode != null && primaryNodeTypeName != null) {
- NodeType primaryNodeType = getPrimaryNodeType(primaryNodeTypeName);
- if (primaryNodeType == null) return null;
- if (!checkTypeAgainstDefinition(primaryNodeType, childNode)) {
- if (checkResidual) {
- // Find a residual child definition ...
- childNode = getChildNodeDefinition(RESIDUAL_ITEM_NAME);
- if (childNode != null) {
- // Check the residual child definition ...
- if (checkTypeAgainstDefinition(primaryNodeType, childNode)) return childNode;
- }
- }
- return null;
- }
- }
- return childNode;
+ Collection<JcrNodeDefinition> allChildNodeDefinitions( Name propertyName,
+ boolean requireSns ) {
+ return allDefinitions.allChildNodeDefinitions(propertyName, requireSns);
}
+ Collection<JcrNodeDefinition> allChildNodeDefinitions( Name propertyName ) {
+ return allDefinitions.allChildNodeDefinitions(propertyName);
+ }
+
/**
* {@inheritDoc}
*
* @see javax.jcr.nodetype.NodeType#canAddChildNode(java.lang.String)
*/
public boolean canAddChildNode( String childNodeName ) {
-
CheckArg.isNotNull(childNodeName, "childNodeName");
-
- // First, try to find a child node definition with the given name
- JcrNodeDefinition childNode = getChildNodeDefinition(childNodeName);
-
- // If there are no named definitions in the type hierarchy, try to find a residual node definition
- if (childNode == null) {
- childNode = getChildNodeDefinition(RESIDUAL_ITEM_NAME);
- }
-
- if (childNode != null) {
- NodeType defaultType = childNode.getDefaultPrimaryType();
- // If there's no default type, the child node can't be created
- if (defaultType == null) {
- return false;
- }
-
- // Check if the node can be added with the named child node definition
- return checkTypeAgainstDefinition(defaultType, childNode);
- }
- return false;
+ Name childName = context.getValueFactories().getNameFactory().create(childNodeName);
+ return nodeTypeManager().findChildNodeDefinition(this.name, null, childName, null, 0, true) != null;
}
- protected final NodeType getPrimaryNodeType( Name primaryNodeTypeName ) {
- return nodeTypeManager.getNodeType(primaryNodeTypeName);
- }
-
/**
* {@inheritDoc}
*
@@ -304,81 +216,28 @@
CheckArg.isNotNull(childNodeName, "childNodeName");
CheckArg.isNotNull(primaryNodeTypeName, "primaryNodeTypeName");
-
- Name nodeTypeName = context.getValueFactories().getNameFactory().create(primaryNodeTypeName);
- NodeType primaryNodeType = getPrimaryNodeType(nodeTypeName);
- if (primaryNodeType == null) {
- // The node type doesn't exist, so you can't add a child node with that type
- return false;
- }
-
- // First, try to find a child node definition with the given name
- JcrNodeDefinition childNode = getChildNodeDefinition(childNodeName);
-
- // If there are no named definitions in the type hierarchy, try to find a residual node definition
- if (childNode == null) {
- childNode = getChildNodeDefinition(RESIDUAL_ITEM_NAME);
- }
-
- // Check if the node can be added with the named child node definition
- if (childNode != null) {
- return checkTypeAgainstDefinition(primaryNodeType, childNode);
- }
-
- return false;
+ Name childName = context.getValueFactories().getNameFactory().create(childNodeName);
+ Name childPrimaryTypeName = context.getValueFactories().getNameFactory().create(primaryNodeTypeName);
+ return nodeTypeManager().findChildNodeDefinition(this.name, null, childName, childPrimaryTypeName, 0, true) != null;
}
- /**
- * Checks whether the given type is the same type or a subtype of each of the required primary types for the given node
- * definition.
- *
- * @param typeToCheck the type to check
- * @param definition the node definition to check against
- * @return <code>true</code> if and only if the given type is the same type or extends each of the required primary types in
- * the given definition
- */
- private boolean checkTypeAgainstDefinition( NodeType typeToCheck,
- NodeDefinition definition ) {
- NodeType[] requiredPrimaryTypes = definition.getRequiredPrimaryTypes();
- for (int i = 0; i < requiredPrimaryTypes.length; i++) {
- // See if the given type for the node matches all of the required primary types
- if (!typeToCheck.isNodeType(requiredPrimaryTypes[i].getName())) {
- return false;
- }
- }
- // The node can be added with the given type based on the given child node definition
- return true;
+ public boolean canRemoveNode( String itemName ) {
+ CheckArg.isNotNull(itemName, "itemName");
+ Name childName = context.getValueFactories().getNameFactory().create(itemName);
+ return nodeTypeManager().canRemoveAllChildren(this.name, null, childName, true);
}
/**
* {@inheritDoc}
+ * <p>
+ * According to the JCR 1.0 JavaDoc, this method applies to all children. However, this appears to be changed in the JSR-283
+ * draft to apply only to nodes, and it is also deprecated.
+ * </p>
*
* @see javax.jcr.nodetype.NodeType#canRemoveItem(java.lang.String)
*/
public boolean canRemoveItem( String itemName ) {
- CheckArg.isNotNull(itemName, "itemName");
-
- // Don't know if item is a property or a node, so check both locally before moving up the type hierarchy
- for (PropertyDefinition item : propertyDefinitions) {
- if (itemName.equals(item.getName())) {
- return !item.isMandatory() && !item.isProtected();
- }
- }
-
- for (NodeDefinition item : childNodeDefinitions) {
- if (itemName.equals(item.getName())) {
- return !item.isMandatory() && !item.isProtected();
- }
- }
-
- // Check if any supertypes prevent the removal of this item
- for (NodeType type : declaredSupertypes) {
- if (!type.canRemoveItem(itemName)) {
- return false;
- }
- }
-
- return true;
+ return canRemoveNode(itemName) || canRemoveProperty(itemName);
}
/**
@@ -395,19 +254,38 @@
* @see PropertyDefinition#getValueConstraints()
* @see JcrPropertyDefinition#satisfiesConstraints(Value)
*/
- private boolean canCastToTypeAndMatchesConstraints( JcrPropertyDefinition propertyDefinition,
- Value value ) {
+ boolean canCastToTypeAndMatchesConstraints( JcrPropertyDefinition propertyDefinition,
+ Value value ) {
try {
assert value instanceof JcrValue : "Illegal implementation of Value interface";
- ((JcrValue)value).asType(propertyDefinition.getRequiredType());
-
+ ((JcrValue)value).asType(propertyDefinition.getRequiredType()); // throws ValueFormatException if there's a problem
return propertyDefinition.satisfiesConstraints(value);
-
} catch (javax.jcr.ValueFormatException vfe) {
// Cast failed
return false;
}
+ }
+ /**
+ * Returns <code>true</code> if <code>value</code> can be cast to <code>property.getRequiredType()</code> per the type
+ * conversion rules in section 6.2.6 of the JCR 1.0 specification AND <code>value</code> satisfies the constraints (if any)
+ * for the property definition. If the property definition has a required type of {@link PropertyType#UNDEFINED}, the cast
+ * will be considered to have succeeded and the value constraints (if any) will be interpreted using the semantics for the
+ * type specified in <code>value.getType()</code>.
+ *
+ * @param propertyDefinition the property definition to validate against
+ * @param values the values to be validated
+ * @return <code>true</code> if the value can be cast to the required type for the property definition (if it exists) and
+ * satisfies the constraints for the property (if any exist).
+ * @see PropertyDefinition#getValueConstraints()
+ * @see JcrPropertyDefinition#satisfiesConstraints(Value)
+ */
+ boolean canCastToTypeAndMatchesConstraints( JcrPropertyDefinition propertyDefinition,
+ Value[] values ) {
+ for (Value value : values) {
+ if (!canCastToTypeAndMatchesConstraints(propertyDefinition, value)) return false;
+ }
+ return true;
}
/**
@@ -418,27 +296,10 @@
public boolean canSetProperty( String propertyName,
Value value ) {
CheckArg.isNotNull(propertyName, "propertyName");
+ Name name = context.getValueFactories().getNameFactory().create(propertyName);
- JcrPropertyDefinition property = getPropertyDefinition(propertyName, false);
- if (property == null) {
- property = getPropertyDefinition(RESIDUAL_ITEM_NAME, false);
- }
-
- if (property == null) {
- return false;
- }
-
- // Can't modify a multi-property with a single value. Can't modify a protected property at all.
- if (property.isMultiple() || property.isProtected()) {
- return false;
- }
-
- // Null values indicates an attempt to unset property
- if (value == null) {
- return !property.isMandatory();
- }
-
- return canCastToTypeAndMatchesConstraints(property, value);
+ // Reuse the logic in RepositoryNodeTypeManager ...
+ return nodeTypeManager().findPropertyDefinition(this.name, null, name, value, false, true) != null;
}
/**
@@ -449,34 +310,21 @@
public boolean canSetProperty( String propertyName,
Value[] values ) {
CheckArg.isNotNull(propertyName, "propertyName");
-
- JcrPropertyDefinition property = getPropertyDefinition(propertyName, true);
- if (property == null) {
- property = getPropertyDefinition(RESIDUAL_ITEM_NAME, true);
+ if (values == null || values.length == 0) {
+ return canRemoveProperty(propertyName);
}
- if (property == null) {
- return false;
- }
+ Name name = context.getValueFactories().getNameFactory().create(propertyName);
+ // Reuse the logic in RepositoryNodeTypeManager ...
+ return nodeTypeManager().findPropertyDefinition(this.name, null, name, values, true) != null;
+ }
- // Can't modify a single valued property with a multiple values. Can't modify a protected property at all.
- if (!property.isMultiple() || property.isProtected()) {
- return false;
- }
+ public boolean canRemoveProperty( String propertyName ) {
+ CheckArg.isNotNull(propertyName, "propertyName");
+ Name name = context.getValueFactories().getNameFactory().create(propertyName);
- // Null values indicates an attempt to unset property
- if (values == null) {
- return !property.isMandatory();
- }
-
- for (int i = 0; i < values.length; i++) {
- if (values[i] != null) {
- if (!canCastToTypeAndMatchesConstraints(property, values[i])) {
- return false;
- }
- }
- }
- return true;
+ // Reuse the logic in RepositoryNodeTypeManager ...
+ return nodeTypeManager().canRemoveProperty(this.name, null, name, true);
}
/**
@@ -485,6 +333,7 @@
* @see javax.jcr.nodetype.NodeType#getDeclaredChildNodeDefinitions()
*/
public NodeDefinition[] getDeclaredChildNodeDefinitions() {
+ // Always have to make a copy to prevent changes ...
return childNodeDefinitions.toArray(new JcrNodeDefinition[childNodeDefinitions.size()]);
}
@@ -494,23 +343,9 @@
* @see javax.jcr.nodetype.NodeType#getChildNodeDefinitions()
*/
public NodeDefinition[] getChildNodeDefinitions() {
- Set<NodeDefinition> nodeDefs = new HashSet<NodeDefinition>();
- NodeType[] supertypes = getSupertypes();
-
- // TODO: This could be cached after being calculated once
- for (int i = 0; i < supertypes.length; i++) {
- NodeDefinition[] childNodeDefinitions = supertypes[i].getChildNodeDefinitions();
- for (int j = 0; j < childNodeDefinitions.length; i++) {
-
- // TODO: Could add sanity check here (assertion?) that definitions of the same child node in multiple supertypes
- // are consistent
- nodeDefs.add(childNodeDefinitions[j]);
- }
- }
-
- nodeDefs.addAll(childNodeDefinitions);
-
- return nodeDefs.toArray(new JcrNodeDefinition[nodeDefs.size()]);
+ // Always have to make a copy to prevent changes ...
+ Collection<JcrNodeDefinition> definitions = this.allDefinitions.allChildNodeDefinitions();
+ return definitions.toArray(new NodeDefinition[definitions.size()]);
}
/**
@@ -519,22 +354,9 @@
* @see javax.jcr.nodetype.NodeType#getPropertyDefinitions()
*/
public PropertyDefinition[] getPropertyDefinitions() {
- Set<PropertyDefinition> propDefs = new HashSet<PropertyDefinition>();
- NodeType[] supertypes = getSupertypes();
-
- // TODO: This could be cached after being calculated once
- for (int i = 0; i < supertypes.length; i++) {
- PropertyDefinition[] childPropertyDefinitions = supertypes[i].getPropertyDefinitions();
- for (int j = 0; j < childPropertyDefinitions.length; j++) {
-
- // TODO: Could add sanity check here (assertion?) that definitions of the same child node in multiple supertypes
- // are consistent
- propDefs.add(childPropertyDefinitions[j]);
- }
- }
- propDefs.addAll(propertyDefinitions);
-
- return propDefs.toArray(new JcrPropertyDefinition[propDefs.size()]);
+ // Always have to make a copy to prevent changes ...
+ Collection<JcrPropertyDefinition> definitions = this.allDefinitions.allPropertyDefinitions();
+ return definitions.toArray(new PropertyDefinition[definitions.size()]);
}
/**
@@ -543,6 +365,7 @@
* @see javax.jcr.nodetype.NodeType#getDeclaredSupertypes()
*/
public NodeType[] getDeclaredSupertypes() {
+ // Always have to make a copy to prevent changes ...
return declaredSupertypes.toArray(new NodeType[declaredSupertypes.size()]);
}
@@ -595,31 +418,7 @@
* @see javax.jcr.nodetype.NodeType#getSupertypes()
*/
public NodeType[] getSupertypes() {
- Set<NodeType> supertypes = new HashSet<NodeType>();
- Stack<NodeType> unvisitedSupertypes = new Stack<NodeType>();
-
- assert declaredSupertypes != null;
- unvisitedSupertypes.addAll(declaredSupertypes);
-
- // TODO: If this ends up getting called frequently, it should probably be executed once in the constructor and have the
- // results cached.
- while (!unvisitedSupertypes.isEmpty()) {
- NodeType nodeType = unvisitedSupertypes.pop();
-
- /*
- * If we haven't already visited this nodeType (which we can
- * infer by whether or not it was already added to the return set),
- * then add the supertypes of this new node to the unvisited set for
- * further inspection.
- */
- if (!supertypes.contains(nodeType)) {
- supertypes.add(nodeType);
- // Violating encapsulation to avoid going from List to array back to List
- unvisitedSupertypes.addAll(((JcrNodeType)nodeType).declaredSupertypes);
- }
- }
-
- return supertypes.toArray(new NodeType[0]);
+ return allSupertypes.toArray(new NodeType[allSupertypes.size()]);
}
/**
@@ -646,17 +445,14 @@
* @see javax.jcr.nodetype.NodeType#isNodeType(java.lang.String)
*/
public boolean isNodeType( String nodeTypeName ) {
- if (this.getName().equals(nodeTypeName)) return true;
+ if (nodeTypeName == null) return false;
+ Name name = context.getValueFactories().getNameFactory().create(nodeTypeName);
+ return this.thisAndAllSupertypesNames.contains(name);
+ }
- // TODO: This could be optimized
- NodeType[] supertypes = getSupertypes();
- for (int i = 0; i < supertypes.length; i++) {
- if (supertypes[i].isNodeType(nodeTypeName)) {
- return true;
- }
- }
-
- return false;
+ boolean isNodeType( Name nodeTypeName ) {
+ if (nodeTypeName == null) return false;
+ return this.thisAndAllSupertypesNames.contains(nodeTypeName);
}
@Override
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNodeTypeManager.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNodeTypeManager.java 2009-03-23 20:41:31 UTC (rev 787)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNodeTypeManager.java 2009-03-24 02:16:34 UTC (rev 788)
@@ -26,12 +26,15 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
+import javax.jcr.PropertyType;
import javax.jcr.RepositoryException;
+import javax.jcr.Value;
import javax.jcr.nodetype.NoSuchNodeTypeException;
import javax.jcr.nodetype.NodeDefinition;
import javax.jcr.nodetype.NodeType;
import javax.jcr.nodetype.NodeTypeIterator;
import javax.jcr.nodetype.NodeTypeManager;
+import javax.jcr.nodetype.PropertyDefinition;
import net.jcip.annotations.Immutable;
import org.jboss.dna.graph.ExecutionContext;
import org.jboss.dna.graph.property.Name;
@@ -178,24 +181,206 @@
*/
JcrNodeDefinition getNodeDefinition( NodeDefinitionId definitionId ) {
if (definitionId == null) return null;
- Name nodeTypeName = definitionId.getNodeTypeName();
- JcrNodeType nodeType = repositoryTypeManager.getNodeType(nodeTypeName);
- return nodeType.getChildNodeDefinition(definitionId.getChildDefinitionName());
+ return repositoryTypeManager.getChildNodeDefinition(definitionId);
}
/**
* Get the property definition given the supplied identifier.
*
* @param definitionId the identifier of the node definition
- * @param prefersMultiValued true if the property should be a multi-valued, or false if it should be single-valued
- * @return the node definition, or null if there is no such definition (or if the ID was null)
+ * @return the property definition, or null if there is no such definition (or if the ID was null)
*/
- JcrPropertyDefinition getPropertyDefinition( PropertyDefinitionId definitionId,
- boolean prefersMultiValued ) {
+ JcrPropertyDefinition getPropertyDefinition( PropertyDefinitionId definitionId ) {
if (definitionId == null) return null;
- Name nodeTypeName = definitionId.getNodeTypeName();
- JcrNodeType nodeType = repositoryTypeManager.getNodeType(nodeTypeName);
- return nodeType.getPropertyDefinition(definitionId.getPropertyDefinitionName(), prefersMultiValued);
+ return repositoryTypeManager.getPropertyDefinition(definitionId);
}
+ /**
+ * Searches the supplied primary node type and the mixin node types for a property definition that is the best match for the
+ * given property name, property type, and value.
+ * <p>
+ * This method first attempts to find a single-valued property definition with the supplied property name and
+ * {@link Value#getType() value's property type} in the primary type, skipping any property definitions that are protected.
+ * The property definition is returned if it has a matching type (or has an {@link PropertyType#UNDEFINED undefined property
+ * type}) and the value satisfies the {@link PropertyDefinition#getValueConstraints() definition's constraints}. Otherwise,
+ * the process continues with each of the mixin types, in the order they are named.
+ * </p>
+ * <p>
+ * If no matching property definition could be found (and <code>checkMultiValuedDefinitions</code> parameter is
+ * <code>true</code>), the process is repeated except with multi-valued property definitions with the same name, property
+ * type, and compatible constraints, starting with the primary type and continuing with each mixin type.
+ * </p>
+ * <p>
+ * If no matching property definition could be found, and the process repeats by searching the primary type (and then mixin
+ * types) for single-valued property definitions with a compatible type, where the values can be safely cast to the
+ * definition's property type and still satisfy the definition's constraints.
+ * </p>
+ * <p>
+ * If no matching property definition could be found, the previous step is repeated with multi-valued property definitions.
+ * </p>
+ * <p>
+ * If no matching property definition could be found (and the supplied property name is not the residual name), the whole
+ * process repeats for residual property definitions (e.g., those that are defined with a {@link JcrNodeType#RESIDUAL_NAME "*"
+ * name}).
+ * </p>
+ * <p>
+ * Finally, if no satisfactory property definition could be found, this method returns null.
+ * </p>
+ *
+ * @param primaryTypeName the name of the primary type; may not be null
+ * @param mixinTypeNames the names of the mixin types; may be null or empty if there are no mixins to include in the search
+ * @param propertyName the name of the property for which the definition should be retrieved. This method will automatically
+ * look for residual definitions, but you can use {@link JcrNodeType#RESIDUAL_ITEM_NAME} to retrieve only the best
+ * residual property definition (if any).
+ * @param value the value, or null if the property is being removed
+ * @param checkMultiValuedDefinitions true if the type's multi-valued property definitions should be considered, or false if
+ * only single-value property definitions should be considered
+ * @param skipProtected true if this operation is being done from within the public JCR node and property API, or false if
+ * this operation is being done from within internal implementations
+ * @return the best property definition, or <code>null</code> if no property definition allows the property with the supplied
+ * name, type and number of values
+ */
+ final JcrPropertyDefinition findPropertyDefinition( Name primaryTypeName,
+ List<Name> mixinTypeNames,
+ Name propertyName,
+ Value value,
+ boolean checkMultiValuedDefinitions,
+ boolean skipProtected ) {
+ return repositoryTypeManager.findPropertyDefinition(primaryTypeName,
+ mixinTypeNames,
+ propertyName,
+ value,
+ checkMultiValuedDefinitions,
+ skipProtected);
+ }
+
+ /**
+ * Searches the supplied primary node type and the mixin node types for a property definition that is the best match for the
+ * given property name, property type, and value. with the given name and property type that allows the supplied values.
+ * <p>
+ * This method first attempts to find a single-valued property definition with the supplied property name and
+ * {@link Value#getType() value's property type} in the primary type, skipping any property definitions that are protected.
+ * The property definition is returned if it has a matching type (or has an {@link PropertyType#UNDEFINED undefined property
+ * type}) and the value satisfies the {@link PropertyDefinition#getValueConstraints() definition's constraints}. Otherwise,
+ * the process continues with each of the mixin types, in the order they are named.
+ * </p>
+ * <p>
+ * If no matching property definition could be found (and <code>checkMultiValuedDefinitions</code> parameter is
+ * <code>true</code>), the process is repeated except with multi-valued property definitions with the same name, property
+ * type, and compatible constraints, starting with the primary type and continuing with each mixin type.
+ * </p>
+ * <p>
+ * If no matching property definition could be found, and the process repeats by searching the primary type (and then mixin
+ * types) for single-valued property definitions with a compatible type, where the values can be safely cast to the
+ * definition's property type and still satisfy the definition's constraints.
+ * </p>
+ * <p>
+ * If no matching property definition could be found, the previous step is repeated with multi-valued property definitions.
+ * </p>
+ * <p>
+ * If no matching property definition could be found (and the supplied property name is not the residual name), the whole
+ * process repeats for residual property definitions (e.g., those that are defined with a {@link JcrNodeType#RESIDUAL_NAME "*"
+ * name}).
+ * </p>
+ * <p>
+ * Finally, if no satisfactory property definition could be found, this method returns null.
+ * </p>
+ *
+ * @param primaryTypeName the name of the primary type; may not be null
+ * @param mixinTypeNames the names of the mixin types; may be null or empty if there are no mixins to include in the search
+ * @param propertyName the name of the property for which the definition should be retrieved. This method will automatically
+ * look for residual definitions, but you can use {@link JcrNodeType#RESIDUAL_ITEM_NAME} to retrieve only the best
+ * residual property definition (if any).
+ * @param values the values
+ * @param skipProtected true if this operation is being done from within the public JCR node and property API, or false if
+ * this operation is being done from within internal implementations
+ * @return the best property definition, or <code>null</code> if no property definition allows the property with the supplied
+ * name, type and number of values
+ */
+ final JcrPropertyDefinition findPropertyDefinition( Name primaryTypeName,
+ List<Name> mixinTypeNames,
+ Name propertyName,
+ Value[] values,
+ boolean skipProtected ) {
+ return repositoryTypeManager.findPropertyDefinition(primaryTypeName, mixinTypeNames, propertyName, values, skipProtected);
+ }
+
+ /**
+ * Determine if the property definitions of the supplied primary type and mixin types allow the property with the supplied
+ * name to be removed.
+ *
+ * @param primaryTypeNameOfParent the name of the primary type for the parent node; may not be null
+ * @param mixinTypeNamesOfParent the names of the mixin types for the parent node; may be null or empty if there are no mixins
+ * to include in the search
+ * @param propertyName the name of the property to be removed; may not be null
+ * @param skipProtected true if this operation is being done from within the public JCR node and property API, or false if
+ * this operation is being done from within internal implementations
+ * @return true if at least one child node definition does not require children with the supplied name to exist, or false
+ * otherwise
+ */
+ boolean canRemoveProperty( Name primaryTypeNameOfParent,
+ List<Name> mixinTypeNamesOfParent,
+ Name propertyName,
+ boolean skipProtected ) {
+ return repositoryTypeManager.canRemoveProperty(primaryTypeNameOfParent,
+ mixinTypeNamesOfParent,
+ propertyName,
+ skipProtected);
+ }
+
+ /**
+ * Searches the supplied primary node type and the mixin node types of a parent node for a child node definition that is the
+ * best match for a new child with the given name, primary node type name, and whether there are existing children with the
+ * same name.
+ *
+ * @param primaryTypeNameOfParent the name of the primary type for the parent node; may not be null
+ * @param mixinTypeNamesOfParent the names of the mixin types for the parent node; may be null or empty if there are no mixins
+ * to include in the search
+ * @param childName the name of the child to be added to the parent; may not be null
+ * @param childPrimaryNodeType the name of the primary node type for the child node, or null if the primary type is not known
+ * and the {@link NodeDefinition#getDefaultPrimaryType() definition's default primary type} will be used
+ * @param numberOfExistingChildrenWithSameName the number of existing children with the same name as the child to be added, or
+ * 0 if this new child will be the first child with this name (or if the number of children is not known)
+ * @param skipProtected true if this operation is being done from within the public JCR node and property API, or false if
+ * this operation is being done from within internal implementations
+ * @return the best child node definition, or <code>null</code> if no node definition allows a new child with the supplied
+ * name, primary type, and whether there are already children with the same name
+ */
+ final JcrNodeDefinition findChildNodeDefinition( Name primaryTypeNameOfParent,
+ List<Name> mixinTypeNamesOfParent,
+ Name childName,
+ Name childPrimaryNodeType,
+ int numberOfExistingChildrenWithSameName,
+ boolean skipProtected ) {
+ return repositoryTypeManager.findChildNodeDefinition(primaryTypeNameOfParent,
+ mixinTypeNamesOfParent,
+ childName,
+ childPrimaryNodeType,
+ numberOfExistingChildrenWithSameName,
+ skipProtected);
+ }
+
+ /**
+ * Determine if the child node definitions of the supplied primary type and mixin types of a parent node allow all of the
+ * children with the supplied name to be removed.
+ *
+ * @param primaryTypeNameOfParent the name of the primary type for the parent node; may not be null
+ * @param mixinTypeNamesOfParent the names of the mixin types for the parent node; may be null or empty if there are no mixins
+ * to include in the search
+ * @param childName the name of the child to be added to the parent; may not be null
+ * @param skipProtected true if this operation is being done from within the public JCR node and property API, or false if
+ * this operation is being done from within internal implementations
+ * @return true if at least one child node definition does not require children with the supplied name to exist, or false
+ * otherwise
+ */
+ final boolean canRemoveAllChildren( Name primaryTypeNameOfParent,
+ List<Name> mixinTypeNamesOfParent,
+ Name childName,
+ boolean skipProtected ) {
+ return repositoryTypeManager.canRemoveAllChildren(primaryTypeNameOfParent,
+ mixinTypeNamesOfParent,
+ childName,
+ skipProtected);
+ }
+
}
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrPropertyDefinition.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrPropertyDefinition.java 2009-03-23 20:41:31 UTC (rev 787)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrPropertyDefinition.java 2009-03-24 02:16:34 UTC (rev 788)
@@ -82,7 +82,8 @@
*/
public PropertyDefinitionId getId() {
if (id == null) {
- id = new PropertyDefinitionId(declaringNodeType.getInternalName(), name);
+ // This is idempotent, so no need to lock
+ id = new PropertyDefinitionId(this.declaringNodeType.getInternalName(), this.name, this.requiredType, this.multiple);
}
return id;
}
@@ -137,9 +138,18 @@
this.getRequiredType(), this.getValueConstraints(), this.isMultiple());
}
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ return getId().toString();
+ }
+
boolean satisfiesConstraints( Value value ) {
- assert value instanceof JcrValue;
-
+ if (value == null) return false;
if (valueConstraints == null || valueConstraints.length == 0) {
return true;
}
@@ -166,7 +176,91 @@
}
}
+ boolean satisfiesConstraints( Value[] values ) {
+ if (valueConstraints == null || valueConstraints.length == 0) {
+ if (requiredType != PropertyType.UNDEFINED) {
+ for (Value value : values) {
+ if (value.getType() != requiredType) return false;
+ }
+ }
+ return true;
+ }
+ if (values == null || values.length == 0) {
+ // There are no values, so see if the definition allows multiple values ...
+ return isMultiple();
+ }
+
+ // Neither the 1.0 or 2.0 specification formally prohibit constraints on properties with no required type.
+ int type = requiredType == PropertyType.UNDEFINED ? values[0].getType() : requiredType;
+
+ /*
+ * Keep a method-local reference to the constraint checker in case another thread attempts to concurrently
+ * check the constraints with a different required type.
+ */
+ ConstraintChecker checker = this.checker;
+
+ if (checker == null || checker.getType() != type) {
+ checker = createChecker(context, type, valueConstraints);
+ this.checker = checker;
+ }
+
+ try {
+ for (Value value : values) {
+ if (requiredType != PropertyType.UNDEFINED && value.getType() != requiredType) return false;
+ if (!checker.matches(value)) return false;
+ }
+ return true;
+ } catch (ValueFormatException vfe) {
+ // The value was so wonky that we couldn't even convert it to an appropriate type
+ return false;
+ }
+ }
+
/**
+ * Returns <code>true</code> if <code>value</code> can be cast to <code>property.getRequiredType()</code> per the type
+ * conversion rules in section 6.2.6 of the JCR 1.0 specification AND <code>value</code> satisfies the constraints (if any)
+ * for the property definition. If the property definition has a required type of {@link PropertyType#UNDEFINED}, the cast
+ * will be considered to have succeeded and the value constraints (if any) will be interpreted using the semantics for the
+ * type specified in <code>value.getType()</code>.
+ *
+ * @param value the value to be validated
+ * @return <code>true</code> if the value can be cast to the required type for the property definition (if it exists) and
+ * satisfies the constraints for the property (if any exist).
+ * @see PropertyDefinition#getValueConstraints()
+ * @see #satisfiesConstraints(Value)
+ */
+ boolean canCastToTypeAndSatisfyConstraints( Value value ) {
+ try {
+ assert value instanceof JcrValue : "Illegal implementation of Value interface";
+ ((JcrValue)value).asType(getRequiredType()); // throws ValueFormatException if there's a problem
+ return satisfiesConstraints(value);
+ } catch (javax.jcr.ValueFormatException vfe) {
+ // Cast failed
+ return false;
+ }
+ }
+
+ /**
+ * Returns <code>true</code> if <code>value</code> can be cast to <code>property.getRequiredType()</code> per the type
+ * conversion rules in section 6.2.6 of the JCR 1.0 specification AND <code>value</code> satisfies the constraints (if any)
+ * for the property definition. If the property definition has a required type of {@link PropertyType#UNDEFINED}, the cast
+ * will be considered to have succeeded and the value constraints (if any) will be interpreted using the semantics for the
+ * type specified in <code>value.getType()</code>.
+ *
+ * @param values the values to be validated
+ * @return <code>true</code> if the value can be cast to the required type for the property definition (if it exists) and
+ * satisfies the constraints for the property (if any exist).
+ * @see PropertyDefinition#getValueConstraints()
+ * @see #satisfiesConstraints(Value)
+ */
+ boolean canCastToTypeAndSatisfyConstraints( Value[] values ) {
+ for (Value value : values) {
+ if (!canCastToTypeAndSatisfyConstraints(value)) return false;
+ }
+ return true;
+ }
+
+ /**
* Returns a {@link ConstraintChecker} that will interpret the constraints described by <code>valueConstraints</code> using
* the semantics defined in section 6.7.16 of the JCR 1.0 specification for the type indicated by <code>type</code> (where
* <code>type</code> is a value from {@link PropertyType}) for the given <code>context</code>. The {@link ExecutionContext} is
@@ -481,7 +575,12 @@
JcrValue jcrValue = (JcrValue)value;
// Need to use the session execution context to handle the remaps
- Name name = jcrValue.sessionCache().session().getExecutionContext().getValueFactories().getNameFactory().create(jcrValue.value());
+ Name name = jcrValue.sessionCache()
+ .session()
+ .getExecutionContext()
+ .getValueFactories()
+ .getNameFactory()
+ .create(jcrValue.value());
for (int i = 0; i < constraints.length; i++) {
if (constraints[i].equals(name)) {
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/NodeDefinitionId.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/NodeDefinitionId.java 2009-03-23 20:41:31 UTC (rev 787)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/NodeDefinitionId.java 2009-03-24 02:16:34 UTC (rev 788)
@@ -25,7 +25,6 @@
import java.io.Serializable;
import net.jcip.annotations.Immutable;
-import org.jboss.dna.common.util.HashCode;
import org.jboss.dna.graph.property.Name;
import org.jboss.dna.graph.property.NameFactory;
import org.jboss.dna.graph.property.ValueFormatException;
@@ -51,7 +50,8 @@
private final Name nodeTypeName;
private final Name childDefinitionName;
- private final int hc;
+ private final Name[] requiredPrimaryTypes;
+ private final String stringVersion;
/**
* Create an identifier for a node definition.
@@ -59,14 +59,23 @@
* @param nodeTypeName the name of the node type on which this child node definition is defined; may not be null
* @param childDefinitionName the name of the child node definition, which may be a {@link #ANY_NAME residual child
* definition}; may not be null
+ * @param requiredPrimaryTypes the names of the required primary types for the child node definition
*/
public NodeDefinitionId( Name nodeTypeName,
- Name childDefinitionName ) {
+ Name childDefinitionName,
+ Name[] requiredPrimaryTypes ) {
assert nodeTypeName != null;
assert childDefinitionName != null;
this.nodeTypeName = nodeTypeName;
this.childDefinitionName = childDefinitionName;
- this.hc = HashCode.compute(this.nodeTypeName, this.childDefinitionName);
+ this.requiredPrimaryTypes = requiredPrimaryTypes;
+ StringBuilder sb = new StringBuilder(this.nodeTypeName.getString());
+ sb.append('/').append(this.childDefinitionName.getString());
+ for (Name requiredPrimaryType : requiredPrimaryTypes) {
+ sb.append('/');
+ sb.append(requiredPrimaryType.getString());
+ }
+ this.stringVersion = sb.toString();
}
/**
@@ -88,6 +97,15 @@
}
/**
+ * @return requiredPrimaryTypes
+ */
+ public Name[] getRequiredPrimaryTypes() {
+ Name[] copy = new Name[requiredPrimaryTypes.length];
+ System.arraycopy(requiredPrimaryTypes, 0, copy, 0, requiredPrimaryTypes.length);
+ return copy;
+ }
+
+ /**
* Determine whether this node definition defines any named child.
*
* @return true if this node definition allows children with any name, or false if this definition requires a particular child
@@ -103,7 +121,7 @@
* @return the string form
*/
public String getString() {
- return this.nodeTypeName.getString() + '/' + this.childDefinitionName.getString();
+ return this.stringVersion;
}
/**
@@ -116,12 +134,16 @@
*/
public static NodeDefinitionId fromString( String definition,
NameFactory factory ) {
- int index = definition.indexOf('/');
- String nodeTypeNameString = definition.substring(0, index);
- String childDefinitionNameString = definition.substring(index + 1);
+ String[] parts = definition.split("/");
+ String nodeTypeNameString = parts[0];
+ String childDefinitionNameString = parts[1];
+ Name[] requiredPrimaryTypes = new Name[parts.length - 2];
+ for (int i = 2, j = 0; i != parts.length; ++i, ++j) {
+ requiredPrimaryTypes[j] = factory.create(parts[i]);
+ }
Name nodeTypeName = factory.create(nodeTypeNameString);
Name childDefinitionName = factory.create(childDefinitionNameString);
- return new NodeDefinitionId(nodeTypeName, childDefinitionName);
+ return new NodeDefinitionId(nodeTypeName, childDefinitionName, requiredPrimaryTypes);
}
/**
@@ -131,7 +153,7 @@
*/
@Override
public int hashCode() {
- return hc;
+ return stringVersion.hashCode();
}
/**
@@ -144,9 +166,7 @@
if (obj == this) return true;
if (obj instanceof NodeDefinitionId) {
NodeDefinitionId that = (NodeDefinitionId)obj;
- if (this.hc != that.hc) return false;
- if (!this.nodeTypeName.equals(that.nodeTypeName)) return false;
- return this.childDefinitionName.equals(that.childDefinitionName);
+ return this.stringVersion.equals(that.stringVersion);
}
return false;
}
@@ -158,7 +178,7 @@
*/
@Override
public String toString() {
- return this.nodeTypeName.toString() + '/' + this.childDefinitionName.toString();
+ return this.stringVersion;
}
}
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/PropertyDefinitionId.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/PropertyDefinitionId.java 2009-03-23 20:41:31 UTC (rev 787)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/PropertyDefinitionId.java 2009-03-24 02:16:34 UTC (rev 788)
@@ -24,8 +24,8 @@
package org.jboss.dna.jcr;
import java.io.Serializable;
+import javax.jcr.PropertyType;
import net.jcip.annotations.Immutable;
-import org.jboss.dna.common.util.HashCode;
import org.jboss.dna.graph.property.Name;
import org.jboss.dna.graph.property.NameFactory;
import org.jboss.dna.graph.property.ValueFormatException;
@@ -51,7 +51,9 @@
private final Name nodeTypeName;
private final Name propertyDefinitionName;
- private final int hc;
+ private final int propertyType;
+ private final boolean allowsMultiple;
+ private final String stringVersion;
/**
* Create a new identifier for a propety definition.
@@ -59,12 +61,20 @@
* @param nodeTypeName the name of the node type; may not be null
* @param propertyDefinitionName the name of the property definition, which may be a {@link #ANY_NAME residual property}; may
* not be null
+ * @param propertyType the required property type for the definition; must be a valid {@link PropertyType} value
+ * @param allowsMultiple true if the property definition should allow multiple values, or false if it is a single-value
+ * property definition
*/
public PropertyDefinitionId( Name nodeTypeName,
- Name propertyDefinitionName ) {
+ Name propertyDefinitionName,
+ int propertyType,
+ boolean allowsMultiple ) {
this.nodeTypeName = nodeTypeName;
this.propertyDefinitionName = propertyDefinitionName;
- this.hc = HashCode.compute(this.nodeTypeName, this.propertyDefinitionName);
+ this.propertyType = propertyType;
+ this.allowsMultiple = allowsMultiple;
+ this.stringVersion = this.nodeTypeName.getString() + '/' + this.propertyDefinitionName.getString() + '/'
+ + PropertyType.nameFromValue(propertyType) + '/' + (allowsMultiple ? '*' : '1');
}
/**
@@ -86,6 +96,24 @@
}
/**
+ * Get the required property type
+ *
+ * @return the property type; always a valid {@link PropertyType} value
+ */
+ public int getPropertyType() {
+ return propertyType;
+ }
+
+ /**
+ * Return whether the property definition allows multiple values.
+ *
+ * @return true if the property definition allows multiple values, or false if it is a single-value property definition
+ */
+ public boolean allowsMultiple() {
+ return allowsMultiple;
+ }
+
+ /**
* Determine whether this property definition allows properties with any name.
*
* @return true if this node definition allows properties with any name, or false if this definition requires a particular
@@ -101,7 +129,7 @@
* @return the string form
*/
public String getString() {
- return this.nodeTypeName.getString() + '/' + this.propertyDefinitionName.getString();
+ return this.stringVersion;
}
/**
@@ -114,14 +142,24 @@
*/
public static PropertyDefinitionId fromString( String definition,
NameFactory factory ) {
- int index = definition.indexOf('/');
- String nodeTypeNameString = definition.substring(0, index);
- String propertyDefinitionNameString = definition.substring(index + 1);
+ String[] parts = definition.split("/");
+ String nodeTypeNameString = parts[0];
+ String propertyDefinitionNameString = parts[1];
Name nodeTypeName = factory.create(nodeTypeNameString);
Name propertyDefinitionName = factory.create(propertyDefinitionNameString);
- return new PropertyDefinitionId(nodeTypeName, propertyDefinitionName);
+ int propertyType = PropertyType.valueFromName(parts[2]);
+ boolean allowsMultiple = parts[3].charAt(0) == '*';
+ return new PropertyDefinitionId(nodeTypeName, propertyDefinitionName, propertyType, allowsMultiple);
}
+ public PropertyDefinitionId asSingleValued() {
+ return new PropertyDefinitionId(nodeTypeName, propertyDefinitionName, propertyType, false);
+ }
+
+ public PropertyDefinitionId asMultiValued() {
+ return new PropertyDefinitionId(nodeTypeName, propertyDefinitionName, propertyType, true);
+ }
+
/**
* {@inheritDoc}
*
@@ -129,7 +167,7 @@
*/
@Override
public int hashCode() {
- return hc;
+ return this.stringVersion.hashCode();
}
/**
@@ -142,9 +180,7 @@
if (obj == this) return true;
if (obj instanceof PropertyDefinitionId) {
PropertyDefinitionId that = (PropertyDefinitionId)obj;
- if (this.hc != that.hc) return false;
- if (!this.nodeTypeName.equals(that.nodeTypeName)) return false;
- return this.propertyDefinitionName.equals(that.propertyDefinitionName);
+ return this.stringVersion.equals(that.stringVersion);
}
return false;
}
@@ -156,7 +192,7 @@
*/
@Override
public String toString() {
- return this.nodeTypeName.toString() + '/' + this.propertyDefinitionName.toString();
+ return this.stringVersion;
}
}
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-03-23 20:41:31 UTC (rev 787)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/RepositoryNodeTypeManager.java 2009-03-24 02:16:34 UTC (rev 788)
@@ -25,7 +25,13 @@
import java.util.Collection;
import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
import java.util.Map;
+import javax.jcr.PropertyType;
+import javax.jcr.Value;
+import javax.jcr.nodetype.NodeDefinition;
+import javax.jcr.nodetype.PropertyDefinition;
import net.jcip.annotations.Immutable;
import org.jboss.dna.graph.ExecutionContext;
import org.jboss.dna.graph.property.Name;
@@ -34,9 +40,9 @@
* The {@link RepositoryNodeTypeManager} is the maintainer of node type information for the entire repository at run-time. The
* repository manager maintains a list of all node types and the ability to retrieve node types by {@link Name}. </p> The JCR 1.0
* and 2.0 specifications both require that node type information be shared across all sessions within a repository and that the
- * {@link javax.jcr.nodetype.NodeTypeManager} perform operations based on the string versions of {@link Name}s based on the permanent
- * (workspace-scoped) and transient (session-scoped) namespace mappings. DNA achieves this by maintaining a single master
- * repository of all node type information (the {@link RepositoryNodeTypeManager}) and per-session wrappers (
+ * {@link javax.jcr.nodetype.NodeTypeManager} perform operations based on the string versions of {@link Name}s based on the
+ * permanent (workspace-scoped) and transient (session-scoped) namespace mappings. DNA achieves this by maintaining a single
+ * master repository of all node type information (the {@link RepositoryNodeTypeManager}) and per-session wrappers (
* {@link JcrNodeTypeManager}) for this master repository that perform {@link String} to {@link Name} translation based on the
* {@link javax.jcr.Session}'s transient mappings and then delegating node type lookups to the repository manager.
*/
@@ -45,20 +51,36 @@
private final Map<Name, JcrNodeType> primaryNodeTypes;
private final Map<Name, JcrNodeType> mixinNodeTypes;
+ private final Map<PropertyDefinitionId, JcrPropertyDefinition> propertyDefinitions;
+ private final Map<NodeDefinitionId, JcrNodeDefinition> childNodeDefinitions;
RepositoryNodeTypeManager( ExecutionContext context,
JcrNodeTypeSource source ) {
Collection<JcrNodeType> primary = source.getPrimaryNodeTypes();
Collection<JcrNodeType> mixins = source.getMixinNodeTypes();
+ propertyDefinitions = new HashMap<PropertyDefinitionId, JcrPropertyDefinition>();
+ childNodeDefinitions = new HashMap<NodeDefinitionId, JcrNodeDefinition>();
primaryNodeTypes = new HashMap<Name, JcrNodeType>(primary.size());
for (JcrNodeType nodeType : primary) {
primaryNodeTypes.put(nodeType.getInternalName(), nodeType.with(this));
+ for (JcrNodeDefinition childDefinition : nodeType.childNodeDefinitions()) {
+ childNodeDefinitions.put(childDefinition.getId(), childDefinition);
+ }
+ for (JcrPropertyDefinition propertyDefinition : nodeType.propertyDefinitions()) {
+ propertyDefinitions.put(propertyDefinition.getId(), propertyDefinition);
+ }
}
mixinNodeTypes = new HashMap<Name, JcrNodeType>(mixins.size());
for (JcrNodeType nodeType : mixins) {
mixinNodeTypes.put(nodeType.getInternalName(), nodeType.with(this));
+ for (JcrNodeDefinition childDefinition : nodeType.childNodeDefinitions()) {
+ childNodeDefinitions.put(childDefinition.getId(), childDefinition);
+ }
+ for (JcrPropertyDefinition propertyDefinition : nodeType.propertyDefinitions()) {
+ propertyDefinitions.put(propertyDefinition.getId(), propertyDefinition);
+ }
}
}
@@ -70,6 +92,14 @@
return primaryNodeTypes.values();
}
+ public JcrPropertyDefinition getPropertyDefinition( PropertyDefinitionId id ) {
+ return propertyDefinitions.get(id);
+ }
+
+ public JcrNodeDefinition getChildNodeDefinition( NodeDefinitionId id ) {
+ return childNodeDefinitions.get(id);
+ }
+
JcrNodeType getNodeType( Name nodeTypeName ) {
JcrNodeType nodeType = primaryNodeTypes.get(nodeTypeName);
@@ -78,4 +108,491 @@
}
return nodeType;
}
+
+ /**
+ * Searches the supplied primary node type and the mixin node types for a property definition that is the best match for the
+ * given property name, property type, and value.
+ * <p>
+ * This method first attempts to find a single-valued property definition with the supplied property name and
+ * {@link Value#getType() value's property type} in the primary type, skipping any property definitions that are protected.
+ * The property definition is returned if it has a matching type (or has an {@link PropertyType#UNDEFINED undefined property
+ * type}) and the value satisfies the {@link PropertyDefinition#getValueConstraints() definition's constraints}. Otherwise,
+ * the process continues with each of the mixin types, in the order they are named.
+ * </p>
+ * <p>
+ * If no matching property definition could be found (and <code>checkMultiValuedDefinitions</code> parameter is
+ * <code>true</code>), the process is repeated except with multi-valued property definitions with the same name, property
+ * type, and compatible constraints, starting with the primary type and continuing with each mixin type.
+ * </p>
+ * <p>
+ * If no matching property definition could be found, and the process repeats by searching the primary type (and then mixin
+ * types) for single-valued property definitions with a compatible type, where the values can be safely cast to the
+ * definition's property type and still satisfy the definition's constraints.
+ * </p>
+ * <p>
+ * If no matching property definition could be found, the previous step is repeated with multi-valued property definitions.
+ * </p>
+ * <p>
+ * If no matching property definition could be found (and the supplied property name is not the residual name), the whole
+ * process repeats for residual property definitions (e.g., those that are defined with a {@link JcrNodeType#RESIDUAL_NAME "*"
+ * name}).
+ * </p>
+ * <p>
+ * Finally, if no satisfactory property definition could be found, this method returns null.
+ * </p>
+ *
+ * @param primaryTypeName the name of the primary type; may not be null
+ * @param mixinTypeNames the names of the mixin types; may be null or empty if there are no mixins to include in the search
+ * @param propertyName the name of the property for which the definition should be retrieved. This method will automatically
+ * look for residual definitions, but you can use {@link JcrNodeType#RESIDUAL_ITEM_NAME} to retrieve only the best
+ * residual property definition (if any).
+ * @param value the value, or null if the property is being removed
+ * @param checkMultiValuedDefinitions true if the type's multi-valued property definitions should be considered, or false if
+ * only single-value property definitions should be considered
+ * @param skipProtected true if this operation is being done from within the public JCR node and property API, or false if
+ * this operation is being done from within internal implementations
+ * @return the best property definition, or <code>null</code> if no property definition allows the property with the supplied
+ * name, type and number of values
+ */
+ JcrPropertyDefinition findPropertyDefinition( Name primaryTypeName,
+ List<Name> mixinTypeNames,
+ Name propertyName,
+ Value value,
+ boolean checkMultiValuedDefinitions,
+ boolean skipProtected ) {
+ boolean setToEmpty = value == null;
+
+ // Look for a single-value property definition on the primary type that matches by name and type ...
+ JcrNodeType primaryType = getNodeType(primaryTypeName);
+ if (primaryType != null) {
+ for (JcrPropertyDefinition definition : primaryType.allSingleValuePropertyDefinitions(propertyName)) {
+ // See if the definition allows the value ...
+ if (skipProtected && definition.isProtected()) continue;
+ if (setToEmpty) {
+ if (!definition.isMandatory()) return definition;
+ // Otherwise this definition doesn't work, so continue with the next ...
+ continue;
+ }
+ assert value != null;
+ // We can use the definition if it matches the type and satisfies the constraints ...
+ int type = definition.getRequiredType();
+ if ((type == PropertyType.UNDEFINED || type == value.getType()) && definition.satisfiesConstraints(value)) return definition;
+ }
+ }
+
+ // Look for a single-value property definition on the mixin types that matches by name and type ...
+ List<JcrNodeType> mixinTypes = null;
+ if (mixinTypeNames != null && !mixinTypeNames.isEmpty()) {
+ mixinTypes = new LinkedList<JcrNodeType>();
+ for (Name mixinTypeName : mixinTypeNames) {
+ JcrNodeType mixinType = getNodeType(mixinTypeName);
+ if (mixinType == null) continue;
+ mixinTypes.add(mixinType);
+ for (JcrPropertyDefinition definition : mixinType.allSingleValuePropertyDefinitions(propertyName)) {
+ // See if the definition allows the value ...
+ if (skipProtected && definition.isProtected()) continue;
+ if (setToEmpty) {
+ if (!definition.isMandatory()) return definition;
+ // Otherwise this definition doesn't work, so continue with the next ...
+ continue;
+ }
+ assert value != null;
+ // We can use the definition if it matches the type and satisfies the constraints ...
+ int type = definition.getRequiredType();
+ if ((type == PropertyType.UNDEFINED || type == value.getType()) && definition.satisfiesConstraints(value)) return definition;
+ }
+ }
+ }
+
+ if (checkMultiValuedDefinitions) {
+ // Look for a multi-value property definition on the primary type that matches by name and type ...
+ if (primaryType != null) {
+ for (JcrPropertyDefinition definition : primaryType.allMultiValuePropertyDefinitions(propertyName)) {
+ // See if the definition allows the value ...
+ if (skipProtected && definition.isProtected()) continue;
+ if (setToEmpty) {
+ if (!definition.isMandatory()) return definition;
+ // Otherwise this definition doesn't work, so continue with the next ...
+ continue;
+ }
+ assert value != null;
+ // We can use the definition if it matches the type and satisfies the constraints ...
+ int type = definition.getRequiredType();
+ if ((type == PropertyType.UNDEFINED || type == value.getType()) && definition.satisfiesConstraints(value)) return definition;
+ }
+ }
+
+ // Look for a multi-value property definition on the mixin types that matches by name and type ...
+ if (mixinTypes != null) {
+ for (JcrNodeType mixinType : mixinTypes) {
+ for (JcrPropertyDefinition definition : mixinType.allMultiValuePropertyDefinitions(propertyName)) {
+ // See if the definition allows the value ...
+ if (skipProtected && definition.isProtected()) continue;
+ if (setToEmpty) {
+ if (!definition.isMandatory()) return definition;
+ // Otherwise this definition doesn't work, so continue with the next ...
+ continue;
+ }
+ assert value != null;
+ // We can use the definition if it matches the type and satisfies the constraints ...
+ int type = definition.getRequiredType();
+ if ((type == PropertyType.UNDEFINED || type == value.getType()) && definition.satisfiesConstraints(value)) return definition;
+ }
+ }
+ }
+ }
+
+ if (value != null) {
+ // Nothing was found with matching name and type, so look for definitions with
+ // matching name and an undefined or castable type ...
+
+ // Look for a single-value property definition on the primary type that matches by name ...
+ if (primaryType != null) {
+ for (JcrPropertyDefinition definition : primaryType.allSingleValuePropertyDefinitions(propertyName)) {
+ // See if the definition allows the value ...
+ if (skipProtected && definition.isProtected()) continue;
+ assert definition.getRequiredType() != PropertyType.UNDEFINED;
+ if (definition.canCastToTypeAndSatisfyConstraints(value)) return definition;
+ }
+ }
+
+ // Look for a single-value property definition on the mixin types that matches by name ...
+ if (mixinTypes != null) {
+ for (JcrNodeType mixinType : mixinTypes) {
+ for (JcrPropertyDefinition definition : mixinType.allSingleValuePropertyDefinitions(propertyName)) {
+ // See if the definition allows the value ...
+ if (skipProtected && definition.isProtected()) continue;
+ assert definition.getRequiredType() != PropertyType.UNDEFINED;
+ if (definition.canCastToTypeAndSatisfyConstraints(value)) return definition;
+ }
+ }
+ }
+
+ if (checkMultiValuedDefinitions) {
+ // Look for a multi-value property definition on the primary type that matches by name ...
+ if (primaryType != null) {
+ for (JcrPropertyDefinition definition : primaryType.allMultiValuePropertyDefinitions(propertyName)) {
+ // See if the definition allows the value ...
+ if (skipProtected && definition.isProtected()) continue;
+ assert definition.getRequiredType() != PropertyType.UNDEFINED;
+ if (definition.canCastToTypeAndSatisfyConstraints(value)) return definition;
+ }
+ }
+
+ // Look for a multi-value property definition on the mixin types that matches by name ...
+ if (mixinTypes != null) {
+ for (JcrNodeType mixinType : mixinTypes) {
+ for (JcrPropertyDefinition definition : mixinType.allMultiValuePropertyDefinitions(propertyName)) {
+ // See if the definition allows the value ...
+ if (skipProtected && definition.isProtected()) continue;
+ assert definition.getRequiredType() != PropertyType.UNDEFINED;
+ if (definition.canCastToTypeAndSatisfyConstraints(value)) return definition;
+ }
+ }
+ }
+ }
+ }
+
+ // Nothing was found, so look for residual property definitions ...
+ if (!propertyName.equals(JcrNodeType.RESIDUAL_NAME)) return findPropertyDefinition(primaryTypeName,
+ mixinTypeNames,
+ JcrNodeType.RESIDUAL_NAME,
+ value,
+ checkMultiValuedDefinitions,
+ skipProtected);
+ return null;
+ }
+
+ /**
+ * Searches the supplied primary node type and the mixin node types for a property definition that is the best match for the
+ * given property name, property type, and value.
+ * <p>
+ * This method first attempts to find a single-valued property definition with the supplied property name and
+ * {@link Value#getType() value's property type} in the primary type, skipping any property definitions that are protected.
+ * The property definition is returned if it has a matching type (or has an {@link PropertyType#UNDEFINED undefined property
+ * type}) and the value satisfies the {@link PropertyDefinition#getValueConstraints() definition's constraints}. Otherwise,
+ * the process continues with each of the mixin types, in the order they are named.
+ * </p>
+ * <p>
+ * If no matching property definition could be found (and <code>checkMultiValuedDefinitions</code> parameter is
+ * <code>true</code>), the process is repeated except with multi-valued property definitions with the same name, property
+ * type, and compatible constraints, starting with the primary type and continuing with each mixin type.
+ * </p>
+ * <p>
+ * If no matching property definition could be found, and the process repeats by searching the primary type (and then mixin
+ * types) for single-valued property definitions with a compatible type, where the values can be safely cast to the
+ * definition's property type and still satisfy the definition's constraints.
+ * </p>
+ * <p>
+ * If no matching property definition could be found, the previous step is repeated with multi-valued property definitions.
+ * </p>
+ * <p>
+ * If no matching property definition could be found (and the supplied property name is not the residual name), the whole
+ * process repeats for residual property definitions (e.g., those that are defined with a {@link JcrNodeType#RESIDUAL_NAME "*"
+ * name}).
+ * </p>
+ * <p>
+ * Finally, if no satisfactory property definition could be found, this method returns null.
+ * </p>
+ *
+ * @param primaryTypeName the name of the primary type; may not be null
+ * @param mixinTypeNames the names of the mixin types; may be null or empty if there are no mixins to include in the search
+ * @param propertyName the name of the property for which the definition should be retrieved. This method will automatically
+ * look for residual definitions, but you can use {@link JcrNodeType#RESIDUAL_ITEM_NAME} to retrieve only the best
+ * residual property definition (if any).
+ * @param values the values
+ * @param skipProtected true if this operation is being done from within the public JCR node and property API, or false if
+ * this operation is being done from within internal implementations
+ * @return the best property definition, or <code>null</code> if no property definition allows the property with the supplied
+ * name, type and number of values
+ */
+ JcrPropertyDefinition findPropertyDefinition( Name primaryTypeName,
+ List<Name> mixinTypeNames,
+ Name propertyName,
+ Value[] values,
+ boolean skipProtected ) {
+ boolean setToEmpty = values == null || values.length == 0;
+ int propertyType = values == null || values.length == 0 ? PropertyType.STRING : values[0].getType();
+
+ // Look for a multi-value property definition on the primary type that matches by name and type ...
+ JcrNodeType primaryType = getNodeType(primaryTypeName);
+ if (primaryType != null) {
+ for (JcrPropertyDefinition definition : primaryType.allMultiValuePropertyDefinitions(propertyName)) {
+ // See if the definition allows the value ...
+ if (skipProtected && definition.isProtected()) continue;
+ if (setToEmpty) {
+ if (!definition.isMandatory()) return definition;
+ // Otherwise this definition doesn't work, so continue with the next ...
+ continue;
+ }
+ assert values != null;
+ assert values.length != 0;
+ // We can use the definition if it matches the type and satisfies the constraints ...
+ int type = definition.getRequiredType();
+ if ((type == PropertyType.UNDEFINED || type == propertyType) && definition.satisfiesConstraints(values)) return definition;
+ }
+ }
+
+ // Look for a multi-value property definition on the mixin types that matches by name and type ...
+ List<JcrNodeType> mixinTypes = null;
+ if (mixinTypeNames != null && !mixinTypeNames.isEmpty()) {
+ mixinTypes = new LinkedList<JcrNodeType>();
+ for (Name mixinTypeName : mixinTypeNames) {
+ JcrNodeType mixinType = getNodeType(mixinTypeName);
+ if (mixinType == null) continue;
+ mixinTypes.add(mixinType);
+ for (JcrPropertyDefinition definition : mixinType.allMultiValuePropertyDefinitions(propertyName)) {
+ // See if the definition allows the value ...
+ if (skipProtected && definition.isProtected()) continue;
+ if (setToEmpty) {
+ if (!definition.isMandatory()) return definition;
+ // Otherwise this definition doesn't work, so continue with the next ...
+ continue;
+ }
+ assert values != null;
+ assert values.length != 0;
+ // We can use the definition if it matches the type and satisfies the constraints ...
+ int type = definition.getRequiredType();
+ if ((type == PropertyType.UNDEFINED || type == propertyType) && definition.satisfiesConstraints(values)) return definition;
+ }
+ }
+ }
+
+ if (values != null && values.length != 0) {
+ // Nothing was found with matching name and type, so look for definitions with
+ // matching name and an undefined or castable type ...
+
+ // Look for a multi-value property definition on the primary type that matches by name and type ...
+ if (primaryType != null) {
+ for (JcrPropertyDefinition definition : primaryType.allMultiValuePropertyDefinitions(propertyName)) {
+ // See if the definition allows the value ...
+ if (skipProtected && definition.isProtected()) continue;
+ assert definition.getRequiredType() != PropertyType.UNDEFINED;
+ if (definition.canCastToTypeAndSatisfyConstraints(values)) return definition;
+ }
+ }
+
+ // Look for a multi-value property definition on the mixin types that matches by name and type ...
+ if (mixinTypes != null) {
+ for (JcrNodeType mixinType : mixinTypes) {
+ for (JcrPropertyDefinition definition : mixinType.allMultiValuePropertyDefinitions(propertyName)) {
+ // See if the definition allows the value ...
+ if (skipProtected && definition.isProtected()) continue;
+ assert definition.getRequiredType() != PropertyType.UNDEFINED;
+ if (definition.canCastToTypeAndSatisfyConstraints(values)) return definition;
+ }
+ }
+ }
+ }
+
+ // Nothing was found, so look for residual property definitions ...
+ if (!propertyName.equals(JcrNodeType.RESIDUAL_NAME)) return findPropertyDefinition(primaryTypeName,
+ mixinTypeNames,
+ JcrNodeType.RESIDUAL_NAME,
+ values,
+ skipProtected);
+ return null;
+ }
+
+ /**
+ * Determine if the property definitions of the supplied primary type and mixin types allow the property with the supplied
+ * name to be removed.
+ *
+ * @param primaryTypeNameOfParent the name of the primary type for the parent node; may not be null
+ * @param mixinTypeNamesOfParent the names of the mixin types for the parent node; may be null or empty if there are no mixins
+ * to include in the search
+ * @param propertyName the name of the property to be removed; may not be null
+ * @param skipProtected true if this operation is being done from within the public JCR node and property API, or false if
+ * this operation is being done from within internal implementations
+ * @return true if at least one child node definition does not require children with the supplied name to exist, or false
+ * otherwise
+ */
+ boolean canRemoveProperty( Name primaryTypeNameOfParent,
+ List<Name> mixinTypeNamesOfParent,
+ Name propertyName,
+ boolean skipProtected ) {
+ // First look in the primary type ...
+ JcrNodeType primaryType = getNodeType(primaryTypeNameOfParent);
+ if (primaryType != null) {
+ for (JcrPropertyDefinition definition : primaryType.allPropertyDefinitions(propertyName)) {
+ // Skip protected definitions ...
+ if (skipProtected && definition.isProtected()) continue;
+ // If this definition is not mandatory, then we have found that we CAN remove the property ...
+ if (!definition.isMandatory()) return true;
+ }
+ }
+
+ // Then, look in the mixin types ...
+ if (mixinTypeNamesOfParent != null && !mixinTypeNamesOfParent.isEmpty()) {
+ for (Name mixinTypeName : mixinTypeNamesOfParent) {
+ JcrNodeType mixinType = getNodeType(mixinTypeName);
+ if (mixinType == null) continue;
+ for (JcrPropertyDefinition definition : mixinType.allPropertyDefinitions(propertyName)) {
+ // Skip protected definitions ...
+ if (skipProtected && definition.isProtected()) continue;
+ // If this definition is not mandatory, then we have found that we CAN remove the property ...
+ if (!definition.isMandatory()) return true;
+ }
+ }
+ }
+
+ // Nothing was found, so look for residual node definitions ...
+ if (!propertyName.equals(JcrNodeType.RESIDUAL_NAME)) return canRemoveProperty(primaryTypeNameOfParent,
+ mixinTypeNamesOfParent,
+ JcrNodeType.RESIDUAL_NAME,
+ skipProtected);
+ return false;
+ }
+
+ /**
+ * Searches the supplied primary node type and the mixin node types of a parent node for a child node definition that is the
+ * best match for a new child with the given name, primary node type name, and whether there are existing children with the
+ * same name.
+ *
+ * @param primaryTypeNameOfParent the name of the primary type for the parent node; may not be null
+ * @param mixinTypeNamesOfParent the names of the mixin types for the parent node; may be null or empty if there are no mixins
+ * to include in the search
+ * @param childName the name of the child to be added to the parent; may not be null
+ * @param childPrimaryNodeType the name of the primary node type for the child node, or null if the primary type is not known
+ * and the {@link NodeDefinition#getDefaultPrimaryType() definition's default primary type} will be used
+ * @param numberOfExistingChildrenWithSameName the number of existing children with the same name as the child to be added, or
+ * 0 if this new child will be the first child with this name (or if the number of children is not known)
+ * @param skipProtected true if this operation is being done from within the public JCR node and property API, or false if
+ * this operation is being done from within internal implementations
+ * @return the best child node definition, or <code>null</code> if no node definition allows a new child with the supplied
+ * name, primary type, and whether there are already children with the same name
+ */
+ JcrNodeDefinition findChildNodeDefinition( Name primaryTypeNameOfParent,
+ List<Name> mixinTypeNamesOfParent,
+ Name childName,
+ Name childPrimaryNodeType,
+ int numberOfExistingChildrenWithSameName,
+ boolean skipProtected ) {
+ JcrNodeType childType = childPrimaryNodeType != null ? getNodeType(childPrimaryNodeType) : null;
+ boolean requireSns = numberOfExistingChildrenWithSameName != 0;
+
+ // First look in the primary type ...
+ JcrNodeType primaryType = getNodeType(primaryTypeNameOfParent);
+ if (primaryType != null) {
+ for (JcrNodeDefinition definition : primaryType.allChildNodeDefinitions(childName, requireSns)) {
+ // Skip protected definitions ...
+ if (skipProtected && definition.isProtected()) continue;
+ // See if the definition allows a child with the supplied primary type ...
+ if (definition.allowsChildWithType(childType)) return definition;
+ }
+ }
+
+ // Then, look in the mixin types ...
+ if (mixinTypeNamesOfParent != null && !mixinTypeNamesOfParent.isEmpty()) {
+ for (Name mixinTypeName : mixinTypeNamesOfParent) {
+ JcrNodeType mixinType = getNodeType(mixinTypeName);
+ if (mixinType == null) continue;
+ for (JcrNodeDefinition definition : mixinType.allChildNodeDefinitions(childName, requireSns)) {
+ // Skip protected definitions ...
+ if (skipProtected && definition.isProtected()) continue;
+ // See if the definition allows a child with the supplied primary type ...
+ if (definition.allowsChildWithType(childType)) return definition;
+ }
+ }
+ }
+
+ // Nothing was found, so look for residual node definitions ...
+ if (!childName.equals(JcrNodeType.RESIDUAL_NAME)) return findChildNodeDefinition(primaryTypeNameOfParent,
+ mixinTypeNamesOfParent,
+ JcrNodeType.RESIDUAL_NAME,
+ childPrimaryNodeType,
+ numberOfExistingChildrenWithSameName,
+ skipProtected);
+ return null;
+ }
+
+ /**
+ * Determine if the child node definitions of the supplied primary type and mixin types of a parent node allow all of the
+ * children with the supplied name to be removed.
+ *
+ * @param primaryTypeNameOfParent the name of the primary type for the parent node; may not be null
+ * @param mixinTypeNamesOfParent the names of the mixin types for the parent node; may be null or empty if there are no mixins
+ * to include in the search
+ * @param childName the name of the child to be added to the parent; may not be null
+ * @param skipProtected true if this operation is being done from within the public JCR node and property API, or false if
+ * this operation is being done from within internal implementations
+ * @return true if at least one child node definition does not require children with the supplied name to exist, or false
+ * otherwise
+ */
+ boolean canRemoveAllChildren( Name primaryTypeNameOfParent,
+ List<Name> mixinTypeNamesOfParent,
+ Name childName,
+ boolean skipProtected ) {
+ // First look in the primary type ...
+ JcrNodeType primaryType = getNodeType(primaryTypeNameOfParent);
+ if (primaryType != null) {
+ for (JcrNodeDefinition definition : primaryType.allChildNodeDefinitions(childName)) {
+ // Skip protected definitions ...
+ if (skipProtected && definition.isProtected()) continue;
+ // If this definition is not mandatory, then we have found that we CAN remove all children ...
+ if (!definition.isMandatory()) return true;
+ }
+ }
+
+ // Then, look in the mixin types ...
+ if (mixinTypeNamesOfParent != null && !mixinTypeNamesOfParent.isEmpty()) {
+ for (Name mixinTypeName : mixinTypeNamesOfParent) {
+ JcrNodeType mixinType = getNodeType(mixinTypeName);
+ if (mixinType == null) continue;
+ for (JcrNodeDefinition definition : mixinType.allChildNodeDefinitions(childName)) {
+ // Skip protected definitions ...
+ if (skipProtected && definition.isProtected()) continue;
+ // If this definition is not mandatory, then we have found that we CAN remove all children ...
+ if (!definition.isMandatory()) return true;
+ }
+ }
+ }
+
+ // Nothing was found, so look for residual node definitions ...
+ if (!childName.equals(JcrNodeType.RESIDUAL_NAME)) return canRemoveAllChildren(primaryTypeNameOfParent,
+ mixinTypeNamesOfParent,
+ JcrNodeType.RESIDUAL_NAME,
+ skipProtected);
+ return false;
+ }
}
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/SessionCache.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/SessionCache.java 2009-03-23 20:41:31 UTC (rev 787)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/SessionCache.java 2009-03-24 02:16:34 UTC (rev 788)
@@ -27,7 +27,6 @@
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
-import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
@@ -43,10 +42,10 @@
import javax.jcr.PropertyType;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
+import javax.jcr.Value;
import javax.jcr.nodetype.ConstraintViolationException;
import javax.jcr.nodetype.NodeDefinition;
import javax.jcr.nodetype.NodeType;
-import javax.jcr.nodetype.NodeTypeManager;
import javax.jcr.nodetype.PropertyDefinition;
import net.jcip.annotations.ThreadSafe;
import org.jboss.dna.graph.ExecutionContext;
@@ -432,14 +431,16 @@
* existing values will be replaced with the supplied value.
*
* @param name the property name; may not be null
+ * @param propertyType the property type; must be a valid {@link PropertyType} value
* @param value the new property values, which may be converted to the appropriate {@link PropertyType type}
* @throws ConstraintViolationException if the property could not be set because of a node type constraint or property
* definition constraint
*/
public void setProperty( Name name,
+ int propertyType,
Object value ) throws ConstraintViolationException {
Property dnaProp = propertyFactory.create(name, value);
- setProperty(name, dnaProp);
+ setProperty(name, dnaProp, propertyType);
}
/**
@@ -447,46 +448,59 @@
* existing values will be replaced with those that are supplied.
*
* @param name the property name; may not be null
+ * @param propertyType the property type; must be a valid {@link PropertyType} value
* @param value the new property values, which may be converted to the appropriate {@link PropertyType type}
* @throws ConstraintViolationException if the property could not be set because of a node type constraint or property
* definition constraint
*/
public void setProperty( Name name,
+ int propertyType,
Object[] value ) throws ConstraintViolationException {
Property dnaProp = propertyFactory.create(name, value);
- setProperty(name, dnaProp);
+ setProperty(name, dnaProp, propertyType);
}
protected final void setProperty( Name name,
- Property dnaProp ) throws ConstraintViolationException {
+ Property dnaProp,
+ int propertyType ) throws ConstraintViolationException {
+ assert propertyType != PropertyType.UNDEFINED;
PropertyInfo existing = node.getProperty(name);
PropertyInfo newProperty = null;
if (existing != null) {
// We're replacing an existing property, but we still need to check that the property definition
// defines a type. So, find the property definition for the existing property ...
- JcrPropertyDefinition definition = nodeTypes().getPropertyDefinition(existing.getDefinitionId(),
- existing.isMultiValued());
-
- // Look at the required property type ...
- int propertyType = definition.getRequiredType();
- if (propertyType == PropertyType.UNDEFINED) {
- // We need set the new type to that defined by the values ...
- propertyType = JcrSession.jcrPropertyTypeFor(dnaProp);
+ JcrPropertyDefinition definition = nodeTypes().getPropertyDefinition(existing.getDefinitionId());
+ if (definition == null && existing.getDefinitionId().allowsMultiple() && dnaProp.isSingle()) {
+ // Look for a single-valued definition ...
+ PropertyDefinitionId id = existing.getDefinitionId().asSingleValued();
+ definition = nodeTypes().getPropertyDefinition(id);
}
+ if (definition == null) {
+ // Try to find a different (but existing) property definition ...
+ definition = findBestPropertyDefintion(node.getPrimaryTypeName(),
+ node.getMixinTypeNames(),
+ dnaProp,
+ propertyType,
+ true);
+ }
+ if (definition == null) {
+ throw new ConstraintViolationException();
+ }
- // Csreate the property info ...
+ // Create the property info ...
newProperty = new PropertyInfo(existing.getPropertyId(), existing.getDefinitionId(), propertyType, dnaProp,
existing.isMultiValued());
} else {
// It's a new property ...
PropertyId id = new PropertyId(node.getUuid(), name);
// Look find the property definition to use ...
- JcrPropertyDefinition definition = findBestPropertyDefintion(dnaProp);
-
- // Figure out the property type ...
- int propertyType = definition.getRequiredType();
- if (propertyType == PropertyType.UNDEFINED) {
- propertyType = JcrSession.jcrPropertyTypeFor(dnaProp);
+ JcrPropertyDefinition definition = findBestPropertyDefintion(node.getPrimaryTypeName(),
+ node.getMixinTypeNames(),
+ dnaProp,
+ propertyType,
+ true);
+ if (definition == null) {
+ throw new ConstraintViolationException();
}
// Create the property info ...
newProperty = new PropertyInfo(id, definition.getId(), propertyType, dnaProp, definition.isMultiple());
@@ -545,11 +559,19 @@
// Verify that this node's definition allows the specified child ...
Name childName = existingParentInfo.getChildren().getChild(nodeUuid).getName();
int numSns = node.getChildren().getCountOfSameNameSiblingsWithName(childName);
- JcrNodeDefinition definition = findBestChildNodeDefinition(childName, numSns);
+ JcrNodeDefinition definition = nodeTypes().findChildNodeDefinition(node.getPrimaryTypeName(),
+ node.getMixinTypeNames(),
+ childName,
+ childName,
+ numSns,
+ true);
+ if (definition == null) {
+ throw new ConstraintViolationException();
+ }
if (!definition.getId().equals(node.getDefinitionId())) {
// The node definition changed, so try to set the property ...
try {
- setProperty(DnaLexicon.NODE_DEFINITON, definition.getId().getString());
+ setProperty(DnaLexicon.NODE_DEFINITON, PropertyType.STRING, definition.getId().getString());
} catch (ConstraintViolationException e) {
// We can't set this property on the node (according to the node definition).
// But we still want the node info to have the correct node definition.
@@ -597,7 +619,15 @@
// Verify that this node accepts a child of the supplied name (given any existing SNS nodes) ...
int numSns = node.getChildren().getCountOfSameNameSiblingsWithName(name);
- JcrNodeDefinition definition = findBestChildNodeDefinition(name, numSns);
+ JcrNodeDefinition definition = nodeTypes().findChildNodeDefinition(node.getPrimaryTypeName(),
+ node.getMixinTypeNames(),
+ name,
+ primaryTypeName,
+ numSns,
+ true);
+ if (definition == null) {
+ throw new ConstraintViolationException();
+ }
ChildNode result = node.addChild(name, desiredUuid, pathFactory);
@@ -613,14 +643,22 @@
Property nodeDefinitionProp = propertyFactory.create(DnaLexicon.NODE_DEFINITON, nodeDefinitionId.getString());
// Create the property info for the "jcr:primaryType" child property ...
- JcrPropertyDefinition primaryTypeDefn = findBestPropertyDefintion(primaryTypeProp, primaryTypeName);
+ JcrPropertyDefinition primaryTypeDefn = findBestPropertyDefintion(node.getPrimaryTypeName(),
+ node.getMixinTypeNames(),
+ primaryTypeProp,
+ PropertyType.NAME,
+ false);
PropertyDefinitionId primaryTypeDefinitionId = primaryTypeDefn.getId();
PropertyInfo primaryTypeInfo = new PropertyInfo(new PropertyId(desiredUuid, primaryTypeProp.getName()),
primaryTypeDefinitionId, PropertyType.NAME, primaryTypeProp, false);
properties.put(primaryTypeProp.getName(), primaryTypeInfo);
// Create the property info for the "dna:nodeDefinition" child property ...
- JcrPropertyDefinition nodeDefnDefn = findBestPropertyDefintion(nodeDefinitionProp, primaryTypeName);
+ JcrPropertyDefinition nodeDefnDefn = findBestPropertyDefintion(node.getPrimaryTypeName(),
+ node.getMixinTypeNames(),
+ nodeDefinitionProp,
+ PropertyType.STRING,
+ false);
if (nodeDefnDefn != null) {
PropertyDefinitionId nodeDefnDefinitionId = nodeDefnDefn.getId();
PropertyInfo nodeDefinitionInfo = new PropertyInfo(new PropertyId(desiredUuid, nodeDefinitionProp.getName()),
@@ -672,111 +710,6 @@
return false;
}
- /**
- * Find the best property definition in this node's
- *
- * @param dnaProperty the new property that is to be set on this node
- * @return the property definition that allows setting this property; never null
- * @throws ConstraintViolationException if setting the property would violates this node's definition or the property's
- * definition
- */
- protected JcrPropertyDefinition findBestPropertyDefintion( Property dnaProperty ) throws ConstraintViolationException {
- // First check the primary type ...
- JcrPropertyDefinition definition = findBestPropertyDefintion(dnaProperty, node.getPrimaryTypeName());
- if (definition != null) {
- // TODO: Does this definition allow this value? ...
- return definition;
- }
- // Check the mixin types ...
- for (Name mixinTypeName : node.getMixinTypeNames()) {
- definition = findBestPropertyDefintion(dnaProperty, mixinTypeName);
- if (definition != null) {
- // TODO: Does this definition allow this value? ...
- return definition;
- }
- }
-
- // Nothing was found yet, so check the residual property definitions, starting with the primary type ...
- definition = findBestPropertyDefintion(dnaProperty, residualName);
- if (definition != null) {
- // TODO: Does this definition allow this value? ...
- return definition;
- }
- // Check the mixin types ...
- for (Name mixinTypeName : node.getMixinTypeNames()) {
- definition = findBestPropertyDefintion(dnaProperty, mixinTypeName);
- if (definition != null) {
- // TODO: Does this definition allow this value? ...
- return definition;
- }
- }
-
- // No definition that allowed the values ...
- throw new ConstraintViolationException();
- }
-
- /**
- * Find the best property definition in the named node type.
- *
- * @param dnaProperty the new property that is to be set on this node
- * @param nodeTypeName the name of the node type that should be checked; may not be null
- * @return the property definition that allows setting this property; or null if no valid property definition could be
- * found in the given node type
- * @see #findBestPropertyDefintion(Property)
- */
- protected JcrPropertyDefinition findBestPropertyDefintion( Property dnaProperty,
- Name nodeTypeName ) {
- JcrNodeType nodeType = nodeTypes().getNodeType(nodeTypeName);
- Name name = dnaProperty.getName();
- JcrPropertyDefinition definition = null;
- if (dnaProperty.isSingle()) {
- // First look for a single-valued property definition with a matching name ...
- definition = nodeType.getPropertyDefinition(name, false);
- if (definition != null) return definition;
-
- // Then look for a residual definition ...
- definition = nodeType.getPropertyDefinition(JcrNodeType.RESIDUAL_ITEM_NAME, false);
- if (definition != null) return definition;
- }
-
- // Either the DNA property has 0 or 2+ values (and we couldn't use a single-valued definition)
- // OR there was 1 value and we couldn't find a single-valued definition.
- // So, we need to look for a multi-valued property definition ...
-
- // First look for a definition that matches by name ...
- definition = nodeType.getPropertyDefinition(name, true);
- if (definition != null) return definition;
-
- // Then look for a residual definition ...
- definition = nodeType.getPropertyDefinition(JcrNodeType.RESIDUAL_ITEM_NAME, true);
- if (definition != null) return definition;
-
- // Nothing found yet ...
- if (INCLUDE_PROPERTIES_NOT_ALLOWED_BY_NODE_TYPE_OR_MIXINS) {
- // We can use the "nt:unstructured" property definitions for any property ...
- JcrNodeType unstructured = nodeTypes().getNodeType(JcrNtLexicon.UNSTRUCTURED);
- definition = unstructured.getPropertyDefinition(JcrNodeType.RESIDUAL_ITEM_NAME, true);
- if (definition != null) return definition;
- }
-
- // No property definition could be found ...
- return null;
- }
-
- /**
- * @param childName
- * @param numberOfExistingChildrenWithName
- * @return the most specific node definition for the child; never null
- * @throws ConstraintViolationException if the new child would violates this node's definition
- */
- protected JcrNodeDefinition findBestChildNodeDefinition( Name childName,
- int numberOfExistingChildrenWithName )
- throws ConstraintViolationException {
-
- // No definition that allowed the values ...
- throw new ConstraintViolationException();
- }
-
protected boolean isAncestor( UUID uuid ) throws ItemNotFoundException, InvalidItemStateException, RepositoryException {
UUID ancestor = node.getParent();
while (ancestor != null) {
@@ -789,6 +722,56 @@
}
/**
+ * Find the best property definition in this node's
+ *
+ * @param primaryTypeNameOfParent the name of the primary type for the parent node; may not be null
+ * @param mixinTypeNamesOfParent the names of the mixin types for the parent node; may be null or empty if there are no mixins
+ * to include in the search
+ * @param dnaProperty the new property that is to be set on this node
+ * @param propertyType the property type; must be a valid {@link PropertyType} value
+ * @param skipProtected true if this operation is being done from within the public JCR node and property API, or false if
+ * this operation is being done from within internal implementations
+ * @return the property definition that allows setting this property, or null if there is no such definition
+ */
+ protected JcrPropertyDefinition findBestPropertyDefintion( Name primaryTypeNameOfParent,
+ List<Name> mixinTypeNamesOfParent,
+ Property dnaProperty,
+ int propertyType,
+ boolean skipProtected ) {
+ JcrPropertyDefinition definition = null;
+
+ // If single-valued ...
+ if (dnaProperty.isSingle()) {
+ // Create a value for the DNA property value ...
+ Object value = dnaProperty.getFirstValue();
+ Value jcrValue = new JcrValue(context().getValueFactories(), SessionCache.this, propertyType, value);
+ definition = nodeTypes().findPropertyDefinition(primaryTypeNameOfParent,
+ mixinTypeNamesOfParent,
+ dnaProperty.getName(),
+ jcrValue,
+ true,
+ skipProtected);
+ } else {
+ // Create values for the DNA property value ...
+ Value[] jcrValues = new Value[dnaProperty.size()];
+ int index = 0;
+ for (Object value : dnaProperty) {
+ jcrValues[index++] = new JcrValue(context().getValueFactories(), SessionCache.this, propertyType, value);
+ }
+ definition = nodeTypes().findPropertyDefinition(primaryTypeNameOfParent,
+ mixinTypeNamesOfParent,
+ dnaProperty.getName(),
+ jcrValues,
+ skipProtected);
+ }
+
+ if (definition != null) return definition;
+
+ // No definition that allowed the values ...
+ return null;
+ }
+
+ /**
* Utility method that creates and caches the appropriate kind of AbstractJcrNode implementation for node given by the
* supplied information.
*
@@ -828,7 +811,7 @@
*/
private AbstractJcrProperty createAndCacheJcrPropertyFor( PropertyInfo info ) {
boolean multiValued = info.isMultiValued();
- JcrPropertyDefinition definition = nodeTypes().getPropertyDefinition(info.getDefinitionId(), multiValued);
+ JcrPropertyDefinition definition = nodeTypes().getPropertyDefinition(info.getDefinitionId());
assert definition != null;
if (multiValued) {
return new JcrMultiValueProperty(this, info.getPropertyId());
@@ -1271,7 +1254,13 @@
parentInfo = findNodeInfo(null, parentPath.getNormalizedPath());
}
Name childName = path.getLastSegment().getName();
- definition = findNodeDefinitionForChild(parentInfo, childName, primaryTypeName);
+ int numExistingChildrenWithSameName = parentInfo.getChildren().getCountOfSameNameSiblingsWithName(childName);
+ definition = nodeTypes().findChildNodeDefinition(parentInfo.getPrimaryTypeName(),
+ parentInfo.getMixinTypeNames(),
+ childName,
+ primaryTypeName,
+ numExistingChildrenWithSameName,
+ false);
if (definition == null) {
String msg = JcrI18n.nodeDefinitionCouldNotBeDeterminedForNode.text(path, workspaceName);
throw new RepositorySourceException(msg);
@@ -1282,59 +1271,23 @@
// ------------------------------------------------------
// Set the node's properties ...
// ------------------------------------------------------
- // First get the property type for each property, based upon the primary type and mixins ...
- // The map with single-valued properties...
- Map<Name, PropertyDefinition> svPropertyDefinitionsByPropertyName = new HashMap<Name, PropertyDefinition>();
- // ... and the map with multi-valued properties
- Map<Name, PropertyDefinition> mvPropertyDefinitionsByPropertyName = new HashMap<Name, PropertyDefinition>();
-
boolean referenceable = false;
- List<PropertyDefinition> anyPropertyDefinitions = new LinkedList<PropertyDefinition>();
// Start with the primary type ...
- NodeType primaryType = nodeTypes().getNodeType(primaryTypeName);
- for (PropertyDefinition propertyDefn : primaryType.getPropertyDefinitions()) {
- String nameString = propertyDefn.getName();
- if ("*".equals(nameString)) {
- anyPropertyDefinitions.add(propertyDefn);
- continue;
- }
- Name name = nameFactory.create(nameString);
+ JcrNodeType primaryType = nodeTypes().getNodeType(primaryTypeName);
+ if (primaryType.isNodeType(JcrMixLexicon.REFERENCEABLE)) referenceable = true;
- if (propertyDefn.isMultiple()) {
- PropertyDefinition prev = mvPropertyDefinitionsByPropertyName.put(name, propertyDefn);
- if (prev != null) mvPropertyDefinitionsByPropertyName.put(name, prev); // put the first one back ...
- } else {
- PropertyDefinition prev = svPropertyDefinitionsByPropertyName.put(name, propertyDefn);
- if (prev != null) svPropertyDefinitionsByPropertyName.put(name, prev); // put the first one back ...
- }
- }
// The process the mixin types ...
org.jboss.dna.graph.property.Property mixinTypesProperty = graphProperties.get(JcrLexicon.MIXIN_TYPES);
- Set<Name> mixinTypeNames = null;
+ List<Name> mixinTypeNames = null;
if (mixinTypesProperty != null && !mixinTypesProperty.isEmpty()) {
for (Object mixinTypeValue : mixinTypesProperty) {
Name mixinTypeName = nameFactory.create(mixinTypeValue);
- if (mixinTypeNames == null) mixinTypeNames = new HashSet<Name>();
+ if (mixinTypeNames == null) mixinTypeNames = new LinkedList<Name>();
mixinTypeNames.add(mixinTypeName);
- if (!referenceable && JcrMixLexicon.REFERENCEABLE.equals(mixinTypeName)) referenceable = true;
- String mixinTypeNameString = mixinTypeName.getString(namespaces);
- NodeType mixinType = nodeTypes().getNodeType(mixinTypeNameString);
- for (PropertyDefinition propertyDefn : mixinType.getPropertyDefinitions()) {
- String nameString = propertyDefn.getName();
- if ("*".equals(nameString)) {
- anyPropertyDefinitions.add(propertyDefn);
- continue;
- }
- Name name = nameFactory.create(nameString);
- if (propertyDefn.isMultiple()) {
- PropertyDefinition prev = mvPropertyDefinitionsByPropertyName.put(name, propertyDefn);
- if (prev != null) mvPropertyDefinitionsByPropertyName.put(name, prev); // put the first one back ...
- } else {
- PropertyDefinition prev = svPropertyDefinitionsByPropertyName.put(name, propertyDefn);
- if (prev != null) svPropertyDefinitionsByPropertyName.put(name, prev); // put the first one back ...
- }
- }
+ JcrNodeType mixinType = nodeTypes().getNodeType(mixinTypeName);
+ if (mixinType == null) continue;
+ if (!referenceable && mixinType.isNodeType(JcrMixLexicon.REFERENCEABLE)) referenceable = true;
}
}
@@ -1344,47 +1297,25 @@
Name name = dnaProp.getName();
// Figure out the JCR property type for this property ...
- PropertyDefinition propertyDefinition;
- if (dnaProp.isMultiple()) {
- propertyDefinition = mvPropertyDefinitionsByPropertyName.get(name);
- } else {
- propertyDefinition = svPropertyDefinitionsByPropertyName.get(name);
+ int propertyType = JcrSession.jcrPropertyTypeFor(dnaProp);
+ PropertyDefinition propertyDefinition = findBestPropertyDefintion(primaryTypeName,
+ mixinTypeNames,
+ dnaProp,
+ propertyType,
+ false);
- // If the property has only one value, dnaProp.isMultiple() will return false, but the
- // property may actually be a multi-valued property that happens to have one property set.
- if (propertyDefinition == null) {
- propertyDefinition = mvPropertyDefinitionsByPropertyName.get(name);
- }
- }
-
- // If no property type was found for this property, see if there is a wildcard property ...
- if (propertyDefinition == null) {
- for (Iterator<PropertyDefinition> iter = anyPropertyDefinitions.iterator(); iter.hasNext();) {
- PropertyDefinition nextDef = iter.next();
-
- // Grab the first residual definition that matches on cardinality (single-valued vs. multi-valued)
- if ((nextDef.isMultiple() && dnaProp.isMultiple()) || (!nextDef.isMultiple() && !dnaProp.isMultiple())) {
- propertyDefinition = nextDef;
+ // If there still is no property type defined ...
+ if (propertyDefinition == null && INCLUDE_PROPERTIES_NOT_ALLOWED_BY_NODE_TYPE_OR_MIXINS) {
+ // We can use the "nt:unstructured" property definitions for any property ...
+ NodeType unstructured = nodeTypes().getNodeType(JcrNtLexicon.UNSTRUCTURED);
+ for (PropertyDefinition anyDefinition : unstructured.getDeclaredPropertyDefinitions()) {
+ if (anyDefinition.isMultiple()) {
+ propertyDefinition = anyDefinition;
break;
}
}
}
-
- // If there still is no property type defined ...
if (propertyDefinition == null) {
- assert anyPropertyDefinitions.isEmpty();
- if (INCLUDE_PROPERTIES_NOT_ALLOWED_BY_NODE_TYPE_OR_MIXINS) {
- // We can use the "nt:unstructured" property definitions for any property ...
- NodeType unstructured = nodeTypes().getNodeType(JcrNtLexicon.UNSTRUCTURED);
- for (PropertyDefinition anyDefinition : unstructured.getDeclaredPropertyDefinitions()) {
- if (anyDefinition.isMultiple()) {
- propertyDefinition = anyDefinition;
- break;
- }
- }
- }
- }
- if (propertyDefinition == null) {
// We're supposed to skip this property (since we don't have a definition for it) ...
continue;
}
@@ -1397,9 +1328,9 @@
}
// Figure out the property type ...
- int propertyType = propertyDefinition.getRequiredType();
- if (propertyType == PropertyType.UNDEFINED) {
- propertyType = JcrSession.jcrPropertyTypeFor(dnaProp);
+ int definitionType = propertyDefinition.getRequiredType();
+ if (definitionType != PropertyType.UNDEFINED) {
+ propertyType = definitionType;
}
// Record the property in the node information ...
@@ -1412,7 +1343,13 @@
// Now add the "jcr:uuid" property if and only if referenceable ...
if (referenceable) {
// We know that this property is single-valued
- PropertyDefinition propertyDefinition = svPropertyDefinitionsByPropertyName.get(JcrLexicon.UUID);
+ JcrValue value = new JcrValue(context.getValueFactories(), this, PropertyType.STRING, uuid);
+ PropertyDefinition propertyDefinition = nodeTypes().findPropertyDefinition(primaryTypeName,
+ mixinTypeNames,
+ JcrLexicon.UUID,
+ value,
+ false,
+ false);
PropertyId propId = new PropertyId(uuid, JcrLexicon.UUID);
JcrPropertyDefinition defn = (JcrPropertyDefinition)propertyDefinition;
PropertyInfo propInfo = new PropertyInfo(propId, defn.getId(), PropertyType.STRING, uuidProperty, defn.isMultiple());
@@ -1433,31 +1370,6 @@
}
/**
- * Utility method to find the {@link NodeDefinition} for a child node with the supplied {@link Name name}, parent information,
- * and the primary node type of the child.
- *
- * @param parentInfo the parent information; may not be null
- * @param childName the name of the child node (without any same-name-sibling index); may not be null
- * @param primaryTypeOfChild the name of the child's primary type
- * @return the node definition for this child, as best as can be determined, or null if the node definition could not be
- * determined
- * @throws RepositoryException if the parent's primary node type cannot be found in the {@link NodeTypeManager}
- */
- protected JcrNodeDefinition findNodeDefinitionForChild( NodeInfo parentInfo,
- Name childName,
- Name primaryTypeOfChild ) throws RepositoryException {
- // Get the primary type of the parent, and look at it's child definitions ...
- Name primaryTypeName = parentInfo.getPrimaryTypeName();
- JcrNodeType primaryType = nodeTypes().getNodeType(primaryTypeName);
- if (primaryType == null) {
- String msg = JcrI18n.missingNodeTypeForExistingNode.text(primaryTypeName, parentInfo.getUuid(), workspaceName);
- throw new RepositoryException(msg);
- }
- // TODO: should this also check the mixins?
- return primaryType.findBestNodeDefinitionForChild(childName, primaryTypeOfChild);
- }
-
- /**
* This method finds the {@link NodeInfo} for the node with the supplied UUID and marks it as being deleted, and does the same
* for all decendants (e.g., children, grandchildren, great-grandchildren, etc.) that have been cached or changed.
* <p>
@@ -1498,31 +1410,4 @@
}
return numDeleted;
}
-
- /**
- * Find the best {@link JcrNodeDefinition child definition} for a child with the specified name given the named primary type
- * and mixin types.
- *
- * @param childName the name of the child that is to be added
- * @param childPrimaryTypeName the name of the child's primary type, or null if the child's primary type is not known
- * @param requiresMultipleSns true if there is at least one existing child with the same name, requiring the child node type
- * to allow same-name-siblings, or false if the child will be the first child with the supplied name
- * @param primaryTypeName the name of the primary type for the parent; may not be null
- * @param mixinTypeNames the names of the mixin types for the parent; may be null or empty if the parent has no mixins
- * @return the child node definition that can be used (which may be a residual definition), or null if there is no such node
- * type
- */
- protected JcrNodeDefinition findBestChildDefinition( Name childName,
- Name childPrimaryTypeName,
- boolean requiresMultipleSns,
- Name primaryTypeName,
- Collection<Name> mixinTypeNames ) {
- // First check the primary type for a child definition with the supplied name ...
- JcrNodeType primaryType = nodeTypes().getNodeType(primaryTypeName);
- JcrNodeDefinition definition = primaryType.findBestNodeDefinitionForChild(childName, childPrimaryTypeName);
- if (definition != null) {
- // definition.
- }
- return null;
- }
}
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/cache/ChangedNodeInfo.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/cache/ChangedNodeInfo.java 2009-03-23 20:41:31 UTC (rev 787)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/cache/ChangedNodeInfo.java 2009-03-24 02:16:34 UTC (rev 788)
@@ -25,6 +25,8 @@
import java.util.HashMap;
import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
@@ -74,7 +76,7 @@
* The updated list of mixin node type names. This is merely a cached version of what's already in the
* {@link JcrLexicon#MIXIN_TYPES "jcr:mixinTypes"} property.
*/
- private Set<Name> changedMixinTypeNames;
+ private List<Name> changedMixinTypeNames;
/**
* The updated node definition, which may be changed when this node is moved to a different parent (with a different node
@@ -152,7 +154,7 @@
*
* @see org.jboss.dna.jcr.cache.NodeInfo#getMixinTypeNames()
*/
- public Set<Name> getMixinTypeNames() {
+ public List<Name> getMixinTypeNames() {
if (changedMixinTypeNames != null) return changedMixinTypeNames;
return original.getMixinTypeNames();
}
@@ -335,7 +337,7 @@
// If this property was the "jcr:mixinTypes" property, update the cached values ...
if (name.equals(JcrLexicon.MIXIN_TYPES)) {
if (changedMixinTypeNames == null) {
- changedMixinTypeNames = new HashSet<Name>();
+ changedMixinTypeNames = new LinkedList<Name>();
} else {
changedMixinTypeNames.clear();
}
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/cache/ImmutableNodeInfo.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/cache/ImmutableNodeInfo.java 2009-03-23 20:41:31 UTC (rev 787)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/cache/ImmutableNodeInfo.java 2009-03-24 02:16:34 UTC (rev 788)
@@ -24,6 +24,7 @@
package org.jboss.dna.jcr.cache;
import java.util.Collections;
+import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
@@ -44,7 +45,7 @@
private final NodeDefinitionId definition;
private final Children children;
private final Map<Name, PropertyInfo> properties;
- private final Set<Name> mixinTypeNames;
+ private final List<Name> mixinTypeNames;
/**
* Create an immutable NodeInfo instance.
@@ -59,7 +60,7 @@
*/
public ImmutableNodeInfo( Location originalLocation,
Name primaryTypeName,
- Set<Name> mixinTypeNames,
+ List<Name> mixinTypeNames,
NodeDefinitionId definition,
UUID parent,
Children children,
@@ -70,10 +71,8 @@
this.parent = parent;
this.uuid = this.originalLocation.getUuid();
this.children = children != null ? children : new EmptyChildren(this.uuid);
- if (properties == null) properties = Collections.emptyMap();
- this.properties = properties;
- if (mixinTypeNames == null) mixinTypeNames = Collections.emptySet();
- this.mixinTypeNames = mixinTypeNames;
+ this.properties = properties != null ? properties : Collections.<Name, PropertyInfo>emptyMap();
+ this.mixinTypeNames = mixinTypeNames != null ? mixinTypeNames : Collections.<Name>emptyList();
assert this.uuid != null;
assert this.definition != null;
assert this.primaryTypeName != null;
@@ -123,7 +122,7 @@
*
* @see org.jboss.dna.jcr.cache.NodeInfo#getMixinTypeNames()
*/
- public Set<Name> getMixinTypeNames() {
+ public List<Name> getMixinTypeNames() {
return mixinTypeNames;
}
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/cache/NodeInfo.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/cache/NodeInfo.java 2009-03-23 20:41:31 UTC (rev 787)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/cache/NodeInfo.java 2009-03-24 02:16:34 UTC (rev 788)
@@ -23,6 +23,7 @@
*/
package org.jboss.dna.jcr.cache;
+import java.util.List;
import java.util.Set;
import java.util.UUID;
import org.jboss.dna.graph.Location;
@@ -57,9 +58,9 @@
/**
* Get the names of the mixin types for this node.
*
- * @return the unmodifiable set of mixin type names; never null but possibly empty
+ * @return the unmodifiable list of mixin type names; never null but possibly empty
*/
- public Set<Name> getMixinTypeNames();
+ public List<Name> getMixinTypeNames();
/**
* @return definition
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrMultiValuePropertyTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrMultiValuePropertyTest.java 2009-03-23 20:41:31 UTC (rev 787)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrMultiValuePropertyTest.java 2009-03-24 02:16:34 UTC (rev 788)
@@ -71,8 +71,9 @@
dnaProperty = executionContext.getPropertyFactory().create(JcrLexicon.MIMETYPE, true);
stub(definition.getRequiredType()).toReturn(PropertyType.BOOLEAN);
stub(definition.isMultiple()).toReturn(true);
- PropertyDefinitionId definitionId = new PropertyDefinitionId(name("nodeTypeName"), name("propDefnName"));
- stub(nodeTypes.getPropertyDefinition(definitionId, true)).toReturn(definition);
+ PropertyDefinitionId definitionId = new PropertyDefinitionId(name("nodeTypeName"), name("propDefnName"),
+ PropertyType.BOOLEAN, true);
+ stub(nodeTypes.getPropertyDefinition(definitionId)).toReturn(definition);
UUID uuid = UUID.randomUUID();
propertyId = new PropertyId(uuid, JcrLexicon.MIMETYPE);
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrPropertyDefinitionTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrPropertyDefinitionTest.java 2009-03-23 20:41:31 UTC (rev 787)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrPropertyDefinitionTest.java 2009-03-24 02:16:34 UTC (rev 788)
@@ -232,11 +232,10 @@
return true;
}
- @Test( expected = AssertionError.class )
- public void shouldNotAllowNullValue() throws Exception {
+ @Test
+ public void shouldAllowNullValue() throws Exception {
NodeType constrainedType = validateTypeDefinition();
JcrPropertyDefinition prop = propertyDefinitionFor(constrainedType, TestLexicon.CONSTRAINED_BINARY);
-
assertThat(prop.satisfiesConstraints((Value)null), is(false));
}
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrSessionTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrSessionTest.java 2009-03-23 20:41:31 UTC (rev 787)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrSessionTest.java 2009-03-24 02:16:34 UTC (rev 788)
@@ -131,13 +131,13 @@
nodeTypes = new JcrBuiltinNodeTypeSource(context, nodeTypes);
nodeTypes = new DnaBuiltinNodeTypeSource(context, nodeTypes);
repoTypeManager = new RepositoryNodeTypeManager(context, nodeTypes);
-
+
// Stub out the repository, since we only need a few methods ...
MockitoAnnotations.initMocks(this);
stub(repository.getRepositorySourceName()).toReturn(repositorySourceName);
stub(repository.getConnectionFactory()).toReturn(connectionFactory);
stub(repository.getRepositoryTypeManager()).toReturn(repoTypeManager);
-
+
// Set up the session attributes ...
sessionAttributes = new HashMap<String, Object>();
sessionAttributes.put("attribute1", "value1");
@@ -308,7 +308,7 @@
}
@Test
- public void shouldProvideItemsByPath() throws Exception {
+ public void shouldProvideChildrenByPath() throws Exception {
Item item = session.getItem("/a");
assertThat(item, instanceOf(Node.class));
item = session.getItem("/a/b");
@@ -318,6 +318,12 @@
}
@Test
+ public void shouldProvidePropertiesByPath() throws Exception {
+ Item item = session.getItem("/a/b/booleanProperty");
+ assertThat(item, instanceOf(Property.class));
+ }
+
+ @Test
public void shouldProvideValueFactory() throws Exception {
ValueFactory factory = session.getValueFactory();
assertThat(factory, notNullValue());
@@ -417,7 +423,7 @@
NodeType rootNodePrimaryType = rootNode.getPrimaryNodeType();
NodeType dnaRootType = session.nodeTypeManager().getNodeType(DnaLexicon.ROOT);
-
+
assertThat(rootNodePrimaryType.getName(), is(dnaRootType.getName()));
}
@@ -431,7 +437,8 @@
public void rootNodeShouldBeReferenceable() throws RepositoryException {
Node rootNode = session.getRootNode();
- assertTrue(rootNode.getPrimaryNodeType().isNodeType(JcrMixLexicon.REFERENCEABLE.getString(context.getNamespaceRegistry())));
+ assertTrue(rootNode.getPrimaryNodeType()
+ .isNodeType(JcrMixLexicon.REFERENCEABLE.getString(context.getNamespaceRegistry())));
}
@Test
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrSingleValuePropertyTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrSingleValuePropertyTest.java 2009-03-23 20:41:31 UTC (rev 787)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrSingleValuePropertyTest.java 2009-03-24 02:16:34 UTC (rev 788)
@@ -77,8 +77,9 @@
dnaProperty = executionContext.getPropertyFactory().create(JcrLexicon.MIMETYPE, "text/plain");
stub(definition.getRequiredType()).toReturn(PropertyType.STRING);
stub(definition.isMultiple()).toReturn(false);
- PropertyDefinitionId definitionId = new PropertyDefinitionId(name("nodeTypeName"), name("propDefnName"));
- stub(nodeTypes.getPropertyDefinition(definitionId, false)).toReturn(definition);
+ PropertyDefinitionId definitionId = new PropertyDefinitionId(name("nodeTypeName"), name("propDefnName"),
+ PropertyType.STRING, false);
+ stub(nodeTypes.getPropertyDefinition(definitionId)).toReturn(definition);
UUID uuid = UUID.randomUUID();
propertyId = new PropertyId(uuid, JcrLexicon.MIMETYPE);
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/SessionCacheTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/SessionCacheTest.java 2009-03-23 20:41:31 UTC (rev 787)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/SessionCacheTest.java 2009-03-24 02:16:34 UTC (rev 788)
@@ -43,7 +43,6 @@
import java.util.Set;
import java.util.UUID;
import javax.jcr.InvalidItemStateException;
-import javax.jcr.nodetype.NodeType;
import org.jboss.dna.common.statistic.Stopwatch;
import org.jboss.dna.common.util.StringUtil;
import org.jboss.dna.graph.ExecutionContext;
@@ -127,12 +126,12 @@
// Add in the "vehix:car" node type (which extends "nt:unstructured") ...
JcrNodeType car = new JcrNodeType(context, (RepositoryNodeTypeManager)null, carName,
- Arrays.asList(new NodeType[] {unstructured}), NO_PRIMARY_ITEM_NAME, NO_CHILD_NODES,
- NO_PROPERTIES, NOT_MIXIN, ORDERABLE_CHILD_NODES);
+ Arrays.asList(new JcrNodeType[] {unstructured}), NO_PRIMARY_ITEM_NAME,
+ NO_CHILD_NODES, NO_PROPERTIES, NOT_MIXIN, ORDERABLE_CHILD_NODES);
// Add in the "vehix:aircraft" node type (which extends "nt:unstructured") ...
JcrNodeType aircraft = new JcrNodeType(context, (RepositoryNodeTypeManager)null, aircraftName,
- Arrays.asList(new NodeType[] {unstructured}), NO_PRIMARY_ITEM_NAME,
+ Arrays.asList(new JcrNodeType[] {unstructured}), NO_PRIMARY_ITEM_NAME,
NO_CHILD_NODES, NO_PROPERTIES, NOT_MIXIN, ORDERABLE_CHILD_NODES);
primaryNodeTypes.addAll(Arrays.asList(new JcrNodeType[] {car, aircraft,}));
@@ -225,7 +224,20 @@
assertThat(info.getProperty().size(), is(actual.size()));
assertThat(info.getProperty().getValuesAsArray(), is(actual.getValuesAsArray()));
} else {
- assertThat(propertyName, is(JcrLexicon.PRIMARY_TYPE));
+ if (propertyName.equals(JcrLexicon.UUID)) {
+ // check for a DNA UUID property ...
+ actual = dnaNode.getProperty(DnaLexicon.UUID);
+ if (actual != null) {
+ assertThat(info.getProperty().size(), is(actual.size()));
+ assertThat(info.getProperty().getValuesAsArray(), is(actual.getValuesAsArray()));
+ } else {
+ fail("missing property \"" + propertyName + "\" on " + dnaNode);
+ }
+ } else if (propertyName.equals(JcrLexicon.PRIMARY_TYPE)) {
+ // This is okay
+ } else {
+ fail("missing property \"" + propertyName + "\" on " + dnaNode);
+ }
}
}
}
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/TestNodeTypeSource.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/TestNodeTypeSource.java 2009-03-23 20:41:31 UTC (rev 787)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/TestNodeTypeSource.java 2009-03-24 02:16:34 UTC (rev 788)
@@ -28,7 +28,6 @@
import java.util.Collection;
import java.util.List;
import javax.jcr.PropertyType;
-import javax.jcr.nodetype.NodeType;
import org.jboss.dna.graph.ExecutionContext;
/**
@@ -56,17 +55,10 @@
throw new IllegalStateException(JcrI18n.supertypeNotFound.text(baseTypeName, namespaceTypeName));
}
-
-
// Stubbing in child node and property definitions for now
- JcrNodeType constrainedType = new JcrNodeType(
- context,
- NO_NODE_TYPE_MANAGER,
- TestLexicon.CONSTRAINED_TYPE,
- Arrays.asList(new NodeType[] {base}),
- NO_PRIMARY_ITEM_NAME,
- NO_CHILD_NODES,
- Arrays.asList(new JcrPropertyDefinition[] {
+ JcrNodeType constrainedType = new JcrNodeType(context, NO_NODE_TYPE_MANAGER, TestLexicon.CONSTRAINED_TYPE,
+ Arrays.asList(new JcrNodeType[] {base}), NO_PRIMARY_ITEM_NAME,
+ NO_CHILD_NODES, Arrays.asList(new JcrPropertyDefinition[] {
new JcrPropertyDefinition(context, null,
TestLexicon.CONSTRAINED_BINARY,
OnParentVersionBehavior.IGNORE.getJcrValue(),
@@ -104,8 +96,9 @@
OnParentVersionBehavior.IGNORE.getJcrValue(),
false, false, false, NO_DEFAULT_VALUES,
PropertyType.PATH, new String[] {
- // "/" + JcrLexicon.Namespace.URI + ":system/*", "b", "/a/b/c"}, false),
- "/jcr:system/*", "b", "/a/b/c"}, false),
+ // "/" + JcrLexicon.Namespace.URI +
+ // ":system/*", "b", "/a/b/c"}, false),
+ "/jcr:system/*", "b", "/a/b/c"}, false),
new JcrPropertyDefinition(context, null,
TestLexicon.CONSTRAINED_REFERENCE,
OnParentVersionBehavior.IGNORE.getJcrValue(),
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/cache/ChangedNodeInfoTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/cache/ChangedNodeInfoTest.java 2009-03-23 20:41:31 UTC (rev 787)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/cache/ChangedNodeInfoTest.java 2009-03-24 02:16:34 UTC (rev 788)
@@ -37,7 +37,8 @@
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.stub;
import java.util.HashMap;
-import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
@@ -62,11 +63,12 @@
private NodeInfo original;
private UUID uuid;
private Name primaryTypeName;
+ private Name[] requiredPrimaryTypes;
private Location location;
private NodeDefinitionId definitionId;
private ChangedChildren children;
private Map<Name, PropertyInfo> properties;
- private Set<Name> mixinTypeNames;
+ private List<Name> mixinTypeNames;
private ChangedNodeInfo changes;
@Before
@@ -79,10 +81,11 @@
uuid = UUID.randomUUID();
location = Location.create(uuid);
primaryTypeName = name("acme:geniusType");
- definitionId = new NodeDefinitionId(name("acme:geniusContainerType"), name("acme:geniuses"));
+ requiredPrimaryTypes = new Name[] {name("acme:requiredTypeA"), name("acme:requiredTypeB")};
+ definitionId = new NodeDefinitionId(name("acme:geniusContainerType"), name("acme:geniuses"), requiredPrimaryTypes);
children = new ChangedChildren(uuid);
properties = new HashMap<Name, PropertyInfo>();
- mixinTypeNames = new HashSet<Name>();
+ mixinTypeNames = new LinkedList<Name>();
original = new ImmutableNodeInfo(location, primaryTypeName, mixinTypeNames, definitionId, uuid, children, properties);
// Create the changed node representation ...
15 years, 2 months
DNA SVN: r787 - in trunk/dna-graph/src: test/java/org/jboss/dna/graph/property/basic and 1 other directory.
by dna-commits@lists.jboss.org
Author: rhauch
Date: 2009-03-23 16:41:31 -0400 (Mon, 23 Mar 2009)
New Revision: 787
Modified:
trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/BasicName.java
trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/BasicNameTest.java
Log:
DNA-333 BasicName.getString Doesn't Use Provided TextEncoder When the Name Has No Namespace
Applied the patch that corrects BasicName to use the encoder if suppliedto getString(), specifically when the name contains no namespace (e.g., "*"). The patch also changes the behavior of BasicName.getString(TextEncoder) to return the encoded local name ONLY when called. It used to return "{}" + localName.
Verified that all tests pass.
Modified: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/BasicName.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/BasicName.java 2009-03-23 19:31:51 UTC (rev 786)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/BasicName.java 2009-03-23 20:41:31 UTC (rev 787)
@@ -91,7 +91,11 @@
if (this.getLocalName().equals(Path.PARENT)) return Path.PARENT;
}
if (encoder == null) encoder = Path.DEFAULT_ENCODER;
- return "{" + encoder.encode(this.namespaceUri) + "}" + encoder.encode(this.localName);
+
+ if (namespaceUri.length() > 0) {
+ return "{" + encoder.encode(this.namespaceUri) + "}" + encoder.encode(this.localName);
+ }
+ return encoder.encode(this.localName);
}
/**
@@ -117,7 +121,7 @@
if (prefix != null && prefix.length() != 0) {
return encoder.encode(prefix) + ":" + encoder.encode(this.localName);
}
- return this.localName;
+ return encoder.encode(this.localName);
}
/**
@@ -148,7 +152,7 @@
String delim = delimiterEncoder != null ? delimiterEncoder.encode(":") : ":";
return encoder.encode(prefix) + delim + encoder.encode(this.localName);
}
- return this.localName;
+ return encoder.encode(this.localName);
}
/**
Modified: trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/BasicNameTest.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/BasicNameTest.java 2009-03-23 19:31:51 UTC (rev 786)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/BasicNameTest.java 2009-03-23 20:41:31 UTC (rev 787)
@@ -24,6 +24,7 @@
package org.jboss.dna.graph.property.basic;
import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsNot.not;
import static org.junit.Assert.assertThat;
import static org.junit.matchers.JUnitMatchers.containsString;
import org.jboss.dna.common.text.Jsr283Encoder;
@@ -180,7 +181,7 @@
validLocalName = "some:name:with:colons";
name = new BasicName(validNamespaceUri, validLocalName);
result = name.getString(namespaceRegistry, encoder);
- assertThat(result, is("some:name:with:colons"));
+ assertThat(result, is(encoder.encode(validLocalName)));
}
@Test
@@ -191,4 +192,21 @@
assertThat(name.getString(null, encoder, delimiterEncoder), is("\\{" + encoder.encode(DnaLexicon.Namespace.URI)
+ "\\}some\uf03aname\uf03awith\uf03acolons"));
}
+
+ @Test
+ public void shouldEncodeWhenNoNamespace() {
+ String nameForEncoding = "test name";
+ String encodedNameForEncoding = encoder.encode(nameForEncoding);
+ // Make sure that we're not testing a trivial encoding
+ assertThat(encodedNameForEncoding, not(nameForEncoding));
+
+ name = new BasicName(null, nameForEncoding);
+
+ String result = name.getString(namespaceRegistry, encoder);
+ assertThat(result, is(encodedNameForEncoding));
+
+ result = name.getString(encoder);
+ assertThat(result, is(encodedNameForEncoding));
+ }
+
}
15 years, 2 months
DNA SVN: r786 - in trunk/dna-graph/src: test/java/org/jboss/dna/graph/property/basic and 1 other directory.
by dna-commits@lists.jboss.org
Author: rhauch
Date: 2009-03-23 15:31:51 -0400 (Mon, 23 Mar 2009)
New Revision: 786
Modified:
trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/NameValueFactory.java
trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/NameValueFactoryTest.java
Log:
DNA-334 Should not allow creating a Name from a string with multiple non-escaped colons
Changed regular expression used in the NameValueFactory to create values, allowing only a single non-escaped colon in the name. Added a test case to verify that this change indeed was required and has the correct behavior.
Modified: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/NameValueFactory.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/NameValueFactory.java 2009-03-20 18:40:19 UTC (rev 785)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/NameValueFactory.java 2009-03-23 19:31:51 UTC (rev 786)
@@ -62,8 +62,8 @@
protected static final String FULLY_QUALFIED_NAME_PATTERN_STRING = "\\{([^}]*)\\}(.*)";
protected static final Pattern FULLY_QUALIFIED_NAME_PATTERN = Pattern.compile(FULLY_QUALFIED_NAME_PATTERN_STRING);
- // Original pattern: (([^:/]*):)?(.*)
- private static final String PREFIXED_NAME_PATTERN_STRING = "(([^:/]*):)?(.*)";
+ // Original pattern: (([^:/]*):)?([^:]*)
+ private static final String PREFIXED_NAME_PATTERN_STRING = "(([^:/]*):)?([^:]*)";
private static final Pattern PREFIXED_NAME_PATTERN = Pattern.compile(PREFIXED_NAME_PATTERN_STRING);
private static Name BLANK_NAME;
Modified: trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/NameValueFactoryTest.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/NameValueFactoryTest.java 2009-03-20 18:40:19 UTC (rev 785)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/property/basic/NameValueFactoryTest.java 2009-03-23 19:31:51 UTC (rev 786)
@@ -34,6 +34,7 @@
import org.jboss.dna.graph.property.NamespaceRegistry;
import org.jboss.dna.graph.property.Path;
import org.jboss.dna.graph.property.ValueFactory;
+import org.jboss.dna.graph.property.ValueFormatException;
import org.junit.Before;
import org.junit.Test;
@@ -126,6 +127,12 @@
factory.create("a", "", decoder);
}
+ @Test( expected = ValueFormatException.class )
+ public void shouldNotCreateNameFromStringWithMultipleNonEscapedColons() {
+ // This is a requirement of JCR, per the JCR TCK
+ factory.create("a:b:c");
+ }
+
@Test
public void shouldCreateIteratorOverValuesWhenSuppliedIteratorOfUnknownObjects() {
List<String> values = new ArrayList<String>();
15 years, 2 months