Clover Coverage Report - perfectjpattern(Aggregated)
Coverage timestamp: Sat Feb 28 2009 14:35:07 CET
../../../../img/srcFileCovDistChart10.png 0% of files have more coverage
31   251   13   3.88
6   113   0.42   8
8     1.62  
1    
2.2% of code in this file is excluded from these metrics.
 
  AbstractSurrogate       Line # 40 31 2.2% 13 0 100% 1.0
 
  (19)
 
1    //----------------------------------------------------------------------
2    //
3    // PerfectJPattern: "Design patterns are good but components are better!"
4    // AbstractSurrogate.java Copyright (c) 2009 Giovanni Azua Garcia
5    // bravegag@hotmail.com
6    //
7    // This program is free software; you can redistribute it and/or
8    // modify it under the terms of the GNU General Public License
9    // as published by the Free Software Foundation; either version 3
10    // of the License, or (at your option) any later version.
11    //
12    // This program is distributed in the hope that it will be useful,
13    // but WITHOUT ANY WARRANTY; without even the implied warranty of
14    // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15    // GNU General Public License for more details.
16    //
17    // You should have received a copy of the GNU General Public License
18    // along with this program; if not, see <http://www.gnu.org/licenses/>.
19    //
20    //----------------------------------------------------------------------
21    package org.perfectjpattern.core.structural;
22   
23    import java.lang.reflect.*;
24    import java.util.*;
25   
26    import org.apache.commons.lang.*;
27    import org.perfectjpattern.core.api.structural.*;
28   
29    /**
30    * Concrete implementation of {@link ISurrogate} that groups common
31    * functionality for single instance surrogates.
32    *
33    * @param <C> <code>Component</code> or wrapper element type
34    * @param <U> <code>Underlying</code> wrapped element type
35    *
36    * @author <a href="mailto:bravegag@hotmail.com">Giovanni Azua</a>
37    * @version $Revision: 1.0 $Date: Apr 5, 2008 4:04:47 PM $
38    */
39    public abstract
 
