You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by kw...@apache.org on 2021/04/15 14:37:52 UTC

[jackrabbit-filevault] branch feature/improve-docviewproperty created (now 0c18908)

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

kwin pushed a change to branch feature/improve-docviewproperty
in repository https://gitbox.apache.org/repos/asf/jackrabbit-filevault.git.


      at 0c18908  JCRVLT-516 simplify usage of DocViewProperties outside JCR context

This branch includes the following new commits:

     new 0c18908  JCRVLT-516 simplify usage of DocViewProperties outside JCR context

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


[jackrabbit-filevault] 01/01: JCRVLT-516 simplify usage of DocViewProperties outside JCR context

Posted by kw...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

kwin pushed a commit to branch feature/improve-docviewproperty
in repository https://gitbox.apache.org/repos/asf/jackrabbit-filevault.git

commit 0c18908908ec682163daf9f0575f3be2b7aeed68
Author: Konrad Windszus <kw...@apache.org>
AuthorDate: Thu Apr 15 16:37:38 2021 +0200

    JCRVLT-516 simplify usage of DocViewProperties outside JCR context
    
    provide factory methods taking either Property or Value[]
    allow to format a given DocViewProperty
---
 .../jackrabbit/vault/util/DocViewProperty.java     | 176 ++++++++++++++-------
 .../jackrabbit/vault/util/DocViewPropertyTest.java |   8 +-
 2 files changed, 123 insertions(+), 61 deletions(-)

diff --git a/vault-core/src/main/java/org/apache/jackrabbit/vault/util/DocViewProperty.java b/vault-core/src/main/java/org/apache/jackrabbit/vault/util/DocViewProperty.java
index eb3162f..dea8b85 100644
--- a/vault-core/src/main/java/org/apache/jackrabbit/vault/util/DocViewProperty.java
+++ b/vault-core/src/main/java/org/apache/jackrabbit/vault/util/DocViewProperty.java
@@ -17,6 +17,7 @@
 
 package org.apache.jackrabbit.vault.util;
 
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashSet;
 import java.util.LinkedList;
@@ -33,16 +34,22 @@ import javax.jcr.ValueFormatException;
 
 import org.apache.jackrabbit.api.ReferenceBinary;
 import org.apache.jackrabbit.commons.jackrabbit.SimpleReferenceBinary;
+import org.apache.jackrabbit.util.Text;
 import org.apache.jackrabbit.util.XMLChar;
 import org.apache.jackrabbit.value.ValueHelper;
