private Visitor(DAGNode<Component, Dependency> nd, String id) { currentNode = nd; nodeId = id; if (currentNode == null) { throw new IllegalStateException("dumper not running"); } Component csat = currentNode.getLabel(); assert csat != null; satisfaction = csat.getSatisfaction(); }
@Override protected DAGNode<Component, Dependency> buildRecommenderGraph(DataAccessObject dao) { DAGNode<Component, Dependency> graph = super.buildRecommenderGraph(dao); if (mergePool != null) { logger.debug("deduplicating configuration graph"); synchronized (mergePool) { graph = mergePool.merge(graph); } } return graph; }
/** * Get the placeholder nodes from a graph. * * @param graph The graph. * @return The set of nodes that have placeholder satisfactions. */ public static Set<DAGNode<Component, Dependency>> getPlaceholderNodes(DAGNode<Component,Dependency> graph) { return graph.getReachableNodes() .stream() .filter(n -> n.getLabel().getSatisfaction() instanceof PlaceholderSatisfaction) .collect(Collectors.toSet()); }
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; } } }
logger.debug("graph has {} nodes", graph.getReachableNodes().size()); logger.debug("simulating instantiation"); RecommenderInstantiator instantiator = RecommenderInstantiator.create(graph); DAGNode<Component, Dependency> unshared = instantiator.simulate(); logger.debug("unshared graph has {} nodes", unshared.getReachableNodes().size()); try (BufferedWriter bw = new BufferedWriter(graphvizFile); GraphWriter gw = new GraphWriter(bw)) { GraphDumper dumper = new GraphDumper(graph, unshared.getReachableNodes(), gw); logger.debug("writing root node"); String rid = dumper.setRoot(graph); for (DAGEdge<Component, Dependency> e: graph.getOutgoingEdges()) { DAGNode<Component, Dependency> target = e.getTail(); Component csat = target.getLabel(); if (!satIsNull(csat.getSatisfaction())) { logger.debug("processing node {}", csat.getSatisfaction());
/** * 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); } }
LinkedHashSet<DAGNode<Component, Dependency>> shared = Sets.newLinkedHashSet(); graph.getSortedNodes() .stream() .filter(GraphtUtils::isShareable) for (DAGEdge<Component,Dependency> edge: node.getOutgoingEdges()) { if (!edgeIsTransient(edge)) { boolean es = shared.contains(edge.getTail()); isShared &= es; if (!es) { logger.debug("node {} not shared due to non-transient dependency on {}", node, edge.getTail());
@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 = node.getOutgoingEdges() .stream() .sorted(GraphtUtils.DEP_EDGE_ORDER) .map(DAGEdge::getTail) .collect(Collectors.toList()); description.putList("dependencies", edges, INSTANCE); } }
@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; } } }
GraphDumper(DAGNode<Component, Dependency> g, Set<DAGNode<Component, Dependency>> unshared, GraphWriter gw) { writer = gw; graph = g; unsharedNodes = Sets.newHashSet(unshared); unsharedNodes.retainAll(g.getReachableNodes()); logger.debug("{} shared nodes", unsharedNodes.size()); nodeIds = new HashMap<>(); nodeTargets = new HashMap<>(); edgeQueue = new LinkedList<>(); }
public static boolean edgeIsTransient(DAGEdge<?, Dependency> input) { Desire desire = input.getLabel().getInitialDesire(); return desireIsTransient(desire); }
newGraph = newGraph.replaceNode(node, repl, memory);
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(); } }
@Nonnull @Override public Object apply(@Nullable DAGNode<Component, Dependency> input) { Preconditions.checkNotNull(input, "input node"); try { return instantiate(input); } catch (InjectionException e) { throw new RecommenderBuildException("cannot instantiate " + input.getLabel(), e); } }
/** * Replace shareable nodes in a graph. * * @param replace A replacement function. For each shareable node, this function will * be called; if it returns a node different from its input node, the * new node will be used as a replacement for the old. */ private DAGNode<Component,Dependency> replaceShareableNodes(NodeProcessor replace) throws InjectionException { logger.debug("replacing nodes in graph with {} nodes", graph.getReachableNodes().size()); Set<DAGNode<Component,Dependency>> toReplace = GraphtUtils.getShareableNodes(graph); logger.debug("found {} shared nodes", toReplace.size()); DAGNode<Component, Dependency> result = NodeProcessors.processNodes(graph, toReplace, replace); logger.debug("final graph has {} nodes", result.getReachableNodes().size()); return result; } }
Component label = node.getLabel(); Satisfaction satisfaction = label.getSatisfaction(); if (satisfaction.hasInstance()) { DAGNodeBuilder<Component,Dependency> bld = DAGNode.newBuilder(newLabel); for (DAGEdge<Component, Dependency> edge: node.getOutgoingEdges()) { if (!GraphtUtils.edgeIsTransient(edge)) { bld.addEdge(edge.getTail(), edge.getLabel()); return bld.build();
@Nullable private Optional<Object> getDiskCachedObject(Path file, DAGNode<Component,Dependency> node) { if (file != null && Files.exists(file)) { logger.debug("reading object for {} from cache (key {})", node.getLabel().getSatisfaction(), key); Object obj = readCompressedObject(file, node.getLabel().getSatisfaction().getErasedType()); logger.debug("read object {} from key {}", obj, key); return Optional.fromNullable(obj); } else { return null; } }
@Override protected DAGNode<Component, Dependency> instantiateGraph(DAGNode<Component, Dependency> graph) { if (cache == null) { logger.debug("Building directly without a cache"); return super.instantiateGraph(graph); } else { logger.debug("Instantiating graph with a cache"); try { Set<DAGNode<Component, Dependency>> nodes = GraphtUtils.getShareableNodes(graph); logger.debug("resolving {} nodes", nodes.size()); DAGNode<Component, Dependency> newGraph = NodeProcessors.processNodes(graph, nodes, cache); logger.debug("newGraph went from {} to {} nodes", newGraph.getReachableNodes().size(), newGraph.getReachableNodes().size()); return newGraph; } catch (InjectionException e) { logger.error("Error instantiating recommender nodes with cache", e); throw new RecommenderBuildException("Cached instantiation failed", e); } } } }
/** * Get the component of a particular type, if one is already instantiated. This is useful to extract pre-built * models from serialized recommender engines, for example. * @param type The required component type. * @param <T> The required component type. * @return The component instance, or {@code null} if no instance can be retreived (either because no such * component is configured, or it is not yet instantiated). */ @Nullable public <T> T getComponent(Class<T> type) { DAGNode<Component, Dependency> node = GraphtUtils.findSatisfyingNode(graph, Qualifiers.matchDefault(), type); if (node == null) { return null; } Satisfaction sat = node.getLabel().getSatisfaction(); if (sat instanceof InstanceSatisfaction) { return type.cast(((InstanceSatisfaction) sat).getInstance()); } else { return null; } }
Component label = node.getLabel();