|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
AbstractSurrogate | Line # 40 | 31 | 2.2% | 13 | 0 | 100% |
1.0
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
(19) | |||
Result | |||
0.8666667
|
org.perfectjpattern.core.behavioral.observer.TestAsynchronousSubject.testAsynchronousNotification
![]() |
1 PASS | |
0.8
|
org.perfectjpattern.core.structural.decorator.TestExample.testDecorator
![]() |
1 PASS | |
0.75555557
|
org.perfectjpattern.core.structural.proxy.TestExample.testProxy
![]() |
1 PASS | |
0.75555557
|
org.perfectjpattern.jee.integration.dao.jpa.TestExample.testJpaCmpGenericDao
![]() |
1 PASS | |
0.7111111
|
org.perfectjpattern.jee.integration.dao.spring.TestExample.testSpringGenericDao
![]() |
1 PASS | |
0.7111111
|
org.perfectjpattern.jee.integration.dao.TestJpaGenericDao.testUpdate
![]() |
1 PASS | |
0.7111111
|
org.perfectjpattern.jee.integration.dao.hibernate.TestExample.testHibernateGenericDao
![]() |
1 PASS | |
0.7111111
|
org.perfectjpattern.core.structural.adapter.TestExample.testAdapter
![]() |
1 PASS | |
0.6888889
|
org.perfectjpattern.jee.integration.dao.TestJpaGenericReadOnlyDao.testContains
![]() |
1 PASS | |
0.6888889
|
org.perfectjpattern.jee.integration.dao.TestJpaGenericDao.testCreate
![]() |
1 PASS | |
0.6888889
|
org.perfectjpattern.jee.integration.dao.TestJpaGenericReadOnlyDao.testFindAll
![]() |
1 PASS | |
0.6888889
|
org.perfectjpattern.jee.integration.dao.TestJpaGenericReadOnlyDao.testCount
![]() |
1 PASS | |
0.6666667
|
org.perfectjpattern.core.structural.adapter.TestNameMatchAdapter.testAdapter
![]() |
1 PASS | |
0.6
|
org.perfectjpattern.core.structural.adapter.TestExactMatchAdapter.testAdapter
![]() |
1 PASS | |
0.6
|
org.perfectjpattern.core.structural.proxy.TestProxy.testProxying
![]() |
1 PASS | |
0.53333336
|
org.perfectjpattern.core.structural.decorator.TestDecorator.testDecorator
![]() |
1 PASS | |
0.51111114
|
org.perfectjpattern.jee.integration.dao.TestJpaGenericDao.testDelete
![]() |
1 PASS | |
0.51111114
|
org.perfectjpattern.jee.integration.dao.TestJpaGenericReadOnlyDao.testFindById
![]() |
1 PASS | |
0.31111112
|
org.perfectjpattern.jee.integration.dao.TestJpaManagedSessionStrategy.testGetSession
![]() |
1 PASS | |
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<C> 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 |
![]() |
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 |
![]() |
79 | getComponent() | |
80 | { | |
81 | 155 | return theComponent; |
82 | } | |
83 | ||
84 | //------------------------------------------------------------------------ | |
85 | 200 |
![]() |
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 |
![]() |
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 |
![]() |
172 | public final int | |
173 | hashCode() | |
174 | { | |
175 | 1 | return theUnderlying.hashCode(); |
176 | } | |
177 | ||
178 | //------------------------------------------------------------------------ | |
179 | // protected | |
180 | //------------------------------------------------------------------------ | |
181 | /** | |
182 | * {@inheritDoc} | |
183 | */ | |
184 | 265 |
![]() |
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 |
![]() |
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 |
![]() |
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<Method, Method><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 | } |
|