You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by mr...@apache.org on 2009/08/10 10:37:58 UTC

svn commit: r802695 - in /jackrabbit/trunk/jackrabbit-spi-commons: ./ src/main/java/org/apache/jackrabbit/spi/commons/value/

Author: mreutegg
Date: Mon Aug 10 08:37:58 2009
New Revision: 802695

URL: http://svn.apache.org/viewvc?rev=802695&view=rev
Log:
JCR-2245: Make QValueFactoryImpl extensible

Added:
    jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/value/DefaultQValue.java   (with props)
Modified:
    jackrabbit/trunk/jackrabbit-spi-commons/pom.xml
    jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/value/AbstractQValue.java
    jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/value/AbstractQValueFactory.java
    jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/value/QValueFactoryImpl.java

Modified: jackrabbit/trunk/jackrabbit-spi-commons/pom.xml
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/pom.xml?rev=802695&r1=802694&r2=802695&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/pom.xml (original)
+++ jackrabbit/trunk/jackrabbit-spi-commons/pom.xml Mon Aug 10 08:37:58 2009
@@ -139,6 +139,10 @@
       <artifactId>commons-collections</artifactId>
     </dependency>
     <dependency>
+      <groupId>commons-io</groupId>
+      <artifactId>commons-io</artifactId>
+    </dependency>
+    <dependency>
       <groupId>org.slf4j</groupId>
       <artifactId>slf4j-api</artifactId>
     </dependency>

Modified: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/value/AbstractQValue.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/value/AbstractQValue.java?rev=802695&r1=802694&r2=802695&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/value/AbstractQValue.java (original)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/value/AbstractQValue.java Mon Aug 10 08:37:58 2009
@@ -16,12 +16,11 @@
  */
 package org.apache.jackrabbit.spi.commons.value;
 
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 import org.apache.jackrabbit.spi.QValue;
 import org.apache.jackrabbit.spi.Name;
 import org.apache.jackrabbit.spi.Path;
 import org.apache.jackrabbit.util.ISO8601;
+import org.apache.commons.io.IOUtils;
 
 import javax.jcr.PropertyType;
 import javax.jcr.RepositoryException;
@@ -30,16 +29,16 @@
 import java.util.TimeZone;
 import java.math.BigDecimal;
 import java.net.URI;
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.Serializable;
 
 /**
  * <code>AbstractQValue</code>...
  */
