Author: oheger
Date: Mon Sep 16 20:23:54 2013
New Revision: 1523795

URL: http://svn.apache.org/r1523795
Log:
Added an implementation class for FileLocator.

FileLocatorUtils offers a new method for creating FileLocator objects using a
fluent interface.

Modified:
    
commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/io/FileLocatorUtils.java
    
commons/proper/configuration/trunk/src/test/java/org/apache/commons/configuration/io/TestFileLocatorUtils.java

Modified: 
commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/io/FileLocatorUtils.java
URL: 
http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/io/FileLocatorUtils.java?rev=1523795&r1=1523794&r2=1523795&view=diff
==============================================================================
--- 
commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/io/FileLocatorUtils.java
 (original)
+++ 
commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/io/FileLocatorUtils.java
 Mon Sep 16 20:23:54 2013
@@ -22,6 +22,9 @@ import java.net.URL;
 
 import org.apache.commons.configuration.ConfigurationUtils;
 import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.builder.EqualsBuilder;
+import org.apache.commons.lang3.builder.HashCodeBuilder;
+import org.apache.commons.lang3.builder.ToStringBuilder;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
@@ -68,6 +71,44 @@ public final class FileLocatorUtils
     }
 
     /**
+     * Returns an uninitialized {@code FileLocatorBuilder} which can be used
+     * for the creation of a {@code FileLocator} object. This method provides
+     * a convenient way to create file locators using a fluent API as in the
+     * following example:
+     * <pre>
+     * FileLocator locator = FileLocatorUtils.fileLocator()
+     *     .basePath(myBasePath)
+     *     .fileName("test.xml")
+     *     .create();
+     * </pre>
+     * @return a builder object for defining a {@code FileLocator}
+     */
+    public static FileLocatorBuilder fileLocator()
+    {
+        return fileLocator(null);
+    }
+
+    /**
+     * Returns a {@code FileLocatorBuilder} which is already initialized with
+     * the properties of the passed in {@code FileLocator}. This builder can
+     * be used to create a {@code FileLocator} object which shares properties
+     * of the original locator (e.g. the {@code FileSystem} or the encoding),
+     * but points to a different file. An example use case is as follows:
+     * <pre>
+     * FileLocator loc1 = ...
+     * FileLocator loc2 = FileLocatorUtils.fileLocator(loc1)
+     *     .setFileName("anotherTest.xml")
+     *     .create();
+     * </pre>
+     * @param src the source {@code FileLocator} (may be <b>null</b>)
+     * @return an initialized builder object for defining a {@code FileLocator}
+     */
+    public static FileLocatorBuilder fileLocator(FileLocator src)
+    {
+        return new FileLocatorBuilder(src);
+    }
+
+    /**
      * Return the location of the specified resource by searching the user home
      * directory, the current classpath and the system classpath.
      *
@@ -387,4 +428,261 @@ public final class FileLocatorUtils
 
         return file;
     }
+
+    /**
+     * A typical <em>builder</em> implementation for creating
+     * {@code FileLocator} objects. An instance of this class is returned by 
the
+     * {@code fileLocator()} method of {@code FileLocatorUtils}. It can be used
+     * to define the various components of the {@code FileLocator} object. By
+     * calling {@code create()} the new immutable {@code FileLocator} instance
+     * is created.
+     */
+    public static final class FileLocatorBuilder
+    {
+        /** The file name. */
+        private String fileName;
+
+        /** The base path. */
+        private String basePath;
+
+        /** The source URL. */
+        private URL sourceURL;
+
+        /** The encoding. */
+        private String encoding;
+
+        /** The file system. */
+        private FileSystem fileSystem;
+
+        /**
+         * Creates a new instance of {@code FileLocatorBuilder} and initializes
+         * the builder's properties from the passed in {@code FileLocator}
+         * object.
+         *
+         * @param src the source {@code FileLocator} (may be <b>null</b>)
+         */
+        private FileLocatorBuilder(FileLocator src)
+        {
+            if (src != null)
+            {
+                initBuilder(src);
+            }
+        }
+
+        /**
+         * Specifies the encoding of the new {@code FileLocator}.
+         *
+         * @param enc the encoding
+         * @return a reference to this builder for method chaining
+         */
+        public FileLocatorBuilder encoding(String enc)
+        {
+            encoding = enc;
+            return this;
+        }
+
+        /**
+         * Specifies the {@code FileSystem} of the new {@code FileLocator}.
+         *
+         * @param fs the {@code FileSystem}
+         * @return a reference to this builder for method chaining
+         */
+        public FileLocatorBuilder fileSystem(FileSystem fs)
+        {
+            fileSystem = fs;
+            return this;
+        }
+
+        /**
+         * Specifies the base path of the new {@code FileLocator}.
+         *
+         * @param path the base path
+         * @return a reference to this builder for method chaining
+         */
+        public FileLocatorBuilder basePath(String path)
+        {
+            basePath = path;
+            return this;
+        }
+
+        /**
+         * Specifies the file name of the new {@code FileLocator}.
+         *
+         * @param name the file name
+         * @return a reference to this builder for method chaining
+         */
+        public FileLocatorBuilder fileName(String name)
+        {
+            fileName = name;
+            return this;
+        }
+
+        /**
+         * Specifies the source URL of the new {@code FileLocator}.
+         *
+         * @param url the source URL
+         * @return a reference to this builder for method chaining
+         */
+        public FileLocatorBuilder sourceURL(URL url)
+        {
+            sourceURL = url;
+            return this;
+        }
+
+        /**
+         * Creates a new immutable {@code FileLocator} object based on the
+         * properties set so far for this builder.
+         *
+         * @return the newly created {@code FileLocator} object
+         */
+        public FileLocator create()
+        {
+            return new FileLocatorImpl(this);
+        }
+
+        /**
+         * Initializes the properties of this builder from the passed in 
locator
+         * object.
+         *
+         * @param src the source {@code FileLocator}
+         */
+        private void initBuilder(FileLocator src)
+        {
+            basePath = src.getBasePath();
+            fileName = src.getFileName();
+            sourceURL = src.getSourceURL();
+            encoding = src.getEncoding();
+            fileSystem = src.getFileSystem();
+        }
+    }
+
+    /**
+     * A straight-forward immutable implementation of {@code FileLocator}.
+     */
+    private static class FileLocatorImpl implements FileLocator
+    {
+        /** The file name. */
+        private final String fileName;
+
+        /** The base path. */
+        private final String basePath;
+
+        /** The source URL. */
+        private final URL sourceURL;
+
+        /** The encoding. */
+        private final String encoding;
+
+        /** The file system. */
+        private final FileSystem fileSystem;
+
+        /**
+         * Creates a new instance of {@code FileLocatorImpl} and initializes it
+         * from the given builder instance
+         *
+         * @param builder the builder
+         */
+        public FileLocatorImpl(FileLocatorBuilder builder)
+        {
+            fileName = builder.fileName;
+            basePath = builder.basePath;
+            sourceURL = builder.sourceURL;
+            encoding = builder.encoding;
+            fileSystem = builder.fileSystem;
+        }
+
+        public String getFileName()
+        {
+            return fileName;
+        }
+
+        public String getBasePath()
+        {
+            return basePath;
+        }
+
+        public URL getSourceURL()
+        {
+            return sourceURL;
+        }
+
+        public String getEncoding()
+        {
+            return encoding;
+        }
+
+        public FileSystem getFileSystem()
+        {
+            return fileSystem;
+        }
+
+        /**
+         * Returns a hash code for this object.
+         *
+         * @return a hash code for this object
+         */
+        @Override
+        public int hashCode()
+        {
+            return new HashCodeBuilder().append(getFileName())
+                    .append(getBasePath()).append(sourceURLAsString())
+                    
.append(getEncoding()).append(getFileSystem()).toHashCode();
+        }
+
+        /**
+         * Compares this object with another one. Two instances of
+         * {@code FileLocatorImpl} are considered equal if all of their
+         * properties are equal.
+         *
+         * @param obj the object to compare to
+         * @return a flag whether these objects are equal
+         */
+        @Override
+        public boolean equals(Object obj)
+        {
+            if (this == obj)
+            {
+                return true;
+            }
+            if (!(obj instanceof FileLocatorImpl))
+            {
+                return false;
+            }
+
+            FileLocatorImpl c = (FileLocatorImpl) obj;
+            return new EqualsBuilder().append(getFileName(), c.getFileName())
+                    .append(getBasePath(), c.getBasePath())
+                    .append(sourceURLAsString(), c.sourceURLAsString())
+                    .append(getEncoding(), c.getEncoding())
+                    .append(getFileSystem(), c.getFileSystem()).isEquals();
+        }
+
+        /**
+         * Returns a string representation of this object. This string contains
+         * the values of all properties.
+         *
+         * @return a string for this object
+         */
+        @Override
+        public String toString()
+        {
+            return new ToStringBuilder(this).append("fileName", getFileName())
+                    .append("basePath", getBasePath())
+                    .append("sourceURL", sourceURLAsString())
+                    .append("encoding", getEncoding())
+                    .append("fileSystem", getFileSystem()).toString();
+        }
+
+        /**
+         * Returns the source URL as a string. Result is never null. 
Comparisons
+         * are done on this string to avoid blocking network calls.
+         *
+         * @return the source URL as a string (not null)
+         */
+        private String sourceURLAsString()
+        {
+            return (sourceURL != null) ? sourceURL.toExternalForm()
+                    : StringUtils.EMPTY;
+        }
+    }
 }

