1 5 package com.tc.object.walker; 6 7 import java.util.Collection ; 8 import java.util.IdentityHashMap ; 9 import java.util.LinkedList ; 10 import java.util.Map ; 11 12 public class ObjectGraphWalker { 13 14 private final VisitedSet visited; 15 private final LinkedList backtrack = new LinkedList (); 16 private final Visitor visitor; 17 private final MemberValue root; 18 private int currentDepth = 0; 19 private final WalkTest walkTest; 20 21 public ObjectGraphWalker(Object root, WalkTest walkTest, Visitor visitor) { 22 if (root == null) { throw new IllegalArgumentException ("refusing to traverse null"); } 23 if (walkTest == null) { throw new NullPointerException ("null walk test"); } 24 if (visitor == null) { throw new NullPointerException ("null visitor"); } 25 this.root = MemberValue.rootValue(root); 26 this.visitor = visitor; 27 this.visited = new VisitedSet(this.root); 28 this.walkTest = walkTest; 29 } 30 31 public void walk() { 32 visitor.visitRootObject(root); 33 currentDepth++; 34 35 if (!walkTest.shouldTraverse(root)) { return; } 36 37 backtrack.addFirst(makeNode(root.getValueObject())); 38 39 while (backtrack.size() > 0) { 40 Node current = (Node) backtrack.getFirst(); 41 visit(current); 42 } 43 } 44 45 private Node makeNode(Object o) { 46 if (o == null) { throw new NullPointerException (); } 47 48 if (o.getClass().isArray()) { 49 return new ArrayNode(o); 50 } else if (o instanceof Collection ) { 51 return new CollectionNode((Collection ) o); 52 } else if (o instanceof Map ) { 53 return new MapNode((Map ) o); 54 } else if (o instanceof MapEntry) { 55 return new MapEntryNode((MapEntry) o); 56 } else { 57 return new PlainNode(o); 58 } 59 } 60 61 private void visit(Node node) { 62 while (!node.done()) { 63 MemberValue value = node.next(); 64 65 if (value instanceof MapEntry) { 66 MapEntry entry = (MapEntry) value; 67 visitor.visitMapEntry(entry.getIndex(), currentDepth); 68 currentDepth++; 69 backtrack.addFirst(makeNode(entry)); 70 return; 71 } 72 73 Object o = value.getValueObject(); 74 75 boolean shouldTraverse = walkTest.shouldTraverse(value); 76 77 if (shouldTraverse) { 78 visited.visit(value); 79 } 80 81 visitor.visitValue(value, currentDepth); 82 83 if (o != null && shouldTraverse && !value.isRepeated()) { 84 Node next = makeNode(o); 85 currentDepth++; 86 backtrack.addFirst(next); 87 return; 88 } 89 } 90 91 currentDepth--; 92 backtrack.removeFirst(); 93 } 94 95 private static class VisitedSet { 96 private final IdentityHashMap visited = new IdentityHashMap (); 97 98 VisitedSet(MemberValue root) { 99 visit(root); 100 } 101 102 void visit(MemberValue value) { 103 Object o = value.getValueObject(); 104 105 Integer id = (Integer ) visited.get(o); 106 if (id == null) { 107 id = new Integer (visited.size()); 108 visited.put(o, id); 109 } else { 110 value.setRepeated(true); 111 } 112 113 value.setId(id.intValue()); 114 } 115 } 116 117 } 118 | Popular Tags |