-public abstract class AbstractQValue implements QValue {
+public abstract class AbstractQValue implements QValue, Serializable {
 
-    /**
-     * logger instance
-     */
-    private static final Logger log = LoggerFactory.getLogger(AbstractQValue.class);
+    private static final long serialVersionUID = 6976433831974695272L;
 
     protected Object val;
     protected final int type;
@@ -310,9 +309,9 @@
      */
     public boolean getBoolean() throws RepositoryException {
         if (type == PropertyType.BOOLEAN) {
-            return ((Boolean) val).booleanValue();
+            return (Boolean) val;
         } else {
-            return Boolean.valueOf(getString()).booleanValue();
+            return Boolean.valueOf(getString());
         }
     }
 
@@ -332,6 +331,26 @@
     }
 
     /**
+     * @see QValue#getPath()
+     */
+    public String getString() throws RepositoryException {
+        if (type == PropertyType.BINARY) {
+            InputStream stream = getStream();
+            try {
+                return IOUtils.toString(stream, "UTF-8");
+            } catch (IOException e) {
+                throw new RepositoryException("conversion from stream to string failed", e);
+            } finally {
+                IOUtils.closeQuietly(stream);
+            }
+        } else if (type == PropertyType.DATE) {
+            return ISO8601.format(((Calendar) val));
+        } else {
+            return val.toString();
+        }
+    }
+
+    /**
      * @see QValue#discard()
      */
     public void discard() {
@@ -339,13 +358,18 @@
     }
 
     //---------------------------------------------------------< Object >---
+
     /**
      * Returns the string representation of this internal value.
      *
      * @return string representation of this internal value
      */
     public String toString() {
-        return val.toString();
+        if (type == PropertyType.DATE) {
+            return ISO8601.format((Calendar) val);
+        } else {
+            return val.toString();
+        }
     }
 
     /**

Modified: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/value/AbstractQValueFactory.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/value/AbstractQValueFactory.java?rev=802695&r1=802694&r2=802695&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/value/AbstractQValueFactory.java (original)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/value/AbstractQValueFactory.java Mon Aug 10 08:37:58 2009
@@ -18,9 +18,13 @@
 
 import java.util.Calendar;
 import java.util.UUID;
+import java.math.BigDecimal;
+import java.net.URI;
+import java.io.UnsupportedEncodingException;
 
 import javax.jcr.PropertyType;
 import javax.jcr.RepositoryException;
+import javax.jcr.ValueFormatException;
 
 import org.apache.jackrabbit.spi.Name;
 import org.apache.jackrabbit.spi.NameFactory;
@@ -28,11 +32,11 @@
 import org.apache.jackrabbit.spi.QPropertyDefinition;
 import org.apache.jackrabbit.spi.QValue;
 import org.apache.jackrabbit.spi.QValueFactory;
+import org.apache.jackrabbit.spi.Path;
 import org.apache.jackrabbit.spi.commons.name.NameConstants;
 import org.apache.jackrabbit.spi.commons.name.NameFactoryImpl;
 import org.apache.jackrabbit.spi.commons.name.PathFactoryImpl;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import org.apache.jackrabbit.util.ISO8601;
 
 /**
  * <code>AbstractQValueFactory</code>...
@@ -40,12 +44,6 @@
 public abstract class AbstractQValueFactory implements QValueFactory {
 
     /**
-     * logger instance
-     */
-    private static final Logger log = LoggerFactory.getLogger(AbstractQValueFactory.class);
-
-
-    /**
      * the default encoding
      */
     public static final String DEFAULT_ENCODING = "UTF-8";
@@ -59,8 +57,6 @@
      * @see QValueFactory#computeAutoValues(org.apache.jackrabbit.spi.QPropertyDefinition)
      */
     public QValue[] computeAutoValues(QPropertyDefinition propertyDefinition) throws RepositoryException {
-        final String userId = "undefined";
-
         Name declaringNT = propertyDefinition.getDeclaringNodeType();
         Name name = propertyDefinition.getName();
 
@@ -73,4 +69,157 @@
             throw new RepositoryException("createFromDefinition not implemented for: " + name);
         }
     }
