/** * Find a node with a satisfaction for a specified type. Does a breadth-first * search to find the closest matching one. * * @param type The type to look for. * @return A node whose satisfaction is compatible with {@code type}. */ @Nullable public static DAGNode<Component,Dependency> findSatisfyingNode(DAGNode<Component,Dependency> graph, final QualifierMatcher qmatch, final Class<?> type) { Optional<DAGEdge<Component, Dependency>> edge = graph.breadthFirstEdges() .filter(e -> type.isAssignableFrom(e.getTail() .getLabel() .getSatisfaction() .getErasedType())) .filter(e -> qmatch.apply(e.getLabel() .getInitialDesire() .getInjectionPoint() .getQualifier())) .findFirst(); return edge.map(DAGEdge::getTail) .orElse(null); } }
public static <V,E> DAGEdge<V,E> create(DAGNode<V,E> head, DAGNode<V,E> tail, E label) { return new DAGEdge<V,E>(head, tail, label); }
@Nullable @Override public DAGEdge<V, E> apply(@Nullable DAGEdge<V, E> input) { if (input == null) { return null; } DAGNode<V,E> nt, nh; nt = func.apply(input.getTail()); nh = func.apply(input.getHead()); if (nt == null) { nt = input.getTail(); } if (nh == null) { nh = input.getHead(); } if (!nt.equals(input.getTail()) || !nh.equals(input.getHead())) { return create(nh, nt, input.getLabel()); } else { return input; } } };
DAGNode<V,E> tail = edge.getTail(); DAGNode<V,E> transformedTail = tail.transformEdges(function); DAGEdge<V,E> toQuery = edge; if (transformedTail != tail) { toQuery = DAGEdge.create(this, transformedTail, edge.getLabel()); transformedEdge = toQuery; if (edge.equals(transformedEdge)) { builder.addEdge(transformedEdge.getTail(), transformedEdge.getLabel()); builder = newBuilder(label); for (DAGEdge<V,E> done: intact) { builder.addEdge(done.getTail(), done.getLabel()); builder.addEdge(transformedEdge.getTail(), transformedEdge.getLabel());
.transform(DAGEdge.<V,E>extractTail()) .transform(Functions.forMap(mergedMap)) .toSet(); DAGNode<V, E> filtered = mergedMap.get(edge.getTail()); bld.addEdge(filtered, edge.getLabel()); changed |= !filtered.equals(edge.getTail());
assert context.getTailValue().getLeft().equals(root.getLabel().getSatisfaction()); for (DAGEdge<Component, Dependency> edge: root.getOutgoingEdges()) { logger.debug("considering {} for replacement", edge.getTail().getLabel()); Desire desire = edge.getLabel().getDesireChain().getInitialDesire(); DesireChain chain = DesireChain.singleton(desire); Pair<DAGNode<Component, Dependency>, Dependency> repl = null; if (!edge.getLabel().isFixed()) { for (BindingFunction bf: triggerFunctions) { BindingResult result = bf.bind(context, chain); logger.debug("{} is fixed, skipping", edge.getTail().getLabel()); InjectionContext next = context.extend(edge.getTail() .getLabel() .getSatisfaction(), edge.getLabel() .getDesireChain() .getInitialDesire() .getInjectionPoint()); walkGraphForReplacements(edge.getTail(), next, replacements); } else { edge.getTail().getLabel(), repl.getLeft().getLabel()); replacements.put(edge, DAGEdge.create(root, repl.getLeft(), repl.getRight()));
public static boolean edgeIsTransient(DAGEdge<?, Dependency> input) { Desire desire = input.getLabel().getInitialDesire(); return desireIsTransient(desire); }
/** * Get the back edge for a particular node and desire, if one exists. * @return The back edge, or {@code null} if no edge exists. * @see #getBackEdges() */ public synchronized DAGNode<Component, Dependency> getBackEdge(DAGNode<Component, Dependency> parent, Desire desire) { Predicate<DAGEdge<?, Dependency>> pred = DAGEdge.labelMatches(Dependency.hasInitialDesire(desire)); return FluentIterable.from(backEdges.get(parent)) .filter(pred) .first() .transform(DAGEdge.<Component, Dependency>extractTail()) .orNull(); }
/** * Get the nodes that are adjacent to this node (only considering outgoing edges). * @return The set of adjacent nodes. */ public Set<DAGNode<V,E>> getAdjacentNodes() { return FluentIterable.from(outgoingEdges) .transform(DAGEdge.<V, E>extractTail()) .toSet(); }
backEdges.put(parent, DAGEdge.create(parent, merged, result.getRight())); } else {
@Nullable public <T> T tryGetInstance(Class<T> type) throws InjectionException { Desire d = Desires.create(null, type, true); DAGEdge<Component, Dependency> e = graph.getOutgoingEdgeWithLabel(l -> l.hasInitialDesire(d)); if (e != null) { return type.cast(instantiator.instantiate(e.getTail())); } else { DAGNode<Component, Dependency> node = GraphtUtils.findSatisfyingNode(graph, Qualifiers.matchDefault(), type); if (node != null) { return type.cast(instantiator.instantiate(node)); } else { return null; } } }
private void replaceNode(DAGNode<Component,Dependency> old, DAGNode<Component,Dependency> repl) { Map<DAGNode<Component,Dependency>, DAGNode<Component,Dependency>> memory = Maps.newHashMap(); graph = graph.replaceNode(old, repl, memory); // loop over a snapshot of the list, replacing nodes Collection<DAGEdge<Component, Dependency>> oldBackEdges = backEdges.values(); backEdges = HashMultimap.create(); for (DAGEdge<Component,Dependency> edge: oldBackEdges) { DAGNode<Component,Dependency> newHead, newTail; newHead = memory.get(edge.getHead()); if (newHead == null) { newHead = edge.getHead(); } newTail = memory.get(edge.getTail()); if (newTail == null) { newTail = edge.getTail(); } DAGEdge<Component,Dependency> newEdge; if (newHead.equals(edge.getHead()) && newTail.equals(edge.getTail())) { newEdge = edge; } else { newEdge = DAGEdge.create(newHead, newTail, edge.getLabel()); } backEdges.put(newHead, newEdge); } }
private static List<String> extractOrderKey(DAGEdge<Component,Dependency> node) { Desire desire = node.getLabel().getInitialDesire(); InjectionPoint ip = desire.getInjectionPoint(); List<String> key = new ArrayList<>(4); Member member = ip.getMember(); if (member instanceof Constructor) { key.add("0: constructor"); key.add(Integer.toString(ip.getParameterIndex())); } else if (member instanceof Method) { key.add("1: setter"); key.add(member.getName()); key.add(Integer.toString(ip.getParameterIndex())); } else if (member instanceof Field) { key.add("2: field"); key.add(member.getName()); } else if (ip instanceof SimpleInjectionPoint) { key.add("5: simple"); } else { key.add("9: unknown"); key.add(ip.getClass().getName()); } return key; }
@Override public void describe(DAGNode<Component, Dependency> node, DescriptionWriter description) { node.getLabel().getSatisfaction().visit(new LabelDescriptionVisitor(description)); description.putField("cachePolicy", node.getLabel().getCachePolicy().name()); List<DAGNode<Component, Dependency>> edges = Lists.transform(GraphtUtils.DEP_EDGE_ORDER.sortedCopy(node.getOutgoingEdges()), DAGEdge.<Component,Dependency>extractTail()); description.putList("dependencies", edges, INSTANCE); } }
public DAGNode<Component, Dependency> processNode(@Nonnull DAGNode<Component, Dependency> node, @Nonnull DAGNode<Component, Dependency> original) { Component label = node.getLabel(); if (!label.getSatisfaction().hasInstance()) { Satisfaction instanceSat = Satisfactions.nullOfType(label.getSatisfaction().getErasedType()); Component newLbl = Component.create(instanceSat, label.getCachePolicy()); // build new node with replacement label DAGNodeBuilder<Component,Dependency> bld = DAGNode.newBuilder(newLbl); // retain all non-transient edges for (DAGEdge<Component,Dependency> edge: node.getOutgoingEdges()) { if (!GraphtUtils.edgeIsTransient(edge)) { bld.addEdge(edge.getTail(), edge.getLabel()); } } DAGNode<Component,Dependency> repl = bld.build(); logger.debug("simulating instantiation of {}", node); return repl; } else { return node; } } }
DAGNode<Component, Dependency> target = e.getTail(); Component csat = target.getLabel(); if (!satIsNull(csat.getSatisfaction())) {
@Override public boolean apply(@Nullable DAGEdge<?, E> input) { E label = input == null ? null : input.getLabel(); return pred.apply(label); } };
/** * Construct a new DAG node. * @param lbl The label. * @param edges The edges. This takes pairs, not actual edge objects, because the edge objects * need to be constructed within the constructor in order to create the circular * references back to the head nodes properly. */ DAGNode(@Nonnull V lbl, Iterable<Pair<DAGNode<V,E>,E>> edges) { label = lbl; ImmutableSet.Builder<DAGEdge<V,E>> bld = ImmutableSet.builder(); for (Pair<DAGNode<V,E>,E> pair: edges) { DAGEdge<V,E> edge = new DAGEdge<V, E>(this, pair.getLeft(), pair.getRight()); bld.add(edge); } outgoingEdges = bld.build(); initializeCaches(); }