alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (AbstractInjectorGrapher.java)

This example Java source code file (AbstractInjectorGrapher.java) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

abstractinjectorgrapher, aliascreator, edgecreator, grapherparameters, ioexception, iterable, list, map, nodecreator, nodeid, override, rootkeysetcreator, set, transitivedependencyvisitor, util

The AbstractInjectorGrapher.java Java example source code

/**
 * Copyright (C) 2011 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.google.inject.grapher;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.inject.Binding;
import com.google.inject.Injector;
import com.google.inject.Key;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Abstract injector grapher that builds the dependency graph but doesn't render it.
 *
 * @author bojand@google.com (Bojan Djordjevic)
 * @since 4.0
 */
public abstract class AbstractInjectorGrapher implements InjectorGrapher {
  private final RootKeySetCreator rootKeySetCreator;
  private final AliasCreator aliasCreator;
  private final NodeCreator nodeCreator;
  private final EdgeCreator edgeCreator;

  /**
   * Parameters used to override default settings of the grapher.
   * @since 4.0
   */
  public static final class GrapherParameters {
    private RootKeySetCreator rootKeySetCreator = new DefaultRootKeySetCreator();
    private AliasCreator aliasCreator = new ProviderAliasCreator();
    private NodeCreator nodeCreator = new DefaultNodeCreator();
    private EdgeCreator edgeCreator = new DefaultEdgeCreator();

    public RootKeySetCreator getRootKeySetCreator() {
      return rootKeySetCreator;
    }

    public GrapherParameters setRootKeySetCreator(RootKeySetCreator rootKeySetCreator) {
      this.rootKeySetCreator = rootKeySetCreator;
      return this;
    }

    public AliasCreator getAliasCreator() {
      return aliasCreator;
    }

    public GrapherParameters setAliasCreator(AliasCreator aliasCreator) {
      this.aliasCreator = aliasCreator;
      return this;
    }

    public NodeCreator getNodeCreator() {
      return nodeCreator;
    }

    public GrapherParameters setNodeCreator(NodeCreator nodeCreator) {
      this.nodeCreator = nodeCreator;
      return this;
    }

    public EdgeCreator getEdgeCreator() {
      return edgeCreator;
    }

    public GrapherParameters setEdgeCreator(EdgeCreator edgeCreator) {
      this.edgeCreator = edgeCreator;
      return this;
    }
  }

  public AbstractInjectorGrapher() {
    this(new GrapherParameters());
  }

  public AbstractInjectorGrapher(GrapherParameters options) {
    this.rootKeySetCreator = options.getRootKeySetCreator();
    this.aliasCreator = options.getAliasCreator();
    this.nodeCreator = options.getNodeCreator();
    this.edgeCreator = options.getEdgeCreator();
  }

  @Override public final void graph(Injector injector) throws IOException {
    graph(injector, rootKeySetCreator.getRootKeys(injector));
  }

  @Override public final void graph(Injector injector, Set<Key root) throws IOException {
    reset();

    Iterable<Binding bindings = getBindings(injector, root);
    Map<NodeId, NodeId> aliases = resolveAliases(aliasCreator.createAliases(bindings));
    createNodes(nodeCreator.getNodes(bindings), aliases);
    createEdges(edgeCreator.getEdges(bindings), aliases);
    postProcess();
  }

  /** Resets the state of the grapher before rendering a new graph. */
  protected abstract void reset() throws IOException;

  /** Adds a new interface node to the graph. */
  protected abstract void newInterfaceNode(InterfaceNode node) throws IOException;

  /** Adds a new implementation node to the graph. */
  protected abstract void newImplementationNode(ImplementationNode node) throws IOException;

  /** Adds a new instance node to the graph. */
  protected abstract void newInstanceNode(InstanceNode node) throws IOException;

  /** Adds a new dependency edge to the graph. */
  protected abstract void newDependencyEdge(DependencyEdge edge) throws IOException;

  /** Adds a new binding edge to the graph. */
  protected abstract void newBindingEdge(BindingEdge edge) throws IOException;

  /** Performs any post processing required after all nodes and edges have been added. */
  protected abstract void postProcess() throws IOException;

  private void createNodes(Iterable<Node> nodes, Map aliases) throws IOException {
    for (Node node : nodes) {
      NodeId originalId = node.getId();
      NodeId resolvedId = resolveAlias(aliases, originalId);
      node = node.copy(resolvedId);

      // Only render nodes that aren't aliased to some other node.
      if (resolvedId.equals(originalId)) {
        if (node instanceof InterfaceNode) {
          newInterfaceNode((InterfaceNode) node);
        } else if (node instanceof ImplementationNode) {
          newImplementationNode((ImplementationNode) node);
        } else {
          newInstanceNode((InstanceNode) node);
        }
      }
    }
  }

  private void createEdges(Iterable<Edge> edges, Map aliases) throws IOException {
    for (Edge edge : edges) {
      edge = edge.copy(resolveAlias(aliases, edge.getFromId()),
          resolveAlias(aliases, edge.getToId()));
      if (!edge.getFromId().equals(edge.getToId())) {
        if (edge instanceof BindingEdge) {
          newBindingEdge((BindingEdge) edge);
        } else {
          newDependencyEdge((DependencyEdge) edge);
        }
      }
    }
  }

  private NodeId resolveAlias(Map<NodeId, NodeId> aliases, NodeId nodeId) {
    return aliases.containsKey(nodeId) ? aliases.get(nodeId) : nodeId;
  }

  /**
   * Transitively resolves aliases. Given aliases (X to Y) and (Y to Z), it will return mappings
   * (X to Z) and (Y to Z).
   */
  private Map<NodeId, NodeId> resolveAliases(Iterable aliases) {
    Map<NodeId, NodeId> resolved = Maps.newHashMap();
    Map<NodeId, Set inverse = Maps.newHashMap();

    for (Alias alias : aliases) {
      NodeId from = alias.getFromId();
      NodeId to = alias.getToId();
      if (resolved.containsKey(to)) {
        to = resolved.get(to);
      }
      resolved.put(from, to);
      if (inverse.get(to) == null) {
        inverse.put(to, Sets.<NodeId>newHashSet());
      }
      inverse.get(to).add(from);

      Set<NodeId> prev = inverse.get(from);
      if (prev != null) {
        for (NodeId id : prev) {
          resolved.remove(id);
          inverse.get(from).remove(id);
          resolved.put(id, to);
          inverse.get(to).add(id);
        }
      }
    }

    return resolved;
  }

  /** Returns the bindings for the root keys and their transitive dependencies. */
  private Iterable<Binding getBindings(Injector injector, Set> root) {
    Set<Key keys = Sets.newHashSet(root);
    Set<Key visitedKeys = Sets.newHashSet();
    List<Binding bindings = Lists.newArrayList();
    TransitiveDependencyVisitor keyVisitor = new TransitiveDependencyVisitor();

    while (!keys.isEmpty()) {
      Iterator<Key iterator = keys.iterator();
      Key<?> key = iterator.next();
      iterator.remove();

      if (!visitedKeys.contains(key)) {
        Binding<?> binding = injector.getBinding(key);
        bindings.add(binding);
        visitedKeys.add(key);
        keys.addAll(binding.acceptTargetVisitor(keyVisitor));
      }
    }
    return bindings;
  }
}

Other Java examples (source code examples)

Here is a short list of links related to this Java AbstractInjectorGrapher.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.