+
+    /**
+     * @see QValueFactory#create(String, int)
+     */
+    public QValue create(String value, int type) throws RepositoryException {
+        if (value == null) {
+            throw new IllegalArgumentException("Cannot create QValue from null value.");
+        }
+
+        try {
+            switch (type) {
+                case PropertyType.BOOLEAN:
+                    return create(Boolean.valueOf(value));
+                case PropertyType.DATE: {
+                        Calendar cal = ISO8601.parse(value);
+                        if (cal == null) {
+                            throw new ValueFormatException("not a valid date: " + value);
+                        }
+                        return create(cal);
+                    }
+                case PropertyType.DOUBLE:
+                    return create(Double.valueOf(value));
+                case PropertyType.LONG:
+                    return create(Long.valueOf(value));
+                case PropertyType.DECIMAL:
+                    return create(new BigDecimal(value));
+                case PropertyType.URI:
+                    return create(URI.create(value));
+                case PropertyType.PATH:
+                    return create(PATH_FACTORY.create(value));
+                case PropertyType.NAME:
+                    return create(NAME_FACTORY.create(value));
+                case PropertyType.STRING:
+                    return createString(value);
+                case PropertyType.REFERENCE:
+                    return createReference(value, false);
+                case PropertyType.WEAKREFERENCE:
+                    return createReference(value, true);
+                case PropertyType.BINARY:
+                    return create(value.getBytes(DEFAULT_ENCODING));
+                // default: invalid type specified -> see below.
+            }
+        } catch (IllegalArgumentException ex) {
+            // given String value cannot be converted to Long/Double/Path/Name
+            throw new ValueFormatException(ex);
+        } catch (UnsupportedEncodingException ex) {
+            throw new RepositoryException(ex);
+        }
+
+        // invalid type specified:
+        throw new IllegalArgumentException("illegal type " + type);
+    }
+
+    /**
+     * @see QValueFactory#create(Calendar)
+     */
+    public QValue create(Calendar value) throws RepositoryException {
+        if (value == null) {
+            throw new IllegalArgumentException("Cannot create QValue from null value.");
+        }
+        // Calendar is not constant, must create a clone
+        return new DefaultQValue((Calendar) value.clone());
+    }
+
+    /**
+     * @see QValueFactory#create(double)
+     */
+    public QValue create(double value) throws RepositoryException {
+        return new DefaultQValue(value);
+    }
+
+    /**
+     * @see QValueFactory#create(long)
+     */
+    public QValue create(long value) throws RepositoryException {
+        return new DefaultQValue(value);
+    }
+
+    /**
+     * @see QValueFactory#create(boolean)
+     */
+    public QValue create(boolean value) throws RepositoryException {
+        if (value) {
+            return DefaultQValue.TRUE;
+        } else {
+            return DefaultQValue.FALSE;
+        }
+    }
+
+    /**
+     * @see QValueFactory#create(Name)
+     */
+    public QValue create(Name value) throws RepositoryException {
+        if (value == null) {
+            throw new IllegalArgumentException("Cannot create QValue from null value.");
+        }
+        return new DefaultQValue(value);
+    }
+
+    /**
+     * @see QValueFactory#create(Path)
+     */
+    public QValue create(Path value) throws RepositoryException {
+        if (value == null) {
+            throw new IllegalArgumentException("Cannot create QValue from null value.");
+        }
+        return new DefaultQValue(value);
+    }
+
+    /**
+     * @see QValueFactory#create(URI)
+     */
+    public QValue create(URI value) throws RepositoryException {
+        if (value == null) {
+            throw new IllegalArgumentException("Cannot create QValue from null value.");
+        }
+        return new DefaultQValue(value);
+    }
+
+    /**
+     * @see QValueFactory#create(URI)
+     */
+    public QValue create(BigDecimal value) throws RepositoryException {
+        if (value == null) {
+            throw new IllegalArgumentException("Cannot create QValue from null value.");
+        }
+        return new DefaultQValue(value);
+    }
+
+    /**
+     * Creates a new QValue of type STRING.
+     *
+     * @param value the string value.
+     * @return a new QValue.
+     */
+    protected QValue createString(String value) {
+        return new DefaultQValue(value, PropertyType.STRING);
+    }
+
+    /**
+     * Creates a new QValue of type REFERENCE or WEAKREFERENCE.
+     *
+     * @param ref the reference value.
+     * @param weak whether the reference is weak.
+     * @return a new QValue.
+     */
+    protected QValue createReference(String ref, boolean weak) {
+        if (weak) {
+            return new DefaultQValue(ref, PropertyType.WEAKREFERENCE);
+        } else {
+            return new DefaultQValue(ref, PropertyType.REFERENCE);
+        }
+    }
 }
\ No newline at end of file

Added: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/value/DefaultQValue.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/value/DefaultQValue.java?rev=802695&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/value/DefaultQValue.java (added)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/value/DefaultQValue.java Mon Aug 10 08:37:58 2009
@@ -0,0 +1,111 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.spi.commons.value;
+
+import java.io.Serializable;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ByteArrayInputStream;
+import java.io.UnsupportedEncodingException;
+import java.math.BigDecimal;
+import java.net.URI;
+import java.util.Calendar;
+
+import javax.jcr.Binary;
+import javax.jcr.RepositoryException;
+
+import org.apache.jackrabbit.spi.QValue;
+import org.apache.jackrabbit.spi.Name;
+import org.apache.jackrabbit.spi.Path;
+import org.apache.jackrabbit.value.BinaryImpl;
+
+/**
+ * <code>QValue</code> implementation for all valid <code>PropertyType</code>s
+ * except for BINARY.
+ */
+public class DefaultQValue extends AbstractQValue implements Serializable {
+
+    private static final long serialVersionUID = -3887529703765183611L;
+
+    protected static final QValue TRUE = new DefaultQValue(Boolean.TRUE);
+    protected static final QValue FALSE = new DefaultQValue(Boolean.FALSE);
+
+    public DefaultQValue(String value, int type) {
+        super(value, type);
+    }
+
+    public DefaultQValue(Long value) {
+        super(value);
+    }
+
+    public DefaultQValue(Double value) {
+        super(value);
+    }
+
+    public DefaultQValue(BigDecimal value) {
+        super(value);
+    }
+
+    public DefaultQValue(Boolean value) {
+        super(value);
+    }
+
+    public DefaultQValue(Name value) {
+        super(value);
+    }
+
+    public DefaultQValue(Path value) {
+        super(value);
+    }
+
+    public DefaultQValue(URI value) {
+        super(value);
+    }
+
+    protected DefaultQValue(Calendar value) {
+        super(value);
+    }
+
+    //-------------------------------------------------------------< QValue >---
+
+    /**
+     * @see QValue#getBinary()
+     */
+    public Binary getBinary() throws RepositoryException {
+        try {
+            // convert via string
+            return new BinaryImpl(getString().getBytes(
+                    AbstractQValueFactory.DEFAULT_ENCODING));
+        } catch (IOException e) {
+            throw new RepositoryException(e);
+        }
+    }
+
+    /**
+     * @see QValue#getStream()
+     */
+    public InputStream getStream() throws RepositoryException {
+        try {
+            // convert via string
+            return new ByteArrayInputStream(getString().getBytes(
+                    AbstractQValueFactory.DEFAULT_ENCODING));
+        } catch (UnsupportedEncodingException e) {
+            throw new RepositoryException(QValueFactoryImpl.DEFAULT_ENCODING +
+                    " is not supported encoding on this platform", e);
+        }
+    }
+}