40    class AbstractSurrogate<C, U>
41    implements ISurrogate<C>
42    {
43    //------------------------------------------------------------------------
44    // public
45    //------------------------------------------------------------------------
46    /**
47    * Creates an AbstractSurrogate&lt;C&gt; given a <code>Component</code>
48    * interface type and an instance of the underlying wrapped object.
49    *
50    * @param aSurrogateClass The desired <code>Surrogate</code> interface type
51    * @param anUnderlying <code>Underlying</code> instance to surrogate
52    * @throws IllegalArgumentException 'anInterface' must not be null
53    * @throws IllegalArgumentException 'anInterface' must be an interface type
54    * @throws IllegalArgumentException 'aComponent' must not be null
55    */
 
56  45 toggle @SuppressWarnings("unchecked")
57    public
58    AbstractSurrogate(Class<C> aSurrogateClass, U anUnderlying)
59    throws IllegalArgumentException
60    {
61  45 Validate.notNull(aSurrogateClass, "'anInterface' must not be null");
62  45 Validate.isTrue(aSurrogateClass.isInterface(),
63    "'aSurrogateClass' must be an interface type");
64  45 Validate.notNull(anUnderlying, "'anUnderlying' must not be null");
65   
66  45 theComponentClass = aSurrogateClass;
67  45 theUnderlying = anUnderlying;
68   
69  45 final ClassLoader myClassLoader = aSurrogateClass.getClassLoader();
70  45 theComponent = (C) Proxy.newProxyInstance(myClassLoader, new Class[] {
71    aSurrogateClass }, this);
72    }
73   
74    //------------------------------------------------------------------------
75    /**
76    * {@inheritDoc}
77    */
 
78  155 toggle public final C
79    getComponent()
80    {
81  155 return theComponent;
82    }
83   
84    //------------------------------------------------------------------------
 
85  200 toggle public final Object
86    invoke(Object aProxy, Method aMethod, Object[] anArguments)
87    throws Throwable
88    {
89  200 Object myResult = null;
90   
91  200 Method myMethod = null;
92  200 if (theLookup.containsKey(aMethod))
93    {
94  107 myMethod = theLookup.get(aMethod);
95    }
96    else
97    {
98  93 try
99    {
100    // check whether this method is implemented by the
101    // surrogate i.e. this
102  93 myMethod = getClass().getMethod(aMethod.getName(), aMethod.
103    getParameterTypes());
104  31 theLookup.put(aMethod, myMethod);
105    }
106    catch (NoSuchMethodException anException)
107    {
108    // pass it on to the underlying then
109    }
110    }
111   
112    // if the method is decorated then pass control to the surrogate
113    // otherwise forward to the underlying to execute it
114  200 if (myMethod != null)
115    {
116  88 myResult = myMethod.invoke(this, anArguments);
117    }
118    else
119    {
120    // first make sure that the underlying implements such method
121  112 try
122    {
123    // invoke underlying
124  112 myResult = invokeUnderlying(aMethod, anArguments);
125   
126    // cache the association
127  111 theLookup.put(aMethod, myMethod);
128    }
129    catch (NoSuchMethodException anException)
130    {
131    throw new NoSuchMethodError("Underlying component does not " +
132    "implement '" + aMethod.getName() + "'");
133    }
134    }
135   
136  199 return myResult;
137    }
138   
139    //------------------------------------------------------------------------
140    /**
141    * {@inheritDoc}
142    */
 
143  13 toggle @Override
144    public final boolean
145    equals(Object anObject)
146    {
147  13 boolean myResult = false;
148   
149    // FindBugs successfully identifies this equals implementation as
150    // unusual, the reason is that a Surrogate impersonates the real
151    // instance so this equals implementation is an attempt to provide
152    // the same identity view of the Surrogate
153  13 if (anObject instanceof Proxy)
154    {
155  5 Proxy myProxy = (Proxy) anObject;
156   
157  5 myResult = myProxy.equals(theUnderlying);
158    }
159    else
160    {
161  8 myResult = theUnderlying.equals(anObject);
162    }
163   
164  13 return myResult;
165    }
166   
167    //------------------------------------------------------------------------
168    /**
169    * {@inheritDoc}
170    */
 
171  1 toggle @Override
172    public final int
173    hashCode()
174    {
175  1 return theUnderlying.hashCode();
176    }
177   
178    //------------------------------------------------------------------------
179    // protected
180    //------------------------------------------------------------------------
181    /**
182    * {@inheritDoc}
183    */
 
184  265 toggle protected final U
185    getUnderlying()
186    {
187  265 return theUnderlying;
188    }
189   
190    //------------------------------------------------------------------------
191    /**
192    * Returns the result of the Method invocation. This method has two
193    * main purposes:
194    *
195    * <ul>
196    * <li>Provides facility to invoke a method on the actual Underlying</li>
197    * <li>Concrete surrogate implementations that override this method have
198    * a single point to control access to the actual Underlying method
199    * invokation.</li>
200    * </ul>
201    *
202    * @param aMethod Method to invoke
203    * @param anArguments Array of input arguments for the Method to invoke
204    * @return result of the Method invocation
205    * @throws Throwable
206    */
 
207  13 toggle protected Object
208    invokeUnderlying(Method aMethod, Object[] anArguments)
209    throws Throwable
210    {
211  13 return aMethod.invoke(theUnderlying, anArguments);
212    }
213   
214    //------------------------------------------------------------------------
215    /**
216    * Returns the Component class
217    *
218    * @return the Component class
219    */
 
220  136 toggle protected final Class<C>
221    getComponentClass()
222    {
223  136 return theComponentClass;
224    }
225   
226    //------------------------------------------------------------------------
227    // members
228    //------------------------------------------------------------------------
229    /**
230    * <code>Component</code> instance
231    */
232    private final C theComponent;
233   
234    //------------------------------------------------------------------------
235    /**
236    * <code>Component</code> class type
237    */
238    private final Class<C> theComponentClass;
239   
240    /**
241    * Reference to the actual <code>Underlying</code> type wrapped by this
242    * surrogate instance.
243    */
244    private final U theUnderlying;
245   
246    /**
247    * <code>Map&lt;Method, Method&gt;<code> that contains all methods
248    * implemented by the <code>Component</code> type
249    */
250    private final Map<Method, Method> theLookup = new HashMap<Method, Method>();
251    }