TypeHierarchyBrowser { public void visit(final Class<?> startType, final Mode mode, final Visitor<Class<?>> callback, final int maxDepth) { if (maxDepth <= 0) return; List<Class<?>> currentTypes = new LinkedList<Class<?>>(), nextTypes = new LinkedList<Class<?>>(); currentTypes.add(startType); for (int depth = 1; depth <= maxDepth && !currentTypes.isEmpty(); depth++) { final boolean shouldDescend = depth + 1 <= maxDepth; for (final Class<?> type : currentTypes) { final Iterable<? extends Class<?>> superTypes = mode.getSuperTypes(type); for (final Class<?> superType : superTypes) { if (mode.shouldInvokeCallback(superType)) if (!callback.visited(superType, depth)) return; if (shouldDescend) nextTypes.add(superType); } } currentTypes.clear(); final List<Class<?>> swap = currentTypes; currentTypes = mode.prepare(nextTypes); nextTypes = swap; } }  void visit(final Class<?> startType, final Mode mode, final Visitor<Class<?>> callback, final int maxDepth); void visit(final Class<?> startType, final Mode mode, final Visitor<Class<?>> callback); static TypeHierarchyBrowser INSTANCE; }
@Test public void test() { final List<SimpleEntry<Class<?>, Integer>> actual = new ArrayList<SimpleEntry<Class<?>, Integer>>(); TypeHierarchyBrowser.INSTANCE.visit(this.startClass, this.mode, new Visitor<Class<?>>() { @Override public boolean visited(final Class<?> node, final int distance) { actual.add(new SimpleEntry<Class<?>, Integer>(node, distance)); return TypeHierarchyBrowserTest.this.visitor.visited(node, distance); } }, this.maxDepth); if (this.mode == Mode.ALL) Assert.assertEquals(String.format("Failed to browser %s (%s) to %d", this.startClass, this.mode, this.maxDepth), new HashSet<Map.Entry<Class<?>, Integer>>(this.expectedClasses), new HashSet<Map.Entry<Class<?>, Integer>>(actual)); else Assert.assertEquals(String.format("Failed to browser %s (%s) to %d", this.startClass, this.mode, this.maxDepth), this.expectedClasses, actual); }