KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > picocontainer > gems > AssimilatingComponentAdapter


1 /*****************************************************************************
2  * Copyright (C) NanoContainer Organization. All rights reserved. *
3  * ------------------------------------------------------------------------- *
4  * The software in this package is published under the terms of the BSD *
5  * style license a copy of which has been included with this distribution in *
6  * the LICENSE.txt file. *
7  * *
8  * Original code by Joerg Schaibe *
9  *****************************************************************************/

10
11 package org.picocontainer.gems;
12
13 import com.thoughtworks.proxy.ProxyFactory;
14 import com.thoughtworks.proxy.factory.StandardProxyFactory;
15 import com.thoughtworks.proxy.toys.delegate.Delegating;
16
17 import org.picocontainer.ComponentAdapter;
18 import org.picocontainer.PicoContainer;
19 import org.picocontainer.PicoInitializationException;
20 import org.picocontainer.PicoIntrospectionException;
21 import org.picocontainer.defaults.DecoratingComponentAdapter;
22
23
24 /**
25  * ComponentAdapter, that assimilates a component for a specific type.
26  * <p>
27  * Allows the instance of another {@link ComponentAdapter}to be converted into interfacte
28  * <code>type</code>, that the instance is not assignable from. In other words the instance
29  * of the delegated adapter does NOT necessarily implement the <code>type</code> interface.
30  * </p>
31  * <p>
32  * For Example:
33  * </p>
34  * <code><pre>
35  * public interface Foo {
36  * int size();
37  * }
38  *
39  * public class Bar {
40  * public int size() {
41  * return 1;
42  * }
43  * }
44  *
45  * new AssimilatingComponentAdapter(Foo.class, new InstanceComponentAdapter(new Bar()));
46  * </pre></code>
47  * <p>
48  * Notice how Bar does not implement the interface Foo. But Bar does have an identical
49  * <code>size()</code> method.
50  * </p>
51  *
52  * @author J&ouml;rg Schaible
53  * @author Michael Ward
54  * @since 1.0
55  */

56 public class AssimilatingComponentAdapter extends DecoratingComponentAdapter {
57
58     private final Class JavaDoc type;
59     private final ProxyFactory proxyFactory;
60     private final boolean isCompatible;
61
62     /**
63      * Construct an AssimilatingComponentAdapter. The <code>type</code> may not implement the
64      * type of the component instance. If the component instance <b>does </b> implement the
65      * interface, no proxy is used though.
66      *
67      * @param type The class type used as key.
68      * @param delegate The delegated {@link ComponentAdapter}.
69      * @param proxyFactory The {@link ProxyFactory}to use.
70      * @throws PicoIntrospectionException Thrown if the <code>type</code> is not compatible
71      * and cannot be proxied.
72      */

73     public AssimilatingComponentAdapter(final Class JavaDoc type, final ComponentAdapter delegate, final ProxyFactory proxyFactory)
74             throws PicoIntrospectionException {
75         super(delegate);
76         this.type = type;
77         this.proxyFactory = proxyFactory;
78         this.isCompatible = type.isAssignableFrom(delegate.getComponentImplementation());
79         if (!isCompatible) {
80             if (!proxyFactory.canProxy(type)) {
81                 throw new PicoIntrospectionException("Cannot create proxy for type " + type.getName());
82             }
83             // TODO: Check method compatiblity
84
}
85     }
86
87     /**
88      * Construct an AssimilatingComponentAdapter. The <code>type</code> may not implement the
89      * type of the component instance. The implementation will use JDK
90      * {@link java.lang.reflect.Proxy}instances. If the component instant <b>does </b>
91      * implement the interface, no proxy is used anyway.
92      *
93      * @param type The class type used as key.
94      * @param delegate The delegated {@link ComponentAdapter}.
95      */

96     public AssimilatingComponentAdapter(final Class JavaDoc type, final ComponentAdapter delegate) {
97         this(type, delegate, new StandardProxyFactory());
98     }
99
100     /**
101      * Create and return a component instance. If the component instance and the type to
102      * assimilate is not compatible, a proxy for the instance is generated, that implements the
103      * assimilated type.
104      *
105      * @see org.picocontainer.defaults.DecoratingComponentAdapter#getComponentInstance(org.picocontainer.PicoContainer)
106      */

107     public Object JavaDoc getComponentInstance(final PicoContainer container)
108             throws PicoInitializationException, PicoIntrospectionException {
109         return isCompatible ? super.getComponentInstance(container) : Delegating.object(
110                 type, super.getComponentInstance(container), proxyFactory);
111     }
112
113     /**
114      * Return the type of the component. If the component type is not compatible with the type
115      * to assimilate, the assimilated type is returned.
116      *
117      * @see org.picocontainer.defaults.DecoratingComponentAdapter#getComponentImplementation()
118      */

119     public Class JavaDoc getComponentImplementation() {
120         return isCompatible ? super.getComponentImplementation() : type;
121     }
122
123     /**
124      * Return the key of the component. If the key of the delegated component is a type, that is
125      * not compatible with the type to assimilate, then the assimilated type replaces the
126      * original type.
127      *
128      * @see org.picocontainer.defaults.DecoratingComponentAdapter#getComponentKey()
129      */

130     public Object JavaDoc getComponentKey() {
131         final Object JavaDoc key = super.getComponentKey();
132         if (key instanceof Class JavaDoc && (!isCompatible || !type.isAssignableFrom((Class JavaDoc) key))) {
133             return type;
134         }
135         return key;
136     }
137 }
138
Popular Tags