Created
January 27, 2014 16:48
-
-
Save vorburger/8652290 to your computer and use it in GitHub Desktop.
InjectorToString.java - Guice Injector toString - nicer than built-in massive one line dump (currently unfinished)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * Copyright (C) 2014 Michael Vorburger | |
| * | |
| * 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 ch.vorburger.guice.util; | |
| import java.lang.annotation.Annotation; | |
| import java.lang.reflect.Type; | |
| import java.util.Collection; | |
| import java.util.Map.Entry; | |
| import java.util.Set; | |
| import com.google.inject.Binding; | |
| import com.google.inject.Injector; | |
| import com.google.inject.Key; | |
| import com.google.inject.Provider; | |
| import com.google.inject.Scope; | |
| import com.google.inject.spi.ConstructorBinding; | |
| import com.google.inject.spi.Dependency; | |
| import com.google.inject.spi.HasDependencies; | |
| import com.google.inject.spi.InjectionPoint; | |
| import com.google.inject.spi.ProviderInstanceBinding; | |
| import com.google.inject.spi.TypeConverterBinding; | |
| /** | |
| * Utility to dump the Guice Injector toString(). | |
| * | |
| * A little more readable than the OOB massive one line injector.toString()... ;-) | |
| * | |
| * @author Michael Vorburger | |
| */ | |
| public class InjectorToString { | |
| // TODO actually finish it some time, may be | |
| // TODO [HIGH] better nested intention (e.g. for Dependencies).. see how Xtend does it for http://www.eclipse.org/xtend/documentation.html#templates ? | |
| // TODO [HIGH] ignore Provider (but only if duplicates!).. | |
| // TODO [MEDIUM] separate explicit and just-in-time.. how? Note getBindings() vs. getAllBindings().. can we use set substraction? | |
| // TODO [MEDIUM] helper, extensible, to shorten annotations (or any type names).. e.g. @com.google.inject.name.Named ==> @Named, @com.google.inject.Provider ==> c.g.i.Provider (still from logger..) | |
| // TODO [MEDIUM] recursion risk? Note InjectorTest.testToStringDoesNotInfinitelyRecurse() ... | |
| // TODO [LOW] Builder thing, with options like ignoreProviderDuplicates | |
| // TODO [LOW] better to use Writer 1st args, instead of StringBuffer? | |
| protected static final String UNKNOWN_SOURCE = "[unknown source]"; | |
| public String toString(Injector injector) { | |
| StringBuilder sb = new StringBuilder(); | |
| printInjector(sb, injector); | |
| return sb.toString(); | |
| } | |
| protected void printInjector(StringBuilder sb, Injector injector) { | |
| sb.append(injector.toString()); // TODO remove again at the end, just for now.. | |
| sb.append('\n'); | |
| Set<Entry<Key<?>, Binding<?>>> allBindings = injector.getAllBindings().entrySet(); | |
| int i = 0; | |
| for (Entry<Key<?>, Binding<?>> entry : allBindings) { | |
| // TODO factor out methods.. making it easier to overload this | |
| // TOOD align nicely.. first find longest key.. | |
| sb.append(++i); | |
| sb.append(". "); | |
| Key<?> key = entry.getKey(); | |
| if (key.hasAttributes()) { | |
| sb.append(key.getAnnotation().toString()); | |
| sb.append("\n "); | |
| } | |
| Type type = key.getTypeLiteral().getType(); | |
| sb.append(type.toString()); | |
| sb.append(" : "); | |
| Binding<?> value = entry.getValue(); | |
| sb.append(value.toString());// TODO remove | |
| sb.append("\n "); | |
| printProviderBinding(sb, value.getProvider()); | |
| printSource(sb, value.getSource()); | |
| sb.append('\n'); | |
| } | |
| printTypeConverterBindings(sb, injector.getTypeConverterBindings()); | |
| printScopeBindings(sb, injector.getScopeBindings().entrySet()); | |
| printParent(sb, injector.getParent()); | |
| } | |
| protected void printProviderBinding(StringBuilder sb, Provider<?> provider) { | |
| sb.append("?? "); | |
| sb.append(provider.toString()); | |
| if (provider instanceof HasDependencies) { | |
| Set<Dependency<?>> dependencies = ((HasDependencies) provider).getDependencies(); | |
| printDependencies(sb, dependencies); | |
| } | |
| // if (provider instanceof Binding) { | |
| // Binding<?> binding = (Binding<?>) provider; | |
| // } | |
| if (provider instanceof ConstructorBinding) { | |
| ConstructorBinding constructorBinding = (ConstructorBinding) provider; | |
| printInjectionPoint(sb, constructorBinding.getConstructor()); | |
| printInjectionPoints(sb, constructorBinding.getInjectableMembers()); | |
| // TODO } else if (provider instanceof ConvertedConstantBinding) { | |
| // TODO } else if (provider instanceof ExposedBinding) { | |
| // TODO } else if (provider instanceof InstanceBinding) { | |
| // TODO } else if (provider instanceof LinkedKeyBinding) { | |
| // | |
| // TODO } else if (provider instanceof ProviderBinding) { | |
| } else if (provider instanceof ProviderInstanceBinding) { | |
| ProviderInstanceBinding pib = (ProviderInstanceBinding) provider; | |
| sb.append("ProviderInstance: "); | |
| printProviderInstance(sb, pib.getProviderInstance()); | |
| printInjectionPoints(sb, pib.getInjectionPoints()); | |
| // TODO } else if (provider instanceof ProviderKeyBinding) { | |
| // TODO } else if (provider instanceof UntargettedBinding) { | |
| } else { | |
| sb.append("WARN: No handling available for " + provider.getClass()); | |
| } | |
| sb.append(provider.getClass()); | |
| } | |
| protected void printDependencies(StringBuilder sb, Collection<Dependency<?>> dependencies) { | |
| printSectionHeaderIfNonEmptyCollection(sb, dependencies, "Dependencies"); | |
| for (Dependency<?> dependency : dependencies) { | |
| sb.append(dependency.getParameterIndex()); | |
| sb.append("="); | |
| printInjectionPoint(sb, dependency.getInjectionPoint()); | |
| } | |
| } | |
| protected void printInjectionPoints(StringBuilder sb, Set<InjectionPoint> injectionPoints) { | |
| printSectionHeaderIfNonEmptyCollection(sb, injectionPoints, "InjectionPoints"); | |
| for (InjectionPoint injectionPoint: injectionPoints) { | |
| printInjectionPoint(sb, injectionPoint); | |
| } | |
| } | |
| protected void printInjectionPoint(StringBuilder sb, InjectionPoint injectionPoint) { | |
| sb.append(injectionPoint.getDeclaringType()); | |
| sb.append(" -- "); // ? | |
| sb.append(injectionPoint.getMember()); | |
| printDependencies(sb, injectionPoint.getDependencies()); | |
| } | |
| protected void printProviderInstance(StringBuilder sb, Provider providerInstance) { | |
| sb.append(providerInstance.toString()); | |
| } | |
| protected void printTypeConverterBindings(StringBuilder sb, Set<TypeConverterBinding> typeConverterBindings) { | |
| printSectionHeaderIfNonEmptyCollection(sb, typeConverterBindings, "TypeConverterBindings"); | |
| for (TypeConverterBinding typeConverterBinding : typeConverterBindings) { | |
| sb.append("* "); | |
| sb.append(typeConverterBinding.getTypeMatcher().toString()); | |
| sb.append(" : "); | |
| sb.append(typeConverterBinding.getTypeConverter().toString()); | |
| printSource(sb, typeConverterBinding.getSource()); | |
| sb.append("\n"); | |
| } | |
| } | |
| protected void printScopeBindings(StringBuilder sb, Set<Entry<Class<? extends Annotation>, Scope>> scopeBindings) { | |
| printSectionHeaderIfNonEmptyCollection(sb, scopeBindings, "ScopeBindings"); | |
| for (Entry<Class<? extends Annotation>, Scope> scopeBinding : scopeBindings) { | |
| sb.append("* @"); | |
| sb.append(scopeBinding.getKey().getName()); | |
| sb.append(" : "); | |
| sb.append(scopeBinding.getValue().toString()); | |
| sb.append('\n'); | |
| } | |
| } | |
| protected void printSource(StringBuilder sb, Object source) { | |
| String sourceText = source.toString(); | |
| if (!UNKNOWN_SOURCE.equals(sourceText)) { | |
| sb.append("\n SRC "); | |
| sb.append(sourceText); | |
| } | |
| } | |
| // TODO [LOW] include a 1.1. 1.2. 2.1 (parent) kind of numbering | |
| protected void printParent(StringBuilder sb, Injector parent) { | |
| if (parent != null) { | |
| printSectionHeader(sb, "PARENT Injector"); | |
| printInjector(sb, parent); | |
| } | |
| } | |
| protected void printSectionHeaderIfNonEmptyCollection(StringBuilder sb, Collection<?> collection, String title) { | |
| if (!collection.isEmpty()) | |
| printSectionHeader(sb, title); | |
| } | |
| protected void printSectionHeader(StringBuilder sb, String title) { | |
| sb.append("\n"); | |
| sb.append(title); | |
| sb.append(":\n"); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment