You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by oh...@apache.org on 2009/10/04 21:38:02 UTC

svn commit: r821590 - in /commons/proper/configuration/branches/configuration2_experimental/src: main/java/org/apache/commons/configuration2/base/Capabilities.java test/java/org/apache/commons/configuration2/base/TestCapabilities.java

Author: oheger
Date: Sun Oct  4 19:38:02 2009
New Revision: 821590

URL: http://svn.apache.org/viewvc?rev=821590&view=rev
Log:
Added new Capabilities class for managing the capabilities supported by a ConfigurationSource.

Added:
    commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/base/Capabilities.java   (with props)
    commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/base/TestCapabilities.java   (with props)

Added: commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/base/Capabilities.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/base/Capabilities.java?rev=821590&view=auto
==============================================================================
--- commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/base/Capabilities.java (added)
+++ commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/base/Capabilities.java Sun Oct  4 19:38:02 2009
@@ -0,0 +1,155 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.configuration2.base;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+/**
+ * <p>
+ * A class for managing <em>capabilities</em>.
+ * </p>
+ * <p>
+ * This class is intended to support the implementation of the {@code
+ * getCapability()} method defined by the {@link ConfigurationSource} interface.
+ * It maintains the capabilities provided by a concrete configuration source
+ * implementation.
+ * </p>
+ * <p>
+ * An instance is initialized with a reference to an owner and a collection of
+ * {@link Capability} objects. The passed in {@link Capability} objects are
+ * stored directly. From the owner object a list of all implemented interfaces
+ * is obtained, and corresponding {@link Capability} objects are created for
+ * them. The {@code getCapability()} method queries the internal list of
+ * {@link Capability} objects created this way and returns the implementation
+ * objects if a matching class is found. This is exactly what is needed for the
+ * implementation of the {@link ConfigurationSource#getCapability(Class)}
+ * method.
+ * </p>
+ * <p>
+ * Implementation note: This class is immutable.
+ * </p>
+ *
+ * @author Commons Configuration team
+ * @version $Id$
+ */
+public class Capabilities
+{
+    /** The capabilities managed by this instance. */
+    private final Collection<Capability> capabilities;
+
+    /**
+     * Creates a new instance of {@code Capabilities} and initializes it with an
+     * owner and a collection of {@code Capability} objects.
+     *
+     * @param owner the owner object (can be <b>null</b>)
+     * @param caps the collection with {@code Capability} objects (can be
+     *        <b>null</b>)
+     * @throws IllegalArgumentException if one of the {@code Capability} objects
+     *         in the collection is <b>null</b>
+     */
+    public Capabilities(Object owner, Collection<? extends Capability> caps)
+    {
+        if (caps == null)
+        {
+            capabilities = new ArrayList<Capability>();
+        }
+        else
+        {
+            capabilities = new ArrayList<Capability>(caps);
+            for (Capability c : capabilities)
+            {
+                if (c == null)
+                {
+                    throw new IllegalArgumentException(
+                            "Capability must not be null!");
+                }
+            }
+        }
+
+        if (owner != null)
+        {
+            extractOwnerCapabilities(capabilities, owner);
+        }
+    }
+
+    /**
+     * Returns the capability implementation object for the specified capability
+     * (interface) class. This method queries all {@link Capability} objects
+     * stored internally whether they match the specified class. If a match is
+     * found, the corresponding implementation object is returned.
+     * {@link Capability} objects directly passed to the constructor are queried
+     * first (in the order they are provided), then the capabilities obtained
+     * from the interfaces of the owner object are searched. Therefore it is
+     * possible to override interfaces implemented by the owner object by
+     * providing corresponding {@link Capability} instances.
+     *
+     * @param <T> the type of the capability
+     * @param capabilityClass the capability class
+     * @return the object implementing this capability or <b>null</b> if this
+     *         capability is not supported
+     */
+    public <T> T getCapability(Class<T> capabilityClass)
+    {
+        for (Capability cap : capabilities)
+        {
+            if (cap.matches(capabilityClass))
+            {
+                return capabilityClass.cast(cap.getCapabilityObject());
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * Returns a string representation of this object. This string contains the
+     * string representations of all {@code Capability} objects managed by this
+     * instance.
+     *
+     * @return a string for this object
+     */
+    @Override
+    public String toString()
+    {
+        StringBuilder buf = new StringBuilder();
+        buf.append("Capabilities [ capabilities = ");
+        buf.append(capabilities);
+        buf.append(" ]");
+        return buf.toString();
+    }
+
+    /**
+     * Creates {@code Capability} objects for the interfaces implemented by the
+     * owner object. This method is called by the constructor if an owner object
+     * is provided. Note: It is safe to use raw types here because it is ensured
+     * that the owner object actually can be casted to the interfaces it
+     * implements.
+     *
+     * @param caps the list with the capabilities
+     * @param owner the owner object
+     */
+    @SuppressWarnings("unchecked")
+    private static void extractOwnerCapabilities(Collection<Capability> caps,
+            Object owner)
+    {
+        for (Class capCls : owner.getClass().getInterfaces())
+        {
+            caps.add(new Capability(capCls, owner));
+        }
+    }
+}

Propchange: commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/base/Capabilities.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/base/Capabilities.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/base/Capabilities.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/base/TestCapabilities.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/base/TestCapabilities.java?rev=821590&view=auto
==============================================================================
--- commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/base/TestCapabilities.java (added)
+++ commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/base/TestCapabilities.java Sun Oct  4 19:38:02 2009
@@ -0,0 +1,159 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.configuration2.base;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+
+import junit.framework.TestCase;
+
+import org.easymock.EasyMock;
+
+/**
+ * Test class for {@code Capabilities}.
+ *
+ * @author Commons Configuration team
+ * @version $Id$
+ */
+public class TestCapabilities extends TestCase
+{
+    /**
+     * Tries to create an instance with a null capability in the collection.
+     * This should cause an exception.
+     */
+    public void testInitNullCapability()
+    {
+        Collection<Capability> caps = new ArrayList<Capability>();
+        caps.add(new Capability(Runnable.class, EasyMock
+                .createNiceMock(Runnable.class)));
+        caps.add(null);
+        try
+        {
+            new Capabilities(this, caps);
+            fail("Null capability not detected!");
+        }
+        catch (IllegalArgumentException iex)
+        {
+            // ok
+        }
+    }
+
+    /**
+     * Tries to create an instance without a data and capabilities. This should
+     * be possible, however, it is not very useful.
+     */
+    public void testInitNoData()
+    {
+        Capabilities caps = new Capabilities(null, null);
+        assertNull("Got a capability", caps.getCapability(Object.class));
+    }
+
+    /**
+     * Tests whether a defensive copy of the capabilities collection is created.
+     */
+    public void testInitCollectionModify()
+    {
+        Runnable r = EasyMock.createMock(Runnable.class);
+        ConfigurationSource src = EasyMock
+                .createMock(ConfigurationSource.class);
+        EasyMock.replay(r, src);
+        Collection<Capability> col = new ArrayList<Capability>();
+        col.add(new Capability(Runnable.class, r));
+        col.add(new Capability(ConfigurationSource.class, src));
+        Capabilities caps = new Capabilities(null, col);
+        col.clear();
+        assertEquals("Capability not found (1)", r, caps
+                .getCapability(Runnable.class));
+        assertEquals("Capability not found (2)", src, caps
+                .getCapability(ConfigurationSource.class));
+        EasyMock.verify(r, src);
+    }
+
+    /**
+     * Tests whether the instances implemented by the owner can be queried.
+     */
+    public void testGetCapabilityFromOwner()
+    {
+        MapConfigurationSource owner = new MapConfigurationSource();
+        Capabilities caps = new Capabilities(owner, null);
+        assertSame("Wrong source", owner, caps
+                .getCapability(ConfigurationSource.class));
+        assertSame("Wrong flat source", owner, caps
+                .getCapability(FlatConfigurationSource.class));
+    }
+
+    /**
+     * Tests whether capabilities from the list can be obtained.
+     */
+    public void testGetCapabilityFromList()
+    {
+        Runnable r = EasyMock.createMock(Runnable.class);
+        EasyMock.replay(r);
+        Collection<Capability> col = new ArrayList<Capability>();
+        col.add(new Capability(Runnable.class, r));
+        Capabilities caps = new Capabilities(null, col);
+        assertEquals("Wrong capability", r, caps.getCapability(Runnable.class));
+        EasyMock.verify(r);
+    }
+
+    /**
+     * Tests whether capabilities in the list overwrite interfaces implemented
+     * by the owner.
+     */
+    public void testGetCapabilityOverwrite()
+    {
+        ConfigurationSource src = EasyMock
+                .createMock(ConfigurationSource.class);
+        EasyMock.replay(src);
+        Capability c = new Capability(ConfigurationSource.class, src);
+        MapConfigurationSource mapSrc = new MapConfigurationSource();
+        Capabilities caps = new Capabilities(mapSrc, Collections.singleton(c));
+        assertEquals("Wrong source capability", src, caps
+                .getCapability(ConfigurationSource.class));
+        assertEquals("Wrong flat source capability", mapSrc, caps
+                .getCapability(FlatConfigurationSource.class));
+        EasyMock.verify(src);
+    }
+
+    /**
+     * Tries to query a null capability.
+     */
+    public void testGetCapabilityNull()
+    {
+        Capabilities caps = new Capabilities(new MapConfigurationSource(), null);
+        assertNull("Got null capability", caps.getCapability(null));
+    }
+
+    /**
+     * Tests the string representation.
+     */
+    public void testToString()
+    {
+        Runnable r = EasyMock.createMock(Runnable.class);
+        EasyMock.replay(r);
+        Capability c = new Capability(Runnable.class, r);
+        MapConfigurationSource owner = new MapConfigurationSource();
+        Capabilities caps = new Capabilities(owner, Collections.singleton(c));
+        String s = caps.toString();
+        assertTrue("Runnable capability not found: " + s, s.indexOf(c
+                .toString()) > 0);
+        assertTrue("Flat source capability not found: " + s, s
+                .indexOf(new Capability(FlatConfigurationSource.class, owner)
+                        .toString()) > 0);
+    }
+}

Propchange: commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/base/TestCapabilities.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/base/TestCapabilities.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/base/TestCapabilities.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain