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