KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > picocontainer > gems > adapters > 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.adapters;
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 import java.lang.reflect.Method JavaDoc;
24
25
26 /**
27  * ComponentAdapter, that assimilates a component for a specific type.
28  * <p>
29  * Allows the instance of another {@link ComponentAdapter} to be converted into interfacte <code>type</code>, that the
30  * instance is not assignable from. In other words the instance of the delegated adapter does NOT necessarily implement the
31  * <code>type</code> interface.
32  * </p>
33  * <p>
34  * For Example:
35  * </p>
36  * <code><pre>
37  * public interface Foo {
38  * int size();
39  * }
40  *
41  * public class Bar {
42  * public int size() {
43  * return 1;
44  * }
45  * }
46  *
47  * new AssimilatingComponentAdapter(Foo.class, new InstanceComponentAdapter(new Bar()));
48  * </pre></code>
49  * <p>
50  * Notice how Bar does not implement the interface Foo. But Bar does have an identical <code>size()</code> method.
51  * </p>
52  *
53  * @author J&ouml;rg Schaible
54  * @author Michael Ward
55  * @since 1.2
56  */

57 public class AssimilatingComponentAdapter extends DecoratingComponentAdapter {
58
59     private Class JavaDoc type;
60     private ProxyFactory proxyFactory;
61     private boolean isCompatible;
62
63     /**
64      * Construct an AssimilatingComponentAdapter. The <code>type</code> may not implement the type of the component instance.
65      * If the component instance <b>does</b> implement the 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 and cannot be proxied.
71      */

72     public AssimilatingComponentAdapter(final Class JavaDoc type, final ComponentAdapter delegate, final ProxyFactory proxyFactory)
73             throws PicoIntrospectionException {
74         super(delegate);
75         this.type = type;
76         this.proxyFactory = proxyFactory;
77         final Class JavaDoc delegationType = delegate.getComponentImplementation();
78         this.isCompatible = type.isAssignableFrom(delegationType);
79         if (!isCompatible) {
80             if (!proxyFactory.canProxy(type)) {
81                 throw new PicoIntrospectionException("Cannot create proxy for type " + type.getName());
82             }
83             final Method JavaDoc[] methods = type.getMethods();
84             for (int i = 0; i < methods.length; i++) {
85                 final Method JavaDoc method = methods[i];
86                 try {
87                     delegationType.getMethod(method.getName(), method.getParameterTypes());
88                 } catch (final NoSuchMethodException JavaDoc e) {
89                     throw new PicoIntrospectionException("Cannot create proxy for type "
90                             + type.getName()
91                             + ", because of incompatible method "
92                             + method.toString());
93                 }
94             }
95         }
96     }
97
98     /**
99      * Construct an AssimilatingComponentAdapter. The <code>type</code> may not implement the type of the component instance.
100      * The implementation will use JDK {@link java.lang.reflect.Proxy} instances. If the component instant <b>does </b>
101      * implement the interface, no proxy is used anyway.
102      *
103      * @param type The class type used as key.
104      * @param delegate The delegated {@link ComponentAdapter}.
105      */

106     public AssimilatingComponentAdapter(final Class JavaDoc type, final ComponentAdapter delegate) {
107         this(type, delegate, new StandardProxyFactory());
108     }
109
110     /**
111      * Create and return a component instance. If the component instance and the type to assimilate is not compatible, a proxy
112      * for the instance is generated, that implements the assimilated type.
113      *
114      * @see org.picocontainer.defaults.DecoratingComponentAdapter#getComponentInstance(org.picocontainer.PicoContainer)
115      */

116     public Object JavaDoc getComponentInstance(final PicoContainer container)
117             throws PicoInitializationException, PicoIntrospectionException {
118         return isCompatible ? super.getComponentInstance(container) : Delegating.object(
119                 type, super.getComponentInstance(container), proxyFactory);
120     }
121
122     /**
123      * Return the type of the component. If the component type is not compatible with the type to assimilate, the assimilated
124      * type is returned.
125      *
126      * @see org.picocontainer.defaults.DecoratingComponentAdapter#getComponentImplementation()
127      */

128     public Class JavaDoc getComponentImplementation() {
129         return isCompatible ? super.getComponentImplementation() : type;
130     }
131
132     /**
133      * Return the key of the component. If the key of the delegated component is a type, that is not compatible with the type to
134      * assimilate, then the assimilated type replaces the original type.
135      *
136      * @see org.picocontainer.defaults.DecoratingComponentAdapter#getComponentKey()
137      */

138     public Object JavaDoc getComponentKey() {
139         final Object JavaDoc key = super.getComponentKey();
140         if (key instanceof Class JavaDoc && (!isCompatible || !type.isAssignableFrom((Class JavaDoc)key))) {
141             return type;
142         }
143         return key;
144     }
145 }
146
Popular Tags