/* * Copyright 2013 Guidewire Software, Inc. */ package gw.util.cache; import gw.util.Predicate; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; public class FqnCacheNode<K> { private final String name; private final FqnCacheNode<K> parent; private K userData; private Map<String, FqnCacheNode<K>> children; public FqnCacheNode( String text, FqnCacheNode<K> parent ) { this.name = text; this.parent = parent; } public final FqnCacheNode<K> getChild( String segment ) { if (children != null) { return children.get(segment); } else { return null; } } public final void clear() { children = null; } public FqnCacheNode<K> getOrCreateChild( String segment ) { if (children == null) { children = new ConcurrentHashMap<String, FqnCacheNode<K>>(2); } FqnCacheNode<K> node = children.get(segment); if (node == null) { node = new FqnCacheNode<K>(segment, this); children.put(segment, node); } return node; } public final void delete() { parent.deleteChild(this); } private void deleteChild(FqnCacheNode<K> child) { if (children != null) { children.remove(child.name); if (children.isEmpty()) { children = null; } } } public final K getUserData() { return userData; } public final void setUserData( K userData ) { this.userData = userData; } public final boolean isLeaf() { return children == null || children.isEmpty(); } public void collectNames( Set<String> names, String s ) { if (children != null) { for (FqnCacheNode<K> child : children.values()) { String path = s.length() == 0 ? child.name : s + child.separator() + child.name; if (child.isLeaf()) { names.add(path); } else { child.collectNames(names, path); } } } } public final Collection<FqnCacheNode<K>> getChildren() { if (children != null) { return children.values(); } else { return Collections.emptySet(); } } public final boolean visitDepthFirst( Predicate<K> visitor ) { if (children != null) { List<FqnCacheNode<K>> copy = new ArrayList<FqnCacheNode<K>>( children.values() ); for( FqnCacheNode<K> child: copy ) { if( !child.visitDepthFirst( visitor ) ) { return false; } } } return visitor.evaluate( getUserData() ); } public final boolean visitNodeDepthFirst( Predicate<FqnCacheNode> visitor ) { if (children != null) { List<FqnCacheNode<K>> copy = new ArrayList<FqnCacheNode<K>>( children.values() ); for( FqnCacheNode<K> child: copy ) { if( !child.visitNodeDepthFirst( visitor ) ) { return false; } } } return visitor.evaluate( this ); } public final boolean visitBreadthFirst( Predicate<K> visitor ) { if( !visitor.evaluate( getUserData() ) ) { return false; } if (children != null) { List<FqnCacheNode<K>> copy = new ArrayList<FqnCacheNode<K>>( children.values() ); for( FqnCacheNode<K> child: copy ) { child.visitBreadthFirst( visitor ); } } return true; } public final boolean visitNodeBreadthFirst( Predicate<FqnCacheNode> visitor ) { if( !visitor.evaluate( this ) ) { return false; } if( children != null ) { List<FqnCacheNode<K>> copy = new ArrayList<FqnCacheNode<K>>( children.values() ); for( FqnCacheNode<K> child: copy ) { child.visitNodeBreadthFirst( visitor ); } } return true; } public final String getName() { return name; } public final String getFqn() { StringBuilder sb = new StringBuilder(); FqnCacheNode<K> node = this; while( node.parent != null ) { String str = node.name + (sb.length() == 0 ? "" : separator()); sb.insert( 0, str); node = node.parent; } return sb.toString(); } private String separator() { char c = name.charAt(0); return c == '[' || c == '<'? "" : "."; } @Override public String toString() { return name; } }