You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ro...@apache.org on 2017/11/07 09:46:39 UTC

[sling-org-apache-sling-jcr-contentparser] 02/14: SLING-6592 use DocViewProperty from vault-core to parse jcr xml property values fix artifactid

This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to annotated tag org.apache.sling.jcr.contentparser-1.0.0
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-jcr-contentparser.git

commit 081596f751b5ef0474978e02d2c7d42bc3f68eeb
Author: Stefan Seifert <ss...@apache.org>
AuthorDate: Thu Mar 2 21:37:31 2017 +0000

    SLING-6592 use DocViewProperty from vault-core to parse jcr xml property values
    fix artifactid
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/bundles/commons/fscontentparser@1785194 13f79535-47bb-0310-9956-ffa450edef68
---
 pom.xml                                            |  29 ++--
 .../impl/JcrXmlContentFileParser.java              |   7 +-
 .../fscontentparser/impl/JcrXmlValueConverter.java | 192 +++++++++------------
 .../impl/JcrXmlValueConverterTest.java             |  59 ++++---
 4 files changed, 145 insertions(+), 142 deletions(-)

diff --git a/pom.xml b/pom.xml
index da20dc3..6b42222 100644
--- a/pom.xml
+++ b/pom.xml
@@ -26,7 +26,7 @@
         <relativePath />
     </parent>
 
-    <artifactId>org.apache.sling.fscontentparser</artifactId>
+    <artifactId>org.apache.sling.commons.fscontentparser</artifactId>
     <packaging>bundle</packaging>
     <version>1.0.0-SNAPSHOT</version>
 
@@ -47,16 +47,6 @@
                 <groupId>org.apache.felix</groupId>
                 <artifactId>maven-bundle-plugin</artifactId>
                 <extensions>true</extensions>
-                <configuration>
-                    <instructions>
-                        <!-- Embed the nessecary parts of the jackrabbit-jcr-commons bundle as described in http://njbartlett.name/2014/05/26/static-linking.html -->
-                        <Conditional-Package>org.apache.jackrabbit.util</Conditional-Package>
-                        <Import-Package>
-                          !org.apache.jackrabbit.*,
-                          *
-                        </Import-Package>
-                    </instructions>
-                </configuration>
             </plugin>
             <plugin>
                 <groupId>org.apache.rat</groupId>
@@ -100,12 +90,29 @@
             <scope>compile</scope>
         </dependency>
         <dependency>
+            <groupId>javax.jcr</groupId>
+            <artifactId>jcr</artifactId>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.jackrabbit</groupId>
+            <artifactId>jackrabbit-api</artifactId>
+            <version>2.8.0</version>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
             <groupId>org.apache.jackrabbit</groupId>
             <artifactId>jackrabbit-jcr-commons</artifactId>
             <version>2.8.0</version>
             <scope>compile</scope>
         </dependency>
         <dependency>
+            <groupId>org.apache.jackrabbit.vault</groupId>
+            <artifactId>org.apache.jackrabbit.vault</artifactId>
+            <version>3.1.18</version>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
             <groupId>junit</groupId>
             <artifactId>junit</artifactId>
             <scope>test</scope>