-import org.apache.jackrabbit.util.Text;
 
 /**
  * Helper class that represents a (jcr) property in the document view format.
  * It contains formatting and parsing methods for writing/reading enhanced
  * docview properties.
- *
- * {@code prop:= [ "{" type "}" ] ( value | "[" [ value { "," value } ] "]" )}
+ * </p>
+ * The string representation adheres to the following grammar:
+ * <pre>
+ * <code>prop:= [ "{" type "}" ] ( value | "[" [ value { "," value } ] "]" )
+ * {@code type} := {@link PropertyType#nameFromValue(int)} | {@link BINARY_REF}
+ * </code>
+ * </pre>
+ * 
  */
 public class DocViewProperty {
 
@@ -75,9 +82,9 @@ public class DocViewProperty {
     public final boolean isReferenceProperty;
 
     /**
-     * set of unambigous property names
+     * set of unambigous property names (which never need an explicit type descriptor as the types are defined by the spec)
      */
-    private static final Set<String> UNAMBIGOUS = new HashSet<String>();
+    private static final Set<String> UNAMBIGOUS = new HashSet<>();
     static {
         UNAMBIGOUS.add("jcr:primaryType");
         UNAMBIGOUS.add("jcr:mixinTypes");
@@ -95,6 +102,57 @@ public class DocViewProperty {
         this(name, values, multi, type, false);
     }
 
+    public static DocViewProperty fromValues(String name, Value[] values, boolean isMulti, boolean sort, boolean useBinaryReferences) throws RepositoryException {
+        List<String> strValues = new ArrayList<>();
+        if (isMulti) {
+            if (sort) {
+                Arrays.sort(values, ValueComparator.getInstance());
+            }
+        }
+        for (Value value : values) {
+             strValues.add(serializeValue(value, useBinaryReferences));
+        }
+         
+        int type = values[0].getType();
+        boolean isBinaryRef = false;
+        if (type == PropertyType.BINARY && !strValues.get(0).isEmpty()) {
+            isBinaryRef = true;
+        }
+        return new DocViewProperty(name, strValues.toArray(new String[0]), isMulti, type, isBinaryRef);
+    }
+
+    /**
+     * Creates a new property based on a JCR property object
+     * @param prop the jcr property
+     * @param sort if {@code true} multivalue properties should be sorted
+     * @param useBinaryReferences {@code true} to use binary references
+     * @throws RepositoryException 
+     * @throws IllegalArgumentException if single value property and not exactly 1 value is given.
+     */
+    public static DocViewProperty fromProperty(Property prop, boolean sort, boolean useBinaryReferences) throws RepositoryException {
+        return fromValues(prop.getName(), prop.getValues(), prop.getDefinition().isMultiple(), sort, useBinaryReferences);
+    }
+
+    static String serializeValue(Value value, boolean useBinaryReferences) throws RepositoryException {
+        // special handling for binaries
+        String strValue = null;
+        if (value.getType() == PropertyType.BINARY) {
+            if (useBinaryReferences) {
+                Binary bin = value.getBinary();
+                if (bin instanceof ReferenceBinary) {
+                    strValue = ((ReferenceBinary) bin).getReference();
+                }
+            }
+            if (strValue == null) {
+                // leave value empty for other binaries
+                strValue = "";
+            }
+        } else {
+            strValue = ValueHelper.serialize(value, false);
+        }
+        return strValue;
+    }
+
     /**
      * Creates a new property.
      * @param name name of the property
@@ -134,7 +192,7 @@ public class DocViewProperty {
         int pos = 0;
         char state = 'b';
         List<String> vals = null;
-        StringBuffer tmp = new StringBuffer();
+        StringBuilder tmp = new StringBuilder();
         int unicode = 0;
         int unicodePos = 0;
         while (pos < value.length()) {
@@ -264,62 +322,51 @@ public class DocViewProperty {
      */
     public static String format(Property prop, boolean sort, boolean useBinaryReferences)
             throws RepositoryException {
-        StringBuffer attrValue = new StringBuffer();
-        int type = prop.getType();
-        if (type == PropertyType.BINARY || isAmbiguous(prop)) {
-            String referenceBinary = null;
-            if (useBinaryReferences && type == PropertyType.BINARY) {
-                Binary bin = prop.getBinary();
-                if (bin != null && bin instanceof ReferenceBinary) {
-                    referenceBinary = ((ReferenceBinary) bin).getReference();
-                }
-            }
+        return fromProperty(prop, sort, useBinaryReferences).format();
+    }
 
-            if (referenceBinary == null) {
-                attrValue.append("{");
-                attrValue.append(PropertyType.nameFromValue(prop.getType()));
-                attrValue.append("}");
+    /** 
+     * Generates string representation of this DocView property.
+     * @return the string representation
+     */
+    String format() {
+        StringBuilder attrValue = new StringBuilder();
+        
+        if (isAmbiguous(type, name)) {
+            final String strType;
+            if (isReferenceProperty) {
+                strType = BINARY_REF;
             } else {
-                attrValue.append("{");
-                attrValue.append(BINARY_REF);
-                attrValue.append("}");
-                attrValue.append(referenceBinary);
+                strType = PropertyType.nameFromValue(type);
             }
+            attrValue.append('{').append(strType).append('}');
+        }
+        if (isMulti) {
+            attrValue.append('[');
         }
-        // only write values for non binaries
-        if (prop.getType() != PropertyType.BINARY) {
-            if (prop.getDefinition().isMultiple()) {
-                attrValue.append('[');
-                Value[] values = prop.getValues();
-                if (sort) {
-                    Arrays.sort(values, ValueComparator.getInstance());
+        for (int i=0;i<values.length;i++) {
+            String value = values[i];
+            if (values.length == 1 && value.length() == 0) {
+                // special case for empty string MV value (JCR-3661)
+                attrValue.append("\\0");
+            } else {
+                if (i > 0) {
+                    attrValue.append(',');
                 }
-                for (int i = 0; i < values.length; i++) {
-                    if (i > 0) {
-                        attrValue.append(',');
-                    }
-                    String strValue = ValueHelper.serialize(values[i], false);
-                    if (values.length == 1 && strValue.length() == 0) {
-                        // special case for empty string MV value (JCR-3661)
-                        attrValue.append("\\0");
-                    } else {
-                        switch (prop.getType()) {
-                            case PropertyType.STRING:
-                            case PropertyType.NAME:
-                            case PropertyType.PATH:
-                                escape(attrValue, strValue, true);
-                                break;
-                            default:
-                                attrValue.append(strValue);
-                        }
-                    }
+                switch (type) {
+                    case PropertyType.STRING:
+                    case PropertyType.NAME:
+                    case PropertyType.PATH:
+                        attrValue.append(escape(value, isMulti));
+                        break;
+                    default:
+                        attrValue.append(value);
                 }
-                attrValue.append(']');
-            } else {
-                String strValue = ValueHelper.serialize(prop.getValue(), false);
-                escape(attrValue, strValue, false);
             }
         }
+        if (isMulti) {
+            attrValue.append(']');
+        }
         return attrValue.toString();
     }
 
@@ -329,7 +376,8 @@ public class DocViewProperty {
      * @param value value to escape
      * @param isMulti indicates multi value property
      */
-    protected static void escape(StringBuffer buf, String value, boolean isMulti) {
+    protected static String escape(String value, boolean isMulti) {
+        StringBuilder buf = new StringBuilder();
         for (int i=0; i<value.length(); i++) {
             char c = value.charAt(i);
             if (c == '\\') {
@@ -348,6 +396,7 @@ public class DocViewProperty {
                 buf.append(c);
             }
         }
+        return buf.toString();
     }
     
     /**
@@ -358,9 +407,24 @@ public class DocViewProperty {
      * @param prop the property
      * @return type
      * @throws RepositoryException if a repository error occurs
+     * @deprecated use {@link #isAmbiguous(int,String)} instead.
      */
+    @Deprecated
     public static boolean isAmbiguous(Property prop) throws RepositoryException {
-        return prop.getType() != PropertyType.STRING && !UNAMBIGOUS.contains(prop.getName());
+        return isAmbiguous(prop.getType(), prop.getName());
+    }
+
+    /**
+     * Checks if the type of the given property is ambiguous in respect to it's
+     * property definition. the current implementation just checks some well
+     * known properties.
+     *
+     * @param type the type
+     * @param name the name
+     * @return {@code true} if type information should be emitted, otherwise {@code false}
+     */
+    private static boolean isAmbiguous(int type, String name) {
+        return type != PropertyType.STRING && !UNAMBIGOUS.contains(name);
     }
 
     /**
diff --git a/vault-core/src/test/java/org/apache/jackrabbit/vault/util/DocViewPropertyTest.java b/vault-core/src/test/java/org/apache/jackrabbit/vault/util/DocViewPropertyTest.java
index e69fb8e..71337e6 100644
--- a/vault-core/src/test/java/org/apache/jackrabbit/vault/util/DocViewPropertyTest.java
+++ b/vault-core/src/test/java/org/apache/jackrabbit/vault/util/DocViewPropertyTest.java
@@ -148,11 +148,11 @@ public class DocViewPropertyTest {
         Value value = Mockito.mock(Value.class);
 
         Mockito.when(value.getString()).thenReturn("");
+        Mockito.when(value.getType()).thenReturn(PropertyType.STRING);
         Value[] values = new Value[]{value};
         PropertyDefinition pd = Mockito.mock(PropertyDefinition.class);
         Mockito.when(pd.isMultiple()).thenReturn(true);
 
-        Mockito.when(p.getType()).thenReturn(PropertyType.STRING);
         Mockito.when(p.getName()).thenReturn("foo");
         Mockito.when(p.getValues()).thenReturn(values);
         Mockito.when(p.getDefinition()).thenReturn(pd);
@@ -171,11 +171,11 @@ public class DocViewPropertyTest {
         Value value = Mockito.mock(Value.class);
 
         Mockito.when(value.getString()).thenReturn("false");
+        Mockito.when(value.getType()).thenReturn(PropertyType.BOOLEAN);
         Value[] values = new Value[]{value};
         PropertyDefinition pd = Mockito.mock(PropertyDefinition.class);
         Mockito.when(pd.isMultiple()).thenReturn(true);
 
-        Mockito.when(p.getType()).thenReturn(PropertyType.BOOLEAN);
         Mockito.when(p.getName()).thenReturn("foo");
         Mockito.when(p.getValues()).thenReturn(values);
         Mockito.when(p.getDefinition()).thenReturn(pd);
@@ -204,9 +204,7 @@ public class DocViewPropertyTest {
     }
 
     private void assertEscaped(String original, String expected, boolean multi) {
-        StringBuffer buf = new StringBuffer();
-        DocViewProperty.escape(buf, original, multi);
-        Assert.assertEquals(expected, buf.toString());
+        Assert.assertEquals(expected, DocViewProperty.escape(original, multi));
     }
 
     private void assertEquals(DocViewProperty p, boolean multi, int type, String... values) {