diff options
Diffstat (limited to 'guava/src/com/google/common/reflect')
15 files changed, 0 insertions, 3630 deletions
diff --git a/guava/src/com/google/common/reflect/AbstractInvocationHandler.java b/guava/src/com/google/common/reflect/AbstractInvocationHandler.java deleted file mode 100644 index 489dcff..0000000 --- a/guava/src/com/google/common/reflect/AbstractInvocationHandler.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (C) 2012 The Guava Authors - * - * 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.common.reflect; - -import com.google.common.annotations.Beta; - -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; - -import javax.annotation.Nullable; - -/** - * Abstract implementation of {@link InvocationHandler} that handles {@link Object#equals}, - * {@link Object#hashCode} and {@link Object#toString}. - * - * @author Ben Yu - * @since 12.0 - */ -@Beta -public abstract class AbstractInvocationHandler implements InvocationHandler { - - private static final Object[] NO_ARGS = {}; - - /** - * {@inheritDoc} - * - * <p><ul> - * <li>{@code proxy.hashCode()} delegates to {@link AbstractInvocationHandler#hashCode} - * <li>{@code proxy.toString()} delegates to {@link AbstractInvocationHandler#toString} - * <li>{@code proxy.equals(argument)} returns true if: <ul> - * <li>{@code proxy} and {@code argument} are of the same type - * <li>and {@link AbstractInvocationHandler#equals} returns true for the {@link - * InvocationHandler} of {@code argument} - * </ul> - * <li>other method calls are dispatched to {@link #handleInvocation}. - * </ul> - */ - @Override public final Object invoke(Object proxy, Method method, @Nullable Object[] args) - throws Throwable { - if (args == null) { - args = NO_ARGS; - } - if (args.length == 0 && method.getName().equals("hashCode")) { - return hashCode(); - } - if (args.length == 1 - && method.getName().equals("equals") - && method.getParameterTypes()[0] == Object.class) { - Object arg = args[0]; - return proxy.getClass().isInstance(arg) && equals(Proxy.getInvocationHandler(arg)); - } - if (args.length == 0 && method.getName().equals("toString")) { - return toString(); - } - return handleInvocation(proxy, method, args); - } - - /** - * {@link #invoke} delegates to this method upon any method invocation on the proxy instance, - * except {@link Object#equals}, {@link Object#hashCode} and {@link Object#toString}. The result - * will be returned as the proxied method's return value. - * - * <p>Unlike {@link #invoke}, {@code args} will never be null. When the method has no parameter, - * an empty array is passed in. - */ - protected abstract Object handleInvocation(Object proxy, Method method, Object[] args) - throws Throwable; - - /** - * By default delegates to {@link Object#equals} so instances are only equal if they are - * identical. {@code proxy.equals(argument)} returns true if: <ul> - * <li>{@code proxy} and {@code argument} are of the same type - * <li>and this method returns true for the {@link InvocationHandler} of {@code argument} - * </ul> - * Subclasses can override this method to provide custom equality. - */ - @Override public boolean equals(Object obj) { - return super.equals(obj); - } - - /** - * By default delegates to {@link Object#hashCode}. The dynamic proxies' {@code hashCode()} will - * delegate to this method. Subclasses can override this method to provide custom equality. - */ - @Override public int hashCode() { - return super.hashCode(); - } - - /** - * By default delegates to {@link Object#toString}. The dynamic proxies' {@code toString()} will - * delegate to this method. Subclasses can override this method to provide custom string - * representation for the proxies. - */ - @Override public String toString() { - return super.toString(); - } -} diff --git a/guava/src/com/google/common/reflect/ClassPath.java b/guava/src/com/google/common/reflect/ClassPath.java deleted file mode 100644 index cfbc479..0000000 --- a/guava/src/com/google/common/reflect/ClassPath.java +++ /dev/null @@ -1,379 +0,0 @@ -/* - * Copyright (C) 2012 The Guava Authors - * - * 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.common.reflect; - -import static com.google.common.base.Preconditions.checkNotNull; - -import com.google.common.annotations.Beta; -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Splitter; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.ImmutableSortedSet; -import com.google.common.collect.Maps; -import com.google.common.collect.Ordering; - -import java.io.File; -import java.io.IOException; -import java.net.URI; -import java.net.URISyntaxException; -import java.net.URL; -import java.net.URLClassLoader; -import java.util.Enumeration; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.jar.JarEntry; -import java.util.jar.JarFile; -import java.util.jar.Manifest; -import java.util.logging.Logger; - -import javax.annotation.Nullable; - -/** - * Scans the source of a {@link ClassLoader} and finds all the classes loadable. - * - * @author Ben Yu - * @since 14.0 - */ -@Beta -public final class ClassPath { - - private static final Logger logger = Logger.getLogger(ClassPath.class.getName()); - - /** Separator for the Class-Path manifest attribute value in jar files. */ - private static final Splitter CLASS_PATH_ATTRIBUTE_SEPARATOR = - Splitter.on(" ").omitEmptyStrings(); - - private static final String CLASS_FILE_NAME_EXTENSION = ".class"; - - private final ImmutableSet<ResourceInfo> resources; - - private ClassPath(ImmutableSet<ResourceInfo> resources) { - this.resources = resources; - } - - /** - * Returns a {@code ClassPath} representing all classes and resources loadable from {@code - * classloader} and its parent class loaders. - * - * <p>Currently only {@link URLClassLoader} and only {@code file://} urls are supported. - * - * @throws IOException if the attempt to read class path resources (jar files or directories) - * failed. - */ - public static ClassPath from(ClassLoader classloader) throws IOException { - ImmutableSortedSet.Builder<ResourceInfo> resources = - new ImmutableSortedSet.Builder<ResourceInfo>(Ordering.usingToString()); - for (Map.Entry<URI, ClassLoader> entry : getClassPathEntries(classloader).entrySet()) { - browse(entry.getKey(), entry.getValue(), resources); - } - return new ClassPath(resources.build()); - } - - /** - * Returns all resources loadable from the current class path, including the class files of all - * loadable classes. - */ - public ImmutableSet<ResourceInfo> getResources() { - return resources; - } - - /** Returns all top level classes loadable from the current class path. */ - public ImmutableSet<ClassInfo> getTopLevelClasses() { - ImmutableSet.Builder<ClassInfo> builder = ImmutableSet.builder(); - for (ResourceInfo resource : resources) { - if (resource instanceof ClassInfo) { - builder.add((ClassInfo) resource); - } - } - return builder.build(); - } - - /** Returns all top level classes whose package name is {@code packageName}. */ - public ImmutableSet<ClassInfo> getTopLevelClasses(String packageName) { - checkNotNull(packageName); - ImmutableSet.Builder<ClassInfo> builder = ImmutableSet.builder(); - for (ClassInfo classInfo : getTopLevelClasses()) { - if (classInfo.getPackageName().equals(packageName)) { - builder.add(classInfo); - } - } - return builder.build(); - } - - /** - * Returns all top level classes whose package name is {@code packageName} or starts with - * {@code packageName} followed by a '.'. - */ - public ImmutableSet<ClassInfo> getTopLevelClassesRecursive(String packageName) { - checkNotNull(packageName); - String packagePrefix = packageName + '.'; - ImmutableSet.Builder<ClassInfo> builder = ImmutableSet.builder(); - for (ClassInfo classInfo : getTopLevelClasses()) { - if (classInfo.getName().startsWith(packagePrefix)) { - builder.add(classInfo); - } - } - return builder.build(); - } - - /** - * Represents a class path resource that can be either a class file or any other resource file - * loadable from the class path. - * - * @since 14.0 - */ - @Beta - public static class ResourceInfo { - private final String resourceName; - final ClassLoader loader; - - static ResourceInfo of(String resourceName, ClassLoader loader) { - if (resourceName.endsWith(CLASS_FILE_NAME_EXTENSION) && !resourceName.contains("$")) { - return new ClassInfo(resourceName, loader); - } else { - return new ResourceInfo(resourceName, loader); - } - } - - ResourceInfo(String resourceName, ClassLoader loader) { - this.resourceName = checkNotNull(resourceName); - this.loader = checkNotNull(loader); - } - - /** Returns the url identifying the resource. */ - public final URL url() { - return checkNotNull(loader.getResource(resourceName), - "Failed to load resource: %s", resourceName); - } - - /** Returns the fully qualified name of the resource. Such as "com/mycomp/foo/bar.txt". */ - public final String getResourceName() { - return resourceName; - } - - @Override public int hashCode() { - return resourceName.hashCode(); - } - - @Override public boolean equals(Object obj) { - if (obj instanceof ResourceInfo) { - ResourceInfo that = (ResourceInfo) obj; - return resourceName.equals(that.resourceName) - && loader == that.loader; - } - return false; - } - - @Override public String toString() { - return resourceName; - } - } - - /** - * Represents a class that can be loaded through {@link #load}. - * - * @since 14.0 - */ - @Beta - public static final class ClassInfo extends ResourceInfo { - private final String className; - - ClassInfo(String resourceName, ClassLoader loader) { - super(resourceName, loader); - this.className = getClassName(resourceName); - } - - /** Returns the package name of the class, without attempting to load the class. */ - public String getPackageName() { - return Reflection.getPackageName(className); - } - - /** Returns the simple name of the underlying class as given in the source code. */ - public String getSimpleName() { - String packageName = getPackageName(); - if (packageName.isEmpty()) { - return className; - } - // Since this is a top level class, its simple name is always the part after package name. - return className.substring(packageName.length() + 1); - } - - /** Returns the fully qualified name of the class. */ - public String getName() { - return className; - } - - /** Loads (but doesn't link or initialize) the class. */ - public Class<?> load() { - try { - return loader.loadClass(className); - } catch (ClassNotFoundException e) { - // Shouldn't happen, since the class name is read from the class path. - throw new IllegalStateException(e); - } - } - - @Override public String toString() { - return className; - } - } - - @VisibleForTesting static ImmutableMap<URI, ClassLoader> getClassPathEntries( - ClassLoader classloader) { - LinkedHashMap<URI, ClassLoader> entries = Maps.newLinkedHashMap(); - // Search parent first, since it's the order ClassLoader#loadClass() uses. - ClassLoader parent = classloader.getParent(); - if (parent != null) { - entries.putAll(getClassPathEntries(parent)); - } - if (classloader instanceof URLClassLoader) { - URLClassLoader urlClassLoader = (URLClassLoader) classloader; - for (URL entry : urlClassLoader.getURLs()) { - URI uri; - try { - uri = entry.toURI(); - } catch (URISyntaxException e) { - throw new IllegalArgumentException(e); - } - if (!entries.containsKey(uri)) { - entries.put(uri, classloader); - } - } - } - return ImmutableMap.copyOf(entries); - } - - private static void browse( - URI uri, ClassLoader classloader, ImmutableSet.Builder<ResourceInfo> resources) - throws IOException { - if (uri.getScheme().equals("file")) { - browseFrom(new File(uri), classloader, resources); - } - } - - @VisibleForTesting static void browseFrom( - File file, ClassLoader classloader, ImmutableSet.Builder<ResourceInfo> resources) - throws IOException { - if (!file.exists()) { - return; - } - if (file.isDirectory()) { - browseDirectory(file, classloader, resources); - } else { - browseJar(file, classloader, resources); - } - } - - private static void browseDirectory( - File directory, ClassLoader classloader, ImmutableSet.Builder<ResourceInfo> resources) { - browseDirectory(directory, classloader, "", resources); - } - - private static void browseDirectory( - File directory, ClassLoader classloader, String packagePrefix, - ImmutableSet.Builder<ResourceInfo> resources) { - for (File f : directory.listFiles()) { - String name = f.getName(); - if (f.isDirectory()) { - browseDirectory(f, classloader, packagePrefix + name + "/", resources); - } else { - String resourceName = packagePrefix + name; - resources.add(ResourceInfo.of(resourceName, classloader)); - } - } - } - - private static void browseJar( - File file, ClassLoader classloader, ImmutableSet.Builder<ResourceInfo> resources) - throws IOException { - JarFile jarFile; - try { - jarFile = new JarFile(file); - } catch (IOException e) { - // Not a jar file - return; - } - try { - for (URI uri : getClassPathFromManifest(file, jarFile.getManifest())) { - browse(uri, classloader, resources); - } - Enumeration<JarEntry> entries = jarFile.entries(); - while (entries.hasMoreElements()) { - JarEntry entry = entries.nextElement(); - if (entry.isDirectory() || entry.getName().startsWith("META-INF/")) { - continue; - } - resources.add(ResourceInfo.of(entry.getName(), classloader)); - } - } finally { - try { - jarFile.close(); - } catch (IOException ignored) {} - } - } - - /** - * Returns the class path URIs specified by the {@code Class-Path} manifest attribute, according - * to <a href="http://docs.oracle.com/javase/1.4.2/docs/guide/jar/jar.html#Main%20Attributes"> - * JAR File Specification</a>. If {@code manifest} is null, it means the jar file has no manifest, - * and an empty set will be returned. - */ - @VisibleForTesting static ImmutableSet<URI> getClassPathFromManifest( - File jarFile, @Nullable Manifest manifest) { - if (manifest == null) { - return ImmutableSet.of(); - } - ImmutableSet.Builder<URI> builder = ImmutableSet.builder(); - String classpathAttribute = manifest.getMainAttributes().getValue("Class-Path"); - if (classpathAttribute != null) { - for (String path : CLASS_PATH_ATTRIBUTE_SEPARATOR.split(classpathAttribute)) { - URI uri; - try { - uri = getClassPathEntry(jarFile, path); - } catch (URISyntaxException e) { - // Ignore bad entry - logger.warning("Invalid Class-Path entry: " + path); - continue; - } - builder.add(uri); - } - } - return builder.build(); - } - - /** - * Returns the absolute uri of the Class-Path entry value as specified in - * <a href="http://docs.oracle.com/javase/1.4.2/docs/guide/jar/jar.html#Main%20Attributes"> - * JAR File Specification</a>. Even though the specification only talks about relative urls, - * absolute urls are actually supported too (for example, in Maven surefire plugin). - */ - @VisibleForTesting static URI getClassPathEntry(File jarFile, String path) - throws URISyntaxException { - URI uri = new URI(path); - if (uri.isAbsolute()) { - return uri; - } else { - return new File(jarFile.getParentFile(), path.replace('/', File.separatorChar)).toURI(); - } - } - - @VisibleForTesting static String getClassName(String filename) { - int classNameEnd = filename.length() - CLASS_FILE_NAME_EXTENSION.length(); - return filename.substring(0, classNameEnd).replace('/', '.'); - } -} diff --git a/guava/src/com/google/common/reflect/Element.java b/guava/src/com/google/common/reflect/Element.java deleted file mode 100644 index 14962b6..0000000 --- a/guava/src/com/google/common/reflect/Element.java +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright (C) 2012 The Guava Authors - * - * 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.common.reflect; - -import static com.google.common.base.Preconditions.checkNotNull; - -import java.lang.annotation.Annotation; -import java.lang.reflect.AccessibleObject; -import java.lang.reflect.Constructor; -import java.lang.reflect.Field; -import java.lang.reflect.Member; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; - -import javax.annotation.Nullable; - -/** - * Represents either a {@link Field}, a {@link Method} or a {@link Constructor}. - * Provides convenience methods such as {@link #isPublic} and {@link #isPackagePrivate}. - * - * @author Ben Yu - */ -class Element extends AccessibleObject implements Member { - - private final AccessibleObject accessibleObject; - private final Member member; - - <M extends AccessibleObject & Member> Element(M member) { - checkNotNull(member); - this.accessibleObject = member; - this.member = member; - } - - @Override public final boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) { - return accessibleObject.isAnnotationPresent(annotationClass); - } - - @Override public final <A extends Annotation> A getAnnotation(Class<A> annotationClass) { - return accessibleObject.getAnnotation(annotationClass); - } - - @Override public final Annotation[] getAnnotations() { - return accessibleObject.getAnnotations(); - } - - @Override public final Annotation[] getDeclaredAnnotations() { - return accessibleObject.getDeclaredAnnotations(); - } - - @Override public final void setAccessible(boolean flag) throws SecurityException { - accessibleObject.setAccessible(flag); - } - - @Override public final boolean isAccessible() { - return accessibleObject.isAccessible(); - } - - @Override public Class<?> getDeclaringClass() { - return member.getDeclaringClass(); - } - - @Override public final String getName() { - return member.getName(); - } - - @Override public final int getModifiers() { - return member.getModifiers(); - } - - @Override public final boolean isSynthetic() { - return member.isSynthetic(); - } - - /** Returns true if the element is public. */ - public final boolean isPublic() { - return Modifier.isPublic(getModifiers()); - } - - /** Returns true if the element is protected. */ - public final boolean isProtected() { - return Modifier.isProtected(getModifiers()); - } - - /** Returns true if the element is package-private. */ - public final boolean isPackagePrivate() { - return !isPrivate() && !isPublic() && !isProtected(); - } - - /** Returns true if the element is private. */ - public final boolean isPrivate() { - return Modifier.isPrivate(getModifiers()); - } - - /** Returns true if the element is static. */ - public final boolean isStatic() { - return Modifier.isStatic(getModifiers()); - } - - /** - * Returns {@code true} if this method is final, per {@code Modifier.isFinal(getModifiers())}. - * - * <p>Note that a method may still be effectively "final", or non-overridable when it has no - * {@code final} keyword. For example, it could be private, or it could be declared by a final - * class. To tell whether a method is overridable, use {@link Invokable#isOverridable}. - */ - public final boolean isFinal() { - return Modifier.isFinal(getModifiers()); - } - - /** Returns true if the method is abstract. */ - public final boolean isAbstract() { - return Modifier.isAbstract(getModifiers()); - } - - /** Returns true if the element is native. */ - public final boolean isNative() { - return Modifier.isNative(getModifiers()); - } - - /** Returns true if the method is synchronized. */ - public final boolean isSynchronized() { - return Modifier.isSynchronized(getModifiers()); - } - - /** Returns true if the field is volatile. */ - final boolean isVolatile() { - return Modifier.isVolatile(getModifiers()); - } - - /** Returns true if the field is transient. */ - final boolean isTransient() { - return Modifier.isTransient(getModifiers()); - } - - @Override public boolean equals(@Nullable Object obj) { - if (obj instanceof Element) { - Element that = (Element) obj; - return member.equals(that.member); - } - return false; - } - - @Override public int hashCode() { - return member.hashCode(); - } - - @Override public String toString() { - return member.toString(); - } -} diff --git a/guava/src/com/google/common/reflect/ImmutableTypeToInstanceMap.java b/guava/src/com/google/common/reflect/ImmutableTypeToInstanceMap.java deleted file mode 100644 index 43e5e1e..0000000 --- a/guava/src/com/google/common/reflect/ImmutableTypeToInstanceMap.java +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright (C) 2012 The Guava Authors - * - * 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.common.reflect; - -import com.google.common.annotations.Beta; -import com.google.common.collect.ForwardingMap; -import com.google.common.collect.ImmutableMap; - -import java.util.Map; - -/** - * A type-to-instance map backed by an {@link ImmutableMap}. See also {@link - * MutableTypeToInstanceMap}. - * - * @author Ben Yu - * @since 13.0 - */ -@Beta -public final class ImmutableTypeToInstanceMap<B> extends ForwardingMap<TypeToken<? extends B>, B> - implements TypeToInstanceMap<B> { - - /** Returns an empty type to instance map. */ - public static <B> ImmutableTypeToInstanceMap<B> of() { - return new ImmutableTypeToInstanceMap<B>(ImmutableMap.<TypeToken<? extends B>, B>of()); - } - - /** Returns a new builder. */ - public static <B> Builder<B> builder() { - return new Builder<B>(); - } - - /** - * A builder for creating immutable type-to-instance maps. Example: - * <pre> {@code - * - * static final ImmutableTypeToInstanceMap<Handler<?>> HANDLERS = - * ImmutableTypeToInstanceMap.<Handler<?>>builder() - * .put(new TypeToken<Handler<Foo>>() {}, new FooHandler()) - * .put(new TypeToken<Handler<Bar>>() {}, new SubBarHandler()) - * .build();}</pre> - * - * After invoking {@link #build()} it is still possible to add more entries - * and build again. Thus each map generated by this builder will be a superset - * of any map generated before it. - * - * @since 13.0 - */ - @Beta - public static final class Builder<B> { - private final ImmutableMap.Builder<TypeToken<? extends B>, B> mapBuilder - = ImmutableMap.builder(); - - private Builder() {} - - /** - * Associates {@code key} with {@code value} in the built map. Duplicate - * keys are not allowed, and will cause {@link #build} to fail. - */ - public <T extends B> Builder<B> put(Class<T> key, T value) { - mapBuilder.put(TypeToken.of(key), value); - return this; - } - - /** - * Associates {@code key} with {@code value} in the built map. Duplicate - * keys are not allowed, and will cause {@link #build} to fail. - */ - public <T extends B> Builder<B> put(TypeToken<T> key, T value) { - mapBuilder.put(key.rejectTypeVariables(), value); - return this; - } - - /** - * Returns a new immutable type-to-instance map containing the entries - * provided to this builder. - * - * @throws IllegalArgumentException if duplicate keys were added - */ - public ImmutableTypeToInstanceMap<B> build() { - return new ImmutableTypeToInstanceMap<B>(mapBuilder.build()); - } - } - - private final ImmutableMap<TypeToken<? extends B>, B> delegate; - - private ImmutableTypeToInstanceMap(ImmutableMap<TypeToken<? extends B>, B> delegate) { - this.delegate = delegate; - } - - @Override public <T extends B> T getInstance(TypeToken<T> type) { - return trustedGet(type.rejectTypeVariables()); - } - - /** - * Guaranteed to throw an exception and leave the map unmodified. - * - * @throws UnsupportedOperationException always - */ - @Override public <T extends B> T putInstance(TypeToken<T> type, T value) { - throw new UnsupportedOperationException(); - } - - @Override public <T extends B> T getInstance(Class<T> type) { - return trustedGet(TypeToken.of(type)); - } - - /** - * Guaranteed to throw an exception and leave the map unmodified. - * - * @throws UnsupportedOperationException always - */ - @Override public <T extends B> T putInstance(Class<T> type, T value) { - throw new UnsupportedOperationException(); - } - - @Override protected Map<TypeToken<? extends B>, B> delegate() { - return delegate; - } - - @SuppressWarnings("unchecked") // value could not get in if not a T - private <T extends B> T trustedGet(TypeToken<T> type) { - return (T) delegate.get(type); - } -} diff --git a/guava/src/com/google/common/reflect/Invokable.java b/guava/src/com/google/common/reflect/Invokable.java deleted file mode 100644 index a8f9b77..0000000 --- a/guava/src/com/google/common/reflect/Invokable.java +++ /dev/null @@ -1,286 +0,0 @@ -/* - * Copyright (C) 2012 The Guava Authors - * - * 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.common.reflect; - -import static com.google.common.base.Preconditions.checkNotNull; - -import com.google.common.annotations.Beta; -import com.google.common.collect.ImmutableList; - -import java.lang.annotation.Annotation; -import java.lang.reflect.AccessibleObject; -import java.lang.reflect.Constructor; -import java.lang.reflect.GenericDeclaration; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Member; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.lang.reflect.Type; -import java.lang.reflect.TypeVariable; -import java.util.Arrays; - -import javax.annotation.Nullable; - -/** - * Wrapper around either a {@link Method} or a {@link Constructor}. - * Convenience API is provided to make common reflective operation easier to deal with, - * such as {@link #isPublic}, {@link #getParameters} etc. - * - * <p>In addition to convenience methods, {@link TypeToken#method} and {@link - * TypeToken#constructor} will resolve the type parameters of the method or constructor in the - * context of the owner type, which may be a subtype of the declaring class. For example: - * <pre> {@code - * - * Method getMethod = List.class.getMethod("get", int.class); - * Invokable<List<String>, ?> invokable = new TypeToken<List<String>>() {}.method(getMethod); - * assertEquals(TypeToken.of(String.class), invokable.getReturnType()); // Not Object.class! - * assertEquals(new TypeToken<List<String>>() {}, invokable.getOwnerType());}</pre> - * - * @param <T> the type that owns this method or constructor. - * @param <R> the return type of (or supertype thereof) the method or the declaring type of the - * constructor. - * @author Ben Yu - * @since 14.0 - */ -@Beta -public abstract class Invokable<T, R> extends Element implements GenericDeclaration { - - <M extends AccessibleObject & Member> Invokable(M member) { - super(member); - } - - /** Returns {@link Invokable} of {@code method}. */ - public static Invokable<?, Object> from(Method method) { - return new MethodInvokable<Object>(method); - } - - /** Returns {@link Invokable} of {@code constructor}. */ - public static <T> Invokable<T, T> from(Constructor<T> constructor) { - return new ConstructorInvokable<T>(constructor); - } - - /** - * Returns {@code true} if this is an overridable method. Constructors, private, static or final - * methods, or methods declared by final classes are not overridable. - */ - public abstract boolean isOverridable(); - - /** Returns {@code true} if this was declared to take a variable number of arguments. */ - public abstract boolean isVarArgs(); - - /** - * Invokes with {@code receiver} as 'this' and {@code args} passed to the underlying method - * and returns the return value; or calls the underlying constructor with {@code args} and returns - * the constructed instance. - * - * @throws IllegalAccessException if this {@code Constructor} object enforces Java language - * access control and the underlying method or constructor is inaccessible. - * @throws IllegalArgumentException if the number of actual and formal parameters differ; - * if an unwrapping conversion for primitive arguments fails; or if, after possible - * unwrapping, a parameter value cannot be converted to the corresponding formal - * parameter type by a method invocation conversion. - * @throws InvocationTargetException if the underlying method or constructor throws an exception. - */ - // All subclasses are owned by us and we'll make sure to get the R type right. - @SuppressWarnings("unchecked") - public final R invoke(@Nullable T receiver, Object... args) - throws InvocationTargetException, IllegalAccessException { - return (R) invokeInternal(receiver, checkNotNull(args)); - } - - /** Returns the return type of this {@code Invokable}. */ - // All subclasses are owned by us and we'll make sure to get the R type right. - @SuppressWarnings("unchecked") - public final TypeToken<? extends R> getReturnType() { - return (TypeToken<? extends R>) TypeToken.of(getGenericReturnType()); - } - - /** - * Returns all declared parameters of this {@code Invokable}. Note that if this is a constructor - * of a non-static inner class, unlike {@link Constructor#getParameterTypes}, the hidden - * {@code this} parameter of the enclosing class is excluded from the returned parameters. - */ - public final ImmutableList<Parameter> getParameters() { - Type[] parameterTypes = getGenericParameterTypes(); - Annotation[][] annotations = getParameterAnnotations(); - ImmutableList.Builder<Parameter> builder = ImmutableList.builder(); - for (int i = 0; i < parameterTypes.length; i++) { - builder.add(new Parameter( - this, i, TypeToken.of(parameterTypes[i]), annotations[i])); - } - return builder.build(); - } - - /** Returns all declared exception types of this {@code Invokable}. */ - public final ImmutableList<TypeToken<? extends Throwable>> getExceptionTypes() { - ImmutableList.Builder<TypeToken<? extends Throwable>> builder = ImmutableList.builder(); - for (Type type : getGenericExceptionTypes()) { - // getGenericExceptionTypes() will never return a type that's not exception - @SuppressWarnings("unchecked") - TypeToken<? extends Throwable> exceptionType = (TypeToken<? extends Throwable>) - TypeToken.of(type); - builder.add(exceptionType); - } - return builder.build(); - } - - /** - * Explicitly specifies the return type of this {@code Invokable}. For example: - * <pre> {@code - * Method factoryMethod = Person.class.getMethod("create"); - * Invokable<?, Person> factory = Invokable.of(getNameMethod).returning(Person.class); - * }</pre> - */ - public final <R1 extends R> Invokable<T, R1> returning(Class<R1> returnType) { - return returning(TypeToken.of(returnType)); - } - - /** Explicitly specifies the return type of this {@code Invokable}. */ - public final <R1 extends R> Invokable<T, R1> returning(TypeToken<R1> returnType) { - if (!returnType.isAssignableFrom(getReturnType())) { - throw new IllegalArgumentException( - "Invokable is known to return " + getReturnType() + ", not " + returnType); - } - @SuppressWarnings("unchecked") // guarded by previous check - Invokable<T, R1> specialized = (Invokable<T, R1>) this; - return specialized; - } - - @SuppressWarnings("unchecked") // The declaring class is T's raw class, or one of its supertypes. - @Override public final Class<? super T> getDeclaringClass() { - return (Class<? super T>) super.getDeclaringClass(); - } - - /** Returns the type of {@code T}. */ - // Overridden in TypeToken#method() and TypeToken#constructor() - @SuppressWarnings("unchecked") // The declaring class is T. - public TypeToken<T> getOwnerType() { - return (TypeToken<T>) TypeToken.of(getDeclaringClass()); - } - - abstract Object invokeInternal(@Nullable Object receiver, Object[] args) - throws InvocationTargetException, IllegalAccessException; - - abstract Type[] getGenericParameterTypes(); - - /** This should never return a type that's not a subtype of Throwable. */ - abstract Type[] getGenericExceptionTypes(); - - abstract Annotation[][] getParameterAnnotations(); - - abstract Type getGenericReturnType(); - - static class MethodInvokable<T> extends Invokable<T, Object> { - - private final Method method; - - MethodInvokable(Method method) { - super(method); - this.method = method; - } - - @Override final Object invokeInternal(@Nullable Object receiver, Object[] args) - throws InvocationTargetException, IllegalAccessException { - return method.invoke(receiver, args); - } - - @Override Type getGenericReturnType() { - return method.getGenericReturnType(); - } - - @Override Type[] getGenericParameterTypes() { - return method.getGenericParameterTypes(); - } - - @Override Type[] getGenericExceptionTypes() { - return method.getGenericExceptionTypes(); - } - - @Override final Annotation[][] getParameterAnnotations() { - return method.getParameterAnnotations(); - } - - @Override public final TypeVariable<?>[] getTypeParameters() { - return method.getTypeParameters(); - } - - @Override public final boolean isOverridable() { - return !(isFinal() || isPrivate() || isStatic() - || Modifier.isFinal(getDeclaringClass().getModifiers())); - } - - @Override public final boolean isVarArgs() { - return method.isVarArgs(); - } - } - - static class ConstructorInvokable<T> extends Invokable<T, T> { - - private final Constructor<?> constructor; - - ConstructorInvokable(Constructor<?> constructor) { - super(constructor); - this.constructor = constructor; - } - - @Override final Object invokeInternal(@Nullable Object receiver, Object[] args) - throws InvocationTargetException, IllegalAccessException { - try { - return constructor.newInstance(args); - } catch (InstantiationException e) { - throw new RuntimeException(constructor + " failed.", e); - } - } - - @Override Type getGenericReturnType() { - return constructor.getDeclaringClass(); - } - - @Override Type[] getGenericParameterTypes() { - Type[] types = constructor.getGenericParameterTypes(); - Class<?> declaringClass = constructor.getDeclaringClass(); - if (!Modifier.isStatic(declaringClass.getModifiers()) - && declaringClass.getEnclosingClass() != null) { - if (types.length == constructor.getParameterTypes().length) { - // first parameter is the hidden 'this' - return Arrays.copyOfRange(types, 1, types.length); - } - } - return types; - } - - @Override Type[] getGenericExceptionTypes() { - return constructor.getGenericExceptionTypes(); - } - - @Override final Annotation[][] getParameterAnnotations() { - return constructor.getParameterAnnotations(); - } - - @Override public final TypeVariable<?>[] getTypeParameters() { - return constructor.getTypeParameters(); - } - - @Override public final boolean isOverridable() { - return false; - } - - @Override public final boolean isVarArgs() { - return constructor.isVarArgs(); - } - } -} diff --git a/guava/src/com/google/common/reflect/MutableTypeToInstanceMap.java b/guava/src/com/google/common/reflect/MutableTypeToInstanceMap.java deleted file mode 100644 index 5f1249d..0000000 --- a/guava/src/com/google/common/reflect/MutableTypeToInstanceMap.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (C) 2012 The Guava Authors - * - * 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.common.reflect; - -import com.google.common.annotations.Beta; -import com.google.common.collect.ForwardingMap; -import com.google.common.collect.Maps; - -import java.util.Map; - -import javax.annotation.Nullable; - -/** - * A mutable type-to-instance map. - * See also {@link ImmutableTypeToInstanceMap}. - * - * @author Ben Yu - * @since 13.0 - */ -@Beta -public final class MutableTypeToInstanceMap<B> extends ForwardingMap<TypeToken<? extends B>, B> - implements TypeToInstanceMap<B> { - - private final Map<TypeToken<? extends B>, B> backingMap = Maps.newHashMap(); - - @Nullable - @Override - public <T extends B> T getInstance(Class<T> type) { - return trustedGet(TypeToken.of(type)); - } - - @Nullable - @Override - public <T extends B> T putInstance(Class<T> type, @Nullable T value) { - return trustedPut(TypeToken.of(type), value); - } - - @Nullable - @Override - public <T extends B> T getInstance(TypeToken<T> type) { - return trustedGet(type.rejectTypeVariables()); - } - - @Nullable - @Override - public <T extends B> T putInstance(TypeToken<T> type, @Nullable T value) { - return trustedPut(type.rejectTypeVariables(), value); - } - - /** Not supported. Use {@link #putInstance} instead. */ - @Override public B put(TypeToken<? extends B> key, B value) { - throw new UnsupportedOperationException("Please use putInstance() instead."); - } - - /** Not supported. Use {@link #putInstance} instead. */ - @Override public void putAll(Map<? extends TypeToken<? extends B>, ? extends B> map) { - throw new UnsupportedOperationException("Please use putInstance() instead."); - } - - @Override protected Map<TypeToken<? extends B>, B> delegate() { - return backingMap; - } - - @SuppressWarnings("unchecked") // value could not get in if not a T - @Nullable - private <T extends B> T trustedPut(TypeToken<T> type, @Nullable T value) { - return (T) backingMap.put(type, value); - } - - @SuppressWarnings("unchecked") // value could not get in if not a T - @Nullable - private <T extends B> T trustedGet(TypeToken<T> type) { - return (T) backingMap.get(type); - } -} diff --git a/guava/src/com/google/common/reflect/Parameter.java b/guava/src/com/google/common/reflect/Parameter.java deleted file mode 100644 index 977bc8d..0000000 --- a/guava/src/com/google/common/reflect/Parameter.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (C) 2012 The Guava Authors - * - * 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.common.reflect; - -import static com.google.common.base.Preconditions.checkNotNull; - -import com.google.common.annotations.Beta; -import com.google.common.collect.ImmutableList; - -import java.lang.annotation.Annotation; -import java.lang.reflect.AnnotatedElement; - -import javax.annotation.Nullable; - -/** - * Represents a method or constructor parameter. - * - * @author Ben Yu - * @since 14.0 - */ -@Beta -public final class Parameter implements AnnotatedElement { - - private final Invokable<?, ?> declaration; - private final int position; - private final TypeToken<?> type; - private final ImmutableList<Annotation> annotations; - - Parameter( - Invokable<?, ?> declaration, - int position, - TypeToken<?> type, - Annotation[] annotations) { - this.declaration = declaration; - this.position = position; - this.type = type; - this.annotations = ImmutableList.copyOf(annotations); - } - - /** Returns the type of the parameter. */ - public TypeToken<?> getType() { - return type; - } - - /** Returns the {@link Invokable} that declares this parameter. */ - public Invokable<?, ?> getDeclaringInvokable() { - return declaration; - } - - @Override public boolean isAnnotationPresent(Class<? extends Annotation> annotationType) { - return getAnnotation(annotationType) != null; - } - - @Override - @Nullable - public <A extends Annotation> A getAnnotation(Class<A> annotationType) { - checkNotNull(annotationType); - for (Annotation annotation : annotations) { - if (annotationType.isInstance(annotation)) { - return annotationType.cast(annotation); - } - } - return null; - } - - @Override public Annotation[] getAnnotations() { - return getDeclaredAnnotations(); - } - - @Override public Annotation[] getDeclaredAnnotations() { - return annotations.toArray(new Annotation[annotations.size()]); - } - - @Override public boolean equals(@Nullable Object obj) { - if (obj instanceof Parameter) { - Parameter that = (Parameter) obj; - return position == that.position && declaration.equals(that.declaration); - } - return false; - } - - @Override public int hashCode() { - return position; - } - - @Override public String toString() { - return type + " arg" + position; - } -} diff --git a/guava/src/com/google/common/reflect/Reflection.java b/guava/src/com/google/common/reflect/Reflection.java deleted file mode 100644 index 028c8a9..0000000 --- a/guava/src/com/google/common/reflect/Reflection.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (C) 2005 The Guava Authors - * - * 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.common.reflect; - -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; - -import com.google.common.annotations.Beta; - -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.Proxy; - -/** - * Static utilities relating to Java reflection. - * - * @since 12.0 - */ -@Beta -public final class Reflection { - - /** - * Returns the package name of {@code clazz} according to the Java Language Specification (section - * 6.7). Unlike {@link Class#getPackage}, this method only parses the class name, without - * attempting to define the {@link Package} and hence load files. - */ - public static String getPackageName(Class<?> clazz) { - return getPackageName(clazz.getName()); - } - - /** - * Returns the package name of {@code classFullName} according to the Java Language Specification - * (section 6.7). Unlike {@link Class#getPackage}, this method only parses the class name, without - * attempting to define the {@link Package} and hence load files. - */ - public static String getPackageName(String classFullName) { - int lastDot = classFullName.lastIndexOf('.'); - return (lastDot < 0) ? "" : classFullName.substring(0, lastDot); - } - - /** - * Ensures that the given classes are initialized, as described in - * <a href="http://java.sun.com/docs/books/jls/third_edition/html/execution.html#12.4.2"> - * JLS Section 12.4.2</a>. - * - * <p>WARNING: Normally it's a smell if a class needs to be explicitly initialized, because static - * state hurts system maintainability and testability. In cases when you have no choice while - * inter-operating with a legacy framework, this method helps to keep the code less ugly. - * - * @throws ExceptionInInitializerError if an exception is thrown during - * initialization of a class - */ - public static void initialize(Class<?>... classes) { - for (Class<?> clazz : classes) { - try { - Class.forName(clazz.getName(), true, clazz.getClassLoader()); - } catch (ClassNotFoundException e) { - throw new AssertionError(e); - } - } - } - - /** - * Returns a proxy instance that implements {@code interfaceType} by - * dispatching method invocations to {@code handler}. The class loader of - * {@code interfaceType} will be used to define the proxy class. To implement - * multiple interfaces or specify a class loader, use - * {@link Proxy#newProxyInstance}. - * - * @throws IllegalArgumentException if {@code interfaceType} does not specify - * the type of a Java interface - */ - public static <T> T newProxy( - Class<T> interfaceType, InvocationHandler handler) { - checkNotNull(handler); - checkArgument(interfaceType.isInterface(), "%s is not an interface", interfaceType); - Object object = Proxy.newProxyInstance( - interfaceType.getClassLoader(), - new Class<?>[] { interfaceType }, - handler); - return interfaceType.cast(object); - } - - private Reflection() {} -} diff --git a/guava/src/com/google/common/reflect/TypeCapture.java b/guava/src/com/google/common/reflect/TypeCapture.java deleted file mode 100644 index c686661..0000000 --- a/guava/src/com/google/common/reflect/TypeCapture.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (C) 2012 The Guava Authors - * - * 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.common.reflect; - -import static com.google.common.base.Preconditions.checkArgument; - -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; - -/** - * Captures the actual type of {@code T}. - * - * @author Ben Yu - */ -abstract class TypeCapture<T> { - - /** Returns the captured type. */ - final Type capture() { - Type superclass = getClass().getGenericSuperclass(); - checkArgument(superclass instanceof ParameterizedType, - "%s isn't parameterized", superclass); - return ((ParameterizedType) superclass).getActualTypeArguments()[0]; - } -} diff --git a/guava/src/com/google/common/reflect/TypeParameter.java b/guava/src/com/google/common/reflect/TypeParameter.java deleted file mode 100644 index 79bf076..0000000 --- a/guava/src/com/google/common/reflect/TypeParameter.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (C) 2011 The Guava Authors - * - * 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.common.reflect; - -import static com.google.common.base.Preconditions.checkArgument; - -import com.google.common.annotations.Beta; - -import java.lang.reflect.Type; -import java.lang.reflect.TypeVariable; - -import javax.annotation.Nullable; - -/** - * Captures a free type variable that can be used in {@link TypeToken#where}. - * For example: <pre> {@code - * - * static <T> TypeToken<List<T>> listOf(Class<T> elementType) { - * return new TypeToken<List<T>>() {} - * .where(new TypeParameter<T>() {}, elementType); - * } - * }</pre> - * - * @author Ben Yu - * @since 12.0 - */ -@Beta -public abstract class TypeParameter<T> extends TypeCapture<T> { - - final TypeVariable<?> typeVariable; - - protected TypeParameter() { - Type type = capture(); - checkArgument(type instanceof TypeVariable, "%s should be a type variable.", type); - this.typeVariable = (TypeVariable<?>) type; - } - - @Override public final int hashCode() { - return typeVariable.hashCode(); - } - - @Override public final boolean equals(@Nullable Object o) { - if (o instanceof TypeParameter) { - TypeParameter<?> that = (TypeParameter<?>) o; - return typeVariable.equals(that.typeVariable); - } - return false; - } - - @Override public String toString() { - return typeVariable.toString(); - } -} diff --git a/guava/src/com/google/common/reflect/TypeResolver.java b/guava/src/com/google/common/reflect/TypeResolver.java deleted file mode 100644 index 8c2d582..0000000 --- a/guava/src/com/google/common/reflect/TypeResolver.java +++ /dev/null @@ -1,391 +0,0 @@ -/* - * Copyright (C) 2009 The Guava Authors - * - * 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.common.reflect; - -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; -import static com.google.common.base.Preconditions.checkState; - -import com.google.common.base.Joiner; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Maps; -import com.google.common.collect.Sets; - -import java.lang.reflect.GenericArrayType; -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; -import java.lang.reflect.TypeVariable; -import java.lang.reflect.WildcardType; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.atomic.AtomicInteger; - -import javax.annotation.Nullable; - -/** - * An object of this class encapsulates type mappings from type variables. Mappings are established - * with {@link #where} and types are resolved using {@link #resolveType}. - * - * <p>Note that usually type mappings are already implied by the static type hierarchy (for example, - * the {@code E} type variable declared by class {@code List} naturally maps to {@code String} in - * the context of {@code class MyStringList implements List<String>}. In such case, prefer to use - * {@link TypeToken#resolveType} since it's simpler and more type safe. This class should only be - * used when the type mapping isn't implied by the static type hierarchy, but provided through other - * means such as an annotation or external configuration file. - * - * @author Ben Yu - */ -class TypeResolver { - - private final ImmutableMap<TypeVariable<?>, Type> typeTable; - - public TypeResolver() { - this.typeTable = ImmutableMap.of(); - } - - private TypeResolver(ImmutableMap<TypeVariable<?>, Type> typeTable) { - this.typeTable = typeTable; - } - - static TypeResolver accordingTo(Type type) { - return new TypeResolver().where(TypeMappingIntrospector.getTypeMappings(type)); - } - - /** - * Returns a new {@code TypeResolver} with type variables in {@code formal} mapping to types in - * {@code actual}. - * - * <p>For example, if {@code formal} is a {@code TypeVariable T}, and {@code actual} is {@code - * String.class}, then {@code new TypeResolver().where(formal, actual)} will {@linkplain - * #resolveType resolve} {@code ParameterizedType List<T>} to {@code List<String>}, and resolve - * {@code Map<T, Something>} to {@code Map<String, Something>} etc. Similarly, {@code formal} and - * {@code actual} can be {@code Map<K, V>} and {@code Map<String, Integer>} respectively, or they - * can be {@code E[]} and {@code String[]} respectively, or even any arbitrary combination - * thereof. - * - * @param formal The type whose type variables or itself is mapped to other type(s). It's almost - * always a bug if {@code formal} isn't a type variable and contains no type variable. Make - * sure you are passing the two parameters in the right order. - * @param actual The type that the formal type variable(s) are mapped to. It can be or contain yet - * other type variables, in which case these type variables will be further resolved if - * corresponding mappings exist in the current {@code TypeResolver} instance. - */ - public final TypeResolver where(Type formal, Type actual) { - Map<TypeVariable<?>, Type> mappings = Maps.newHashMap(); - populateTypeMappings(mappings, checkNotNull(formal), checkNotNull(actual)); - return where(mappings); - } - - /** Returns a new {@code TypeResolver} with {@code variable} mapping to {@code type}. */ - final TypeResolver where(Map<? extends TypeVariable<?>, ? extends Type> mappings) { - ImmutableMap.Builder<TypeVariable<?>, Type> builder = ImmutableMap.builder(); - builder.putAll(typeTable); - for (Map.Entry<? extends TypeVariable<?>, ? extends Type> mapping : mappings.entrySet()) { - TypeVariable<?> variable = mapping.getKey(); - Type type = mapping.getValue(); - checkArgument(!variable.equals(type), "Type variable %s bound to itself", variable); - builder.put(variable, type); - } - return new TypeResolver(builder.build()); - } - - private static void populateTypeMappings( - Map<TypeVariable<?>, Type> mappings, Type from, Type to) { - if (from.equals(to)) { - return; - } - if (from instanceof TypeVariable) { - mappings.put((TypeVariable<?>) from, to); - } else if (from instanceof GenericArrayType) { - populateTypeMappings(mappings, - ((GenericArrayType) from).getGenericComponentType(), - checkNonNullArgument(Types.getComponentType(to), "%s is not an array type.", to)); - } else if (from instanceof ParameterizedType) { - ParameterizedType fromParameterizedType = (ParameterizedType) from; - ParameterizedType toParameterizedType = expectArgument(ParameterizedType.class, to); - checkArgument(fromParameterizedType.getRawType().equals(toParameterizedType.getRawType()), - "Inconsistent raw type: %s vs. %s", from, to); - Type[] fromArgs = fromParameterizedType.getActualTypeArguments(); - Type[] toArgs = toParameterizedType.getActualTypeArguments(); - checkArgument(fromArgs.length == toArgs.length); - for (int i = 0; i < fromArgs.length; i++) { - populateTypeMappings(mappings, fromArgs[i], toArgs[i]); - } - } else if (from instanceof WildcardType) { - WildcardType fromWildcardType = (WildcardType) from; - WildcardType toWildcardType = expectArgument(WildcardType.class, to); - Type[] fromUpperBounds = fromWildcardType.getUpperBounds(); - Type[] toUpperBounds = toWildcardType.getUpperBounds(); - Type[] fromLowerBounds = fromWildcardType.getLowerBounds(); - Type[] toLowerBounds = toWildcardType.getLowerBounds(); - checkArgument( - fromUpperBounds.length == toUpperBounds.length - && fromLowerBounds.length == toLowerBounds.length, - "Incompatible type: %s vs. %s", from, to); - for (int i = 0; i < fromUpperBounds.length; i++) { - populateTypeMappings(mappings, fromUpperBounds[i], toUpperBounds[i]); - } - for (int i = 0; i < fromLowerBounds.length; i++) { - populateTypeMappings(mappings, fromLowerBounds[i], toLowerBounds[i]); - } - } else { - throw new IllegalArgumentException("No type mapping from " + from); - } - } - - /** - * Resolves all type variables in {@code type} and all downstream types and - * returns a corresponding type with type variables resolved. - */ - public final Type resolveType(Type type) { - checkNotNull(type); - if (type instanceof TypeVariable) { - return resolveTypeVariable((TypeVariable<?>) type); - } else if (type instanceof ParameterizedType) { - return resolveParameterizedType((ParameterizedType) type); - } else if (type instanceof GenericArrayType) { - return resolveGenericArrayType((GenericArrayType) type); - } else if (type instanceof WildcardType) { - WildcardType wildcardType = (WildcardType) type; - return new Types.WildcardTypeImpl( - resolveTypes(wildcardType.getLowerBounds()), - resolveTypes(wildcardType.getUpperBounds())); - } else { - // if Class<?>, no resolution needed, we are done. - return type; - } - } - - private Type[] resolveTypes(Type[] types) { - Type[] result = new Type[types.length]; - for (int i = 0; i < types.length; i++) { - result[i] = resolveType(types[i]); - } - return result; - } - - private Type resolveGenericArrayType(GenericArrayType type) { - Type componentType = resolveType(type.getGenericComponentType()); - return Types.newArrayType(componentType); - } - - private Type resolveTypeVariable(final TypeVariable<?> var) { - final TypeResolver unguarded = this; - TypeResolver guarded = new TypeResolver(typeTable) { - @Override Type resolveTypeVariable( - TypeVariable<?> intermediateVar, TypeResolver guardedResolver) { - if (intermediateVar.getGenericDeclaration().equals(var.getGenericDeclaration())) { - return intermediateVar; - } - return unguarded.resolveTypeVariable(intermediateVar, guardedResolver); - } - }; - return resolveTypeVariable(var, guarded); - } - - /** - * Resolves {@code var} using the encapsulated type mapping. If it maps to yet another - * non-reified type, {@code guardedResolver} is used to do further resolution, which doesn't try - * to resolve any type variable on generic declarations that are already being resolved. - */ - Type resolveTypeVariable(TypeVariable<?> var, TypeResolver guardedResolver) { - checkNotNull(guardedResolver); - Type type = typeTable.get(var); - if (type == null) { - Type[] bounds = var.getBounds(); - if (bounds.length == 0) { - return var; - } - return Types.newTypeVariable( - var.getGenericDeclaration(), - var.getName(), - guardedResolver.resolveTypes(bounds)); - } - return guardedResolver.resolveType(type); // in case the type is yet another type variable. - } - - private ParameterizedType resolveParameterizedType(ParameterizedType type) { - Type owner = type.getOwnerType(); - Type resolvedOwner = (owner == null) ? null : resolveType(owner); - Type resolvedRawType = resolveType(type.getRawType()); - - Type[] vars = type.getActualTypeArguments(); - Type[] resolvedArgs = new Type[vars.length]; - for (int i = 0; i < vars.length; i++) { - resolvedArgs[i] = resolveType(vars[i]); - } - return Types.newParameterizedTypeWithOwner( - resolvedOwner, (Class<?>) resolvedRawType, resolvedArgs); - } - - private static <T> T checkNonNullArgument(T arg, String format, Object... messageParams) { - checkArgument(arg != null, format, messageParams); - return arg; - } - - private static <T> T expectArgument(Class<T> type, Object arg) { - try { - return type.cast(arg); - } catch (ClassCastException e) { - throw new IllegalArgumentException(arg + " is not a " + type.getSimpleName()); - } - } - - private static final class TypeMappingIntrospector { - - private static final WildcardCapturer wildcardCapturer = new WildcardCapturer(); - - private final Map<TypeVariable<?>, Type> mappings = Maps.newHashMap(); - private final Set<Type> introspectedTypes = Sets.newHashSet(); - - /** - * Returns type mappings using type parameters and type arguments found in - * the generic superclass and the super interfaces of {@code contextClass}. - */ - static ImmutableMap<TypeVariable<?>, Type> getTypeMappings( - Type contextType) { - TypeMappingIntrospector introspector = new TypeMappingIntrospector(); - introspector.introspect(wildcardCapturer.capture(contextType)); - return ImmutableMap.copyOf(introspector.mappings); - } - - private void introspect(Type type) { - if (!introspectedTypes.add(type)) { - return; - } - if (type instanceof ParameterizedType) { - introspectParameterizedType((ParameterizedType) type); - } else if (type instanceof Class) { - introspectClass((Class<?>) type); - } else if (type instanceof TypeVariable) { - for (Type bound : ((TypeVariable<?>) type).getBounds()) { - introspect(bound); - } - } else if (type instanceof WildcardType) { - for (Type bound : ((WildcardType) type).getUpperBounds()) { - introspect(bound); - } - } - } - - private void introspectClass(Class<?> clazz) { - introspect(clazz.getGenericSuperclass()); - for (Type interfaceType : clazz.getGenericInterfaces()) { - introspect(interfaceType); - } - } - - private void introspectParameterizedType( - ParameterizedType parameterizedType) { - Class<?> rawClass = (Class<?>) parameterizedType.getRawType(); - TypeVariable<?>[] vars = rawClass.getTypeParameters(); - Type[] typeArgs = parameterizedType.getActualTypeArguments(); - checkState(vars.length == typeArgs.length); - for (int i = 0; i < vars.length; i++) { - map(vars[i], typeArgs[i]); - } - introspectClass(rawClass); - introspect(parameterizedType.getOwnerType()); - } - - private void map(final TypeVariable<?> var, final Type arg) { - if (mappings.containsKey(var)) { - // Mapping already established - // This is possible when following both superClass -> enclosingClass - // and enclosingclass -> superClass paths. - // Since we follow the path of superclass first, enclosing second, - // superclass mapping should take precedence. - return; - } - // First, check whether var -> arg forms a cycle - for (Type t = arg; t != null; t = mappings.get(t)) { - if (var.equals(t)) { - // cycle detected, remove the entire cycle from the mapping so that - // each type variable resolves deterministically to itself. - // Otherwise, a F -> T cycle will end up resolving both F and T - // nondeterministically to either F or T. - for (Type x = arg; x != null; x = mappings.remove(x)) {} - return; - } - } - mappings.put(var, arg); - } - } - - // This is needed when resolving types against a context with wildcards - // For example: - // class Holder<T> { - // void set(T data) {...} - // } - // Holder<List<?>> should *not* resolve the set() method to set(List<?> data). - // Instead, it should create a capture of the wildcard so that set() rejects any List<T>. - private static final class WildcardCapturer { - - private final AtomicInteger id = new AtomicInteger(); - - Type capture(Type type) { - checkNotNull(type); - if (type instanceof Class) { - return type; - } - if (type instanceof TypeVariable) { - return type; - } - if (type instanceof GenericArrayType) { - GenericArrayType arrayType = (GenericArrayType) type; - return Types.newArrayType(capture(arrayType.getGenericComponentType())); - } - if (type instanceof ParameterizedType) { - ParameterizedType parameterizedType = (ParameterizedType) type; - return Types.newParameterizedTypeWithOwner( - captureNullable(parameterizedType.getOwnerType()), - (Class<?>) parameterizedType.getRawType(), - capture(parameterizedType.getActualTypeArguments())); - } - if (type instanceof WildcardType) { - WildcardType wildcardType = (WildcardType) type; - Type[] lowerBounds = wildcardType.getLowerBounds(); - if (lowerBounds.length == 0) { // ? extends something changes to capture-of - Type[] upperBounds = wildcardType.getUpperBounds(); - String name = "capture#" + id.incrementAndGet() + "-of ? extends " - + Joiner.on('&').join(upperBounds); - return Types.newTypeVariable( - WildcardCapturer.class, name, wildcardType.getUpperBounds()); - } else { - // TODO(benyu): handle ? super T somehow. - return type; - } - } - throw new AssertionError("must have been one of the known types"); - } - - private Type captureNullable(@Nullable Type type) { - if (type == null) { - return null; - } - return capture(type); - } - - private Type[] capture(Type[] types) { - Type[] result = new Type[types.length]; - for (int i = 0; i < types.length; i++) { - result[i] = capture(types[i]); - } - return result; - } - } -} diff --git a/guava/src/com/google/common/reflect/TypeToInstanceMap.java b/guava/src/com/google/common/reflect/TypeToInstanceMap.java deleted file mode 100644 index 3b00820..0000000 --- a/guava/src/com/google/common/reflect/TypeToInstanceMap.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (C) 2012 The Guava Authors - * - * 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.common.reflect; - -import com.google.common.annotations.Beta; - -import java.util.Map; - -import javax.annotation.Nullable; - -/** - * A map, each entry of which maps a {@link TypeToken} to an instance of that type. - * In addition to implementing {@code Map}, the additional type-safe operations - * {@link #putInstance} and {@link #getInstance} are available. - * - * <p>Generally, implementations don't support {@link #put} and {@link #putAll} - * because there is no way to check an object at runtime to be an instance of a - * {@link TypeToken}. Instead, caller should use the type safe {@link #putInstance}. - * - * <p>Also, if caller suppresses unchecked warnings and passes in an {@code Iterable<String>} - * for type {@code Iterable<Integer>}, the map won't be able to detect and throw type error. - * - * <p>Like any other {@code Map<Class, Object>}, this map may contain entries - * for primitive types, and a primitive type and its corresponding wrapper type - * may map to different values. - * - * @param <B> the common supertype that all entries must share; often this is - * simply {@link Object} - * - * @author Ben Yu - * @since 13.0 - */ -@Beta -public interface TypeToInstanceMap<B> extends Map<TypeToken<? extends B>, B> { - - /** - * Returns the value the specified class is mapped to, or {@code null} if no - * entry for this class is present. This will only return a value that was - * bound to this specific class, not a value that may have been bound to a - * subtype. - * - * <p>{@code getInstance(Foo.class)} is equivalent to - * {@code getInstance(TypeToken.of(Foo.class))}. - */ - @Nullable - <T extends B> T getInstance(Class<T> type); - - /** - * Maps the specified class to the specified value. Does <i>not</i> associate - * this value with any of the class's supertypes. - * - * <p>{@code putInstance(Foo.class, foo)} is equivalent to - * {@code putInstance(TypeToken.of(Foo.class), foo)}. - * - * @return the value previously associated with this class (possibly {@code null}), - * or {@code null} if there was no previous entry. - */ - @Nullable - <T extends B> T putInstance(Class<T> type, @Nullable T value); - - /** - * Returns the value the specified type is mapped to, or {@code null} if no - * entry for this type is present. This will only return a value that was - * bound to this specific type, not a value that may have been bound to a subtype. - */ - @Nullable - <T extends B> T getInstance(TypeToken<T> type); - - /** - * Maps the specified type to the specified value. Does <i>not</i> associate - * this value with any of the type's supertypes. - * - * @return the value previously associated with this type (possibly {@code null}), - * or {@code null} if there was no previous entry. - */ - @Nullable - <T extends B> T putInstance(TypeToken<T> type, @Nullable T value); -} diff --git a/guava/src/com/google/common/reflect/TypeToken.java b/guava/src/com/google/common/reflect/TypeToken.java deleted file mode 100644 index 61469b5..0000000 --- a/guava/src/com/google/common/reflect/TypeToken.java +++ /dev/null @@ -1,1146 +0,0 @@ -/* - * Copyright (C) 2006 The Guava Authors - * - * 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.common.reflect; - -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; -import static com.google.common.base.Preconditions.checkState; - -import com.google.common.annotations.Beta; -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Predicate; -import com.google.common.collect.FluentIterable; -import com.google.common.collect.ForwardingSet; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Maps; -import com.google.common.collect.Ordering; - -import java.io.Serializable; -import java.lang.reflect.Constructor; -import java.lang.reflect.GenericArrayType; -import java.lang.reflect.Method; -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; -import java.lang.reflect.TypeVariable; -import java.lang.reflect.WildcardType; -import java.util.Arrays; -import java.util.Comparator; -import java.util.Map; -import java.util.Set; - -import javax.annotation.Nullable; - -/** - * A {@link Type} with generics. - * - * <p>Operations that are otherwise only available in {@link Class} are implemented to support - * {@code Type}, for example {@link #isAssignableFrom}, {@link #isArray} and {@link - * #getComponentType}. It also provides additional utilities such as {@link #getTypes} and {@link - * #resolveType} etc. - * - * <p>There are three ways to get a {@code TypeToken} instance: <ul> - * <li>Wrap a {@code Type} obtained via reflection. For example: {@code - * TypeToken.of(method.getGenericReturnType())}. - * <li>Capture a generic type with a (usually anonymous) subclass. For example: <pre> {@code - * - * new TypeToken<List<String>>() {} - * }</pre> - * Note that it's critical that the actual type argument is carried by a subclass. - * The following code is wrong because it only captures the {@code <T>} type variable - * of the {@code listType()} method signature; while {@code <String>} is lost in erasure: - * <pre> {@code - * - * class Util { - * static <T> TypeToken<List<T>> listType() { - * return new TypeToken<List<T>>() {}; - * } - * } - * - * TypeToken<List<String>> stringListType = Util.<String>listType(); - * }</pre> - * <li>Capture a generic type with a (usually anonymous) subclass and resolve it against - * a context class that knows what the type parameters are. For example: <pre> {@code - * abstract class IKnowMyType<T> { - * TypeToken<T> type = new TypeToken<T>(getClass()) {}; - * } - * new IKnowMyType<String>() {}.type => String - * }</pre> - * </ul> - * - * <p>{@code TypeToken} is serializable when no type variable is contained in the type. - * - * <p>Note to Guice users: {@code} TypeToken is similar to Guice's {@code TypeLiteral} class, - * but with one important difference: it supports non-reified types such as {@code T}, - * {@code List<T>} or even {@code List<? extends Number>}; while TypeLiteral does not. - * TypeToken is also serializable and offers numerous additional utility methods. - * - * @author Bob Lee - * @author Sven Mawson - * @author Ben Yu - * @since 12.0 - */ -@Beta -@SuppressWarnings("serial") // SimpleTypeToken is the serialized form. -public abstract class TypeToken<T> extends TypeCapture<T> implements Serializable { - - private final Type runtimeType; - - /** Resolver for resolving types with {@link #runtimeType} as context. */ - private transient TypeResolver typeResolver; - - /** - * Constructs a new type token of {@code T}. - * - * <p>Clients create an empty anonymous subclass. Doing so embeds the type - * parameter in the anonymous class's type hierarchy so we can reconstitute - * it at runtime despite erasure. - * - * <p>For example: <pre> {@code - * - * TypeToken<List<String>> t = new TypeToken<List<String>>() {}; - * }</pre> - */ - protected TypeToken() { - this.runtimeType = capture(); - checkState(!(runtimeType instanceof TypeVariable), - "Cannot construct a TypeToken for a type variable.\n" + - "You probably meant to call new TypeToken<%s>(getClass()) " + - "that can resolve the type variable for you.\n" + - "If you do need to create a TypeToken of a type variable, " + - "please use TypeToken.of() instead.", runtimeType); - } - - /** - * Constructs a new type token of {@code T} while resolving free type variables in the context of - * {@code declaringClass}. - * - * <p>Clients create an empty anonymous subclass. Doing so embeds the type - * parameter in the anonymous class's type hierarchy so we can reconstitute - * it at runtime despite erasure. - * - * <p>For example: <pre> {@code - * - * abstract class IKnowMyType<T> { - * TypeToken<T> getMyType() { - * return new TypeToken<T>(getClass()) {}; - * } - * } - * - * new IKnowMyType<String>() {}.getMyType() => String - * }</pre> - */ - protected TypeToken(Class<?> declaringClass) { - Type captured = super.capture(); - if (captured instanceof Class) { - this.runtimeType = captured; - } else { - this.runtimeType = of(declaringClass).resolveType(captured).runtimeType; - } - } - - private TypeToken(Type type) { - this.runtimeType = checkNotNull(type); - } - - /** Returns an instance of type token that wraps {@code type}. */ - public static <T> TypeToken<T> of(Class<T> type) { - return new SimpleTypeToken<T>(type); - } - - /** Returns an instance of type token that wraps {@code type}. */ - public static TypeToken<?> of(Type type) { - return new SimpleTypeToken<Object>(type); - } - - /** - * Returns the raw type of {@code T}. Formally speaking, if {@code T} is returned by - * {@link java.lang.reflect.Method#getGenericReturnType}, the raw type is what's returned by - * {@link java.lang.reflect.Method#getReturnType} of the same method object. Specifically: - * <ul> - * <li>If {@code T} is a {@code Class} itself, {@code T} itself is returned. - * <li>If {@code T} is a {@link ParameterizedType}, the raw type of the parameterized type is - * returned. - * <li>If {@code T} is a {@link GenericArrayType}, the returned type is the corresponding array - * class. For example: {@code List<Integer>[] => List[]}. - * <li>If {@code T} is a type variable or a wildcard type, the raw type of the first upper bound - * is returned. For example: {@code <X extends Foo> => Foo}. - * </ul> - */ - public final Class<? super T> getRawType() { - Class<?> rawType = getRawType(runtimeType); - @SuppressWarnings("unchecked") // raw type is |T| - Class<? super T> result = (Class<? super T>) rawType; - return result; - } - - /** - * Returns the raw type of the class or parameterized type; if {@code T} is type variable or - * wildcard type, the raw types of all its upper bounds are returned. - */ - private ImmutableSet<Class<? super T>> getImmediateRawTypes() { - // Cast from ImmutableSet<Class<?>> to ImmutableSet<Class<? super T>> - @SuppressWarnings({"unchecked", "rawtypes"}) - ImmutableSet<Class<? super T>> result = (ImmutableSet) getRawTypes(runtimeType); - return result; - } - - /** Returns the represented type. */ - public final Type getType() { - return runtimeType; - } - - /** - * Returns a new {@code TypeToken} where type variables represented by {@code typeParam} - * are substituted by {@code typeArg}. For example, it can be used to construct - * {@code Map<K, V>} for any {@code K} and {@code V} type: <pre> {@code - * - * static <K, V> TypeToken<Map<K, V>> mapOf( - * TypeToken<K> keyType, TypeToken<V> valueType) { - * return new TypeToken<Map<K, V>>() {} - * .where(new TypeParameter<K>() {}, keyType) - * .where(new TypeParameter<V>() {}, valueType); - * } - * }</pre> - * - * @param <X> The parameter type - * @param typeParam the parameter type variable - * @param typeArg the actual type to substitute - */ - public final <X> TypeToken<T> where(TypeParameter<X> typeParam, TypeToken<X> typeArg) { - TypeResolver resolver = new TypeResolver() - .where(ImmutableMap.of(typeParam.typeVariable, typeArg.runtimeType)); - // If there's any type error, we'd report now rather than later. - return new SimpleTypeToken<T>(resolver.resolveType(runtimeType)); - } - - /** - * Returns a new {@code TypeToken} where type variables represented by {@code typeParam} - * are substituted by {@code typeArg}. For example, it can be used to construct - * {@code Map<K, V>} for any {@code K} and {@code V} type: <pre> {@code - * - * static <K, V> TypeToken<Map<K, V>> mapOf( - * Class<K> keyType, Class<V> valueType) { - * return new TypeToken<Map<K, V>>() {} - * .where(new TypeParameter<K>() {}, keyType) - * .where(new TypeParameter<V>() {}, valueType); - * } - * }</pre> - * - * @param <X> The parameter type - * @param typeParam the parameter type variable - * @param typeArg the actual type to substitute - */ - public final <X> TypeToken<T> where(TypeParameter<X> typeParam, Class<X> typeArg) { - return where(typeParam, of(typeArg)); - } - - /** - * Resolves the given {@code type} against the type context represented by this type. - * For example: <pre> {@code - * - * new TypeToken<List<String>>() {}.resolveType( - * List.class.getMethod("get", int.class).getGenericReturnType()) - * => String.class - * }</pre> - */ - public final TypeToken<?> resolveType(Type type) { - checkNotNull(type); - TypeResolver resolver = typeResolver; - if (resolver == null) { - resolver = (typeResolver = TypeResolver.accordingTo(runtimeType)); - } - return of(resolver.resolveType(type)); - } - - private Type[] resolveInPlace(Type[] types) { - for (int i = 0; i < types.length; i++) { - types[i] = resolveType(types[i]).getType(); - } - return types; - } - - private TypeToken<?> resolveSupertype(Type type) { - TypeToken<?> supertype = resolveType(type); - // super types' type mapping is a subset of type mapping of this type. - supertype.typeResolver = typeResolver; - return supertype; - } - - /** - * Returns the generic superclass of this type or {@code null} if the type represents - * {@link Object} or an interface. This method is similar but different from {@link - * Class#getGenericSuperclass}. For example, {@code - * new TypeToken<StringArrayList>() {}.getGenericSuperclass()} will return {@code - * new TypeToken<ArrayList<String>>() {}}; while {@code - * StringArrayList.class.getGenericSuperclass()} will return {@code ArrayList<E>}, where {@code E} - * is the type variable declared by class {@code ArrayList}. - * - * <p>If this type is a type variable or wildcard, its first upper bound is examined and returned - * if the bound is a class or extends from a class. This means that the returned type could be a - * type variable too. - */ - @Nullable - final TypeToken<? super T> getGenericSuperclass() { - if (runtimeType instanceof TypeVariable) { - // First bound is always the super class, if one exists. - return boundAsSuperclass(((TypeVariable<?>) runtimeType).getBounds()[0]); - } - if (runtimeType instanceof WildcardType) { - // wildcard has one and only one upper bound. - return boundAsSuperclass(((WildcardType) runtimeType).getUpperBounds()[0]); - } - Type superclass = getRawType().getGenericSuperclass(); - if (superclass == null) { - return null; - } - @SuppressWarnings("unchecked") // super class of T - TypeToken<? super T> superToken = (TypeToken<? super T>) resolveSupertype(superclass); - return superToken; - } - - @Nullable private TypeToken<? super T> boundAsSuperclass(Type bound) { - TypeToken<?> token = of(bound); - if (token.getRawType().isInterface()) { - return null; - } - @SuppressWarnings("unchecked") // only upper bound of T is passed in. - TypeToken<? super T> superclass = (TypeToken<? super T>) token; - return superclass; - } - - /** - * Returns the generic interfaces that this type directly {@code implements}. This method is - * similar but different from {@link Class#getGenericInterfaces()}. For example, {@code - * new TypeToken<List<String>>() {}.getGenericInterfaces()} will return a list that contains - * {@code new TypeToken<Iterable<String>>() {}}; while {@code List.class.getGenericInterfaces()} - * will return an array that contains {@code Iterable<T>}, where the {@code T} is the type - * variable declared by interface {@code Iterable}. - * - * <p>If this type is a type variable or wildcard, its upper bounds are examined and those that - * are either an interface or upper-bounded only by interfaces are returned. This means that the - * returned types could include type variables too. - */ - final ImmutableList<TypeToken<? super T>> getGenericInterfaces() { - if (runtimeType instanceof TypeVariable) { - return boundsAsInterfaces(((TypeVariable<?>) runtimeType).getBounds()); - } - if (runtimeType instanceof WildcardType) { - return boundsAsInterfaces(((WildcardType) runtimeType).getUpperBounds()); - } - ImmutableList.Builder<TypeToken<? super T>> builder = ImmutableList.builder(); - for (Type interfaceType : getRawType().getGenericInterfaces()) { - @SuppressWarnings("unchecked") // interface of T - TypeToken<? super T> resolvedInterface = (TypeToken<? super T>) - resolveSupertype(interfaceType); - builder.add(resolvedInterface); - } - return builder.build(); - } - - private ImmutableList<TypeToken<? super T>> boundsAsInterfaces(Type[] bounds) { - ImmutableList.Builder<TypeToken<? super T>> builder = ImmutableList.builder(); - for (Type bound : bounds) { - @SuppressWarnings("unchecked") // upper bound of T - TypeToken<? super T> boundType = (TypeToken<? super T>) of(bound); - if (boundType.getRawType().isInterface()) { - builder.add(boundType); - } - } - return builder.build(); - } - - /** - * Returns the set of interfaces and classes that this type is or is a subtype of. The returned - * types are parameterized with proper type arguments. - * - * <p>Subtypes are always listed before supertypes. But the reverse is not true. A type isn't - * necessarily a subtype of all the types following. Order between types without subtype - * relationship is arbitrary and not guaranteed. - * - * <p>If this type is a type variable or wildcard, upper bounds that are themselves type variables - * aren't included (their super interfaces and superclasses are). - */ - public final TypeSet getTypes() { - return new TypeSet(); - } - - /** - * Returns the generic form of {@code superclass}. For example, if this is - * {@code ArrayList<String>}, {@code Iterable<String>} is returned given the - * input {@code Iterable.class}. - */ - public final TypeToken<? super T> getSupertype(Class<? super T> superclass) { - checkArgument(superclass.isAssignableFrom(getRawType()), - "%s is not a super class of %s", superclass, this); - if (runtimeType instanceof TypeVariable) { - return getSupertypeFromUpperBounds(superclass, ((TypeVariable<?>) runtimeType).getBounds()); - } - if (runtimeType instanceof WildcardType) { - return getSupertypeFromUpperBounds(superclass, ((WildcardType) runtimeType).getUpperBounds()); - } - if (superclass.isArray()) { - return getArraySupertype(superclass); - } - @SuppressWarnings("unchecked") // resolved supertype - TypeToken<? super T> supertype = (TypeToken<? super T>) - resolveSupertype(toGenericType(superclass).runtimeType); - return supertype; - } - - /** - * Returns subtype of {@code this} with {@code subclass} as the raw class. - * For example, if this is {@code Iterable<String>} and {@code subclass} is {@code List}, - * {@code List<String>} is returned. - */ - public final TypeToken<? extends T> getSubtype(Class<?> subclass) { - checkArgument(!(runtimeType instanceof TypeVariable), - "Cannot get subtype of type variable <%s>", this); - if (runtimeType instanceof WildcardType) { - return getSubtypeFromLowerBounds(subclass, ((WildcardType) runtimeType).getLowerBounds()); - } - checkArgument(getRawType().isAssignableFrom(subclass), - "%s isn't a subclass of %s", subclass, this); - // unwrap array type if necessary - if (isArray()) { - return getArraySubtype(subclass); - } - @SuppressWarnings("unchecked") // guarded by the isAssignableFrom() statement above - TypeToken<? extends T> subtype = (TypeToken<? extends T>) - of(resolveTypeArgsForSubclass(subclass)); - return subtype; - } - - /** Returns true if this type is assignable from the given {@code type}. */ - public final boolean isAssignableFrom(TypeToken<?> type) { - return isAssignableFrom(type.runtimeType); - } - - /** Check if this type is assignable from the given {@code type}. */ - public final boolean isAssignableFrom(Type type) { - return isAssignable(checkNotNull(type), runtimeType); - } - - /** - * Returns true if this type is known to be an array type, such as {@code int[]}, {@code T[]}, - * {@code <? extends Map<String, Integer>[]>} etc. - */ - public final boolean isArray() { - return getComponentType() != null; - } - - /** - * Returns the array component type if this type represents an array ({@code int[]}, {@code T[]}, - * {@code <? extends Map<String, Integer>[]>} etc.), or else {@code null} is returned. - */ - @Nullable public final TypeToken<?> getComponentType() { - Type componentType = Types.getComponentType(runtimeType); - if (componentType == null) { - return null; - } - return of(componentType); - } - - /** - * Returns the {@link Invokable} for {@code method}, which must be a member of {@code T}. - * - * @since 14.0 - */ - public final Invokable<T, Object> method(Method method) { - checkArgument(of(method.getDeclaringClass()).isAssignableFrom(this), - "%s not declared by %s", method, this); - return new Invokable.MethodInvokable<T>(method) { - @Override Type getGenericReturnType() { - return resolveType(super.getGenericReturnType()).getType(); - } - @Override Type[] getGenericParameterTypes() { - return resolveInPlace(super.getGenericParameterTypes()); - } - @Override Type[] getGenericExceptionTypes() { - return resolveInPlace(super.getGenericExceptionTypes()); - } - @Override public TypeToken<T> getOwnerType() { - return TypeToken.this; - } - }; - } - - /** - * Returns the {@link Invokable} for {@code constructor}, which must be a member of {@code T}. - * - * @since 14.0 - */ - public final Invokable<T, T> constructor(Constructor<?> constructor) { - checkArgument(constructor.getDeclaringClass() == getRawType(), - "%s not declared by %s", constructor, getRawType()); - return new Invokable.ConstructorInvokable<T>(constructor) { - @Override Type getGenericReturnType() { - return resolveType(super.getGenericReturnType()).getType(); - } - @Override Type[] getGenericParameterTypes() { - return resolveInPlace(super.getGenericParameterTypes()); - } - @Override Type[] getGenericExceptionTypes() { - return resolveInPlace(super.getGenericExceptionTypes()); - } - @Override public TypeToken<T> getOwnerType() { - return TypeToken.this; - } - }; - } - - /** - * The set of interfaces and classes that {@code T} is or is a subtype of. {@link Object} is not - * included in the set if this type is an interface. - */ - public class TypeSet extends ForwardingSet<TypeToken<? super T>> implements Serializable { - - private transient ImmutableSet<TypeToken<? super T>> types; - - TypeSet() {} - - /** Returns the types that are interfaces implemented by this type. */ - public TypeSet interfaces() { - return new InterfaceSet(this); - } - - /** Returns the types that are classes. */ - public TypeSet classes() { - return new ClassSet(); - } - - @Override protected Set<TypeToken<? super T>> delegate() { - ImmutableSet<TypeToken<? super T>> filteredTypes = types; - if (filteredTypes == null) { - // Java has no way to express ? super T when we parameterize TypeToken vs. Class. - @SuppressWarnings({"unchecked", "rawtypes"}) - ImmutableList<TypeToken<? super T>> collectedTypes = (ImmutableList) - TypeCollector.FOR_GENERIC_TYPE.collectTypes(TypeToken.this); - return (types = FluentIterable.from(collectedTypes) - .filter(TypeFilter.IGNORE_TYPE_VARIABLE_OR_WILDCARD) - .toSet()); - } else { - return filteredTypes; - } - } - - /** Returns the raw types of the types in this set, in the same order. */ - public Set<Class<? super T>> rawTypes() { - // Java has no way to express ? super T when we parameterize TypeToken vs. Class. - @SuppressWarnings({"unchecked", "rawtypes"}) - ImmutableList<Class<? super T>> collectedTypes = (ImmutableList) - TypeCollector.FOR_RAW_TYPE.collectTypes(getImmediateRawTypes()); - return ImmutableSet.copyOf(collectedTypes); - } - - private static final long serialVersionUID = 0; - } - - private final class InterfaceSet extends TypeSet { - - private transient final TypeSet allTypes; - private transient ImmutableSet<TypeToken<? super T>> interfaces; - - InterfaceSet(TypeSet allTypes) { - this.allTypes = allTypes; - } - - @Override protected Set<TypeToken<? super T>> delegate() { - ImmutableSet<TypeToken<? super T>> result = interfaces; - if (result == null) { - return (interfaces = FluentIterable.from(allTypes) - .filter(TypeFilter.INTERFACE_ONLY) - .toSet()); - } else { - return result; - } - } - - @Override public TypeSet interfaces() { - return this; - } - - @Override public Set<Class<? super T>> rawTypes() { - // Java has no way to express ? super T when we parameterize TypeToken vs. Class. - @SuppressWarnings({"unchecked", "rawtypes"}) - ImmutableList<Class<? super T>> collectedTypes = (ImmutableList) - TypeCollector.FOR_RAW_TYPE.collectTypes(getImmediateRawTypes()); - return FluentIterable.from(collectedTypes) - .filter(new Predicate<Class<?>>() { - @Override public boolean apply(Class<?> type) { - return type.isInterface(); - } - }) - .toSet(); - } - - @Override public TypeSet classes() { - throw new UnsupportedOperationException("interfaces().classes() not supported."); - } - - private Object readResolve() { - return getTypes().interfaces(); - } - - private static final long serialVersionUID = 0; - } - - private final class ClassSet extends TypeSet { - - private transient ImmutableSet<TypeToken<? super T>> classes; - - @Override protected Set<TypeToken<? super T>> delegate() { - ImmutableSet<TypeToken<? super T>> result = classes; - if (result == null) { - @SuppressWarnings({"unchecked", "rawtypes"}) - ImmutableList<TypeToken<? super T>> collectedTypes = (ImmutableList) - TypeCollector.FOR_GENERIC_TYPE.classesOnly().collectTypes(TypeToken.this); - return (classes = FluentIterable.from(collectedTypes) - .filter(TypeFilter.IGNORE_TYPE_VARIABLE_OR_WILDCARD) - .toSet()); - } else { - return result; - } - } - - @Override public TypeSet classes() { - return this; - } - - @Override public Set<Class<? super T>> rawTypes() { - // Java has no way to express ? super T when we parameterize TypeToken vs. Class. - @SuppressWarnings({"unchecked", "rawtypes"}) - ImmutableList<Class<? super T>> collectedTypes = (ImmutableList) - TypeCollector.FOR_RAW_TYPE.classesOnly().collectTypes(getImmediateRawTypes()); - return ImmutableSet.copyOf(collectedTypes); - } - - @Override public TypeSet interfaces() { - throw new UnsupportedOperationException("classes().interfaces() not supported."); - } - - private Object readResolve() { - return getTypes().classes(); - } - - private static final long serialVersionUID = 0; - } - - private enum TypeFilter implements Predicate<TypeToken<?>> { - - IGNORE_TYPE_VARIABLE_OR_WILDCARD { - @Override public boolean apply(TypeToken<?> type) { - return !(type.runtimeType instanceof TypeVariable - || type.runtimeType instanceof WildcardType); - } - }, - INTERFACE_ONLY { - @Override public boolean apply(TypeToken<?> type) { - return type.getRawType().isInterface(); - } - } - } - - /** - * Returns true if {@code o} is another {@code TypeToken} that represents the same {@link Type}. - */ - @Override public boolean equals(@Nullable Object o) { - if (o instanceof TypeToken) { - TypeToken<?> that = (TypeToken<?>) o; - return runtimeType.equals(that.runtimeType); - } - return false; - } - - @Override public int hashCode() { - return runtimeType.hashCode(); - } - - @Override public String toString() { - return Types.toString(runtimeType); - } - - /** Implemented to support serialization of subclasses. */ - protected Object writeReplace() { - // TypeResolver just transforms the type to our own impls that are Serializable - // except TypeVariable. - return of(new TypeResolver().resolveType(runtimeType)); - } - - /** - * Ensures that this type token doesn't contain type variables, which can cause unchecked type - * errors for callers like {@link TypeToInstanceMap}. - */ - final TypeToken<T> rejectTypeVariables() { - checkArgument(!Types.containsTypeVariable(runtimeType), - "%s contains a type variable and is not safe for the operation"); - return this; - } - - private static boolean isAssignable(Type from, Type to) { - if (to.equals(from)) { - return true; - } - if (to instanceof WildcardType) { - return isAssignableToWildcardType(from, (WildcardType) to); - } - // if "from" is type variable, it's assignable if any of its "extends" - // bounds is assignable to "to". - if (from instanceof TypeVariable) { - return isAssignableFromAny(((TypeVariable<?>) from).getBounds(), to); - } - // if "from" is wildcard, it'a assignable to "to" if any of its "extends" - // bounds is assignable to "to". - if (from instanceof WildcardType) { - return isAssignableFromAny(((WildcardType) from).getUpperBounds(), to); - } - if (from instanceof GenericArrayType) { - return isAssignableFromGenericArrayType((GenericArrayType) from, to); - } - // Proceed to regular Type assignability check - if (to instanceof Class) { - return isAssignableToClass(from, (Class<?>) to); - } else if (to instanceof ParameterizedType) { - return isAssignableToParameterizedType(from, (ParameterizedType) to); - } else if (to instanceof GenericArrayType) { - return isAssignableToGenericArrayType(from, (GenericArrayType) to); - } else { // to instanceof TypeVariable - return false; - } - } - - private static boolean isAssignableFromAny(Type[] fromTypes, Type to) { - for (Type from : fromTypes) { - if (isAssignable(from, to)) { - return true; - } - } - return false; - } - - private static boolean isAssignableToClass(Type from, Class<?> to) { - return to.isAssignableFrom(getRawType(from)); - } - - private static boolean isAssignableToWildcardType( - Type from, WildcardType to) { - // if "to" is <? extends Foo>, "from" can be: - // Foo, SubFoo, <? extends Foo>, <? extends SubFoo>, <T extends Foo> or - // <T extends SubFoo>. - // if "to" is <? super Foo>, "from" can be: - // Foo, SuperFoo, <? super Foo> or <? super SuperFoo>. - return isAssignable(from, supertypeBound(to)) && isAssignableBySubtypeBound(from, to); - } - - private static boolean isAssignableBySubtypeBound(Type from, WildcardType to) { - Type toSubtypeBound = subtypeBound(to); - if (toSubtypeBound == null) { - return true; - } - Type fromSubtypeBound = subtypeBound(from); - if (fromSubtypeBound == null) { - return false; - } - return isAssignable(toSubtypeBound, fromSubtypeBound); - } - - private static boolean isAssignableToParameterizedType(Type from, ParameterizedType to) { - Class<?> matchedClass = getRawType(to); - if (!matchedClass.isAssignableFrom(getRawType(from))) { - return false; - } - Type[] typeParams = matchedClass.getTypeParameters(); - Type[] toTypeArgs = to.getActualTypeArguments(); - TypeToken<?> fromTypeToken = of(from); - for (int i = 0; i < typeParams.length; i++) { - // If "to" is "List<? extends CharSequence>" - // and "from" is StringArrayList, - // First step is to figure out StringArrayList "is-a" List<E> and <E> is - // String. - // typeParams[0] is E and fromTypeToken.get(typeParams[0]) will resolve to - // String. - // String is then matched against <? extends CharSequence>. - Type fromTypeArg = fromTypeToken.resolveType(typeParams[i]).runtimeType; - if (!matchTypeArgument(fromTypeArg, toTypeArgs[i])) { - return false; - } - } - return true; - } - - private static boolean isAssignableToGenericArrayType(Type from, GenericArrayType to) { - if (from instanceof Class) { - Class<?> fromClass = (Class<?>) from; - if (!fromClass.isArray()) { - return false; - } - return isAssignable(fromClass.getComponentType(), to.getGenericComponentType()); - } else if (from instanceof GenericArrayType) { - GenericArrayType fromArrayType = (GenericArrayType) from; - return isAssignable(fromArrayType.getGenericComponentType(), to.getGenericComponentType()); - } else { - return false; - } - } - - private static boolean isAssignableFromGenericArrayType(GenericArrayType from, Type to) { - if (to instanceof Class) { - Class<?> toClass = (Class<?>) to; - if (!toClass.isArray()) { - return toClass == Object.class; // any T[] is assignable to Object - } - return isAssignable(from.getGenericComponentType(), toClass.getComponentType()); - } else if (to instanceof GenericArrayType) { - GenericArrayType toArrayType = (GenericArrayType) to; - return isAssignable(from.getGenericComponentType(), toArrayType.getGenericComponentType()); - } else { - return false; - } - } - - private static boolean matchTypeArgument(Type from, Type to) { - if (from.equals(to)) { - return true; - } - if (to instanceof WildcardType) { - return isAssignableToWildcardType(from, (WildcardType) to); - } - return false; - } - - private static Type supertypeBound(Type type) { - if (type instanceof WildcardType) { - return supertypeBound((WildcardType) type); - } - return type; - } - - private static Type supertypeBound(WildcardType type) { - Type[] upperBounds = type.getUpperBounds(); - if (upperBounds.length == 1) { - return supertypeBound(upperBounds[0]); - } else if (upperBounds.length == 0) { - return Object.class; - } else { - throw new AssertionError( - "There should be at most one upper bound for wildcard type: " + type); - } - } - - @Nullable private static Type subtypeBound(Type type) { - if (type instanceof WildcardType) { - return subtypeBound((WildcardType) type); - } else { - return type; - } - } - - @Nullable private static Type subtypeBound(WildcardType type) { - Type[] lowerBounds = type.getLowerBounds(); - if (lowerBounds.length == 1) { - return subtypeBound(lowerBounds[0]); - } else if (lowerBounds.length == 0) { - return null; - } else { - throw new AssertionError( - "Wildcard should have at most one lower bound: " + type); - } - } - - @VisibleForTesting static Class<?> getRawType(Type type) { - // For wildcard or type variable, the first bound determines the runtime type. - return getRawTypes(type).iterator().next(); - } - - @VisibleForTesting static ImmutableSet<Class<?>> getRawTypes(Type type) { - if (type instanceof Class) { - return ImmutableSet.<Class<?>>of((Class<?>) type); - } else if (type instanceof ParameterizedType) { - ParameterizedType parameterizedType = (ParameterizedType) type; - // JDK implementation declares getRawType() to return Class<?>: http://goo.gl/YzaEd - return ImmutableSet.<Class<?>>of((Class<?>) parameterizedType.getRawType()); - } else if (type instanceof GenericArrayType) { - GenericArrayType genericArrayType = (GenericArrayType) type; - return ImmutableSet.<Class<?>>of(Types.getArrayClass( - getRawType(genericArrayType.getGenericComponentType()))); - } else if (type instanceof TypeVariable) { - return getRawTypes(((TypeVariable<?>) type).getBounds()); - } else if (type instanceof WildcardType) { - return getRawTypes(((WildcardType) type).getUpperBounds()); - } else { - throw new AssertionError(type + " unsupported"); - } - } - - private static ImmutableSet<Class<?>> getRawTypes(Type[] types) { - ImmutableSet.Builder<Class<?>> builder = ImmutableSet.builder(); - for (Type type : types) { - builder.addAll(getRawTypes(type)); - } - return builder.build(); - } - - /** - * Returns the type token representing the generic type declaration of {@code cls}. For example: - * {@code TypeToken.getGenericType(Iterable.class)} returns {@code Iterable<T>}. - * - * <p>If {@code cls} isn't parameterized and isn't a generic array, the type token of the class is - * returned. - */ - @VisibleForTesting static <T> TypeToken<? extends T> toGenericType(Class<T> cls) { - if (cls.isArray()) { - Type arrayOfGenericType = Types.newArrayType( - // If we are passed with int[].class, don't turn it to GenericArrayType - toGenericType(cls.getComponentType()).runtimeType); - @SuppressWarnings("unchecked") // array is covariant - TypeToken<? extends T> result = (TypeToken<? extends T>) of(arrayOfGenericType); - return result; - } - TypeVariable<Class<T>>[] typeParams = cls.getTypeParameters(); - if (typeParams.length > 0) { - @SuppressWarnings("unchecked") // Like, it's Iterable<T> for Iterable.class - TypeToken<? extends T> type = (TypeToken<? extends T>) - of(Types.newParameterizedType(cls, typeParams)); - return type; - } else { - return of(cls); - } - } - - private TypeToken<? super T> getSupertypeFromUpperBounds( - Class<? super T> supertype, Type[] upperBounds) { - for (Type upperBound : upperBounds) { - @SuppressWarnings("unchecked") // T's upperbound is <? super T>. - TypeToken<? super T> bound = (TypeToken<? super T>) of(upperBound); - if (of(supertype).isAssignableFrom(bound)) { - @SuppressWarnings({"rawtypes", "unchecked"}) // guarded by the isAssignableFrom check. - TypeToken<? super T> result = bound.getSupertype((Class) supertype); - return result; - } - } - throw new IllegalArgumentException(supertype + " isn't a super type of " + this); - } - - private TypeToken<? extends T> getSubtypeFromLowerBounds(Class<?> subclass, Type[] lowerBounds) { - for (Type lowerBound : lowerBounds) { - @SuppressWarnings("unchecked") // T's lower bound is <? extends T> - TypeToken<? extends T> bound = (TypeToken<? extends T>) of(lowerBound); - // Java supports only one lowerbound anyway. - return bound.getSubtype(subclass); - } - throw new IllegalArgumentException(subclass + " isn't a subclass of " + this); - } - - private TypeToken<? super T> getArraySupertype(Class<? super T> supertype) { - // with component type, we have lost generic type information - // Use raw type so that compiler allows us to call getSupertype() - @SuppressWarnings("rawtypes") - TypeToken componentType = checkNotNull(getComponentType(), - "%s isn't a super type of %s", supertype, this); - // array is covariant. component type is super type, so is the array type. - @SuppressWarnings("unchecked") // going from raw type back to generics - TypeToken<?> componentSupertype = componentType.getSupertype(supertype.getComponentType()); - @SuppressWarnings("unchecked") // component type is super type, so is array type. - TypeToken<? super T> result = (TypeToken<? super T>) - // If we are passed with int[].class, don't turn it to GenericArrayType - of(newArrayClassOrGenericArrayType(componentSupertype.runtimeType)); - return result; - } - - private TypeToken<? extends T> getArraySubtype(Class<?> subclass) { - // array is covariant. component type is subtype, so is the array type. - TypeToken<?> componentSubtype = getComponentType() - .getSubtype(subclass.getComponentType()); - @SuppressWarnings("unchecked") // component type is subtype, so is array type. - TypeToken<? extends T> result = (TypeToken<? extends T>) - // If we are passed with int[].class, don't turn it to GenericArrayType - of(newArrayClassOrGenericArrayType(componentSubtype.runtimeType)); - return result; - } - - private Type resolveTypeArgsForSubclass(Class<?> subclass) { - if (runtimeType instanceof Class) { - // no resolution needed - return subclass; - } - // class Base<A, B> {} - // class Sub<X, Y> extends Base<X, Y> {} - // Base<String, Integer>.subtype(Sub.class): - - // Sub<X, Y>.getSupertype(Base.class) => Base<X, Y> - // => X=String, Y=Integer - // => Sub<X, Y>=Sub<String, Integer> - TypeToken<?> genericSubtype = toGenericType(subclass); - @SuppressWarnings({"rawtypes", "unchecked"}) // subclass isn't <? extends T> - Type supertypeWithArgsFromSubtype = genericSubtype - .getSupertype((Class) getRawType()) - .runtimeType; - return new TypeResolver().where(supertypeWithArgsFromSubtype, runtimeType) - .resolveType(genericSubtype.runtimeType); - } - - /** - * Creates an array class if {@code componentType} is a class, or else, a - * {@link GenericArrayType}. This is what Java7 does for generic array type - * parameters. - */ - private static Type newArrayClassOrGenericArrayType(Type componentType) { - return Types.JavaVersion.JAVA7.newArrayType(componentType); - } - - private static final class SimpleTypeToken<T> extends TypeToken<T> { - - SimpleTypeToken(Type type) { - super(type); - } - - private static final long serialVersionUID = 0; - } - - /** - * Collects parent types from a sub type. - * - * @param <K> The type "kind". Either a TypeToken, or Class. - */ - private abstract static class TypeCollector<K> { - - static final TypeCollector<TypeToken<?>> FOR_GENERIC_TYPE = - new TypeCollector<TypeToken<?>>() { - @Override Class<?> getRawType(TypeToken<?> type) { - return type.getRawType(); - } - - @Override Iterable<? extends TypeToken<?>> getInterfaces(TypeToken<?> type) { - return type.getGenericInterfaces(); - } - - @Nullable - @Override TypeToken<?> getSuperclass(TypeToken<?> type) { - return type.getGenericSuperclass(); - } - }; - - static final TypeCollector<Class<?>> FOR_RAW_TYPE = - new TypeCollector<Class<?>>() { - @Override Class<?> getRawType(Class<?> type) { - return type; - } - - @Override Iterable<? extends Class<?>> getInterfaces(Class<?> type) { - return Arrays.asList(type.getInterfaces()); - } - - @Nullable - @Override Class<?> getSuperclass(Class<?> type) { - return type.getSuperclass(); - } - }; - - /** For just classes, we don't have to traverse interfaces. */ - final TypeCollector<K> classesOnly() { - return new ForwardingTypeCollector<K>(this) { - @Override Iterable<? extends K> getInterfaces(K type) { - return ImmutableSet.of(); - } - @Override ImmutableList<K> collectTypes(Iterable<? extends K> types) { - ImmutableList.Builder<K> builder = ImmutableList.builder(); - for (K type : types) { - if (!getRawType(type).isInterface()) { - builder.add(type); - } - } - return super.collectTypes(builder.build()); - } - }; - } - - final ImmutableList<K> collectTypes(K type) { - return collectTypes(ImmutableList.of(type)); - } - - ImmutableList<K> collectTypes(Iterable<? extends K> types) { - // type -> order number. 1 for Object, 2 for anything directly below, so on so forth. - Map<K, Integer> map = Maps.newHashMap(); - for (K type : types) { - collectTypes(type, map); - } - return sortKeysByValue(map, Ordering.natural().reverse()); - } - - /** Collects all types to map, and returns the total depth from T up to Object. */ - private int collectTypes(K type, Map<? super K, Integer> map) { - Integer existing = map.get(this); - if (existing != null) { - // short circuit: if set contains type it already contains its supertypes - return existing; - } - int aboveMe = getRawType(type).isInterface() - ? 1 // interfaces should be listed before Object - : 0; - for (K interfaceType : getInterfaces(type)) { - aboveMe = Math.max(aboveMe, collectTypes(interfaceType, map)); - } - K superclass = getSuperclass(type); - if (superclass != null) { - aboveMe = Math.max(aboveMe, collectTypes(superclass, map)); - } - /* - * TODO(benyu): should we include Object for interface? - * Also, CharSequence[] and Object[] for String[]? - * - */ - map.put(type, aboveMe + 1); - return aboveMe + 1; - } - - private static <K, V> ImmutableList<K> sortKeysByValue( - final Map<K, V> map, final Comparator<? super V> valueComparator) { - Ordering<K> keyOrdering = new Ordering<K>() { - @Override public int compare(K left, K right) { - return valueComparator.compare(map.get(left), map.get(right)); - } - }; - return keyOrdering.immutableSortedCopy(map.keySet()); - } - - abstract Class<?> getRawType(K type); - abstract Iterable<? extends K> getInterfaces(K type); - @Nullable abstract K getSuperclass(K type); - - private static class ForwardingTypeCollector<K> extends TypeCollector<K> { - - private final TypeCollector<K> delegate; - - ForwardingTypeCollector(TypeCollector<K> delegate) { - this.delegate = delegate; - } - - @Override Class<?> getRawType(K type) { - return delegate.getRawType(type); - } - - @Override Iterable<? extends K> getInterfaces(K type) { - return delegate.getInterfaces(type); - } - - @Override K getSuperclass(K type) { - return delegate.getSuperclass(type); - } - } - } -} diff --git a/guava/src/com/google/common/reflect/Types.java b/guava/src/com/google/common/reflect/Types.java deleted file mode 100644 index c19f38e..0000000 --- a/guava/src/com/google/common/reflect/Types.java +++ /dev/null @@ -1,504 +0,0 @@ -/* - * Copyright (C) 2011 The Guava Authors - * - * 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.common.reflect; - -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; -import static com.google.common.collect.Iterables.transform; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Function; -import com.google.common.base.Joiner; -import com.google.common.base.Objects; -import com.google.common.base.Predicates; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.Iterables; - -import java.io.Serializable; -import java.lang.reflect.Array; -import java.lang.reflect.GenericArrayType; -import java.lang.reflect.GenericDeclaration; -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; -import java.lang.reflect.TypeVariable; -import java.lang.reflect.WildcardType; -import java.util.Arrays; -import java.util.Collection; - -import javax.annotation.Nullable; - -/** - * Utilities for working with {@link Type}. - * - * @author Ben Yu - */ -final class Types { - - /** Class#toString without the "class " and "interface " prefixes */ - private static final Function<Type, String> TYPE_TO_STRING = - new Function<Type, String>() { - @Override public String apply(Type from) { - return Types.toString(from); - } - }; - - private static final Joiner COMMA_JOINER = Joiner.on(", ").useForNull("null"); - - /** Returns the array type of {@code componentType}. */ - static Type newArrayType(Type componentType) { - if (componentType instanceof WildcardType) { - WildcardType wildcard = (WildcardType) componentType; - Type[] lowerBounds = wildcard.getLowerBounds(); - checkArgument(lowerBounds.length <= 1, "Wildcard cannot have more than one lower bounds."); - if (lowerBounds.length == 1) { - return supertypeOf(newArrayType(lowerBounds[0])); - } else { - Type[] upperBounds = wildcard.getUpperBounds(); - checkArgument(upperBounds.length == 1, "Wildcard should have only one upper bound."); - return subtypeOf(newArrayType(upperBounds[0])); - } - } - return JavaVersion.CURRENT.newArrayType(componentType); - } - - /** - * Returns a type where {@code rawType} is parameterized by - * {@code arguments} and is owned by {@code ownerType}. - */ - static ParameterizedType newParameterizedTypeWithOwner( - @Nullable Type ownerType, Class<?> rawType, Type... arguments) { - if (ownerType == null) { - return newParameterizedType(rawType, arguments); - } - // ParameterizedTypeImpl constructor already checks, but we want to throw NPE before IAE - checkNotNull(arguments); - checkArgument(rawType.getEnclosingClass() != null, "Owner type for unenclosed %s", rawType); - return new ParameterizedTypeImpl(ownerType, rawType, arguments); - } - - /** - * Returns a type where {@code rawType} is parameterized by - * {@code arguments}. - */ - static ParameterizedType newParameterizedType(Class<?> rawType, Type... arguments) { - return new ParameterizedTypeImpl( - ClassOwnership.JVM_BEHAVIOR.getOwnerType(rawType), rawType, arguments); - } - - /** Decides what owner type to use for constructing {@link ParameterizedType} from a raw class. */ - private enum ClassOwnership { - - OWNED_BY_ENCLOSING_CLASS { - @Nullable - @Override - Class<?> getOwnerType(Class<?> rawType) { - return rawType.getEnclosingClass(); - } - }, - LOCAL_CLASS_HAS_NO_OWNER { - @Nullable - @Override - Class<?> getOwnerType(Class<?> rawType) { - if (rawType.isLocalClass()) { - return null; - } else { - return rawType.getEnclosingClass(); - } - } - }; - - @Nullable abstract Class<?> getOwnerType(Class<?> rawType); - - static final ClassOwnership JVM_BEHAVIOR = detectJvmBehavior(); - - private static ClassOwnership detectJvmBehavior() { - class LocalClass<T> {} - Class<?> subclass = new LocalClass<String>() {}.getClass(); - ParameterizedType parameterizedType = (ParameterizedType) - subclass.getGenericSuperclass(); - for (ClassOwnership behavior : ClassOwnership.values()) { - if (behavior.getOwnerType(LocalClass.class) == parameterizedType.getOwnerType()) { - return behavior; - } - } - throw new AssertionError(); - } - } - - /** - * Returns a new {@link TypeVariable} that belongs to {@code declaration} with - * {@code name} and {@code bounds}. - */ - static <D extends GenericDeclaration> TypeVariable<D> newTypeVariable( - D declaration, String name, Type... bounds) { - return new TypeVariableImpl<D>( - declaration, - name, - (bounds.length == 0) - ? new Type[] { Object.class } - : bounds); - } - - /** Returns a new {@link WildcardType} with {@code upperBound}. */ - @VisibleForTesting static WildcardType subtypeOf(Type upperBound) { - return new WildcardTypeImpl(new Type[0], new Type[] { upperBound }); - } - - /** Returns a new {@link WildcardType} with {@code lowerBound}. */ - @VisibleForTesting static WildcardType supertypeOf(Type lowerBound) { - return new WildcardTypeImpl(new Type[] { lowerBound }, new Type[] { Object.class }); - } - - /** - * Returns human readable string representation of {@code type}. - * <ul> - * <li> For array type {@code Foo[]}, {@code "com.mypackage.Foo[]"} are - * returned. - * <li> For any class, {@code theClass.getName()} are returned. - * <li> For all other types, {@code type.toString()} are returned. - * </ul> - */ - static String toString(Type type) { - return (type instanceof Class) - ? ((Class<?>) type).getName() - : type.toString(); - } - - @Nullable static Type getComponentType(Type type) { - checkNotNull(type); - if (type instanceof Class) { - return ((Class<?>) type).getComponentType(); - } else if (type instanceof GenericArrayType) { - return ((GenericArrayType) type).getGenericComponentType(); - } else if (type instanceof WildcardType) { - return subtypeOfComponentType(((WildcardType) type).getUpperBounds()); - } else if (type instanceof TypeVariable) { - return subtypeOfComponentType(((TypeVariable<?>) type).getBounds()); - } else { - return null; - } - } - - /** - * Returns {@code ? extends X} if any of {@code bounds} is a subtype of {@code X[]}; or null - * otherwise. - */ - @Nullable private static Type subtypeOfComponentType(Type[] bounds) { - for (Type bound : bounds) { - Type componentType = getComponentType(bound); - if (componentType != null) { - // Only the first bound can be a class or array. - // Bounds after the first can only be interfaces. - if (componentType instanceof Class) { - Class<?> componentClass = (Class<?>) componentType; - if (componentClass.isPrimitive()) { - return componentClass; - } - } - return subtypeOf(componentType); - } - } - return null; - } - - static boolean containsTypeVariable(@Nullable Type type) { - if (type instanceof TypeVariable) { - return true; - } - if (type instanceof GenericArrayType) { - return containsTypeVariable(((GenericArrayType) type).getGenericComponentType()); - } - if (type instanceof ParameterizedType) { - return containsTypeVariable(((ParameterizedType) type).getActualTypeArguments()); - } - if (type instanceof WildcardType) { - WildcardType wildcard = (WildcardType) type; - return containsTypeVariable(wildcard.getUpperBounds()) - || containsTypeVariable(wildcard.getLowerBounds()); - } - return false; - } - - private static boolean containsTypeVariable(Type[] types) { - for (Type paramType : types) { - if (containsTypeVariable(paramType)) { - return true; - } - } - return false; - } - - private static final class GenericArrayTypeImpl - implements GenericArrayType, Serializable { - - private final Type componentType; - - GenericArrayTypeImpl(Type componentType) { - this.componentType = JavaVersion.CURRENT.usedInGenericType(componentType); - } - - @Override public Type getGenericComponentType() { - return componentType; - } - - @Override public String toString() { - return Types.toString(componentType) + "[]"; - } - - @Override public int hashCode() { - return componentType.hashCode(); - } - - @Override public boolean equals(Object obj) { - if (obj instanceof GenericArrayType) { - GenericArrayType that = (GenericArrayType) obj; - return Objects.equal( - getGenericComponentType(), that.getGenericComponentType()); - } - return false; - } - - private static final long serialVersionUID = 0; - } - - private static final class ParameterizedTypeImpl - implements ParameterizedType, Serializable { - - private final Type ownerType; - private final ImmutableList<Type> argumentsList; - private final Class<?> rawType; - - ParameterizedTypeImpl( - @Nullable Type ownerType, Class<?> rawType, Type[] typeArguments) { - checkNotNull(rawType); - checkArgument(typeArguments.length == rawType.getTypeParameters().length); - disallowPrimitiveType(typeArguments, "type parameter"); - this.ownerType = ownerType; - this.rawType = rawType; - this.argumentsList = JavaVersion.CURRENT.usedInGenericType(typeArguments); - } - - @Override public Type[] getActualTypeArguments() { - return toArray(argumentsList); - } - - @Override public Type getRawType() { - return rawType; - } - - @Override public Type getOwnerType() { - return ownerType; - } - - @Override public String toString() { - StringBuilder builder = new StringBuilder(); - if (ownerType != null) { - builder.append(Types.toString(ownerType)).append('.'); - } - builder.append(rawType.getName()) - .append('<') - .append(COMMA_JOINER.join(transform(argumentsList, TYPE_TO_STRING))) - .append('>'); - return builder.toString(); - } - - @Override public int hashCode() { - return (ownerType == null ? 0 : ownerType.hashCode()) - ^ argumentsList.hashCode() ^ rawType.hashCode(); - } - - @Override public boolean equals(Object other) { - if (!(other instanceof ParameterizedType)) { - return false; - } - ParameterizedType that = (ParameterizedType) other; - return getRawType().equals(that.getRawType()) - && Objects.equal(getOwnerType(), that.getOwnerType()) - && Arrays.equals( - getActualTypeArguments(), that.getActualTypeArguments()); - } - - private static final long serialVersionUID = 0; - } - - private static final class TypeVariableImpl<D extends GenericDeclaration> - implements TypeVariable<D> { - - private final D genericDeclaration; - private final String name; - private final ImmutableList<Type> bounds; - - TypeVariableImpl(D genericDeclaration, String name, Type[] bounds) { - disallowPrimitiveType(bounds, "bound for type variable"); - this.genericDeclaration = checkNotNull(genericDeclaration); - this.name = checkNotNull(name); - this.bounds = ImmutableList.copyOf(bounds); - } - - @Override public Type[] getBounds() { - return toArray(bounds); - } - - @Override public D getGenericDeclaration() { - return genericDeclaration; - } - - @Override public String getName() { - return name; - } - - @Override public String toString() { - return name; - } - - @Override public int hashCode() { - return genericDeclaration.hashCode() ^ name.hashCode(); - } - - @Override public boolean equals(Object obj) { - if (obj instanceof TypeVariable) { - TypeVariable<?> that = (TypeVariable<?>) obj; - return name.equals(that.getName()) - && genericDeclaration.equals(that.getGenericDeclaration()); - } - return false; - } - } - - static final class WildcardTypeImpl implements WildcardType, Serializable { - - private final ImmutableList<Type> lowerBounds; - private final ImmutableList<Type> upperBounds; - - WildcardTypeImpl(Type[] lowerBounds, Type[] upperBounds) { - disallowPrimitiveType(lowerBounds, "lower bound for wildcard"); - disallowPrimitiveType(upperBounds, "upper bound for wildcard"); - this.lowerBounds = JavaVersion.CURRENT.usedInGenericType(lowerBounds); - this.upperBounds = JavaVersion.CURRENT.usedInGenericType(upperBounds); - } - - @Override public Type[] getLowerBounds() { - return toArray(lowerBounds); - } - - @Override public Type[] getUpperBounds() { - return toArray(upperBounds); - } - - @Override public boolean equals(Object obj) { - if (obj instanceof WildcardType) { - WildcardType that = (WildcardType) obj; - return lowerBounds.equals(Arrays.asList(that.getLowerBounds())) - && upperBounds.equals(Arrays.asList(that.getUpperBounds())); - } - return false; - } - - @Override public int hashCode() { - return lowerBounds.hashCode() ^ upperBounds.hashCode(); - } - - @Override public String toString() { - StringBuilder builder = new StringBuilder("?"); - for (Type lowerBound : lowerBounds) { - builder.append(" super ").append(Types.toString(lowerBound)); - } - for (Type upperBound : filterUpperBounds(upperBounds)) { - builder.append(" extends ").append(Types.toString(upperBound)); - } - return builder.toString(); - } - - private static final long serialVersionUID = 0; - } - - private static Type[] toArray(Collection<Type> types) { - return types.toArray(new Type[types.size()]); - } - - private static Iterable<Type> filterUpperBounds(Iterable<Type> bounds) { - return Iterables.filter( - bounds, Predicates.not(Predicates.<Type>equalTo(Object.class))); - } - - private static void disallowPrimitiveType(Type[] types, String usedAs) { - for (Type type : types) { - if (type instanceof Class) { - Class<?> cls = (Class<?>) type; - checkArgument(!cls.isPrimitive(), - "Primitive type '%s' used as %s", cls, usedAs); - } - } - } - - /** Returns the {@code Class} object of arrays with {@code componentType}. */ - static Class<?> getArrayClass(Class<?> componentType) { - // TODO(user): This is not the most efficient way to handle generic - // arrays, but is there another way to extract the array class in a - // non-hacky way (i.e. using String value class names- "[L...")? - return Array.newInstance(componentType, 0).getClass(); - } - - // TODO(benyu): Once we are on Java 7, delete this abstraction - enum JavaVersion { - - JAVA6 { - @Override GenericArrayType newArrayType(Type componentType) { - return new GenericArrayTypeImpl(componentType); - } - @Override Type usedInGenericType(Type type) { - checkNotNull(type); - if (type instanceof Class) { - Class<?> cls = (Class<?>) type; - if (cls.isArray()) { - return new GenericArrayTypeImpl(cls.getComponentType()); - } - } - return type; - } - }, - JAVA7 { - @Override Type newArrayType(Type componentType) { - if (componentType instanceof Class) { - return getArrayClass((Class<?>) componentType); - } else { - return new GenericArrayTypeImpl(componentType); - } - } - @Override Type usedInGenericType(Type type) { - return checkNotNull(type); - } - } - ; - - static final JavaVersion CURRENT = - (new TypeCapture<int[]>() {}.capture() instanceof Class) - ? JAVA7 : JAVA6; - abstract Type newArrayType(Type componentType); - abstract Type usedInGenericType(Type type); - - final ImmutableList<Type> usedInGenericType(Type[] types) { - ImmutableList.Builder<Type> builder = ImmutableList.builder(); - for (Type type : types) { - builder.add(usedInGenericType(type)); - } - return builder.build(); - } - } - - private Types() {} -} diff --git a/guava/src/com/google/common/reflect/package-info.java b/guava/src/com/google/common/reflect/package-info.java deleted file mode 100644 index e8ac02a..0000000 --- a/guava/src/com/google/common/reflect/package-info.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (C) 2012 The Guava Authors - * - * 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. - */ - -/** - * This package contains utilities to work with Java reflection. - * It is a part of the open-source - * <a href="http://guava-libraries.googlecode.com">Guava libraries</a>. - */ -@javax.annotation.ParametersAreNonnullByDefault -package com.google.common.reflect; |