package er.neo4jadaptor.query.neo4j_eval.retrievers; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import org.neo4j.graphdb.PropertyContainer; import er.neo4jadaptor.query.neo4j_eval.Cost; import er.neo4jadaptor.utils.iteration.MultiLevelIterator; /** * Chains retrievers <code>r_0, r_1, ..., r_K</code> to simulate getting value by key-path. * <code>r_0, r_1, ..., r_{K-1}</code> are expected to on retrieval to return {@link PropertyContainer}s * while <code>r_K</code> can return objects of any type. * * @author Jedrzej Sobanski * * @param <N> * @param <V> */ public class ChainedRetriever <N extends PropertyContainer, V> implements Retriever<N, V> { private final List<Retriever<N, ?>> chain = new ArrayList<Retriever<N, ?>>(); @SuppressWarnings("unchecked") public ChainedRetriever( List<Retriever<? extends PropertyContainer, ? extends PropertyContainer>> retrievers, Retriever<? extends PropertyContainer, V> lastRetriever) { // chain.addAll((Collection<? extends Retriever<N, ?>>) retrievers); for (Retriever<? extends PropertyContainer, ? extends PropertyContainer> r : retrievers) { chain.add((Retriever<N, ?>) r); } chain.add((Retriever<N, ?>) lastRetriever); } public Iterator<V> retrieve(N node) { Retriever<N, N> rootRetriever = getRootRetriever(); return new MultiLevelIterator<N, V>(rootRetriever.retrieve(node), chain.size()) { @Override protected Iterator<?> createThisLevelIterator(N node, int resultLevelIndex) { return chain.get(resultLevelIndex).retrieve(node); } }; } @SuppressWarnings("unchecked") private Retriever<N, N> getRootRetriever() { // we assume that the chain contains at least 2 values therefore its first element is a retriever that // ..transforms PropertyContainer (Node/Relationship) into another Node/Relationship return (Retriever<N, N>) chain.get(0); } @Override public String toString() { StringBuilder b = new StringBuilder(); for (Retriever<?, ?> r : chain) { if (b.length() > 0) { b.append(", "); } b.append(r.toString()); } return b.toString(); } public Cost getCost() { return Cost.getHighest(chain); } }