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:53 UTC
[jackrabbit-filevault] 01/01: JCRVLT-516 simplify usage of
DocViewProperties outside JCR context
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) {