You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by st...@apache.org on 2006/03/08 13:20:38 UTC

svn commit: r384197 - in /incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core: jndi/provider/DummyContext.java xml/DocViewImportHandler.java xml/DocViewSAXEventGenerator.java

Author: stefan
Date: Wed Mar  8 04:20:37 2006
New Revision: 384197

URL: http://svn.apache.org/viewcvs?rev=384197&view=rev
Log:
JCR-325: docview roundtripping does not work with multivalue non-string properties

Modified:
    incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/jndi/provider/DummyContext.java
    incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/xml/DocViewImportHandler.java
    incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/xml/DocViewSAXEventGenerator.java

Modified: incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/jndi/provider/DummyContext.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/jndi/provider/DummyContext.java?rev=384197&r1=384196&r2=384197&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/jndi/provider/DummyContext.java (original)
+++ incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/jndi/provider/DummyContext.java Wed Mar  8 04:20:37 2006
@@ -35,7 +35,7 @@
 import java.util.Properties;
 
 /**
- * <code>DummyContext</code>  is a simple service provider that
+ * <code>DummyContext</code> is a simple service provider that
  * implements a flat namespace in memory. It is intended to be used for
  * testing purposes only.
  */

Modified: incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/xml/DocViewImportHandler.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/xml/DocViewImportHandler.java?rev=384197&r1=384196&r2=384197&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/xml/DocViewImportHandler.java (original)
+++ incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/xml/DocViewImportHandler.java Wed Mar  8 04:20:37 2006
@@ -20,6 +20,7 @@
 import org.apache.jackrabbit.name.NamespaceResolver;
 import org.apache.jackrabbit.name.QName;
 import org.apache.jackrabbit.util.ISO9075;
+import org.apache.jackrabbit.util.Text;
 import org.apache.jackrabbit.core.NodeId;
 import org.apache.log4j.Logger;
 import org.xml.sax.Attributes;
@@ -162,6 +163,9 @@
 
     /**
      * {@inheritDoc}
+     * <p/>
+     * See also {@link DocViewSAXEventGenerator#leaving(javax.jcr.Node, int)}
+     * regarding special handling of multi-valued properties on export.
      */
     public void startElement(String namespaceURI, String localName,
                              String qName, Attributes atts)
@@ -188,35 +192,49 @@
                 // value(s)
                 String attrValue = atts.getValue(i);
                 Importer.TextValue[] propValues;
