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 2005/04/28 15:07:00 UTC

svn commit: r165135 [2/3] - in /incubator/jackrabbit/trunk/src: java/org/apache/jackrabbit/core/ java/org/apache/jackrabbit/core/lock/ java/org/apache/jackrabbit/core/nodetype/ java/org/apache/jackrabbit/core/nodetype/virtual/ java/org/apache/jackrabbit/core/nodetype/xml/ java/org/apache/jackrabbit/core/query/ java/org/apache/jackrabbit/core/query/lucene/ java/org/apache/jackrabbit/core/query/sql/ java/org/apache/jackrabbit/core/query/xpath/ java/org/apache/jackrabbit/core/state/ java/org/apache/jackrabbit/core/state/mem/ java/org/apache/jackrabbit/core/state/obj/ java/org/apache/jackrabbit/core/state/xml/ java/org/apache/jackrabbit/core/util/ java/org/apache/jackrabbit/core/util/uuid/ java/org/apache/jackrabbit/core/value/ java/org/apache/jackrabbit/core/version/ java/org/apache/jackrabbit/core/version/persistence/ java/org/apache/jackrabbit/core/virtual/ java/org/apache/jackrabbit/core/xml/ test/org/apache/jackrabbit/core/nodetype/xml/

Added: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/value/BLOBFileValue.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/value/BLOBFileValue.java?rev=165135&view=auto
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/value/BLOBFileValue.java (added)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/value/BLOBFileValue.java Thu Apr 28 06:06:58 2005
@@ -0,0 +1,461 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation or its licensors,
+ *                     as applicable.
+ *
+ * Licensed 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.core.value;
+
+import org.apache.jackrabbit.core.fs.FileSystemException;
+import org.apache.jackrabbit.core.fs.FileSystemResource;
+import org.apache.jackrabbit.core.util.ISO8601;
+
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+import javax.jcr.Value;
+import javax.jcr.ValueFormatException;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+import java.util.Arrays;
+import java.util.Calendar;
+
+/**
+ * <code>BLOBFileValue</code> represents a binary <code>Value</code> that
+ * is backed by a file. Unlike <code>javax.jcr.BinaryValue</code> it has no
+ * state, i.e. the <code>getStream()</code> method always returns a fresh
+ * <code>InputStream</code> instance.
+ */
+public class BLOBFileValue implements Value {
+
+    /**
+     * the property type
+     */
+    public static final int TYPE = PropertyType.BINARY;
+
+    /**
+     * the default encoding
+     */
+    protected static final String DEFAULT_ENCODING = "UTF-8";
+
+    /**
+     * empty array
+     */
+    private static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
+
+    /**
+     * max size for keeping tmp data in memory
+     */
+    private static final int MAX_BUFFER_SIZE = 0x10000;
+
+    /**
+     * underlying file
+     */
+    private final File file;
+
+    /**
+     * flag indicating if this instance is backed by a temp file
+     */
+    private final boolean tmpFile;
+
+    /**
+     * buffer for small-sized data
+     */
+    private byte[] buffer = EMPTY_BYTE_ARRAY;
+
+    /**
+     * underlying file system resource
+     */
+    private final FileSystemResource fsResource;
+
+    /**
+     * converted text
+     */
+    private String text = null;
+
+    /**
+     * Creates a new <code>BLOBFileValue</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
+     * {@link #MAX_BUFFER_SIZE}.
+     *
+     * @param in stream to be represented as a <code>BLOBFileValue</code> instance
+     * @throws IOException if an error occurs while reading from the stream or
+     *                     writing to the temporary file
+     */
+    public BLOBFileValue(InputStream in) throws IOException {
+        byte[] spoolBuffer = new byte[0x2000];
+        int read;
+        int len = 0;
+        OutputStream out = null;
+        File spoolFile = null;
+        try {
+            while ((read = in.read(spoolBuffer)) > 0) {
+                if (out != null) {
+                    // spool to temp file
+                    out.write(spoolBuffer, 0, read);
+                    len += read;
+                } else if (len + read > MAX_BUFFER_SIZE) {
+                    // threshold for keeping data in memory exceeded;
+                    // create temp file and spool buffer contents
+                    spoolFile = File.createTempFile("bin", null);
+                    spoolFile.deleteOnExit();
+                    out = new FileOutputStream(spoolFile);
+                    out.write(buffer, 0, len);
+                    out.write(spoolBuffer, 0, read);
+                    buffer = null;
+                    len += read;
+                } else {
+                    // reallocate new buffer and spool old buffer contents
+                    byte[] newBuffer = new byte[len + read];
+                    System.arraycopy(buffer, 0, newBuffer, 0, len);
+                    System.arraycopy(spoolBuffer, 0, newBuffer, len, read);
+                    buffer = newBuffer;
+                    len += read;
+                }
+            }
+        } finally {
+            in.close();
+            if (out != null) {
+                out.close();
+            }
+        }
+
+        // init vars
+        file = spoolFile;
+        fsResource = null;
+        tmpFile = true;
+    }
+
+    /**
+     * Creates a new <code>BLOBFileValue</code> instance from a <code>File</code>.
+     *
+     * @param file file to be represented as a <code>BLOBFileValue</code> instance
+     * @throws IOException if the file can not be read
+     */
+    public BLOBFileValue(File file) throws IOException {
+        String path = file.getCanonicalPath();
+        if (!file.isFile()) {
+            throw new IOException(path + ": the specified file does not exist");
+        }
+        if (!file.canRead()) {
+            throw new IOException(path + ": the specified file can not be read");
+        }
+        this.file = file;
+        // this instance is backed by a 'real' file; set virtual fs resource to null
+        fsResource = null;
+
+        tmpFile = false;
+    }
+
+    /**
+     * Creates a new <code>BLOBFileValue</code> instance from a resource in the
+     * virtual file system.
+     *
+     * @param fsResource resource in virtual file system
+     * @throws IOException if the resource can not be read
+     */
+    public BLOBFileValue(FileSystemResource fsResource) throws IOException {
+        try {
+            if (!fsResource.exists()) {
+                throw new IOException(fsResource.getPath()
+                        + ": the specified resource does not exist");
+            }
+        } catch (FileSystemException fse) {
+            throw new IOException(fsResource.getPath()
+                    + ": the specified resource does not exist");
+        }
+        // this instance is backed by a resource in the virtual file system
+        this.fsResource = fsResource;
+        // set 'real' file to null
+        file = null;
+
+        tmpFile = false;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof BLOBFileValue) {
+            BLOBFileValue other = (BLOBFileValue) obj;
+            return ((file == null ? other.file == null : file.equals(other.file))
+                    && (fsResource == null ? other.fsResource == null : fsResource.equals(other.fsResource))
+                    && Arrays.equals(buffer, other.buffer));
+        }
+        return false;
+    }
+
+    /**
+     * Returns the length of this <code>BLOBFileValue</code>.
+     *
+     * @return The length, in bytes, of this <code>BLOBFileValue</code>,
+     *         or -1L if the length can't be determined.
+     */
+    public long getLength() {
+        if (file != null) {
+            // this instance is backed by a 'real' file
+            if (file.exists()) {
+                return file.length();
+            } else {
+                return -1;
+            }
+        } else if (fsResource != null) {
+            // this instance is backed by a resource in the virtual file system
+            try {
+                return fsResource.length();
+            } catch (FileSystemException fse) {
+                return -1;
+            }
+        } else {
+            // this instance is backed by a in-memory buffer
+            return buffer.length;
+        }
+    }
+
+    /**
+     * Returns <code>true</code> it this <code>BLOBFileValue</code> is backed
+     * by a temporary file.
+     *
+     * @return <code>true</code> it this <code>BLOBFileValue</code> is backed
+     *         by a temporary file.
+     */
+    public boolean isTempFile() {
+        return tmpFile;
+    }
+
+    /**
+     * Deletes the file backing this <code>BLOBFileValue</code>.
+     * Same as <code>{@link #delete(false)}</code>.
+     */
+    public void delete() {
+        delete(false);
+    }
+
+    /**
+     * Deletes the file backing this <code>BLOBFileValue</code>.
+     *
+     * @param pruneEmptyParentDirs if <code>true</code>, empty parent directories
+     *                             will automatically be deleted
+     */
+    public void delete(boolean pruneEmptyParentDirs) {
+        if (file != null) {
+            // this instance is backed by a 'real' file
+            file.delete();
+            if (pruneEmptyParentDirs) {
+                // prune empty parent directories
+                File parent = file.getParentFile();
+                while (parent != null && parent.delete()) {
+                    parent = parent.getParentFile();
+                }
+            }
+        } else if (fsResource != null) {
+            // this instance is backed by a resource in the virtual file system
+            try {
+                fsResource.delete(pruneEmptyParentDirs);
+            } catch (FileSystemException fse) {
+                // ignore
+            }
+        } else {
+            // this instance is backed by a in-memory buffer
+            buffer = EMPTY_BYTE_ARRAY;
+        }
+    }
+
+    /**
+     * Spools the contents of this <code>BLOBFileValue</code> to the given
+     * output stream.
+     *
+     * @param out output stream
+     * @throws RepositoryException if the input stream for this
+     *                             <code>BLOBFileValue</code> could not be obtained
+     * @throws IOException         if an error occurs while while spooling
+     */
+    public 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 if (fsResource != null) {
+            // this instance is backed by a resource in the virtual file system
+            try {
+                in = fsResource.getInputStream();
+            } catch (FileSystemException fse) {
+                throw new RepositoryException(fsResource.getPath()
+                        + ": the specified resource does not exist", fse);
+            }
+        } else {
+            // this instance is backed by a 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) {
+            }
+        }
+    }
+
+    //-------------------------------------------< java.lang.Object overrides >
+    /**
+     * Returns the path string of the backing file.
+     *
+     * @return The path string of the backing file.
+     */
+    public String toString() {
+        if (file != null) {
+            // this instance is backed by a 'real' file
+            return file.toString();
+        } else if (fsResource != null) {
+            // this instance is backed by a resource in the virtual file system
+            return fsResource.toString();
+        } else {
+            // this instance is backed by a in-memory buffer
+            return buffer.toString();
+        }
+    }
+
+    //----------------------------------------------------------------< Value >
+    /**
+     * {@inheritDoc}
+     */
+    public int getType() {
+        return TYPE;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String getString()
+            throws ValueFormatException, IllegalStateException,
+            RepositoryException {
+        if (text == null) {
+            ByteArrayOutputStream out = new ByteArrayOutputStream();
+            try {
+                spool(out);
+                byte[] data = out.toByteArray();
+                text = new String(data, DEFAULT_ENCODING);
+            } catch (UnsupportedEncodingException e) {
+                throw new RepositoryException(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;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public InputStream getStream()
+            throws ValueFormatException, IllegalStateException,
+            RepositoryException {
+        // always return a 'fresh' stream
+        if (file != null) {
+            // this instance is backed by a 'real' file
+            try {
+                return new FileInputStream(file);
+            } catch (FileNotFoundException fnfe) {
+                throw new RepositoryException("file backing binary value not found",
+                        fnfe);
+            }
+        } else if (fsResource != null) {
+            // this instance is backed by a resource in the virtual file system
+            try {
+                return fsResource.getInputStream();
+            } catch (FileSystemException fse) {
+                throw new RepositoryException(fsResource.getPath()
+                        + ": the specified resource does not exist", fse);
+            }
+        } else {
+            return new ByteArrayInputStream(buffer);
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public double getDouble()
+            throws ValueFormatException, IllegalStateException,
+            RepositoryException {
+        try {
+            return Double.parseDouble(getString());
+        } catch (NumberFormatException e) {
+            throw new ValueFormatException("conversion to double failed", e);
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Calendar getDate()
+            throws ValueFormatException, IllegalStateException,
+            RepositoryException {
+        Calendar cal = ISO8601.parse(getString());
+        if (cal != null) {
+            return cal;
+        } else {
+            throw new ValueFormatException("not a valid date format");
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public long getLong()
+            throws ValueFormatException, IllegalStateException,
+            RepositoryException {
+        try {
+            return Long.parseLong(getString());
+        } catch (NumberFormatException e) {
+            throw new ValueFormatException("conversion to long failed", e);
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean getBoolean()
+            throws ValueFormatException, IllegalStateException,
+            RepositoryException {
+        return Boolean.valueOf(getString()).booleanValue();
+    }
+}

Propchange: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/value/BLOBFileValue.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/value/BaseValue.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/value/BaseValue.java?rev=165135&view=auto
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/value/BaseValue.java (added)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/value/BaseValue.java Thu Apr 28 06:06:58 2005
@@ -0,0 +1,209 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation or its licensors,
+ *                     as applicable.
+ *
+ * Licensed 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.core.value;
+
+import org.apache.jackrabbit.core.util.ISO8601;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.Value;
+import javax.jcr.ValueFormatException;
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.util.Calendar;
+
+/**
+ * This class is the superclass of the type-specific
+ * classes implementing the <code>Value</code> interfaces.
+ *
+ * @see Value
+ * @see StringValue
+ * @see LongValue
+ * @see DoubleValue
+ * @see BooleanValue
+ * @see DateValue
+ * @see BinaryValue
+ * @see NameValue
+ * @see PathValue
+ * @see ReferenceValue
+ */
+public abstract class BaseValue implements Value {
+
+    protected static final String DEFAULT_ENCODING = "UTF-8";
+
+    private static final short STATE_UNDEFINED = 0;
+    private static final short STATE_VALUE_CONSUMED = 1;
+    private static final short STATE_STREAM_CONSUMED = 2;
+
+    private short state = STATE_UNDEFINED;
+
+    protected final int type;
+
+    protected InputStream stream = null;
+
+    /**
+     * Package-private default constructor.
+     *
+     * @param type The type of this value.
+     */
+    BaseValue(int type) {
+        this.type = type;
+    }
+
+    /**
+     * Checks if the non-stream value of this instance has already been
+     * consumed (if any getter methods except <code>{@link #getStream()}</code> and
+     * <code>{@link #getType()}</code> have been previously called at least once) and
+     * sets the state to <code>STATE_STREAM_CONSUMED</code>.
+     *
+     * @throws IllegalStateException if any getter methods other than
+     *                               <code>getStream()</code> and
+     *                               <code>getType()</code> have been
+     *                               previously called at least once.
+     */
+    protected void setStreamConsumed() throws IllegalStateException {
+        if (state == STATE_VALUE_CONSUMED) {
+            throw new IllegalStateException("non-stream value has already been consumed");
+        }
+        state = STATE_STREAM_CONSUMED;
+    }
+
+    /**
+     * Checks if the stream value of this instance has already been
+     * consumed (if {@link #getStream()} has been previously called
+     * at least once) and sets the state to <code>STATE_VALUE_CONSUMED</code>.
+     *
+     * @throws IllegalStateException if <code>getStream()</code> has been
+     *                               previously called at least once.
+     */
+    protected void setValueConsumed() throws IllegalStateException {
+        if (state == STATE_STREAM_CONSUMED) {
+            throw new IllegalStateException("stream value has already been consumed");
+        }
+        state = STATE_VALUE_CONSUMED;
+    }
+
+    /**
+     * Returns the internal string representation of this value without modifying
+     * the value state.
+     *
+     * @return the internal string representation
+     * @throws ValueFormatException if the value can not be represented as a
+     *                              <code>String</code> or if the value is
+     *                              <code>null</code>.
+     * @throws RepositoryException  if another error occurs.
+     */
+    protected abstract String getInternalString()
+            throws ValueFormatException, RepositoryException;
+
+    //----------------------------------------------------------------< Value >
+    /**
+     * {@inheritDoc}
+     */
+    public int getType() {
+        return type;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Calendar getDate()
+            throws ValueFormatException, IllegalStateException,
+            RepositoryException {
+        setValueConsumed();
+
+        Calendar cal = ISO8601.parse(getInternalString());
+        if (cal == null) {
+            throw new ValueFormatException("not a valid date format");
+        } else {
+            return cal;
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public long getLong()
+            throws ValueFormatException, IllegalStateException,
+            RepositoryException {
+        setValueConsumed();
+
+        try {
+            return Long.parseLong(getInternalString());
+        } catch (NumberFormatException e) {
+            throw new ValueFormatException("conversion to long failed", e);
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean getBoolean()
+            throws ValueFormatException, IllegalStateException,
+            RepositoryException {
+        setValueConsumed();
+
+        return Boolean.valueOf(getInternalString()).booleanValue();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public double getDouble()
+            throws ValueFormatException, IllegalStateException,
+            RepositoryException {
+        setValueConsumed();
+
+        try {
+            return Double.parseDouble(getInternalString());
+        } catch (NumberFormatException e) {
+            throw new ValueFormatException("conversion to double failed", e);
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public InputStream getStream()
+            throws IllegalStateException, RepositoryException {
+        setStreamConsumed();
+
+        if (stream != null) {
+            return stream;
+        }
+
+        try {
+            // convert via string
+            stream = new ByteArrayInputStream(getInternalString().getBytes(DEFAULT_ENCODING));
+            return stream;
+        } catch (UnsupportedEncodingException e) {
+            throw new RepositoryException(DEFAULT_ENCODING
+                    + " not supported on this platform", e);
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String getString()
+            throws ValueFormatException, IllegalStateException,
+            RepositoryException {
+        setValueConsumed();
+
+        return getInternalString();
+    }
+}

Propchange: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/value/BaseValue.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/value/BinaryValue.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/value/BinaryValue.java?rev=165135&view=auto
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/value/BinaryValue.java (added)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/value/BinaryValue.java Thu Apr 28 06:06:58 2005
@@ -0,0 +1,182 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation or its licensors,
+ *                     as applicable.
+ *
+ * Licensed 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.core.value;
+
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+import javax.jcr.ValueFormatException;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+
+/**
+ * A <code>BinaryValue</code> provides an implementation
+ * of the <code>Value</code> interface representing a binary value.
+ */
+public class BinaryValue extends BaseValue {
+
+    public static final int TYPE = PropertyType.BINARY;
+
+    // those fields are mutually exclusive, i.e. only one can be non-null
+    private byte[] streamData = null;
+    private String text = null;
+
+    /**
+     * Constructs a <code>BinaryValue</code> object based on a string.
+     *
+     * @param text the string this <code>BinaryValue</code> should represent
+     */
+    public BinaryValue(String text) {
+        super(TYPE);
+        this.text = text;
+    }
+
+    /**
+     * Constructs a <code>BinaryValue</code> object based on a stream.
+     *
+     * @param stream the stream this <code>BinaryValue</code> should represent
+     */
+    public BinaryValue(InputStream stream) {
+        super(TYPE);
+        this.stream = stream;
+    }
+
+    /**
+     * Constructs a <code>BinaryValue</code> object based on a stream.
+     *
+     * @param data the stream this <code>BinaryValue</code> should represent
+     */
+    public BinaryValue(byte[] data) {
+        super(TYPE);
+        streamData = data;
+    }
+
+    /**
+     * Indicates whether some other object is "equal to" this one.
+     * <p/>
+     * The result is <code>true</code> if and only if the argument is not
+     * <code>null</code> and is a <code>BinaryValue</code> object that
+     * represents the same value as this object.
+     *
+     * @param obj the reference object with which to compare.
+     * @return <code>true</code> if this object is the same as the obj
+     *         argument; <code>false</code> otherwise.
+     */
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof BinaryValue) {
+            BinaryValue other = (BinaryValue) obj;
+            if (text == other.text && stream == other.stream &&
+                    streamData == other.streamData) {
+                return true;
+            }
+            // stream, streamData and text are mutually exclusive,
+            // i.e. only one of them can be non-null
+            if (stream != null) {
+                return stream.equals(other.stream);
+            } else if (streamData != null) {
+                return streamData.equals(other.streamData);
+            } else {
+                return text.equals(other.text);
+            }
+        }
+        return false;
+    }
+
+    //------------------------------------------------------------< BaseValue >
+    /**
+     * Gets the string representation of this binary value.
+     *
+     * @return string representation of this binary value.
+     *
+     * @throws ValueFormatException
+     * @throws RepositoryException  if another error occurs
+     */
+    public String getInternalString()
+            throws ValueFormatException, RepositoryException {
+        // build text value if necessary
+        if (streamData != null) {
+            try {
+                text = new String(streamData, DEFAULT_ENCODING);
+            } catch (UnsupportedEncodingException e) {
+                throw new RepositoryException(DEFAULT_ENCODING
+                        + " not supported on this platform", e);
+            }
+            streamData = null;
+        } else if (stream != null) {
+            try {
+                ByteArrayOutputStream out = new ByteArrayOutputStream();
+                byte[] buffer = new byte[8192];
+                int read;
+                while ((read = stream.read(buffer)) > 0) {
+                    out.write(buffer, 0, read);
+                }
+                byte[] data = out.toByteArray();
+                text = new String(data, DEFAULT_ENCODING);
+            } catch (UnsupportedEncodingException e) {
+                throw new RepositoryException(DEFAULT_ENCODING
+                        + " not supported on this platform", e);
+            } catch (IOException e) {
+                throw new RepositoryException("conversion from stream to string failed", e);
+            } finally {
+                try {
+                    if (stream != null) {
+                        stream.close();
+                    }
+                } catch (IOException e) {
+                    // ignore
+                }
+            }
+            stream = null;
+        }
+
+        if (text != null) {
+            return text;
+        } else {
+            throw new ValueFormatException("empty value");
+        }
+    }
+
+    //----------------------------------------------------------------< Value >
+    /**
+     * {@inheritDoc}
+     */
+    public InputStream getStream()
+            throws IllegalStateException, RepositoryException {
+        setStreamConsumed();
+
+        // build stream value if necessary
+        if (streamData != null) {
+            stream = new ByteArrayInputStream(streamData);
+            streamData = null;
+        } else if (text != null) {
+            try {
+                stream = new ByteArrayInputStream(text.getBytes(DEFAULT_ENCODING));
+            } catch (UnsupportedEncodingException e) {
+                throw new RepositoryException(DEFAULT_ENCODING
+                        + " not supported on this platform", e);
+            }
+            text = null;
+        }
+
+        return super.getStream();
+    }
+}

Propchange: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/value/BinaryValue.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/value/BooleanValue.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/value/BooleanValue.java?rev=165135&view=auto
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/value/BooleanValue.java (added)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/value/BooleanValue.java Thu Apr 28 06:06:58 2005
@@ -0,0 +1,152 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation or its licensors,
+ *                     as applicable.
+ *
+ * Licensed 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.core.value;
+
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+import javax.jcr.ValueFormatException;
+import java.util.Calendar;
+
+/**
+ * A <code>BooleanValue</code> provides an implementation
+ * of the <code>Value</code> interface representing a boolean value.
+ */
+public class BooleanValue extends BaseValue {
+
+    public static final int TYPE = PropertyType.BOOLEAN;
+
+    private final Boolean bool;
+
+    /**
+     * Constructs a <code>BooleanValue</code> object representing a boolean.
+     *
+     * @param bool the boolean this <code>BooleanValue</code> should represent
+     */
+    public BooleanValue(Boolean bool) {
+        super(TYPE);
+        this.bool = bool;
+    }
+
+    /**
+     * Constructs a <code>BooleanValue</code> object representing a boolean.
+     *
+     * @param bool the boolean this <code>BooleanValue</code> should represent
+     */
+    public BooleanValue(boolean bool) {
+        super(TYPE);
+        this.bool = new Boolean(bool);
+    }
+
+    /**
+     * Returns a new <code>BooleanValue</code> initialized to the value
+     * represented by the specified <code>String</code>.
+     *
+     * @param s the string to be parsed.
+     * @return a newly constructed <code>BooleanValue</code> representing the
+     *         the specified value.
+     */
+    public static BooleanValue valueOf(String s) {
+        return new BooleanValue(Boolean.valueOf(s));
+    }
+
+    /**
+     * Indicates whether some other object is "equal to" this one.
+     * <p/>
+     * The result is <code>true</code> if and only if the argument is not
+     * <code>null</code> and is a <code>BooleanValue</code> object that
+     * represents the same value as this object.
+     *
+     * @param obj the reference object with which to compare.
+     * @return <code>true</code> if this object is the same as the obj
+     *         argument; <code>false</code> otherwise.
+     */
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof BooleanValue) {
+            BooleanValue other = (BooleanValue) obj;
+            if (bool == other.bool) {
+                return true;
+            } else if (bool != null && other.bool != null) {
+                return bool.equals(other.bool);
+            }
+        }
+        return false;
+    }
+
+    //------------------------------------------------------------< BaseValue >
+    /**
+     * {@inheritDoc}
+     */
+    protected String getInternalString() throws ValueFormatException {
+        if (bool != null) {
+            return bool.toString();
+        } else {
+            throw new ValueFormatException("empty value");
+        }
+    }
+
+    //----------------------------------------------------------------< Value >
+    /**
+     * {@inheritDoc}
+     */
+    public Calendar getDate()
+            throws ValueFormatException, IllegalStateException,
+            RepositoryException {
+        setValueConsumed();
+
+        throw new ValueFormatException("conversion to date failed: inconvertible types");
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public long getLong()
+            throws ValueFormatException, IllegalStateException,
+            RepositoryException {
+        setValueConsumed();
+
+        throw new ValueFormatException("conversion to long failed: inconvertible types");
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean getBoolean()
+            throws ValueFormatException, IllegalStateException,
+            RepositoryException {
+        setValueConsumed();
+
+        if (bool != null) {
+            return bool.booleanValue();
+        } else {
+            throw new ValueFormatException("empty value");
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public double getDouble()
+            throws ValueFormatException, IllegalStateException,
+            RepositoryException {
+        setValueConsumed();
+
+        throw new ValueFormatException("conversion to double failed: inconvertible types");
+    }
+}

Propchange: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/value/BooleanValue.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/value/DateValue.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/value/DateValue.java?rev=165135&view=auto
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/value/DateValue.java (added)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/value/DateValue.java Thu Apr 28 06:06:58 2005
@@ -0,0 +1,172 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation or its licensors,
+ *                     as applicable.
+ *
+ * Licensed 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.core.value;
+
+import org.apache.jackrabbit.core.util.ISO8601;
+
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+import javax.jcr.ValueFormatException;
+import java.util.Calendar;
+
+/**
+ * A <code>DateValue</code> provides an implementation
+ * of the <code>Value</code> interface representing a date value.
+ */
+public class DateValue extends BaseValue {
+
+    public static final int TYPE = PropertyType.DATE;
+
+    private final Calendar date;
+
+    /**
+     * Constructs a <code>DateValue</code> object representing a date.
+     *
+     * @param date the date this <code>DateValue</code> should represent
+     */
+    public DateValue(Calendar date) {
+        super(TYPE);
+        this.date = date;
+    }
+
+    /**
+     * Returns a new <code>DateValue</code> initialized to the value
+     * represented by the specified <code>String</code>.
+     * <p/>
+     * The specified <code>String</code> must be a ISO8601-compliant date/time
+     * string.
+     *
+     * @param s the string to be parsed.
+     * @return a newly constructed <code>DateValue</code> representing the
+     *         the specified value.
+     * @throws ValueFormatException If the <code>String</code> is not a valid
+     *                              ISO8601-compliant date/time string.
+     * @see ISO8601
+     */
+    public static DateValue valueOf(String s) throws ValueFormatException {
+        Calendar cal = ISO8601.parse(s);
+        if (cal != null) {
+            return new DateValue(cal);
+        } else {
+            throw new ValueFormatException("not a valid date format");
+        }
+    }
+
+    /**
+     * Indicates whether some other object is "equal to" this one.
+     * <p/>
+     * The result is <code>true</code> if and only if the argument is not
+     * <code>null</code> and is a <code>DateValue</code> object that
+     * represents the same value as this object.
+     *
+     * @param obj the reference object with which to compare.
+     * @return <code>true</code> if this object is the same as the obj
+     *         argument; <code>false</code> otherwise.
+     */
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof DateValue) {
+            DateValue other = (DateValue) obj;
+            if (date == other.date) {
+                return true;
+            } else if (date != null && other.date != null) {
+                return date.equals(other.date);
+            }
+        }
+        return false;
+    }
+
+
+    //------------------------------------------------------------< BaseValue >
+    /**
+     * {@inheritDoc}
+     */
+    protected String getInternalString() throws ValueFormatException {
+        if (date != null) {
+            return ISO8601.format(date);
+        } else {
+            throw new ValueFormatException("empty value");
+        }
+    }
+
+    //----------------------------------------------------------------< Value >
+    /**
+     * {@inheritDoc}
+     */
+    public Calendar getDate()
+            throws ValueFormatException, IllegalStateException,
+            RepositoryException {
+        setValueConsumed();
+
+        if (date != null) {
+            return date;
+        } else {
+            throw new ValueFormatException("empty value");
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public long getLong()
+            throws ValueFormatException, IllegalStateException,
+            RepositoryException {
+        setValueConsumed();
+
+        if (date != null) {
+            return date.getTimeInMillis();
+        } else {
+            throw new ValueFormatException("empty value");
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean getBoolean()
+            throws ValueFormatException, IllegalStateException,
+            RepositoryException {
+        setValueConsumed();
+
+        if (date != null) {
+            throw new ValueFormatException("cannot convert date to boolean");
+        } else {
+            throw new ValueFormatException("empty value");
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public double getDouble()
+            throws ValueFormatException, IllegalStateException,
+            RepositoryException {
+        setValueConsumed();
+
+        if (date != null) {
+            long ms = date.getTimeInMillis();
+            if (ms <= Double.MAX_VALUE) {
+                return ms;
+            }
+            throw new ValueFormatException("conversion from date to double failed: inconvertible types");
+        } else {
+            throw new ValueFormatException("empty value");
+        }
+    }
+}

Propchange: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/value/DateValue.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/value/DoubleValue.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/value/DoubleValue.java?rev=165135&view=auto
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/value/DoubleValue.java (added)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/value/DoubleValue.java Thu Apr 28 06:06:58 2005
@@ -0,0 +1,170 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation or its licensors,
+ *                     as applicable.
+ *
+ * Licensed 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.core.value;
+
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+import javax.jcr.ValueFormatException;
+import java.util.Calendar;
+import java.util.Date;
+
+/**
+ * A <code>DoubleValue</code> provides an implementation
+ * of the <code>Value</code> interface representing a double value.
+ */
+public class DoubleValue extends BaseValue {
+
+    public static final int TYPE = PropertyType.DOUBLE;
+
+    private final Double dblNumber;
+
+    /**
+     * Constructs a <code>DoubleValue</code> object representing a double.
+     *
+     * @param dblNumber the double this <code>DoubleValue</code> should represent
+     */
+    public DoubleValue(Double dblNumber) {
+        super(TYPE);
+        this.dblNumber = dblNumber;
+    }
+
+    /**
+     * Constructs a <code>DoubleValue</code> object representing a double.
+     *
+     * @param dbl the double this <code>DoubleValue</code> should represent
+     */
+    public DoubleValue(double dbl) {
+        super(TYPE);
+        this.dblNumber = new Double(dbl);
+    }
+
+    /**
+     * Returns a new <code>DoubleValue</code> initialized to the value
+     * represented by the specified <code>String</code>.
+     *
+     * @param s the string to be parsed.
+     * @return a newly constructed <code>DoubleValue</code> representing the
+     *         the specified value.
+     * @throws javax.jcr.ValueFormatException If the <code>String</code> does not
+     *                                        contain a parsable <code>double</code>.
+     */
+    public static DoubleValue valueOf(String s) throws ValueFormatException {
+        try {
+            return new DoubleValue(Double.parseDouble(s));
+        } catch (NumberFormatException e) {
+            throw new ValueFormatException("invalid format", e);
+        }
+    }
+
+    /**
+     * Indicates whether some other object is "equal to" this one.
+     * <p/>
+     * The result is <code>true</code> if and only if the argument is not
+     * <code>null</code> and is a <code>DoubleValue</code> object that
+     * represents the same value as this object.
+     *
+     * @param obj the reference object with which to compare.
+     * @return <code>true</code> if this object is the same as the obj
+     *         argument; <code>false</code> otherwise.
+     */
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof DoubleValue) {
+            DoubleValue other = (DoubleValue) obj;
+            if (dblNumber == other.dblNumber) {
+                return true;
+            } else if (dblNumber != null && other.dblNumber != null) {
+                return dblNumber.equals(other.dblNumber);
+            }
+        }
+        return false;
+    }
+
+    //------------------------------------------------------------< BaseValue >
+    /**
+     * {@inheritDoc}
+     */
+    protected String getInternalString() throws ValueFormatException {
+        if (dblNumber != null) {
+            return dblNumber.toString();
+        } else {
+            throw new ValueFormatException("empty value");
+        }
+    }
+
+    //----------------------------------------------------------------< Value >
+    /**
+     * {@inheritDoc}
+     */
+    public Calendar getDate()
+            throws ValueFormatException, IllegalStateException,
+            RepositoryException {
+        setValueConsumed();
+
+        if (dblNumber != null) {
+            // loosing timezone information...
+            Calendar cal = Calendar.getInstance();
+            cal.setTime(new Date(dblNumber.longValue()));
+            return cal;
+        } else {
+            throw new ValueFormatException("empty value");
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public long getLong()
+            throws ValueFormatException, IllegalStateException,
+            RepositoryException {
+        setValueConsumed();
+
+        if (dblNumber != null) {
+            return dblNumber.longValue();
+        } else {
+            throw new ValueFormatException("empty value");
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean getBoolean()
+            throws ValueFormatException, IllegalStateException,
+            RepositoryException {
+        setValueConsumed();
+
+        throw new ValueFormatException("conversion to boolean failed: inconvertible types");
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public double getDouble()
+            throws ValueFormatException, IllegalStateException,
+            RepositoryException {
+        setValueConsumed();
+
+        if (dblNumber != null) {
+            return dblNumber.doubleValue();
+        } else {
+            throw new ValueFormatException("empty value");
+        }
+    }
+}

Propchange: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/value/DoubleValue.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/value/InternalValue.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/value/InternalValue.java?rev=165135&view=auto
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/value/InternalValue.java (added)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/value/InternalValue.java Thu Apr 28 06:06:58 2005
@@ -0,0 +1,474 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation or its licensors,
+ *                     as applicable.
+ *
+ * Licensed 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.core.value;
+
+import org.apache.jackrabbit.core.IllegalNameException;
+import org.apache.jackrabbit.core.MalformedPathException;
+import org.apache.jackrabbit.core.NamespaceResolver;
+import org.apache.jackrabbit.core.NoPrefixDeclaredException;
+import org.apache.jackrabbit.core.Path;
+import org.apache.jackrabbit.core.QName;
+import org.apache.jackrabbit.core.UnknownPrefixException;
+import org.apache.jackrabbit.core.fs.FileSystemResource;
+import org.apache.jackrabbit.core.util.ISO8601;
+import org.apache.jackrabbit.core.util.uuid.UUID;
+
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+import javax.jcr.Value;
+import javax.jcr.ValueFormatException;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Calendar;
+
+/**
+ * <code>InternalValue</code> represents the internal format of a property value.
+ * <p/>
+ * The following table specifies the internal format for every property type:
+ * <pre>
+ * <table>
+ * <tr><b>PropertyType</b><td></td><td><b>Internal Format</b></td></tr>
+ * <tr>STRING<td></td><td>String</td></tr>
+ * <tr>LONG<td></td><td>Long</td></tr>
+ * <tr>DOUBLE<td></td><td>Double</td></tr>
+ * <tr>DATE<td></td><td>Calendar</td></tr>
+ * <tr>BOOLEAN<td></td><td>Boolean</td></tr>
+ * <tr>NAME<td></td><td>QName</td></tr>
+ * <tr>PATH<td></td><td>Path</td></tr>
+ * <tr>BINARY<td></td><td>BLOBFileValue</td></tr>
+ * <tr>REFERENCE<td></td><td>UUID</td></tr>
+ * </table>
+ * </pre>
+ */
+public class InternalValue {
+
+    public static final InternalValue[] EMPTY_ARRAY = new InternalValue[0];
+
+    private final Object val;
+    private final int type;
+
+    //------------------------------------------------------< factory methods >
+    /**
+     * @param value
+     * @param nsResolver
+     * @return
+     * @throws ValueFormatException
+     * @throws RepositoryException
+     */
+    public static InternalValue create(Value value, NamespaceResolver nsResolver)
+            throws ValueFormatException, RepositoryException {
+        if (value == null) {
+            throw new IllegalArgumentException("null value");
+        }
+
+        switch (value.getType()) {
+            case PropertyType.BINARY:
+                try {
+                    if (value instanceof BLOBFileValue) {
+                        return new InternalValue((BLOBFileValue) value);
+                    } else {
+                        return new InternalValue(new BLOBFileValue(value.getStream()));
+                    }
+                } catch (IOException ioe) {
+                    throw new ValueFormatException(ioe.getMessage());
+                }
+            case PropertyType.BOOLEAN:
+                return new InternalValue(value.getBoolean());
+            case PropertyType.DATE:
+                return new InternalValue(value.getDate());
+            case PropertyType.DOUBLE:
+                return new InternalValue(value.getDouble());
+            case PropertyType.LONG:
+                return new InternalValue(value.getLong());
+            case PropertyType.REFERENCE:
+                return new InternalValue(new UUID(value.getString()));
+            case PropertyType.NAME:
+                try {
+                    return new InternalValue(QName.fromJCRName(value.getString(), nsResolver));
+                } catch (IllegalNameException ine) {
+                    throw new ValueFormatException(ine.getMessage());
+                } catch (UnknownPrefixException upe) {
+                    throw new ValueFormatException(upe.getMessage());
+                }
+            case PropertyType.PATH:
+                try {
+                    return new InternalValue(Path.create(value.getString(), nsResolver, false));
+                } catch (MalformedPathException mpe) {
+                    throw new ValueFormatException(mpe.getMessage());
+                }
+            case PropertyType.STRING:
+                return new InternalValue(value.getString());
+
+            default:
+                throw new IllegalArgumentException("illegal value");
+        }
+    }
+
+    /**
+     * @param value
+     * @param targetType
+     * @param nsResolver
+     * @return
+     * @throws ValueFormatException
+     * @throws RepositoryException
+     */
+    public static InternalValue create(Value value, int targetType,
+                                       NamespaceResolver nsResolver)
+            throws ValueFormatException, RepositoryException {
+        if (value == null) {
+            throw new IllegalArgumentException("null value");
+        }
+        return create(ValueHelper.convert(value, targetType), nsResolver);
+    }
+
+    /**
+     * @param value
+     * @param targetType
+     * @param nsResolver
+     * @return
+     * @throws ValueFormatException
+     * @throws RepositoryException
+     */
+    public static InternalValue create(String value, int targetType,
+                                       NamespaceResolver nsResolver)
+            throws ValueFormatException, RepositoryException {
+        if (value == null) {
+            throw new IllegalArgumentException("null value");
+        }
+        return create(ValueHelper.convert(value, targetType), nsResolver);
+    }
+
+    /**
+     * @param value
+     * @return
+     */
+    public static InternalValue create(String value) {
+        return new InternalValue(value);
+    }
+
+    /**
+     * @param value
+     * @return
+     */
+    public static InternalValue create(long value) {
+        return new InternalValue(value);
+    }
+
+    /**
+     * @param value
+     * @return
+     */
+    public static InternalValue create(double value) {
+        return new InternalValue(value);
+    }
+
+    /**
+     * @param value
+     * @return
+     */
+    public static InternalValue create(Calendar value) {
+        return new InternalValue(value);
+    }
+
+    /**
+     * @param value
+     * @return
+     */
+    public static InternalValue create(boolean value) {
+        return new InternalValue(value);
+    }
+
+    /**
+     * @param value
+     * @return
+     * @throws IOException
+     */
+    public static InternalValue create(InputStream value) throws IOException {
+        return new InternalValue(new BLOBFileValue(value));
+    }
+
+    /**
+     * @param value
+     * @return
+     * @throws IOException
+     */
+    public static InternalValue create(FileSystemResource value)
+            throws IOException {
+        return new InternalValue(new BLOBFileValue(value));
+    }
+
+    /**
+     * @param value
+     * @return
+     * @throws IOException
+     */
+    public static InternalValue create(File value) throws IOException {
+        return new InternalValue(new BLOBFileValue(value));
+    }
+
+    /**
+     * @param value
+     * @return
+     */
+    public static InternalValue create(QName value) {
+        return new InternalValue(value);
+    }
+
+    /**
+     * @param values
+     * @return
+     */
+    public static InternalValue[] create(QName[] values) {
+        InternalValue[] ret = new InternalValue[values.length];
+        for (int i = 0; i < values.length; i++) {
+            ret[i] = new InternalValue(values[i]);
+        }
+        return ret;
+    }
+
+    /**
+     * @param values
+     * @return
+     */
+    public static InternalValue[] create(String[] values) {
+        InternalValue[] ret = new InternalValue[values.length];
+        for (int i = 0; i < values.length; i++) {
+            ret[i] = new InternalValue(values[i]);
+        }
+        return ret;
+    }
+
+    /**
+     * @param values
+     * @return
+     */
+    public static InternalValue[] create(Calendar[] values) {
+        InternalValue[] ret = new InternalValue[values.length];
+        for (int i = 0; i < values.length; i++) {
+            ret[i] = new InternalValue(values[i]);
+        }
+        return ret;
+    }
+
+    /**
+     * @param value
+     * @return
+     */
+    public static InternalValue create(Path value) {
+        return new InternalValue(value);
+    }
+
+    /**
+     * @param value
+     * @return
+     */
+    public static InternalValue create(UUID value) {
+        return new InternalValue(value);
+    }
+
+    //----------------------------------------------------< conversions, etc. >
+    /**
+     * @param nsResolver
+     * @return
+     * @throws RepositoryException
+     */
+    public Value toJCRValue(NamespaceResolver nsResolver)
+            throws RepositoryException {
+        switch (type) {
+            case PropertyType.BINARY:
+                return new BinaryValue(((BLOBFileValue) val).getStream());
+            case PropertyType.BOOLEAN:
+                return new BooleanValue(((Boolean) val));
+            case PropertyType.DATE:
+                return new DateValue((Calendar) val);
+            case PropertyType.DOUBLE:
+                return new DoubleValue((Double) val);
+            case PropertyType.LONG:
+                return new LongValue((Long) val);
+            case PropertyType.REFERENCE:
+                return ReferenceValue.valueOf(((UUID) val).toString());
+            case PropertyType.PATH:
+                try {
+                    return PathValue.valueOf(((Path) val).toJCRPath(nsResolver));
+                } catch (NoPrefixDeclaredException npde) {
+                    // should never get here...
+                    throw new RepositoryException("internal error: encountered unregistered namespace", npde);
+                }
+            case PropertyType.NAME:
+                try {
+                    return NameValue.valueOf(((QName) val).toJCRName(nsResolver));
+                } catch (NoPrefixDeclaredException npde) {
+                    // should never get here...
+                    throw new RepositoryException("internal error: encountered unregistered namespace", npde);
+                }
+            case PropertyType.STRING:
+                return new StringValue((String) val);
+            default:
+                throw new RepositoryException("illegal internal value type");
+        }
+    }
+
+    /**
+     * @return
+     */
+    public Object internalValue() {
+        return val;
+    }
+
+    /**
+     * @return
+     */
+    public int getType() {
+        return type;
+    }
+
+    /**
+     * @return
+     * @throws RepositoryException
+     */
+    public InternalValue createCopy() throws RepositoryException {
+        switch (type) {
+            case PropertyType.BINARY:
+                try {
+                    return new InternalValue(new BLOBFileValue(((BLOBFileValue) val).getStream()));
+                } catch (IOException ioe) {
+                    throw new RepositoryException("failed to copy binary value", ioe);
+                }
+            case PropertyType.BOOLEAN:
+                return new InternalValue(((Boolean) val).booleanValue());
+            case PropertyType.DATE:
+                return new InternalValue((Calendar) val);
+            case PropertyType.DOUBLE:
+                return new InternalValue(((Double) val).doubleValue());
+            case PropertyType.LONG:
+                return new InternalValue(((Long) val).longValue());
+            case PropertyType.REFERENCE:
+                return new InternalValue((UUID) val);
+            case PropertyType.PATH:
+                return new InternalValue((Path) val);
+            case PropertyType.NAME:
+                return new InternalValue((QName) val);
+            case PropertyType.STRING:
+                return new InternalValue((String) val);
+            default:
+                throw new RepositoryException("illegal internal value type");
+        }
+    }
+
+    /**
+     * Returns the string representation of this internal value. If this is a
+     * <i>binary</i> value then the path of its backing file will be returned.
+     *
+     * @return string representation of this internal value
+     */
+    public String toString() {
+        if (type == PropertyType.DATE) {
+            return ISO8601.format((Calendar) val);
+        } else {
+            return val.toString();
+        }
+    }
+
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof InternalValue) {
+            InternalValue other = (InternalValue) obj;
+            return val.equals(other.val);
+        }
+        return false;
+    }
+
+    /**
+     * @param s
+     * @param type
+     * @return
+     */
+    public static InternalValue valueOf(String s, int type) {
+        switch (type) {
+            case PropertyType.BOOLEAN:
+                return new InternalValue(Boolean.valueOf(s).booleanValue());
+            case PropertyType.DATE:
+                return new InternalValue(ISO8601.parse(s));
+            case PropertyType.DOUBLE:
+                return new InternalValue(Double.valueOf(s).doubleValue());
+            case PropertyType.LONG:
+                return new InternalValue(Long.valueOf(s).longValue());
+            case PropertyType.REFERENCE:
+                return new InternalValue(new UUID(s));
+            case PropertyType.PATH:
+                return new InternalValue(Path.valueOf(s));
+            case PropertyType.NAME:
+                return new InternalValue(QName.valueOf(s));
+            case PropertyType.STRING:
+                return new InternalValue(s);
+
+            case PropertyType.BINARY:
+                throw new IllegalArgumentException("this method does not support the type PropertyType.BINARY");
+            default:
+                throw new IllegalArgumentException("illegal type");
+        }
+    }
+
+    //-------------------------------------------------------< implementation >
+    private InternalValue(String value) {
+        val = value;
+        type = PropertyType.STRING;
+    }
+
+    private InternalValue(QName value) {
+        val = value;
+        type = PropertyType.NAME;
+    }
+
+    private InternalValue(long value) {
+        val = new Long(value);
+        type = PropertyType.LONG;
+    }
+
+    private InternalValue(double value) {
+        val = new Double(value);
+        type = PropertyType.DOUBLE;
+    }
+
+    private InternalValue(Calendar value) {
+        val = value;
+        type = PropertyType.DATE;
+    }
+
+    private InternalValue(boolean value) {
+        val = new Boolean(value);
+        type = PropertyType.BOOLEAN;
+    }
+
+    private InternalValue(BLOBFileValue value) {
+        val = value;
+        type = PropertyType.BINARY;
+    }
+
+    private InternalValue(Path value) {
+        val = value;
+        type = PropertyType.PATH;
+    }
+
+    private InternalValue(UUID value) {
+        val = value;
+        type = PropertyType.REFERENCE;
+    }
+}

Propchange: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/value/InternalValue.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/value/LongValue.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/value/LongValue.java?rev=165135&view=auto
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/value/LongValue.java (added)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/value/LongValue.java Thu Apr 28 06:06:58 2005
@@ -0,0 +1,170 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation or its licensors,
+ *                     as applicable.
+ *
+ * Licensed 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.core.value;
+
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+import javax.jcr.ValueFormatException;
+import java.util.Calendar;
+import java.util.Date;
+
+/**
+ * A <code>LongValue</code> provides an implementation
+ * of the <code>Value</code> interface representing a long value.
+ */
+public class LongValue extends BaseValue {
+
+    public static final int TYPE = PropertyType.LONG;
+
+    private final Long lNumber;
+
+    /**
+     * Constructs a <code>LongValue</code> object representing a long.
+     *
+     * @param lNumber the long this <code>LongValue</code> should represent
+     */
+    public LongValue(Long lNumber) {
+        super(TYPE);
+        this.lNumber = lNumber;
+    }
+
+    /**
+     * Constructs a <code>LongValue</code> object representing a long.
+     *
+     * @param l the long this <code>LongValue</code> should represent
+     */
+    public LongValue(long l) {
+        super(TYPE);
+        this.lNumber = new Long(l);
+    }
+
+    /**
+     * Returns a new <code>LongValue</code> initialized to the value
+     * represented by the specified <code>String</code>.
+     *
+     * @param s the string to be parsed.
+     * @return a newly constructed <code>LongValue</code> representing the
+     *         the specified value.
+     * @throws ValueFormatException If the <code>String</code> does not
+     *                                        contain a parsable <code>long</code>.
+     */
+    public static LongValue valueOf(String s) throws ValueFormatException {
+        try {
+            return new LongValue(Long.parseLong(s));
+        } catch (NumberFormatException e) {
+            throw new ValueFormatException("invalid format", e);
+        }
+    }
+
+    /**
+     * Indicates whether some other object is "equal to" this one.
+     * <p/>
+     * The result is <code>true</code> if and only if the argument is not
+     * <code>null</code> and is a <code>LongValue</code> object that
+     * represents the same value as this object.
+     *
+     * @param obj the reference object with which to compare.
+     * @return <code>true</code> if this object is the same as the obj
+     *         argument; <code>false</code> otherwise.
+     */
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof LongValue) {
+            LongValue other = (LongValue) obj;
+            if (lNumber == other.lNumber) {
+                return true;
+            } else if (lNumber != null && other.lNumber != null) {
+                return lNumber.equals(other.lNumber);
+            }
+        }
+        return false;
+    }
+
+    //------------------------------------------------------------< BaseValue >
+    /**
+     * {@inheritDoc}
+     */
+    protected String getInternalString() throws ValueFormatException {
+        if (lNumber != null) {
+            return lNumber.toString();
+        } else {
+            throw new ValueFormatException("empty value");
+        }
+    }
+
+    //----------------------------------------------------------------< Value >
+    /**
+     * {@inheritDoc}
+     */
+    public Calendar getDate()
+            throws ValueFormatException, IllegalStateException,
+            RepositoryException {
+        setValueConsumed();
+
+        if (lNumber != null) {
+            // loosing timezone information...
+            Calendar cal = Calendar.getInstance();
+            cal.setTime(new Date(lNumber.longValue()));
+            return cal;
+        } else {
+            throw new ValueFormatException("empty value");
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public long getLong()
+            throws ValueFormatException, IllegalStateException,
+            RepositoryException {
+        setValueConsumed();
+
+        if (lNumber != null) {
+            return lNumber.longValue();
+        } else {
+            throw new ValueFormatException("empty value");
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean getBoolean()
+            throws ValueFormatException, IllegalStateException,
+            RepositoryException {
+        setValueConsumed();
+
+        throw new ValueFormatException("conversion to boolean failed: inconvertible types");
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public double getDouble()
+            throws ValueFormatException, IllegalStateException,
+            RepositoryException {
+        setValueConsumed();
+
+        if (lNumber != null) {
+            return lNumber.doubleValue();
+        } else {
+            throw new ValueFormatException("empty value");
+        }
+    }
+}

Propchange: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/value/LongValue.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/value/NameValue.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/value/NameValue.java?rev=165135&view=auto
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/value/NameValue.java (added)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/value/NameValue.java Thu Apr 28 06:06:58 2005
@@ -0,0 +1,157 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation or its licensors,
+ *                     as applicable.
+ *
+ * Licensed 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.core.value;
+
+import org.apache.jackrabbit.core.IllegalNameException;
+import org.apache.jackrabbit.core.QName;
+
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+import javax.jcr.ValueFormatException;
+import java.util.Calendar;
+
+/**
+ * A <code>NameValue</code> provides an implementation
+ * of the <code>Value</code> interface representing a <code>NAME</code> value
+ * (a string that is namespace-qualified).
+ */
+public class NameValue extends BaseValue {
+
+    public static final int TYPE = PropertyType.NAME;
+
+    private final String name;
+
+    /**
+     * Returns a new <code>NameValue</code> initialized to the value
+     * represented by the specified <code>String</code>.
+     * <p/>
+     * The specified <code>String</code> must be a valid JCR name.
+     *
+     * @param s the string to be parsed.
+     * @return a newly constructed <code>NameValue</code> representing the
+     *         the specified value.
+     * @throws ValueFormatException If the <code>String</code> is not a valid
+     *                              name.
+     */
+    public static NameValue valueOf(String s) throws ValueFormatException {
+        if (s != null) {
+            try {
+                QName.checkFormat(s);
+            } catch (IllegalNameException ine) {
+                throw new ValueFormatException(ine.getMessage());
+            }
+            return new NameValue(s);
+        } else {
+            throw new ValueFormatException("not a valid name format");
+        }
+    }
+
+    /**
+     * Protected constructor creating a <code>NameValue</code> object
+     * without validating the name.
+     *
+     * @param name the name this <code>NameValue</code> should represent
+     * @see #valueOf
+     */
+    protected NameValue(String name) {
+        super(TYPE);
+        this.name = name;
+    }
+
+    /**
+     * Indicates whether some other object is "equal to" this one.
+     * <p/>
+     * The result is <code>true</code> if and only if the argument is not
+     * <code>null</code> and is a <code>NameValue</code> object that
+     * represents the same value as this object.
+     *
+     * @param obj the reference object with which to compare.
+     * @return <code>true</code> if this object is the same as the obj
+     *         argument; <code>false</code> otherwise.
+     */
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof NameValue) {
+            NameValue other = (NameValue) obj;
+            if (name == other.name) {
+                return true;
+            } else if (name != null && other.name != null) {
+                return name.equals(other.name);
+            }
+        }
+        return false;
+    }
+
+    //------------------------------------------------------------< BaseValue >
+    /**
+     * {@inheritDoc}
+     */
+    protected String getInternalString() throws ValueFormatException {
+        if (name != null) {
+            return name;
+        } else {
+            throw new ValueFormatException("empty value");
+        }
+    }
+
+    //----------------------------------------------------------------< Value >
+    /**
+     * {@inheritDoc}
+     */
+    public Calendar getDate()
+            throws ValueFormatException, IllegalStateException,
+            RepositoryException {
+        setValueConsumed();
+
+        throw new ValueFormatException("conversion to date failed: inconvertible types");
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public long getLong()
+            throws ValueFormatException, IllegalStateException,
+            RepositoryException {
+        setValueConsumed();
+
+        throw new ValueFormatException("conversion to long failed: inconvertible types");
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean getBoolean()
+            throws ValueFormatException, IllegalStateException,
+            RepositoryException {
+        setValueConsumed();
+
+        throw new ValueFormatException("conversion to boolean failed: inconvertible types");
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public double getDouble()
+            throws ValueFormatException, IllegalStateException,
+            RepositoryException {
+        setValueConsumed();
+
+        throw new ValueFormatException("conversion to double failed: inconvertible types");
+    }
+}

Propchange: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/value/NameValue.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/value/PathValue.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/value/PathValue.java?rev=165135&view=auto
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/value/PathValue.java (added)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/value/PathValue.java Thu Apr 28 06:06:58 2005
@@ -0,0 +1,158 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation or its licensors,
+ *                     as applicable.
+ *
+ * Licensed 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.core.value;
+
+import org.apache.jackrabbit.core.MalformedPathException;
+import org.apache.jackrabbit.core.Path;
+
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+import javax.jcr.ValueFormatException;
+import java.util.Calendar;
+
+/**
+ * A <code>PathValue</code> provides an implementation
+ * of the <code>Value</code> interface representing a <code>PATH</code> value
+ * (an absolute or relative workspace path).
+ */
+public class PathValue extends BaseValue {
+
+    public static final int TYPE = PropertyType.PATH;
+
+    private final String path;
+
+    /**
+     * Returns a new <code>PathValue</code> initialized to the value
+     * represented by the specified <code>String</code>.
+     * <p/>
+     * The specified <code>String</code> must be a valid absolute or relative
+     * path.
+     *
+     * @param s the string to be parsed.
+     * @return a newly constructed <code>PathValue</code> representing the
+     *         the specified value.
+     * @throws ValueFormatException If the <code>String</code> is not a valid
+     *                              absolute or relative path.
+     */
+    public static PathValue valueOf(String s) throws ValueFormatException {
+        if (s != null) {
+            try {
+                Path.checkFormat(s);
+            } catch (MalformedPathException mpe) {
+                throw new ValueFormatException(mpe.getMessage());
+            }
+            return new PathValue(s);
+        } else {
+            throw new ValueFormatException("not a valid path format");
+        }
+    }
+
+    /**
+     * Protected constructor creating a <code>PathValue</code> object
+     * without validating the path.
+     *
+     * @param path the path this <code>PathValue</code> should represent
+     * @see #valueOf
+     */
+    protected PathValue(String path) {
+        super(TYPE);
+        this.path = path;
+    }
+
+    /**
+     * Indicates whether some other object is "equal to" this one.
+     * <p/>
+     * The result is <code>true</code> if and only if the argument is not
+     * <code>null</code> and is a <code>PathValue</code> object that
+     * represents the same value as this object.
+     *
+     * @param obj the reference object with which to compare.
+     * @return <code>true</code> if this object is the same as the obj
+     *         argument; <code>false</code> otherwise.
+     */
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof PathValue) {
+            PathValue other = (PathValue) obj;
+            if (path == other.path) {
+                return true;
+            } else if (path != null && other.path != null) {
+                return path.equals(other.path);
+            }
+        }
+        return false;
+    }
+
+    //------------------------------------------------------------< BaseValue >
+    /**
+     * {@inheritDoc}
+     */
+    protected String getInternalString() throws ValueFormatException {
+        if (path != null) {
+            return path;
+        } else {
+            throw new ValueFormatException("empty value");
+        }
+    }
+
+    //----------------------------------------------------------------< Value >
+    /**
+     * {@inheritDoc}
+     */
+    public Calendar getDate()
+            throws ValueFormatException, IllegalStateException,
+            RepositoryException {
+        setValueConsumed();
+
+        throw new ValueFormatException("conversion to date failed: inconvertible types");
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public long getLong()
+            throws ValueFormatException, IllegalStateException,
+            RepositoryException {
+        setValueConsumed();
+
+        throw new ValueFormatException("conversion to long failed: inconvertible types");
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean getBoolean()
+            throws ValueFormatException, IllegalStateException,
+            RepositoryException {
+        setValueConsumed();
+
+        throw new ValueFormatException("conversion to boolean failed: inconvertible types");
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public double getDouble()
+            throws ValueFormatException, IllegalStateException,
+            RepositoryException {
+        setValueConsumed();
+
+        throw new ValueFormatException("conversion to double failed: inconvertible types");
+    }
+}

Propchange: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/value/PathValue.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/value/ReferenceValue.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/value/ReferenceValue.java?rev=165135&view=auto
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/value/ReferenceValue.java (added)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/value/ReferenceValue.java Thu Apr 28 06:06:58 2005
@@ -0,0 +1,176 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation or its licensors,
+ *                     as applicable.
+ *
+ * Licensed 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.core.value;
+
+import org.apache.jackrabbit.core.util.uuid.UUID;
+
+import javax.jcr.Node;
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+import javax.jcr.UnsupportedRepositoryOperationException;
+import javax.jcr.ValueFormatException;
+import java.util.Calendar;
+
+/**
+ * A <code>ReferenceValue</code> provides an implementation
+ * of the <code>Value</code> interface representing a <code>REFERENCE</code> value
+ * (a UUID of an existing node).
+ */
+public class ReferenceValue extends BaseValue {
+
+    public static final int TYPE = PropertyType.REFERENCE;
+
+    private final String uuid;
+
+    /**
+     * Constructs a <code>ReferenceValue</code> object representing the UUID of
+     * an existing node.
+     *
+     * @param target the node to be referenced
+     * @throws IllegalArgumentException If <code>target</code> is nonreferenceable.
+     * @throws RepositoryException      If another error occurs.
+     */
+    public ReferenceValue(Node target) throws RepositoryException {
+        super(TYPE);
+        try {
+            this.uuid = target.getUUID();
+        } catch (UnsupportedRepositoryOperationException ure) {
+            throw new IllegalArgumentException("target is nonreferenceable.");
+        }
+    }
+
+    /**
+     * Returns a new <code>ReferenceValue</code> initialized to the value
+     * represented by the specified <code>String</code>.
+     * <p/>
+     * The specified <code>String</code> must denote the UUID of an existing
+     * node.
+     *
+     * @param s the string to be parsed.
+     * @return a newly constructed <code>ReferenceValue</code> representing the
+     *         the specified value.
+     * @throws ValueFormatException If the <code>String</code> is not a valid
+     *                              not a valid UUID format.
+     */
+    public static ReferenceValue valueOf(String s) throws ValueFormatException {
+        if (s != null) {
+            try {
+                UUID.fromString(s);
+            } catch (IllegalArgumentException iae) {
+                throw new ValueFormatException("not a valid UUID format");
+            }
+            return new ReferenceValue(s);
+        } else {
+            throw new ValueFormatException("not a valid UUID format");
+        }
+    }
+
+    /**
+     * Protected constructor creating a <code>ReferenceValue</code> object
+     * without validating the UUID format.
+     *
+     * @param uuid the UUID of the node to be referenced
+     * @see #valueOf
+     */
+    protected ReferenceValue(String uuid) {
+        super(TYPE);
+        this.uuid = uuid;
+    }
+
+    /**
+     * Indicates whether some other object is "equal to" this one.
+     * <p/>
+     * The result is <code>true</code> if and only if the argument is not
+     * <code>null</code> and is a <code>ReferenceValue</code> object that
+     * represents the same value as this object.
+     *
+     * @param obj the reference object with which to compare.
+     * @return <code>true</code> if this object is the same as the obj
+     *         argument; <code>false</code> otherwise.
+     */
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof ReferenceValue) {
+            ReferenceValue other = (ReferenceValue) obj;
+            if (uuid == other.uuid) {
+                return true;
+            } else if (uuid != null && other.uuid != null) {
+                return uuid.equals(other.uuid);
+            }
+        }
+        return false;
+    }
+
+    //------------------------------------------------------------< BaseValue >
+    /**
+     * {@inheritDoc}
+     */
+    protected String getInternalString() throws ValueFormatException {
+        if (uuid != null) {
+            return uuid;
+        } else {
+            throw new ValueFormatException("empty value");
+        }
+    }
+
+    //----------------------------------------------------------------< Value >
+    /**
+     * {@inheritDoc}
+     */
+    public Calendar getDate()
+            throws ValueFormatException, IllegalStateException,
+            RepositoryException {
+        setValueConsumed();
+
+        throw new ValueFormatException("conversion to date failed: inconvertible types");
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public long getLong()
+            throws ValueFormatException, IllegalStateException,
+            RepositoryException {
+        setValueConsumed();
+
+        throw new ValueFormatException("conversion to long failed: inconvertible types");
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean getBoolean()
+            throws ValueFormatException, IllegalStateException,
+            RepositoryException {
+        setValueConsumed();
+
+        throw new ValueFormatException("conversion to boolean failed: inconvertible types");
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public double getDouble()
+            throws ValueFormatException, IllegalStateException,
+            RepositoryException {
+        setValueConsumed();
+
+        throw new ValueFormatException("conversion to double failed: inconvertible types");
+    }
+}