package edu.uw.zookeeper.data; import java.util.Iterator; import java.util.Map; import com.google.common.base.Function; import com.google.common.collect.ImmutableMap; import edu.uw.zookeeper.common.Pair; import edu.uw.zookeeper.common.Reference; import edu.uw.zookeeper.data.NameTrie; import edu.uw.zookeeper.data.ValueNode; import edu.uw.zookeeper.data.SimpleLabelTrie; import edu.uw.zookeeper.data.ZNodeSchema; import edu.uw.zookeeper.data.ZNodeSchema.DeclarationTraversal; import edu.uw.zookeeper.data.ZNodePath; public class SchemaElementLookup extends Pair<NameTrie<ValueNode<ZNodeSchema>>, Map<Object, ValueNode<ZNodeSchema>>> implements Reference<NameTrie<ValueNode<ZNodeSchema>>>, Function<Object, ValueNode<ZNodeSchema>> { public static SchemaElementLookup fromHierarchy(Class<?> root) { NameTrie<ValueNode<ZNodeSchema>> schema = null; Iterator<DeclarationTraversal.Element> itr = ZNodeSchema.fromHierarchy(root); ImmutableMap.Builder<Object, ValueNode<ZNodeSchema>> byElement = ImmutableMap.builder(); while (itr.hasNext()) { DeclarationTraversal.Element next = itr.next(); ZNodeSchema nextSchema = next.getBuilder().build(); ZNodeName name = ZNodeName.fromString(nextSchema.getName()); ZNodePath path = next.getPath().join(name); if (schema == null) { ValueNode<ZNodeSchema> node; if (path.isRoot()) { node = ValueNode.root(nextSchema); } else { node = ValueNode.root(ZNodeSchema.getDefault()); } schema = SimpleLabelTrie.forRoot(node); } ValueNode<ZNodeSchema> node; if (path.isRoot()) { node = schema.root(); } else { ValueNode<ZNodeSchema> parent = schema.get(next.getPath()); node = ValueNode.child(nextSchema, name, parent); parent.put(node.parent().name(), node); } byElement.put(next.getElement(), node); } return new SchemaElementLookup(schema, byElement.build()); } protected SchemaElementLookup(NameTrie<ValueNode<ZNodeSchema>> schema, Map<Object, ValueNode<ZNodeSchema>> byElement) { super(schema, byElement); } @Override public NameTrie<ValueNode<ZNodeSchema>> get() { return first; } @Override public ValueNode<ZNodeSchema> apply(Object type) { return second.get(type); } }