11d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/* 21d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Copyright (C) 2009 The Guava Authors 31d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 41d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Licensed under the Apache License, Version 2.0 (the "License"); 51d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * you may not use this file except in compliance with the License. 61d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * You may obtain a copy of the License at 71d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 81d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * http://www.apache.org/licenses/LICENSE-2.0 91d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Unless required by applicable law or agreed to in writing, software 111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * distributed under the License is distributed on an "AS IS" BASIS, 121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * See the License for the specific language governing permissions and 141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * limitations under the License. 151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertpackage com.google.common.collect; 181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport static com.google.common.collect.Lists.transform; 201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport static com.google.common.collect.Sets.newHashSet; 211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport static com.google.common.collect.Sets.newTreeSet; 221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport static java.lang.reflect.Modifier.isPublic; 231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport static java.lang.reflect.Modifier.isStatic; 241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.base.Function; 261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.base.Joiner; 271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.base.Objects; 281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport junit.framework.TestCase; 301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.lang.reflect.Method; 321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.lang.reflect.Type; 331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.lang.reflect.TypeVariable; 341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.Arrays; 351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.Collections; 361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.List; 371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.Map; 381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.Set; 391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/** 411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Tests that all {@code public static} methods "inherited" from superclasses 421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * are "overridden" in each immutable-collection class. This ensures, for 431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * example, that a call written "{@code ImmutableSortedSet.copyOf()}" cannot 441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * secretly be a call to {@code ImmutableSet.copyOf()}. 451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @author Chris Povirk 471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertpublic class FauxveridesTest extends TestCase { 491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testImmutableBiMap() { 501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert doHasAllFauxveridesTest(ImmutableBiMap.class, ImmutableMap.class); 511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testImmutableListMultimap() { 541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert doHasAllFauxveridesTest( 551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert ImmutableListMultimap.class, ImmutableMultimap.class); 561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testImmutableSetMultimap() { 591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert doHasAllFauxveridesTest( 601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert ImmutableSetMultimap.class, ImmutableMultimap.class); 611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testImmutableSortedMap() { 641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert doHasAllFauxveridesTest(ImmutableSortedMap.class, ImmutableMap.class); 651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testImmutableSortedSet() { 681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert doHasAllFauxveridesTest(ImmutableSortedSet.class, ImmutableSet.class); 691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /* 721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Demonstrate that ClassCastException is possible when calling 731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * ImmutableSorted{Set,Map}.copyOf(), whose type parameters we are unable to 741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * restrict (see ImmutableSortedSetFauxverideShim). 751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testImmutableSortedMapCopyOfMap() { 781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Map<Object, Object> original = 791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert ImmutableMap.of(new Object(), new Object(), new Object(), new Object()); 801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert try { 821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert ImmutableSortedMap.copyOf(original); 831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert fail(); 841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } catch (ClassCastException expected) { 851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testImmutableSortedSetCopyOfIterable() { 891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Set<Object> original = ImmutableSet.of(new Object(), new Object()); 901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert try { 921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert ImmutableSortedSet.copyOf(original); 931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert fail(); 941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } catch (ClassCastException expected) { 951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testImmutableSortedSetCopyOfIterator() { 991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Set<Object> original = ImmutableSet.of(new Object(), new Object()); 1001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert try { 1021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert ImmutableSortedSet.copyOf(original.iterator()); 1031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert fail(); 1041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } catch (ClassCastException expected) { 1051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private void doHasAllFauxveridesTest(Class<?> descendant, Class<?> ancestor) { 1091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Set<MethodSignature> required = 1101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert getAllRequiredToFauxveride(descendant, ancestor); 1111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Set<MethodSignature> found = getAllFauxveridden(descendant, ancestor); 1121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert required.removeAll(found); 1131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals("Must hide public static methods from ancestor classes", 1151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Collections.emptySet(), newTreeSet(required)); 1161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private static Set<MethodSignature> getAllRequiredToFauxveride( 1191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Class<?> descendant, Class<?> ancestor) { 1201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return getPublicStaticMethodsBetween(ancestor, Object.class); 1211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private static Set<MethodSignature> getAllFauxveridden( 1241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Class<?> descendant, Class<?> ancestor) { 1251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return getPublicStaticMethodsBetween(descendant, ancestor); 1261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private static Set<MethodSignature> getPublicStaticMethodsBetween( 1291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Class<?> descendant, Class<?> ancestor) { 1301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Set<MethodSignature> methods = newHashSet(); 1311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert for (Class<?> clazz : getClassesBetween(descendant, ancestor)) { 1321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert methods.addAll(getPublicStaticMethods(clazz)); 1331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return methods; 1351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private static Set<MethodSignature> getPublicStaticMethods(Class<?> clazz) { 1381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Set<MethodSignature> publicStaticMethods = newHashSet(); 1391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert for (Method method : clazz.getDeclaredMethods()) { 1411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert int modifiers = method.getModifiers(); 1421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (isPublic(modifiers) && isStatic(modifiers)) { 1431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert publicStaticMethods.add(new MethodSignature(method)); 1441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return publicStaticMethods; 1481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** [descendant, ancestor) */ 1511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private static Set<Class<?>> getClassesBetween( 1521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Class<?> descendant, Class<?> ancestor) { 1531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Set<Class<?>> classes = newHashSet(); 1541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert while (!descendant.equals(ancestor)) { 1561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert classes.add(descendant); 1571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert descendant = descendant.getSuperclass(); 1581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return classes; 1611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 1641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Not really a signature -- just the parts that affect whether one method is 1651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * a fauxveride of a method from an ancestor class. 1661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p> 1671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * See JLS 8.4.2 for the definition of the related "override-equivalent." 1681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 1691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private static final class MethodSignature 1701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert implements Comparable<MethodSignature> { 1711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert final String name; 1721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert final List<Class<?>> parameterTypes; 1731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert final TypeSignature typeSignature; 1741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert MethodSignature(Method method) { 1761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert name = method.getName(); 1771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert parameterTypes = Arrays.asList(method.getParameterTypes()); 1781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert typeSignature = new TypeSignature(method.getTypeParameters()); 1791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override public boolean equals(Object obj) { 1821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (obj instanceof MethodSignature) { 1831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert MethodSignature other = (MethodSignature) obj; 1841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return name.equals(other.name) 1851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert && parameterTypes.equals(other.parameterTypes) 1861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert && typeSignature.equals(other.typeSignature); 1871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return false; 1901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override public int hashCode() { 1931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return Objects.hashCode(name, parameterTypes, typeSignature); 1941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override public String toString() { 1971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return String.format("%s%s(%s)", 1981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert typeSignature, name, getTypesString(parameterTypes)); 1991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override public int compareTo(MethodSignature o) { 2021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return toString().compareTo(o.toString()); 2031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private static final class TypeSignature { 2071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert final List<TypeParameterSignature> parameterSignatures; 2081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert TypeSignature(TypeVariable<Method>[] parameters) { 2101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert parameterSignatures = 2111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert transform(Arrays.asList(parameters), 2121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert new Function<TypeVariable<?>, TypeParameterSignature>() { 2131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 2141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public TypeParameterSignature apply(TypeVariable<?> from) { 2151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return new TypeParameterSignature(from); 2161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert }); 2181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override public boolean equals(Object obj) { 2211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (obj instanceof TypeSignature) { 2221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert TypeSignature other = (TypeSignature) obj; 2231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return parameterSignatures.equals(other.parameterSignatures); 2241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return false; 2271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override public int hashCode() { 2301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return parameterSignatures.hashCode(); 2311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override public String toString() { 2341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return (parameterSignatures.isEmpty()) 2351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert ? "" 2361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert : "<" + Joiner.on(", ").join(parameterSignatures) + "> "; 2371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private static final class TypeParameterSignature { 2411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert final String name; 2421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert final List<Type> bounds; 2431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert TypeParameterSignature(TypeVariable<?> typeParameter) { 2451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert name = typeParameter.getName(); 2461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert bounds = Arrays.asList(typeParameter.getBounds()); 2471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override public boolean equals(Object obj) { 2501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (obj instanceof TypeParameterSignature) { 2511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert TypeParameterSignature other = (TypeParameterSignature) obj; 2521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /* 2531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * The name is here only for display purposes; <E extends Number> and <T 2541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * extends Number> are equivalent. 2551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 2561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return bounds.equals(other.bounds); 2571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return false; 2601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override public int hashCode() { 2631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return bounds.hashCode(); 2641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override public String toString() { 2671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return (bounds.equals(ImmutableList.of(Object.class))) 2681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert ? name 2691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert : name + " extends " + getTypesString(bounds); 2701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private static String getTypesString(List<? extends Type> types) { 2741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert List<String> names = transform(types, SIMPLE_NAME_GETTER); 2751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return Joiner.on(", ").join(names); 2761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private static final Function<Type, String> SIMPLE_NAME_GETTER = 2791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert new Function<Type, String>() { 2801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 2811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public String apply(Type from) { 2821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (from instanceof Class) { 2831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return ((Class<?>) from).getSimpleName(); 2841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return from.toString(); 2861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert }; 2881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert} 289