1 13 14 package mondrian.olap; 15 import java.io.PrintWriter ; 16 import java.util.Enumeration ; 17 import java.util.Stack ; 18 19 35 public class Walker implements Enumeration { 36 42 private final Stack stack; 43 private Frame currentFrame; 44 private Object nextNode; 45 46 private class Frame { 47 Frame(Frame parent, Object node) { 48 this.parent = parent; 49 this.node = node; 50 this.children = getChildren(node); 51 this.childIndex = -1; } 53 final Frame parent; 54 final Object node; 55 final Object [] children; 56 int childIndex; 57 } 58 59 public Walker(Walkable root) 60 { 61 stack = new Stack (); 62 currentFrame = null; 63 visit(null, root); 64 } 65 66 private void moveToNext() 67 { 68 if (stack.empty()) 69 return; 70 71 currentFrame = (Frame) stack.peek(); 72 73 do { 75 Frame frame = (Frame) stack.peek(); 76 if (frame.children != null && 77 ++frame.childIndex < frame.children.length) { 78 visit(frame, frame.children[frame.childIndex]); 80 return; 81 } 82 stack.pop(); 83 } while (!stack.empty()); 84 nextNode = null; 85 } 86 87 private void visit(Frame parent, Object node) 88 { 89 nextNode = node; 90 stack.addElement(new Frame(parent, node)); 91 } 92 93 public boolean hasMoreElements() 94 { 95 return nextNode != null; 96 } 97 98 public Object nextElement() 99 { 100 moveToNext(); 101 return currentFrame.node; 102 } 103 104 107 public void prune() 108 { 109 if( currentFrame.children != null ){ 110 currentFrame.childIndex = currentFrame.children.length; 111 } 112 if( this.hasMoreElements() ){ 115 Object nextFrameParentNode = ((Frame )stack.peek()).parent.node; 116 if( nextFrameParentNode != currentFrame.node ) 117 return; 118 stack.pop(); 120 if( currentFrame.parent != null) 121 currentFrame = currentFrame.parent; 122 nextElement(); 123 } 124 } 125 126 public void pruneSiblings() 127 { 128 prune(); 129 currentFrame = currentFrame.parent; 130 if( currentFrame != null ){ 131 prune(); 132 } 133 } 134 135 136 138 public Object currentElement() 139 { 140 return currentFrame.node; 141 } 142 143 145 public int level() 146 { 147 int i = 0; 148 for (Frame f = currentFrame; f != null; f = f.parent) 149 i++; 150 return i; 151 } 152 153 public final Object getParent() 154 { 155 return getAncestor(1); 156 } 157 158 public final Object getAncestor(int iDepth) 159 { 160 Frame f = getAncestorFrame(iDepth); 161 return f == null ? null : f.node; 162 } 163 164 165 private Frame getAncestorFrame(int iDepth) 166 { 167 for (Frame f = currentFrame; f != null; f = f.parent) 168 if (iDepth-- == 0) 169 return f; 170 return null; 171 } 172 173 175 public int getOrdinal() 176 { 177 return currentFrame.parent == null ? 0 : 180 arrayFind(currentFrame.parent.children, currentFrame.node); 181 } 182 183 185 public int getAncestorOrdinal(int iDepth) 186 { 187 Frame f = getAncestorFrame(iDepth); 188 return f == null ? -1 : 189 f.parent == null ? 0 : 190 arrayFind(f.parent.children, f.node); 191 } 192 193 195 public Object [] getChildren(Object node) 196 { 197 if (node instanceof Walkable) 198 return ((Walkable) node).getChildren(); 199 else 200 return null; 201 } 202 203 private static int arrayFind(Object [] array, Object o) 204 { 205 for (int i = 0; i < array.length; i++) 206 if (array[i] == o) 207 return i; 208 return -1; 209 } 210 211 private static class Region implements Walkable 212 { 213 String name; 214 Region[] children; 215 216 Region(String name, Region[] children) 217 { 218 this.name = name; 219 this.children = children; 220 } 221 222 public Object [] getChildren() { return children; } 223 224 public static void walkUntil(Walker walker, String name) { 225 while (walker.hasMoreElements()) { 226 Region region = (Region) walker.nextElement(); 227 if (region.name.equals(name)) { 228 break; 229 } 230 } 231 } 232 }; 233 234 public static void main(String [] args) 235 { 236 PrintWriter pw = new PrintWriter (System.out); 237 Region usa = new Region( 238 "USA", new Region[] { 239 new Region("CA", new Region[] { 240 new Region("San Francisco", new Region[]{ 241 new Region("WesternAddition", new Region[]{ new Region("Haight", null)}), 242 new Region("Soma", null) 243 }), 244 new Region("Los Angeles", null)}), 245 new Region("WA", new Region[] { 246 new Region("Seattle", null), 247 new Region("Tacoma", null)})}); 248 249 Walker walker = new Walker(usa); 250 if (false) { 251 while (walker.hasMoreElements()) { 252 Region region = (Region) walker.nextElement(); 253 pw.println(region.name); 254 pw.flush(); 255 } 256 } 257 258 Region.walkUntil(walker, "CA"); 259 walker.prune(); 260 Region region = (Region) walker.nextElement(); pw.println(region.name); 262 pw.flush(); 263 264 walker = new Walker(usa); 265 Region.walkUntil(walker, "USA"); 266 walker.prune(); 267 region = (Region) walker.nextElement(); if( region == null ) 269 pw.println("null"); 270 pw.flush(); 271 272 walker = new Walker(usa); 273 Region.walkUntil(walker, "Los Angeles"); 274 walker.prune(); 275 region = (Region) walker.nextElement(); pw.println(region.name); 277 pw.flush(); 278 279 walker = new Walker(usa); 280 Region.walkUntil(walker, "Haight"); 281 walker.prune(); 282 region = (Region) walker.nextElement(); pw.println(region.name); 284 pw.flush(); 285 286 walker = new Walker(usa); 287 Region.walkUntil(walker, "Soma"); 288 walker.prune(); 289 region = (Region) walker.nextElement(); pw.println(region.name); 291 pw.flush(); 292 293 walker = new Walker(usa); 294 Region.walkUntil(walker, "CA"); 295 walker.pruneSiblings(); 296 region = (Region) walker.nextElement(); if (region == null ){ 298 pw.println("null"); 299 pw.flush(); 300 } 301 302 walker = new Walker(usa); 303 Region.walkUntil(walker, "Soma"); 304 walker.pruneSiblings(); 305 region = (Region) walker.nextElement(); if (region == null ){ 307 pw.println("null"); 308 pw.flush(); 309 } 310 } 311 } 312 313 314 | Popular Tags |