Package com.google.gwt.inject.rebind.resolution

Source Code of com.google.gwt.inject.rebind.resolution.BindingInstaller$Factory

/*
* Copyright 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.gwt.inject.rebind.resolution;

import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.inject.rebind.GinjectorBindings;
import com.google.gwt.inject.rebind.binding.Binding;
import com.google.gwt.inject.rebind.binding.BindingFactory;
import com.google.gwt.inject.rebind.binding.Context;
import com.google.gwt.inject.rebind.binding.Dependency;
import com.google.gwt.inject.rebind.binding.ParentBinding;
import com.google.gwt.inject.rebind.resolution.DependencyExplorer.DependencyExplorerOutput;
import com.google.gwt.inject.rebind.util.PrettyPrinter;
import com.google.inject.Inject;
import com.google.inject.Key;
import com.google.inject.assistedinject.Assisted;

import java.util.Map;

/**
* Adds all of the positioned implicit bindings necessary to satisfy the unresolved bindings in the
* origin injector to the {@link GinjectorBindings} where we've placed each key.  It installs the
* following bindings using {@link GinjectorBindings#addBinding(Key, Binding)}:
* <ul>
* <li>Each implicit binding created for a key is installed in the Ginjector that
* {@link BindingPositioner} decided it should be placed in.
* </li>
* <li>For each implicit binding added to a Ginjector G, we add {@link ParentBinding}s to G
* to make sure it can access any dependencies for the implicit binding.
* </li>
* <li>For all the dependencies in the origin, we add  {@link ParentBinding}s for the targets that
* are not available at the origin (eg, installed higher in the Ginjector hierarchy).
* </li>
* </ul>
*
* <p>See {@link BindingResolver} for how this fits into the overall algorithm for resolution.
*/
class BindingInstaller {
 
  private final BindingPositioner positions;
  private final BindingFactory bindingFactory;
  private final TreeLogger logger;

  @Inject
  public BindingInstaller(
      BindingPositioner.Factory positionsFactory,
      BindingFactory bindingFactory,
      @Assisted TreeLogger logger) {
    this.positions = positionsFactory.create(logger);
    this.bindingFactory = bindingFactory;
    this.logger = logger;
  }
 
  /**
   * Installs all of the implicit bindings as described {@link BindingInstaller above}.
   *
   * @param output {@link DependencyExplorerOutput} with information about the unresolved bindings
   *     for the current ginjector.
   */
  public void installBindings(DependencyExplorerOutput output) {
    positions.position(output);
   
    // Install each implicit binding in the correct position
    for (Map.Entry<Key<?>, Binding> entry : output.getImplicitBindings()) {
      installBinding(output.getGraph(), entry.getKey(), entry.getValue());
    }
   
    // Make sure that each of the dependencies needed directly from the origin are available
    GinjectorBindings origin = output.getGraph().getOrigin();
    inheritBindingsForDeps(origin, origin.getDependencies());
  }
 
  /**
   * Adds the given implicit binding in the graph to the injector hierarchy in the position
   * specified by the {@link BindingPositioner}. Also ensures that the dependencies of the implicit
   * binding are available at the chosen position.
   */
  private void installBinding(DependencyGraph graph, Key<?> key, Binding binding) {
    // Figure out where we're putting the implicit entry
    GinjectorBindings implicitEntryPosition = positions.getInstallPosition(key);
   
    // Ensure that the dependencies are available to the ginjector
    inheritBindingsForDeps(implicitEntryPosition, graph.getDependenciesOf(key));
   
    // Now add the implicit binding to the ginjector
    implicitEntryPosition.addBinding(key, binding);
  }
 
  /**
   * @param ginjector Ginjector that needs the dependencies
   * @param deps dependencies that are needed
   */
  private void inheritBindingsForDeps(GinjectorBindings ginjector, Iterable<Dependency> deps) {
    for (Dependency dep : deps) {
      ensureAccessible(dep.getTarget(), positions.getInstallPosition(dep.getTarget()), ginjector);
    }
  }
 
  /**
   * Ensure that the binding for key which exists in the parent Ginjector is also available to the
   * child Ginjector.
   */
  private void ensureAccessible(Key<?> key, GinjectorBindings parent, GinjectorBindings child) {
    // Parent will be null if it is was an optional dependency and it couldn't be created.
    if (parent != null && !child.equals(parent) && !child.isBound(key)) {
      PrettyPrinter.log(logger, TreeLogger.DEBUG,
          "In %s: inheriting binding for %s from the parent %s", child, key, parent);
      Context context = Context.format("Inheriting %s from parent", key);

      // We don't strictly need all the extra checks in addBinding, but it can't hurt.  We know, for
      // example, that there will not be any unresolved bindings for this key.
      child.addBinding(key, bindingFactory.getParentBinding(key, parent, context));
    }
  }

  interface Factory {
    BindingInstaller create(TreeLogger logger);
  }
}
TOP

Related Classes of com.google.gwt.inject.rebind.resolution.BindingInstaller$Factory

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.