diff --git a/src/main/java/org/apache/sling/fscontentparser/impl/JcrXmlContentFileParser.java b/src/main/java/org/apache/sling/fscontentparser/impl/JcrXmlContentFileParser.java
index 060308e..c97317e 100644
--- a/src/main/java/org/apache/sling/fscontentparser/impl/JcrXmlContentFileParser.java
+++ b/src/main/java/org/apache/sling/fscontentparser/impl/JcrXmlContentFileParser.java
@@ -129,11 +129,10 @@ public final class JcrXmlContentFileParser implements ContentFileParser {
             for (int i=0; i<attributes.getLength(); i++) {
                 String propertyName = helper.cleanupPropertyName(decodeName(attributes.getQName(i)));
                 if (!helper.ignoreProperty(propertyName)) {
-                    Object value = JcrXmlValueConverter.parseValue(attributes.getValue(i));
-                    if (value instanceof Object[]) {
-                        value = helper.convertSingleTypeArray((Object[])value);
+                    Object value = JcrXmlValueConverter.parseValue(propertyName, attributes.getValue(i));
+                    if (value != null) {
+                        element.put(propertyName, value);
                     }
-                    element.put(propertyName, value);
                 }
             }
         }
diff --git a/src/main/java/org/apache/sling/fscontentparser/impl/JcrXmlValueConverter.java b/src/main/java/org/apache/sling/fscontentparser/impl/JcrXmlValueConverter.java
index b3a817e..8e9fad4 100644
--- a/src/main/java/org/apache/sling/fscontentparser/impl/JcrXmlValueConverter.java
+++ b/src/main/java/org/apache/sling/fscontentparser/impl/JcrXmlValueConverter.java
@@ -18,23 +18,22 @@
  */
 package org.apache.sling.fscontentparser.impl;
 
-import java.util.ArrayList;
-import java.util.List;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
+import java.lang.reflect.Array;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.Calendar;
+import java.util.UUID;
+
+import javax.jcr.PropertyType;
 
-import org.apache.commons.lang3.ArrayUtils;
-import org.apache.commons.lang3.StringUtils;
 import org.apache.jackrabbit.util.ISO8601;
+import org.apache.jackrabbit.vault.util.DocViewProperty;
 
 /**
  * Parses JCR XML files that contains content fragments.
  */
 class JcrXmlValueConverter {
     
-    private static final Pattern TYPE_PREFIX = Pattern.compile("^\\{([^\\{\\}]+)\\}(.+)$");
-    private static final Pattern VALUE_ARRAY = Pattern.compile("^\\[(.*)\\]$");
-    
     private JcrXmlValueConverter() {
         // static methods only
     }
@@ -44,125 +43,106 @@ class JcrXmlValueConverter {
      * @param value XML attribute value
      * @return Value object
      */
-    public static Object parseValue(final String rawValue) {
-        String value = rawValue;
-        String[] valueArray = null;
-        
-        if (rawValue == null) {
+    public static Object parseValue(final String name, final String value) {
+        if (value == null) {
             return null;
         }
+        DocViewProperty prop = DocViewProperty.parse(name, value);
         
-        // detect type prefix
-        String typePrefix = null;
-        Matcher typePrefixMatcher = TYPE_PREFIX.matcher(value);
-        if (typePrefixMatcher.matches()) {
-            typePrefix = typePrefixMatcher.group(1);
-            value = typePrefixMatcher.group(2);
-        }
-        
-        // check for array
-        Matcher arrayMatcher = VALUE_ARRAY.matcher(value);
-        if (arrayMatcher.matches()) {
-            value = null;
-            valueArray = splitPreserveAllTokens(arrayMatcher.group(1), ',');
-        }
-
         // convert values
-        if (valueArray != null) {
-            Object[] result = new Object[valueArray.length];
-            for (int i=0; i<valueArray.length; i++) {
-                result[i] = convertValue(valueArray[i], typePrefix, true);
+        if (prop.isMulti) {
+            Class<?> arrayType = getType(prop.type);
+            if (arrayType == null) {
+                return null;
+            }
+            Object result = Array.newInstance(arrayType, prop.values.length);
+            for (int i=0; i<prop.values.length; i++) {
+                Array.set(result, i, convertValue(prop.values[i], prop.type, true));
             }
             return result;
         }
         else {
-            return convertValue(value, typePrefix, false);
+            return convertValue(prop.values[0], prop.type, false);
         }
     }
     
     /**
-     * Split string preserving all tokens - but ignore separators that are escaped with \.
-     * @param str Combined string
-     * @param sep Separator
-     * @return Tokens
-     */
-    private static String[] splitPreserveAllTokens(String str, char sep) {
-        final int len = str.length();
-        if (len == 0) {
-            return ArrayUtils.EMPTY_STRING_ARRAY;
-        }
-        final List<String> list = new ArrayList<String>();
-        int i = 0, start = 0;
-        boolean match = false;
-        boolean lastMatch = false;
-        boolean escaped = false;
-        while (i < len) {
-            if (str.charAt(i) == '\\' && !escaped) {
-                escaped = true;
-            }
-            else {
-                if (str.charAt(i) == sep && !escaped) {
-                    lastMatch = true;
-                    list.add(str.substring(start, i));
-                    match = false;
-                    start = ++i;
-                    continue;
-                }
-                lastMatch = false;
-                match = true;
-                escaped = false;
-            }
-            i++;
-        }
-        if (match || lastMatch) {
-            list.add(str.substring(start, i));
-        }
-        return list.toArray(new String[list.size()]);        
-    }
-    
-    /**
      * Parse value depending on type prefix.
      * @param value Value
-     * @param typePrefix Type prefix
+     * @param type Type
      * @param inArray Value is in array
      * @return Value object
      */
-    private static Object convertValue(final String value, final String typePrefix, final boolean inArray) {
-        if (typePrefix == null || StringUtils.equals(typePrefix, "Name")) {
-            return deescapeStringValue(value, inArray);
-        }
-        else if (StringUtils.equals(typePrefix, "Boolean")) {
-            return Boolean.valueOf(value);
-        }
-        else if (StringUtils.equals(typePrefix, "Long")) {
-            return Long.valueOf(value);
-        }
-        else if (StringUtils.equals(typePrefix, "Decimal")) {
-            return Double.valueOf(value);
-        }
-        else if (StringUtils.equals(typePrefix, "Date")) {
-            return ISO8601.parse(value);
-        }
-        else {
-            throw new IllegalArgumentException("Unexpected type prefix: " + typePrefix);
+    private static Object convertValue(final String value, final int type, final boolean inArray) {
+        switch (type) {
+            case PropertyType.UNDEFINED:
+            case PropertyType.STRING:
+            case PropertyType.NAME:
+            case PropertyType.PATH:
+                return value;
+            case PropertyType.BOOLEAN:
+                return Boolean.valueOf(value);
+            case PropertyType.LONG:
+                return Long.valueOf(value);
+            case PropertyType.DOUBLE:
+            case PropertyType.DECIMAL:
+                // TODO: specific handling for BigDecimal? not properly supported in ValueMapDecorator until very recent Sling API versions
+                return Double.valueOf(value);
+            case PropertyType.DATE:
+                return ISO8601.parse(value);
+            case PropertyType.REFERENCE:
+            case PropertyType.WEAKREFERENCE:
+                return UUID.fromString(value);
+            case PropertyType.URI:
+                try {
+                    return new URI(value);
+                }
+                catch (URISyntaxException ex) {
+                    throw new IllegalArgumentException("Unexpected URI syntax: " + value);
+                }
+            case PropertyType.BINARY:
+                // not supported - ignore value
+                return null;
+            default:
+                throw new IllegalArgumentException("Unexpected type: " + PropertyType.nameFromValue(type));
+            
         }
     }
     
     /**
-     * De-escape string value.
-     * @param value Escaped string value
-     * @param inArray In array
-     * @return De-escaped string value
+     * Get java type for given JCR type.
+     * @param type Type
+     * @return Type
      */
-    private static String deescapeStringValue(final String value, final boolean inArray) {
-        String descapedValue = value;
-        if (inArray) {
-          descapedValue = StringUtils.replace(descapedValue, "\\,", ",");
+    private static Class<?> getType(final int type) {
+        switch (type) {
+            case PropertyType.UNDEFINED:
+            case PropertyType.STRING:
+            case PropertyType.NAME:
+            case PropertyType.PATH:
+                return String.class;
+            case PropertyType.BOOLEAN:
+                return Boolean.class;
+            case PropertyType.LONG:
+                return Long.class;
+            case PropertyType.DOUBLE:
+            case PropertyType.DECIMAL:
+                // TODO: specific handling for BigDecimal? not properly supported in ValueMapDecorator until very recent Sling API versions
+                return Double.class;
+            case PropertyType.DATE:
+                return Calendar.class;
+            case PropertyType.REFERENCE:
+            case PropertyType.WEAKREFERENCE:
+                return UUID.class;
+            case PropertyType.URI:
+                return URI.class;
+            case PropertyType.BINARY:
+                // not supported - ignore value
+                return null;
+            default:
+                throw new IllegalArgumentException("Unexpected type: " + PropertyType.nameFromValue(type));
+            
         }
-        else if (StringUtils.startsWith(descapedValue, "\\{") || StringUtils.startsWith(descapedValue, "\\[")) {
-            descapedValue = descapedValue.substring(1);
-        }
-        return StringUtils.replace(descapedValue, "\\\\", "\\");
     }
-        
+    
 }
diff --git a/src/test/java/org/apache/sling/fscontentparser/impl/JcrXmlValueConverterTest.java b/src/test/java/org/apache/sling/fscontentparser/impl/JcrXmlValueConverterTest.java
index bddf053..2f02aae 100644
--- a/src/test/java/org/apache/sling/fscontentparser/impl/JcrXmlValueConverterTest.java
+++ b/src/test/java/org/apache/sling/fscontentparser/impl/JcrXmlValueConverterTest.java
@@ -23,75 +23,79 @@ import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNull;
 
+import java.net.URI;
 import java.util.Calendar;
+import java.util.UUID;
 
 import org.junit.Test;
 
 public class JcrXmlValueConverterTest {
+    
+    private static final String NAME = "prop1";
 
     @Test
     public void testNull() {
-        assertNull(parseValue(null));
+        assertNull(parseValue(NAME, null));
     }
 
     @Test(expected = IllegalArgumentException.class)
     public void testInvalid() {
-        parseValue("{InvalidType}xyz");
+        parseValue(NAME, "{InvalidType}xyz");
     }
 
     @Test
     public void testString() {
-        assertEquals("myString", parseValue("myString"));
-        assertEquals("prop", "myString [ ] { } \\ ,", parseValue("myString [ ] { } \\\\ ,"));
-        assertEquals("{myString}", parseValue("\\{myString}"));
-        assertEquals("aaa{myString}", parseValue("aaa{myString}"));
-        assertEquals("[myString]", parseValue("\\[myString]"));
-        assertEquals("aaa[myString]", parseValue("aaa[myString]"));
+        assertEquals("myString", parseValue(NAME, "myString"));
+        assertEquals("prop", "myString [ ] { } \\ ,", parseValue(NAME, "myString [ ] { } \\\\ ,"));
+        assertEquals("{myString}", parseValue(NAME, "\\{myString}"));
+        assertEquals("aaa{myString}", parseValue(NAME, "aaa{myString}"));
+        assertEquals("[myString]", parseValue(NAME, "\\[myString]"));
+        assertEquals("aaa[myString]", parseValue(NAME, "aaa[myString]"));
     }
 
     @Test
     public void testStringArray() {
-        assertArrayEquals(new Object[] { "myString1", "myString2" }, (Object[]) parseValue("[myString1,myString2]"));
+        assertArrayEquals(new Object[] { "myString1", "myString2" }, (Object[]) parseValue(NAME, "[myString1,myString2]"));
         assertArrayEquals(new Object[] { "myString1,[]\\äöü߀", "myString2", "myString3 [ ] { } \\ ,", "", "[myString5]", "{myString6}" },
-                (Object[]) parseValue("[myString1\\,[]\\\\äöü߀,myString2,myString3 [ ] { } \\\\ \\,,,[myString5],{myString6}]"));
+                (Object[]) parseValue(NAME, "[myString1\\,[]\\\\äöü߀,myString2,myString3 [ ] { } \\\\ \\,,,[myString5],{myString6}]"));
     }
 
     @Test
     public void testBoolean() {
-        assertEquals(true, parseValue("{Boolean}true"));
-        assertEquals(false, parseValue("{Boolean}false"));
+        assertEquals(true, parseValue(NAME, "{Boolean}true"));
+        assertEquals(false, parseValue(NAME, "{Boolean}false"));
     }
 
     @Test
     public void testBooleanArray() {
-        assertArrayEquals(new Object[] { true, false }, (Object[]) parseValue("{Boolean}[true,false]"));
+        assertArrayEquals(new Object[] { true, false }, (Object[]) parseValue(NAME, "{Boolean}[true,false]"));
     }
 
     @Test
     public void testLong() {
-        assertEquals(1L, parseValue("{Long}1"));
-        assertEquals(10000000000L, parseValue("{Long}10000000000"));
+        assertEquals(1L, parseValue(NAME, "{Long}1"));
+        assertEquals(10000000000L, parseValue(NAME, "{Long}10000000000"));
     }
 
     @Test
     public void testLongArray() {
-        assertArrayEquals(new Object[] { 1L, 2L }, (Object[]) parseValue("{Long}[1,2]"));
-        assertArrayEquals(new Object[] { 10000000000L, 20000000000L }, (Object[]) parseValue("{Long}[10000000000,20000000000]"));
+        assertArrayEquals(new Object[] { 1L, 2L }, (Object[]) parseValue(NAME, "{Long}[1,2]"));
+        assertArrayEquals(new Object[] { 10000000000L, 20000000000L }, (Object[]) parseValue(NAME, "{Long}[10000000000,20000000000]"));
     }
 
     @Test
     public void testDouble() {
-        assertEquals(1.234d, parseValue("{Decimal}1.234"));
+        assertEquals(1.234d, parseValue(NAME, "{Decimal}1.234"));
     }
 
     @Test
     public void testDoubleArray() {
-        assertArrayEquals(new Object[] { 1.234d, 2.345d }, (Object[]) parseValue("{Decimal}[1.234,2.345]"));
+        assertArrayEquals(new Object[] { 1.234d, 2.345d }, (Object[]) parseValue(NAME, "{Decimal}[1.234,2.345]"));
     }
 
     @Test
     public void testCalendar() {
-        Calendar value = (Calendar)parseValue("{Date}2010-09-05T15:10:20.000Z");
+        Calendar value = (Calendar)parseValue(NAME, "{Date}2010-09-05T15:10:20.000Z");
         assertEquals(2010, value.get(Calendar.YEAR));
         assertEquals(8, value.get(Calendar.MONTH));
         assertEquals(5, value.get(Calendar.DAY_OF_MONTH));
@@ -99,7 +103,20 @@ public class JcrXmlValueConverterTest {
 
     @Test
     public void testStringArrayRepPrivileges() {
-        assertArrayEquals(new Object[] { "rep:write", "crx:replicate", "jcr:read" }, (Object[]) parseValue("{Name}[rep:write,crx:replicate,jcr:read]"));
+        assertArrayEquals(new Object[] { "rep:write", "crx:replicate", "jcr:read" }, (Object[]) parseValue(NAME, "{Name}[rep:write,crx:replicate,jcr:read]"));
+    }
+
+    @Test
+    public void testReference() {
+        UUID uuid = UUID.randomUUID();
+        UUID value = (UUID)parseValue(NAME, "{Reference}" + uuid.toString());
+        assertEquals(uuid, value);
+    }
+
+    @Test
+    public void testURI() {
+        URI value = (URI)parseValue(NAME, "{URI}http://www.jodelkaiser.de/");
+        assertEquals("http://www.jodelkaiser.de/", value.toString());
     }
 
 }

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.