/*
* 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.ParentBinding;
import com.google.gwt.inject.rebind.resolution.DependencyExplorer.DependencyExplorerOutput;
import com.google.gwt.inject.rebind.resolution.UnresolvedBindingValidator.InvalidKeys;
import com.google.gwt.inject.rebind.util.PrettyPrinter;
import com.google.inject.Inject;
import com.google.inject.Provider;
/**
* Drives the top level Binding Resolution algorithm. This performs the following steps:
* <ol>
* <li>Create a dependency graph representing all of the unresolved keys (required and optional)
* for a Ginjector in the hierarchy. This graph will have internal nodes for all of the implicit
* bindings that need to be created, and leaf nodes (no outgoing edges) for all bindings that are
* already available to the Ginjector. See {@link DependencyExplorer}.
* </li>
* <li>Verify that there are no errors in the dependency graph. Errors are detected and reported as
* described in {@link UnresolvedBindingValidator} which also makes use of {@link EagerCycleFinder}.
* </li>
* <li>Determine which injector each of the implicit bindings should be placed in, according to the
* constraints described in {@link BindingPositioner}.
* </li>
* <li>Install each implicit binding, and any {@link ParentBinding}s necessary to inherit
* dependencies from higher in the hierarchy, to the Ginjectors. See {@link BindingInstaller}.
* </ol>
*/
public class BindingResolver {
private final DependencyExplorer.Factory explorerFactory;
private final UnresolvedBindingValidator.Factory validatorFactory;
private final BindingInstaller.Factory installerFactory;
private final TreeLogger logger;
@Inject
public BindingResolver(DependencyExplorer.Factory explorerFactory,
UnresolvedBindingValidator.Factory validatorFactory,
BindingInstaller.Factory installerFactory,
TreeLogger logger) {
this.explorerFactory = explorerFactory;
this.validatorFactory = validatorFactory;
this.installerFactory = installerFactory;
this.logger = logger;
}
public void resolveBindings(GinjectorBindings origin) {
TreeLogger branch = logger.branch(TreeLogger.DEBUG, PrettyPrinter.format(
"Resolving bindings for %s", origin));
// Use providers so that the instances are cleaned up after this method. This ensures that even
// though BindingResolver may be held on to (eg, {@link GinjectorBindings}, we won't leak
// memory used for temporary storage during resolution.
DependencyExplorerOutput output = explorerFactory.create(branch).explore(origin);
UnresolvedBindingValidator validator = validatorFactory.create(branch);
InvalidKeys invalidKeys = validator.getInvalidKeys(output);
if (validator.validate(output, invalidKeys)) {
validator.pruneInvalidOptional(output, invalidKeys);
installerFactory.create(branch).installBindings(output);
}
}
}