View Javadoc

1   /**
2    * Copyright 2010 The Kuali Foundation Licensed under the
3    * Educational Community License, Version 2.0 (the "License"); you may
4    * not use this file except in compliance with the License. You may
5    * obtain a copy of the License at
6    *
7    * http://www.osedu.org/licenses/ECL-2.0
8    *
9    * Unless required by applicable law or agreed to in writing,
10   * software distributed under the License is distributed on an "AS IS"
11   * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
12   * or implied. See the License for the specific language governing
13   * permissions and limitations under the License.
14   */
15  
16  package org.kuali.student.common.ui.client.widgets.table;
17  
18  import java.util.ArrayList;
19  import java.util.List;
20  
21  import org.kuali.student.common.ui.client.widgets.rules.Token;
22  /**
23   * A generic tree node. 
24   * */
25  public class Node<T> implements Cloneable{
26      /** Children are stored in a list*/
27      List<Node> childrenList = new ArrayList<Node>();
28      /** Parent Node. null if node has no parent*/
29      Node parent;
30      /** User Object*/
31      T userObject;
32      String id;
33      /**
34       * Empty, default constructor
35       * */
36      public Node() {}
37      /**
38       * Constructor of Node which accepts the user object
39       * 
40       * @param obj user object
41       * */
42      public Node(T obj) {
43          userObject = obj;
44      }
45      /**
46       * Get the user object from node
47       * 
48       * @return T returns the user object. User object must by type T 
49       * */
50      public T getUserObject() {
51          return userObject;
52      }
53      /**
54       * Set the user object to this node
55       * 
56       * @param obj obj must be an instanceo of type T
57       * */
58      public void setUserObject(T obj) {
59          userObject = obj;
60      }
61      /**
62       * Set the Parent node for current node
63       * 
64       * @param parent new parent
65       * */
66      public void setParent(Node parent) {
67          this.parent = parent;
68      }
69  
70      /**
71       * Get the parent of current node
72       * @return the parent
73       * */
74      public Node getParent() {
75          return parent;
76      }
77      /**
78       * Add one child and set child's parent to current node
79       * 
80       * @param node new child
81       * 
82       * */
83      public void addNode(Node node) {
84          childrenList.add(node);
85          node.setParent(this);
86      }
87      /** If it has no children, it is a leaf
88       * 
89       * @return boolean is it a leaf
90       * 
91       * */
92      public boolean isLeaf() {
93          return getChildCount() == 0;
94      }
95      /** 
96       * Return the child count 
97       * 
98       * @retrun int the child count
99       * */
100     public int getChildCount() {
101         return childrenList.size();
102     }
103     /** 
104      * Get the child at index
105      *
106      * @param index the index of the child
107      * @return the child
108      * */
109     public Node getChildAt(int index) {
110         return childrenList.get(index);
111     }
112     /** Remove child from parent*/
113     public void removeFromParent() {
114         Node parent = this.getParent();
115         if (parent == null) {
116             return;
117         } else {
118             parent.children().remove(this);
119             this.setParent(null);
120         }
121     }
122     /** Remove child at childIndex
123      * 
124      * @param childIndex child indexs
125      * */
126     public void remove(int childIndex) {
127         Node child = getChildAt(childIndex);
128         childrenList.remove(childIndex);
129         child.setParent(null);
130     }
131     /** Remove child from children list
132      * 
133      * @param child 
134      * */
135     public void remove(Node child) {
136         childrenList.remove(child);
137         child.setParent(null);
138     }
139     public void removeAllChildren(){
140         childrenList.clear();
141     }
142     /** 
143      * Is passed node a child of current node
144      *  
145      *  @param aNode 
146      * 
147      * */
148     public boolean isNodeChild(Node aNode) {
149         boolean retval;
150         if (aNode == null) {
151             retval = false;
152         } else {
153             if (getChildCount() == 0) {
154                 retval = false;
155             } else {
156                 retval = (aNode.getParent() == this);
157             }
158         }
159         return retval;
160     }
161     
162     public int getIndex(Node aChild) {
163         if (!isNodeChild(aChild)) {
164             return -1;
165         }
166         return childrenList.indexOf(aChild); // linear search
167     }
168     /** Is parsed in node a sibling */
169     public boolean isNodeSibling(Node anotherNode) {
170         boolean retval;
171 
172         if (anotherNode == null) {
173             retval = false;
174         } else if (anotherNode == this) {
175             retval = true;
176         } else {
177             Node myParent = getParent();
178             retval = (myParent != null && myParent == anotherNode.getParent());
179 
180             if (retval && !((Node) getParent()).isNodeChild(anotherNode)) {
181                 throw new Error("sibling has different parent");
182             }
183         }
184         return retval;
185     }
186 
187     /**
188      * Returns the total number of leaves that are descendants of this node.
189      * 
190      * @return the number of leaves beneath this node
191      */
192     public int getAllLeafCount() {
193         int count = 0;
194         List<Node<T>> nodeList = getAllChildren();
195         for (Node<T> node : nodeList) {
196             if (node.isLeaf()) {
197                 count++;
198             }
199         }
200 
201         return count;
202     }
203     /** Return all children and grand children*/
204     public List<Node<T>> getAllChildren() {
205         List<Node<T>> nodeList = new ArrayList<Node<T>>();
206         for (Node<T> child : childrenList) {
207             nodeList.add(child);
208             if (!child.isLeaf()) {
209                 nodeList.addAll(child.getAllChildren());
210             }
211         }
212         return nodeList;
213     }
214     /** Get the first leaf among all its children*/
215     public Node<T> getFirstLeafDescendant() {
216         List<Node<T>> list = getAllChildren();
217         for (Node<T> node : list) {
218             if (node.isLeaf()) {
219                 return node;
220             }
221         }
222         return null;
223 
224     }
225     /** Return all non-leaf children 
226      * 
227      * @return List<Node> list of non-leaf children
228      * */
229     public List<Node> getNonLeafChildren() {
230         List<Node> list = new ArrayList<Node>();
231         for (Node n : children()) {
232             if (n.isLeaf() == false) {
233                 list.add(n);
234             }
235         }
236         return list;
237     }
238     
239     public List<Node> getLeafChildren() {
240         List<Node> list = new ArrayList<Node>();
241         for (Node n : children()) {
242             if (n.isLeaf()) {
243                 list.add(n);
244             }
245         }
246         return list;
247     }
248 
249     public List<Node> getSiblings() {
250         Node parent = this.getParent();
251         List<Node> list = new ArrayList<Node>();
252         if (parent != null) {
253 
254             for (int i = 0; i < parent.getChildCount(); i++) {
255                 if (parent.getChildAt(i) != this) {
256                     list.add(parent.getChildAt(i));
257                 }
258             }
259             return list;
260         }
261         return list;
262 
263     }
264 
265     public List<Node> getLeafSiblings() {
266         List<Node> list = new ArrayList<Node>();
267         List<Node> siblings = getSiblings();
268         for (Node n : siblings) {
269             if (n.isLeaf()) {
270                 list.add(n);
271             }
272         }
273 
274         return list;
275     }
276 
277     public List<Node> children() {
278         if (childrenList == null) {
279             return new ArrayList<Node>();
280         } else {
281             return childrenList;
282         }
283     }
284 
285     // root is the level one
286     // results contain current node
287     public List<List<Node>> toLevel() {
288         List<List<Node>> levelList = new ArrayList<List<Node>>();
289 
290         List<Node> level = new ArrayList<Node>();
291         level.add(this);
292         levelList.add(level);
293 
294         int maxDistance = getMaxLevelDistance();
295 
296         List<Node<T>> nodeList = getAllChildren();
297         for (int levelIndex = 1; levelIndex <= maxDistance; levelIndex++) {
298             level = new ArrayList<Node>();
299             for (Node node : nodeList) {
300                 int d = getDistance(node);
301                 if (levelIndex == d) {
302                     level.add(node);
303                 }
304             }
305             levelList.add(level);
306         }
307 
308         return levelList;
309     }
310 
311     public List<Node> deepTrans(Node root) {
312         List<Node> list = new ArrayList<Node>();
313         for (int i = 0; i < root.getChildCount(); i++) {
314             Node n = root.getChildAt(i);
315             if (n.isLeaf()) {
316                 list.add(n);
317             } else {
318                 list.addAll(deepTrans(n));
319             }
320 
321         }
322         list.add(root);
323         return list;
324     }
325 
326     public int getMaxLevelDistance() {
327         List<Node<T>> nodeList = getAllChildren();
328         int maxDistance = 0;
329         for (Node<T> node : nodeList) {
330             int d = getDistance(node);
331             if (maxDistance < d) {
332                 maxDistance = d;
333             }
334         }
335         return maxDistance;
336     }
337 
338     // return the level distance to the current node
339     public int getDistance(Node node) {
340         Node myParent = node.getParent();
341         int level = 1;
342         while (myParent != null && myParent != this) {
343             level++;
344             myParent = myParent.getParent();
345         }
346         return level;
347     }
348 
349     public String toString() {
350         if (userObject == null) {
351             return "no user object";
352         }
353 
354         StringBuilder sb = new StringBuilder(userObject.toString());
355         if (this.getChildCount() == 0) {
356             return sb.toString();
357         }
358         sb.append("{");
359         for (int i = 0; i < this.getChildCount(); i++) {
360             if (this.getChildAt(i).getParent() == this) {
361                 sb.append(this.getChildAt(i).toString() + ",");
362             }
363 
364         }
365         sb.append("}");
366         return sb.toString();
367     }
368 
369     public Node<T> clone() {
370         Node<T> newNode = new Node<T>();
371         newNode.setUserObject(this.getUserObject());
372         if (this.isLeaf() == false) {
373             for (Node<T> n : this.childrenList) {
374                 newNode.addNode(n.clone());
375             }
376         }
377         return newNode;
378     }
379 
380     public static void main(String[] argv) {
381 /*        Node root = new Node();
382         root.setUserObject("root");
383         Node r = new Node();
384         r.setUserObject("r");
385         Node q = new Node();
386         q.setUserObject("q");
387         root.addNode(q);
388         root.addNode(r);
389 
390         Node a = new Node();
391         a.setUserObject("a");
392         q.addNode(a);
393 
394 //        System.out.println(root.deepTrans(root));
395   //      System.out.println(root.deepTrans(root.clone()));
396         
397         Node x = new Node();
398         x.setUserObject("x");
399 
400         Node y = new Node();
401         y.setUserObject("y");
402 
403         Node z = new Node();
404         z.setUserObject("z");
405         
406         x.addNode(y);
407         x.addNode(z);
408         System.out.println(x.deepTrans(x.clone()));
409 */        
410         ExpressionParser p = new ExpressionParser();
411         Node<Token> n = p.parse("(a or b) and c or d and f");
412         System.out.println(n);
413         System.out.println(ExpressionParser.getExpressionString(n));
414     }
415 }