Modified: 
commons/proper/configuration/trunk/src/test/java/org/apache/commons/configuration/io/TestFileLocatorUtils.java
URL: 
http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/test/java/org/apache/commons/configuration/io/TestFileLocatorUtils.java?rev=1523795&r1=1523794&r2=1523795&view=diff
==============================================================================
--- 
commons/proper/configuration/trunk/src/test/java/org/apache/commons/configuration/io/TestFileLocatorUtils.java
 (original)
+++ 
commons/proper/configuration/trunk/src/test/java/org/apache/commons/configuration/io/TestFileLocatorUtils.java
 Mon Sep 16 20:23:54 2013
@@ -16,13 +16,20 @@
  */
 package org.apache.commons.configuration.io;
 
+import static org.hamcrest.CoreMatchers.containsString;
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertThat;
 
 import java.io.File;
 import java.net.MalformedURLException;
 import java.net.URL;
 
+import org.apache.commons.configuration.ConfigurationAssert;
+import org.easymock.EasyMock;
+import org.junit.BeforeClass;
 import org.junit.Test;
 
 /**
@@ -32,6 +39,29 @@ import org.junit.Test;
  */
 public class TestFileLocatorUtils
 {
+    /** Constant for a file name. */
+    private static final String FILE_NAME = "testFile.dat";
+
+    /** Constant for a base path. */
+    private static final String BASE_PATH = "/etc/test/path/";
+
+    /** Constant for a test encoding. */
+    private static final String ENCODING = "utf-8";
+
+    /** A test URL. */
+    private static URL sourceURL;
+
+    /** A test file system. */
+    private static FileSystem fileSystem;
+
+    @BeforeClass
+    public static void setUpOnce() throws Exception
+    {
+        sourceURL = ConfigurationAssert.getTestURL("test.xml");
+        fileSystem = EasyMock.createMock(FileSystem.class);
+        EasyMock.replay(fileSystem);
+    }
+
     /**
      * Tests whether an encoded "%" character in the file name is handled 
correctly by
      * fileFromURL(). This test is related to CONFIGURATION-521.
@@ -132,4 +162,162 @@ public class TestFileLocatorUtils
             Thread.currentThread().setContextClassLoader(cl);
         }
     }
+
+    /**
+     * Tests whether an undefined file locator can be created.
+     */
+    @Test
+    public void testCreateFileLocatorUndefined()
+    {
+        FileLocator locator = FileLocatorUtils.fileLocator().create();
+        assertNull("Got a base path", locator.getBasePath());
+        assertNull("Got a file name", locator.getFileName());
+        assertNull("Got a URL", locator.getSourceURL());
+        assertNull("Got an encoding", locator.getEncoding());
+        assertNull("Got a file system", locator.getFileSystem());
+    }
+
+    /**
+     * Tests whether a locator has the expected properties.
+     *
+     * @param locator the locator to check
+     */
+    private static void checkLocator(FileLocator locator)
+    {
+        assertEquals("Wrong base path", BASE_PATH, locator.getBasePath());
+        assertEquals("Wrong file name", FILE_NAME, locator.getFileName());
+        assertEquals("Wrong encoding", ENCODING, locator.getEncoding());
+        assertEquals("Wrong URL", sourceURL.toExternalForm(), locator
+                .getSourceURL().toExternalForm());
+        assertSame("Wrong file system", fileSystem, locator.getFileSystem());
+    }
+
+    /**
+     * Tests the creation of a file locator.
+     */
+    @Test
+    public void testCreateFileLocator()
+    {
+        FileLocator locator =
+                FileLocatorUtils.fileLocator().basePath(BASE_PATH)
+                        .fileName(FILE_NAME).encoding(ENCODING)
+                        .fileSystem(fileSystem).sourceURL(sourceURL).create();
+        checkLocator(locator);
+    }
+
+    /**
+     * Tests whether a file locator can be created from a source locator.
+     */
+    @Test
+    public void testCreateFileLocatorFromSource()
+    {
+        FileLocator locatorSrc =
+                FileLocatorUtils.fileLocator().basePath(BASE_PATH)
+                        .fileName("someFile").encoding(ENCODING)
+                        .fileSystem(fileSystem).sourceURL(sourceURL).create();
+        FileLocator locator =
+                FileLocatorUtils.fileLocator(locatorSrc).fileName(FILE_NAME)
+                        .create();
+        checkLocator(locator);
+    }
+
+    /**
+     * Tests the equals() implementation of FileLocator if the expected result
+     * is true.
+     */
+    @Test
+    public void testFileLocatorEqualsTrue()
+    {
+        FileLocator loc1 = FileLocatorUtils.fileLocator().create();
+        ConfigurationAssert.checkEquals(loc1, loc1, true);
+        FileLocator loc2 = FileLocatorUtils.fileLocator().create();
+        ConfigurationAssert.checkEquals(loc1, loc2, true);
+        loc1 =
+                FileLocatorUtils.fileLocator().basePath(BASE_PATH)
+                        .fileName(FILE_NAME).encoding(ENCODING)
+                        .fileSystem(fileSystem).sourceURL(sourceURL).create();
+        loc2 =
+                FileLocatorUtils.fileLocator().basePath(BASE_PATH)
+                        .fileName(FILE_NAME).encoding(ENCODING)
+                        .fileSystem(fileSystem).sourceURL(sourceURL).create();
+        ConfigurationAssert.checkEquals(loc1, loc2, true);
+    }
+
+    /**
+     * Tests the equals() implementation of FileLocator if the expected result
+     * is false.
+     */
+    @Test
+    public void testFileLocatorEqualsFalse()
+    {
+        FileLocator loc1 =
+                FileLocatorUtils.fileLocator().basePath(BASE_PATH)
+                        .fileName(FILE_NAME).encoding(ENCODING)
+                        .fileSystem(fileSystem).sourceURL(sourceURL).create();
+        FileLocator loc2 =
+                FileLocatorUtils.fileLocator(loc1)
+                        .basePath(BASE_PATH + "_other").create();
+        ConfigurationAssert.checkEquals(loc1, loc2, false);
+        loc2 =
+                FileLocatorUtils.fileLocator(loc1)
+                        .fileName(FILE_NAME + "_other").create();
+        ConfigurationAssert.checkEquals(loc1, loc2, false);
+        loc2 =
+                FileLocatorUtils.fileLocator(loc1)
+                        .encoding(ENCODING + "_other").create();
+        ConfigurationAssert.checkEquals(loc1, loc2, false);
+        loc2 =
+                FileLocatorUtils.fileLocator(loc1)
+                        .fileSystem(EasyMock.createMock(FileSystem.class))
+                        .create();
+        ConfigurationAssert.checkEquals(loc1, loc2, false);
+        loc2 =
+                FileLocatorUtils
+                        .fileLocator(loc1)
+                        .sourceURL(
+                                ConfigurationAssert
+                                        .getTestURL("test.properties"))
+                        .create();
+        ConfigurationAssert.checkEquals(loc1, loc2, false);
+    }
+
+    /**
+     * Tests equals() with a null object.
+     */
+    @Test
+    public void testFileLocatorEqualsNull()
+    {
+        FileLocator loc =
+                FileLocatorUtils.fileLocator().fileName(FILE_NAME).create();
+        assertFalse("Wrong result", loc.equals(null));
+    }
+
+    /**
+     * Tests equals() with an object from another class.
+     */
+    @Test
+    public void testFileLocatorEqualsOtherClass()
+    {
+        FileLocator loc =
+                FileLocatorUtils.fileLocator().fileName(FILE_NAME).create();
+        assertFalse("Wrong result", loc.equals(this));
+    }
+
+    /**
+     * Tests the string representation of a locator.
+     */
+    @Test
+    public void testFileLocatorToString()
+    {
+        FileLocator loc =
+                FileLocatorUtils.fileLocator().basePath(BASE_PATH)
+                        .fileName(FILE_NAME).encoding(ENCODING)
+                        .fileSystem(fileSystem).sourceURL(sourceURL).create();
+        String s = loc.toString();
+        assertThat(s, containsString("fileName=" + FILE_NAME));
+        assertThat(s, containsString("basePath=" + BASE_PATH));
+        assertThat(s, containsString("sourceURL=" + sourceURL));
+        assertThat(s, containsString("encoding=" + ENCODING));
+        assertThat(s, containsString("fileSystem=" + fileSystem));
+    }
 }


Reply via email to