View Javadoc

1   /*
2    * ModeShape (http://www.modeshape.org)
3    * See the COPYRIGHT.txt file distributed with this work for information
4    * regarding copyright ownership.  Some portions may be licensed
5    * to Red Hat, Inc. under one or more contributor license agreements.
6    * See the AUTHORS.txt file in the distribution for a full listing of 
7    * individual contributors.
8    *
9    * ModeShape is free software. Unless otherwise indicated, all code in ModeShape
10   * is licensed to you under the terms of the GNU Lesser General Public License as
11   * published by the Free Software Foundation; either version 2.1 of
12   * the License, or (at your option) any later version.
13   * 
14   * ModeShape is distributed in the hope that it will be useful,
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17   * Lesser General Public License for more details.
18   *
19   * You should have received a copy of the GNU Lesser General Public
20   * License along with this software; if not, write to the Free
21   * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
22   * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
23   */
24  package org.modeshape.graph.query.model;
25  
26  import java.util.HashMap;
27  import java.util.HashSet;
28  import java.util.Iterator;
29  import java.util.LinkedList;
30  import java.util.Map;
31  import java.util.Set;
32  import org.modeshape.common.util.CheckArg;
33  import org.modeshape.graph.ExecutionContext;
34  import org.modeshape.graph.property.Name;
35  import org.modeshape.graph.property.NamespaceRegistry;
36  import org.modeshape.graph.property.Path;
37  
38  /**
39   * A set of common visitors that can be reused or extended, and methods that provide easy construction and calling of visitors.
40   */
41  public class Visitors {
42  
43      /**
44       * Visit all objects in the supplied {@link Visitable object} using a {@link NavigationVisitor} (specifically a
45       * {@link WalkAllVisitor}), and with each of these visited objects calling the appropriate {@code visit(...)} method on the
46       * supplied {@link Visitor}.
47       * 
48       * @param <StrategyVisitor> the type of strategy visitor
49       * @param visitable the top-level object to be visited
50       * @param strategyVisitor the visitor that is to be called for each visited objects, but that does <i>not</i> call
51       *        {@link Visitable#accept(Visitor)}
52       * @return the strategy visitor, allowing the caller to easily invoke operations on the visitor after visitation has completed
53       */
54      public static <StrategyVisitor extends Visitor> StrategyVisitor visitAll( Visitable visitable,
55                                                                                StrategyVisitor strategyVisitor ) {
56          if (visitable != null) visitable.accept(new WalkAllVisitor(strategyVisitor));
57          return strategyVisitor;
58      }
59  
60      /**
61       * Visit the supplied {@link Visitable object} using the supplied {@link Visitor}, which must be responsible for navigation as
62       * well as any business logic.
63       * 
64       * @param <GeneralVisitor> the type of visitor
65       * @param visitable the top-level object to be visited
66       * @param visitor the visitor that is to be used
67       * @return the visitor, allowing the caller to easily invoke operations on the visitor after visitation has completed
68       */
69      public static <GeneralVisitor extends Visitor> GeneralVisitor visit( Visitable visitable,
70                                                                           GeneralVisitor visitor ) {
71          if (visitable != null) visitable.accept(visitor);
72          return visitor;
73      }
74  
75      /**
76       * Using a visitor, obtain the readable string representation of the supplied {@link Visitable object}
77       * 
78       * @param visitable the visitable
79       * @return the string representation
80       */
81      public static String readable( Visitable visitable ) {
82          return visit(visitable, new ReadableVisitor()).getString();
83      }
84  
85      /**
86       * Get a map of the selector names keyed by their aliases.
87       * 
88       * @param visitable the object to be visited
89       * @return the map from the aliases to the aliased selector name; never null but possibly empty
90       */
91      public static Map<SelectorName, SelectorName> getSelectorNamesByAlias( Visitable visitable ) {
92          // Find all of the selectors that have aliases ...
93          final Map<SelectorName, SelectorName> result = new HashMap<SelectorName, SelectorName>();
94          Visitors.visitAll(visitable, new Visitors.AbstractVisitor() {
95              @Override
96              public void visit( AllNodes allNodes ) {
97                  if (allNodes.hasAlias()) {
98                      result.put(allNodes.alias(), allNodes.name());
99                  }
100             }
101 
102             @Override
103             public void visit( NamedSelector selector ) {
104                 if (selector.hasAlias()) {
105                     result.put(selector.alias(), selector.name());
106                 }
107             }
108         });
109         return result;
110     }
111 
112     /**
113      * Get a map of the selector aliases keyed by their names.
114      * 
115      * @param visitable the object to be visited
116      * @return the map from the selector names to their alias (or name if there is no alias); never null but possibly empty
117      */
118     public static Map<SelectorName, SelectorName> getSelectorAliasesByName( Visitable visitable ) {
119         // Find all of the selectors that have aliases ...
120         final Map<SelectorName, SelectorName> result = new HashMap<SelectorName, SelectorName>();
121         Visitors.visitAll(visitable, new Visitors.AbstractVisitor() {
122             @Override
123             public void visit( AllNodes allNodes ) {
124                 if (allNodes.hasAlias()) {
125                     result.put(allNodes.name(), allNodes.aliasOrName());
126                 }
127             }
128 
129             @Override
130             public void visit( NamedSelector selector ) {
131                 if (selector.hasAlias()) {
132                     result.put(selector.name(), selector.aliasOrName());
133                 }
134             }
135         });
136         return result;
137     }
138 
139     /**
140      * Get the names of the selectors referenced by the visitable object.
141      * 
142      * @param visitable the object to be visited
143      * @return the set of selector names referenced in some way by the visitable; never null
144      */
145     public static Set<SelectorName> getSelectorsReferencedBy( Visitable visitable ) {
146         final Set<SelectorName> symbols = new HashSet<SelectorName>();
147         // Walk the entire structure, so only supply a StrategyVisitor (that does no navigation) ...
148         visitAll(visitable, new AbstractVisitor() {
149             @Override
150             public void visit( AllNodes allNodes ) {
151                 if (allNodes.hasAlias()) {
152                     symbols.add(allNodes.alias());
153                 } else {
154                     symbols.add(allNodes.name());
155                 }
156             }
157 
158             @Override
159             public void visit( ChildNode childNode ) {
160                 symbols.add(childNode.selectorName());
161             }
162 
163             @Override
164             public void visit( ChildNodeJoinCondition joinCondition ) {
165                 symbols.add(joinCondition.childSelectorName());
166                 symbols.add(joinCondition.parentSelectorName());
167             }
168 
169             @Override
170             public void visit( Column column ) {
171                 symbols.add(column.selectorName());
172             }
173 
174             @Override
175             public void visit( DescendantNode descendant ) {
176                 symbols.add(descendant.selectorName());
177             }
178 
179             @Override
180             public void visit( DescendantNodeJoinCondition joinCondition ) {
181                 symbols.add(joinCondition.ancestorSelectorName());
182                 symbols.add(joinCondition.descendantSelectorName());
183             }
184 
185             @Override
186             public void visit( EquiJoinCondition joinCondition ) {
187                 symbols.add(joinCondition.selector1Name());
188                 symbols.add(joinCondition.selector2Name());
189             }
190 
191             @Override
192             public void visit( FullTextSearch fullTextSearch ) {
193                 symbols.add(fullTextSearch.selectorName());
194             }
195 
196             @Override
197             public void visit( FullTextSearchScore fullTextSearchScore ) {
198                 symbols.add(fullTextSearchScore.selectorName());
199             }
200 
201             @Override
202             public void visit( Length length ) {
203                 symbols.add(length.selectorName());
204             }
205 
206             @Override
207             public void visit( NodeDepth depth ) {
208                 symbols.add(depth.selectorName());
209             }
210 
211             @Override
212             public void visit( NodePath path ) {
213                 symbols.add(path.selectorName());
214             }
215 
216             @Override
217             public void visit( NodeLocalName node ) {
218                 symbols.add(node.selectorName());
219             }
220 
221             @Override
222             public void visit( NodeName node ) {
223                 symbols.add(node.selectorName());
224             }
225 
226             @Override
227             public void visit( NamedSelector node ) {
228                 if (node.hasAlias()) {
229                     symbols.add(node.alias());
230                 } else {
231                     symbols.add(node.name());
232                 }
233             }
234 
235             @Override
236             public void visit( PropertyExistence prop ) {
237                 symbols.add(prop.selectorName());
238             }
239 
240             @Override
241             public void visit( PropertyValue prop ) {
242                 symbols.add(prop.selectorName());
243             }
244 
245             @Override
246             public void visit( ReferenceValue ref ) {
247                 symbols.add(ref.selectorName());
248             }
249 
250             @Override
251             public void visit( SameNode node ) {
252                 symbols.add(node.selectorName());
253             }
254 
255             @Override
256             public void visit( SameNodeJoinCondition joinCondition ) {
257                 symbols.add(joinCondition.selector1Name());
258                 symbols.add(joinCondition.selector2Name());
259             }
260         });
261         return symbols;
262     }
263 
264     /**
265      * A common base class for all visitors, which provides no-op implementations for all {@code visit(...)} methods. Visitor
266      * implementations can subclass and implement only those methods that they need to implement.
267      * <p>
268      * This is often an excellent base class for <i>strategy visitors</i>, which simply are {@link Visitor} implementations that
269      * are responsible only for visiting the supplied object but that never call {@link Visitable#accept(Visitor)}. Such strategy
270      * visitors can be used in conjunction with separate <i>{@link NavigationVisitor navigation visitors}</i> that do the job of
271      * navigating the Visitable objects and, for each, delegating to the strategy visitor. See
272      * {@link Visitors#visitAll(Visitable, Visitor)} for an example.
273      * </p>
274      */
275     public static class AbstractVisitor implements Visitor {
276 
277         /**
278          * {@inheritDoc}
279          * 
280          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.AllNodes)
281          */
282         public void visit( AllNodes obj ) {
283         }
284 
285         /**
286          * {@inheritDoc}
287          * 
288          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.And)
289          */
290         public void visit( And obj ) {
291         }
292 
293         /**
294          * {@inheritDoc}
295          * 
296          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.ArithmeticOperand)
297          */
298         public void visit( ArithmeticOperand obj ) {
299         }
300 
301         /**
302          * {@inheritDoc}
303          * 
304          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.Between)
305          */
306         public void visit( Between obj ) {
307         }
308 
309         /**
310          * {@inheritDoc}
311          * 
312          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.BindVariableName)
313          */
314         public void visit( BindVariableName obj ) {
315         }
316 
317         /**
318          * {@inheritDoc}
319          * 
320          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.ChildNode)
321          */
322         public void visit( ChildNode obj ) {
323         }
324 
325         /**
326          * {@inheritDoc}
327          * 
328          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.ChildNodeJoinCondition)
329          */
330         public void visit( ChildNodeJoinCondition obj ) {
331         }
332 
333         /**
334          * {@inheritDoc}
335          * 
336          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.Column)
337          */
338         public void visit( Column obj ) {
339         }
340 
341         /**
342          * {@inheritDoc}
343          * 
344          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.Comparison)
345          */
346         public void visit( Comparison obj ) {
347         }
348 
349         /**
350          * {@inheritDoc}
351          * 
352          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.DescendantNode)
353          */
354         public void visit( DescendantNode obj ) {
355         }
356 
357         /**
358          * {@inheritDoc}
359          * 
360          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.DescendantNodeJoinCondition)
361          */
362         public void visit( DescendantNodeJoinCondition obj ) {
363         }
364 
365         /**
366          * {@inheritDoc}
367          * 
368          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.EquiJoinCondition)
369          */
370         public void visit( EquiJoinCondition obj ) {
371         }
372 
373         /**
374          * {@inheritDoc}
375          * 
376          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.FullTextSearch)
377          */
378         public void visit( FullTextSearch obj ) {
379         }
380 
381         /**
382          * {@inheritDoc}
383          * 
384          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.FullTextSearchScore)
385          */
386         public void visit( FullTextSearchScore obj ) {
387         }
388 
389         /**
390          * {@inheritDoc}
391          * 
392          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.Join)
393          */
394         public void visit( Join obj ) {
395         }
396 
397         /**
398          * {@inheritDoc}
399          * 
400          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.Length)
401          */
402         public void visit( Length obj ) {
403         }
404 
405         /**
406          * {@inheritDoc}
407          * 
408          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.Limit)
409          */
410         public void visit( Limit limit ) {
411         }
412 
413         /**
414          * {@inheritDoc}
415          * 
416          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.Literal)
417          */
418         public void visit( Literal obj ) {
419         }
420 
421         /**
422          * {@inheritDoc}
423          * 
424          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.LowerCase)
425          */
426         public void visit( LowerCase obj ) {
427         }
428 
429         /**
430          * {@inheritDoc}
431          * 
432          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.NodeDepth)
433          */
434         public void visit( NodeDepth obj ) {
435         }
436 
437         /**
438          * {@inheritDoc}
439          * 
440          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.NodePath)
441          */
442         public void visit( NodePath obj ) {
443         }
444 
445         /**
446          * {@inheritDoc}
447          * 
448          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.NodeName)
449          */
450         public void visit( NodeName obj ) {
451         }
452 
453         /**
454          * {@inheritDoc}
455          * 
456          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.NodeLocalName)
457          */
458         public void visit( NodeLocalName obj ) {
459         }
460 
461         /**
462          * {@inheritDoc}
463          * 
464          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.NamedSelector)
465          */
466         public void visit( NamedSelector obj ) {
467         }
468 
469         /**
470          * {@inheritDoc}
471          * 
472          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.Not)
473          */
474         public void visit( Not obj ) {
475         }
476 
477         /**
478          * {@inheritDoc}
479          * 
480          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.Or)
481          */
482         public void visit( Or obj ) {
483         }
484 
485         /**
486          * {@inheritDoc}
487          * 
488          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.Ordering)
489          */
490         public void visit( Ordering obj ) {
491         }
492 
493         /**
494          * {@inheritDoc}
495          * 
496          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.PropertyExistence)
497          */
498         public void visit( PropertyExistence obj ) {
499         }
500 
501         /**
502          * {@inheritDoc}
503          * 
504          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.PropertyValue)
505          */
506         public void visit( PropertyValue obj ) {
507         }
508 
509         /**
510          * {@inheritDoc}
511          * 
512          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.Query)
513          */
514         public void visit( Query obj ) {
515         }
516 
517         /**
518          * {@inheritDoc}
519          * 
520          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.ReferenceValue)
521          */
522         public void visit( ReferenceValue obj ) {
523         }
524 
525         /**
526          * {@inheritDoc}
527          * 
528          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.SameNode)
529          */
530         public void visit( SameNode obj ) {
531         }
532 
533         /**
534          * {@inheritDoc}
535          * 
536          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.SameNodeJoinCondition)
537          */
538         public void visit( SameNodeJoinCondition obj ) {
539         }
540 
541         /**
542          * {@inheritDoc}
543          * 
544          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.SetCriteria)
545          */
546         public void visit( SetCriteria obj ) {
547         }
548 
549         /**
550          * {@inheritDoc}
551          * 
552          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.SetQuery)
553          */
554         public void visit( SetQuery obj ) {
555         }
556 
557         /**
558          * {@inheritDoc}
559          * 
560          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.UpperCase)
561          */
562         public void visit( UpperCase obj ) {
563         }
564     }
565 
566     /**
567      * An abstract visitor implementation that performs navigation of the query object.
568      * <p>
569      * Subclasses should always implement the {@code visit(T object)} methods by performing the following actions:
570      * <ol>
571      * <li>Call <code>strategy.visit(object);</code></li>
572      * <li>Add any children of {@code object} that are to be visited using {@link #enqueue(Visitable)}</li>
573      * <li>Call {@link #visitNext()}</code></li>
574      * </ol>
575      * </p>
576      */
577     public static abstract class NavigationVisitor implements Visitor {
578         protected final Visitor strategy;
579         private final LinkedList<? super Visitable> itemQueue = new LinkedList<Visitable>();
580 
581         /**
582          * Create a visitor that walks all query objects.
583          * 
584          * @param strategy the visitor that should be called at every node.
585          */
586         protected NavigationVisitor( Visitor strategy ) {
587             assert strategy != null;
588             this.strategy = strategy;
589         }
590 
591         protected final void enqueue( Visitable objectToBeVisited ) {
592             if (objectToBeVisited != null) {
593                 itemQueue.add(objectToBeVisited);
594             }
595         }
596 
597         protected final void enqueue( Iterable<? extends Visitable> objectsToBeVisited ) {
598             for (Visitable objectToBeVisited : objectsToBeVisited) {
599                 if (objectToBeVisited != null) {
600                     itemQueue.add(objectToBeVisited);
601                 }
602             }
603         }
604 
605         protected final void visitNext() {
606             if (!itemQueue.isEmpty()) {
607                 Visitable first = (Visitable)itemQueue.removeFirst();
608                 assert first != null;
609                 first.accept(this);
610             }
611         }
612     }
613 
614     /**
615      * A visitor implementation that walks the entire query object tree and delegates to another supplied visitor to do the actual
616      * work.
617      */
618     public static class WalkAllVisitor extends NavigationVisitor {
619 
620         /**
621          * Create a visitor that walks all query objects.
622          * 
623          * @param strategy the visitor that should be called at every node.
624          */
625         protected WalkAllVisitor( Visitor strategy ) {
626             super(strategy);
627         }
628 
629         /**
630          * {@inheritDoc}
631          * 
632          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.AllNodes)
633          */
634         public void visit( AllNodes allNodes ) {
635             strategy.visit(allNodes);
636             visitNext();
637         }
638 
639         /**
640          * {@inheritDoc}
641          * 
642          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.And)
643          */
644         public void visit( And and ) {
645             strategy.visit(and);
646             enqueue(and.left());
647             enqueue(and.right());
648             visitNext();
649         }
650 
651         /**
652          * {@inheritDoc}
653          * 
654          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.ArithmeticOperand)
655          */
656         public void visit( ArithmeticOperand arithmeticOperation ) {
657             strategy.visit(arithmeticOperation);
658             enqueue(arithmeticOperation.left());
659             enqueue(arithmeticOperation.right());
660             visitNext();
661         }
662 
663         /**
664          * {@inheritDoc}
665          * 
666          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.Between)
667          */
668         public void visit( Between between ) {
669             strategy.visit(between);
670             enqueue(between.operand());
671             enqueue(between.lowerBound());
672             enqueue(between.upperBound());
673             visitNext();
674         }
675 
676         /**
677          * {@inheritDoc}
678          * 
679          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.BindVariableName)
680          */
681         public void visit( BindVariableName variableName ) {
682             strategy.visit(variableName);
683             visitNext();
684         }
685 
686         /**
687          * {@inheritDoc}
688          * 
689          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.ChildNode)
690          */
691         public void visit( ChildNode child ) {
692             strategy.visit(child);
693             visitNext();
694         }
695 
696         /**
697          * {@inheritDoc}
698          * 
699          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.ChildNodeJoinCondition)
700          */
701         public void visit( ChildNodeJoinCondition joinCondition ) {
702             strategy.visit(joinCondition);
703             visitNext();
704         }
705 
706         /**
707          * {@inheritDoc}
708          * 
709          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.Column)
710          */
711         public void visit( Column column ) {
712             strategy.visit(column);
713             visitNext();
714         }
715 
716         /**
717          * {@inheritDoc}
718          * 
719          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.Comparison)
720          */
721         public void visit( Comparison comparison ) {
722             strategy.visit(comparison);
723             enqueue(comparison.operand1());
724             enqueue(comparison.operand2());
725             visitNext();
726         }
727 
728         /**
729          * {@inheritDoc}
730          * 
731          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.DescendantNode)
732          */
733         public void visit( DescendantNode descendant ) {
734             strategy.visit(descendant);
735             visitNext();
736         }
737 
738         /**
739          * {@inheritDoc}
740          * 
741          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.DescendantNodeJoinCondition)
742          */
743         public void visit( DescendantNodeJoinCondition condition ) {
744             strategy.visit(condition);
745             visitNext();
746         }
747 
748         /**
749          * {@inheritDoc}
750          * 
751          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.EquiJoinCondition)
752          */
753         public void visit( EquiJoinCondition condition ) {
754             strategy.visit(condition);
755             visitNext();
756         }
757 
758         /**
759          * {@inheritDoc}
760          * 
761          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.FullTextSearch)
762          */
763         public void visit( FullTextSearch fullTextSearch ) {
764             strategy.visit(fullTextSearch);
765             visitNext();
766         }
767 
768         /**
769          * {@inheritDoc}
770          * 
771          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.FullTextSearchScore)
772          */
773         public void visit( FullTextSearchScore score ) {
774             strategy.visit(score);
775             visitNext();
776         }
777 
778         /**
779          * {@inheritDoc}
780          * 
781          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.Join)
782          */
783         public void visit( Join join ) {
784             strategy.visit(join);
785             enqueue(join.left());
786             enqueue(join.joinCondition());
787             enqueue(join.right());
788             visitNext();
789         }
790 
791         /**
792          * {@inheritDoc}
793          * 
794          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.Length)
795          */
796         public void visit( Length length ) {
797             strategy.visit(length);
798             visitNext();
799         }
800 
801         /**
802          * {@inheritDoc}
803          * 
804          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.Limit)
805          */
806         public void visit( Limit limit ) {
807             strategy.visit(limit);
808             visitNext();
809         }
810 
811         /**
812          * {@inheritDoc}
813          * 
814          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.Literal)
815          */
816         public void visit( Literal literal ) {
817             strategy.visit(literal);
818             visitNext();
819         }
820 
821         /**
822          * {@inheritDoc}
823          * 
824          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.LowerCase)
825          */
826         public void visit( LowerCase lowerCase ) {
827             strategy.visit(lowerCase);
828             enqueue(lowerCase.operand());
829             visitNext();
830         }
831 
832         /**
833          * {@inheritDoc}
834          * 
835          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.NodeDepth)
836          */
837         public void visit( NodeDepth depth ) {
838             strategy.visit(depth);
839             visitNext();
840         }
841 
842         /**
843          * {@inheritDoc}
844          * 
845          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.NodePath)
846          */
847         public void visit( NodePath path ) {
848             strategy.visit(path);
849             visitNext();
850         }
851 
852         /**
853          * {@inheritDoc}
854          * 
855          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.NodeName)
856          */
857         public void visit( NodeName nodeName ) {
858             strategy.visit(nodeName);
859             visitNext();
860         }
861 
862         /**
863          * {@inheritDoc}
864          * 
865          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.NodeLocalName)
866          */
867         public void visit( NodeLocalName nodeLocalName ) {
868             strategy.visit(nodeLocalName);
869             visitNext();
870         }
871 
872         /**
873          * {@inheritDoc}
874          * 
875          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.NamedSelector)
876          */
877         public void visit( NamedSelector selector ) {
878             strategy.visit(selector);
879             visitNext();
880         }
881 
882         /**
883          * {@inheritDoc}
884          * 
885          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.Not)
886          */
887         public void visit( Not not ) {
888             strategy.visit(not);
889             enqueue(not.constraint());
890             visitNext();
891         }
892 
893         /**
894          * {@inheritDoc}
895          * 
896          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.Or)
897          */
898         public void visit( Or or ) {
899             strategy.visit(or);
900             enqueue(or.left());
901             enqueue(or.right());
902             visitNext();
903         }
904 
905         /**
906          * {@inheritDoc}
907          * 
908          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.Ordering)
909          */
910         public void visit( Ordering ordering ) {
911             strategy.visit(ordering);
912             enqueue(ordering.operand());
913             visitNext();
914         }
915 
916         /**
917          * {@inheritDoc}
918          * 
919          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.PropertyExistence)
920          */
921         public void visit( PropertyExistence existence ) {
922             strategy.visit(existence);
923             visitNext();
924         }
925 
926         /**
927          * {@inheritDoc}
928          * 
929          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.PropertyValue)
930          */
931         public void visit( PropertyValue propertyValue ) {
932             strategy.visit(propertyValue);
933             visitNext();
934         }
935 
936         /**
937          * {@inheritDoc}
938          * 
939          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.Query)
940          */
941         public void visit( Query query ) {
942             strategy.visit(query);
943             enqueue(query.source());
944             enqueue(query.columns());
945             enqueue(query.constraint());
946             enqueue(query.orderings());
947             visitNext();
948         }
949 
950         /**
951          * {@inheritDoc}
952          * 
953          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.ReferenceValue)
954          */
955         public void visit( ReferenceValue referenceValue ) {
956             strategy.visit(referenceValue);
957             visitNext();
958         }
959 
960         /**
961          * {@inheritDoc}
962          * 
963          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.SameNode)
964          */
965         public void visit( SameNode sameNode ) {
966             strategy.visit(sameNode);
967             visitNext();
968         }
969 
970         /**
971          * {@inheritDoc}
972          * 
973          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.SameNodeJoinCondition)
974          */
975         public void visit( SameNodeJoinCondition condition ) {
976             strategy.visit(condition);
977             visitNext();
978         }
979 
980         /**
981          * {@inheritDoc}
982          * 
983          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.SetCriteria)
984          */
985         public void visit( SetCriteria setCriteria ) {
986             strategy.visit(setCriteria);
987             enqueue(setCriteria.leftOperand());
988             for (StaticOperand right : setCriteria.rightOperands()) {
989                 enqueue(right);
990             }
991             visitNext();
992         }
993 
994         /**
995          * {@inheritDoc}
996          * 
997          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.SetQuery)
998          */
999         public void visit( SetQuery setQuery ) {
1000             strategy.visit(setQuery);
1001             enqueue(setQuery.left());
1002             enqueue(setQuery.right());
1003             visitNext();
1004         }
1005 
1006         /**
1007          * {@inheritDoc}
1008          * 
1009          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.UpperCase)
1010          */
1011         public void visit( UpperCase upperCase ) {
1012             strategy.visit(upperCase);
1013             enqueue(upperCase.operand());
1014             visitNext();
1015         }
1016     }
1017 
1018     public static class ReadableVisitor implements Visitor {
1019         private final StringBuilder sb = new StringBuilder();
1020         private final ExecutionContext context;
1021         private final NamespaceRegistry registry;
1022 
1023         public ReadableVisitor( ExecutionContext context ) {
1024             CheckArg.isNotNull(context, "context");
1025             this.context = context;
1026             this.registry = context == null ? null : context.getNamespaceRegistry();
1027         }
1028 
1029         public ReadableVisitor() {
1030             this.context = null;
1031             this.registry = null;
1032         }
1033 
1034         protected final ReadableVisitor append( String string ) {
1035             sb.append(string);
1036             return this;
1037         }
1038 
1039         protected final ReadableVisitor append( char character ) {
1040             sb.append(character);
1041             return this;
1042         }
1043 
1044         protected final ReadableVisitor append( int value ) {
1045             sb.append(value);
1046             return this;
1047         }
1048 
1049         protected final ReadableVisitor append( SelectorName name ) {
1050             sb.append(name.getString());
1051             return this;
1052         }
1053 
1054         protected final ReadableVisitor append( Name name ) {
1055             sb.append(name.getString(registry, null, null));
1056             return this;
1057         }
1058 
1059         protected final ReadableVisitor append( Path path ) {
1060             sb.append('\'');
1061             sb.append(path.getString(registry));
1062             sb.append('\'');
1063             return this;
1064         }
1065 
1066         /**
1067          * @return context
1068          */
1069         public final ExecutionContext getContext() {
1070             return context;
1071         }
1072 
1073         /**
1074          * Get the string representation of the visited objects.
1075          * 
1076          * @return the string representation
1077          */
1078         public final String getString() {
1079             return sb.toString();
1080         }
1081 
1082         /**
1083          * {@inheritDoc}
1084          * 
1085          * @see java.lang.Object#toString()
1086          */
1087         @Override
1088         public String toString() {
1089             return sb.toString();
1090         }
1091 
1092         /**
1093          * {@inheritDoc}
1094          * 
1095          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.AllNodes)
1096          */
1097         public void visit( AllNodes allNodes ) {
1098             append(allNodes.name());
1099             if (allNodes.hasAlias()) {
1100                 append(" AS ").append(allNodes.alias());
1101             }
1102         }
1103 
1104         /**
1105          * {@inheritDoc}
1106          * 
1107          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.And)
1108          */
1109         public void visit( And and ) {
1110             append('(');
1111             and.left().accept(this);
1112             append(" AND ");
1113             and.right().accept(this);
1114             append(')');
1115         }
1116 
1117         /**
1118          * {@inheritDoc}
1119          * 
1120          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.ArithmeticOperand)
1121          */
1122         public void visit( ArithmeticOperand arithmeticOperand ) {
1123             append('(');
1124             arithmeticOperand.left().accept(this);
1125             append(' ');
1126             append(arithmeticOperand.operator().symbol());
1127             append(' ');
1128             arithmeticOperand.right().accept(this);
1129             append(')');
1130         }
1131 
1132         /**
1133          * {@inheritDoc}
1134          * 
1135          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.Between)
1136          */
1137         public void visit( Between between ) {
1138             between.operand().accept(this);
1139             append(" BETWEEN ");
1140             between.lowerBound().accept(this);
1141             if (!between.isLowerBoundIncluded()) append(" EXCLUSIVE");
1142             append(" AND ");
1143             between.upperBound().accept(this);
1144             if (!between.isUpperBoundIncluded()) append(" EXCLUSIVE");
1145         }
1146 
1147         /**
1148          * {@inheritDoc}
1149          * 
1150          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.BindVariableName)
1151          */
1152         public void visit( BindVariableName variable ) {
1153             append('$').append(variable.variableName());
1154         }
1155 
1156         /**
1157          * {@inheritDoc}
1158          * 
1159          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.ChildNode)
1160          */
1161         public void visit( ChildNode child ) {
1162             append("ISCHILDNODE(");
1163             append(child.selectorName());
1164             append(',');
1165             append(child.parentPath());
1166             append(')');
1167         }
1168 
1169         /**
1170          * {@inheritDoc}
1171          * 
1172          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.ChildNodeJoinCondition)
1173          */
1174         public void visit( ChildNodeJoinCondition condition ) {
1175             append("ISCHILDNODE(");
1176             append(condition.childSelectorName());
1177             append(',');
1178             append(condition.parentSelectorName());
1179             append(')');
1180         }
1181 
1182         /**
1183          * {@inheritDoc}
1184          * 
1185          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.Column)
1186          */
1187         public void visit( Column column ) {
1188             append(column.selectorName());
1189             if (column.propertyName() == null) {
1190                 append(".*");
1191             } else {
1192                 String propertyName = column.propertyName();
1193                 append('.').append(propertyName);
1194                 if (!propertyName.equals(column.columnName()) && !propertyName.equals(column.columnName())) {
1195                     append(" AS ").append(column.columnName());
1196                 }
1197             }
1198         }
1199 
1200         /**
1201          * {@inheritDoc}
1202          * 
1203          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.Comparison)
1204          */
1205         public void visit( Comparison comparison ) {
1206             comparison.operand1().accept(this);
1207             append(' ').append(comparison.operator().symbol()).append(' ');
1208             comparison.operand2().accept(this);
1209         }
1210 
1211         /**
1212          * {@inheritDoc}
1213          * 
1214          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.DescendantNode)
1215          */
1216         public void visit( DescendantNode descendant ) {
1217             append("ISDESCENDANTNODE(");
1218             append(descendant.selectorName());
1219             append(',');
1220             append(descendant.ancestorPath());
1221             append(')');
1222         }
1223 
1224         /**
1225          * {@inheritDoc}
1226          * 
1227          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.DescendantNodeJoinCondition)
1228          */
1229         public void visit( DescendantNodeJoinCondition condition ) {
1230             append("ISDESCENDANTNODE(");
1231             append(condition.descendantSelectorName());
1232             append(',');
1233             append(condition.ancestorSelectorName());
1234             append(')');
1235         }
1236 
1237         /**
1238          * {@inheritDoc}
1239          * 
1240          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.EquiJoinCondition)
1241          */
1242         public void visit( EquiJoinCondition condition ) {
1243             append(condition.selector1Name()).append('.').append(condition.property1Name());
1244             append(" = ");
1245             append(condition.selector2Name()).append('.').append(condition.property2Name());
1246         }
1247 
1248         /**
1249          * {@inheritDoc}
1250          * 
1251          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.FullTextSearch)
1252          */
1253         public void visit( FullTextSearch fullText ) {
1254             append("CONTAINS(").append(fullText.selectorName());
1255             if (fullText.propertyName() != null) {
1256                 append('.').append(fullText.propertyName());
1257             }
1258             sb.append(",'").append(fullText.fullTextSearchExpression()).append("')");
1259         }
1260 
1261         /**
1262          * {@inheritDoc}
1263          * 
1264          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.FullTextSearchScore)
1265          */
1266         public void visit( FullTextSearchScore score ) {
1267             append("SCORE(").append(score.selectorName()).append(')');
1268         }
1269 
1270         /**
1271          * {@inheritDoc}
1272          * 
1273          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.Join)
1274          */
1275         public void visit( Join join ) {
1276             join.left().accept(this);
1277             // if (join.getType() != JoinType.INNER) {
1278             sb.append(' ').append(join.type().symbol());
1279             // } else {
1280             // sb.append(',');
1281             // }
1282             append(' ');
1283             join.right().accept(this);
1284             append(" ON ");
1285             join.joinCondition().accept(this);
1286         }
1287 
1288         /**
1289          * {@inheritDoc}
1290          * 
1291          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.Length)
1292          */
1293         public void visit( Length length ) {
1294             append("LENGTH(");
1295             length.propertyValue().accept(this);
1296             append(')');
1297         }
1298 
1299         /**
1300          * {@inheritDoc}
1301          * 
1302          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.Limit)
1303          */
1304         public void visit( Limit limit ) {
1305             append("LIMIT ").append(limit.rowLimit());
1306             if (limit.offset() != 0) {
1307                 append(" OFFSET ").append(limit.offset());
1308             }
1309         }
1310 
1311         /**
1312          * {@inheritDoc}
1313          * 
1314          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.Literal)
1315          */
1316         public void visit( Literal literal ) {
1317             Object value = literal.value();
1318             boolean quote = value instanceof String || value instanceof Path || value instanceof Name;
1319             if (quote) append('\'');
1320             if (context == null) {
1321                 append(literal.value().toString());
1322             } else {
1323                 append(context.getValueFactories().getStringFactory().create(literal.value()));
1324             }
1325             if (quote) append('\'');
1326         }
1327 
1328         /**
1329          * {@inheritDoc}
1330          * 
1331          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.LowerCase)
1332          */
1333         public void visit( LowerCase lowerCase ) {
1334             append("LOWER(");
1335             lowerCase.operand().accept(this);
1336             append(')');
1337         }
1338 
1339         /**
1340          * {@inheritDoc}
1341          * 
1342          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.NodeDepth)
1343          */
1344         public void visit( NodeDepth depth ) {
1345             append("DEPTH(").append(depth.selectorName()).append(')');
1346         }
1347 
1348         /**
1349          * {@inheritDoc}
1350          * 
1351          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.NodePath)
1352          */
1353         public void visit( NodePath path ) {
1354             append("PATH(").append(path.selectorName()).append(')');
1355         }
1356 
1357         /**
1358          * {@inheritDoc}
1359          * 
1360          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.NodeLocalName)
1361          */
1362         public void visit( NodeLocalName name ) {
1363             append("LOCALNAME(").append(name.selectorName()).append(')');
1364         }
1365 
1366         /**
1367          * {@inheritDoc}
1368          * 
1369          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.NodeName)
1370          */
1371         public void visit( NodeName name ) {
1372             append("NAME(").append(name.selectorName()).append(')');
1373         }
1374 
1375         /**
1376          * {@inheritDoc}
1377          * 
1378          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.NamedSelector)
1379          */
1380         public void visit( NamedSelector selector ) {
1381             append(selector.name());
1382             if (selector.hasAlias()) {
1383                 append(" AS ").append(selector.alias());
1384             }
1385         }
1386 
1387         /**
1388          * {@inheritDoc}
1389          * 
1390          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.Not)
1391          */
1392         public void visit( Not not ) {
1393             append('(');
1394             append("NOT ");
1395             not.constraint().accept(this);
1396             append(')');
1397         }
1398 
1399         /**
1400          * {@inheritDoc}
1401          * 
1402          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.Or)
1403          */
1404         public void visit( Or or ) {
1405             append('(');
1406             or.left().accept(this);
1407             append(" OR ");
1408             or.right().accept(this);
1409             append(')');
1410         }
1411 
1412         /**
1413          * {@inheritDoc}
1414          * 
1415          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.Ordering)
1416          */
1417         public void visit( Ordering ordering ) {
1418             ordering.operand().accept(this);
1419             append(' ').append(ordering.order().symbol());
1420         }
1421 
1422         /**
1423          * {@inheritDoc}
1424          * 
1425          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.PropertyExistence)
1426          */
1427         public void visit( PropertyExistence existence ) {
1428             append(existence.selectorName()).append('.').append(existence.propertyName()).append(" IS NOT NULL");
1429         }
1430 
1431         /**
1432          * {@inheritDoc}
1433          * 
1434          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.PropertyValue)
1435          */
1436         public void visit( PropertyValue value ) {
1437             append(value.selectorName()).append('.').append(value.propertyName());
1438         }
1439 
1440         /**
1441          * {@inheritDoc}
1442          * 
1443          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.ReferenceValue)
1444          */
1445         public void visit( ReferenceValue value ) {
1446             append(value.selectorName());
1447             if (value.propertyName() != null) {
1448                 append('.').append(value.propertyName());
1449             }
1450         }
1451 
1452         /**
1453          * {@inheritDoc}
1454          * 
1455          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.Query)
1456          */
1457         public void visit( Query query ) {
1458             append("SELECT ");
1459             if (query.isDistinct()) append("DISTINCT ");
1460             if (query.columns().isEmpty()) {
1461                 append('*');
1462             } else {
1463                 boolean isFirst = true;
1464                 for (Column column : query.columns()) {
1465                     if (isFirst) isFirst = false;
1466                     else append(',');
1467                     column.accept(this);
1468                 }
1469             }
1470             append(" FROM ");
1471             query.source().accept(this);
1472             if (query.constraint() != null) {
1473                 append(" WHERE ");
1474                 query.constraint().accept(this);
1475             }
1476             if (!query.orderings().isEmpty()) {
1477                 append(" ORDER BY ");
1478                 boolean isFirst = true;
1479                 for (Ordering ordering : query.orderings()) {
1480                     if (isFirst) isFirst = false;
1481                     else append(',');
1482                     ordering.accept(this);
1483                 }
1484             }
1485             if (!query.limits().isUnlimited()) {
1486                 append(' ');
1487                 query.limits().accept(this);
1488             }
1489         }
1490 
1491         /**
1492          * {@inheritDoc}
1493          * 
1494          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.SameNode)
1495          */
1496         public void visit( SameNode sameNode ) {
1497             append("ISSAMENODE(").append(sameNode.selectorName()).append(',').append(sameNode.path()).append(')');
1498         }
1499 
1500         /**
1501          * {@inheritDoc}
1502          * 
1503          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.SameNodeJoinCondition)
1504          */
1505         public void visit( SameNodeJoinCondition condition ) {
1506             append("ISSAMENODE(").append(condition.selector1Name()).append(',').append(condition.selector2Name());
1507             if (condition.selector2Path() != null) {
1508                 append(',').append(condition.selector2Path());
1509             }
1510             append(')');
1511         }
1512 
1513         /**
1514          * {@inheritDoc}
1515          * 
1516          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.SetCriteria)
1517          */
1518         public void visit( SetCriteria criteria ) {
1519             criteria.leftOperand().accept(this);
1520             append(" IN (");
1521             Iterator<? extends StaticOperand> iter = criteria.rightOperands().iterator();
1522             if (iter.hasNext()) {
1523                 iter.next().accept(this);
1524                 while (iter.hasNext()) {
1525                     append(',');
1526                     iter.next().accept(this);
1527                 }
1528             }
1529             append(')');
1530         }
1531 
1532         /**
1533          * {@inheritDoc}
1534          * 
1535          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.SetQuery)
1536          */
1537         public void visit( SetQuery query ) {
1538             query.left().accept(this);
1539             append(' ').append(query.operation().getSymbol()).append(' ');
1540             if (query.isAll()) append("ALL ");
1541             query.right().accept(this);
1542         }
1543 
1544         /**
1545          * {@inheritDoc}
1546          * 
1547          * @see org.modeshape.graph.query.model.Visitor#visit(org.modeshape.graph.query.model.UpperCase)
1548          */
1549         public void visit( UpperCase upperCase ) {
1550             append("UPPER(");
1551             upperCase.operand().accept(this);
1552             append(')');
1553         }
1554 
1555     }
1556 }