/*
 * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

/*
 * @test
 * @bug 6499673 6557966
 * @library /tools/javac/lib
 * @build JavacTestingAbstractProcessor IntersectionPropertiesTest
 * @run main IntersectionPropertiesTest
 * @summary Assertion check for TypeVariable.getUpperBound() fails
 */

import com.sun.source.util.*;
import com.sun.tools.javac.util.Assert;
import javax.annotation.processing.*;
import javax.lang.model.type.*;
import javax.lang.model.util.ElementFilter;
import javax.lang.model.element.*;
import javax.tools.*;
import java.util.*;
import java.io.*;
import javax.lang.model.util.Types;

public class IntersectionPropertiesTest {

    private int errors = 0;
    private static final String Intersection_name = "IntersectionTest.java";
    private static final String Intersection_contents =
        "import java.util.AbstractList;\n" +
        "import java.util.List;\n" +
        "import java.io.Serializable;\t" +
        "public class IntersectionTest<S extends List & Serializable, One extends AbstractList & Runnable & Serializable, Two extends AbstractList & Serializable & Runnable> {\n" +
        "  void method(S s, One o, Two t) { }\n" +
        "  public static abstract class SubType extends AbstractList implements Runnable, Serializable { } \n" +
        "}";

    private static final File classesdir = new File("intersectionproperties");
    private static final JavaCompiler comp =
        ToolProvider.getSystemJavaCompiler();
    private static final StandardJavaFileManager fm =
        comp.getStandardFileManager(null, null, null);

    public void runOne(final String Test_name, final String Test_contents)
        throws IOException {
        System.err.println("Testing " + Test_name);
        final Iterable<? extends JavaFileObject> files =
            fm.getJavaFileObjectsFromFiles(Collections.singleton(writeFile(classesdir, Test_name, Test_contents)));
        final JavacTask ct =
            (JavacTask)comp.getTask(null, fm, null, null, null, files);
        ct.setProcessors(Collections.singleton(new TestProcessor()));

        if (!ct.call()) {
            System.err.println("Compilation unexpectedly failed");
            errors++;
        }
    }

    public void run() throws IOException {
        runOne(Intersection_name, Intersection_contents);

        if (0 != errors)
            throw new RuntimeException(errors + " errors occurred");
    }

    public static void main(String... args) throws IOException {
        new IntersectionPropertiesTest().run();
    }

    private static File writeFile(File dir, String path, String body)
        throws IOException {
        File f = new File(dir, path);
        f.getParentFile().mkdirs();
        try (FileWriter out = new FileWriter(f)) {
            out.write(body);
        }
        return f;
    }

    private class TestProcessor extends JavacTestingAbstractProcessor {

        private Set<? extends Element> rootElements;

        public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
            rootElements = roundEnv.getRootElements();
            if (!rootElements.isEmpty()) {
                performCheck();
            }
            return true;
        }

        private void performCheck() {
            TypeElement typeElement = (TypeElement) rootElements.iterator().next();
            ExecutableElement method = ElementFilter.methodsIn(typeElement.getEnclosedElements()).get(0);
            TypeVariable typeVariable = (TypeVariable) method.getParameters().get(0).asType();

            final TypeMirror upperBound = typeVariable.getUpperBound();

            TypeParameterElement typeParameterElement = ((TypeParameterElement) typeVariable.asElement());
            final List<? extends TypeMirror> bounds = typeParameterElement.getBounds();
            Types types = processingEnv.getTypeUtils();
            final HashSet<TypeMirror> actual = new HashSet<TypeMirror>(types.directSupertypes(upperBound));
            final HashSet<TypeMirror> expected = new HashSet<TypeMirror>(bounds);
            if (!expected.equals(actual)) {
                System.err.println("Mismatched expected and actual bounds.");
                System.err.println("Expected:");
                for(TypeMirror tm : expected)
                    System.err.println("  " + tm);
                System.err.println("Actual:");
                for(TypeMirror tm : actual)
                    System.err.println("  " + tm);
                errors++;
            }

            TypeVariable oneTypeVariable = (TypeVariable) method.getParameters().get(1).asType();
            TypeMirror oneUpperBound = oneTypeVariable.getUpperBound();
            TypeVariable twoTypeVariable = (TypeVariable) method.getParameters().get(2).asType();
            TypeMirror twoUpperBound = twoTypeVariable.getUpperBound();
            TypeElement oneUpperBoundElement = (TypeElement) types.asElement(oneUpperBound);

            Assert.checkNonNull(oneUpperBoundElement);

            Assert.check("java.util.AbstractList".equals(oneUpperBoundElement.getSuperclass().toString()),
                         oneUpperBoundElement.getSuperclass().toString());

            List<String> superInterfaces = new java.util.ArrayList<>();

            for (TypeMirror tm : oneUpperBoundElement.getInterfaces()) {
                superInterfaces.add(tm.toString());
            }

            Assert.check(java.util.Arrays.asList("java.lang.Runnable",
                                                 "java.io.Serializable").equals(superInterfaces),
                         superInterfaces);

            Assert.check(types.isSameType(upperBound, types.capture(upperBound)));
            Assert.check(types.isSameType(types.erasure(typeVariable), types.erasure(upperBound)));

            TypeElement subTypeClass = processingEnv.getElementUtils().getTypeElement("IntersectionTest.SubType");

            Assert.checkNonNull(subTypeClass);

            Assert.check(types.isAssignable(subTypeClass.asType(), oneUpperBound));
            Assert.check(types.isSameType(oneUpperBound, twoUpperBound));
            Assert.check(!types.isSameType(upperBound, twoUpperBound));
            Assert.check(types.isSubtype(subTypeClass.asType(), oneUpperBound));
            Assert.check(types.isSubtype(oneUpperBound, upperBound));
        }

    }

}