Propchange: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/value/DefaultQValue.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/value/QValueFactoryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/value/QValueFactoryImpl.java?rev=802695&r1=802694&r2=802695&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/value/QValueFactoryImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/value/QValueFactoryImpl.java Mon Aug 10 08:37:58 2009
@@ -20,15 +20,12 @@
 import org.apache.jackrabbit.spi.Path;
 import org.apache.jackrabbit.spi.QValue;
 import org.apache.jackrabbit.spi.QValueFactory;
-import org.apache.jackrabbit.util.ISO8601;
 import org.apache.jackrabbit.util.TransientFileFactory;
 
 import javax.jcr.PropertyType;
 import javax.jcr.RepositoryException;
-import javax.jcr.ValueFormatException;
 import javax.jcr.Binary;
 import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
@@ -39,157 +36,23 @@
 import java.io.ObjectOutputStream;
 import java.io.OutputStream;
 import java.io.Serializable;
-import java.io.UnsupportedEncodingException;
 import java.io.RandomAccessFile;
 import java.util.Arrays;
-import java.util.Calendar;
-import java.math.BigDecimal;
-import java.net.URI;
-import java.net.URISyntaxException;
 
 /**
  * <code>QValueFactoryImpl</code>...
  */
-public final class QValueFactoryImpl extends AbstractQValueFactory {
+public class QValueFactoryImpl extends AbstractQValueFactory {
 
     private static final QValueFactory INSTANCE = new QValueFactoryImpl();
 
-    private QValueFactoryImpl() {
+    protected QValueFactoryImpl() {
     }
 
     public static QValueFactory getInstance() {
         return INSTANCE;
     }
 
-    //------------------------------------------------------< QValueFactory >---
-    /**
-     * @see QValueFactory#create(String, int)
-     */
-    public QValue create(String value, int type) throws RepositoryException {
-        if (value == null) {
-            throw new IllegalArgumentException("Cannot create QValue from null value.");
-        }
-
-        try {
-            switch (type) {
-                case PropertyType.BOOLEAN:
-                    return (Boolean.valueOf(value).booleanValue()) ?
-                            QValueImpl.TRUE :
-                            QValueImpl.FALSE;
-                case PropertyType.DATE: {
-                        Calendar cal = ISO8601.parse(value);
-                        if (cal == null) {
-                            throw new ValueFormatException("not a valid date: " + value);
-                        }
-                        return new DateQValue(cal);
-                    }
-                case PropertyType.DOUBLE:
-                    return new QValueImpl(Double.valueOf(value));
-                case PropertyType.LONG:
-                    return new QValueImpl(Long.valueOf(value));
-                case PropertyType.DECIMAL:
-                    return new QValueImpl(new BigDecimal(value));
-                case PropertyType.URI:
-                    return new QValueImpl(URI.create(value));
-                case PropertyType.PATH:
-                    return new QValueImpl(PATH_FACTORY.create(value));
-                case PropertyType.NAME:
-                    return new QValueImpl(NAME_FACTORY.create(value));
-                case PropertyType.STRING:
-                case PropertyType.REFERENCE:
-                case PropertyType.WEAKREFERENCE:
-                    return new QValueImpl(value, type);
-                case PropertyType.BINARY:
-                    return new BinaryQValue(value.getBytes(DEFAULT_ENCODING));
-                // default: invalid type specified -> see below.
-            }
-        } catch (IllegalArgumentException ex) {
-            // given String value cannot be converted to Long/Double/Path/Name
-            throw new ValueFormatException(ex);
-        } catch (UnsupportedEncodingException ex) {
-            throw new RepositoryException(ex);
-        }
-
-        // invalid type specified:
-        throw new IllegalArgumentException("illegal type " + type);
-    }
-
-    /**
-     * @see QValueFactory#create(Calendar)
-     */
-    public QValue create(Calendar value) {
-        if (value == null) {
-            throw new IllegalArgumentException("Cannot create QValue from null value.");
-        }
-        // Calendar is not constant, must create a clone
-        return new DateQValue((Calendar) value.clone());
-    }
-
-    /**
-     * @see QValueFactory#create(double)
-     */
-    public QValue create(double value) {
-        return new QValueImpl(Double.valueOf(value));
-    }
-
-    /**
-     * @see QValueFactory#create(long)
-     */
-    public QValue create(long value) {
-        return new QValueImpl(Long.valueOf(value));
-    }
-
-    /**
-     * @see QValueFactory#create(boolean)
-     */
-    public QValue create(boolean value) {
-        if (value) {
-            return QValueImpl.TRUE;
-        } else {
-            return QValueImpl.FALSE;
-        }
-    }
-
-    /**
-     * @see QValueFactory#create(Name)
-     */
-    public QValue create(Name value) {
-        if (value == null) {
-            throw new IllegalArgumentException("Cannot create QValue from null value.");
-        }
-        return new QValueImpl(value);
-    }
-
-    /**
-     * @see QValueFactory#create(Path)
-     */
-    public QValue create(Path value) {
-        if (value == null) {
-            throw new IllegalArgumentException("Cannot create QValue from null value.");
-        }
-        return new QValueImpl(value);
-    }
-
-    /**
-     * @see QValueFactory#create(URI)
-     */
-    public QValue create(URI value) {
-        if (value == null) {
-            throw new IllegalArgumentException("Cannot create QValue from null value.");
-        }
-        return new QValueImpl(value);
-    }
-
-    /**
-     * @see QValueFactory#create(URI)
-     */
-    public QValue create(BigDecimal value) {
-        if (value == null) {
-            throw new IllegalArgumentException("Cannot create QValue from null value.");
-        }
-        return new QValueImpl(value);
-    }
-
     /**
      * @see QValueFactory#create(byte[])
      */
@@ -220,162 +83,23 @@
         return new BinaryQValue(value);
     }
 
-
     //--------------------------------------------------------< Inner Class >---
-    /**
-     * <code>QValue</code> implementation for all valid <code>PropertyType</code>s
-     * except for BINARY and DATE.
-     * @see QValueFactoryImpl.BinaryQValue
-     */
-    private static class QValueImpl extends AbstractQValue implements Serializable {
-
-        private static final QValue TRUE = new QValueImpl(Boolean.TRUE);
-        private static final QValue FALSE = new QValueImpl(Boolean.FALSE);
-
-
-        private QValueImpl(Object value, int type) {
-            super(value, type);
-        }
-
-        private QValueImpl(String value, int type) {
-            super(value, type);
-        }
-
-        private QValueImpl(Long value) {
-            super(value);
-        }
-
-        private QValueImpl(Double value) {
-            super(value);
-        }
-
-        private QValueImpl(BigDecimal value) {
-            super(value);
-        }
-
-        private QValueImpl(Boolean value) {
-            super(value);
-        }
-
-        private QValueImpl(Name value) {
-            super(value);
-        }
-
-        private QValueImpl(Path value) {
-            super(value);
-        }
 
-        private QValueImpl(URI value) {
-            super(value);
-        }
-
-        //---------------------------------------------------------< QValue >---
-        /**
-         * @see QValue#getString()
-         */
-        public String getString() {
-            return val.toString();
-        }
-
-        /**
-         * @see QValue#getBinary()
-         */
-        public Binary getBinary() throws RepositoryException {
-            // TODO FIXME consolidate Binary implementations
-            return new Binary() {
-                public InputStream getStream() throws RepositoryException {
-                    return QValueImpl.this.getStream();
-                }
-
-                public int read(byte[] b, long position) throws IOException, RepositoryException {
-                    InputStream in = getStream();
-                    try {
-                        in.skip(position);
-                        return in.read(b);
-                    } finally {
-                        in.close();
-                    }
-                }
-
-                public long getSize() throws RepositoryException {
-                    return getLength();
-                }
-
-                public void dispose() {
-                }
-
-            };
-        }
-
-        /**
-         * @see QValue#getStream()
-         */
-        public InputStream getStream() throws RepositoryException {
-            try {
-                // convert via string
-                return new ByteArrayInputStream(getString().getBytes(DEFAULT_ENCODING));
-            } catch (UnsupportedEncodingException e) {
-                throw new RepositoryException(QValueFactoryImpl.DEFAULT_ENCODING + " is not supported encoding on this platform", e);
-            }
-    }
-    }
-
-    //--------------------------------------------------------< Inner Class >---
-    /**
-     * Extension for values of type {@link PropertyType#DATE}.
-     */
-    private static class DateQValue extends QValueImpl {
-
-        private final String formattedStr;
-
-        private DateQValue(Calendar value) {
-            super(value, PropertyType.DATE);
-            formattedStr = ISO8601.format(value);
-        }
-
-        /**
-         * @return The formatted String of the internal Calendar value.
-         * @see QValue#getString()
-         * @see ISO8601#format(Calendar)
-         */
-        public String getString() {
-            return formattedStr;
-        }
-
-        /**
-         * @param obj
-         * @return true if the given Object is a <code>DateQValue</code> with an
-         * equal String representation.
-         * @see Object#equals(Object)
-         */
-        public boolean equals(Object obj) {
-            if (this == obj) {
-                return true;
-            }
-            if (obj instanceof DateQValue) {
-                DateQValue other = (DateQValue) obj;
-                return formattedStr.equals(other.formattedStr);
-            }
-            return false;
-        }
-
-        /**
-         * @return the hashCode of the formatted String of the Calender value.
-         * @see Object#hashCode()
-         */
-        public int hashCode() {
-            return formattedStr.hashCode();
-        }
-    }
-
-    //--------------------------------------------------------< Inner Class >---
     /**
      * <code>BinaryQValue</code> represents a binary <code>Value</code> which is
      * backed by a resource or byte[]. Unlike <code>BinaryValue</code> it has no
      * state, i.e. the <code>getStream()</code> method always returns a fresh
      * <code>InputStream</code> instance.
      */
-    private static class BinaryQValue implements QValue, Binary, Serializable {
+    private static class BinaryQValue extends AbstractQValue implements Binary, Serializable {
+
+        /**
+         * A dummy value for calling the constructor of AbstractQValue
+         */
+        private static final Object DUMMY_VALUE = new Serializable() {
+            private static final long serialVersionUID = 2849470089518940117L;
+        };
+
         /**
          * empty array
          */
@@ -404,11 +128,6 @@
         private byte[] buffer = BinaryQValue.EMPTY_BYTE_ARRAY;
 
         /**
-         * Converted text
-         */
-        private transient String text = null;
-
-        /**
          * Creates a new <code>BinaryQValue</code> instance from an
          * <code>InputStream</code>. The contents of the stream is spooled
          * to a temporary file or to a byte buffer if its size is smaller than
@@ -444,6 +163,7 @@
          *                     writing to the temporary file
          */
         private BinaryQValue(InputStream in, boolean temp) throws IOException {
+            super(DUMMY_VALUE, PropertyType.BINARY);
             byte[] spoolBuffer = new byte[0x2000];
             int read;
             int len = 0;
@@ -495,6 +215,7 @@
          *              instance
          */
         private BinaryQValue(byte[] bytes) {
+            super(DUMMY_VALUE, PropertyType.BINARY);
             buffer = bytes;
             file = null;
             // this instance is not backed by a temporarily allocated buffer
@@ -508,6 +229,7 @@
          * @throws IOException if the file can not be read
          */
         private BinaryQValue(File file) throws IOException {
+            super(DUMMY_VALUE, PropertyType.BINARY);
             String path = file.getCanonicalPath();
             if (!file.isFile()) {
                 throw new IOException(path + ": the specified file does not exist");
@@ -523,12 +245,6 @@
         }
 
         //---------------------------------------------------------< QValue >---
-        /**
-         * @see QValue#getType()
-         */
-        public int getType() {
-            return PropertyType.BINARY;
-        }
 
         /**
          * Returns the length of this <code>BinaryQValue</code>.
@@ -552,32 +268,6 @@
         }
 
         /**
-         * @see QValue#getString()
-         */
-        public String getString() throws RepositoryException {
-            if (text == null) {
-                ByteArrayOutputStream out = new ByteArrayOutputStream();
-                try {
-                    spool(out);
-                    byte[] data = out.toByteArray();
-                    text = new String(data, QValueFactoryImpl.DEFAULT_ENCODING);
-                } catch (UnsupportedEncodingException e) {
-                    throw new RepositoryException(QValueFactoryImpl.DEFAULT_ENCODING
-                        + " not supported on this platform", e);
-                } catch (IOException e) {
-                    throw new ValueFormatException("conversion from stream to string failed", e);
-                } finally {
-                    try {
-                        out.close();
-                    } catch (IOException e) {
-                        // ignore
-                    }
-                }
-            }
-            return text;
-        }
-
-        /**
          * @see QValue#getStream()
          */
         public InputStream getStream() throws RepositoryException {
@@ -603,47 +293,6 @@
         }
 
         /**
-         * @see QValue#getCalendar()
-         */
-        public Calendar getCalendar() throws RepositoryException {
-             Calendar cal = ISO8601.parse(getString());
-             if (cal == null) {
-                 throw new ValueFormatException("not a date string: " + getString());
-             } else {
-                 return cal;
-             }
-        }
-
-        /**
-         * @see QValue#getDouble()
-         */
-        public double getDouble() throws RepositoryException {
-            try {
-                return Double.parseDouble(getString());
-            } catch (NumberFormatException ex) {
-                throw new ValueFormatException(ex);
-            }
-        }
-
-        /**
-         * @see QValue#getLong()
-         */
-        public long getLong() throws RepositoryException {
-            try {
-                return Long.parseLong(getString());
-            } catch (NumberFormatException ex) {
-                throw new ValueFormatException(ex);
-            }
-        }
-
-        /**
-         * @see QValue#getBoolean()
-         */
-        public boolean getBoolean() throws RepositoryException {
-            return Boolean.valueOf(getString());
-        }
-
-        /**
          * @see QValue#getPath()
          */
         public Path getPath() throws RepositoryException {
@@ -651,28 +300,6 @@
         }
 
         /**
-         * @see QValue#getDecimal()
-         */
-        public BigDecimal getDecimal() throws RepositoryException {
-            try {
-                return new BigDecimal(getString());
-            } catch (NumberFormatException ex) {
-                throw new ValueFormatException(ex);
-            }
-        }
-
-        /**
-         * @see QValue#getURI()
-         */
-        public URI getURI() throws RepositoryException {
-            try {
-                return new URI(getString());
-            } catch (URISyntaxException ex) {
-                throw new ValueFormatException(ex);
-            }
-        }
-
-        /**
          * @see QValue#getBinary()
          */
         public Binary getBinary() throws RepositoryException {
@@ -750,44 +377,6 @@
             return 0;
         }
 
-        //----------------------------------------------------------------------
-        /**
-         * Spools the contents of this <code>BinaryQValue</code> to the given
-         * output stream.
-         *
-         * @param out output stream
-         * @throws RepositoryException if the input stream for this
-         *                             <code>BinaryQValue</code> could not be obtained
-         * @throws IOException         if an error occurs while while spooling
-         */
-        private void spool(OutputStream out) throws RepositoryException, IOException {
-            InputStream in;
-            if (file != null) {
-                // this instance is backed by a 'real' file
-                try {
-                    in = new FileInputStream(file);
-                } catch (FileNotFoundException fnfe) {
-                    throw new RepositoryException("file backing binary value not found",
-                        fnfe);
-                }
-            } else {
-                // this instance is backed by an in-memory buffer
-                in = new ByteArrayInputStream(buffer);
-            }
-            try {
-                byte[] buffer = new byte[0x2000];
-                int read;
-                while ((read = in.read(buffer)) > 0) {
-                    out.write(buffer, 0, read);
-                }
-            } finally {
-                try {
-                    in.close();
-                } catch (IOException ignore) {
-                }
-            }
-        }
-
         //-----------------------------< javx.jcr.Binary >----------------------
         /**
          * {@inheritDoc}