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 }