DNA SVN: r819 - trunk/dna-jcr/src/main/java/org/jboss/dna/jcr.
by dna-commits@lists.jboss.org
Author: rhauch
Date: 2009-04-13 15:29:46 -0400 (Mon, 13 Apr 2009)
New Revision: 819
Modified:
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/RepositoryNodeTypeManager.java
Log:
DNA-350 RepoistoryNodeTypeManager.findBest*Definition Returns Wrong Definition for Protected Items if skipProtected is True.
Applied the patch.
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/RepositoryNodeTypeManager.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/RepositoryNodeTypeManager.java 2009-04-13 19:27:37 UTC (rev 818)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/RepositoryNodeTypeManager.java 2009-04-13 19:29:46 UTC (rev 819)
@@ -186,7 +186,7 @@
if (primaryType != null) {
for (JcrPropertyDefinition definition : primaryType.allSingleValuePropertyDefinitions(propertyName)) {
// See if the definition allows the value ...
- if (skipProtected && definition.isProtected()) continue;
+ if (skipProtected && definition.isProtected()) return null;
if (setToEmpty) {
if (!definition.isMandatory()) return definition;
// Otherwise this definition doesn't work, so continue with the next ...
@@ -209,7 +209,7 @@
mixinTypes.add(mixinType);
for (JcrPropertyDefinition definition : mixinType.allSingleValuePropertyDefinitions(propertyName)) {
// See if the definition allows the value ...
- if (skipProtected && definition.isProtected()) continue;
+ if (skipProtected && definition.isProtected()) return null;
if (setToEmpty) {
if (!definition.isMandatory()) return definition;
// Otherwise this definition doesn't work, so continue with the next ...
@@ -228,7 +228,7 @@
if (primaryType != null) {
for (JcrPropertyDefinition definition : primaryType.allMultiValuePropertyDefinitions(propertyName)) {
// See if the definition allows the value ...
- if (skipProtected && definition.isProtected()) continue;
+ if (skipProtected && definition.isProtected()) return null;
if (setToEmpty) {
if (!definition.isMandatory()) return definition;
// Otherwise this definition doesn't work, so continue with the next ...
@@ -246,7 +246,7 @@
for (JcrNodeType mixinType : mixinTypes) {
for (JcrPropertyDefinition definition : mixinType.allMultiValuePropertyDefinitions(propertyName)) {
// See if the definition allows the value ...
- if (skipProtected && definition.isProtected()) continue;
+ if (skipProtected && definition.isProtected()) return null;
if (setToEmpty) {
if (!definition.isMandatory()) return definition;
// Otherwise this definition doesn't work, so continue with the next ...
@@ -269,7 +269,7 @@
if (primaryType != null) {
for (JcrPropertyDefinition definition : primaryType.allSingleValuePropertyDefinitions(propertyName)) {
// See if the definition allows the value ...
- if (skipProtected && definition.isProtected()) continue;
+ if (skipProtected && definition.isProtected()) return null;
assert definition.getRequiredType() != PropertyType.UNDEFINED;
if (definition.canCastToTypeAndSatisfyConstraints(value)) return definition;
}
@@ -280,7 +280,7 @@
for (JcrNodeType mixinType : mixinTypes) {
for (JcrPropertyDefinition definition : mixinType.allSingleValuePropertyDefinitions(propertyName)) {
// See if the definition allows the value ...
- if (skipProtected && definition.isProtected()) continue;
+ if (skipProtected && definition.isProtected()) return null;
assert definition.getRequiredType() != PropertyType.UNDEFINED;
if (definition.canCastToTypeAndSatisfyConstraints(value)) return definition;
}
@@ -292,7 +292,7 @@
if (primaryType != null) {
for (JcrPropertyDefinition definition : primaryType.allMultiValuePropertyDefinitions(propertyName)) {
// See if the definition allows the value ...
- if (skipProtected && definition.isProtected()) continue;
+ if (skipProtected && definition.isProtected()) return null;
assert definition.getRequiredType() != PropertyType.UNDEFINED;
if (definition.canCastToTypeAndSatisfyConstraints(value)) return definition;
}
@@ -303,7 +303,7 @@
for (JcrNodeType mixinType : mixinTypes) {
for (JcrPropertyDefinition definition : mixinType.allMultiValuePropertyDefinitions(propertyName)) {
// See if the definition allows the value ...
- if (skipProtected && definition.isProtected()) continue;
+ if (skipProtected && definition.isProtected()) return null;
assert definition.getRequiredType() != PropertyType.UNDEFINED;
if (definition.canCastToTypeAndSatisfyConstraints(value)) return definition;
}
@@ -378,7 +378,7 @@
if (primaryType != null) {
for (JcrPropertyDefinition definition : primaryType.allMultiValuePropertyDefinitions(propertyName)) {
// See if the definition allows the value ...
- if (skipProtected && definition.isProtected()) continue;
+ if (skipProtected && definition.isProtected()) return null;
if (setToEmpty) {
if (!definition.isMandatory()) return definition;
// Otherwise this definition doesn't work, so continue with the next ...
@@ -402,7 +402,7 @@
mixinTypes.add(mixinType);
for (JcrPropertyDefinition definition : mixinType.allMultiValuePropertyDefinitions(propertyName)) {
// See if the definition allows the value ...
- if (skipProtected && definition.isProtected()) continue;
+ if (skipProtected && definition.isProtected()) return null;
if (setToEmpty) {
if (!definition.isMandatory()) return definition;
// Otherwise this definition doesn't work, so continue with the next ...
@@ -425,7 +425,7 @@
if (primaryType != null) {
for (JcrPropertyDefinition definition : primaryType.allMultiValuePropertyDefinitions(propertyName)) {
// See if the definition allows the value ...
- if (skipProtected && definition.isProtected()) continue;
+ if (skipProtected && definition.isProtected()) return null;
assert definition.getRequiredType() != PropertyType.UNDEFINED;
if (definition.canCastToTypeAndSatisfyConstraints(values)) return definition;
}
@@ -436,7 +436,7 @@
for (JcrNodeType mixinType : mixinTypes) {
for (JcrPropertyDefinition definition : mixinType.allMultiValuePropertyDefinitions(propertyName)) {
// See if the definition allows the value ...
- if (skipProtected && definition.isProtected()) continue;
+ if (skipProtected && definition.isProtected()) return null;
assert definition.getRequiredType() != PropertyType.UNDEFINED;
if (definition.canCastToTypeAndSatisfyConstraints(values)) return definition;
}
@@ -535,7 +535,7 @@
if (primaryType != null) {
for (JcrNodeDefinition definition : primaryType.allChildNodeDefinitions(childName, requireSns)) {
// Skip protected definitions ...
- if (skipProtected && definition.isProtected()) continue;
+ if (skipProtected && definition.isProtected()) return null;
// See if the definition allows a child with the supplied primary type ...
if (definition.allowsChildWithType(childType)) return definition;
}
@@ -548,7 +548,7 @@
if (mixinType == null) continue;
for (JcrNodeDefinition definition : mixinType.allChildNodeDefinitions(childName, requireSns)) {
// Skip protected definitions ...
- if (skipProtected && definition.isProtected()) continue;
+ if (skipProtected && definition.isProtected()) return null;
// See if the definition allows a child with the supplied primary type ...
if (definition.allowsChildWithType(childType)) return definition;
}
16 years, 8 months
DNA SVN: r818 - trunk/dna-jcr/src/main/java/org/jboss/dna/jcr.
by dna-commits@lists.jboss.org
Author: rhauch
Date: 2009-04-13 15:27:37 -0400 (Mon, 13 Apr 2009)
New Revision: 818
Modified:
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/SessionCache.java
Log:
DNA-349 AbstractJcrNode.addNode Does Not Add jcr:uuid Property if Primary Type Extends mix:referenceable
Applied the patch, whic correctly adds the "jcr:uuid" property now.
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-04-13 19:23:31 UTC (rev 817)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/SessionCache.java 2009-04-13 19:27:37 UTC (rev 818)
@@ -881,6 +881,27 @@
Property primaryTypeProp = propertyFactory.create(JcrLexicon.PRIMARY_TYPE, primaryTypeName);
Property nodeDefinitionProp = propertyFactory.create(DnaLexicon.NODE_DEFINITON, definition.getId().getString());
+ // Now add the "jcr:uuid" property if and only if referenceable ...
+ if (primaryType.isNodeType(JcrMixLexicon.REFERENCEABLE)) {
+ if (desiredUuid == null) {
+ desiredUuid = UUID.randomUUID();
+ }
+
+ // We know that this property is single-valued
+ JcrValue value = new JcrValue(factories(), SessionCache.this, PropertyType.STRING, desiredUuid.toString());
+ PropertyDefinition propertyDefinition = nodeTypes().findPropertyDefinition(primaryTypeName,
+ Collections.<Name>emptyList(),
+ JcrLexicon.UUID,
+ value,
+ false,
+ false);
+ PropertyId propId = new PropertyId(desiredUuid, JcrLexicon.UUID);
+ JcrPropertyDefinition defn = (JcrPropertyDefinition)propertyDefinition;
+ org.jboss.dna.graph.property.Property uuidProperty = propertyFactory.create(JcrLexicon.UUID, desiredUuid);
+ PropertyInfo propInfo = new PropertyInfo(propId, defn.getId(), PropertyType.STRING, uuidProperty, defn.isMultiple());
+ properties.put(JcrLexicon.UUID, propInfo);
+ }
+
// Create the property info for the "jcr:primaryType" child property ...
JcrPropertyDefinition primaryTypeDefn = findBestPropertyDefintion(node.getPrimaryTypeName(),
node.getMixinTypeNames(),
16 years, 8 months
DNA SVN: r817 - 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-04-13 15:23:31 -0400 (Mon, 13 Apr 2009)
New Revision: 817
Modified:
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrNode.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/AbstractJcrNodeTest.java
Log:
DNA-348 AbstractJcrNode.checkin and .checkout Throws the Wrong Exception Type
Applied the patch as is, which corrects the exception that is thrown from the methods.
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrNode.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrNode.java 2009-04-13 19:20:51 UTC (rev 816)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrNode.java 2009-04-13 19:23:31 UTC (rev 817)
@@ -1341,21 +1341,21 @@
/**
* {@inheritDoc}
*
- * @throws UnsupportedOperationException always
+ * @throws UnsupportedRepositoryOperationException always
* @see javax.jcr.Node#checkin()
*/
- public final Version checkin() {
- throw new UnsupportedOperationException();
+ public final Version checkin() throws UnsupportedRepositoryOperationException {
+ throw new UnsupportedRepositoryOperationException();
}
/**
* {@inheritDoc}
*
- * @throws UnsupportedOperationException always
+ * @throws UnsupportedRepositoryOperationException always
* @see javax.jcr.Node#checkout()
*/
- public final void checkout() {
- throw new UnsupportedOperationException();
+ public final void checkout() throws UnsupportedRepositoryOperationException {
+ throw new UnsupportedRepositoryOperationException();
}
/**
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/AbstractJcrNodeTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/AbstractJcrNodeTest.java 2009-04-13 19:20:51 UTC (rev 816)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/AbstractJcrNodeTest.java 2009-04-13 19:23:31 UTC (rev 817)
@@ -239,12 +239,12 @@
node.cancelMerge(null);
}
- @Test( expected = UnsupportedOperationException.class )
+ @Test( expected = UnsupportedRepositoryOperationException.class )
public void shoudNotAllowCheckin() throws Exception {
node.checkin();
}
- @Test( expected = UnsupportedOperationException.class )
+ @Test( expected = UnsupportedRepositoryOperationException.class )
public void shoudNotAllowCheckout() throws Exception {
node.checkout();
}
16 years, 8 months
DNA SVN: r816 - 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-04-13 15:20:51 -0400 (Mon, 13 Apr 2009)
New Revision: 816
Modified:
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrQueryManager.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSession.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrWorkspaceTest.java
Log:
DNA-347 JcrQuery.storeAsNode Is Not Implemented
Applied the patch, which implements the JcrQuery.storeAsNode(...) method.
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrQueryManager.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrQueryManager.java 2009-04-13 19:13:43 UTC (rev 815)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrQueryManager.java 2009-04-13 19:20:51 UTC (rev 816)
@@ -26,8 +26,9 @@
import java.util.Arrays;
import javax.jcr.ItemNotFoundException;
import javax.jcr.Node;
+import javax.jcr.PathNotFoundException;
import javax.jcr.RepositoryException;
-import javax.jcr.UnsupportedRepositoryOperationException;
+import javax.jcr.nodetype.ConstraintViolationException;
import javax.jcr.query.InvalidQueryException;
import javax.jcr.query.Query;
import javax.jcr.query.QueryManager;
@@ -64,11 +65,11 @@
* {@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 statement
* @param language
* @param storedNode
* @return A {@code Query} object
- * @throws InvalidQueryException if statement is invalid or language is unsupported.
+ * @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,
@@ -179,8 +180,21 @@
*
* @see javax.jcr.query.Query#storeAsNode(java.lang.String)
*/
- public Node storeAsNode( java.lang.String absPath ) throws UnsupportedRepositoryOperationException {
- throw new UnsupportedRepositoryOperationException();
+ public Node storeAsNode( java.lang.String absPath )
+ throws PathNotFoundException, ConstraintViolationException, RepositoryException {
+ NamespaceRegistry namespaces = this.session.namespaces();
+
+ Path path = session.getExecutionContext().getValueFactories().getPathFactory().create(absPath);
+ Path parentPath = path.getParent();
+
+ Node parentNode = session.getNode(parentPath);
+ Node queryNode = parentNode.addNode(path.relativeTo(parentPath).getString(namespaces),
+ JcrNtLexicon.QUERY.getString(namespaces));
+
+ queryNode.setProperty(JcrLexicon.LANGUAGE.getString(namespaces), this.language);
+ queryNode.setProperty(JcrLexicon.STATEMENT.getString(namespaces), this.statement);
+
+ return queryNode;
}
}
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-04-13 19:13:43 UTC (rev 815)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSession.java 2009-04-13 19:20:51 UTC (rev 816)
@@ -406,6 +406,7 @@
* @throws RepositoryException if there is a problem
*/
Node getNode( Path path ) throws RepositoryException, PathNotFoundException {
+ if (path.isRoot()) return cache.findJcrRootNode();
return cache.findJcrNode(null, path.relativeTo(rootPath));
}
@@ -452,9 +453,7 @@
return new ValueFactory() {
public Value createValue( String value,
- int propertyType )
- throws ValueFormatException
- {
+ int propertyType ) throws ValueFormatException {
return new JcrValue(valueFactories, sessionCache, propertyType, convertValueToType(value, propertyType));
}
@@ -488,8 +487,9 @@
public Value createValue( String value ) {
return new JcrValue(valueFactories, sessionCache, PropertyType.STRING, value);
}
-
- Object convertValueToType(Object value, int toType) throws ValueFormatException {
+
+ Object convertValueToType( Object value,
+ int toType ) throws ValueFormatException {
switch (toType) {
case PropertyType.BOOLEAN:
try {
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrWorkspaceTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrWorkspaceTest.java 2009-04-13 19:13:43 UTC (rev 815)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrWorkspaceTest.java 2009-04-13 19:20:51 UTC (rev 816)
@@ -30,6 +30,9 @@
import java.util.HashMap;
import java.util.Map;
import javax.jcr.NamespaceRegistry;
+import javax.jcr.Node;
+import javax.jcr.query.Query;
+import javax.jcr.query.QueryManager;
import org.jboss.dna.graph.ExecutionContext;
import org.jboss.dna.graph.Graph;
import org.jboss.dna.graph.JcrLexicon;
@@ -56,7 +59,7 @@
@Mock
private JcrRepository repository;
private RepositoryNodeTypeManager repoManager;
-
+
@Before
public void beforeEach() throws Exception {
final String repositorySourceName = "repository";
@@ -94,12 +97,12 @@
// Stub out the repository, since we only need a few methods ...
MockitoAnnotations.initMocks(this);
-
+
JcrNodeTypeSource source = null;
source = new JcrBuiltinNodeTypeSource(context, source);
source = new DnaBuiltinNodeTypeSource(context, source);
repoManager = new RepositoryNodeTypeManager(context, source);
-
+
stub(repository.getRepositorySourceName()).toReturn(repositorySourceName);
stub(repository.getRepositoryTypeManager()).toReturn(repoManager);
stub(repository.getConnectionFactory()).toReturn(connectionFactory);
@@ -174,6 +177,49 @@
}
@Test
+ public void shouldCreateQuery() throws Exception {
+ String statement = "Some query syntax";
+
+ QueryManager queryManager = workspace.getQueryManager();
+ Query query = queryManager.createQuery(statement, Query.XPATH);
+
+ assertThat(query, is(notNullValue()));
+ assertThat(query.getLanguage(), is(Query.XPATH));
+ assertThat(query.getStatement(), is(statement));
+ }
+
+ @Test
+ public void shouldStoreQueryAsNode() throws Exception {
+ String statement = "Some query syntax";
+
+ QueryManager queryManager = workspace.getQueryManager();
+ Query query = queryManager.createQuery(statement, Query.XPATH);
+
+ Node node = query.storeAsNode("/storedQuery");
+ assertThat(node, is(notNullValue()));
+ assertThat(node.getPrimaryNodeType().getName(), is("nt:query"));
+ assertThat(node.getProperty("jcr:language").getString(), is(Query.XPATH));
+ assertThat(node.getProperty("jcr:statement").getString(), is(statement));
+ }
+
+ @Test
+ public void shouldLoadStoredQuery() throws Exception {
+ String statement = "Some query syntax";
+
+ QueryManager queryManager = workspace.getQueryManager();
+ Query query = queryManager.createQuery(statement, Query.XPATH);
+
+ Node node = query.storeAsNode("/storedQuery");
+
+ Query loaded = queryManager.getQuery(node);
+
+ assertThat(loaded, is(notNullValue()));
+ assertThat(loaded.getLanguage(), is(Query.XPATH));
+ assertThat(loaded.getStatement(), is(statement));
+ assertThat(loaded.getStoredQueryPath(), is(node.getPath()));
+ }
+
+ @Test
public void shouldProvideSession() throws Exception {
assertThat(workspace.getSession(), is(notNullValue()));
}
16 years, 8 months
DNA SVN: r815 - 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-04-13 15:13:43 -0400 (Mon, 13 Apr 2009)
New Revision: 815
Modified:
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrNode.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrI18n.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrMultiValueProperty.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
Log:
DNA-346 JR TCK Tests for SetPropertyStringTest and SetPropertyValueTest Fail
Applied the patch, which fixed a couple of minor defects that were keeping the tests from passing as per Javadoc in section 7.1.5 of the 1.0.1 spec:
- Added code to "compact" value arrays, that is, Node.setProperty(String, Value[]) and Node.setProperty(String, Value[], int) should ignore any null values in the value array.
- Added code to throw a ValueFormatException if the values in the value arrays in Node.setProperty(String, Value[]) and Node.setProperty(String, Value[], int) are not all of the same type. The spec permits coercing the values into the type expected by the property, but it does not permit different types of values in the array.
- Added code (AbstractJcrNode.checkCardinalityOfExistingProperty) to throw a ValueFormatException if one attempts to set a multi-valued value onto an existing single-valued array (or vice versa) directly through the node.
A few minor changes were made to the patch, including supplying useful error messages for exceptions, and some minor refactoring of some code to compute the Name object only once.
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrNode.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrNode.java 2009-04-09 20:07:42 UTC (rev 814)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrNode.java 2009-04-13 19:13:43 UTC (rev 815)
@@ -49,6 +49,7 @@
import javax.jcr.RepositoryException;
import javax.jcr.UnsupportedRepositoryOperationException;
import javax.jcr.Value;
+import javax.jcr.ValueFormatException;
import javax.jcr.lock.Lock;
import javax.jcr.lock.LockException;
import javax.jcr.nodetype.ConstraintViolationException;
@@ -68,11 +69,11 @@
import org.jboss.dna.graph.property.NamespaceRegistry;
import org.jboss.dna.graph.property.Path;
import org.jboss.dna.graph.property.ValueFactories;
-import org.jboss.dna.graph.property.ValueFormatException;
import org.jboss.dna.jcr.SessionCache.NodeEditor;
import org.jboss.dna.jcr.cache.ChildNode;
import org.jboss.dna.jcr.cache.Children;
import org.jboss.dna.jcr.cache.NodeInfo;
+import org.jboss.dna.jcr.cache.PropertyInfo;
/**
* An abstract implementation of the JCR {@link Node} interface. Instances of this class are created and managed by the
@@ -151,13 +152,16 @@
final JcrValue[] valuesFrom( int propertyType,
Object[] values ) {
+ /*
+ * Null values in the array are "compacted" (read: ignored) as per section 7.1.6 in the JCR 1.0.1 specification.
+ */
int len = values.length;
ValueFactories factories = cache.factories();
- JcrValue[] results = new JcrValue[values.length];
+ List<JcrValue> results = new ArrayList<JcrValue>(len);
for (int i = 0; i != len; ++i) {
- results[i] = new JcrValue(factories, cache, propertyType, values[i]);
+ if (values[i] != null) results.add(new JcrValue(factories, cache, propertyType, values[i]));
}
- return results;
+ return results.toArray(new JcrValue[results.size()]);
}
@Override
@@ -905,7 +909,7 @@
Path path = null;
try {
path = cache.pathFactory().create(relPath);
- } catch (ValueFormatException e) {
+ } catch (org.jboss.dna.graph.property.ValueFormatException e) {
throw new RepositoryException(JcrI18n.invalidPathParameter.text(relPath, "relPath"));
}
if (path.size() == 0) {
@@ -954,7 +958,7 @@
if (primaryNodeTypeName != null) {
try {
childPrimaryTypeName = cache.nameFactory().create(primaryNodeTypeName);
- } catch (ValueFormatException e) {
+ } catch (org.jboss.dna.graph.property.ValueFormatException e) {
throw new RepositoryException(JcrI18n.invalidNodeTypeNameParameter.text(primaryNodeTypeName,
"primaryNodeTypeName"));
}
@@ -976,6 +980,33 @@
}
/**
+ * Checks whether there is an existing property with this name that does not match the given cardinality. If such a property
+ * exists, a {@code javax.jcr.ValueFormatException} is thrown, as per section 7.1.5 of the JCR 1.0.1 specification.
+ *
+ * @param propertyName the name of the property
+ * @param isMultiple whether the property must have multiple values
+ * @throws javax.jcr.ValueFormatException if the property exists but has the opposite cardinality
+ * @throws RepositoryException if any other error occurs
+ */
+ private void checkCardinalityOfExistingProperty( Name propertyName,
+ boolean isMultiple )
+ throws javax.jcr.ValueFormatException, RepositoryException {
+ // Check for existing single-valued property - can't set multiple values on single-valued property
+ PropertyInfo propInfo = this.nodeInfo().getProperty(propertyName);
+ if (propInfo != null && propInfo.isMultiValued() != isMultiple) {
+ if (isMultiple) {
+ I18n msg = JcrI18n.unableToSetSingleValuedPropertyUsingMultipleValues;
+ throw new ValueFormatException(msg.text(getPath(),
+ propertyName.getString(cache.namespaces),
+ cache.workspaceName()));
+ }
+ I18n msg = JcrI18n.unableToSetMultiValuedPropertyUsingSingleValue;
+ throw new ValueFormatException(msg.text(getPath(), propertyName, cache.workspaceName()));
+ }
+
+ }
+
+ /**
* {@inheritDoc}
*
* @see javax.jcr.Node#setProperty(java.lang.String, boolean)
@@ -983,7 +1014,9 @@
public final Property setProperty( String name,
boolean value )
throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
- return cache.findJcrProperty(editor().setProperty(nameFrom(name), valueFrom(PropertyType.BOOLEAN, value)));
+ Name propertyName = nameFrom(name);
+ checkCardinalityOfExistingProperty(propertyName, false);
+ return cache.findJcrProperty(editor().setProperty(propertyName, valueFrom(PropertyType.BOOLEAN, value)));
}
@@ -999,8 +1032,11 @@
// If there is an existing property, then remove it ...
return removeExistingValuedProperty(name);
}
- return cache.findJcrProperty(editor().setProperty(nameFrom(name), valueFrom(value)));
+ Name propertyName = nameFrom(name);
+ checkCardinalityOfExistingProperty(propertyName, false);
+ return cache.findJcrProperty(editor().setProperty(propertyName, valueFrom(value)));
+
}
/**
@@ -1011,7 +1047,9 @@
public final Property setProperty( String name,
double value )
throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
- return cache.findJcrProperty(editor().setProperty(nameFrom(name), valueFrom(PropertyType.DOUBLE, value)));
+ Name propertyName = nameFrom(name);
+ checkCardinalityOfExistingProperty(propertyName, false);
+ return cache.findJcrProperty(editor().setProperty(propertyName, valueFrom(PropertyType.DOUBLE, value)));
}
@@ -1027,7 +1065,9 @@
// If there is an existing property, then remove it ...
return removeExistingValuedProperty(name);
}
- return cache.findJcrProperty(editor().setProperty(nameFrom(name), valueFrom(value)));
+ Name propertyName = nameFrom(name);
+ checkCardinalityOfExistingProperty(propertyName, false);
+ return cache.findJcrProperty(editor().setProperty(propertyName, valueFrom(value)));
}
/**
@@ -1038,8 +1078,9 @@
public final Property setProperty( String name,
long value )
throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
- return cache.findJcrProperty(editor().setProperty(nameFrom(name), valueFrom(PropertyType.LONG, value)));
-
+ Name propertyName = nameFrom(name);
+ checkCardinalityOfExistingProperty(propertyName, false);
+ return cache.findJcrProperty(editor().setProperty(propertyName, valueFrom(PropertyType.LONG, value)));
}
/**
@@ -1054,7 +1095,10 @@
// If there is an existing property, then remove it ...
return removeExistingValuedProperty(name);
}
- return cache.findJcrProperty(editor().setProperty(nameFrom(name), valueFrom(value)));
+
+ Name propertyName = nameFrom(name);
+ checkCardinalityOfExistingProperty(propertyName, false);
+ return cache.findJcrProperty(editor().setProperty(propertyName, valueFrom(value)));
}
/**
@@ -1069,7 +1113,9 @@
// If there is an existing property, then remove it ...
return removeExistingValuedProperty(name);
}
- return cache.findJcrProperty(editor().setProperty(nameFrom(name), valueFrom(PropertyType.STRING, value)));
+ Name propertyName = nameFrom(name);
+ checkCardinalityOfExistingProperty(propertyName, false);
+ return cache.findJcrProperty(editor().setProperty(propertyName, valueFrom(PropertyType.STRING, value)));
}
/**
@@ -1085,7 +1131,9 @@
// If there is an existing property, then remove it ...
return removeExistingValuedProperty(name);
}
- return cache.findJcrProperty(editor().setProperty(nameFrom(name), valueFrom(type, value)));
+ Name propertyName = nameFrom(name);
+ checkCardinalityOfExistingProperty(propertyName, false);
+ return cache.findJcrProperty(editor().setProperty(propertyName, valueFrom(type, value)));
}
/**
@@ -1100,7 +1148,9 @@
// If there is an existing property, then remove it ...
return removeExistingValuedProperty(name);
}
- return cache.findJcrProperty(editor().setProperty(nameFrom(name), valuesFrom(PropertyType.STRING, values)));
+ Name propertyName = nameFrom(name);
+ checkCardinalityOfExistingProperty(propertyName, true);
+ return cache.findJcrProperty(editor().setProperty(propertyName, valuesFrom(PropertyType.STRING, values)));
}
/**
@@ -1116,7 +1166,9 @@
// If there is an existing property, then remove it ...
return removeExistingValuedProperty(name);
}
- return cache.findJcrProperty(editor().setProperty(nameFrom(name), valuesFrom(type, values)));
+ Name propertyName = nameFrom(name);
+ checkCardinalityOfExistingProperty(propertyName, true);
+ return cache.findJcrProperty(editor().setProperty(propertyName, valuesFrom(type, values)));
}
/**
@@ -1131,7 +1183,9 @@
// If there is an existing property, then remove it ...
return removeExistingValuedProperty(name);
}
- return cache.findJcrProperty(editor().setProperty(nameFrom(name), (JcrValue)value));
+ Name propertyName = nameFrom(name);
+ checkCardinalityOfExistingProperty(propertyName, false);
+ return cache.findJcrProperty(editor().setProperty(propertyName, (JcrValue)value));
}
protected final Property removeExistingValuedProperty( String name )
@@ -1159,7 +1213,9 @@
// If there is an existing property, then remove it ...
return removeExistingValuedProperty(name);
}
- return cache.findJcrProperty(editor().setProperty(nameFrom(name), ((JcrValue)value).asType(type)));
+ Name propertyName = nameFrom(name);
+ checkCardinalityOfExistingProperty(propertyName, false);
+ return cache.findJcrProperty(editor().setProperty(propertyName, ((JcrValue)value).asType(type)));
}
/**
@@ -1180,9 +1236,25 @@
newValues = JcrMultiValueProperty.EMPTY_VALUES;
} else {
List<Value> valuesWithDesiredType = new ArrayList<Value>(len);
+ int expectedType = -1;
for (int i = 0; i != len; ++i) {
Value value = values[i];
if (value == null) continue;
+ if (expectedType == -1) {
+ expectedType = value.getType();
+ } else if (value.getType() != expectedType) {
+ // Make sure the type of each value is the same, as per Javadoc in section 7.1.5 of the JCR 1.0.1 spec
+ StringBuilder sb = new StringBuilder();
+ sb.append('[');
+ for (int j = 0; j != values.length; ++j) {
+ if (j != 0) sb.append(",");
+ sb.append(values[j].toString());
+ }
+ sb.append(']');
+ String propType = PropertyType.nameFromValue(expectedType);
+ I18n msg = JcrI18n.allPropertyValuesMustHaveSameType;
+ throw new ValueFormatException(msg.text(name, values, propType, getPath(), cache.workspaceName()));
+ }
valuesWithDesiredType.add(value);
}
if (valuesWithDesiredType.isEmpty()) {
@@ -1191,8 +1263,11 @@
newValues = valuesWithDesiredType.toArray(new Value[valuesWithDesiredType.size()]);
}
}
+
+ Name propertyName = nameFrom(name);
+ checkCardinalityOfExistingProperty(propertyName, true);
// Set the value, perhaps to an empty array ...
- return cache.findJcrProperty(editor().setProperty(nameFrom(name), newValues));
+ return cache.findJcrProperty(editor().setProperty(propertyName, newValues));
}
/**
@@ -1208,15 +1283,33 @@
// If there is an existing property, then remove it ...
return removeExistingValuedProperty(name);
}
+
int len = values.length;
Value[] newValues = null;
if (len == 0) {
newValues = JcrMultiValueProperty.EMPTY_VALUES;
} else {
List<Value> valuesWithDesiredType = new ArrayList<Value>(len);
+ int expectedType = -1;
for (int i = 0; i != len; ++i) {
Value value = values[i];
+
if (value == null) continue;
+ if (expectedType == -1) {
+ expectedType = value.getType();
+ } else if (value.getType() != expectedType) {
+ // Make sure the type of each value is the same, as per Javadoc in section 7.1.5 of the JCR 1.0.1 spec
+ StringBuilder sb = new StringBuilder();
+ sb.append('[');
+ for (int j = 0; j != values.length; ++j) {
+ if (j != 0) sb.append(",");
+ sb.append(values[j].toString());
+ }
+ sb.append(']');
+ String propType = PropertyType.nameFromValue(expectedType);
+ I18n msg = JcrI18n.allPropertyValuesMustHaveSameType;
+ throw new ValueFormatException(msg.text(name, values, propType, getPath(), cache.workspaceName()));
+ }
if (value.getType() != type) {
value = ((JcrValue)value).asType(type);
}
@@ -1228,8 +1321,11 @@
newValues = valuesWithDesiredType.toArray(new Value[valuesWithDesiredType.size()]);
}
}
+
+ Name propertyName = nameFrom(name);
+ checkCardinalityOfExistingProperty(propertyName, true);
// Set the value, perhaps to an empty array ...
- return cache.findJcrProperty(editor().setProperty(nameFrom(name), newValues));
+ return cache.findJcrProperty(editor().setProperty(propertyName, newValues));
}
/**
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-04-09 20:07:42 UTC (rev 814)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrI18n.java 2009-04-13 19:13:43 UTC (rev 815)
@@ -80,6 +80,9 @@
public static I18n unableToCreateNodeWithPrimaryTypeThatDoesNotExist;
public static I18n unableToCreateNodeWithNoDefaultPrimaryTypeOnChildNodeDefinition;
public static I18n unableToSaveNodeThatWasCreatedSincePreviousSave;
+ public static I18n unableToSetMultiValuedPropertyUsingSingleValue;
+ public static I18n unableToSetSingleValuedPropertyUsingMultipleValues;
+ public static I18n allPropertyValuesMustHaveSameType;
public static I18n unableToRemoveRootNode;
public static I18n unableToMoveNodeToBeChildOfDecendent;
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-04-09 20:07:42 UTC (rev 814)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrMultiValueProperty.java 2009-04-13 19:13:43 UTC (rev 815)
@@ -37,6 +37,7 @@
import javax.jcr.nodetype.ConstraintViolationException;
import javax.jcr.version.VersionException;
import net.jcip.annotations.NotThreadSafe;
+import org.jboss.dna.common.i18n.I18n;
import org.jboss.dna.graph.property.Property;
import org.jboss.dna.graph.property.ValueFactory;
@@ -193,6 +194,7 @@
Value[] newValues = null;
if (values.length != 0) {
int numValues = values.length;
+ int valueType = -1;
List<Value> valuesList = new ArrayList<Value>(numValues);
ValueFactory<?> factory = null;
for (int i = 0; i != numValues; ++i) {
@@ -200,7 +202,24 @@
if (value == null) {
// skip null values ...
continue;
- } else if (value instanceof JcrValue) {
+ }
+ if (valueType == -1) {
+ valueType = value.getType();
+ } else if (value.getType() != valueType) {
+ // Make sure the type of each value is the same, as per Javadoc in section 7.1.5 of the JCR 1.0.1 spec
+ StringBuilder sb = new StringBuilder();
+ sb.append('[');
+ for (int j = 0; j != values.length; ++j) {
+ if (j != 0) sb.append(",");
+ sb.append(values[j].toString());
+ }
+ sb.append(']');
+ String propType = PropertyType.nameFromValue(valueType);
+ I18n msg = JcrI18n.allPropertyValuesMustHaveSameType;
+ throw new ValueFormatException(msg.text(getName(), values, propType, getPath(), cache.workspaceName()));
+ }
+
+ if (value instanceof JcrValue) {
// just use the value ...
valuesList.add(value);
} else {
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-04-09 20:07:42 UTC (rev 814)
+++ trunk/dna-jcr/src/main/resources/org/jboss/dna/jcr/JcrI18n.properties 2009-04-13 19:13:43 UTC (rev 815)
@@ -70,6 +70,9 @@
unableToCreateNodeWithPrimaryTypeThatDoesNotExist = Unable to create child "{1}" in workspace "{2}" because the node type "{0}" does not exist
unableToCreateNodeWithNoDefaultPrimaryTypeOnChildNodeDefinition = Unable to create child "{2}" in workspace "{3}" because the node definition "{0}" on the "{1}" node type has no default primary type
unableToSaveNodeThatWasCreatedSincePreviousSave = Unable to save node "{0}" in workspace "{1}" because it was created since the last save
+unableToSetMultiValuedPropertyUsingSingleValue = Unable to set existing multi-valued property "{0}" on node "{1}" in workspace "{2}" using single-value setter methods
+unableToSetSingleValuedPropertyUsingMultipleValues = Unable to set existing single-valued property "{0}" on node "{1}" in workspace "{2}" using multi-value setter methods
+allPropertyValuesMustHaveSameType = All values of property "{0}" on node "{3}" in workspace "{4}" must all be {2} values (values were: {1})
unableToRemoveRootNode = Unable to remove the root node in workspace "{1}"
unableToMoveNodeToBeChildOfDecendent = Node "{0}" in workspace "{2}" cannot be moved under a decendant node ("{1}")
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-04-09 20:07:42 UTC (rev 814)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckTest.java 2009-04-13 19:13:43 UTC (rev 815)
@@ -50,6 +50,8 @@
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.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;
@@ -183,7 +185,7 @@
// addTestSuite(NodeUUIDTest.class);
// addTestSuite(NodeOrderableChildNodesTest.class);
addTestSuite(PropertyTest.class);
- //
+
addTestSuite(SetValueBinaryTest.class);
addTestSuite(SetValueBooleanTest.class);
addTestSuite(SetValueDateTest.class);
@@ -201,8 +203,8 @@
addTestSuite(SetPropertyInputStreamTest.class);
addTestSuite(SetPropertyLongTest.class);
// addTestSuite(SetPropertyNodeTest.class);
- // addTestSuite(SetPropertyStringTest.class);
- // addTestSuite(SetPropertyValueTest.class);
+ addTestSuite(SetPropertyStringTest.class);
+ addTestSuite(SetPropertyValueTest.class);
addTestSuite(SetPropertyConstraintViolationExceptionTest.class);
// addTestSuite(SetPropertyAssumeTypeTest.class);
//
@@ -210,11 +212,11 @@
// 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);
16 years, 8 months
DNA SVN: r814 - trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic.
by dna-commits@lists.jboss.org
Author: rhauch
Date: 2009-04-09 16:07:42 -0400 (Thu, 09 Apr 2009)
New Revision: 814
Modified:
trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/AbstractBinary.java
Log:
Minor change to the 'toString()' method of AbstractBinary, to no longer include in the resulting string the value of the binary (which could be very large). We're relying upon 'toString()' for a number of error messages (especially in 'dna-jcr').
Modified: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/AbstractBinary.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/AbstractBinary.java 2009-04-08 03:06:01 UTC (rev 813)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/AbstractBinary.java 2009-04-09 20:07:42 UTC (rev 814)
@@ -131,8 +131,10 @@
try {
acquire();
StringBuilder sb = new StringBuilder(super.toString());
- sb.append(" len=").append(getSize()).append("; [");
- sb.append(Base64.encodeBytes(getBytes()));
+ sb.append("binary[");
+ sb.append(getSize());
+ sb.append("] with hash ");
+ sb.append(Base64.encodeBytes(getHash()));
return sb.toString();
} finally {
release();
16 years, 8 months
DNA SVN: r813 - 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-04-07 23:06:01 -0400 (Tue, 07 Apr 2009)
New Revision: 813
Modified:
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrNode.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrMultiValueProperty.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckTest.java
Log:
DNA-345 JcrMultiValueProperty.setValues(null) Doesn't Remove Property
Applied the patch, and also uncommented a few more TCK unit tests after additional corrections to the AbstractJcrNode.setProperty implementations.
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrNode.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrNode.java 2009-04-07 22:28:53 UTC (rev 812)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrNode.java 2009-04-08 03:06:01 UTC (rev 813)
@@ -672,7 +672,8 @@
JcrNodeDefinition match = this.cache.nodeTypes().findChildNodeDefinition(mixinCandidateType.getInternalName(),
Collections.<Name>emptyList(),
nodeName,
- childNode.getPrimaryNodeType().getInternalName(),
+ childNode.getPrimaryNodeType()
+ .getInternalName(),
snsCount,
false);
@@ -996,7 +997,7 @@
throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
if (value == null) {
// If there is an existing property, then remove it ...
- return removeExistingSingleValuedProperty(name);
+ return removeExistingValuedProperty(name);
}
return cache.findJcrProperty(editor().setProperty(nameFrom(name), valueFrom(value)));
@@ -1024,7 +1025,7 @@
throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
if (value == null) {
// If there is an existing property, then remove it ...
- return removeExistingSingleValuedProperty(name);
+ return removeExistingValuedProperty(name);
}
return cache.findJcrProperty(editor().setProperty(nameFrom(name), valueFrom(value)));
}
@@ -1051,7 +1052,7 @@
throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
if (value == null) {
// If there is an existing property, then remove it ...
- return removeExistingSingleValuedProperty(name);
+ return removeExistingValuedProperty(name);
}
return cache.findJcrProperty(editor().setProperty(nameFrom(name), valueFrom(value)));
}
@@ -1066,7 +1067,7 @@
throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
if (value == null) {
// If there is an existing property, then remove it ...
- return removeExistingSingleValuedProperty(name);
+ return removeExistingValuedProperty(name);
}
return cache.findJcrProperty(editor().setProperty(nameFrom(name), valueFrom(PropertyType.STRING, value)));
}
@@ -1082,7 +1083,7 @@
throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
if (value == null) {
// If there is an existing property, then remove it ...
- return removeExistingSingleValuedProperty(name);
+ return removeExistingValuedProperty(name);
}
return cache.findJcrProperty(editor().setProperty(nameFrom(name), valueFrom(type, value)));
}
@@ -1095,6 +1096,10 @@
public final Property setProperty( String name,
String[] values )
throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
+ if (values == null) {
+ // If there is an existing property, then remove it ...
+ return removeExistingValuedProperty(name);
+ }
return cache.findJcrProperty(editor().setProperty(nameFrom(name), valuesFrom(PropertyType.STRING, values)));
}
@@ -1107,6 +1112,10 @@
String[] values,
int type )
throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
+ if (values == null) {
+ // If there is an existing property, then remove it ...
+ return removeExistingValuedProperty(name);
+ }
return cache.findJcrProperty(editor().setProperty(nameFrom(name), valuesFrom(type, values)));
}
@@ -1120,17 +1129,16 @@
throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
if (value == null) {
// If there is an existing property, then remove it ...
- return removeExistingSingleValuedProperty(name);
+ return removeExistingValuedProperty(name);
}
return cache.findJcrProperty(editor().setProperty(nameFrom(name), (JcrValue)value));
}
- protected final Property removeExistingSingleValuedProperty( String name )
+ protected final Property removeExistingValuedProperty( String name )
throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
PropertyId id = new PropertyId(nodeUuid, nameFrom(name));
AbstractJcrProperty property = cache.findJcrProperty(id);
if (property != null) {
- assert !property.isMultiple();
property.remove();
return property;
}
@@ -1147,6 +1155,10 @@
Value value,
int type )
throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
+ if (value == null) {
+ // If there is an existing property, then remove it ...
+ return removeExistingValuedProperty(name);
+ }
return cache.findJcrProperty(editor().setProperty(nameFrom(name), ((JcrValue)value).asType(type)));
}
@@ -1158,7 +1170,29 @@
public final Property setProperty( String name,
Value[] values )
throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
- return cache.findJcrProperty(editor().setProperty(nameFrom(name), values));
+ if (values == null) {
+ // If there is an existing property, then remove it ...
+ return removeExistingValuedProperty(name);
+ }
+ int len = values.length;
+ Value[] newValues = null;
+ if (len == 0) {
+ newValues = JcrMultiValueProperty.EMPTY_VALUES;
+ } else {
+ List<Value> valuesWithDesiredType = new ArrayList<Value>(len);
+ for (int i = 0; i != len; ++i) {
+ Value value = values[i];
+ if (value == null) continue;
+ valuesWithDesiredType.add(value);
+ }
+ if (valuesWithDesiredType.isEmpty()) {
+ newValues = JcrMultiValueProperty.EMPTY_VALUES;
+ } else {
+ newValues = valuesWithDesiredType.toArray(new Value[valuesWithDesiredType.size()]);
+ }
+ }
+ // Set the value, perhaps to an empty array ...
+ return cache.findJcrProperty(editor().setProperty(nameFrom(name), newValues));
}
/**
@@ -1170,6 +1204,10 @@
Value[] values,
int type )
throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
+ if (values == null) {
+ // If there is an existing property, then remove it ...
+ return removeExistingValuedProperty(name);
+ }
int len = values.length;
Value[] newValues = null;
if (len == 0) {
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-04-07 22:28:53 UTC (rev 812)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrMultiValueProperty.java 2009-04-08 03:06:01 UTC (rev 813)
@@ -184,8 +184,14 @@
*/
public final void setValue( Value[] values )
throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
+
+ if (values == null) {
+ this.remove();
+ return;
+ }
+
Value[] newValues = null;
- if (values != null && values.length != 0) {
+ if (values.length != 0) {
int numValues = values.length;
List<Value> valuesList = new ArrayList<Value>(numValues);
ValueFactory<?> factory = null;
@@ -257,8 +263,13 @@
*/
public final void setValue( String[] values )
throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
+ if (values == null) {
+ this.remove();
+ return;
+ }
+
Value[] jcrValues = null;
- if (values != null && values.length != 0) {
+ if (values.length != 0) {
int numValues = values.length;
List<Value> valuesList = new ArrayList<Value>(numValues);
jcrValues = new JcrValue[numValues];
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-04-07 22:28:53 UTC (rev 812)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckTest.java 2009-04-08 03:06:01 UTC (rev 813)
@@ -57,8 +57,16 @@
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.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.jboss.dna.graph.DnaLexicon;
import org.jboss.dna.graph.ExecutionContext;
import org.jboss.dna.graph.Graph;
@@ -182,7 +190,7 @@
addTestSuite(SetValueDoubleTest.class);
addTestSuite(SetValueLongTest.class);
addTestSuite(SetValueReferenceTest.class);
- // addTestSuite(SetValueStringTest.class);
+ addTestSuite(SetValueStringTest.class);
addTestSuite(SetValueConstraintViolationExceptionTest.class);
// addTestSuite(SetValueValueFormatExceptionTest.class);
addTestSuite(SetValueVersionExceptionTest.class);
@@ -207,13 +215,13 @@
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(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);
16 years, 8 months
DNA SVN: r812 - 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-04-07 18:28:53 -0400 (Tue, 07 Apr 2009)
New Revision: 812
Added:
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/MixinTest.java
Modified:
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrNode.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/PropertyTypeUtil.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/SessionCache.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/AbstractJcrNodeTest.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckTest.java
Log:
DNA-343 TCK Tests for Node Mixin Modification Methods Fail
Applied the patch that takes a stab the missing functionality.
In addition to the usual rules required by the JCR 1.0 specification, the canAddMixin and addMixin methods enforce internal consistency by requiring that:
* No properties defined by the mixin type can have the same name as any property defined by the node's primary type or any of its existing mixin types.
* No child nodes defined by the mixin type can have the same name as any child node defined by the node's primary type or any of its existing mixin types.
* If the node has a current residual definition for child nodes and/or properties, all nodes and properties that share a name with a child node definition or property definition from the new mixin type must be compatible with the definition provided by the new mixin type.
The removeMixin imposes the following rule in addition to those required by the JCR 1.0 specification:
* A mixin type can be removed if and only if all of the node's existing child nodes and properties would still have a valid definition from the node's primary type or other mixin types. In practice, this means that either the node must have a residual definition compatible with any of the remaining child nodes or properties that currently use a definition from the to-be-removed mixin type or all of the child nodes and properties that use a definition from the to-be-removed mixin type must be removed prior to calling this method.
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrNode.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrNode.java 2009-04-07 22:22:56 UTC (rev 811)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrNode.java 2009-04-07 22:28:53 UTC (rev 812)
@@ -27,9 +27,12 @@
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
+import java.util.Set;
import java.util.UUID;
import java.util.regex.Pattern;
import javax.jcr.InvalidItemStateException;
@@ -49,6 +52,7 @@
import javax.jcr.lock.Lock;
import javax.jcr.lock.LockException;
import javax.jcr.nodetype.ConstraintViolationException;
+import javax.jcr.nodetype.NoSuchNodeTypeException;
import javax.jcr.nodetype.NodeDefinition;
import javax.jcr.nodetype.NodeType;
import javax.jcr.nodetype.NodeTypeManager;
@@ -224,7 +228,7 @@
* @throws UnsupportedOperationException always
* @see javax.jcr.Node#getPrimaryNodeType()
*/
- public NodeType getPrimaryNodeType() throws RepositoryException {
+ public JcrNodeType getPrimaryNodeType() throws RepositoryException {
Name primaryTypeName = nodeInfo().getPrimaryTypeName();
return session().nodeTypeManager().getNodeType(primaryTypeName);
}
@@ -251,26 +255,6 @@
/**
* {@inheritDoc}
*
- * @return <code>false</code>
- * @see javax.jcr.Node#canAddMixin(java.lang.String)
- */
- public final boolean canAddMixin( String mixinName ) {
- return false;
- }
-
- /**
- * {@inheritDoc}
- *
- * @throws UnsupportedOperationException always
- * @see javax.jcr.Node#removeMixin(java.lang.String)
- */
- public final void removeMixin( String mixinName ) {
- throw new UnsupportedOperationException();
- }
-
- /**
- * {@inheritDoc}
- *
* @see javax.jcr.Node#getPrimaryItem()
*/
public final Item getPrimaryItem() throws RepositoryException {
@@ -604,17 +588,300 @@
/**
* {@inheritDoc}
+ * <p>
+ * <b>DNA Implementation Notes</b>
+ * </p>
+ * <p>
+ * DNA imposes the following additional restrictions on the addition of mixin types in addition to the restrictions provided
+ * by the JCR 1.0 specification:
+ * <ol>
+ * <li>No properties defined by the mixin type can have the same name as any property defined by the node's primary type or
+ * any of its existing mixin types.</li>
+ * <li>No child nodes defined by the mixin type can have the same name as any child node defined by the node's primary type or
+ * any of its existing mixin types.</li>
+ * <li>If the node has a current residual definition for child nodes and/or properties, all nodes and properties that share a
+ * name with a child node definition or property definition from the new mixin type must be compatible with the definition
+ * provided by the new mixin type.</li>
+ * </ol>
+ * </p>
*
- * @throws UnsupportedOperationException always
+ * @see javax.jcr.Node#canAddMixin(java.lang.String)
+ */
+ public final boolean canAddMixin( String mixinName ) throws NoSuchNodeTypeException, RepositoryException {
+ CheckArg.isNotNull(mixinName, "mixinName");
+ CheckArg.isNotZeroLength(mixinName, "mixinName");
+
+ JcrNodeType mixinCandidateType = cache.nodeTypes().getNodeType(mixinName);
+
+ if (this.isLocked()) {
+ return false;
+ }
+
+ if (this.getDefinition().isProtected()) {
+ return false;
+ }
+
+ // TODO: Check access control when that support is added
+ // TODO: Throw VersionException if this node is versionable and checked in or unversionable and the nearest versionable
+ // ancestor is checked in
+
+ NodeType primaryType = this.getPrimaryNodeType();
+ NodeType[] mixinTypes = this.getMixinNodeTypes();
+
+ if (!mixinCandidateType.isMixin()) {
+ return false;
+ }
+
+ if (mixinCandidateType.conflictsWith(primaryType, mixinTypes)) {
+ return false;
+ }
+
+ // ------------------------------------------------------------------------------
+ // Check for any existing properties based on residual definitions that conflict
+ // ------------------------------------------------------------------------------
+ for (JcrPropertyDefinition propertyDefinition : mixinCandidateType.propertyDefinitions()) {
+ AbstractJcrProperty existingProp = cache.findJcrProperty(new PropertyId(nodeUuid,
+ propertyDefinition.getInternalName()));
+ if (existingProp != null) {
+ if (propertyDefinition.isMultiple()) {
+ if (!propertyDefinition.canCastToTypeAndSatisfyConstraints(existingProp.getValues())) {
+ return false;
+ }
+ } else {
+ if (!propertyDefinition.canCastToTypeAndSatisfyConstraints(existingProp.getValue())) {
+ return false;
+ }
+ }
+ }
+ }
+
+ // ------------------------------------------------------------------------------
+ // Check for any existing child nodes based on residual definitions that conflict
+ // ------------------------------------------------------------------------------
+ Set<Name> mixinChildNodeNames = new HashSet<Name>();
+ for (JcrNodeDefinition nodeDefinition : mixinCandidateType.childNodeDefinitions()) {
+ mixinChildNodeNames.add(nodeDefinition.getInternalName());
+ }
+
+ for (Name nodeName : mixinChildNodeNames) {
+ // Need to figure out if the child node requires an SNS definition
+ int snsCount = nodeInfo().getChildren().getCountOfSameNameSiblingsWithName(nodeName);
+
+ for (Iterator<ChildNode> iter = nodeInfo().getChildren().getChildren(nodeName); iter.hasNext();) {
+ AbstractJcrNode childNode = cache.findJcrNode(iter.next().getUuid());
+ JcrNodeDefinition match = this.cache.nodeTypes().findChildNodeDefinition(mixinCandidateType.getInternalName(),
+ Collections.<Name>emptyList(),
+ nodeName,
+ childNode.getPrimaryNodeType().getInternalName(),
+ snsCount,
+ false);
+
+ if (match == null) {
+ return false;
+ }
+ }
+
+ }
+
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * <b>DNA Implementation Notes</b>
+ * </p>
+ * <p>
+ * The criteria noted in {@link #canAddMixin(String)} must be satisifed in addition to the criteria defined in the JCR 1.0
+ * specification.
+ * </p>
+ *
* @see javax.jcr.Node#addMixin(java.lang.String)
*/
- public final void addMixin( String mixinName ) {
- throw new UnsupportedOperationException();
+ public final void addMixin( String mixinName ) throws RepositoryException {
+ CheckArg.isNotNull(mixinName, "mixinName");
+ CheckArg.isNotZeroLength(mixinName, "mixinName");
+
+ JcrNodeType mixinCandidateType = cache.nodeTypes().getNodeType(mixinName);
+
+ // Check this separately since it throws a different type of exception
+ if (this.isLocked()) {
+ throw new LockException();
+ }
+
+ if (!canAddMixin(mixinName)) {
+ throw new ConstraintViolationException();
+ }
+
+ Property existingMixinProperty = getProperty(JcrLexicon.MIXIN_TYPES);
+ Value[] existingMixinValues;
+ if (existingMixinProperty != null) {
+ existingMixinValues = existingMixinProperty.getValues();
+ } else {
+ existingMixinValues = new Value[0];
+ }
+
+ Value[] newMixinValues = new Value[existingMixinValues.length + 1];
+ System.arraycopy(existingMixinValues, 0, newMixinValues, 0, existingMixinValues.length);
+ newMixinValues[newMixinValues.length - 1] = valueFrom(PropertyType.NAME, mixinCandidateType.getInternalName());
+
+ cache.findJcrProperty(editor().setProperty(JcrLexicon.MIXIN_TYPES, newMixinValues, false));
+
+ // ------------------------------------------------------------------------------
+ // Create any auto-created properties/nodes from new type
+ // ------------------------------------------------------------------------------
+
+ for (JcrPropertyDefinition propertyDefinition : mixinCandidateType.propertyDefinitions()) {
+ if (propertyDefinition.isAutoCreated() && !propertyDefinition.isProtected()) {
+ if (null == cache.findJcrProperty(new PropertyId(nodeUuid, propertyDefinition.getInternalName()))) {
+ assert propertyDefinition.getDefaultValues() != null;
+ if (propertyDefinition.isMultiple()) {
+ setProperty(propertyDefinition.getName(), propertyDefinition.getDefaultValues());
+ } else {
+ assert propertyDefinition.getDefaultValues().length == 1;
+ setProperty(propertyDefinition.getName(), propertyDefinition.getDefaultValues()[0]);
+ }
+ }
+ }
+ }
+
+ for (JcrNodeDefinition nodeDefinition : mixinCandidateType.childNodeDefinitions()) {
+ if (nodeDefinition.isAutoCreated() && !nodeDefinition.isProtected()) {
+ Name nodeName = nodeDefinition.getInternalName();
+ if (!nodeInfo().getChildren().getChildren(nodeName).hasNext()) {
+ assert nodeDefinition.getDefaultPrimaryType() != null;
+ editor().createChild(nodeName,
+ (UUID)null,
+ ((JcrNodeType)nodeDefinition.getDefaultPrimaryType()).getInternalName());
+ }
+ }
+ }
+
}
/**
* {@inheritDoc}
+ * <p>
+ * <b>DNA Implementation Notes</b>
+ * </p>
+ * <p>
+ * DNA allows the removal of a mixin type if and only if all of the node's existing child nodes and properties would still
+ * have a valid definition from the node's primary type or other mixin types. In practice, this means that either the node
+ * must have a residual definition compatible with any of the remaining child nodes or properties that currently use a
+ * definition from the to-be-removed mixin type or all of the child nodes and properties that use a definition from the
+ * to-be-removed mixin type must be removed prior to calling this method.
+ * </p>
+ * *
*
+ * @see javax.jcr.Node#removeMixin(java.lang.String)
+ */
+ public final void removeMixin( String mixinName ) throws RepositoryException {
+
+ if (this.isLocked()) {
+ throw new LockException();
+ }
+
+ // TODO: Check access control when that support is added
+ // TODO: Throw VersionException if this node is versionable and checked in or unversionable and the nearest versionable
+ // ancestor is checked in
+
+ Property existingMixinProperty = getProperty(JcrLexicon.MIXIN_TYPES);
+
+ if (existingMixinProperty == null) {
+ throw new NoSuchNodeTypeException();
+ }
+
+ Value[] existingMixinValues = existingMixinProperty.getValues();
+
+ if (existingMixinValues.length == 0) {
+ throw new NoSuchNodeTypeException();
+ }
+
+ // ------------------------------------------------------------------------------
+ // Build the new list of mixin types
+ // ------------------------------------------------------------------------------
+
+ int newMixinValuesCount = existingMixinValues.length - 1;
+ Value[] newMixinValues = new Value[newMixinValuesCount];
+ List<Name> newMixinNames = new ArrayList<Name>(newMixinValuesCount);
+ Name primaryTypeName = getPrimaryNodeType().getInternalName();
+
+ int j = 0;
+ for (int i = 0; i < existingMixinValues.length; i++) {
+ if (!existingMixinValues[i].getString().equals(mixinName)) {
+ if (j < newMixinValuesCount) {
+ newMixinValues[j++] = existingMixinValues[i];
+ newMixinNames.add(cache.nameFactory.create(existingMixinValues[i].getString()));
+ } else {
+ throw new NoSuchNodeTypeException();
+ }
+ }
+ }
+
+ // ------------------------------------------------------------------------------
+ // Check that any remaining properties that use the mixin type to be removed
+ // match the residual definition for the node.
+ // ------------------------------------------------------------------------------
+
+ for (PropertyIterator iter = getProperties(); iter.hasNext();) {
+ Property property = iter.nextProperty();
+ if (mixinName.equals(property.getDefinition().getDeclaringNodeType().getName())) {
+ JcrPropertyDefinition match;
+
+ // Only the residual definition would work - if there were any other definition for this name,
+ // the mixin type would not have been added due to the conflict
+ if (property.getDefinition().isMultiple()) {
+ match = cache.nodeTypes().findPropertyDefinition(primaryTypeName,
+ newMixinNames,
+ JcrNodeType.RESIDUAL_NAME,
+ property.getValues(),
+ true);
+ } else {
+ match = cache.nodeTypes().findPropertyDefinition(primaryTypeName,
+ newMixinNames,
+ JcrNodeType.RESIDUAL_NAME,
+ property.getValue(),
+ true,
+ true);
+ }
+
+ if (match == null) {
+ throw new ConstraintViolationException();
+ }
+ }
+ }
+
+ // ------------------------------------------------------------------------------
+ // Check that any remaining child nodes that use the mixin type to be removed
+ // match the residual definition for the node.
+ // ------------------------------------------------------------------------------
+ for (NodeIterator iter = getNodes(); iter.hasNext();) {
+ AbstractJcrNode node = (AbstractJcrNode)iter.nextNode();
+ Name childNodeName = cache.nameFactory.create(node.getName());
+ int snsCount = node.nodeInfo().getChildren().getCountOfSameNameSiblingsWithName(childNodeName);
+ if (mixinName.equals(node.getDefinition().getDeclaringNodeType().getName())) {
+ // Only the residual definition would work - if there were any other definition for this name,
+ // the mixin type would not have been added due to the conflict
+ JcrNodeDefinition match = cache.nodeTypes().findChildNodeDefinition(primaryTypeName,
+ newMixinNames,
+ JcrNodeType.RESIDUAL_NAME,
+ node.getPrimaryNodeType().getInternalName(),
+ snsCount,
+ true);
+
+ if (match == null) {
+ throw new ConstraintViolationException();
+ }
+ }
+ }
+
+ cache.findJcrProperty(editor().setProperty(JcrLexicon.MIXIN_TYPES, newMixinValues, false));
+
+ }
+
+ /**
+ * {@inheritDoc}
+ *
* @see javax.jcr.Node#addNode(java.lang.String)
*/
public final Node addNode( String relPath )
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-04-07 22:22:56 UTC (rev 811)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNodeType.java 2009-04-07 22:28:53 UTC (rev 812)
@@ -26,9 +26,11 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
+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 javax.jcr.PropertyType;
import javax.jcr.Value;
@@ -488,4 +490,128 @@
final RepositoryNodeTypeManager nodeTypeManager() {
return nodeTypeManager;
}
+
+ /**
+ * Returns whether this node type is in conflict with the provided primary node type or mixin types.
+ * <p>
+ * A node type is in conflict with another set of node types if either of the following is true:
+ * <ol>
+ * <li>This node type has the same name as any of the other node types</li>
+ * <li>This node type defines a property (or inherits the definition of a property) with the same name as a property defined
+ * in any of the other node types <i>unless</i> this node type and the other node type both inherited the property definition
+ * from the same ancestor node type</li>
+ * <li>This node type defines a child node (or inherits the definition of a child node) with the same name as a child node
+ * defined in any of the other node types <i>unless</i> this node type and the other node type both inherited the child node
+ * definition from the same ancestor node type</li>
+ * </ol>
+ * </p>
+ *
+ * @param primaryNodeType the primary node type to check
+ * @param mixinNodeTypes the mixin node types to check
+ * @return true if this node type conflicts with the provided primary or mixin node types as defined below
+ */
+ final boolean conflictsWith( NodeType primaryNodeType,
+ NodeType[] mixinNodeTypes ) {
+ Map<PropertyDefinitionId, JcrPropertyDefinition> props = new HashMap<PropertyDefinitionId, JcrPropertyDefinition>();
+ /*
+ * Need to have the same parent name for all PropertyDefinitionIds and NodeDefinitionIds as we're checking for conflicts on the definition name
+ */
+ final Name DEFAULT_NAME = this.name;
+
+ for (JcrPropertyDefinition property : propertyDefinitions()) {
+ /*
+ * I'm trying really hard to reuse existing code, but it's a stretch in this case. I don't care about the property
+ * types or where they were declared... if more than one definition with the given name exists (not counting definitions
+ * inherited from the same root definition), then there is a conflict.
+ */
+ PropertyDefinitionId pid = new PropertyDefinitionId(DEFAULT_NAME, property.name, PropertyType.UNDEFINED,
+ property.isMultiple());
+ props.put(pid, property);
+ }
+
+ /*
+ * The specification does not mandate whether this should or should not be consider a conflict. However, the Apache
+ * TCK canRemoveMixin test cases assume that this will generate a conflict.
+ */
+ if (primaryNodeType.getName().equals(getName())) {
+ // This node type has already been applied to the node
+ return true;
+ }
+
+ for (JcrPropertyDefinition property : ((JcrNodeType)primaryNodeType).propertyDefinitions()) {
+ PropertyDefinitionId pid = new PropertyDefinitionId(DEFAULT_NAME, property.name, PropertyType.UNDEFINED,
+ property.isMultiple());
+ JcrPropertyDefinition oldProp = props.put(pid, property);
+ if (oldProp != null) {
+ String oldPropTypeName = oldProp.getDeclaringNodeType().getName();
+ String propTypeName = property.getDeclaringNodeType().getName();
+ if (!oldPropTypeName.equals(propTypeName)) {
+ // The two types conflict as both separately declare a property with the same name
+ return true;
+ }
+ }
+ }
+
+ for (NodeType mixinNodeType : mixinNodeTypes) {
+ /*
+ * The specification does not mandate whether this should or should not be consider a conflict. However, the Apache
+ * TCK canRemoveMixin test cases assume that this will generate a conflict.
+ */
+ if (mixinNodeType.getName().equals(getName())) {
+ // This node type has already been applied to the node
+ return true;
+ }
+
+ for (JcrPropertyDefinition property : ((JcrNodeType)mixinNodeType).propertyDefinitions()) {
+ PropertyDefinitionId pid = new PropertyDefinitionId(DEFAULT_NAME, property.name, PropertyType.UNDEFINED,
+ property.isMultiple());
+ JcrPropertyDefinition oldProp = props.put(pid, property);
+ if (oldProp != null) {
+ String oldPropTypeName = oldProp.getDeclaringNodeType().getName();
+ String propTypeName = property.getDeclaringNodeType().getName();
+ if (!oldPropTypeName.equals(propTypeName)) {
+ // The two types conflict as both separately declare a property with the same name
+ return true;
+ }
+ }
+ }
+ }
+
+ Map<NodeDefinitionId, JcrNodeDefinition> childNodes = new HashMap<NodeDefinitionId, JcrNodeDefinition>();
+
+ for (JcrNodeDefinition childNode : childNodeDefinitions()) {
+ NodeDefinitionId nid = new NodeDefinitionId(DEFAULT_NAME, childNode.name, new Name[0]);
+ childNodes.put(nid, childNode);
+ }
+
+ for (JcrNodeDefinition childNode : ((JcrNodeType)primaryNodeType).childNodeDefinitions()) {
+ NodeDefinitionId nid = new NodeDefinitionId(DEFAULT_NAME, childNode.name, new Name[0]);
+ JcrNodeDefinition oldNode = childNodes.put(nid, childNode);
+ if (oldNode != null) {
+ String oldNodeTypeName = oldNode.getDeclaringNodeType().getName();
+ String childNodeTypeName = childNode.getDeclaringNodeType().getName();
+ if (!oldNodeTypeName.equals(childNodeTypeName)) {
+ // The two types conflict as both separately declare a child node with the same name
+ return true;
+ }
+ }
+ }
+
+ for (NodeType mixinNodeType : mixinNodeTypes) {
+ for (JcrNodeDefinition childNode : ((JcrNodeType)mixinNodeType).childNodeDefinitions()) {
+ NodeDefinitionId nid = new NodeDefinitionId(DEFAULT_NAME, childNode.name, new Name[0]);
+ JcrNodeDefinition oldNode = childNodes.put(nid, childNode);
+ if (oldNode != null) {
+ String oldNodeTypeName = oldNode.getDeclaringNodeType().getName();
+ String childNodeTypeName = childNode.getDeclaringNodeType().getName();
+ if (!oldNodeTypeName.equals(childNodeTypeName)) {
+ // The two types conflict as both separately declare a child node with the same name
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+ }
}
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-04-07 22:22:56 UTC (rev 811)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNodeTypeManager.java 2009-04-07 22:28:53 UTC (rev 812)
@@ -90,7 +90,7 @@
*
* @see javax.jcr.nodetype.NodeTypeManager#getNodeType(java.lang.String)
*/
- public NodeType getNodeType( String nodeTypeName ) throws NoSuchNodeTypeException, RepositoryException {
+ public JcrNodeType getNodeType( String nodeTypeName ) throws NoSuchNodeTypeException, RepositoryException {
Name ntName = context.getValueFactories().getNameFactory().create(nodeTypeName);
JcrNodeType type = repositoryTypeManager.getNodeType(ntName);
if (type != null) {
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/PropertyTypeUtil.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/PropertyTypeUtil.java 2009-04-07 22:22:56 UTC (rev 811)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/PropertyTypeUtil.java 2009-04-07 22:28:53 UTC (rev 812)
@@ -43,6 +43,7 @@
*/
static final int jcrPropertyTypeFor( org.jboss.dna.graph.property.Property property ) {
Object value = property.getFirstValue();
+ if (value == null) return PropertyType.UNDEFINED;
// Get the DNA property type for this ...
switch (org.jboss.dna.graph.property.PropertyType.discoverType(value)) {
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-04-07 22:22:56 UTC (rev 811)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/SessionCache.java 2009-04-07 22:28:53 UTC (rev 812)
@@ -539,6 +539,12 @@
*/
public PropertyId setProperty( Name name,
JcrValue value ) throws ConstraintViolationException {
+ return setProperty(name, value, true);
+ }
+
+ public PropertyId setProperty( Name name,
+ JcrValue value,
+ boolean skipProtected ) throws ConstraintViolationException {
assert name != null;
assert value != null;
JcrPropertyDefinition definition = null;
@@ -576,7 +582,7 @@
name,
value,
true,
- true);
+ skipProtected);
if (definition == null) {
throw new ConstraintViolationException();
}
@@ -607,6 +613,9 @@
/**
* Set the values for the property. If the property does not exist, it will be added. If the property does exist, the
* existing values will be replaced with those that are supplied.
+ * <p>
+ * This method will not set protected property definitions and should be used in almost all cases.
+ * </p>
*
* @param name the property name; may not be null
* @param values new property values, all of which must have the same {@link Value#getType() property type}; may not be
@@ -617,6 +626,25 @@
*/
public PropertyId setProperty( Name name,
Value[] values ) throws ConstraintViolationException {
+ return setProperty(name, values, true);
+ }
+
+ /**
+ * Set the values for the property. If the property does not exist, it will be added. If the property does exist, the
+ * existing values will be replaced with those that are supplied.
+ *
+ * @param name the property name; may not be null
+ * @param values new property values, all of which must have the same {@link Value#getType() property type}; may not be
+ * null but may be empty
+ * @param skipProtected if true, attempts to set protected properties will fail. If false, attempts to set protected
+ * properties will be allowed.
+ * @return the identifier for the property; never null
+ * @throws ConstraintViolationException if the property could not be set because of a node type constraint or property
+ * definition constraint
+ */
+ public PropertyId setProperty( Name name,
+ Value[] values,
+ boolean skipProtected ) throws ConstraintViolationException {
assert name != null;
assert values != null;
int numValues = values.length;
@@ -660,7 +688,7 @@
node.getMixinTypeNames(),
name,
values,
- true);
+ skipProtected);
if (definition == null) {
throw new ConstraintViolationException();
}
@@ -757,8 +785,8 @@
if (!definition.getId().equals(node.getDefinitionId())) {
// The node definition changed, so try to set the property ...
try {
- JcrValue value = new JcrValue(factories(), SessionCache.this, PropertyType.STRING, definition.getId()
- .getString());
+ JcrValue value = new JcrValue(factories(), 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).
@@ -887,10 +915,7 @@
// ---------------------------------------
// Now record the changes to the store ...
// ---------------------------------------
- Graph.Create<Graph.Batch> create = operations.createUnder(currentLocation)
- .nodeNamed(name)
- .with(desiredUuid)
- .with(primaryTypeProp);
+ Graph.Create<Graph.Batch> create = operations.createUnder(currentLocation).nodeNamed(name).with(desiredUuid).with(primaryTypeProp);
if (nodeDefnDefn != null) {
create = create.with(nodeDefinitionProp);
}
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/AbstractJcrNodeTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/AbstractJcrNodeTest.java 2009-04-07 22:22:56 UTC (rev 811)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/AbstractJcrNodeTest.java 2009-04-07 22:28:53 UTC (rev 812)
@@ -229,16 +229,11 @@
node.getProperty("../good/path");
}
- @Test( expected = UnsupportedOperationException.class )
- public void shoudNotAllowAddMixin() throws Exception {
- node.addMixin(null);
- }
+ /*
+ * More comprehensive tests of addMixin, removeMixin, and canAddMixin require additional setup
+ * and are in MixinTest
+ */
- @Test
- public void shoudNotAllowCanAddMixin() throws Exception {
- assertThat(node.canAddMixin(null), is(false));
- }
-
@Test( expected = UnsupportedOperationException.class )
public void shoudNotAllowCancelMerge() throws Exception {
node.cancelMerge(null);
@@ -702,11 +697,6 @@
node.orderBefore(null, null);
}
- @Test( expected = UnsupportedOperationException.class )
- public void shouldNotAllowRemoveMixin() throws Exception {
- node.removeMixin(null);
- }
-
@Test( expected = UnsupportedRepositoryOperationException.class )
public void shouldNotAllowRestoreVersionName() throws Exception {
node.restore((String)null, false);
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-04-07 22:22:56 UTC (rev 811)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckTest.java 2009-04-07 22:28:53 UTC (rev 812)
@@ -38,6 +38,9 @@
import org.apache.jackrabbit.test.RepositoryStub;
import org.apache.jackrabbit.test.api.AddNodeTest;
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.NodeRemoveMixinTest;
import org.apache.jackrabbit.test.api.PropertyTest;
import org.apache.jackrabbit.test.api.RepositoryLoginTest;
import org.apache.jackrabbit.test.api.SessionUUIDTest;
@@ -200,9 +203,9 @@
// addTestSuite(PropertyItemIsModifiedTest.class);
// addTestSuite(PropertyItemIsNewTest.class);
//
- // addTestSuite(NodeAddMixinTest.class);
- // addTestSuite(NodeCanAddMixinTest.class);
- // addTestSuite(NodeRemoveMixinTest.class);
+ addTestSuite(NodeAddMixinTest.class);
+ addTestSuite(NodeCanAddMixinTest.class);
+ addTestSuite(NodeRemoveMixinTest.class);
//
// addTestSuite(WorkspaceCloneReferenceableTest.class);
// addTestSuite(WorkspaceCloneSameNameSibsTest.class);
Added: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/MixinTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/MixinTest.java (rev 0)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/MixinTest.java 2009-04-07 22:28:53 UTC (rev 812)
@@ -0,0 +1,675 @@
+/*
+ * 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.junit.Assert.assertThat;
+import static org.mockito.Mockito.stub;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.EnumMap;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.jcr.Node;
+import javax.jcr.Property;
+import javax.jcr.PropertyType;
+import javax.jcr.Value;
+import javax.jcr.nodetype.ConstraintViolationException;
+import javax.jcr.nodetype.NoSuchNodeTypeException;
+import javax.jcr.version.OnParentVersionAction;
+import org.jboss.dna.graph.ExecutionContext;
+import org.jboss.dna.graph.Graph;
+import org.jboss.dna.graph.connector.RepositoryConnection;
+import org.jboss.dna.graph.connector.RepositoryConnectionFactory;
+import org.jboss.dna.graph.connector.RepositorySourceException;
+import org.jboss.dna.graph.connector.inmemory.InMemoryRepositorySource;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.NamespaceRegistry;
+import org.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;
+
+public class MixinTest {
+
+ /*
+ * Declares the following node types:
+ * mixinTypeA with child node nodeA and property propertyA
+ * mixinTypeB with child node nodeB and property propertyB
+ * mixinTypeC with child node nodeA and property propertyB
+ * mixinTypeWithAutoCreatedProperty with auto-created property propertyB
+ * mixinTypeWithAutoCreatedChildNode with auto-created child node nodeB
+ * mixinTypeC with child node nodeA and property propertyB
+ * primaryTypeA with child node nodeA and property propertyA
+ */
+ static final Name MIXIN_TYPE_A = new BasicName("", "mixinTypeA");
+ static final Name MIXIN_TYPE_B = new BasicName("", "mixinTypeB");
+ static final Name MIXIN_TYPE_C = new BasicName("", "mixinTypeC");
+ static final Name MIXIN_TYPE_WITH_AUTO_PROP = new BasicName("", "mixinTypeWithAutoCreatedProperty");
+ static final Name MIXIN_TYPE_WITH_AUTO_CHILD = new BasicName("", "mixinTypeWithAutoCreatedChildNode");
+ static final Name PRIMARY_TYPE_A = new BasicName("", "mixinTypeA");
+
+ static final Name PROPERTY_A = new BasicName("", "propertyA");
+ static final Name PROPERTY_B = new BasicName("", "propertyB");
+
+ static final Name CHILD_NODE_A = new BasicName("", "nodeA");
+ static final Name CHILD_NODE_B = new BasicName("", "nodeB");
+
+ 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 Map<JcrRepository.Options, String> options;
+ private NamespaceRegistry registry;
+ @Mock
+ private JcrRepository repository;
+
+ @Before
+ public void beforeEach() throws Exception {
+ MockitoAnnotations.initMocks(this);
+
+ workspaceName = "workspace1";
+ final String repositorySourceName = "repository";
+
+ // Set up the source ...
+ source = new InMemoryRepositorySource();
+ source.setName(workspaceName);
+ source.setDefaultWorkspaceName(workspaceName);
+
+ // Set up the execution context ...
+ context = new ExecutionContext();
+ // Register the test namespace
+ context.getNamespaceRegistry().register(TestLexicon.Namespace.PREFIX, TestLexicon.Namespace.URI);
+
+ // Set up the initial content ...
+ graph = Graph.create(source, context);
+
+ // Make sure the path to the namespaces exists ...
+ graph.create("/jcr:system"); // .and().create("/jcr:system/dna:namespaces");
+ graph.set("jcr:primaryType").on("/jcr:system").to(DnaLexicon.SYSTEM);
+
+ // 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);
+
+ // Stub out the repository options ...
+ options = new EnumMap<JcrRepository.Options, String>(JcrRepository.Options.class);
+ options.put(JcrRepository.Options.PROJECT_NODE_TYPES, Boolean.FALSE.toString());
+ stub(repository.getOptions()).toReturn(options);
+
+ // 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();
+ registry = session.getExecutionContext().getNamespaceRegistry();
+ }
+
+ @After
+ public void after() throws Exception {
+ if (session != null && session.isLive()) {
+ session.logout();
+ }
+ }
+
+ @Test( expected = IllegalArgumentException.class )
+ public void shouldNotAllowNullMixinTypeName() throws Exception {
+ graph.create("/a");
+ graph.set("jcr:primaryType").on("/a").to(PRIMARY_TYPE_A);
+
+ Node rootNode = session.getRootNode();
+ Node nodeA = rootNode.getNode("a");
+
+ nodeA.canAddMixin(null);
+ }
+
+ @Test( expected = IllegalArgumentException.class )
+ public void shouldNotAllowEmptyMixinTypeName() throws Exception {
+ graph.create("/a");
+ graph.set("jcr:primaryType").on("/a").to(PRIMARY_TYPE_A);
+
+ Node rootNode = session.getRootNode();
+ Node nodeA = rootNode.getNode("a");
+
+ nodeA.canAddMixin("");
+ }
+
+ @Test( expected = NoSuchNodeTypeException.class )
+ public void shouldNotAllowInvalidMixinTypeName() throws Exception {
+ graph.create("/a");
+ graph.set(JcrLexicon.PRIMARY_TYPE.getString(registry)).on("/a").to(PRIMARY_TYPE_A);
+
+ Node rootNode = session.getRootNode();
+ Node nodeA = rootNode.getNode("a");
+
+ nodeA.canAddMixin("foo");
+ }
+
+ @Test
+ public void shouldNotAllowAddingMixinToProtectedNodes() throws Exception {
+ Node rootNode = session.getRootNode();
+ Node systemNode = rootNode.getNode(JcrLexicon.SYSTEM.getString(registry));
+
+ assertThat(systemNode.getDefinition().isProtected(), is(true));
+ assertThat(systemNode.canAddMixin(JcrMixLexicon.VERSIONABLE.getString(registry)), is(false));
+ }
+
+ @Test
+ public void shouldAllowAddingMixinIfNoConflict() throws Exception {
+ graph.create("/a");
+ graph.set(JcrLexicon.PRIMARY_TYPE.getString(registry)).on("/a").to(PRIMARY_TYPE_A);
+ graph.set(JcrLexicon.MIXIN_TYPES.getString(registry)).on("/a").to(JcrMixLexicon.REFERENCEABLE.getString(registry));
+
+ Node rootNode = session.getRootNode();
+ Node nodeA = rootNode.getNode("a");
+
+ assertThat(nodeA.canAddMixin(MIXIN_TYPE_B.getString(registry)), is(true));
+ }
+
+ @Test
+ public void shouldNotAllowAddingMixinIfPrimaryTypeConflicts() throws Exception {
+ graph.create("/a");
+ graph.set(JcrLexicon.PRIMARY_TYPE.getString(registry)).on("/a").to(PRIMARY_TYPE_A);
+ graph.set(JcrLexicon.MIXIN_TYPES.getString(registry)).on("/a").to(JcrMixLexicon.REFERENCEABLE.getString(registry));
+
+ Node rootNode = session.getRootNode();
+ Node nodeA = rootNode.getNode("a");
+
+ assertThat(nodeA.canAddMixin(MIXIN_TYPE_C.getString(registry)), is(false));
+ }
+
+ @Test
+ public void shouldNotAllowAddingMixinIfMixinTypeConflicts() throws Exception {
+ graph.create("/a");
+ graph.set(JcrLexicon.PRIMARY_TYPE.getString(registry)).on("/a").to(JcrNtLexicon.BASE.getString(registry));
+ graph.set(JcrLexicon.MIXIN_TYPES.getString(registry)).on("/a").to(MIXIN_TYPE_B);
+
+ Node rootNode = session.getRootNode();
+ Node nodeA = rootNode.getNode("a");
+
+ assertThat(nodeA.canAddMixin(MIXIN_TYPE_C.getString(registry)), is(false));
+ }
+
+ @Test
+ public void shouldAutoCreateAutoCreatedPropertiesOnAddition() throws Exception {
+ graph.create("/a");
+ graph.set(JcrLexicon.PRIMARY_TYPE.getString(registry)).on("/a").to(JcrNtLexicon.BASE.getString(registry));
+
+ Node rootNode = session.getRootNode();
+ Node nodeA = rootNode.getNode("a");
+
+ assertThat(nodeA.canAddMixin(MIXIN_TYPE_WITH_AUTO_PROP.getString(registry)), is(true));
+ nodeA.addMixin(MIXIN_TYPE_WITH_AUTO_PROP.getString(registry));
+ Property prop = nodeA.getProperty(PROPERTY_B.getString(registry));
+
+ assertThat(prop, is(notNullValue()));
+ assertThat(prop.getLong(), is(10L));
+ }
+
+ @Test
+ public void shouldAutoCreateAutoCreatedChildNodesOnAddition() throws Exception {
+ graph.create("/a");
+ graph.set(JcrLexicon.PRIMARY_TYPE.getString(registry)).on("/a").to(JcrNtLexicon.BASE.getString(registry));
+
+ Node rootNode = session.getRootNode();
+ Node nodeA = rootNode.getNode("a");
+
+ assertThat(nodeA.canAddMixin(MIXIN_TYPE_WITH_AUTO_CHILD.getString(registry)), is(true));
+ nodeA.addMixin(MIXIN_TYPE_WITH_AUTO_CHILD.getString(registry));
+ Node childNode = nodeA.getNode(CHILD_NODE_B.getString(registry));
+
+ assertThat(childNode, is(notNullValue()));
+ assertThat(childNode.getPrimaryNodeType().getName(), is(JcrNtLexicon.UNSTRUCTURED.getString(registry)));
+ }
+
+ @Test( expected = ConstraintViolationException.class )
+ public void shouldNotAllowAdditionIfResidualPropertyConflicts() throws Exception {
+ graph.create("/a");
+ graph.set(JcrLexicon.PRIMARY_TYPE.getString(registry)).on("/a").to(JcrNtLexicon.UNSTRUCTURED.getString(registry));
+
+ Node rootNode = session.getRootNode();
+ Node nodeA = rootNode.getNode("a");
+ nodeA.setProperty(PROPERTY_B.getString(registry), "Not a boolean");
+
+ assertThat(nodeA.canAddMixin(MIXIN_TYPE_WITH_AUTO_PROP.getString(registry)), is(false));
+ nodeA.addMixin(MIXIN_TYPE_WITH_AUTO_PROP.getString(registry));
+ }
+
+ @Test
+ public void shouldAllowAdditionIfResidualPropertyDoesNotConflict() throws Exception {
+ graph.create("/a");
+ graph.set(JcrLexicon.PRIMARY_TYPE.getString(registry)).on("/a").to(JcrNtLexicon.UNSTRUCTURED.getString(registry));
+
+ Node rootNode = session.getRootNode();
+ Node nodeA = rootNode.getNode("a");
+ nodeA.setProperty(PROPERTY_B.getString(registry), 10L);
+
+ assertThat(nodeA.canAddMixin(MIXIN_TYPE_WITH_AUTO_PROP.getString(registry)), is(true));
+ nodeA.addMixin(MIXIN_TYPE_WITH_AUTO_PROP.getString(registry));
+ }
+
+ @Test( expected = ConstraintViolationException.class )
+ public void shouldNotAllowAdditionIfResidualChildNodeConflicts() throws Exception {
+ graph.create("/a").and().create("/a/" + CHILD_NODE_B);
+ graph.set(JcrLexicon.PRIMARY_TYPE.getString(registry)).on("/a").to(JcrNtLexicon.UNSTRUCTURED.getString(registry));
+ graph.set(JcrLexicon.PRIMARY_TYPE.getString(registry)).on("/a/" + CHILD_NODE_B).to(JcrNtLexicon.BASE.getString(registry));
+
+ Node rootNode = session.getRootNode();
+ Node nodeA = rootNode.getNode("a");
+
+ assertThat(nodeA.canAddMixin(MIXIN_TYPE_WITH_AUTO_CHILD.getString(registry)), is(false));
+ nodeA.addMixin(MIXIN_TYPE_WITH_AUTO_CHILD.getString(registry));
+ }
+
+ @Test
+ public void shouldAllowAdditionIfResidualChildNodeDoesNotConflict() throws Exception {
+ graph.create("/a").and().create("/a/" + CHILD_NODE_B);
+ graph.set(JcrLexicon.PRIMARY_TYPE.getString(registry)).on("/a").to(JcrNtLexicon.UNSTRUCTURED.getString(registry));
+ graph.set(JcrLexicon.PRIMARY_TYPE.getString(registry)).on("/a/" + CHILD_NODE_B).to(JcrNtLexicon.UNSTRUCTURED.getString(registry));
+
+ Node rootNode = session.getRootNode();
+ Node nodeA = rootNode.getNode("a");
+
+ assertThat(nodeA.canAddMixin(MIXIN_TYPE_WITH_AUTO_CHILD.getString(registry)), is(true));
+ nodeA.addMixin(MIXIN_TYPE_WITH_AUTO_CHILD.getString(registry));
+ nodeA.save();
+
+ Node newRootNode = session.getRootNode();
+ Node newNodeA = newRootNode.getNode("a");
+
+ Node newNodeB = newNodeA.getNode(CHILD_NODE_B.getString(registry));
+
+ assertThat(newNodeA.isNodeType(MIXIN_TYPE_WITH_AUTO_CHILD.getLocalName()), is(true));
+ assertThat(newNodeB.isNodeType("nt:unstructured"), is(true));
+ assertThat(newNodeB, is(notNullValue()));
+
+ // Uncomment this to see the problem with the session cache not refreshing the immutable info for /a after a save
+ // assertThat(newNodeB.getDefinition().getDeclaringNodeType().getName(), is(MIXIN_TYPE_B.getString(registry)));
+
+ }
+
+ @Test
+ public void shouldAllowSettingNewPropertyAfterAddingMixin() throws Exception {
+ graph.create("/a");
+ graph.set(JcrLexicon.PRIMARY_TYPE.getString(registry)).on("/a").to(PRIMARY_TYPE_A);
+ graph.set(JcrLexicon.MIXIN_TYPES.getString(registry)).on("/a").to(JcrMixLexicon.REFERENCEABLE.getString(registry));
+
+ Node rootNode = session.getRootNode();
+ Node nodeA = rootNode.getNode("a");
+
+ assertThat(nodeA.canAddMixin(MIXIN_TYPE_B.getString(registry)), is(true));
+ nodeA.addMixin(MIXIN_TYPE_B.getString(registry));
+
+ nodeA.setProperty(PROPERTY_B.getString(registry), "some string");
+ nodeA.save();
+
+ rootNode = session.getRootNode();
+ nodeA = rootNode.getNode("a");
+ Property propB = nodeA.getProperty(PROPERTY_B.getString(registry));
+
+ assertThat(propB, is(notNullValue()));
+ assertThat(propB.getValue().getString(), is("some string"));
+ }
+
+ @Test
+ public void shouldAllowAddingNewChildNodeAfterAddingMixin() throws Exception {
+ graph.create("/a");
+ graph.set(JcrLexicon.PRIMARY_TYPE.getString(registry)).on("/a").to(PRIMARY_TYPE_A);
+ graph.set(JcrLexicon.MIXIN_TYPES.getString(registry)).on("/a").to(JcrMixLexicon.REFERENCEABLE.getString(registry));
+
+ Node rootNode = session.getRootNode();
+ Node nodeA = rootNode.getNode("a");
+
+ assertThat(nodeA.canAddMixin(MIXIN_TYPE_B.getString(registry)), is(true));
+ nodeA.addMixin(MIXIN_TYPE_B.getString(registry));
+
+ nodeA.addNode(CHILD_NODE_B.getString(registry));
+ nodeA.save();
+
+ Node newRootNode = session.getRootNode();
+ Node newNodeA = newRootNode.getNode("a");
+ Node newNodeB = newNodeA.getNode(CHILD_NODE_B.getString(registry));
+
+ assertThat(newNodeB, is(notNullValue()));
+ assertThat(newNodeB.getDefinition().getDeclaringNodeType().getName(), is(MIXIN_TYPE_B.getString(registry)));
+ }
+
+ @Test
+ public void shouldAllowRemovalIfNoConflict() throws Exception {
+ graph.create("/a").and().create("/a/nodeB");
+ graph.set(JcrLexicon.PRIMARY_TYPE.getString(registry)).on("/a").to(JcrNtLexicon.UNSTRUCTURED);
+ graph.set(JcrLexicon.MIXIN_TYPES.getString(registry)).on("/a").to(MIXIN_TYPE_B);
+
+ Node rootNode = session.getRootNode();
+ Node nodeA = rootNode.getNode("a");
+ nodeA.removeMixin(MIXIN_TYPE_B.getString(registry));
+ nodeA.save();
+
+ rootNode = session.getRootNode();
+ nodeA = rootNode.getNode("a");
+
+ assertThat(nodeA.getMixinNodeTypes().length, is(0));
+ }
+
+ @Test
+ public void shouldAllowRemovalIfExistingPropertyWouldHaveDefinition() throws Exception {
+ graph.create("/a").and().create("/a");
+ graph.set(PROPERTY_B).on("/a").to("true");
+ graph.set(JcrLexicon.PRIMARY_TYPE.getString(registry)).on("/a").to(JcrNtLexicon.UNSTRUCTURED);
+ graph.set(JcrLexicon.MIXIN_TYPES.getString(registry)).on("/a").to(MIXIN_TYPE_B);
+
+ Node rootNode = session.getRootNode();
+ Node nodeA = rootNode.getNode("a");
+ nodeA.removeMixin(MIXIN_TYPE_B.getString(registry));
+ nodeA.save();
+
+ rootNode = session.getRootNode();
+ nodeA = rootNode.getNode("a");
+
+ assertThat(nodeA.getMixinNodeTypes().length, is(0));
+ }
+
+ @Test( expected = ConstraintViolationException.class )
+ public void shouldNotAllowRemovalIfExistingPropertyWouldHaveNoDefinition() throws Exception {
+ graph.create("/a").and().create("/a");
+ graph.set(PROPERTY_B).on("/a").to("true");
+ graph.set(JcrLexicon.PRIMARY_TYPE.getString(registry)).on("/a").to(PRIMARY_TYPE_A);
+ graph.set(JcrLexicon.MIXIN_TYPES.getString(registry)).on("/a").to(MIXIN_TYPE_B);
+
+ Node rootNode = session.getRootNode();
+ Node nodeA = rootNode.getNode("a");
+ nodeA.removeMixin(MIXIN_TYPE_B.getString(registry));
+ nodeA.save();
+
+ rootNode = session.getRootNode();
+ nodeA = rootNode.getNode("a");
+
+ assertThat(nodeA.getMixinNodeTypes().length, is(0));
+ }
+
+ @Test
+ public void shouldAllowRemovalIfExistingChildNodeWouldHaveDefinition() throws Exception {
+ graph.create("/a").and().create("/a/nodeB");
+ graph.set(JcrLexicon.PRIMARY_TYPE.getString(registry)).on("/a").to(JcrNtLexicon.UNSTRUCTURED);
+ graph.set(JcrLexicon.MIXIN_TYPES.getString(registry)).on("/a").to(MIXIN_TYPE_B);
+
+ Node rootNode = session.getRootNode();
+ Node nodeA = rootNode.getNode("a");
+ nodeA.removeMixin(MIXIN_TYPE_B.getString(registry));
+ }
+
+ @Test( expected = ConstraintViolationException.class )
+ public void shouldNotAllowRemovalIfExistingChildNodeWouldHaveNoDefinition() throws Exception {
+ graph.create("/a").and().create("/a/nodeB");
+ graph.set(JcrLexicon.PRIMARY_TYPE.getString(registry)).on("/a").to(PRIMARY_TYPE_A);
+ graph.set(JcrLexicon.MIXIN_TYPES.getString(registry)).on("/a").to(MIXIN_TYPE_B);
+
+ Node rootNode = session.getRootNode();
+ Node nodeA = rootNode.getNode("a");
+ nodeA.removeMixin(MIXIN_TYPE_B.getString(registry));
+ }
+
+ class TestNodeTypeSource extends AbstractJcrNodeTypeSource {
+
+ /** The list of primary node types. */
+ private final List<JcrNodeType> nodeTypes;
+
+ 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));
+ }
+
+ JcrNodeType unstructured = findType(JcrNtLexicon.UNSTRUCTURED);
+
+ if (unstructured == null) {
+ String baseTypeName = JcrNtLexicon.UNSTRUCTURED.getString(context.getNamespaceRegistry());
+ String namespaceTypeName = DnaLexicon.NAMESPACE.getString(context.getNamespaceRegistry());
+ throw new IllegalStateException(JcrI18n.supertypeNotFound.text(baseTypeName, namespaceTypeName));
+ }
+
+ Value tenValue = new JcrValue(context.getValueFactories(), null, PropertyType.LONG, 10);
+
+ // Stubbing in child node and property definitions for now
+ JcrNodeType mixinTypeA = new JcrNodeType(
+ context,
+ NO_NODE_TYPE_MANAGER,
+ MIXIN_TYPE_A,
+ Arrays.asList(new JcrNodeType[] {base}),
+ NO_PRIMARY_ITEM_NAME,
+ Arrays.asList(new JcrNodeDefinition[] {new JcrNodeDefinition(
+ context,
+ null,
+ CHILD_NODE_A,
+ OnParentVersionAction.IGNORE,
+ false,
+ false,
+ false,
+ false,
+ JcrNtLexicon.BASE,
+ new JcrNodeType[] {base}),}),
+ Arrays.asList(new JcrPropertyDefinition[] {new JcrPropertyDefinition(
+ context,
+ null,
+ PROPERTY_A,
+ OnParentVersionBehavior.IGNORE.getJcrValue(),
+ false,
+ false,
+ false,
+ NO_DEFAULT_VALUES,
+ PropertyType.STRING,
+ NO_CONSTRAINTS,
+ false),}),
+ IS_A_MIXIN, UNORDERABLE_CHILD_NODES);
+
+ JcrNodeType mixinTypeB = new JcrNodeType(
+ context,
+ NO_NODE_TYPE_MANAGER,
+ MIXIN_TYPE_B,
+ Arrays.asList(new JcrNodeType[] {base}),
+ NO_PRIMARY_ITEM_NAME,
+ Arrays.asList(new JcrNodeDefinition[] {new JcrNodeDefinition(
+ context,
+ null,
+ CHILD_NODE_B,
+ OnParentVersionAction.IGNORE,
+ false,
+ false,
+ false,
+ false,
+ JcrNtLexicon.BASE,
+ new JcrNodeType[] {base}),}),
+ Arrays.asList(new JcrPropertyDefinition[] {new JcrPropertyDefinition(
+ context,
+ null,
+ PROPERTY_B,
+ OnParentVersionBehavior.IGNORE.getJcrValue(),
+ false,
+ false,
+ false,
+ NO_DEFAULT_VALUES,
+ PropertyType.BINARY,
+ NO_CONSTRAINTS,
+ false),}),
+ IS_A_MIXIN, UNORDERABLE_CHILD_NODES);
+
+ JcrNodeType mixinTypeC = new JcrNodeType(
+ context,
+ NO_NODE_TYPE_MANAGER,
+ MIXIN_TYPE_C,
+ Arrays.asList(new JcrNodeType[] {base}),
+ NO_PRIMARY_ITEM_NAME,
+ Arrays.asList(new JcrNodeDefinition[] {new JcrNodeDefinition(
+ context,
+ null,
+ CHILD_NODE_A,
+ OnParentVersionAction.IGNORE,
+ false,
+ false,
+ false,
+ false,
+ JcrNtLexicon.BASE,
+ new JcrNodeType[] {base}),}),
+ Arrays.asList(new JcrPropertyDefinition[] {new JcrPropertyDefinition(
+ context,
+ null,
+ PROPERTY_B,
+ OnParentVersionBehavior.IGNORE.getJcrValue(),
+ false,
+ false,
+ false,
+ NO_DEFAULT_VALUES,
+ PropertyType.STRING,
+ NO_CONSTRAINTS,
+ false),}),
+ IS_A_MIXIN, UNORDERABLE_CHILD_NODES);
+
+ JcrNodeType mixinTypeWithAutoChild = new JcrNodeType(
+ context,
+ NO_NODE_TYPE_MANAGER,
+ MIXIN_TYPE_WITH_AUTO_CHILD,
+ Arrays.asList(new JcrNodeType[] {base}),
+ NO_PRIMARY_ITEM_NAME,
+ Arrays.asList(new JcrNodeDefinition[] {new JcrNodeDefinition(
+ context,
+ null,
+ CHILD_NODE_B,
+ OnParentVersionAction.IGNORE,
+ true,
+ true,
+ false,
+ false,
+ JcrNtLexicon.UNSTRUCTURED,
+ new JcrNodeType[] {unstructured}),}),
+ NO_PROPERTIES, IS_A_MIXIN, UNORDERABLE_CHILD_NODES);
+
+ JcrNodeType mixinTypeWithAutoProperty = new JcrNodeType(
+ context,
+ NO_NODE_TYPE_MANAGER,
+ MIXIN_TYPE_WITH_AUTO_PROP,
+ Arrays.asList(new JcrNodeType[] {base}),
+ NO_PRIMARY_ITEM_NAME,
+ NO_CHILD_NODES,
+ Arrays.asList(new JcrPropertyDefinition[] {new JcrPropertyDefinition(
+ context,
+ null,
+ PROPERTY_B,
+ OnParentVersionBehavior.IGNORE.getJcrValue(),
+ true,
+ true,
+ false,
+ new Value[] {tenValue},
+ PropertyType.LONG,
+ NO_CONSTRAINTS,
+ false),}),
+ IS_A_MIXIN, UNORDERABLE_CHILD_NODES);
+
+ JcrNodeType primaryTypeA = new JcrNodeType(
+ context,
+ NO_NODE_TYPE_MANAGER,
+ PRIMARY_TYPE_A,
+ Arrays.asList(new JcrNodeType[] {base}),
+ NO_PRIMARY_ITEM_NAME,
+ Arrays.asList(new JcrNodeDefinition[] {new JcrNodeDefinition(
+ context,
+ null,
+ CHILD_NODE_A,
+ OnParentVersionAction.IGNORE,
+ false,
+ false,
+ false,
+ false,
+ JcrNtLexicon.BASE,
+ new JcrNodeType[] {base}),}),
+ Arrays.asList(new JcrPropertyDefinition[] {new JcrPropertyDefinition(
+ context,
+ null,
+ PROPERTY_A,
+ OnParentVersionBehavior.IGNORE.getJcrValue(),
+ false,
+ false,
+ false,
+ NO_DEFAULT_VALUES,
+ PropertyType.STRING,
+ NO_CONSTRAINTS,
+ false),}),
+ NOT_MIXIN, UNORDERABLE_CHILD_NODES);
+
+ nodeTypes.addAll(Arrays.asList(new JcrNodeType[] {mixinTypeA, mixinTypeB, mixinTypeC, mixinTypeWithAutoChild,
+ mixinTypeWithAutoProperty, primaryTypeA,}));
+ }
+
+ /**
+ * {@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/MixinTest.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
16 years, 8 months
DNA SVN: r811 - trunk/dna-jcr/src/main/java/org/jboss/dna/jcr.
by dna-commits@lists.jboss.org
Author: rhauch
Date: 2009-04-07 18:22:56 -0400 (Tue, 07 Apr 2009)
New Revision: 811
Modified:
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrValue.java
Log:
DNA-344 JcrSession.getValueFactory.create(String, int) Does Not Fail Fast as per Specification
Applied second patch to clean up some of the code that is no longer needed.
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-04-07 22:21:03 UTC (rev 810)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrValue.java 2009-04-07 22:22:56 UTC (rev 811)
@@ -343,11 +343,7 @@
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 {
+ if (this.type != PropertyType.STRING && this.type != PropertyType.BINARY) {
throw createValueFormatException(boolean.class);
}
try {
@@ -357,15 +353,8 @@
}
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 {
+ if (this.type != PropertyType.STRING && this.type != PropertyType.BINARY && this.type != PropertyType.DOUBLE
+ && this.type != PropertyType.LONG) {
throw createValueFormatException(Calendar.class);
}
try {
@@ -375,13 +364,7 @@
}
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 {
+ if (this.type != PropertyType.STRING && this.type != PropertyType.BINARY && this.type != PropertyType.PATH) {
throw createValueFormatException(Name.class);
}
try {
@@ -391,13 +374,7 @@
}
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 {
+ if (this.type != PropertyType.STRING && this.type != PropertyType.BINARY && this.type != PropertyType.NAME) {
throw createValueFormatException(Path.class);
}
try {
@@ -407,11 +384,7 @@
}
case PropertyType.REFERENCE:
- 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.STRING && this.type != PropertyType.BINARY) {
throw createValueFormatException(Node.class);
}
try {
@@ -420,15 +393,8 @@
throw createValueFormatException(vfe);
}
case PropertyType.DOUBLE:
- 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 {
+ if (this.type != PropertyType.STRING && this.type != PropertyType.BINARY && this.type != PropertyType.LONG
+ && this.type != PropertyType.DATE) {
throw createValueFormatException(double.class);
}
try {
@@ -437,15 +403,8 @@
throw createValueFormatException(vfe);
}
case PropertyType.LONG:
- 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 {
+ if (this.type != PropertyType.STRING && this.type != PropertyType.BINARY && this.type != PropertyType.DOUBLE
+ && this.type != PropertyType.DATE) {
throw createValueFormatException(long.class);
}
try {
16 years, 8 months
DNA SVN: r810 - 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-04-07 18:21:03 -0400 (Tue, 07 Apr 2009)
New Revision: 810
Modified:
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrNode.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrI18n.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrValue.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
Log:
DNA-194 Implement update JCR capability
Uncommented more TCK unit tests for Level 2.
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrNode.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrNode.java 2009-04-07 21:23:28 UTC (rev 809)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrNode.java 2009-04-07 22:21:03 UTC (rev 810)
@@ -727,6 +727,10 @@
public final Property setProperty( String name,
Calendar value )
throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
+ if (value == null) {
+ // If there is an existing property, then remove it ...
+ return removeExistingSingleValuedProperty(name);
+ }
return cache.findJcrProperty(editor().setProperty(nameFrom(name), valueFrom(value)));
}
@@ -751,6 +755,10 @@
public final Property setProperty( String name,
InputStream value )
throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
+ if (value == null) {
+ // If there is an existing property, then remove it ...
+ return removeExistingSingleValuedProperty(name);
+ }
return cache.findJcrProperty(editor().setProperty(nameFrom(name), valueFrom(value)));
}
@@ -774,6 +782,10 @@
public final Property setProperty( String name,
Node value )
throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
+ if (value == null) {
+ // If there is an existing property, then remove it ...
+ return removeExistingSingleValuedProperty(name);
+ }
return cache.findJcrProperty(editor().setProperty(nameFrom(name), valueFrom(value)));
}
@@ -785,6 +797,10 @@
public final Property setProperty( String name,
String value )
throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
+ if (value == null) {
+ // If there is an existing property, then remove it ...
+ return removeExistingSingleValuedProperty(name);
+ }
return cache.findJcrProperty(editor().setProperty(nameFrom(name), valueFrom(PropertyType.STRING, value)));
}
@@ -797,6 +813,10 @@
String value,
int type )
throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
+ if (value == null) {
+ // If there is an existing property, then remove it ...
+ return removeExistingSingleValuedProperty(name);
+ }
return cache.findJcrProperty(editor().setProperty(nameFrom(name), valueFrom(type, value)));
}
@@ -831,9 +851,26 @@
public final Property setProperty( String name,
Value value )
throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
+ if (value == null) {
+ // If there is an existing property, then remove it ...
+ return removeExistingSingleValuedProperty(name);
+ }
return cache.findJcrProperty(editor().setProperty(nameFrom(name), (JcrValue)value));
}
+ protected final Property removeExistingSingleValuedProperty( String name )
+ throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
+ PropertyId id = new PropertyId(nodeUuid, nameFrom(name));
+ AbstractJcrProperty property = cache.findJcrProperty(id);
+ if (property != null) {
+ assert !property.isMultiple();
+ property.remove();
+ return property;
+ }
+ // else the property doesn't exist ...
+ throw new RepositoryException(JcrI18n.propertyNotFoundOnNode.text(name, getPath(), cache.workspaceName()));
+ }
+
/**
* {@inheritDoc}
*
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-04-07 21:23:28 UTC (rev 809)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrI18n.java 2009-04-07 22:21:03 UTC (rev 810)
@@ -69,6 +69,7 @@
public static I18n itemNotFoundWithUuid;
public static I18n itemNotFoundAtPath;
public static I18n itemNotFoundAtPathRelativeToReferenceNode;
+ public static I18n propertyNotFoundOnNode;
public static I18n propertyNotFoundAtPathRelativeToReferenceNode;
public static I18n nodeNotFoundAtPathRelativeToReferenceNode;
public static I18n childNotFoundUnderNode;
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-04-07 21:23:28 UTC (rev 809)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrValue.java 2009-04-07 22:21:03 UTC (rev 810)
@@ -50,6 +50,8 @@
@NotThreadSafe
final class JcrValue implements Value {
+ static final JcrValue[] EMPTY_ARRAY = new JcrValue[] {};
+
private final SessionCache sessionCache;
private final ValueFactories valueFactories;
private final int type;
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-04-07 21:23:28 UTC (rev 809)
+++ trunk/dna-jcr/src/main/resources/org/jboss/dna/jcr/JcrI18n.properties 2009-04-07 22:21:03 UTC (rev 810)
@@ -59,6 +59,7 @@
itemNotFoundWithUuid = An item with UUID "{0}" could not be found in workspace "{1}": {2}
itemNotFoundAtPath = An item at "{0}" could not be found in workspace "{1}"
itemNotFoundAtPathRelativeToReferenceNode = An item at "{0}" relative to "{1}" could not be found in workspace "{2}"
+propertyNotFoundOnNode = Property "{0}" does not exist on node "{1}" in workspace "{2}"
propertyNotFoundAtPathRelativeToReferenceNode = A property at "{0}" relative to "{1}" could not be found in workspace "{2}"
nodeNotFoundAtPathRelativeToReferenceNode = A node at "{0}" relative to "{1}" could not be found in workspace "{2}"
childNotFoundUnderNode = The child "{0}" could not be found under "{1}" in workspace "{2}"
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-04-07 21:23:28 UTC (rev 809)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckTest.java 2009-04-07 22:21:03 UTC (rev 810)
@@ -41,11 +41,20 @@
import org.apache.jackrabbit.test.api.PropertyTest;
import org.apache.jackrabbit.test.api.RepositoryLoginTest;
import org.apache.jackrabbit.test.api.SessionUUIDTest;
+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.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.SetValueVersionExceptionTest;
import org.apache.jackrabbit.test.api.ValueFactoryTest;
import org.jboss.dna.graph.DnaLexicon;
import org.jboss.dna.graph.ExecutionContext;
@@ -164,26 +173,26 @@
// addTestSuite(NodeOrderableChildNodesTest.class);
addTestSuite(PropertyTest.class);
//
- // addTestSuite(SetValueBinaryTest.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(SetValueConstraintViolationExceptionTest.class);
// addTestSuite(SetValueValueFormatExceptionTest.class);
- // addTestSuite(SetValueVersionExceptionTest.class);
- //
- // addTestSuite(SetPropertyBooleanTest.class);
- // addTestSuite(SetPropertyCalendarTest.class);
- // addTestSuite(SetPropertyDoubleTest.class);
- // addTestSuite(SetPropertyInputStreamTest.class);
- // addTestSuite(SetPropertyLongTest.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(SetPropertyConstraintViolationExceptionTest.class);
// addTestSuite(SetPropertyAssumeTypeTest.class);
//
// addTestSuite(NodeItemIsModifiedTest.class);
16 years, 8 months