/*
 * Copyright 2008 Google Inc.
 *
 * 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.gwt.dev.javac.typemodel;

import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.typeinfo.JWildcardType.BoundType;
import com.google.gwt.core.ext.typeinfo.NotFoundException;
import com.google.gwt.dev.javac.typemodel.test.CA;
import com.google.gwt.dev.javac.typemodel.test.CB;
import com.google.gwt.dev.javac.typemodel.test.CC;
import com.google.gwt.dev.util.log.PrintWriterTreeLogger;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

/**
 * Test for {@link JWildcardType}.
 */
public class JWildcardTypeTest extends JDelegatingClassTypeTestBase {
  private final boolean logToConsole = false;
  private final ModuleContext moduleContext = new ModuleContext(logToConsole
      ? new PrintWriterTreeLogger() : TreeLogger.NULL,
      "com.google.gwt.dev.javac.typemodel.TypeOracleTest");

  public JWildcardTypeTest() throws UnableToCompleteException {
  }

  @Override
  public void testFindConstructor() {
    // Wildcard types do not have constructors
  }

  @Override
  public void testFindNestedType() {
    // Wildcard do not have nested types...
  }

  @Override
  public void testGetConstructors() {
  }

  @Override
  public void testGetEnclosingType() {
    // Wildcard do not have nested types...
  }

  @Override
  public void testGetErasedType() throws NotFoundException {
    TypeOracle oracle = moduleContext.getOracle();
    JClassType numberType = oracle.getType(Number.class.getCanonicalName());

    // Tests that ? extends Number erases to number.
    JWildcardType upperBoundWildcard = oracle.getWildcardType(
        BoundType.EXTENDS, numberType);
    assertEquals(numberType, upperBoundWildcard.getErasedType());

    // Tests that ? super Number erases to Object
    JWildcardType lowerBoundWildcard = oracle.getWildcardType(BoundType.SUPER,
        numberType);
    assertEquals(oracle.getJavaLangObject(), lowerBoundWildcard.getErasedType());
  }

  @Override
  public void testGetInheritableMethods() {
    // No inheritable methods
  }

  @Override
  public void testGetMethods() throws NotFoundException {
    super.testGetMethods();
  }

  @Override
  public void testGetNestedType() {
    // No nested types
  }

  @Override
  public void testGetNestedTypes() {
    // No nested types
  }

  @Override
  public void testGetOverridableMethods() {
    // No overridable methods
  }

  /**
   * Tests that {@link JWildcardType#getParameterizedQualifiedSourceName()}
   * returns the expected value. We test this because JSNI code depends on it.
   *
   * @throws NotFoundException
   */
  public void testGetParameterizedQualifiedSourceName()
      throws NotFoundException {
    TypeOracle oracle = moduleContext.getOracle();
    JClassType numberType = oracle.getType(Number.class.getName());

    JWildcardType numberUpperBound = oracle.getWildcardType(BoundType.EXTENDS,
        numberType);
    assertEquals("? extends " + Number.class.getCanonicalName(),
        numberUpperBound.getParameterizedQualifiedSourceName());

    JWildcardType numberLowerBound = oracle.getWildcardType(BoundType.SUPER,
        numberType);
    assertEquals("? super " + Number.class.getCanonicalName(),
        numberLowerBound.getParameterizedQualifiedSourceName());

    JWildcardType unboundWildcard = oracle.getWildcardType(BoundType.UNBOUND,
        oracle.getJavaLangObject());
    assertEquals("?", unboundWildcard.getParameterizedQualifiedSourceName());
  }

  @Override
  public void testGetSubtypes() {
    // Tested by testGetSubtypes_LowerBound() and testGetSubtypes_UpperBound()
  }

  public void testGetSubtypes_LowerBound() throws NotFoundException {
    TypeOracle oracle = moduleContext.getOracle();
    // <? super Number>
    JWildcardType lowerBoundWildcard = oracle.getWildcardType(BoundType.SUPER,
        oracle.getType(Number.class.getName()));
    JClassType[] subtypes = lowerBoundWildcard.getSubtypes();
    assertEquals(0, subtypes.length);
  }

  public void testGetSubtypes_UpperBound() throws NotFoundException {
    TypeOracle oracle = moduleContext.getOracle();
    // <? extends CA>
    JWildcardType upperBoundWildcard = oracle.getWildcardType(
        BoundType.EXTENDS, oracle.getType(CA.class.getName()));

    JClassType[] expected = new JClassType[]{
        oracle.getType(CB.class.getName()), oracle.getType(CC.class.getName())};
    Set<JClassType> expectedSet = new HashSet<JClassType>();
    expectedSet.addAll(Arrays.asList(expected));

    JClassType[] actual = upperBoundWildcard.getSubtypes();
    assertEquals(expectedSet.size(), actual.length);

    for (int i = 0; i < actual.length; ++i) {
      expectedSet.remove(actual[i]);
    }
    assertTrue(expectedSet.isEmpty());
  }