-/*
-                // @todo should attribute value be interpreted as LIST type (i.e. multi-valued property)?
-                String[] strings = Text.explode(attrValue, ' ', true);
-                propValues = new Value[strings.length];
-                for (int j = 0; j < strings.length; j++) {
-                    // decode encoded blanks in value
-                    strings[j] = Text.replace(strings[j], "_x0020_", " ");
-                    propValues[j] = InternalValue.create(strings[j]);
+
+                if (attrValue.startsWith("\n")) {
+                    // assume multi-valued property:
+                    // a leading line-feed (a valid whitespace NMTOKENS delimiter)
+                    // is interpreted as a hint that this attribute value is of
+                    // type NMTOKENS.
+                    // see DocViewSAXEventGenerator#leaving(Node, int)
+                    attrValue = attrValue.substring(1);
+                    String[] strings = Text.explode(attrValue, ' ', true);
+                    propValues = new Importer.TextValue[strings.length];
+                    for (int j = 0; j < strings.length; j++) {
+                        // decode encoded blanks in value
+                        strings[j] = Text.replace(strings[j], "_x0020_", " ");
+                        propValues[j] = new StringValue(strings[j]);
+                    }
+                } else {
+                    // assume single-valued property
+                    propValues = new Importer.TextValue[1];
+                    propValues[0] = new StringValue(attrValue);
                 }
-*/
+
                 if (propName.equals(QName.JCR_PRIMARYTYPE)) {
                     // jcr:primaryType
                     if (attrValue.length() > 0) {
                         try {
                             nodeTypeName = QName.fromJCRName(attrValue, nsContext);
-                        } catch (NameException be) {
+                        } catch (NameException ne) {
                             throw new SAXException("illegal jcr:primaryType value: "
-                                    + attrValue, be);
+                                    + attrValue, ne);
                         }
                     }
                 } else if (propName.equals(QName.JCR_MIXINTYPES)) {
                     // jcr:mixinTypes
-                    if (attrValue.length() > 0) {
-                        try {
-                            mixinTypes =
-                                    new QName[]{QName.fromJCRName(attrValue, nsContext)};
-                        } catch (NameException be) {
-                            throw new SAXException("illegal jcr:mixinTypes value: "
-                                    + attrValue, be);
+                    if (propValues.length > 0) {
+                        mixinTypes = new QName[propValues.length];
+                        for (int j = 0; j < propValues.length; j++) {
+                            String val = ((StringValue) propValues[j]).retrieve();
+                            try {
+                                mixinTypes[j] = QName.fromJCRName(val, nsContext);
+                            } catch (NameException ne) {
+                                throw new SAXException("illegal jcr:mixinTypes value: "
+                                        + val, ne);
+                            }
                         }
                     }
                 } else if (propName.equals(QName.JCR_UUID)) {
@@ -225,8 +243,6 @@
                         id = NodeId.valueOf(attrValue);
                     }
                 } else {
-                    propValues = new Importer.TextValue[1];
-                    propValues[0] = new StringValue(atts.getValue(i));
                     props.add(new Importer.PropInfo(propName,
                             PropertyType.UNDEFINED, propValues));
                 }

Modified: incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/xml/DocViewSAXEventGenerator.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/xml/DocViewSAXEventGenerator.java?rev=384197&r1=384196&r2=384197&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/xml/DocViewSAXEventGenerator.java (original)
+++ incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/xml/DocViewSAXEventGenerator.java Wed Mar  8 04:20:37 2006
@@ -98,6 +98,9 @@
 
     /**
      * {@inheritDoc}
+     * <p/>
+     * See also {@link DocViewImportHandler#startElement(String, String, String, org.xml.sax.Attributes)}
+     * regarding special handling of multi-valued properties on import.
      */
     protected void leavingProperties(Node node, int level)
             throws RepositoryException, SAXException {
@@ -146,18 +149,44 @@
                     StringBuffer attrValue = new StringBuffer();
                     // process property value(s)
                     boolean multiValued = prop.getDefinition().isMultiple();
-                    Value[] vals;
+
                     if (multiValued) {
-                        vals = prop.getValues();
-                    } else {
-                        vals = new Value[]{prop.getValue()};
-                    }
-                    for (int i = 0; i < vals.length; i++) {
-                        if (i > 0) {
-                            // use space as delimiter for multi-valued properties
-                            attrValue.append(" ");
+                        // multi-valued property:
+                        // according to "6.4.2.5 Multi-value Properties" of the
+                        // jsr-170 specification a multi-valued property can be
+                        // either skipped or it must be exported as NMTOKENS
+                        // type where "a mechanism must be adopted whereby upon
+                        // re-import the distinction between multi- and single-
+                        // value properties is not lost"...
+
+                        // the following implementation is a pragmatic approach
+                        // in the interest of improved useability:
+                        // the attribute value is constructed by concatenating
+                        // the serialized and escaped values, separated by a
+                        // space character each, into a single string and
+                        // prepending a new-line to help distinguish multi-
+                        // from single-valued properties on re-import.
+
+                        // use a leading line-feed (a valid whitespace
+                        // delimiter) as a hint on re-import that this attribute
+                        // value is of type NMTOKENS; note that line-feed rather
+                        // than space has been chosen as leading line-feeds are 
+                        // not affected by attribute-value normalization
+                        // (http://www.w3.org/TR/REC-xml/#AVNormalize)
+                        attrValue.append("\n");
+                        Value[] vals = prop.getValues();
+                        for (int i = 0; i < vals.length; i++) {
+                            if (i > 0) {
+                                // use space as delimiter for separate values
+                                attrValue.append(" ");
+                            }
+                            // serialize value (with encoded embedded spaces)
+                            attrValue.append(ValueHelper.serialize(vals[i], true));
                         }
-                        attrValue.append(ValueHelper.serialize(vals[i], true));
+                    } else {
+                        // single-valued property:
+                        // serialize value without encoding embedded spaces
+                        attrValue.append(ValueHelper.serialize(prop.getValue(), false));
                     }
                     attrs.addAttribute(qName.getNamespaceURI(),
                             qName.getLocalName(), attrName, CDATA_TYPE,