Program: 15742
Project: 15742
Buggy source:
/** 
 * Returns the most specific common class (or interface) of two parameter types for the purpose of unwrapping. This is trickier then finding the most specific overlapping superclass of two classes, because: <ul> <li>It considers primitive classes as the subclasses of the boxing classes.</li> <li>It considers widening numerical conversion as if the narrower type is subclass.</li> <li>If the only common class is   {@link Object}, it will try to find a common interface. If there are more of them, it will start removing those that are known to be uninteresting as unwrapping hint.</li> </ul>
 * @param c1 Parameter type 1
 * @param c2 Parameter type 2
 */
protected Class getCommonSupertypeForUnwrappingHint(Class c1,Class c2){
  if (c1 == c2)   return c1;
  if (bugfixed) {
    final boolean c1WasPrim;
    if (c1.isPrimitive()) {
      c1=OverloadedMethodsSubset.primitiveClassToBoxingClass(c1);
      c1WasPrim=true;
    }
 else {
      c1WasPrim=false;
    }
    final boolean c2WasPrim;
    if (c2.isPrimitive()) {
      c2=OverloadedMethodsSubset.primitiveClassToBoxingClass(c2);
      c2WasPrim=true;
    }
 else {
      c2WasPrim=false;
    }
    if (c1 == c2) {
      return c1;
    }
 else     if (Number.class.isAssignableFrom(c1) && Number.class.isAssignableFrom(c2)) {
      return Number.class;
    }
 else     if (c1WasPrim || c2WasPrim) {
      return Object.class;
    }
  }
 else {
    if (c2.isPrimitive()) {
      if (c2 == Byte.TYPE)       c2=Byte.class;
 else       if (c2 == Short.TYPE)       c2=Short.class;
 else       if (c2 == Character.TYPE)       c2=Character.class;
 else       if (c2 == Integer.TYPE)       c2=Integer.class;
 else       if (c2 == Float.TYPE)       c2=Float.class;
 else       if (c2 == Long.TYPE)       c2=Long.class;
 else       if (c2 == Double.TYPE)       c2=Double.class;
    }
  }
  Set commonTypes=MethodUtilities.getAssignables(c1,c2);
  commonTypes.retainAll(MethodUtilities.getAssignables(c2,c1));
  if (commonTypes.isEmpty()) {
    return Object.class;
  }
  List max=new ArrayList();
  listCommonTypes:   for (Iterator commonTypesIter=commonTypes.iterator(); commonTypesIter.hasNext(); ) {
    Class clazz=(Class)commonTypesIter.next();
    for (Iterator maxIter=max.iterator(); maxIter.hasNext(); ) {
      Class maxClazz=(Class)maxIter.next();
      if (MethodUtilities.isMoreSpecificOrTheSame(maxClazz,clazz,bugfixed)) {
        continue listCommonTypes;
      }
      if (MethodUtilities.isMoreSpecificOrTheSame(clazz,maxClazz,bugfixed)) {
        maxIter.remove();
      }
    }
    max.add(clazz);
  }
  if (max.size() > 1) {
    if (bugfixed) {
      for (Iterator it=max.iterator(); it.hasNext(); ) {
        Class maxCl=(Class)it.next();
        if (!maxCl.isInterface()) {
          if (maxCl != Object.class) {
            return maxCl;
          }
 else {
            it.remove();
          }
        }
      }
      max.remove(Cloneable.class);
      if (max.size() > 1) {
        max.remove(Serializable.class);
        if (max.size() > 1) {
          max.remove(Comparable.class);
          if (max.size() > 1) {
            return Object.class;
          }
        }
      }
    }
 else {
      return Object.class;
    }
  }
  return (Class)max.get(0);
}

Fixed version (ground truth):
/** 
 * Returns the most specific common class (or interface) of two parameter types for the purpose of unwrapping. This is trickier then finding the most specific overlapping superclass of two classes, because: <ul> <li>It considers primitive classes as the subclasses of the boxing classes.</li> <li>It considers widening numerical conversion as if the narrower type is subclass.</li> <li>If the only common class is   {@link Object}, it will try to find a common interface. If there are more of them, it will start removing those that are known to be uninteresting as unwrapping hint.</li> </ul>
 * @param c1 Parameter type 1
 * @param c2 Parameter type 2
 */
protected Class getCommonSupertypeForUnwrappingHint(Class c1,Class c2){
  if (c1 == c2)   return c1;
  if (bugfixed) {
    final boolean c1WasPrim;
    if (c1.isPrimitive()) {
      c1=ClassUtil.primitiveClassToBoxingClass(c1);
      c1WasPrim=true;
    }
 else {
      c1WasPrim=false;
    }
    final boolean c2WasPrim;
    if (c2.isPrimitive()) {
      c2=ClassUtil.primitiveClassToBoxingClass(c2);
      c2WasPrim=true;
    }
 else {
      c2WasPrim=false;
    }
    if (c1 == c2) {
      return c1;
    }
 else     if (Number.class.isAssignableFrom(c1) && Number.class.isAssignableFrom(c2)) {
      return Number.class;
    }
 else     if (c1WasPrim || c2WasPrim) {
      return Object.class;
    }
  }
 else {
    if (c2.isPrimitive()) {
      if (c2 == Byte.TYPE)       c2=Byte.class;
 else       if (c2 == Short.TYPE)       c2=Short.class;
 else       if (c2 == Character.TYPE)       c2=Character.class;
 else       if (c2 == Integer.TYPE)       c2=Integer.class;
 else       if (c2 == Float.TYPE)       c2=Float.class;
 else       if (c2 == Long.TYPE)       c2=Long.class;
 else       if (c2 == Double.TYPE)       c2=Double.class;
    }
  }
  Set commonTypes=MethodUtilities.getAssignables(c1,c2);
  commonTypes.retainAll(MethodUtilities.getAssignables(c2,c1));
  if (commonTypes.isEmpty()) {
    return Object.class;
  }
  List max=new ArrayList();
  listCommonTypes:   for (Iterator commonTypesIter=commonTypes.iterator(); commonTypesIter.hasNext(); ) {
    Class clazz=(Class)commonTypesIter.next();
    for (Iterator maxIter=max.iterator(); maxIter.hasNext(); ) {
      Class maxClazz=(Class)maxIter.next();
      if (MethodUtilities.isMoreOrSameSpecificParameterType(maxClazz,clazz,bugfixed,0) != 0) {
        continue listCommonTypes;
      }
      if (MethodUtilities.isMoreOrSameSpecificParameterType(clazz,maxClazz,bugfixed,0) != 0) {
        maxIter.remove();
      }
    }
    max.add(clazz);
  }
  if (max.size() > 1) {
    if (bugfixed) {
      for (Iterator it=max.iterator(); it.hasNext(); ) {
        Class maxCl=(Class)it.next();
        if (!maxCl.isInterface()) {
          if (maxCl != Object.class) {
            return maxCl;
          }
 else {
            it.remove();
          }
        }
      }
      max.remove(Cloneable.class);
      if (max.size() > 1) {
        max.remove(Serializable.class);
        if (max.size() > 1) {
          max.remove(Comparable.class);
          if (max.size() > 1) {
            return Object.class;
          }
        }
      }
    }
 else {
      return Object.class;
    }
  }
  return (Class)max.get(0);
}