1b71955639ab617e0a4115b1439c8b9982227a018sberlin/** 2b71955639ab617e0a4115b1439c8b9982227a018sberlin * Copyright (C) 2011 Google Inc. 3b71955639ab617e0a4115b1439c8b9982227a018sberlin * 4b71955639ab617e0a4115b1439c8b9982227a018sberlin * Licensed under the Apache License, Version 2.0 (the "License"); 5b71955639ab617e0a4115b1439c8b9982227a018sberlin * you may not use this file except in compliance with the License. 6b71955639ab617e0a4115b1439c8b9982227a018sberlin * You may obtain a copy of the License at 7b71955639ab617e0a4115b1439c8b9982227a018sberlin * 8b71955639ab617e0a4115b1439c8b9982227a018sberlin * http://www.apache.org/licenses/LICENSE-2.0 9b71955639ab617e0a4115b1439c8b9982227a018sberlin * 10b71955639ab617e0a4115b1439c8b9982227a018sberlin * Unless required by applicable law or agreed to in writing, software 11b71955639ab617e0a4115b1439c8b9982227a018sberlin * distributed under the License is distributed on an "AS IS" BASIS, 12b71955639ab617e0a4115b1439c8b9982227a018sberlin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b71955639ab617e0a4115b1439c8b9982227a018sberlin * See the License for the specific language governing permissions and 14b71955639ab617e0a4115b1439c8b9982227a018sberlin * limitations under the License. 15b71955639ab617e0a4115b1439c8b9982227a018sberlin */ 16b71955639ab617e0a4115b1439c8b9982227a018sberlin 17b71955639ab617e0a4115b1439c8b9982227a018sberlinpackage com.google.inject.grapher; 18b71955639ab617e0a4115b1439c8b9982227a018sberlin 19b71955639ab617e0a4115b1439c8b9982227a018sberlinimport com.google.common.collect.ImmutableList; 20b71955639ab617e0a4115b1439c8b9982227a018sberlinimport com.google.common.collect.Lists; 21b71955639ab617e0a4115b1439c8b9982227a018sberlinimport com.google.inject.Binding; 22b71955639ab617e0a4115b1439c8b9982227a018sberlinimport com.google.inject.spi.ConstructorBinding; 23b71955639ab617e0a4115b1439c8b9982227a018sberlinimport com.google.inject.spi.ConvertedConstantBinding; 24b71955639ab617e0a4115b1439c8b9982227a018sberlinimport com.google.inject.spi.DefaultBindingTargetVisitor; 25b71955639ab617e0a4115b1439c8b9982227a018sberlinimport com.google.inject.spi.Dependency; 26b71955639ab617e0a4115b1439c8b9982227a018sberlinimport com.google.inject.spi.HasDependencies; 27b71955639ab617e0a4115b1439c8b9982227a018sberlinimport com.google.inject.spi.InstanceBinding; 28b71955639ab617e0a4115b1439c8b9982227a018sberlinimport com.google.inject.spi.LinkedKeyBinding; 29b71955639ab617e0a4115b1439c8b9982227a018sberlinimport com.google.inject.spi.ProviderBinding; 30b71955639ab617e0a4115b1439c8b9982227a018sberlinimport com.google.inject.spi.ProviderInstanceBinding; 31b71955639ab617e0a4115b1439c8b9982227a018sberlinimport com.google.inject.spi.ProviderKeyBinding; 32b71955639ab617e0a4115b1439c8b9982227a018sberlinimport java.util.Collection; 33b71955639ab617e0a4115b1439c8b9982227a018sberlinimport java.util.List; 34b71955639ab617e0a4115b1439c8b9982227a018sberlin 35b71955639ab617e0a4115b1439c8b9982227a018sberlin/** 36b71955639ab617e0a4115b1439c8b9982227a018sberlin * Default edge creator. 37b71955639ab617e0a4115b1439c8b9982227a018sberlin * 38b71955639ab617e0a4115b1439c8b9982227a018sberlin * @author bojand@google.com (Bojan Djordjevic) 39b71955639ab617e0a4115b1439c8b9982227a018sberlin */ 40b71955639ab617e0a4115b1439c8b9982227a018sberlinfinal class DefaultEdgeCreator implements EdgeCreator { 41b71955639ab617e0a4115b1439c8b9982227a018sberlin 42b71955639ab617e0a4115b1439c8b9982227a018sberlin @Override public Iterable<Edge> getEdges(Iterable<Binding<?>> bindings) { 43b71955639ab617e0a4115b1439c8b9982227a018sberlin List<Edge> edges = Lists.newArrayList(); 44b71955639ab617e0a4115b1439c8b9982227a018sberlin EdgeVisitor visitor = new EdgeVisitor(); 45b71955639ab617e0a4115b1439c8b9982227a018sberlin for (Binding<?> binding : bindings) { 46b71955639ab617e0a4115b1439c8b9982227a018sberlin edges.addAll(binding.acceptTargetVisitor(visitor)); 47b71955639ab617e0a4115b1439c8b9982227a018sberlin } 48b71955639ab617e0a4115b1439c8b9982227a018sberlin return edges; 49b71955639ab617e0a4115b1439c8b9982227a018sberlin } 50b71955639ab617e0a4115b1439c8b9982227a018sberlin 51b71955639ab617e0a4115b1439c8b9982227a018sberlin /** 52b71955639ab617e0a4115b1439c8b9982227a018sberlin * {@link BindingTargetVisitor} that adds edges to the graph based on the visited {@link Binding}. 53b71955639ab617e0a4115b1439c8b9982227a018sberlin */ 54b71955639ab617e0a4115b1439c8b9982227a018sberlin private static final class EdgeVisitor 55b71955639ab617e0a4115b1439c8b9982227a018sberlin extends DefaultBindingTargetVisitor<Object, Collection<Edge>> { 56b71955639ab617e0a4115b1439c8b9982227a018sberlin 57b71955639ab617e0a4115b1439c8b9982227a018sberlin /** 58b71955639ab617e0a4115b1439c8b9982227a018sberlin * Returns a dependency edge for each {@link Dependency} in the binding. These will be from the 59b71955639ab617e0a4115b1439c8b9982227a018sberlin * given node ID to the {@link Dependency}'s {@link Key}. 60b71955639ab617e0a4115b1439c8b9982227a018sberlin * 61b71955639ab617e0a4115b1439c8b9982227a018sberlin * @param nodeId ID of the node that should be the tail of the dependency 62b71955639ab617e0a4115b1439c8b9982227a018sberlin * edges 63b71955639ab617e0a4115b1439c8b9982227a018sberlin * @param binding {@link Binding} for the dependencies 64b71955639ab617e0a4115b1439c8b9982227a018sberlin */ 65b71955639ab617e0a4115b1439c8b9982227a018sberlin private <T extends Binding<?> & HasDependencies> Collection<Edge> newDependencyEdges( 66b71955639ab617e0a4115b1439c8b9982227a018sberlin NodeId nodeId, T binding) { 67b71955639ab617e0a4115b1439c8b9982227a018sberlin ImmutableList.Builder<Edge> builder = ImmutableList.builder(); 68b71955639ab617e0a4115b1439c8b9982227a018sberlin for (Dependency<?> dependency : binding.getDependencies()) { 69b71955639ab617e0a4115b1439c8b9982227a018sberlin NodeId to = NodeId.newTypeId(dependency.getKey()); 70b71955639ab617e0a4115b1439c8b9982227a018sberlin builder.add(new DependencyEdge(nodeId, to, dependency.getInjectionPoint())); 71b71955639ab617e0a4115b1439c8b9982227a018sberlin } 72b71955639ab617e0a4115b1439c8b9982227a018sberlin return builder.build(); 73b71955639ab617e0a4115b1439c8b9982227a018sberlin } 74b71955639ab617e0a4115b1439c8b9982227a018sberlin 75b71955639ab617e0a4115b1439c8b9982227a018sberlin /** 76b71955639ab617e0a4115b1439c8b9982227a018sberlin * Visitor for {@link ConstructorBinding}s. These are for classes that Guice will instantiate to 77b71955639ab617e0a4115b1439c8b9982227a018sberlin * satisfy injection requests. 78b71955639ab617e0a4115b1439c8b9982227a018sberlin */ 79b71955639ab617e0a4115b1439c8b9982227a018sberlin @Override public Collection<Edge> visit(ConstructorBinding<?> binding) { 80b71955639ab617e0a4115b1439c8b9982227a018sberlin return newDependencyEdges(NodeId.newTypeId(binding.getKey()), binding); 81b71955639ab617e0a4115b1439c8b9982227a018sberlin } 82b71955639ab617e0a4115b1439c8b9982227a018sberlin 83b71955639ab617e0a4115b1439c8b9982227a018sberlin /** 84b71955639ab617e0a4115b1439c8b9982227a018sberlin * Visitor for {@link ConvertedConstantBinding}. The {@link Binding}'s {@link Key} will be of an 85b71955639ab617e0a4115b1439c8b9982227a018sberlin * annotated primitive type, and the value of {@link ConvertedConstantBinding#getSourceKey()} 86b71955639ab617e0a4115b1439c8b9982227a018sberlin * will be of a {@link String} with the same annotation. 87b71955639ab617e0a4115b1439c8b9982227a018sberlin */ 88b71955639ab617e0a4115b1439c8b9982227a018sberlin @Override public Collection<Edge> visit(ConvertedConstantBinding<?> binding) { 89b71955639ab617e0a4115b1439c8b9982227a018sberlin return ImmutableList.<Edge>of(new BindingEdge(NodeId.newTypeId(binding.getKey()), 90b71955639ab617e0a4115b1439c8b9982227a018sberlin NodeId.newTypeId(binding.getSourceKey()), 91b71955639ab617e0a4115b1439c8b9982227a018sberlin BindingEdge.Type.CONVERTED_CONSTANT)); 92b71955639ab617e0a4115b1439c8b9982227a018sberlin } 93b71955639ab617e0a4115b1439c8b9982227a018sberlin 94b71955639ab617e0a4115b1439c8b9982227a018sberlin /** 95b71955639ab617e0a4115b1439c8b9982227a018sberlin * Visitor for {@link InstanceBinding}. We then render any dependency edgess that the instance 96b71955639ab617e0a4115b1439c8b9982227a018sberlin * may have, which come either from {@link InjectionPoint}s (method and field) on the instance, 97b71955639ab617e0a4115b1439c8b9982227a018sberlin * or on {@link Dependency}s the instance declares through the {@link HasDependencies} 98b71955639ab617e0a4115b1439c8b9982227a018sberlin * interface. 99b71955639ab617e0a4115b1439c8b9982227a018sberlin */ 100b71955639ab617e0a4115b1439c8b9982227a018sberlin @Override public Collection<Edge> visit(InstanceBinding<?> binding) { 101b71955639ab617e0a4115b1439c8b9982227a018sberlin return new ImmutableList.Builder<Edge>() 102b71955639ab617e0a4115b1439c8b9982227a018sberlin .add(new BindingEdge(NodeId.newTypeId(binding.getKey()), 103b71955639ab617e0a4115b1439c8b9982227a018sberlin NodeId.newInstanceId(binding.getKey()), 104b71955639ab617e0a4115b1439c8b9982227a018sberlin BindingEdge.Type.NORMAL)) 105b71955639ab617e0a4115b1439c8b9982227a018sberlin .addAll(newDependencyEdges(NodeId.newInstanceId(binding.getKey()), binding)) 106b71955639ab617e0a4115b1439c8b9982227a018sberlin .build(); 107b71955639ab617e0a4115b1439c8b9982227a018sberlin } 108b71955639ab617e0a4115b1439c8b9982227a018sberlin 109b71955639ab617e0a4115b1439c8b9982227a018sberlin /** 110b71955639ab617e0a4115b1439c8b9982227a018sberlin * Visitor for {@link LinkedKeyBinding}. This is the standard {@link Binding} you get from 111b71955639ab617e0a4115b1439c8b9982227a018sberlin * binding an interface class to an implementation class. We draw a {@link BindingEdge} from 112b71955639ab617e0a4115b1439c8b9982227a018sberlin * the interface node to the node of the implementing class. 113b71955639ab617e0a4115b1439c8b9982227a018sberlin */ 114b71955639ab617e0a4115b1439c8b9982227a018sberlin @Override public Collection<Edge> visit(LinkedKeyBinding<?> binding) { 115b71955639ab617e0a4115b1439c8b9982227a018sberlin return ImmutableList.<Edge>of(new BindingEdge(NodeId.newTypeId(binding.getKey()), 116b71955639ab617e0a4115b1439c8b9982227a018sberlin NodeId.newTypeId(binding.getLinkedKey()), 117b71955639ab617e0a4115b1439c8b9982227a018sberlin BindingEdge.Type.NORMAL)); 118b71955639ab617e0a4115b1439c8b9982227a018sberlin } 119b71955639ab617e0a4115b1439c8b9982227a018sberlin 120b71955639ab617e0a4115b1439c8b9982227a018sberlin /** 121b71955639ab617e0a4115b1439c8b9982227a018sberlin * Visitor for {@link ProviderBinding}. These {@link Binding}s arise from an 122b71955639ab617e0a4115b1439c8b9982227a018sberlin * {@link InjectionPoint} for the {@link Provider} interface. 123b71955639ab617e0a4115b1439c8b9982227a018sberlin */ 124b71955639ab617e0a4115b1439c8b9982227a018sberlin @Override public Collection<Edge> visit(ProviderBinding<?> binding) { 125b71955639ab617e0a4115b1439c8b9982227a018sberlin return ImmutableList.<Edge>of(new BindingEdge(NodeId.newTypeId(binding.getKey()), 126b71955639ab617e0a4115b1439c8b9982227a018sberlin NodeId.newTypeId(binding.getProvidedKey()), BindingEdge.Type.PROVIDER)); 127b71955639ab617e0a4115b1439c8b9982227a018sberlin } 128b71955639ab617e0a4115b1439c8b9982227a018sberlin 129b71955639ab617e0a4115b1439c8b9982227a018sberlin /** 130b71955639ab617e0a4115b1439c8b9982227a018sberlin * Same as {@link #visit(InstanceBinding)}, but the binding edge is 131b71955639ab617e0a4115b1439c8b9982227a018sberlin * {@link BindingEdge.Type#PROVIDER}. 132b71955639ab617e0a4115b1439c8b9982227a018sberlin */ 133b71955639ab617e0a4115b1439c8b9982227a018sberlin @Override public Collection<Edge> visit(ProviderInstanceBinding<?> binding) { 134b71955639ab617e0a4115b1439c8b9982227a018sberlin return new ImmutableList.Builder<Edge>() 135b71955639ab617e0a4115b1439c8b9982227a018sberlin .add(new BindingEdge(NodeId.newTypeId(binding.getKey()), 136b71955639ab617e0a4115b1439c8b9982227a018sberlin NodeId.newInstanceId(binding.getKey()), BindingEdge.Type.PROVIDER)) 137b71955639ab617e0a4115b1439c8b9982227a018sberlin .addAll(newDependencyEdges(NodeId.newInstanceId(binding.getKey()), binding)) 138b71955639ab617e0a4115b1439c8b9982227a018sberlin .build(); 139b71955639ab617e0a4115b1439c8b9982227a018sberlin } 140b71955639ab617e0a4115b1439c8b9982227a018sberlin 141b71955639ab617e0a4115b1439c8b9982227a018sberlin /** 142b71955639ab617e0a4115b1439c8b9982227a018sberlin * Same as {@link #visit(LinkedKeyBinding)}, but the binding edge is 143b71955639ab617e0a4115b1439c8b9982227a018sberlin * {@link BindingEdge.Type#PROVIDER}. 144b71955639ab617e0a4115b1439c8b9982227a018sberlin */ 145b71955639ab617e0a4115b1439c8b9982227a018sberlin @Override public Collection<Edge> visit(ProviderKeyBinding<?> binding) { 146b71955639ab617e0a4115b1439c8b9982227a018sberlin return ImmutableList.<Edge>of(new BindingEdge(NodeId.newTypeId(binding.getKey()), 147b71955639ab617e0a4115b1439c8b9982227a018sberlin NodeId.newTypeId(binding.getProviderKey()), BindingEdge.Type.PROVIDER)); 148b71955639ab617e0a4115b1439c8b9982227a018sberlin } 149b71955639ab617e0a4115b1439c8b9982227a018sberlin 150b71955639ab617e0a4115b1439c8b9982227a018sberlin @Override public Collection<Edge> visitOther(Binding<?> binding) { 151b71955639ab617e0a4115b1439c8b9982227a018sberlin return ImmutableList.of(); 152b71955639ab617e0a4115b1439c8b9982227a018sberlin } 153b71955639ab617e0a4115b1439c8b9982227a018sberlin } 154b71955639ab617e0a4115b1439c8b9982227a018sberlin} 155