Author: rhauch
Date: 2009-04-27 14:45:16 -0400 (Mon, 27 Apr 2009)
New Revision: 857
Added:
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/DnaIntLexicon.java
Modified:
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/DnaLexicon.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrBuiltinNodeTypeSource.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNamespaceRegistry.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/SessionCache.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/cache/ChangedNodeInfo.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckTest.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/SessionCacheTest.java
Log:
DNA-374 Multiplicity of some properties may change when saved and reloaded from the graph
Added a patch that fixes this issue by maintaining a hidden property to store the names of
the properties that use multi-valued definitions but that have only one value. This
property is persisted as required, but is also cleaned up if it is empty or no longer
needed.
The patch also moves the "dna:nodeDefinition" and this new property into a new
"dnaint" namespace. This allows some of the code to just check the namespace to
know whether properties should be hidden from the JCR view.
Committed the patch, which also added in a number of commented-out TCK unit tests.
Added: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/DnaIntLexicon.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/DnaIntLexicon.java
(rev 0)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/DnaIntLexicon.java 2009-04-27 18:45:16
UTC (rev 857)
@@ -0,0 +1,41 @@
+/*
+ * JBoss DNA (
http://www.jboss.org/dna)
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership. Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ * See the AUTHORS.txt file in the distribution for a full listing of
+ * individual contributors.
+ *
+ * Unless otherwise indicated, all code in JBoss DNA is licensed
+ * to you under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * JBoss DNA is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.jboss.dna.jcr;
+
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.basic.BasicName;
+
+/**
+ * A lexicon of internal and implementation-specific information
+ */
+public class DnaIntLexicon {
+
+ public static class Namespace {
+ public static final String URI =
"http://www.jboss.org/dna/internal/1.0";
+ public static final String PREFIX = "dnaint";
+ }
+
+ public static final Name NODE_DEFINITON = new BasicName(Namespace.URI,
"nodeDefinition");
+ public static final Name MULTI_VALUED_PROPERTIES = new BasicName(Namespace.URI,
"multiValuedProperties");
+}
Property changes on: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/DnaIntLexicon.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/DnaLexicon.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/DnaLexicon.java 2009-04-23 21:51:50 UTC
(rev 856)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/DnaLexicon.java 2009-04-27 18:45:16 UTC
(rev 857)
@@ -31,9 +31,8 @@
*/
public class DnaLexicon extends org.jboss.dna.repository.DnaLexicon {
- public static final Name DEFINED = new BasicName(Namespace.URI,
"defined");
+ public static final Name BASE = new BasicName(Namespace.URI, "base");
public static final Name NAMESPACE = new BasicName(Namespace.URI,
"namespace");
- public static final Name NODE_DEFINITON = new BasicName(Namespace.URI,
"nodeDefinition");
public static final Name NODE_TYPES = new BasicName(Namespace.URI,
"nodeTypes");
public static final Name ROOT = new BasicName(Namespace.URI, "root");
public static final Name SYSTEM = new BasicName(Namespace.URI, "system");
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrBuiltinNodeTypeSource.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrBuiltinNodeTypeSource.java 2009-04-23
21:51:50 UTC (rev 856)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrBuiltinNodeTypeSource.java 2009-04-27
18:45:16 UTC (rev 857)
@@ -65,25 +65,17 @@
// Value trueValue = new JcrValue(context.getValueFactories(), null,
PropertyType.BOOLEAN, Boolean.TRUE);
Value ntBaseValue = new JcrValue(context.getValueFactories(), null,
PropertyType.NAME, JcrNtLexicon.BASE);
- JcrNodeType defined = new JcrNodeType(
- context,
- NO_NODE_TYPE_MANAGER,
- DnaLexicon.DEFINED,
- NO_SUPERTYPES,
- DnaLexicon.NODE_DEFINITON,
- NO_CHILD_NODES,
- Arrays.asList(new JcrPropertyDefinition[]
{new JcrPropertyDefinition(
-
context,
-
null,
-
DnaLexicon.NODE_DEFINITON,
-
OnParentVersionBehavior.INITIALIZE.getJcrValue(),
-
false,
-
false,
-
true,
-
NO_DEFAULT_VALUES,
-
PropertyType.STRING,
-
NO_CONSTRAINTS,
-
false),}),
+ JcrNodeType defined = new JcrNodeType(context, NO_NODE_TYPE_MANAGER,
DnaLexicon.BASE, NO_SUPERTYPES,
+ DnaIntLexicon.NODE_DEFINITON,
NO_CHILD_NODES,
+ Arrays.asList(new JcrPropertyDefinition[]
{
+ new JcrPropertyDefinition(context,
null, DnaIntLexicon.NODE_DEFINITON,
+
OnParentVersionBehavior.INITIALIZE.getJcrValue(),
+ false, false,
true, NO_DEFAULT_VALUES,
+
PropertyType.STRING, NO_CONSTRAINTS, false),
+ new JcrPropertyDefinition(context,
null, DnaIntLexicon.MULTI_VALUED_PROPERTIES,
+
OnParentVersionBehavior.INITIALIZE.getJcrValue(),
+ false, false,
true, NO_DEFAULT_VALUES,
+
PropertyType.STRING, NO_CONSTRAINTS, true),}),
IS_A_MIXIN, UNORDERABLE_CHILD_NODES);
// Stubbing in child node and property definitions for now
JcrNodeType base = new JcrNodeType(context, NO_NODE_TYPE_MANAGER,
JcrNtLexicon.BASE,
@@ -636,7 +628,7 @@
// Disabling version-related types until DNA supports versioning, as per section
4.11 of the 1.0.1 specification
nodeTypes.addAll(Arrays.asList(new JcrNodeType[] {defined, base, unstructured,
childNodeDefinition, file, folder,
frozenNode, hierarchyNode, linkedFile, nodeType, propertyDefinition, query,
resource, nodeType /*, version, versionHistory,
-
versionLabels, versionedChild */}));
+
versionLabels, versionedChild */}));
JcrNodeType lockable = new JcrNodeType(context, NO_NODE_TYPE_MANAGER,
JcrMixLexicon.LOCKABLE, NO_SUPERTYPES,
NO_PRIMARY_ITEM_NAME, NO_CHILD_NODES,
Arrays.asList(new JcrPropertyDefinition[] {
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNamespaceRegistry.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNamespaceRegistry.java 2009-04-23
21:51:50 UTC (rev 856)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNamespaceRegistry.java 2009-04-27
18:45:16 UTC (rev 857)
@@ -71,7 +71,7 @@
static final String XML_SCHEMA_NAMESPACE_URI =
"http://www.w3.org/2001/XMLSchema";
static final String XML_SCHEMA_INSTANCE_NAMESPACE_PREFIX = "xsi";
static final String XML_SCHEMA_INSTANCE_NAMESPACE_URI =
"http://www.w3.org/2001/XMLSchema-instance";
-
+
static final Set<String> STANDARD_BUILT_IN_PREFIXES;
static final Set<String> STANDARD_BUILT_IN_URIS;
static final Map<String, String> STANDARD_BUILT_IN_NAMESPACES_BY_PREFIX;
@@ -90,6 +90,7 @@
namespaces.put(XML_SCHEMA_NAMESPACE_PREFIX, XML_SCHEMA_NAMESPACE_URI);
namespaces.put(XML_SCHEMA_INSTANCE_NAMESPACE_PREFIX,
XML_SCHEMA_INSTANCE_NAMESPACE_URI);
namespaces.put(DnaLexicon.Namespace.PREFIX, DnaLexicon.Namespace.URI);
+ namespaces.put(DnaIntLexicon.Namespace.PREFIX, DnaIntLexicon.Namespace.URI);
// Set up the reverse map for the standard namespaces ...
Map<String, String> prefixes = new HashMap<String, String>();
for (Map.Entry<String, String> entry : namespaces.entrySet()) {
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-23 21:51:50
UTC (rev 856)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/SessionCache.java 2009-04-27 18:45:16
UTC (rev 857)
@@ -53,6 +53,7 @@
import javax.jcr.nodetype.PropertyDefinition;
import net.jcip.annotations.ThreadSafe;
import org.jboss.dna.common.i18n.I18n;
+import org.jboss.dna.common.util.Logger;
import org.jboss.dna.graph.ExecutionContext;
import org.jboss.dna.graph.Graph;
import org.jboss.dna.graph.Location;
@@ -128,6 +129,8 @@
*/
private static final boolean INCLUDE_PROPERTIES_NOT_ALLOWED_BY_NODE_TYPE_OR_MIXINS =
true;
+ private static final Set<Name> EMPTY_NAMES = Collections.emptySet();
+
private final JcrSession session;
private final String workspaceName;
protected final ExecutionContext context;
@@ -391,6 +394,7 @@
mixinTypeNames,
property.property(),
property.getType(),
+
property.property().isSingle(),
false);
if (definition == null) {
throw new
ConstraintViolationException(JcrI18n.noDefinition.text("property",
@@ -748,7 +752,8 @@
PropertyInfo info = findPropertyInfo(propertyId); // throws PathNotFoundException
if node not there
if (info == null) return null; // no such property on this node
- if (DnaLexicon.NODE_DEFINITON.equals(info.getPropertyName())) return null;
+ // Skip all internal properties ...
+ if (info.getPropertyName().getNamespaceUri().equals(DnaIntLexicon.Namespace.URI))
return null;
// Now create the appropriate JCR Property object ...
return createAndCacheJcrPropertyFor(info);
@@ -760,7 +765,7 @@
Set<Name> propertyNames = info.getPropertyNames();
Collection<AbstractJcrProperty> result = new
ArrayList<AbstractJcrProperty>(propertyNames.size());
for (Name propertyName : propertyNames) {
- if (!DnaLexicon.NODE_DEFINITON.equals(propertyName)) {
+ if (!propertyName.getNamespaceUri().equals(DnaIntLexicon.Namespace.URI)) {
result.add(findJcrProperty(new PropertyId(nodeUuid, propertyName)));
}
}
@@ -1080,8 +1085,7 @@
assert name != null;
assert values != null;
- // TODO: Re-add following line!
- // checkCardinalityOfExistingProperty(name, true);
+ checkCardinalityOfExistingProperty(name, true);
int len = values.length;
Value[] newValues = null;
@@ -1171,8 +1175,8 @@
}
}
// Create the DNA property ...
- int type = newValues.length != 0 ? newValues[0].getType() :
definition.getRequiredType();
- Object[] objValues = new Object[newValues.length];
+ int type = numValues != 0 ? newValues[0].getType() :
definition.getRequiredType();
+ Object[] objValues = new Object[numValues];
int propertyType = definition.getRequiredType();
if (propertyType == PropertyType.UNDEFINED || propertyType == type) {
// Can use the values as is ...
@@ -1198,6 +1202,23 @@
// Finally update the cached information and record the change ...
node.setProperty(newProperty, factories());
operations.set(dnaProp).on(currentLocation);
+
+ // If there is a single value, we need to record that this property is
actually a multi-valued property definition ...
+ if (numValues == 1) {
+ if (node.setSingleMultiProperty(name)) {
+ Set<Name> names = node.getSingleMultiPropertyNames();
+ // Added this property name to the set, so record the change ...
+ PropertyInfo singleMulti =
createSingleMultiplePropertyInfo(node.getUuid(),
+
node.getPrimaryTypeName(),
+
node.getMixinTypeNames(),
+ names);
+ node.setProperty(singleMulti, factories());
+ operations.set(singleMulti.getProperty()).on(currentLocation);
+ }
+ } else {
+ removeSingleMultiProperty(node, name);
+ }
+
return newProperty.getPropertyId();
}
@@ -1208,13 +1229,35 @@
* @return true if there was a property with the supplied name, or false if no
such property existed
*/
public boolean removeProperty( Name name ) {
- if (node.removeProperty(name) != null) {
+ PropertyInfo info = node.removeProperty(name);
+ if (info != null) {
operations.remove(name).on(currentLocation);
+ // Is this named in the single-multi property names? ...
+ removeSingleMultiProperty(node, name);
return true;
}
return false;
}
+ private void removeSingleMultiProperty( ChangedNodeInfo node,
+ Name propertyName ) {
+ if (node.removeSingleMultiProperty(propertyName)) {
+ Set<Name> names = node.getSingleMultiPropertyNames();
+ if (names == null || names.isEmpty()) {
+ node.removeProperty(DnaIntLexicon.MULTI_VALUED_PROPERTIES);
+
operations.remove(DnaIntLexicon.MULTI_VALUED_PROPERTIES).on(currentLocation);
+ } else {
+ // Added this property name to the set, so record the change ...
+ PropertyInfo singleMulti =
createSingleMultiplePropertyInfo(node.getUuid(),
+
node.getPrimaryTypeName(),
+
node.getMixinTypeNames(),
+ names);
+ node.setProperty(singleMulti, factories());
+ operations.set(singleMulti.getProperty()).on(currentLocation);
+ }
+ }
+ }
+
/**
* Move the child specified by the supplied UUID to be a child of this node,
appending the child to the end of the current
* list of children. This method automatically disconnects the node from its
current parent.
@@ -1255,7 +1298,7 @@
try {
JcrValue value = new JcrValue(factories(), SessionCache.this,
PropertyType.STRING, definition.getId()
.getString());
- setProperty(DnaLexicon.NODE_DEFINITON, value);
+ setProperty(DnaIntLexicon.NODE_DEFINITON, value);
} catch (ConstraintViolationException e) {
// We can't set this property on the node (according to the node
definition).
// But we still want the node info to have the correct node
definition.
@@ -1264,7 +1307,7 @@
node.setDefinitionId(definition.getId());
// And remove the property from the info ...
- newChildEditor.removeProperty(DnaLexicon.NODE_DEFINITON);
+ newChildEditor.removeProperty(DnaIntLexicon.NODE_DEFINITON);
}
}
@@ -1428,7 +1471,7 @@
// Create the properties ...
Map<Name, PropertyInfo> properties = new HashMap<Name,
PropertyInfo>();
Property primaryTypeProp = propertyFactory.create(JcrLexicon.PRIMARY_TYPE,
primaryTypeName);
- Property nodeDefinitionProp =
propertyFactory.create(DnaLexicon.NODE_DEFINITON, definition.getId().getString());
+ Property nodeDefinitionProp =
propertyFactory.create(DnaIntLexicon.NODE_DEFINITON, definition.getId().getString());
// Now add the "jcr:uuid" property if and only if referenceable
...
if (primaryType.isNodeType(JcrMixLexicon.REFERENCEABLE)) {
@@ -1457,6 +1500,7 @@
node.getMixinTypeNames(),
primaryTypeProp,
PropertyType.NAME,
+ true,
false);
PropertyDefinitionId primaryTypeDefinitionId = primaryTypeDefn.getId();
PropertyInfo primaryTypeInfo = new PropertyInfo(new PropertyId(desiredUuid,
primaryTypeProp.getName()),
@@ -1469,6 +1513,7 @@
node.getMixinTypeNames(),
nodeDefinitionProp,
PropertyType.STRING,
+ false,
false);
if (nodeDefnDefn != null) {
PropertyDefinitionId nodeDefnDefinitionId = nodeDefnDefn.getId();
@@ -1538,6 +1583,8 @@
* to include in the search
* @param dnaProperty the new property that is to be set on this node
* @param propertyType the property type; must be a valid {@link PropertyType} value
+ * @param isSingle true if the property definition should be single-valued, or false
if the property definition should allow
+ * multiple values
* @param skipProtected true if this operation is being done from within the public
JCR node and property API, or false if
* this operation is being done from within internal implementations
* @return the property definition that allows setting this property, or null if
there is no such definition
@@ -1546,6 +1593,7 @@
List<Name>
mixinTypeNamesOfParent,
Property dnaProperty,
int propertyType,
+ boolean isSingle,
boolean skipProtected ) {
JcrPropertyDefinition definition = null;
if (propertyType == PropertyType.UNDEFINED) {
@@ -1553,7 +1601,7 @@
}
// If single-valued ...
- if (dnaProperty.isSingle()) {
+ if (isSingle) {
// Create a value for the DNA property value ...
Object value = dnaProperty.getFirstValue();
Value jcrValue = new JcrValue(factories(), SessionCache.this, propertyType,
value);
@@ -2047,7 +2095,7 @@
// Look for a node definition stored on the node ...
JcrNodeDefinition definition = null;
- org.jboss.dna.graph.property.Property nodeDefnProperty =
graphProperties.get(DnaLexicon.NODE_DEFINITON);
+ org.jboss.dna.graph.property.Property nodeDefnProperty =
graphProperties.get(DnaIntLexicon.NODE_DEFINITON);
if (nodeDefnProperty != null && !nodeDefnProperty.isEmpty()) {
String nodeDefinitionString =
stringFactory.create(nodeDefnProperty.getFirstValue());
NodeDefinitionId id = NodeDefinitionId.fromString(nodeDefinitionString,
nameFactory);
@@ -2089,7 +2137,7 @@
if (primaryType.isNodeType(JcrMixLexicon.REFERENCEABLE)) referenceable = true;
// The process the mixin types ...
- org.jboss.dna.graph.property.Property mixinTypesProperty =
graphProperties.get(JcrLexicon.MIXIN_TYPES);
+ Property mixinTypesProperty = graphProperties.get(JcrLexicon.MIXIN_TYPES);
List<Name> mixinTypeNames = null;
if (mixinTypesProperty != null && !mixinTypesProperty.isEmpty()) {
for (Object mixinTypeValue : mixinTypesProperty) {
@@ -2102,17 +2150,31 @@
}
}
+ // Create the set of multi-valued property names ...
+ Set<Name> multiValuedPropertyNames = EMPTY_NAMES;
+ Set<Name> newSingleMultiPropertyNames = null;
+ Property multiValuedPropNamesProp =
graphProperties.get(DnaIntLexicon.MULTI_VALUED_PROPERTIES);
+ if (multiValuedPropNamesProp != null &&
!multiValuedPropNamesProp.isEmpty()) {
+ multiValuedPropertyNames =
getSingleMultiPropertyNames(multiValuedPropNamesProp, location.getPath(), uuid);
+ }
+
// Now create the JCR property object wrappers around the other properties ...
Map<Name, PropertyInfo> props = new HashMap<Name, PropertyInfo>();
- for (org.jboss.dna.graph.property.Property dnaProp : graphProperties.values()) {
+ for (Property dnaProp : graphProperties.values()) {
Name name = dnaProp.getName();
+ // Is this is single-valued property?
+ boolean isSingle = dnaProp.isSingle();
+ // Make sure that this isn't a multi-valued property with one value ...
+ if (isSingle && multiValuedPropertyNames.contains(name)) isSingle =
false;
+
// Figure out the JCR property type for this property ...
int propertyType = PropertyTypeUtil.jcrPropertyTypeFor(dnaProp);
PropertyDefinition propertyDefinition =
findBestPropertyDefintion(primaryTypeName,
mixinTypeNames,
dnaProp,
propertyType,
+ isSingle,
false);
// If there still is no property type defined ...
@@ -2138,6 +2200,12 @@
continue;
}
+ // Update the list of single-valued multi-property names ...
+ if (isMultiple && isSingle) {
+ if (newSingleMultiPropertyNames == null) newSingleMultiPropertyNames =
new HashSet<Name>();
+ newSingleMultiPropertyNames.add(name);
+ }
+
// Figure out the property type ...
int definitionType = propertyDefinition.getRequiredType();
if (definitionType != PropertyType.UNDEFINED) {
@@ -2173,6 +2241,15 @@
// Make sure the "dna:uuid" property did not get in there ...
props.remove(DnaLexicon.UUID);
+ // Make sure the single-valued multi-property names are stored as a property ...
+ if (newSingleMultiPropertyNames != null) {
+ PropertyInfo info = createSingleMultiplePropertyInfo(uuid,
+ primaryTypeName,
+ mixinTypeNames,
+
newSingleMultiPropertyNames);
+ props.put(info.getPropertyName(), info);
+ }
+
// Create the node information ...
UUID parentUuid = parentInfo != null ? parentInfo.getUuid() : null;
List<Location> locations = graphNode.getChildren();
@@ -2181,6 +2258,69 @@
return new ImmutableNodeInfo(location, primaryTypeName, mixinTypeNames,
definition.getId(), parentUuid, children, props);
}
+ protected final PropertyInfo createSingleMultiplePropertyInfo( UUID uuid,
+ Name primaryTypeName,
+ List<Name>
mixinTypeNames,
+ Set<Name>
newSingleMultiPropertyNames ) {
+ int number = newSingleMultiPropertyNames.size();
+ String[] names = new String[number];
+ JcrValue[] values = new JcrValue[number];
+ if (number == 1) {
+ String str =
newSingleMultiPropertyNames.iterator().next().getString(namespaces);
+ names[0] = str;
+ values[0] = new JcrValue(factories(), this, PropertyType.STRING, str);
+ } else {
+ int index = 0;
+ for (Name name : newSingleMultiPropertyNames) {
+ String str = name.getString(namespaces);
+ names[index] = str;
+ values[index] = new JcrValue(factories(), this, PropertyType.STRING,
str);
+ ++index;
+ }
+ }
+ PropertyDefinition propertyDefinition =
nodeTypes().findPropertyDefinition(primaryTypeName,
+
mixinTypeNames,
+
DnaIntLexicon.MULTI_VALUED_PROPERTIES,
+
values,
+
false);
+ Property dnaProp = propertyFactory.create(DnaIntLexicon.MULTI_VALUED_PROPERTIES,
newSingleMultiPropertyNames.iterator()
+
.next());
+ PropertyId propId = new PropertyId(uuid, dnaProp.getName());
+ JcrPropertyDefinition defn = (JcrPropertyDefinition)propertyDefinition;
+ return new PropertyInfo(propId, defn.getId(), PropertyType.STRING, dnaProp,
defn.isMultiple(), true, false);
+ }
+
+ protected final Set<Name> getSingleMultiPropertyNames( Property dnaProperty,
+ Path knownPath,
+ UUID knownUuid ) {
+ Set<Name> multiValuedPropertyNames = new HashSet<Name>();
+ for (Object value : dnaProperty) {
+ try {
+ multiValuedPropertyNames.add(nameFactory.create(value));
+ } catch (ValueFormatException e) {
+ String msg = "{0} value \"{1}\" on {2} in
\"{3}\" workspace is not a valid name and is being ignored";
+ String path = null;
+ if (knownPath != null) {
+ path = knownPath.getString(namespaces);
+ } else {
+ assert knownUuid != null;
+ try {
+ path = getPathFor(knownUuid).getString(namespaces);
+ } catch (RepositoryException err) {
+ path = knownUuid.toString();
+ }
+ }
+ Logger.getLogger(getClass()).trace(e,
+ msg,
+
DnaIntLexicon.MULTI_VALUED_PROPERTIES.getString(namespaces),
+ value,
+ path,
+ workspaceName());
+ }
+ }
+ return multiValuedPropertyNames;
+ }
+
/**
* This method finds the {@link NodeInfo} for the node with the supplied UUID and
marks it as being deleted, and does the same
* for all decendants (e.g., children, grandchildren, great-grandchildren, etc.) that
have been cached or changed.
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/cache/ChangedNodeInfo.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/cache/ChangedNodeInfo.java 2009-04-23
21:51:50 UTC (rev 856)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/cache/ChangedNodeInfo.java 2009-04-27
18:45:16 UTC (rev 857)
@@ -32,6 +32,7 @@
import java.util.Map;
import java.util.Set;
import java.util.UUID;
+import net.jcip.annotations.NotThreadSafe;
import org.jboss.dna.graph.JcrLexicon;
import org.jboss.dna.graph.Location;
import org.jboss.dna.graph.property.Name;
@@ -40,7 +41,7 @@
import org.jboss.dna.graph.property.ValueFactories;
import org.jboss.dna.graph.property.ValueFactory;
import org.jboss.dna.graph.property.Path.Segment;
-import org.jboss.dna.jcr.DnaLexicon;
+import org.jboss.dna.jcr.DnaIntLexicon;
import org.jboss.dna.jcr.NodeDefinitionId;
/**
@@ -49,6 +50,7 @@
* Each instance maintains a reference to the original (usually immutable) NodeInfo
representation that was probably read from the
* repository.
*/
+@NotThreadSafe
public class ChangedNodeInfo implements NodeInfo {
protected static final PropertyInfo DELETED_PROPERTY = null;
@@ -88,6 +90,8 @@
private List<UUID> peers;
+ private Set<Name> singleMultiPropertyNames;
+
/**
* Create an immutable NodeInfo instance.
*
@@ -127,6 +131,19 @@
peers.add(peerUuid);
}
+ public boolean setSingleMultiProperty( Name name ) {
+ if (singleMultiPropertyNames == null) singleMultiPropertyNames = new
HashSet<Name>();
+ return singleMultiPropertyNames.add(name);
+ }
+
+ public boolean removeSingleMultiProperty( Name name ) {
+ return singleMultiPropertyNames == null ? false :
singleMultiPropertyNames.remove(name);
+ }
+
+ public Set<Name> getSingleMultiPropertyNames() {
+ return singleMultiPropertyNames;
+ }
+
/**
* Return the original node information. May be null if this is a new node.
*
@@ -213,8 +230,8 @@
/**
* Set the identifier of the node definition for this node. This should normally be
changed by
- * {@link #setProperty(PropertyInfo, ValueFactories) setting} the {@link
DnaLexicon#NODE_DEFINITON} property. However, since
- * that property is not always allowed, this method provides a way to set it locally
(without requiring a property).
+ * {@link #setProperty(PropertyInfo, ValueFactories) setting} the {@link
DnaIntLexicon#NODE_DEFINITON} property. However,
+ * since that property is not always allowed, this method provides a way to set it
locally (without requiring a property).
*
* @param definitionId the new property definition identifier; may not be null
* @see #setProperty(PropertyInfo, ValueFactories)
@@ -404,7 +421,7 @@
for (Object value : newProperty.getProperty()) {
changedMixinTypeNames.add(nameFactory.create(value));
}
- } else if (name.equals(DnaLexicon.NODE_DEFINITON)) {
+ } else if (name.equals(DnaIntLexicon.NODE_DEFINITON)) {
ValueFactory<String> stringFactory = factories.getStringFactory();
String value =
stringFactory.create(newProperty.getProperty().getFirstValue());
changedDefinitionId = NodeDefinitionId.fromString(value,
factories.getNameFactory());
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-23 21:51:50 UTC
(rev 856)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckTest.java 2009-04-27 18:45:16 UTC
(rev 857)
@@ -62,6 +62,8 @@
import org.apache.jackrabbit.test.api.SetPropertyInputStreamTest;
import org.apache.jackrabbit.test.api.SetPropertyLongTest;
import org.apache.jackrabbit.test.api.SetPropertyNodeTest;
+import org.apache.jackrabbit.test.api.SetPropertyStringTest;
+import org.apache.jackrabbit.test.api.SetPropertyValueTest;
import org.apache.jackrabbit.test.api.SetValueBinaryTest;
import org.apache.jackrabbit.test.api.SetValueBooleanTest;
import org.apache.jackrabbit.test.api.SetValueConstraintViolationExceptionTest;
@@ -216,8 +218,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);
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/SessionCacheTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/SessionCacheTest.java 2009-04-23
21:51:50 UTC (rev 856)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/SessionCacheTest.java 2009-04-27
18:45:16 UTC (rev 857)
@@ -188,6 +188,8 @@
}
} else if (propertyName.equals(JcrLexicon.PRIMARY_TYPE)) {
// This is okay
+ } else if (propertyName.equals(DnaIntLexicon.MULTI_VALUED_PROPERTIES)) {
+ // This is okay
} else {
fail("missing property \"" + propertyName +
"\" on " + dnaNode);
}