@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; } } }
/** * 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); } }
DAGNode<Component, Dependency> target = e.getTail(); Component csat = target.getLabel(); if (!satIsNull(csat.getSatisfaction())) {
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; } } }
bld.addEdge(edge.getTail(), edge.getLabel());
Desire dep = e.getLabel().getInitialDesire(); Annotation q = dep.getInjectionPoint().getQualifier(); DAGNode<Component, Dependency> targetNode = e.getTail(); if (q != null && q.annotationType().getAnnotation(Parameter.class) != null) { logger.debug("dumping parameter {}", q);
public DAGNode<Component, Dependency> processNode(@Nonnull DAGNode<Component, Dependency> node, @Nonnull DAGNode<Component, Dependency> original) { Component label = node.getLabel(); Satisfaction satisfaction = label.getSatisfaction(); if (satisfaction.hasInstance()) { return node; } Object obj = instantiator.apply(node); Satisfaction instanceSat; if (obj == null) { instanceSat = Satisfactions.nullOfType(satisfaction.getErasedType()); } else { instanceSat = Satisfactions.instance(obj); } Component newLabel = Component.create(instanceSat, label.getCachePolicy()); // build new node with replacement label DAGNodeBuilder<Component,Dependency> bld = DAGNode.newBuilder(newLabel); // retain all non-transient edges for (DAGEdge<Component, Dependency> edge: node.getOutgoingEdges()) { if (!GraphtUtils.edgeIsTransient(edge)) { bld.addEdge(edge.getTail(), edge.getLabel()); } } return bld.build(); } }
@Nullable @Override public DAGNode<V, E> apply(@Nullable DAGEdge<V, E> input) { return input == null ? null : input.getTail(); } };
@Override public boolean apply(@Nullable DAGEdge<V, E> input) { DAGNode<V,E> tail = input == null ? null : input.getTail(); return pred.apply(tail); } };
/** * Get the outgoing edge with the specified target and label, if it exists. * @param target The target node. * @param label The label. * @return The edge from this node to {@code target} with label {@code label}, if it exists, or * {@code null} if no such edge exists. */ public DAGEdge<V,E> getOutgoingEdge(DAGNode<V,E> target, E label) { for (DAGEdge<V,E> edge: outgoingEdges) { if (edge.getTail().equals(target) && edge.getLabel().equals(label)) { return edge; } } return null; }
/** * Helper mode for {@link #getSortedNodes()}, via {@link TopologicalSortSupplier}. This method * does a depth-first traversal of the nodes, adding each to the {@code visited} set when it is * left. This results in {@code visited} being a topological sort. * * @param visited The set of nodes seen so far. */ private void sortVisit(LinkedHashSet<DAGNode<V,E>> visited) { if (!visited.contains(this)) { for (DAGEdge<V,E> nbr: outgoingEdges) { nbr.getTail().sortVisit(visited); } // neighbors won't have added this, or we have an impossible cycle assert !visited.contains(this); visited.add(this); } }
@Override public boolean equals(Object o) { if (o == this) { return true; } else if (o instanceof DAGEdge) { DAGEdge<?,?> oe = (DAGEdge<?,?>) o; return head.equals(oe.getHead()) && tail.equals(oe.getTail()) && label.equals(oe.getLabel()); } else { return false; } }
@Nullable @Override public Instantiator apply(@Nullable Desire input) { for (DAGEdge<Component,Dependency> edge: edges) { if (edge.getLabel().getInitialDesire().equals(input)) { return makeInstantiator(edge.getTail(), backEdges); } } return null; } }
@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; } } };
@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; } } }
/** * Create a new builder initialized to build a copy of the specified node. * @param node The node to copy. * @param <V> The type of node labels. * @param <E> The type of edge labels. * @return A new builder initialized with the labels and edges of {@code node}. */ public static <V,E> DAGNodeBuilder<V,E> copyBuilder(DAGNode<V,E> node) { DAGNodeBuilder<V,E> bld = newBuilder(node.getLabel()); for (DAGEdge<V,E> edge: node.getOutgoingEdges()) { bld.addEdge(edge.getTail(), edge.getLabel()); } return bld; }
@Override @SuppressWarnings("unchecked") public <T> T getInstance(Annotation qualifier, Class<T> type) throws InjectionException { // All Provider cache access, graph resolution, etc. occur // within this exclusive lock so we know everything is thread safe // albeit in a non-optimal way. synchronized(this) { Desire desire = Desires.create(qualifier, type, false); Predicate<Dependency> pred = Dependency.hasInitialDesire(desire); // check if the desire is already in the graph DAGEdge<Component, Dependency> resolved = solver.getGraph().getOutgoingEdgeWithLabel(pred); // The edge is only non-null if instantiate() has been called before, // it may be present in the graph at a deeper node. If that's the case // it will be properly merged after regenerating the graph at the root context. if (resolved == null) { logger.info("Must resolve desire: {}", desire); solver.resolve(desire); resolved = solver.getGraph().getOutgoingEdgeWithLabel(pred); } // Check if the provider for the resolved node is in our cache DAGNode<Component, Dependency> resolvedNode = resolved.getTail(); return type.cast(instantiator.makeInstantiator(resolvedNode, solver.getBackEdges()).instantiate()); } } }
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; } } }
public DAGNode<Component, Dependency> processNode(@Nonnull DAGNode<Component, Dependency> node, @Nonnull DAGNode<Component, Dependency> original) { Component label = node.getLabel(); Satisfaction satisfaction = label.getSatisfaction(); if (satisfaction.hasInstance()) { return node; } Object obj = instantiator.apply(node); Satisfaction instanceSat; if (obj == null) { instanceSat = Satisfactions.nullOfType(satisfaction.getErasedType()); } else { instanceSat = Satisfactions.instance(obj); } Component newLabel = Component.create(instanceSat, label.getCachePolicy()); // build new node with replacement label DAGNodeBuilder<Component,Dependency> bld = DAGNode.newBuilder(newLabel); // retain all non-transient edges for (DAGEdge<Component, Dependency> edge: node.getOutgoingEdges()) { if (!GraphtUtils.edgeIsTransient(edge)) { bld.addEdge(edge.getTail(), edge.getLabel()); } } return bld.build(); } }