1 //----------------------------------------------------------------------
2 //
3 // PerfectJPattern: "Design patterns are good but components are better!"
4 // TestVisitorPattern.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.behavioral.visitor;
22
23 import java.util.*;
24
25 import junit.framework.*;
26
27 import org.perfectjpattern.core.api.behavioral.visitor.*;
28 import org.slf4j.*;
29
30
31 /**
32 * Test Suite for {@link AbstractVisitor} implementation.
33 *
34 * @see AbstractVisitor
35 *
36 * @author <a href="mailto:bravegag@hotmail.com">Giovanni Azua</a>
37 * @version $Revision: 1.0 $ $Date: Jul 1, 2007 12:06:36 PM $
38 */
39 @SuppressWarnings("unchecked")
40 public
41 class TestVisitor
42 extends TestCase
43 {
44 //------------------------------------------------------------------------
45 // public
46 //------------------------------------------------------------------------
47 /**
48 * Test simple Visitor usage
49 */
50 public void
51 testSimpleUsage()
52 {
53 IVisitor<BlackNode> mySimpleVisitor = new SimpleVisitor();
54
55 BlackNode myBlackNode = theBlackNode;
56
57 // visit two times
58 mySimpleVisitor.visit(myBlackNode);
59 mySimpleVisitor.visit(myBlackNode);
60
61 theLogger.debug("Running assertions ... ");
62
63 assertEquals("Simple visit implementation did not work as expected.",
64 BLACK_NODE_NAME, ((SimpleVisitor) mySimpleVisitor).
65 getElementName());
66
67 assertEquals("The two calls were not executed.", 2,
68 ((SimpleVisitor) mySimpleVisitor).getCallsCounter());
69
70 theLogger.debug("Completed");
71 }
72
73 /**
74 * Test that VisitorA properly visited the required nodes.
75 */
76 public void
77 testVisitorA()
78 {
79 theLogger.debug("Running assertions ... ");
80
81 assertTrue("VisitorA visitRedNode was not successfully called.",
82 theVisitorA.isCalled());
83
84 assertEquals("VisitorA visited incorrect node.", RED_NODE_NAME,
85 theVisitorA.getElementName());
86
87 theLogger.debug("Completed");
88 }
89
90 //------------------------------------------------------------------------
91 /**
92 * Test that VisitorB properly visited the required nodes.
93 */
94 public void
95 testVisitorB()
96 {
97 theLogger.debug("Running assertions ... ");
98
99 assertTrue("VisitorB's visitBlackNode was not successfully called.",
100 theVisitorB.isCalled());
101
102 assertEquals("VisitorB visited incorrect node.", BLACK_NODE_NAME,
103 theVisitorB.getElementName());
104
105 theLogger.debug("Completed");
106 }
107
108 //------------------------------------------------------------------------
109 /**
110 * Test that VisitorC properly visited the required nodes.
111 */
112 public void
113 testVisitorC()
114 {
115 theLogger.debug("Running assertions ... ");
116
117 assertTrue("VisitorC visitBlackNode was not successfully called.",
118 theVisitorC.isCalledBlack());
119
120 assertTrue("VisitorC visitRedNode was not successfully called.",
121 theVisitorC.isCalledRed());
122
123 assertEquals("VisitorC visited incorrect node.", BLACK_NODE_NAME,
124 theVisitorC.getBlackElementName());
125
126 assertEquals("VisitorC visited incorrect node.", RED_NODE_NAME,
127 theVisitorC.getRedElementName());
128
129 theLogger.debug("Completed");
130 }
131
132 //------------------------------------------------------------------------
133 // protected
134 //------------------------------------------------------------------------
135 @Override
136 protected void
137 setUp()
138 throws Exception
139 {
140 super.setUp();
141
142 theLogger.debug("Creating Visitor pattern test fixture ... ");
143
144 // fixture for the usage of Visitor Pattern
145 fixture();
146
147 theLogger.debug("Completed Visitor pattern test fixture.");
148 }
149
150 //------------------------------------------------------------------------
151 // private
152 //------------------------------------------------------------------------
153 /**
154 * Provides example usage of the Visitor Pattern.
155 */
156 private void
157 fixture()
158 {
159 theLogger.debug("Step #1 := Create a Collection of Visitors");
160
161 Collection<IVisitor> myVisitors = Arrays.asList(new IVisitor[]
162 {
163 theVisitorA, theVisitorB
164 });
165
166 theLogger.debug("Step #2 := Have every visitor visit every element.");
167 for (IVisitor myVisitor : myVisitors)
168 {
169 AbstractVisitor.reusableVisit(myVisitor, theBlackNode, theRedNode);
170 }
171
172 theLogger.debug("Step #3 := Have visitor C visit every element.");
173 theVisitorC.visit(theBlackNode);
174 theVisitorC.visit(theRedNode);
175 }
176
177 //------------------------------------------------------------------------
178 // inner classes
179 //------------------------------------------------------------------------
180 /**
181 * Test Element that extends the AbstractElement base class.
182 */
183 private static
184 class RedNode
185 implements IElement
186 {
187 //--------------------------------------------------------------------
188 /**
189 * @return the myName
190 */
191 public final String
192 getName()
193 {
194 return RED_NODE_NAME;
195 }
196 }
197
198 //------------------------------------------------------------------------
199 /**
200 * Test Element that extends the AbstractElement base class.
201 */
202 private static class BlackNode
203 implements IElement
204 {
205 //--------------------------------------------------------------------
206 /**
207 * @return the myName
208 */
209 public final String
210 getName()
211 {
212 return BLACK_NODE_NAME;
213 }
214 }
215
216 //-------------------------------------------------------------------------
217 public static
218 class SimpleVisitor
219 extends AbstractVisitor<BlackNode>
220 {
221 //---------------------------------------------------------------------
222 public void
223 visitBlackNode(BlackNode aNode)
224 {
225 theCallsCounter++;
226
227 theElementName = aNode.getName();
228 }
229
230 //---------------------------------------------------------------------
231 /**
232 * @return the Calls Counter
233 */
234 public final int
235 getCallsCounter()
236 {
237 return theCallsCounter;
238 }
239
240 //---------------------------------------------------------------------
241 /**
242 * @return the elementName
243 */
244 public final String
245 getElementName()
246 {
247 return theElementName;
248 }
249
250 //---------------------------------------------------------------------
251 // members
252 //---------------------------------------------------------------------
253 private int theCallsCounter = 0;
254 private String theElementName = null;
255 }
256
257 //-------------------------------------------------------------------------
258 /**
259 * Test Visitor that extends the AbstractVisitor base class.
260 */
261 public static
262 class VisitorA<E extends IElement>
263 extends AbstractVisitor<E>
264 {
265 //---------------------------------------------------------------------
266 public void
267 visitRedNode(RedNode aNode)
268 {
269 theCalled = true;
270 theElementName = aNode.getName();
271 }
272
273 //---------------------------------------------------------------------
274 /**
275 * @return the Called
276 */
277 public final boolean
278 isCalled()
279 {
280 return theCalled;
281 }
282
283 //---------------------------------------------------------------------
284 /**
285 * @return the elementName
286 */
287 public final String
288 getElementName()
289 {
290 return theElementName;
291 }
292
293 //---------------------------------------------------------------------
294 // members
295 //---------------------------------------------------------------------
296 private boolean theCalled = false;
297 private String theElementName = null;
298 }
299
300 //------------------------------------------------------------------------
301 /**
302 * Test Visitor that extends the AbstractVisitor base class.
303 */
304 public static
305 class VisitorB<E extends IElement>
306 extends AbstractVisitor<E>
307 {
308 //--------------------------------------------------------------------
309 public void
310 visitBlackNode(BlackNode aNode)
311 {
312 theCalled = true;
313 theElementName = aNode.getName();
314 }
315
316 //--------------------------------------------------------------------
317 /**
318 * @return the Called
319 */
320 public final boolean
321 isCalled()
322 {
323 return theCalled;
324 }
325
326 //--------------------------------------------------------------------
327 /**
328 * @return the elementName
329 */
330 public final String
331 getElementName()
332 {
333 return theElementName;
334 }
335
336 //--------------------------------------------------------------------
337 // members
338 //--------------------------------------------------------------------
339 private boolean theCalled = false;
340 private String theElementName = null;
341 }
342
343 //------------------------------------------------------------------------
344 /**
345 * Test Visitor that implements the IVisitor interface, and delegates core
346 * visit method to the AbstractVisitor's static implementation.
347 */
348 public static
349 class VisitorC<E extends IElement>
350 implements IVisitor<E>
351 {
352 //--------------------------------------------------------------------
353 public void
354 visit(E anElement)
355 {
356 AbstractVisitor.reusableVisit(this, anElement);
357 }
358
359 //--------------------------------------------------------------------
360 public void
361 visitRedNode(RedNode aNode)
362 {
363 theCalledRed = true;
364 theRedElementName = aNode.getName();
365 }
366
367 //--------------------------------------------------------------------
368 public void
369 visitBlackNode(BlackNode aNode)
370 {
371 theCalledBlack = true;
372 theBlackElementName = aNode.getName();
373 }
374
375 //--------------------------------------------------------------------
376 /**
377 * @return the blackElementName
378 */
379 public final String
380 getBlackElementName()
381 {
382 return theBlackElementName;
383 }
384
385 //--------------------------------------------------------------------
386 /**
387 * @return the CalledBlack
388 */
389 public final boolean
390 isCalledBlack()
391 {
392 return theCalledBlack;
393 }
394
395 //--------------------------------------------------------------------
396 /**
397 * @return the CalledRed
398 */
399 public final boolean
400 isCalledRed()
401 {
402 return theCalledRed;
403 }
404
405 //--------------------------------------------------------------------
406 /**
407 * @return the redElementName
408 */
409 public final String
410 getRedElementName()
411 {
412 return theRedElementName;
413 }
414
415 //--------------------------------------------------------------------
416 // members
417 //--------------------------------------------------------------------
418 private boolean theCalledRed = false;
419 private boolean theCalledBlack = false;
420 private String theRedElementName = null;
421 private String theBlackElementName = null;
422 }
423
424 //------------------------------------------------------------------------
425 // members
426 //------------------------------------------------------------------------
427 private static final String BLACK_NODE_NAME = "Black Node";
428 private static final String RED_NODE_NAME = "Red Node";
429
430 /**
431 * Element components
432 */
433 private final BlackNode theBlackNode = new BlackNode();
434 private final RedNode theRedNode = new RedNode();
435
436 /**
437 * Visitor components
438 */
439 private final VisitorA theVisitorA = new VisitorA();
440 private final VisitorB theVisitorB = new VisitorB();
441 private final VisitorC theVisitorC = new VisitorC();
442
443 /**
444 * Provides logging services for this class.
445 */
446 private final Logger theLogger = LoggerFactory.getLogger(this.getClass());
447 }