  @Override
  public void testIsAssignableFrom() throws NotFoundException {
    // Covered by the different testIsAssignableFrom*() variants below.
    TypeOracle oracle = moduleContext.getOracle();

    JClassType integerType = oracle.getType(Integer.class.getName());
    JClassType numberType = oracle.getType(Number.class.getName());

    // ? extends Number
    JClassType extendsNumber = oracle.getWildcardType(BoundType.EXTENDS,
        numberType);

    // ? extends Integer
    JClassType extendsInteger = oracle.getWildcardType(BoundType.EXTENDS,
        integerType);

    // Integer is not assignable from ? extends Number
    assertFalse(integerType.isAssignableFrom(extendsNumber));

    // Integer is assignable from ? extends Integer
    assertTrue(integerType.isAssignableFrom(extendsInteger));

    // Number is assignable from ? extends Integer
    assertTrue(numberType.isAssignableFrom(extendsInteger));

    // ? super Integer
    JClassType superInteger = oracle.getWildcardType(BoundType.SUPER,
        integerType);

    // Integer is assignable from ? super Integer
    assertFalse(integerType.isAssignableFrom(superInteger));

    // ? super Integer is assignable from Number
    assertTrue(superInteger.isAssignableFrom(numberType));

    JClassType superNumber = oracle.getWildcardType(BoundType.SUPER, numberType);

    // ? super Number is not assignable from Integer
    assertFalse(superNumber.isAssignableFrom(integerType));

    // ? super Number is not assignable from Character
    JClassType characterType = oracle.getType(Character.class.getName());
    assertFalse(superNumber.isAssignableFrom(characterType));
  }

  /**
   * Tests that <? extends Number> is assignable from <? extends Integer> and
   * that the reverse is not <code>true</code>.
   */
  public void testIsAssignableFrom_Extends_Number_To_Extends_Integer()
      throws NotFoundException {
    TypeOracle oracle = moduleContext.getOracle();
    JClassType numberType = oracle.getType(Number.class.getName());
    JClassType integerType = oracle.getType(Integer.class.getName());

    JWildcardType numberWildcard = oracle.getWildcardType(BoundType.EXTENDS,
        numberType);
    JWildcardType integerWildcard = oracle.getWildcardType(BoundType.EXTENDS,
        integerType);

    assertTrue(numberWildcard.isAssignableFrom(integerWildcard));
    assertFalse(integerWildcard.isAssignableFrom(numberWildcard));
  }

  public void testUnboundIsSameAsExtendsObject() {
    TypeOracle oracle = moduleContext.getOracle();

    JClassType javaLangObject = oracle.getJavaLangObject();

    // ?
    JWildcardType unbound = oracle.getWildcardType(BoundType.UNBOUND, javaLangObject);

    // ? extends Object
    JWildcardType upperWildcard = oracle.getWildcardType(BoundType.EXTENDS, javaLangObject);

    assertSame(unbound, upperWildcard);

    // ? super Object
    JWildcardType lowerWildcard = oracle.getWildcardType(BoundType.SUPER, javaLangObject);

    assertNotSame(unbound, lowerWildcard);
  }

  /**
   * Tests that <? extends Object> is assignable to and from <? super Object>.
   */
  public void testIsAssignableFrom_Extends_Object_From_Super_Object() {
    TypeOracle oracle = moduleContext.getOracle();

    JClassType javaLangObject = oracle.getJavaLangObject();

    // ? super Object
    JWildcardType lowerWildcard = oracle.getWildcardType(BoundType.SUPER,
        javaLangObject);

    // ? extends Object
    JWildcardType upperWildcard = oracle.getWildcardType(BoundType.EXTENDS,
        javaLangObject);

    // ? extends Object assignable from ? super Object
    assertTrue(upperWildcard.isAssignableFrom(lowerWildcard));

    // ? super Object not assignable from ? extends Object
    assertFalse(lowerWildcard.isAssignableFrom(upperWildcard));
  }

  /**
   * Tests that <? super Integer> is assignable from <? super Number>.
   */
  public void testIsAssignableFrom_Super_Integer_From_Super_Number()
      throws NotFoundException {
    TypeOracle oracle = moduleContext.getOracle();
    JClassType numberType = oracle.getType(Number.class.getName());
    JClassType integerType = oracle.getType(Integer.class.getName());

    JWildcardType wildcardSuperNumber = oracle.getWildcardType(BoundType.SUPER,
        numberType);
    JWildcardType wildcardSuperInteger = oracle.getWildcardType(BoundType.SUPER,
        integerType);

    assertFalse(wildcardSuperNumber.isAssignableFrom(wildcardSuperInteger));
    assertTrue(wildcardSuperNumber.isAssignableTo(wildcardSuperInteger));
    assertTrue(wildcardSuperInteger.isAssignableFrom(wildcardSuperNumber));
    assertFalse(wildcardSuperInteger.isAssignableTo(wildcardSuperNumber));
  }

  @Override
  public void testIsAssignableTo() {
    // NOTE These cases were tested as part of testIsAssignableFrom.
  }

  /**
   * Tests that <? extends Integer> is assignable to <? extends Number> and that
   * the reverse is not <code>true</code>.
   */
  public void testIsAssignableTo_Extends_Integer_To_Extends_Number()
      throws NotFoundException {
    TypeOracle oracle = moduleContext.getOracle();
    JClassType numberType = oracle.getType(Number.class.getName());
    JClassType integerType = oracle.getType(Integer.class.getName());

    JWildcardType numberWildcard = oracle.getWildcardType(BoundType.EXTENDS,
        numberType);
    JWildcardType integerWildcard = oracle.getWildcardType(BoundType.EXTENDS,
        integerType);

    assertTrue(integerWildcard.isAssignableTo(numberWildcard));
    assertFalse(numberWildcard.isAssignableTo(integerWildcard));
  }

  @Override
  protected Substitution getSubstitution() {
    return new Substitution() {
      @Override
      public JClassType getSubstitution(JClassType type) {
        return type;
      }
    };
  }

  @Override
  protected JWildcardType getTestType() throws NotFoundException {
    TypeOracle oracle = moduleContext.getOracle();
    return oracle.getWildcardType(BoundType.EXTENDS,
        oracle.getType(Number.class.getName()));
  }
}
