KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > hibernate > hql > ast > util > ASTUtil


1 // $Id: ASTUtil.java,v 1.1 2005/07/12 20:27:17 steveebersole Exp $
2
package org.hibernate.hql.ast.util;
3
4 import java.util.ArrayList JavaDoc;
5 import java.util.List JavaDoc;
6
7 import antlr.ASTFactory;
8 import antlr.collections.AST;
9 import antlr.collections.impl.ASTArray;
10
11 /**
12  * Provides utility methods for AST traversal and manipulation.
13  *
14  * @author Joshua Davis (pgmjsd@sourceforge.net)
15  */

16 public final class ASTUtil {
17     /**
18      * Private empty constructor.
19      * (or else checkstyle says: 'warning: Utility classes should not have a public or default constructor.')
20      *
21      * @deprecated (tell clover to ignore this)
22      */

23     private ASTUtil() {
24     }
25
26     /**
27      * Creates a single node AST.
28      *
29      * @param astFactory The factory.
30      * @param type The node type.
31      * @param text The node text.
32      * @return AST - A single node tree.
33      */

34     public static AST create(ASTFactory astFactory, int type, String JavaDoc text) {
35         AST node = astFactory.create( type, text );
36         return node;
37     }
38
39     /**
40      * Creates a single node AST as a sibling.
41      *
42      * @param astFactory The factory.
43      * @param type The node type.
44      * @param text The node text.
45      * @param prevSibling The previous sibling.
46      * @return AST - A single node tree.
47      */

48     public static AST createSibling(ASTFactory astFactory, int type, String JavaDoc text, AST prevSibling) {
49         AST node = astFactory.create( type, text );
50         node.setNextSibling( prevSibling.getNextSibling() );
51         prevSibling.setNextSibling( node );
52         return node;
53     }
54
55     public static AST insertSibling(AST node, AST prevSibling) {
56         node.setNextSibling( prevSibling.getNextSibling() );
57         prevSibling.setNextSibling( node );
58         return node;
59     }
60
61     /**
62      * Creates a 'binary operator' subtree, given the information about the
63      * parent and the two child nodex.
64      *
65      * @param factory The AST factory.
66      * @param parentType The type of the parent node.
67      * @param parentText The text of the parent node.
68      * @param child1 The first child.
69      * @param child2 The second child.
70      * @return AST - A new sub-tree of the form "(parent child1 child2)"
71      */

72     public static AST createBinarySubtree(ASTFactory factory, int parentType, String JavaDoc parentText, AST child1, AST child2) {
73         ASTArray array = createAstArray( factory, 3, parentType, parentText, child1 );
74         array.add( child2 );
75         return factory.make( array );
76     }
77
78     /**
79      * Creates a single parent of the specified child (i.e. a 'unary operator'
80      * subtree).
81      *
82      * @param factory The AST factory.
83      * @param parentType The type of the parent node.
84      * @param parentText The text of the parent node.
85      * @param child The child.
86      * @return AST - A new sub-tree of the form "(parent child)"
87      */

88     public static AST createParent(ASTFactory factory, int parentType, String JavaDoc parentText, AST child) {
89         ASTArray array = createAstArray( factory, 2, parentType, parentText, child );
90         return factory.make( array );
91     }
92
93     public static AST createTree(ASTFactory factory, AST[] nestedChildren) {
94         AST[] array = new AST[2];
95         int limit = nestedChildren.length - 1;
96         for ( int i = limit; i >= 0; i-- ) {
97             if ( i != limit ) {
98                 array[1] = nestedChildren[i + 1];
99                 array[0] = nestedChildren[i];
100                 factory.make( array );
101             }
102         }
103         return array[0];
104     }
105
106     /**
107      * Finds the first node of the specified type in the chain of children.
108      *
109      * @param parent The parent
110      * @param type The type to find.
111      * @return The first node of the specified type, or null if not found.
112      */

113     public static AST findTypeInChildren(AST parent, int type) {
114         AST n = parent.getFirstChild();
115         while ( n != null && n.getType() != type )
116             n = n.getNextSibling();
117         return n;
118     }
119
120     /**
121      * Returns the last direct child of 'n'.
122      *
123      * @param n The parent
124      * @return The last direct child of 'n'.
125      */

126     public static AST getLastChild(AST n) {
127         return getLastSibling( n.getFirstChild() );
128     }
129
130     /**
131      * Returns the last sibling of 'a'.
132      *
133      * @param a The sibling.
134      * @return The last sibling of 'a'.
135      */

136     private static AST getLastSibling(AST a) {
137         AST last = null;
138         while ( a != null ) {
139             last = a;
140             a = a.getNextSibling();
141         }
142         return last;
143     }
144
145     /**
146      * Returns the 'list' representation with some brackets around it for debugging.
147      *
148      * @param n The tree.
149      * @return The list representation of the tree.
150      */

151     public static String JavaDoc getDebugString(AST n) {
152         StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
153         buf.append( "[ " );
154         buf.append( ( n == null ) ? "{null}" : n.toStringTree() );
155         buf.append( " ]" );
156         return buf.toString();
157     }
158
159     /**
160      * Find the previous sibling in the parent for the given child.
161      *
162      * @param parent the parent node
163      * @param child the child to find the previous sibling of
164      * @return the previous sibling of the child
165      */

166     public static AST findPreviousSibling(AST parent, AST child) {
167         AST prev = null;
168         AST n = parent.getFirstChild();
169         while ( n != null ) {
170             if ( n == child ) {
171                 return prev;
172             }
173             prev = n;
174             n = n.getNextSibling();
175         }
176         throw new IllegalArgumentException JavaDoc( "Child not found in parent!" );
177     }
178
179     /**
180      * Makes the child node a sibling of the parent, reconnecting all siblings.
181      *
182      * @param parent the parent
183      * @param child the child
184      */

185     public static void makeSiblingOfParent(AST parent, AST child) {
186         AST prev = findPreviousSibling( parent, child );
187         if ( prev != null ) {
188             prev.setNextSibling( child.getNextSibling() );
189         }
190         else { // child == parent.getFirstChild()
191
parent.setFirstChild( child.getNextSibling() );
192         }
193         child.setNextSibling( parent.getNextSibling() );
194         parent.setNextSibling( child );
195     }
196
197     public static String JavaDoc getPathText(AST n) {
198         StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
199         getPathText( buf, n );
200         return buf.toString();
201     }
202
203     private static void getPathText(StringBuffer JavaDoc buf, AST n) {
204         AST firstChild = n.getFirstChild();
205         // If the node has a first child, recurse into the first child.
206
if ( firstChild != null ) {
207             getPathText( buf, firstChild );
208         }
209         // Append the text of the current node.
210
buf.append( n.getText() );
211         // If there is a second child (RHS), recurse into that child.
212
if ( firstChild != null && firstChild.getNextSibling() != null ) {
213             getPathText( buf, firstChild.getNextSibling() );
214         }
215     }
216
217     public static boolean hasExactlyOneChild(AST n) {
218         return n != null && n.getFirstChild() != null && n.getFirstChild().getNextSibling() == null;
219     }
220
221     public static void appendSibling(AST n, AST s) {
222         while ( n.getNextSibling() != null )
223             n = n.getNextSibling();
224         n.setNextSibling( s );
225     }
226
227     /**
228      * Inserts the child as the first child of the parent, all other children are shifted over to the 'right'.
229      *
230      * @param parent the parent
231      * @param child the new first child
232      */

233     public static void insertChild(AST parent, AST child) {
234         if ( parent.getFirstChild() == null ) {
235             parent.setFirstChild( child );
236         }
237         else {
238             AST n = parent.getFirstChild();
239             parent.setFirstChild( child );
240             child.setNextSibling( n );
241         }
242     }
243
244     /**
245      * Filters nodes out of a tree.
246      */

247     public static interface FilterPredicate {
248         /**
249          * Returns true if the node should be filtered out.
250          *
251          * @param n The node.
252          * @return true if the node should be filtered out, false to keep the node.
253          */

254         boolean exclude(AST n);
255     }
256
257     /**
258      * A predicate that uses inclusion, rather than exclusion semantics.
259      */

260     public abstract static class IncludePredicate implements FilterPredicate {
261         public final boolean exclude(AST node) {
262             return !include( node );
263         }
264
265         public abstract boolean include(AST node);
266     }
267
268     private static ASTArray createAstArray(ASTFactory factory, int size, int parentType, String JavaDoc parentText, AST child1) {
269         ASTArray array = new ASTArray( size );
270         array.add( factory.create( parentType, parentText ) );
271         array.add( child1 );
272         return array;
273     }
274
275     public static List JavaDoc collectChildren(AST root, FilterPredicate predicate) {
276         List JavaDoc children = new ArrayList JavaDoc();
277         collectChildren( children, root, predicate );
278         return children;
279     }
280
281     private static void collectChildren(List JavaDoc children, AST root, FilterPredicate predicate) {
282         for ( AST n = root.getFirstChild(); n != null; n = n.getNextSibling() ) {
283             if ( predicate == null || !predicate.exclude( n ) ) {
284                 children.add( n );
285             }
286             collectChildren( children, n, predicate );
287         }
288     }
289
290 }
291
Popular Tags