/*
 * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Oracle nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.lang.annotation.Annotation;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.element.*;
import javax.lang.model.element.Modifier;
import javax.lang.model.type.*;
import javax.lang.model.util.*;
import java.lang.reflect.*;
import java.io.Writer;
import java.util.*;

import static javax.lang.model.SourceVersion.RELEASE_9;
import static java.util.Objects.*;

/**
 * This class provides a proof-of-concept implementation of the {@code
 * javax.lang.model.*} API backed by core reflection. That is, rather
 * than having a source file or compile-time class file as the
 * originator of the information about an element or type, as done
 * during standard annotation processing, runtime core reflection
 * objects serve that purpose instead.
 *
 * With this kind of implementation, the same logic can be used for
 * both compile-time and runtime processing of annotations.
 *
 * The nested types in this class define a specialization of {@code
 * javax.lang.model.*} to provide some additional functionality and
 * type information. The original {@code javax.lang.model.*} API was
 * designed to accommodate such a specialization by using wildcards in
 * the return types of methods.
 *
 * It would be technically possible for further specializations of the
 * API implemented in this class to define alternative semantics of
 * annotation look-up. For example to allow one annotation to have the
 * effect of macro-expanding into a set of other annotations.
 *
 * Some aspects of the implementation are left as "exercises for the
 * reader" to complete if interested.
 *
 * When passed null pointers, the methods defined in this type will
 * generally throw null pointer exceptions.
 *
 * To get started, first compile this file with a command line like:
 *
 * <pre>
 * $JDK/bin/javac -parameters -Xdoclint:all/public -Xlint:all -d $OUTPUT_DIR CoreReflectionFactory.java
 * </pre>
 *
 * and then run the main method of {@code CoreReflectionFactory},
 * which will print out a representation of {@code
 * CoreReflectionFactory}. To use the printing logic defined in {@code
 * javac}, put {@code tools.jar} on the classpath as in:
 *
 * <pre>
 * $JDK/bin/java -cp $OUTPUT_DIR:$JDK_ROOT/lib/tools.jar CoreReflectionFactory
 * </pre>
 *
 * @author Joseph D. Darcy (darcy)
 * @author Joel Borggren-Franck (jfranck)
 */
public class CoreReflectionFactory {
    private CoreReflectionFactory() {
        throw new AssertionError("No instances of CoreReflectionFactory for you!");
    }

    /**
     * Returns a reflection type element mirroring a {@code Class} object.
     * @return a reflection type element mirroring a {@code Class} object
     * @param clazz the {@code Class} to mirror
     */
    public static ReflectionTypeElement createMirror(Class<?> clazz) {
        return new CoreReflTypeElement(Objects.requireNonNull(clazz));
    }

    /**
     * Returns a reflection package element mirroring a {@code Package} object.
     * @return a reflection package element mirroring a {@code Package} object
     * @param pkg the {@code Package} to mirror
     */
    public static ReflectionPackageElement createMirror(Package pkg) {
        // Treat a null pkg to mean an unnamed package.
        return new CoreReflPackageElement(pkg);
    }

    /**
     * Returns a reflection variable element mirroring a {@code Field} object.
     * @return a reflection variable element mirroring a {@code Field} object
     * @param field the {@code Field} to mirror
     */
    public static ReflectionVariableElement createMirror(Field field) {
        return new CoreReflFieldVariableElement(Objects.requireNonNull(field));
    }

    /**
     * Returns a reflection executable element mirroring a {@code Method} object.
     * @return a reflection executable element mirroring a {@code Method} object
     * @param method the {@code Method} to mirror
     */
    public static ReflectionExecutableElement createMirror(Method method)  {
        return new CoreReflMethodExecutableElement(Objects.requireNonNull(method));
    }

    /**
     * Returns a reflection executable element mirroring a {@code Constructor} object.
     * @return a reflection executable element mirroring a {@code Constructor} object
     * @param constructor the {@code Constructor} to mirror
     */
    public static ReflectionExecutableElement createMirror(Constructor<?> constructor)  {
        return new CoreReflConstructorExecutableElement(Objects.requireNonNull(constructor));
    }

    /**
     * Returns a type parameter element mirroring a {@code TypeVariable} object.
     * @return a type parameter element mirroring a {@code TypeVariable} object
     * @param tv the {@code TypeVariable} to mirror
     */
    public static TypeParameterElement createMirror(java.lang.reflect.TypeVariable<?> tv) {
        return new CoreReflTypeParameterElement(Objects.requireNonNull(tv));
    }

    /**
     * Returns a variable element mirroring a {@code Parameter} object.
     * @return a variable element mirroring a {@code Parameter} object
     * @param p the {Parameter} to mirror
     */
    public static VariableElement createMirror(java.lang.reflect.Parameter p) {
        return new CoreReflParameterVariableElement(Objects.requireNonNull(p));
    }

    /**
     * Returns an annotation mirror mirroring an annotation object.
     * @return an annotation mirror mirroring an annotation object
     * @param annotation the annotation to mirror
     */
    public static AnnotationMirror createMirror(Annotation annotation)  {
        return new CoreReflAnnotationMirror(Objects.requireNonNull(annotation));
    }

    /**
     * Returns a {@code Types} utility object for type objects backed by core reflection.
     * @return a {@code Types} utility object for type objects backed by core reflection
     */
    public static Types getTypes() {
        return CoreReflTypes.instance();
    }

    /**
     * Returns an {@code Elements} utility object for type objects backed by core reflection.
     * @return an {@code Elements} utility object for type objects backed by core reflection
     */
    public static Elements getElements() {
        return CoreReflElements.instance();
    }

    // Helper
    private static TypeMirror createTypeMirror(Class<?> c) {
        return TypeFactory.instance(Objects.requireNonNull(c));
    }

    /**
     * Main method; prints out a representation of this class.
     * @param args command-line arguments, currently ignored
     */
    public static void main(String... args) {
        getElements().printElements(new java.io.PrintWriter(System.out),
                                    createMirror(CoreReflectionFactory.class));
    }

    /**
     * A specialization of {@code javax.lang.model.element.Element} that is
     * backed by core reflection.
     */
    public static interface ReflectionElement
        extends Element, AnnotatedElement {

        /**
         * {@inheritDoc}
         */
        @Override
        ReflectionElement getEnclosingElement();

        /**
         * {@inheritDoc}
         */
        @Override
        List<ReflectionElement> getEnclosedElements();

        /**
         * Applies a visitor to this element.
         *
         * @param v the visitor operating on this element
         * @param p additional parameter to the visitor
         * @param <R> the return type of the visitor's methods
         * @param <P> the type of the additional parameter to the visitor's methods
         * @return a visitor-specified result
         */
        <R,P> R accept(ReflectionElementVisitor<R,P> v, P p);

        // Functionality specific to the specialization
        /**
         * Returns the underlying core reflection source object, if applicable.
         * @return the underlying core reflection source object, if applicable
         */
        AnnotatedElement getSource();

        // Functionality from javax.lang.model.util.Elements
        /**
         * Returns the package of an element. The package of a package
         * is itself.
         * @return the package of an element
         */
        ReflectionPackageElement getPackage();

    }

    /**
     * A logical specialization of {@code
     * javax.lang.model.element.ElementVisitor} being backed by core
     * reflection.
     *
     * @param <R> the return type of this visitor's methods.
     * @param <P> the type of the additional parameter to this visitor's
     *            methods.
     */
    public static interface ReflectionElementVisitor<R, P> {
        /**
         * Visits an element.
         * @param e  the element to visit
         * @param p  a visitor-specified parameter
         * @return a visitor-specified result
         */
        R visit(ReflectionElement e, P p);

        /**
         * A convenience method equivalent to {@code v.visit(e, null)}.
         * @param e  the element to visit
         * @return a visitor-specified result
         */
        R visit(ReflectionElement e);

        /**
         * Visits a package element.
         * @param e  the element to visit
         * @param p  a visitor-specified parameter
         * @return a visitor-specified result
         */
        R visitPackage(ReflectionPackageElement e, P p);

        /**
         * Visits a type element.
         * @param e  the element to visit
         * @param p  a visitor-specified parameter
         * @return a visitor-specified result
         */
        R visitType(ReflectionTypeElement e, P p);

        /**
         * Visits a variable element.
         * @param e  the element to visit
         * @param p  a visitor-specified parameter
         * @return a visitor-specified result
         */
        R visitVariable(ReflectionVariableElement e, P p);

        /**
         * Visits an executable element.
         * @param e  the element to visit
         * @param p  a visitor-specified parameter
         * @return a visitor-specified result
         */
        R visitExecutable(ReflectionExecutableElement e, P p);

        /**
         * Visits a type parameter element.
         * @param e  the element to visit
         * @param p  a visitor-specified parameter
         * @return a visitor-specified result
         */
        R visitTypeParameter(ReflectionTypeParameterElement e, P p);

        /**
         * Visits an unknown kind of element.
         * This can occur if the language evolves and new kinds
         * of elements are added to the {@code Element} hierarchy.
         *
         * @param e  the element to visit
         * @param p  a visitor-specified parameter
         * @return a visitor-specified result
         * @throws UnknownElementException
         * a visitor implementation may optionally throw this exception
         */
        R visitUnknown(ReflectionElement e, P p);
    }

    /**
     * A specialization of {@code javax.lang.model.element.ExecutableElement} that is
     * backed by core reflection.
     */
    public static interface ReflectionExecutableElement
        extends ReflectionElement, ExecutableElement, ReflectionParameterizable {

        /**
         * {@inheritDoc}
         */
        @Override
        List<ReflectionTypeParameterElement> getTypeParameters();

        /**
         * {@inheritDoc}
         */
        @Override
        List<ReflectionVariableElement> getParameters();

        // Functionality specific to the specialization
        /**
         * Returns all parameters, including synthetic ones.
         * @return all parameters, including synthetic ones
         */
        List<ReflectionVariableElement> getAllParameters();

        /**
         * {@inheritDoc}
         */
        @Override
        Executable getSource();

        /**
         * Returns true if this executable is a synthetic construct; returns false otherwise.
         * @return true if this executable is a synthetic construct; returns false otherwise
         */
        boolean isSynthetic();

        /**
         * Returns true if this executable is a bridge method; returns false otherwise.
         * @return true if this executable is a bridge method; returns false otherwise
         */
        boolean isBridge();
    }

    /**
     * A specialization of {@code javax.lang.model.element.PackageElement} being
     * backed by core reflection.
     */
    public static interface ReflectionPackageElement
        extends ReflectionElement, PackageElement {

        // Functionality specific to the specialization
        /**
         * {@inheritDoc}
         */
        @Override
        Package getSource();
    }

    /**
     * A specialization of {@code javax.lang.model.element.TypeElement} that is
     * backed by core reflection.
     */
    public static interface ReflectionTypeElement
        extends ReflectionElement, TypeElement, ReflectionParameterizable {

        /**
         * {@inheritDoc}
         */
        @Override
        List<ReflectionTypeParameterElement> getTypeParameters();

        /**
         * {@inheritDoc}
         */
        @Override
        List<ReflectionElement> getEnclosedElements();

        // Methods specific to the specialization, but functionality
        // also present in javax.lang.model.util.Elements.
        /**
         * Returns all members of a type element, whether inherited or
         * declared directly. For a class the result also includes its
         * constructors, but not local or anonymous classes.
         * @return all members of the type
         */
        List<ReflectionElement> getAllMembers();

        /**
         * Returns the binary name of a type element.
         * @return the binary name of a type element
         */
        Name getBinaryName();

        // Functionality specific to the specialization
        /**
         * {@inheritDoc}
         */
        @Override
        Class<?> getSource();
    }

    /**
     * A specialization of {@code javax.lang.model.element.TypeParameterElement} being
     * backed by core reflection.
     */
    public static interface ReflectionTypeParameterElement
        extends ReflectionElement, TypeParameterElement {

        /**
         * {@inheritDoc}
         */
        @Override
        ReflectionElement getGenericElement();

        // Functionality specific to the specialization
        /**
         * {@inheritDoc}
         */
        @Override
        java.lang.reflect.TypeVariable<?> getSource();
    }

    /**
     * A specialization of {@code javax.lang.model.element.VariableElement} that is
     * backed by core reflection.
     */
    public static interface ReflectionVariableElement
        extends ReflectionElement, VariableElement {

        // Functionality specific to the specialization
        /**
         * Returns true if this variable is a synthetic construct; returns false otherwise.
         * @return true if this variable is a synthetic construct; returns false otherwise
         */
        boolean isSynthetic();

        /**
         * Returns true if this variable is implicitly declared in source code; returns false otherwise.
         * @return true if this variable is implicitly declared in source code; returns false otherwise
         */
        boolean isImplicit();

        // The VariableElement concept covers fields, variables, and
        // method and constructor parameters. Therefore, this
        // interface cannot define a more precise override of
        // getSource since those three concept have different core
        // reflection types with no supertype more precise than
        // AnnotatedElement.
    }

    /**
     * A specialization of {@code javax.lang.model.element.Parameterizable} being
     * backed by core reflection.
     */
    public static interface ReflectionParameterizable
        extends ReflectionElement, Parameterizable {
        @Override
        List<ReflectionTypeParameterElement> getTypeParameters();
    }

    /**
     * Base class for concrete visitors of elements backed by core reflection.
     */
    public static abstract class AbstractReflectionElementVisitor9<R, P>
        extends AbstractElementVisitor9<R, P>
        implements ReflectionElementVisitor<R, P> {
        protected AbstractReflectionElementVisitor9() {
            super();
        }
    }

    /**
     * Base class for simple visitors of elements that are backed by core reflection.
     */
    @SupportedSourceVersion(value=RELEASE_9)
    public static abstract class SimpleReflectionElementVisitor9<R, P>
        extends SimpleElementVisitor9<R, P>
        implements ReflectionElementVisitor<R, P> {

        protected SimpleReflectionElementVisitor9(){
            super();
        }

        protected SimpleReflectionElementVisitor9(R defaultValue) {
            super(defaultValue);
        }

        // Create manual "bridge methods" for now.

        @Override
        public final R visitPackage(PackageElement e, P p) {
            return visitPackage((ReflectionPackageElement) e , p);
        }

        @Override
        public final R visitType(TypeElement e, P p) {
            return visitType((ReflectionTypeElement) e , p);
        }

        @Override
        public final R visitVariable(VariableElement e, P p) {
            return visitVariable((ReflectionVariableElement) e , p);
        }

        @Override
        public final R visitExecutable(ExecutableElement e, P p) {
            return visitExecutable((ReflectionExecutableElement) e , p);
        }

        @Override
        public final R visitTypeParameter(TypeParameterElement e, P p) {
            return visitTypeParameter((ReflectionTypeParameterElement) e , p);
        }
    }

    /**
     * {@inheritDoc}
     */
    public static interface ReflectionElements  extends Elements {
        /**
         * Returns the innermost enclosing {@link ReflectionTypeElement}
         * of the {@link ReflectionElement} or {@code null} if the
         * supplied ReflectionElement is toplevel or represents a
         * Package.
         *
         * @param e the {@link ReflectionElement} whose innermost
         * enclosing {@link ReflectionTypeElement} is sought
         * @return the innermost enclosing {@link
         * ReflectionTypeElement} or @{code null} if the parameter
         * {@code e} is a toplevel element or a package
         */
        ReflectionTypeElement getEnclosingTypeElement(ReflectionElement e);

        /**
         * {@inheritDoc}
         */
        @Override
        List<? extends ReflectionElement> getAllMembers(TypeElement type);

        /**
         * {@inheritDoc}
         */
        @Override
        ReflectionPackageElement getPackageElement(CharSequence name);

        /**
         * {@inheritDoc}
         */
        @Override
        ReflectionPackageElement getPackageOf(Element type);

        /**
         * {@inheritDoc}
         */
        @Override
        ReflectionTypeElement getTypeElement(CharSequence name);
    }

    // ------------------------- Implementation classes ------------------------

    // Exercise for the reader: review the CoreReflElement class
    // hierarchy below with an eye toward exposing it as an extensible
    // API that could be subclassed to provide customized behavior,
    // such as alternate annotation lookup semantics.

    private static abstract class CoreReflElement
        implements ReflectionElement, AnnotatedElement {
        public abstract AnnotatedElement getSource();

        protected CoreReflElement() {
            super();
        }

        // ReflectionElement methods
        @Override
        public ReflectionPackageElement getPackage() {
            throw new UnsupportedOperationException();
        }

        @Override
        public TypeMirror asType() {
            throw new UnsupportedOperationException(getClass().toString());
        }

        @Override
        public List<? extends AnnotationMirror> getAnnotationMirrors() {
            Annotation[] annotations = getSource().getDeclaredAnnotations();
            int len = annotations.length;

            if (len > 0) {
                List<AnnotationMirror> res = new ArrayList<>(len);
                for (Annotation a : annotations) {
                    res.add(createMirror(a));
                }
                return Collections.unmodifiableList(res);
            } else {
                return Collections.emptyList();
            }
        }

        @Override
        public Set<Modifier> getModifiers() {
            return ModifierUtil.instance(0, false);
        }

        @Override
        public abstract Name getSimpleName();

        @Override
        public abstract ReflectionElement getEnclosingElement();

        @Override
        public abstract List<ReflectionElement> getEnclosedElements();

        //AnnotatedElement methods
        @Override
        public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
            return getSource().getAnnotation(annotationClass);
        }

        @Override
        public <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass) {
            return getSource().getAnnotationsByType(annotationClass);
        }

        @Override
        public Annotation[] getAnnotations() {
            return getSource().getAnnotations();
        }

        @Override
        public <T extends Annotation> T getDeclaredAnnotation(Class<T> annotationClass) {
            return getSource().getDeclaredAnnotation(annotationClass);
        }

        @Override
        public <T extends Annotation> T[] getDeclaredAnnotationsByType(Class<T> annotationClass) {
            return getSource().getDeclaredAnnotationsByType(annotationClass);
        }

        @Override
        public Annotation[] getDeclaredAnnotations() {
            return getSource().getDeclaredAnnotations();
        }

        // java.lang.Object methods
        @Override
        public boolean equals(Object obj) {
            if (obj instanceof CoreReflElement) {
                CoreReflElement other = (CoreReflElement)obj;
                return Objects.equals(other.getSource(), this.getSource());
            }
            return false;
        }

        @Override
        public int hashCode() {
            return Objects.hashCode(getSource());
        }

        @Override
        public String toString() {
            return getKind().toString() + " " + getSimpleName().toString();
        }
    }

    // Type
    private static class CoreReflTypeElement extends CoreReflElement
        implements ReflectionTypeElement {
        private final Class<?> source;

        protected CoreReflTypeElement(Class<?> source) {
            Objects.requireNonNull(source);
            if (source.isPrimitive() ||
                source.isArray()) {
                throw new IllegalArgumentException("Cannot create a ReflectionTypeElement based on class: " + source);
            }

            this.source = source;
        }

        @Override
        public TypeMirror asType() {
            return createTypeMirror(source);
        }

        @Override
        public Class<?> getSource() {
            return source;
        }

        @Override
        public boolean equals(Object o) {
            if (o instanceof CoreReflTypeElement) {
                return source.equals(((CoreReflTypeElement)o).getSource());
            } else {
                return false;
            }
        }

        @Override
        public <R,P> R accept(ElementVisitor<R,P> v, P p) {
            return v.visitType(this, p);
        }

        @Override
        public <R,P> R accept(ReflectionElementVisitor<R,P> v, P p) {
            return v.visitType(this, p);
        }

        @Override
        public Set<Modifier> getModifiers() {
            return ModifierUtil.instance(source.getModifiers() &
                                         (source.isInterface() ?
                                          java.lang.reflect.Modifier.interfaceModifiers() :
                                          java.lang.reflect.Modifier.classModifiers()),
                                         false);
        }

        @Override
        public List<ReflectionElement> getEnclosedElements() {
            List<ReflectionElement> enclosedElements = new ArrayList<>();

            for (Class<?> declaredClass : source.getDeclaredClasses()) {
                enclosedElements.add(createMirror(declaredClass));
            }

            // Add elements in the conventional ordering: fields, then
            // constructors, then methods.
            for (Field f : source.getDeclaredFields()) {
                enclosedElements.add(createMirror(f));
            }

            for (Constructor<?> c : source.getDeclaredConstructors()) {
                enclosedElements.add(createMirror(c));
            }

            for (Method m : source.getDeclaredMethods()) {
                enclosedElements.add(createMirror(m));
            }

            return (enclosedElements.isEmpty() ?
                    Collections.emptyList():
                    Collections.unmodifiableList(enclosedElements));
        }

        // Review for default method handling.
        @Override
        public List<ReflectionElement> getAllMembers() {
            List<ReflectionElement> allMembers = new ArrayList<>();

            // If I only had a MultiMap ...
            List<ReflectionElement> fields = new ArrayList<>();
            List<ReflectionExecutableElement> methods = new ArrayList<>();
            List<ReflectionElement> classes = new ArrayList<>();

            // Add all fields for this class
            for (Field f : source.getDeclaredFields()) {
                fields.add(createMirror(f));
            }

            // Add all methods for this class
            for (Method m : source.getDeclaredMethods()) {
                methods.add(createMirror(m));
            }

            // Add all classes for this class, except anonymous/local as per Elements.getAllMembers doc
            for (Class<?> c : source.getDeclaredClasses()) {
                if (c.isLocalClass() || c.isAnonymousClass())
                    continue;
                classes.add(createMirror(c));
            }

            Class<?> cls = source;
            if (cls.isInterface()) {
                cls = null;
            }
            do {
                // Walk up superclasses adding non-private elements.
                // If source is an interface, just add Object's
                // elements.

                if (cls == null) {
                    cls = java.lang.Object.class;
                } else {
                    cls = cls.getSuperclass();
                }

                addMembers(cls, fields, methods, classes);

            } while (cls != java.lang.Object.class);

            // add members on (super)interface(s)
            Set<Class<?>> seenInterfaces = new HashSet<>();
            Queue<Class<?>> interfaces = new LinkedList<>();
            if (source.isInterface()) {
                seenInterfaces.add(source);
                interfaces.add(source);
            } else {
                Class<?>[] ifaces = source.getInterfaces();
                for (Class<?> iface : ifaces) {
                    seenInterfaces.add(iface);
                    interfaces.add(iface);
                }
            }

            while (interfaces.peek() != null) {
                Class<?> head = interfaces.remove();
                addMembers(head, fields, methods, classes);

                Class<?>[] ifaces = head.getInterfaces();
                for (Class<?> iface : ifaces) {
                    if (!seenInterfaces.contains(iface)) {
                        seenInterfaces.add(iface);
                        interfaces.add(iface);
                    }
                }
            }

            // Add constructors
            for (Constructor<?> c : source.getDeclaredConstructors()) {
                allMembers.add(createMirror(c));
            }

            // Add all unique methods
            allMembers.addAll(methods);

            // Add all unique fields
            allMembers.addAll(fields);

            // Add all unique classes
            allMembers.addAll(classes);

            return Collections.unmodifiableList(allMembers);
        }

        private void addMembers(Class<?> cls,
                                List<ReflectionElement> fields,
                                List<ReflectionExecutableElement> methods,
                                List<ReflectionElement> classes) {
            Elements elements = getElements();

            for (Field f : cls.getDeclaredFields()) {
                if (java.lang.reflect.Modifier.isPrivate(f.getModifiers())) { continue; }
                ReflectionElement tmp = createMirror(f);
                boolean add = true;
                for (ReflectionElement e : fields) {
                    if (elements.hides(e, tmp)) {
                        add = false;
                        break;
                    }
                }
                if (add) {
                    fields.add(tmp);
                }
            }

            for (Method m : cls.getDeclaredMethods()) {
                if (java.lang.reflect.Modifier.isPrivate(m.getModifiers()))
                    continue;

                ReflectionExecutableElement tmp = createMirror(m);
                boolean add = true;
                for (ReflectionExecutableElement e : methods) {
                    if (elements.hides(e, tmp)) {
                        add = false;
                        break;
                    } else if (elements.overrides(e, tmp, this)) {
                        add = false;
                        break;
                    }
                }
                if (add) {
                    methods.add(tmp);
                }
            }

            for (Class<?> c : cls.getDeclaredClasses()) {
                if (java.lang.reflect.Modifier.isPrivate(c.getModifiers()) ||
                    c.isLocalClass() ||
                    c.isAnonymousClass())
                    continue;

                ReflectionElement tmp = createMirror(c);
                boolean add = true;
                for (ReflectionElement e : classes) {
                    if (elements.hides(e, tmp)) {
                        add = false;
                        break;
                    }
                }
                if (add) {
                    classes.add(tmp);
                }
            }
        }

        @Override
        public ElementKind getKind() {
            if (source.isInterface()) {
                if (source.isAnnotation())
                    return ElementKind.ANNOTATION_TYPE;
                else
                    return ElementKind.INTERFACE;
            } else if (source.isEnum()) {
                return ElementKind.ENUM;
            } else
                return ElementKind.CLASS;
        }

        @Override
        public NestingKind getNestingKind() {
            if (source.isAnonymousClass())
                return NestingKind.ANONYMOUS;
            else if (source.isLocalClass())
                return NestingKind.LOCAL;
            else if (source.isMemberClass())
                return NestingKind.MEMBER;
            else return
                NestingKind.TOP_LEVEL;
        }

        @Override
        public Name getQualifiedName() {
            String name = source.getCanonicalName(); // TODO, this should be a FQN for
                                                     // the current element
            if (name == null)
                name = "";
            return StringName.instance(name);
        }

        @Override
        public Name getSimpleName() {
            return StringName.instance(source.getSimpleName());
        }

        @Override
        public TypeMirror getSuperclass() {
            if (source.equals(java.lang.Object.class)) {
                return NoType.getNoneInstance();
            } else {
                return createTypeMirror(source.getSuperclass());
            }
        }

        @Override
        public List<? extends TypeMirror> getInterfaces() {
            Class[] interfaces = source.getInterfaces();
            int len = interfaces.length;
            List<TypeMirror> res = new ArrayList<>(len);

            if (len > 0) {
                for (Class<?> c : interfaces) {
                    res.add(createTypeMirror(c));
                }
            } else {
                return Collections.emptyList();
            }
            return Collections.unmodifiableList(res);
        }

        @Override
        public List<ReflectionTypeParameterElement> getTypeParameters() {
            return createTypeParameterList(source);
        }

        @Override
        public ReflectionElement getEnclosingElement() {
            // Returns the package of a top-level type and returns the
            // immediately lexically enclosing element for a nested type.

            switch(getNestingKind()) {
            case TOP_LEVEL:
                return createMirror(source.getPackage());
            case MEMBER:
                return createMirror(source.getEnclosingClass());
            default:
                if (source.getEnclosingConstructor() != null) {
                    return createMirror(source.getEnclosingConstructor());
                } else if (source.getEnclosingMethod() != null) {
                    return createMirror(source.getEnclosingMethod());
                } else {
                    return createMirror(source.getEnclosingClass());
                }
            }
        }

        @Override
        public Name getBinaryName() {
            return StringName.instance(getSource().getName());
        }
    }

    private static abstract class CoreReflExecutableElement extends CoreReflElement
        implements ReflectionExecutableElement {

        protected Executable source = null;
        protected final List<CoreReflParameterVariableElement> parameters;

        protected CoreReflExecutableElement(Executable source,
                                            List<CoreReflParameterVariableElement> parameters) {
            this.source = Objects.requireNonNull(source);
            this.parameters = Objects.requireNonNull(parameters);
        }

        @Override
        public <R,P> R accept(ElementVisitor<R,P> v, P p) {
            return v.visitExecutable(this, p);
        }

        @Override
        public <R,P> R accept(ReflectionElementVisitor<R,P> v, P p) {
            return v.visitExecutable(this, p);
        }

        @Override
        public abstract ExecutableType asType();

        // Only Types and Packages enclose elements; see Element.getEnclosedElements()
        @Override
        public List<ReflectionElement> getEnclosedElements() {
            return Collections.emptyList();
        }

        @Override
        public List<ReflectionVariableElement> getParameters() {
            List<ReflectionVariableElement> tmp = new ArrayList<>();
            for (ReflectionVariableElement parameter : parameters) {
                if (!parameter.isSynthetic())
                    tmp.add(parameter);
            }
            return tmp;
        }

        @Override
        public List<ReflectionVariableElement> getAllParameters() {
            // Could "fix" this if the return type included wildcards
            @SuppressWarnings("unchecked")
            List<ReflectionVariableElement> tmp = (List<ReflectionVariableElement>)(List)parameters;
            return tmp;
        }

        @Override
        public List<? extends TypeMirror> getThrownTypes() {
            Class<?>[] thrown = source.getExceptionTypes();
            int len = thrown.length;
            List<TypeMirror> res = new ArrayList<>(len);

            if (len > 0) {
                for (Class<?> c : thrown) {
                    res.add(createTypeMirror(c));
                }
            } else {
                return Collections.emptyList();
            }
            return Collections.unmodifiableList(res);
        }

        @Override
        public boolean isVarArgs() {
            return source.isVarArgs();
        }

        @Override
        public boolean isSynthetic() {
            return source.isSynthetic();
        }

        @Override
        public boolean isBridge() {
            return false;
        }

        @Override
        public List<ReflectionTypeParameterElement> getTypeParameters() {
            return createTypeParameterList(source);
        }

        public abstract AnnotationValue getDefaultValue();

        @Override
        public TypeMirror getReceiverType() {
            // New in JDK 8
            throw new UnsupportedOperationException(this.toString());
        }
    }

    private static class CoreReflConstructorExecutableElement
        extends CoreReflExecutableElement {

        protected CoreReflConstructorExecutableElement(Constructor<?> source) {
            super(Objects.requireNonNull(source),
                  createParameterList(source));
        }

        @Override
        public  Constructor<?> getSource() {
            return (Constructor<?>)source;
        }

        @Override
        public TypeMirror getReturnType() {
            return NoType.getVoidInstance();
        }

        @Override
        public ExecutableType asType() {
            throw new UnsupportedOperationException(getClass().toString());
        }

        @Override
        public boolean equals(Object o) {
            if (o instanceof CoreReflConstructorExecutableElement) {
                return source.equals(((CoreReflConstructorExecutableElement)o).getSource());
            } else {
                return false;
            }
        }

        @Override
        public ElementKind getKind() {
            return ElementKind.CONSTRUCTOR;
        }

        @Override
        public Set<Modifier> getModifiers() {
            return ModifierUtil.instance(source.getModifiers() &
                                         java.lang.reflect.Modifier.constructorModifiers(), false);
        }

        @Override
        public ReflectionElement getEnclosingElement() {
            return createMirror(source.getDeclaringClass());
        }

        @Override
        public Name getSimpleName() {
            return StringName.instance("<init>");
        }

        @Override
        public AnnotationValue getDefaultValue() {
            // a constructor is never an annotation element
            return null;
        }

        @Override
        public boolean isDefault() {
            return false; // A constructor cannot be a default method
        }
    }

    private static class CoreReflMethodExecutableElement
        extends CoreReflExecutableElement {

        protected CoreReflMethodExecutableElement(Method source) {
            super(Objects.requireNonNull(source),
                  createParameterList(source));
            this.source = source;
        }

        @Override
        public Method getSource() {
            return (Method)source;
        }

        @Override
        public TypeMirror getReturnType() {
            return TypeFactory.instance(getSource().getReturnType());
        }

        @Override
        public boolean equals(Object o) {
            if (o instanceof CoreReflMethodExecutableElement) {
                return source.equals( ((CoreReflMethodExecutableElement)o).getSource());
            } else {
                return false;
            }
        }

        @Override
        public ElementKind getKind() {
            return ElementKind.METHOD;
        }

        @Override
        public Set<Modifier> getModifiers() {
            return ModifierUtil.instance(source.getModifiers() &
                                         java.lang.reflect.Modifier.methodModifiers(),
                                         isDefault());
        }

        @Override
        public ReflectionElement getEnclosingElement() {
            return createMirror(source.getDeclaringClass());
        }

        @Override
        public Name getSimpleName() {
            return StringName.instance(source.getName());
        }

        @Override
        public AnnotationValue getDefaultValue() {
            Object value = getSource().getDefaultValue();
            if (null == value) {
                return null;
            } else {
                return new CoreReflAnnotationValue(value);
            }
        }

        @Override
        public boolean isDefault() {
            return getSource().isDefault();
        }

        @Override
        public boolean isBridge() {
            return getSource().isBridge();
        }

        @Override
        public ExecutableType asType() {
            return TypeFactory.instance(getSource());
        }
    }

    private static List<CoreReflParameterVariableElement> createParameterList(Executable source) {
        Parameter[] parameters = source.getParameters();
        int length = parameters.length;
        if (length == 0)
            return Collections.emptyList();
        else {
            List<CoreReflParameterVariableElement> tmp = new ArrayList<>(length);
            for (Parameter parameter : parameters) {
                tmp.add(new CoreReflParameterVariableElement(parameter));
            }
            return Collections.unmodifiableList(tmp);
        }
    }

    private static List<ReflectionTypeParameterElement> createTypeParameterList(GenericDeclaration source) {
        java.lang.reflect.TypeVariable<?>[] typeParams = source.getTypeParameters();
        int length = typeParams.length;
        if (length == 0)
            return Collections.emptyList();
        else {
            List<ReflectionTypeParameterElement> tmp = new ArrayList<>(length);
            for (java.lang.reflect.TypeVariable<?> typeVar : typeParams)
                tmp.add(new CoreReflTypeParameterElement(typeVar));
            return Collections.unmodifiableList(tmp);
        }
    }

    private static class CoreReflTypeParameterElement
        extends CoreReflElement
        implements ReflectionTypeParameterElement {

        private final GenericDeclaration source;
        private final java.lang.reflect.TypeVariable<?> sourceTypeVar;

        protected CoreReflTypeParameterElement(java.lang.reflect.TypeVariable<?> sourceTypeVar) {
            this.sourceTypeVar = Objects.requireNonNull(sourceTypeVar);
            this.source = Objects.requireNonNull(sourceTypeVar.getGenericDeclaration());
        }

        @Override
        public java.lang.reflect.TypeVariable<?> getSource() {
            return sourceTypeVar;
        }

        protected java.lang.reflect.TypeVariable<?> getSourceTypeVar() {
            return sourceTypeVar;
        }

        @Override
        public boolean equals(Object o) {
            if (o instanceof CoreReflTypeParameterElement) {
                return sourceTypeVar.equals(((CoreReflTypeParameterElement)o).sourceTypeVar);
            } else {
                return false;
            }
        }

        @Override
        public <R,P> R accept(ElementVisitor<R,P> v, P p) {
            return v.visitTypeParameter(this, p);
        }

        @Override
        public <R,P> R accept(ReflectionElementVisitor<R,P> v, P p) {
            return v.visitTypeParameter(this, p);
        }

        @Override
        public List<ReflectionElement> getEnclosedElements() {
            return Collections.emptyList();
        }

        @Override
        public ReflectionElement getEnclosingElement() {
            if (source instanceof Class)
                return createMirror((Class<?>)source);
            else if (source instanceof Method)
                return createMirror((Method)source);
            else if (source instanceof Constructor)
                return createMirror((Constructor<?>)source);
            else
                throw new AssertionError("Unexpected enclosing element: " + source);
        }

        @Override
        public ElementKind getKind() {
            return ElementKind.TYPE_PARAMETER;
        }

        @Override
        public Name getSimpleName() {
            return StringName.instance(sourceTypeVar.getName());
        }

        // TypeParameterElement methods
        @Override
        public ReflectionElement getGenericElement() {
            return getEnclosingElement(); // As per the doc,
                                          // getEnclosingElement and
                                          // getGenericElement return
                                          // the same information.
        }

        @Override
        public List<? extends TypeMirror> getBounds() {
            Type[] types = getSourceTypeVar().getBounds();
            int len = types.length;

            if (len > 0) {
                List<TypeMirror> res = new ArrayList<>(len);
                for (Type t : types) {
                    res.add(TypeFactory.instance(t));
                }
                return Collections.unmodifiableList(res);
            } else {
                return Collections.emptyList();
            }
        }
    }

    private abstract static class CoreReflVariableElement extends CoreReflElement
        implements ReflectionVariableElement {

        protected CoreReflVariableElement() {}

        // Element visitor
        @Override
        public <R,P> R accept(ElementVisitor<R,P>v, P p) {
            return v.visitVariable(this, p);
        }

        // ReflectElement visitor
        @Override
        public <R,P> R accept(ReflectionElementVisitor<R,P> v, P p) {
            return v.visitVariable(this, p);
        }

        @Override
        public List<ReflectionElement> getEnclosedElements() {
            return Collections.emptyList();
        }

        @Override
        public ReflectionElement getEnclosingElement() {
            return null;
        }

        @Override
        public boolean isSynthetic() {
            return false;
        }

        @Override
        public boolean isImplicit() {
            return false;
        }
    }

    private static class CoreReflFieldVariableElement extends CoreReflVariableElement {
        private final Field source;

        protected CoreReflFieldVariableElement(Field source) {
            this.source = Objects.requireNonNull(source);
        }

        @Override
        public Field getSource() {
            return source;
        }

        @Override
        public TypeMirror asType() {
            return createTypeMirror(getSource().getType());
        }

        @Override
        public ElementKind getKind() {
            if (source.isEnumConstant())
                return ElementKind.ENUM_CONSTANT;
            else
                return ElementKind.FIELD;
        }

        @Override
        public Set<Modifier> getModifiers() {
            return ModifierUtil.instance(source.getModifiers() &
                                         java.lang.reflect.Modifier.fieldModifiers(), false);
        }

        @Override
        public Name getSimpleName() {
            return StringName.instance(source.getName());
        }

        @Override
        public ReflectionElement getEnclosingElement() {
            return createMirror(source.getDeclaringClass());
        }

        @Override
        public boolean equals(Object o) {
            if (o instanceof CoreReflFieldVariableElement) {
                return Objects.equals(source,
                                      ((CoreReflFieldVariableElement)o).getSource());
            } else {
                return false;
            }
        }

        @Override
        public Object getConstantValue() {
            Field target = source;

            // The api says only Strings and primitives may be compile time constants.
            // Ensure field is that, and final.
            //
            // Also, we don't have an instance so restrict to static Fields
            //
            if (!(source.getType().equals(java.lang.String.class)
                  || source.getType().isPrimitive())) {
                return null;
            }
            final int modifiers = target.getModifiers();
            if (!( java.lang.reflect.Modifier.isFinal(modifiers) &&
                   java.lang.reflect.Modifier.isStatic(modifiers))) {
                return null;
            }

            try {
                return target.get(null);
            } catch (IllegalAccessException e) {
                try {
                    target.setAccessible(true);
                    return target.get(null);
                } catch (IllegalAccessException i) {
                    throw new SecurityException(i);
                }
            }
        }
    }

    private static class CoreReflParameterVariableElement
        extends CoreReflVariableElement {
        private final Parameter source;

        protected CoreReflParameterVariableElement(Parameter source) {
            this.source = Objects.requireNonNull(source);
        }

        @Override
        public Parameter getSource() {
            return source;
        }

        @Override
        public Set<Modifier> getModifiers() {
            return ModifierUtil.instance(source.getModifiers() &
                                         java.lang.reflect.Modifier.parameterModifiers(), false);
        }

        @Override
        public TypeMirror asType() {
            // TODO : switch to parameterized type
            return createTypeMirror(source.getType());
        }

        @Override
        public ElementKind getKind() {
            return ElementKind.PARAMETER;
        }

        @Override
        public Name getSimpleName() {
            return StringName.instance(source.getName());
        }

        @Override
        public ReflectionElement getEnclosingElement() {
            Executable enclosing = source.getDeclaringExecutable();
            if (enclosing instanceof Method)
                return createMirror((Method)enclosing);
            else if (enclosing instanceof Constructor)
                return createMirror((Constructor<?>)enclosing);
            else
                throw new AssertionError("Bad enclosing value.");
        }

        @Override
        public boolean equals(Object o) {
            if (o instanceof CoreReflParameterVariableElement) {
                return source.equals(((CoreReflParameterVariableElement) o).getSource());
            } else
                return false;
        }

        // VariableElement methods
        @Override
        public Object getConstantValue() {
            return null;
        }

        @Override
        public boolean isSynthetic() {
            return source.isSynthetic();
        }

        @Override
        public boolean isImplicit() {
            return source.isImplicit();
        }
    }

    private static class CoreReflPackageElement extends CoreReflElement
        implements ReflectionPackageElement {

        private final Package source;

        protected CoreReflPackageElement(Package source) {
            this.source = source;
        }

        @Override
        public Package getSource() {
            return source;
        }

        @Override
        public <R,P> R accept(ElementVisitor<R,P> v, P p) {
            return v.visitPackage(this, p);
        }

        @Override
        public <R,P> R accept(ReflectionElementVisitor<R,P> v, P p) {
            return v.visitPackage(this, p);
        }

        @Override
        public boolean equals(Object o) {
            if (o instanceof CoreReflPackageElement) {
                return Objects.equals(source,
                                      ((CoreReflPackageElement)o).getSource());
            } else {
                return false;
            }
        }

        @Override
        public ElementKind getKind() {
            return ElementKind.PACKAGE;
        }

        @Override
        public ReflectionElement getEnclosingElement() {
            return null;
        }

        @Override
        public List<ReflectionElement> getEnclosedElements() {
            throw new UnsupportedOperationException();
        }

        @Override
        public Name getQualifiedName() {
            return StringName.instance((source != null) ?
                                       source.getName() :
                                       "" );
        }

        @Override
        public Name getSimpleName() {
            String n = ((source != null) ?
                        source.getName() :
                        "");
            int index = n.lastIndexOf('.');
            if (index > 0) {
                return StringName.instance(n.substring(index + 1, n.length()));
            } else {
                return StringName.instance(n);
            }
        }

        @Override
        public boolean isUnnamed() {
            if (source != null) {
                String name = source.getName();
                return(name == null || name.isEmpty());
            } else
                return true;
        }
    }

    private static class CoreReflAnnotationMirror
        implements javax.lang.model.element.AnnotationMirror {
        private final Annotation annotation;

        protected CoreReflAnnotationMirror(Annotation annotation) {
            this.annotation = Objects.requireNonNull(annotation);
        }

        @Override
        public DeclaredType getAnnotationType() {
            return (DeclaredType)TypeFactory.instance(annotation.annotationType());
        }

        @Override
        public Map<? extends ReflectionExecutableElement, ? extends AnnotationValue> getElementValues() {
            // This differs from the javac implementation in that it returns default values

            Method[] elems = annotation.annotationType().getDeclaredMethods();
            int len = elems.length;

            if (len > 0) {
                Map<ReflectionExecutableElement, AnnotationValue> res = new HashMap<>();
                for (Method m : elems) {
                    AnnotationValue v;
                    try {
                        v = new CoreReflAnnotationValue(m.invoke(annotation));
                    } catch (IllegalAccessException e) {
                        try {
                            m.setAccessible(true);
                            v = new CoreReflAnnotationValue(m.invoke(annotation));
                        } catch (IllegalAccessException i) {
                            throw new SecurityException(i);
                        } catch (InvocationTargetException ee) {
                            throw new RuntimeException(ee);
                        }
                    } catch (InvocationTargetException ee) {
                        throw new RuntimeException(ee);
                    }
                    ReflectionExecutableElement e = createMirror(m);
                    res.put(e, v);
                }

                return Collections.unmodifiableMap(res);
            } else {
                return Collections.emptyMap();
            }
        }

        @Override
        public boolean equals(Object other) {
            if (other instanceof CoreReflAnnotationMirror) {
                return annotation.equals(((CoreReflAnnotationMirror)other).annotation);
            } else {
                return false;
            }
        }

        @Override
        public int hashCode() {
            return Objects.hashCode(annotation);
        }

        @Override
        public String toString() {
            return annotation.toString();
        }
    }

    private static class CoreReflAnnotationValue
        implements javax.lang.model.element.AnnotationValue {
        private Object value = null;

        protected CoreReflAnnotationValue(Object value) {
            // Is this constraint really necessary?
            Objects.requireNonNull(value);
            this.value = value;
        }

        @Override
        public Object getValue() {
            return value;
        }

        @Override
        public String toString() {
            return value.toString();
        }

        @Override
        public <R,P> R accept(AnnotationValueVisitor<R,P> v, P p) {
            return v.visit(this, p);
        }
    }

    // Helper utility classes

    private static class StringName implements Name {
        private String name;

        private StringName(String name) {
            this.name = Objects.requireNonNull(name);
        }

        public static StringName instance(String name) {
            return new StringName(name);
        }

        @Override
        public int length() {
            return name.length();
        }

        @Override
        public char charAt(int index) {
            return name.charAt(index);
        }

        @Override
        public CharSequence subSequence(int start, int end) {
            return name.subSequence(start, end);
        }

        @Override
        public String toString() {
            return name;
        }

        @Override
        public boolean equals(Object other) {
            if (other instanceof StringName) {
                return name.equals(((StringName) other).name);
            } else {
                return false;
            }
        }

        @Override
        public int hashCode() {
            return name.hashCode();
        }

        @Override
        public boolean contentEquals(CharSequence cs) {
            return name.contentEquals(cs);
        }
    }

    /*
     * Given an {@code int} value of modifiers, return a proper immutable set
     * of {@code Modifier}s as a result.
     */
    private static class ModifierUtil {
        private ModifierUtil() {
            throw new AssertionError("No instances for you.");
        }

        // Exercise for the reader: explore if caching of sets of
        // Modifiers would be helpful.

        public static Set<Modifier> instance(int modifiers, boolean isDefault) {
            Set<Modifier> modSet = EnumSet.noneOf(Modifier.class);

            if (java.lang.reflect.Modifier.isAbstract(modifiers))
                modSet.add(Modifier.ABSTRACT);

            if (java.lang.reflect.Modifier.isFinal(modifiers))
                modSet.add(Modifier.FINAL);

            if (java.lang.reflect.Modifier.isNative(modifiers))
                modSet.add(Modifier.NATIVE);

            if (java.lang.reflect.Modifier.isPrivate(modifiers))
                modSet.add(Modifier.PRIVATE);

            if (java.lang.reflect.Modifier.isProtected(modifiers))
                modSet.add(Modifier.PROTECTED);

            if (java.lang.reflect.Modifier.isPublic(modifiers))
                modSet.add(Modifier.PUBLIC);

            if (java.lang.reflect.Modifier.isStatic(modifiers))
                modSet.add(Modifier.STATIC);

            if (java.lang.reflect.Modifier.isStrict(modifiers))
                modSet.add(Modifier.STRICTFP);

            if (java.lang.reflect.Modifier.isSynchronized(modifiers))
                modSet.add(Modifier.SYNCHRONIZED);

            if (java.lang.reflect.Modifier.isTransient(modifiers))
                modSet.add(Modifier.TRANSIENT);

            if (java.lang.reflect.Modifier.isVolatile(modifiers))
                modSet.add(Modifier.VOLATILE);

            if (isDefault)
                modSet.add(Modifier.DEFAULT);

            return Collections.unmodifiableSet(modSet);
        }
    }

    private abstract static class AbstractTypeMirror implements TypeMirror {
        private final TypeKind kind;

        protected AbstractTypeMirror(TypeKind kind) {
            this.kind = Objects.requireNonNull(kind);
        }

        @Override
        public TypeKind getKind() {
            return kind;
        }

        @Override
        public <R,P> R accept(TypeVisitor<R,P> v, P p) {
            return v.visit(this, p);
        }

        //Types methods
        abstract List<? extends TypeMirror> directSuperTypes();

        TypeMirror capture() {
            // Exercise for the reader: make this abstract and implement in subtypes
            throw new UnsupportedOperationException();
        }

        TypeMirror erasure() {
            // Exercise for the reader: make this abstract and implement in subtypes
            throw new UnsupportedOperationException();
        }

        // Exercise for the reader: implement the AnnotatedConstruct methods
        @Override
        public List<? extends AnnotationMirror> getAnnotationMirrors() {
            throw new UnsupportedOperationException();
        }

        @Override
        public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
            throw new UnsupportedOperationException();
        }

        @Override
        public <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass) {
            throw new UnsupportedOperationException();
        }
    }

    private static class CoreReflArrayType extends AbstractTypeMirror
        implements javax.lang.model.type.ArrayType,
                   Reifiable {
        private Class<?> source = null;
        private Class<?> component = null;
        private TypeMirror eagerComponent = null;

        protected CoreReflArrayType(Class<?> source) {
            super(TypeKind.ARRAY);
            this.source = source;
            this.component = source.getComponentType();
            this.eagerComponent = TypeFactory.instance(component);
        }

        public TypeMirror getComponentType() {
            return eagerComponent;
        }

        @Override
        public Class<?> getSource() {
            return source;
        }

        @Override
        List<? extends TypeMirror> directSuperTypes() {
            final TypeMirror componentType = getComponentType();
            final TypeMirror[] directSupers;

            // JLS v4 4.10.3
            if (componentType.getKind().isPrimitive() ||
                component.equals(java.lang.Object.class)) {
                directSupers = new TypeMirror[3];
                directSupers[0] = TypeFactory.instance(java.lang.Object.class);
                directSupers[1] = TypeFactory.instance(java.lang.Cloneable.class);
                directSupers[2] = TypeFactory.instance(java.io.Serializable.class);
            } else if (componentType.getKind() == TypeKind.ARRAY) {
                List<? extends TypeMirror> componentDirectSupertypes = CoreReflTypes.instance().directSupertypes(componentType);
                directSupers = new TypeMirror[componentDirectSupertypes.size()];
                for (int i = 0; i < directSupers.length; i++) {
                    directSupers[i] = new CoreReflArrayType(Array.newInstance(((Reifiable)componentDirectSupertypes.get(i)).getSource(), 0).getClass());
                }
            } else {
                Class<?> superClass = component.getSuperclass();
                Class<?>[] interfaces = component.getInterfaces();
                directSupers = new TypeMirror[1 + interfaces.length];

                directSupers[0] = TypeFactory.instance(Array.newInstance(superClass, 0).getClass());

                for (int i = 0; i < interfaces.length; i++) {
                    directSupers[i + 1] = TypeFactory.instance(Array.newInstance(interfaces[i],0).getClass());
                }
            }

            return Collections.unmodifiableList(Arrays.asList(directSupers));
        }

        @Override
        public String toString() {
            return getKind() + " of " + getComponentType().toString();
        }
    }

    private static class CaptureTypeVariable extends AbstractTypeMirror implements javax.lang.model.type.TypeVariable {
        private TypeMirror source = null;
        private TypeMirror upperBound = null;
        private TypeMirror lowerBound = null;

        CaptureTypeVariable(TypeMirror source,
                            TypeMirror upperBound,
                            TypeMirror lowerBound) {
            super(TypeKind.TYPEVAR);

            this.source = Objects.requireNonNull(source);
            this.upperBound = (upperBound == null ? CoreReflTypes.instance().getNullType() : upperBound);
            this.lowerBound = (lowerBound == null ? CoreReflTypes.instance().getNullType() : lowerBound);
        }

        protected Class<?> getSource() {
            if (source instanceof CoreReflDeclaredType) {
                return ((CoreReflDeclaredType)source).getSource();
            } else {
                return null;
            }
        }

        @Override
        public TypeMirror getUpperBound() {
            return upperBound;
        }

        @Override
        public TypeMirror getLowerBound() {
            return lowerBound;
        }

        @Override
        public Element asElement() {
            if (null == getSource()) {
                return null;
            }
            return CoreReflectionFactory.createMirror(getSource());
        }

        @Override
        List<? extends TypeMirror> directSuperTypes() {
            throw new UnsupportedOperationException();

        }

        @Override
        public String toString() {
            return getKind() + " CAPTURE of: " + source.toString();
        }
    }

    private static class CoreReflElements implements ReflectionElements {
        private CoreReflElements() {} // mostly one instance for you

        private static CoreReflElements instance = new CoreReflElements();

        static CoreReflElements instance() {
            return instance;
        }

        /**
         * {@inheritDoc}
         */
        @Override
        public ReflectionPackageElement getPackageElement(CharSequence name) {
            return createMirror(Package.getPackage(name.toString()));
        }

        /**
         * {@inheritDoc}
         */
        @Override
        public ReflectionTypeElement getTypeElement(CharSequence name) {
            // where name is a Canonical Name jls 6.7
            // but this method will probably accept an equivalent FQN
            // depending on Class.forName(String)

            ReflectionTypeElement tmp = null;

            // Filter out arrays
            String n = name.toString();
            if (n.contains("[")) return null;
            if (n.equals("")) return null;

            // The intention of this loop is to handle nested
            // elements.  If finding the element using Class.forName
            // fails, an attempt is made to find the element as an
            // enclosed element by trying fo find a prefix of the name
            // (dropping a trailing ".xyz") and looking for "xyz" as
            // an enclosed element.

            Deque<String> parts = new ArrayDeque<>();
            boolean again;
            do {
                again = false;
                try {
                    tmp = createMirror(Class.forName(n));
                } catch (ClassNotFoundException e) {
                    tmp = null;
                }

                if (tmp != null) {
                    if (parts.isEmpty()) {
                        return tmp;
                    }

                    tmp = findInner(tmp, parts);
                    if (tmp != null) {
                        return tmp;
                    }
                }

                int indx = n.lastIndexOf('.');
                if (indx > -1) {
                    parts.addFirst(n.substring(indx + 1));
                    n = n.substring(0, indx);
                    again = true;
                }
            } while (again);

            return null;
        }

        // Recursively finds enclosed type elements named as part.top() popping part and repeating
        private ReflectionTypeElement findInner(ReflectionTypeElement e, Deque<String> parts) {
            if (parts.isEmpty()) {
                return e;
            }

            String part = parts.removeFirst();
            List<ReflectionElement> enclosed = e.getEnclosedElements();
            for (ReflectionElement elm : enclosed) {
                if ((elm.getKind() == ElementKind.CLASS ||
                     elm.getKind() == ElementKind.INTERFACE ||
                     elm.getKind() == ElementKind.ENUM ||
                     elm.getKind() == ElementKind.ANNOTATION_TYPE)
                    && elm.getSimpleName().toString().equals(part)) {
                    ReflectionTypeElement t = findInner((ReflectionTypeElement)elm, parts);
                    if (t != null) {
                        return t;
                    }
                }
            }
            return null;
        }

        /**
         * {@inheritDoc}
         */
        @Override
        public Map<? extends ReflectionExecutableElement, ? extends AnnotationValue>
            getElementValuesWithDefaults(AnnotationMirror a) {
            if (a instanceof CoreReflAnnotationMirror) {
                return ((CoreReflAnnotationMirror)a).getElementValues();
            } else {
                throw new IllegalArgumentException();
            }
        }

        /**
         * {@inheritDoc}
         */
        @Override
        public String getDocComment(Element e) {
            checkElement(e);
            return null; // As per the doc
        }

        /**
         * {@inheritDoc}
         */
        @Override
        public boolean isDeprecated(Element e) {
            checkElement(e);
            return ((CoreReflElement)e).getSource().isAnnotationPresent(java.lang.Deprecated.class);
        }

        /**
         * {@inheritDoc}
         */
        @Override
        public Name getBinaryName(TypeElement type) {
            checkElement(type);
            return StringName.instance(((CoreReflTypeElement)type)
                                       .getSource()
                                       .getName());
        }

        /**
         * {@inheritDoc}
         */
        @Override
        public ReflectionPackageElement getPackageOf(Element type) {
            checkElement(type);
            if (type instanceof ReflectionPackageElement) {
                return (ReflectionPackageElement)type;
            }

            Package p;
            if (type instanceof CoreReflTypeElement) {
                p = ((CoreReflTypeElement)type).getSource().getPackage();
            } else {
                CoreReflTypeElement enclosingTypeElement = (CoreReflTypeElement)getEnclosingTypeElement((ReflectionElement)type);
                p = enclosingTypeElement.getSource().getPackage();
            }

            return createMirror(p);
        }

        /**
         * {@inheritDoc}
         */
        @Override
        public List<? extends ReflectionElement> getAllMembers(TypeElement type) {
            checkElement(type);
            return getAllMembers((ReflectionTypeElement)type);
        }

        // Exercise for the reader: should this method, and similar
        // ones that specialize on the more specific argument types,
        // be addd to the public ReflectionElements API?
        public List<? extends ReflectionElement> getAllMembers(ReflectionTypeElement type) {
            return type.getAllMembers();
        }

        /**
         * {@inheritDoc}
         */
        @Override
        public List<? extends AnnotationMirror> getAllAnnotationMirrors(Element e) {
            checkElement(e);
            AnnotatedElement ae = CoreReflElement.class.cast(e).getSource();
            Annotation[] annotations = ae.getAnnotations();
            int len = annotations.length;

            if (len > 0) {
                List<AnnotationMirror> res = new ArrayList<>(len);
                for (Annotation a : annotations) {
                    res.add(createMirror(a));
                }
                return Collections.unmodifiableList(res);
            } else {
                List<AnnotationMirror> ret = Collections.emptyList();
                return ret;
            }
        }

        /**
         * {@inheritDoc}
         */
        @Override
        public boolean hides(Element hider, Element hidden) {
            checkElement(hider);
            checkElement(hidden);

            // Names must be equal
            if (!hider.getSimpleName().equals(hidden.getSimpleName())) {
                return false;
            }

            // Hides isn't reflexive
            if (hider.equals(hidden)) {
                return false;
            }

            // Hider and hidden needs to be field, method or type
            // and fields hide fields, types hide types, methods hide methods
            // IE a Field doesn't hide a Methods etc
            ElementKind hiderKind = hider.getKind();
            ElementKind hiddenKind = hidden.getKind();
            if (hiderKind.isField() && !hiddenKind.isField()) {
                return false;
            } else if (hiderKind.isClass() &&
                       !(hiddenKind.isClass() || hiddenKind.isInterface())) {
                return false;
            } else if (hiderKind.isInterface() &&
                       !(hiddenKind.isClass() || hiddenKind.isInterface())) {
                return false;
            } else if (hiderKind == ElementKind.METHOD && hiddenKind != ElementKind.METHOD) {
                return false;
            } else if (!(hiderKind.isClass() ||
                         hiderKind.isInterface() ||
                         hiderKind.isField() ||
                         hiderKind == ElementKind.METHOD)) {
                return false;
            }

            Set<Modifier> hm = hidden.getModifiers();
            // jls 8.4.8.2 only static methods can hide methods
            if (hider.getKind() == ElementKind.METHOD) {
                if (!hider.getModifiers().contains(Modifier.STATIC)) {
                    return false; // hider not static
                } else if (!hm.contains(Modifier.STATIC)) { // we know it's a method
                    return false; // hidden not static
                }

                // For methods we also need to check parameter types
                Class<?>[] h1 = ((CoreReflMethodExecutableElement)hider).getSource().getParameterTypes();
                Class<?>[] h2 = ((CoreReflMethodExecutableElement)hidden).getSource().getParameterTypes();
                if (h1.length != h2.length) {
                    return false;
                }
                for (int i = 0; i < h1.length; i++) {
                    if (h1[i] != h2[i]) {
                        return false;
                    }
                }
            }

            // You can only hide visible elements
            if (hm.contains(Modifier.PRIVATE)) {
                return false; // hidden private, can't be hidden
            } else if ((!(hm.contains(Modifier.PUBLIC) || hm.contains(Modifier.PROTECTED))) && // not private, not (public or protected) IE package private
                       (!getPackageOf(hider).equals(getPackageOf(hidden)))) {
                return false; // hidden package private, and different packages, IE not visible
            }

            // Ok so now hider actually hides hidden if hider is
            // declared on a subtype of hidden.
            //
            // TODO: should this be a proper subtype or is that taken
            // care of by the reflexive check in the beginning?
            //
            TypeMirror hiderType = getEnclosingTypeElement((ReflectionElement)hider).asType();
            TypeMirror hiddenType = getEnclosingTypeElement((ReflectionElement)hidden).asType();

            return getTypes().isSubtype(hiderType, hiddenType);
        }

        /**
         * {@inheritDoc}
         */
        @Override
        public ReflectionTypeElement getEnclosingTypeElement(ReflectionElement e) {
            if (e.getKind() == ElementKind.PACKAGE) {
                return null;
            }

            if(e instanceof CoreReflTypeParameterElement) {
                ReflectionElement encElem = ((CoreReflTypeParameterElement)e).getEnclosingElement();
                if (encElem instanceof ReflectionTypeElement) {
                    return (ReflectionTypeElement)encElem;
                } else  {
                    return getEnclosingTypeElement(encElem);
                }
            }

            Class<?> encl = null;
            if (e instanceof CoreReflTypeElement) {
                encl = ((CoreReflTypeElement)e).getSource().getDeclaringClass();
            } else if (e instanceof CoreReflExecutableElement) {
                encl = (((CoreReflExecutableElement)e).getSource()).getDeclaringClass();
            } else if (e instanceof CoreReflFieldVariableElement) {
                encl = ((CoreReflFieldVariableElement)e).getSource().getDeclaringClass();
            } else if (e instanceof CoreReflParameterVariableElement) {
                encl = ((CoreReflParameterVariableElement)e).getSource().getDeclaringExecutable().getDeclaringClass();
            }

            return encl == null ? null : createMirror(encl);
        }

        /**
         *{@inheritDoc}
         *
         * Note that this implementation does not handle the situation
         * where A overrides B and B overrides C but A does not
         * directly override C. In this case, this implementation will
         * erroneously return false.
         */
        @Override
        public boolean overrides(ExecutableElement overrider, ExecutableElement overridden,
                                 TypeElement type) {
            checkElement(overrider);
            checkElement(overridden);
            checkElement(type);

            // TODO handle transitive overrides
            return overridesDirect(overrider, overridden, type);
        }

        private boolean overridesDirect(ExecutableElement overrider, ExecutableElement overridden,
                                         TypeElement type) {
            // Should we check that at least one of the types
            // overrider has is in fact a supertype of the TypeElement
            // 'type' supplied?

            CoreReflExecutableElement rider = (CoreReflExecutableElement)overrider;
            CoreReflExecutableElement ridden = (CoreReflExecutableElement)overridden;
            CoreReflTypeElement riderType = (CoreReflTypeElement)type;

            // Names must match, redundant - see subsignature below
            if (!rider.getSimpleName().equals(ridden.getSimpleName())) {
                return false;
            }

            // Constructors don't override
            // TODO: verify this fact
            if (rider.getKind() == ElementKind.CONSTRUCTOR ||
                ridden.getKind() == ElementKind.CONSTRUCTOR) {
                return false;
            }

            // Overridden must be visible to be overridden
            // TODO Fix transitive visibility/override
            Set<Modifier> rm = ridden.getModifiers();
            if (rm.contains(Modifier.PRIVATE)) {
                return false; // overridden private, can't be overridden
            } else if ((!(rm.contains(Modifier.PUBLIC) || rm.contains(Modifier.PROTECTED))) && // not private, not (public or protected) IE package private
                       (!getPackageOf(rider).equals(getPackageOf(ridden)))) {
                return false; // ridden package private, and different packages, IE not visible
            }

            // Static methods doesn't override
            if (rm.contains(Modifier.STATIC) ||
                rider.getModifiers().contains(Modifier.STATIC)) {
                return false;
            }

            // Declaring class of overrider must be a subclass of declaring class of overridden
            // except we use the parameter type as declaring class of overrider
            if (!getTypes().isSubtype(riderType.asType(), getEnclosingTypeElement(ridden).asType())) {
                return false;
            }

            // Now overrider overrides overridden if the signature of rider is a subsignature of ridden
            return getTypes().isSubsignature(rider.asType(), ridden.asType());
        }

        /**
         *{@inheritDoc}
         */
        @Override
        public String getConstantExpression(Object value) {
            return Constants.format(value);
        }

        // If CoreReflectionFactory were a proper part of the JDK, the
        // analogous functionality in javac could be reused.
        private static class Constants {
            /**
             * Returns a string representation of a constant value (given in
             * standard wrapped representation), quoted and formatted as in
             * Java source.
             */
            public static String format(Object value) {
                if (value instanceof Byte)      return formatByte((Byte) value);
                if (value instanceof Short)     return formatShort((Short) value);
                if (value instanceof Long)      return formatLong((Long) value);
                if (value instanceof Float)     return formatFloat((Float) value);
                if (value instanceof Double)    return formatDouble((Double) value);
                if (value instanceof Character) return formatChar((Character) value);
                if (value instanceof String)    return formatString((String) value);
                if (value instanceof Integer ||
                    value instanceof Boolean)   return value.toString();
                else
                    throw new IllegalArgumentException("Argument is not a primitive type or a string; it " +
                                                       ((value == null) ?
                                                        "is a null value." :
                                                        "has class " +
                                                        value.getClass().getName()) + "." );
            }

            private static String formatByte(byte b) {
                return String.format("(byte)0x%02x", b);
            }

            private static String formatShort(short s) {
                return String.format("(short)%d", s);
            }

            private static String formatLong(long lng) {
                return lng + "L";
            }

            private static String formatFloat(float f) {
                if (Float.isNaN(f))
                    return "0.0f/0.0f";
                else if (Float.isInfinite(f))
                    return (f < 0) ? "-1.0f/0.0f" : "1.0f/0.0f";
                else
                    return f + "f";
            }

            private static String formatDouble(double d) {
                if (Double.isNaN(d))
                    return "0.0/0.0";
                else if (Double.isInfinite(d))
                    return (d < 0) ? "-1.0/0.0" : "1.0/0.0";
                else
                    return d + "";
            }

            private static String formatChar(char c) {
                return '\'' + quote(c) + '\'';
            }

            private static String formatString(String s) {
                return '"' + quote(s) + '"';
            }

            /**
             * Escapes each character in a string that has an escape sequence or
             * is non-printable ASCII.  Leaves non-ASCII characters alone.
             */
            private static String quote(String s) {
                StringBuilder buf = new StringBuilder();
                for (int i = 0; i < s.length(); i++) {
                    buf.append(quote(s.charAt(i)));
                }
                return buf.toString();
            }

            /**
             * Escapes a character if it has an escape sequence or is
             * non-printable ASCII.  Leaves ASCII characters alone.
             */
            private static String quote(char ch) {
                switch (ch) {
                case '\b':  return "\\b";
                case '\f':  return "\\f";
                case '\n':  return "\\n";
                case '\r':  return "\\r";
                case '\t':  return "\\t";
                case '\'':  return "\\'";
                case '\"':  return "\\\"";
                case '\\':  return "\\\\";
                default:
                    return (isPrintableAscii(ch))
                        ? String.valueOf(ch)
                        : String.format("\\u%04x", (int) ch);
                }
            }

            /**
             * Is a character printable ASCII?
             */
            private static boolean isPrintableAscii(char ch) {
                return ch >= ' ' && ch <= '~';
            }
        }

        /**
         * {@inheritDoc}
         */
        @Override
        public void printElements(Writer w, Element... elements) {
            ElementVisitor<?, ?> printer = getPrinter(w);
            try {
                for (Element e : elements) {
                    checkElement(e);
                    printer.visit(e);
                }
            } finally {
                try {
                    w.flush();
                } catch (java.io.IOException e) { /* Ignore */;}
            }
        }

        private ElementVisitor<?, ?> getPrinter(Writer w) {
            // First try a reflective call into javac and if that
            // fails, fallback to a very simple toString-based
            // scanner.
            try {
                //reflective form of
                // return new com.sun.tools.javac.processing.PrintingProcessor.PrintingElementVisitor(w, getElements());
                Class<?> printProcClass =
                    ClassLoader.getSystemClassLoader().loadClass("com.sun.tools.javac.processing.PrintingProcessor$PrintingElementVisitor");
                Constructor<?> printProcCtor = printProcClass.getConstructor(Writer.class, Elements.class);
                return (ElementVisitor) printProcCtor.newInstance(w, getElements());
            } catch (ReflectiveOperationException | SecurityException e) {
                return new ElementScanner9<Writer, Void>(w){
                    @Override
                    public Writer scan(Element e, Void v) {
                        try {
                            DEFAULT_VALUE.append(e.toString());
                            DEFAULT_VALUE.append("\n");
                        } catch (java.io.IOException ioe) {
                            throw new RuntimeException(ioe);
                        }
                        return DEFAULT_VALUE;
                    }
                };
            }
        }

        /**
         * {@inheritDoc}
         */
        @Override
        public Name getName(CharSequence cs) {
            return StringName.instance(cs.toString());
        }

        private void checkElement(Element e) {
            if(!(e instanceof CoreReflElement)) {
                throw new IllegalArgumentException();
            }
        }

        @Override
        public boolean isFunctionalInterface(TypeElement e) {
            throw new UnsupportedOperationException();
            // Update once this functionality is in core reflection
        }
    }

    private static class CoreReflTypes implements javax.lang.model.util.Types {
        private static Types instance = new CoreReflTypes();

        public static Types instance() {
            return instance;
        }

        // Private to suppress instantiation
        private CoreReflTypes() {}

        // Types methods
        @Override
        public Element asElement(TypeMirror t) {
            checkType(t);
            if (t instanceof javax.lang.model.type.TypeVariable) {
                ((javax.lang.model.type.TypeVariable)t).asElement();
            } else if (t instanceof DeclaredType) {
                return ((DeclaredType)t).asElement();
            }
            return null;
        }

        @Override
        public boolean isSameType(TypeMirror t1, TypeMirror t2) {
            if (t1.getKind() != t2.getKind()) {
                return false;
            }

            if (t1.getKind() == TypeKind.WILDCARD ||
                t2.getKind() == TypeKind.WILDCARD) {
                // Wildcards are not equal to any type
                return false;
            }

            if (t1 instanceof CoreReflDeclaredType &&
                t2 instanceof CoreReflDeclaredType) {
                return ((CoreReflDeclaredType)t1).isSameType((CoreReflDeclaredType)t2);
            } else if (t1 instanceof PrimitiveType &&
                       t2 instanceof PrimitiveType) {
                return t1.getKind() == t2.getKind();
            } else if (t1 instanceof NoType &&
                       t2 instanceof NoType) {
                return true;
            } else if (t1 instanceof NullType &&
                       t2 instanceof NullType) {
                return true;
            } else if (t1 instanceof ArrayType &&
                       t2 instanceof ArrayType) {
                return isSameType(((ArrayType)t1).getComponentType(), ((ArrayType)t2).getComponentType());
            }

            return false;
        }

        @Override
        public boolean isSubtype(TypeMirror t1, TypeMirror t2) {
            checkType(t1);
            checkType(t2);

            if (isSameType(t1, t2)) {
                return true;
            } else if(t1.getKind() == TypeKind.NULL) {
                return true;
            }

            // This depth first traversal should terminate due to the ban on circular inheritance
            List<? extends TypeMirror> directSupertypes = directSupertypes(t1);
            if (directSupertypes.isEmpty()) {
                return false;
            }
            for (TypeMirror ti : directSupertypes) {
                if (isSameType(ti, t2) || isSubtype(ti, t2)) {
                    return true;
                }
            }
            return false;
        }

        @Override
        public boolean isAssignable(TypeMirror t1, TypeMirror t2) {
            throw new UnsupportedOperationException();
        }

        @Override
        public boolean contains(TypeMirror t1, TypeMirror t2) {
            throw new UnsupportedOperationException();
        }

        @Override
        public boolean isSubsignature(ExecutableType m1, ExecutableType m2) {
            checkType(m1);
            checkType(m2);

            ExecutableMethodType m0 = (ExecutableMethodType)m1;

            return m0.sameSignature((ExecutableMethodType)m2) || m0.sameSignature((ExecutableMethodType)erasure(m2));
        }

        @Override
        public List<? extends TypeMirror> directSupertypes(TypeMirror t) {
            checkType(t);
            if (t instanceof ExecutableType ||
                t.getKind() == TypeKind.PACKAGE) {
                throw new IllegalArgumentException("You can't ask for direct supertypes for type: " + t);
            }
            return ((AbstractTypeMirror)t).directSuperTypes();
        }

        @Override
        public TypeMirror erasure(TypeMirror t) {
            checkType(t);
            return ((AbstractTypeMirror)t).erasure();
        }

        @Override
        public TypeElement boxedClass(javax.lang.model.type.PrimitiveType p) {
            throw new UnsupportedOperationException();
        }

        @Override
        public PrimitiveType unboxedType(TypeMirror t) {
            throw new UnsupportedOperationException();
        }

        @Override
        public TypeMirror capture(TypeMirror t) {
            checkType(t);
            return ((AbstractTypeMirror)t).capture();
        }

        @Override
        public PrimitiveType getPrimitiveType(TypeKind kind) {
            return PrimitiveType.instance(kind);
        }

        @Override
        public NullType getNullType() {
            return CoreReflNullType.getInstance();
        }

        @Override
        public javax.lang.model.type.NoType getNoType(TypeKind kind) {
            if (kind == TypeKind.NONE) {
                return NoType.getNoneInstance();
            } else if (kind == TypeKind.VOID) {
                return NoType.getVoidInstance();
            } else {
                throw new IllegalArgumentException("No NoType of kind: " + kind);
            }
        }

        @Override
        public ArrayType getArrayType(TypeMirror componentType) {
            throw new UnsupportedOperationException();
        }

        @Override
        public javax.lang.model.type.WildcardType getWildcardType(TypeMirror extendsBound,
                                                                  TypeMirror superBound) {
            throw new UnsupportedOperationException();
        }

        @Override
        public DeclaredType getDeclaredType(TypeElement typeElem, TypeMirror... typeArgs) {
            throw new UnsupportedOperationException();
        }

        @Override
        public javax.lang.model.type.DeclaredType getDeclaredType(javax.lang.model.type.DeclaredType containing,
                                                                  TypeElement typeElem,
                                                                  TypeMirror... typeArgs) {
            throw new UnsupportedOperationException();
        }

        @Override
        public TypeMirror asMemberOf(javax.lang.model.type.DeclaredType containing, Element element) {
            throw new UnsupportedOperationException();
        }

        private void checkType(TypeMirror t) {
            if (!(t instanceof AbstractTypeMirror)) {
                throw new IllegalArgumentException("This Types implementation can only operate on CoreReflectionFactory type classes");
            }
        }
    }

    private abstract static class CoreReflDeclaredType extends AbstractTypeMirror
        implements javax.lang.model.type.DeclaredType {
        private Class<?> source = null;

        private CoreReflDeclaredType(Class<?> source) {
            super(TypeKind.DECLARED);
            this.source = source;
        }

        static DeclaredType instance(Class<?> source, Type genericSource) {
            if (genericSource instanceof ParameterizedType) {
                return new ParameterizedDeclaredType(source, (ParameterizedType)genericSource);
            } else if (genericSource instanceof Class) { // This happens when a field has a raw type
                if (!source.equals(genericSource)) {
                    throw new IllegalArgumentException("Don't know how to handle this");
                }
                return instance(source);
            }
            throw new IllegalArgumentException("Don't know how to create a declared type from: " +
                                               source +
                                               " and genericSource " +
                                               genericSource);
        }

        static DeclaredType instance(Class<?> source) {
            return new RawDeclaredType(source);
        }

        protected Class<?> getSource() {
            return source;
        }

        @Override
        public Element asElement() {
            return CoreReflectionFactory.createMirror(getSource());
        }

        abstract boolean isSameType(DeclaredType other);

        @Override
        TypeMirror capture() {
            return new CaptureDeclaredType(this);
        }

        private static class CaptureDeclaredType extends CoreReflDeclaredType {
            CoreReflDeclaredType cap;
            CaptureDeclaredType(CoreReflDeclaredType t) {
                super(t.source);
                this.cap = t;
            }

            @Override
            public List<? extends TypeMirror> getTypeArguments() {
                List<? extends TypeMirror> wrapped = cap.getTypeArguments();
                ArrayList<TypeMirror> res = new ArrayList<>(wrapped.size());
                res.ensureCapacity(wrapped.size());

                for (int i = 0; i < wrapped.size(); i++) {
                    TypeMirror t = wrapped.get(i);

                    if (t instanceof javax.lang.model.type.WildcardType) {
                        res.add(i, convert(t));
                    } else {
                        res.add(i, t);
                    }
                }
                return Collections.unmodifiableList(res);
            }

            private TypeMirror convert(TypeMirror t) {
                if (!(t instanceof javax.lang.model.type.WildcardType)) {
                    throw new IllegalArgumentException();
                } else {
                    javax.lang.model.type.WildcardType w = (javax.lang.model.type.WildcardType)t;
                    return TypeFactory.typeVariableInstance(w, w.getExtendsBound(), w.getSuperBound());
                }
            }

            @Override
            public TypeMirror getEnclosingType() {
                return cap.getEnclosingType();
            }

            @Override
            List<? extends TypeMirror> directSuperTypes() {
                return cap.directSuperTypes();
            }

            @Override
            boolean isSameType(DeclaredType other) {
                return other == this;
            }

            @Override
            public String toString() {
                return " CAPTURE of: " + cap.toString();
            }
        }

        private static class RawDeclaredType extends CoreReflDeclaredType
            implements Reifiable {
            private RawDeclaredType(Class<?> source) {
                super(source);
            }

            @Override
            public Class<?> getSource() {
                return super.getSource();
            }

            @Override
            public TypeMirror getEnclosingType() {
                Class<?> enclosing = getSource().getEnclosingClass();
                if (null == enclosing) {
                    return NoType.getNoneInstance();
                } else {
                    return TypeFactory.instance(enclosing);
                }
            }

            @Override
            public List<? extends TypeMirror> getTypeArguments() {
                return Collections.emptyList();
            }

            @Override
            List<? extends TypeMirror> directSuperTypes() {
                if (getSource().isEnum()) {
                    return enumSuper();
                }

                if (getSource() == java.lang.Object.class) {
                    return Collections.emptyList();
                }
                List<TypeMirror> res = new ArrayList<>();
                Type[] superInterfaces = getSource().getInterfaces();
                if (!getSource().isInterface()) {
                    res.add(TypeFactory.instance(getSource().getSuperclass()));
                } else if (superInterfaces.length == 0) {
                    // Interfaces that don't extend another interface
                    // have java.lang.Object as a direct supertype.
                    return Collections.unmodifiableList(Arrays.asList(TypeFactory.instance(java.lang.Object.class)));
                }

                for (Type t : superInterfaces) {
                    res.add(TypeFactory.instance(t));
                }
                return Collections.unmodifiableList(res);
            }

            private List<? extends TypeMirror> enumSuper() {
                Class<?> rawSuper = getSource().getSuperclass();
                Type[] actualArgs = ((ParameterizedTypeImpl)getSource().getGenericSuperclass()).getActualTypeArguments();

                // Reconsider this : assume the problem is making
                // Enum<MyEnum> rather than just a raw enum.
                return Collections.unmodifiableList(Arrays.asList(TypeFactory.instance(ParameterizedTypeImpl.make(rawSuper,
                                                                                                                  Arrays.copyOf(actualArgs,
                                                                                                                                actualArgs.length),
                                                                                                                  null))));
            }

            @Override
            boolean isSameType(DeclaredType other) {
                if (other instanceof RawDeclaredType) {
                    return Objects.equals(getSource(), ((RawDeclaredType)other).getSource());
                } else {
                    return false;
                }
            }

            @Override
            public String toString() {
                return getSource().toString();
            }
        }

        private static class ParameterizedDeclaredType extends CoreReflDeclaredType {
            private ParameterizedType genericSource = null;
            private ParameterizedDeclaredType(Class<?> source, ParameterizedType genericSource) {
                super(source);
                this.genericSource = genericSource;
            }

            @Override
            public TypeMirror getEnclosingType() {
                Type me = genericSource;
                Type owner = GenericTypes.getEnclosingType(me);
                if (owner == null) {
                    return NoType.getNoneInstance();
                }
                return TypeFactory.instance(owner);
            }

            @Override
            public List<? extends TypeMirror> getTypeArguments() {
                Type[] typeArgs = genericSource.getActualTypeArguments();

                int length = typeArgs.length;
                if (length == 0)
                    return Collections.emptyList();
                else {
                    List<TypeMirror> tmp = new ArrayList<>(length);
                    for (Type t : typeArgs) {
                        tmp.add(TypeFactory.instance(t));
                    }
                    return Collections.unmodifiableList(tmp);
                }
            }

            @Override
            List<? extends TypeMirror> directSuperTypes() {
                if (getSource() == java.lang.Object.class) {
                    return Collections.emptyList();
                }

                List<TypeMirror> res = new ArrayList<>();
                Type[] superInterfaces = getSource().getGenericInterfaces();
                if (!getSource().isInterface()) {
                    // Replace actual type arguments with our type arguments
                    res.add(TypeFactory.instance(substituteTypeArgs(getSource().getGenericSuperclass())));
                } else if (superInterfaces.length == 0) {
                    // Interfaces that don't extend another interface
                    // have java.lang.Object as a direct supertype, plus
                    // possibly the interface's raw type
                    res.add(TypeFactory.instance(java.lang.Object.class));
                }

                for (Type t : superInterfaces) {
                    res.add(TypeFactory.instance(substituteTypeArgs(t)));
                }

                res.add(TypeFactory.instance(getSource())); // Add raw type
                return Collections.unmodifiableList(res);
            }

            private Type substituteTypeArgs(Type type) {
                if (!(type instanceof ParameterizedType)) {
                    return type;
                }

                ParameterizedType target = (ParameterizedType)type;
                // Cast to get a Class instead of a plain type.
                Class<?> raw = ((ParameterizedTypeImpl)target).getRawType();
                Type[] actualArgs = genericSource.getActualTypeArguments();

                return  ParameterizedTypeImpl.make(raw, Arrays.copyOf(actualArgs, actualArgs.length), null);
            }

            @Override
            boolean isSameType(DeclaredType other) {
                if (other instanceof ParameterizedDeclaredType) {
                    return GenericTypes.isSameGenericType(genericSource,
                                                          ((ParameterizedDeclaredType)other).genericSource);
                } else {
                    return false;
                }
            }

            @Override
            public String toString() {
                return getKind().toString() + " " + genericSource.toString();
            }
        }

        /**
         * Implementing class for ParameterizedType interface.
         * Derived from sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl
         */

        private static class ParameterizedTypeImpl implements ParameterizedType {
            private Type[] actualTypeArguments;
            private Class<?>  rawType;
            private Type   ownerType;

            private ParameterizedTypeImpl(Class<?> rawType,
                                          Type[] actualTypeArguments,
                                          Type ownerType) {
                this.actualTypeArguments = actualTypeArguments;
                this.rawType             = rawType;
                if (ownerType != null) {
                    this.ownerType = ownerType;
                } else {
                    this.ownerType = rawType.getDeclaringClass();
                }
                validateConstructorArguments();
            }

            private void validateConstructorArguments() {
                java.lang.reflect.TypeVariable/*<?>*/[] formals = rawType.getTypeParameters();
                // check correct arity of actual type args
                if (formals.length != actualTypeArguments.length){
                    throw new MalformedParameterizedTypeException();
                }
            }

            /**
             * Static factory. Given a (generic) class, actual type arguments
             * and an owner type, creates a parameterized type.
             * This class can be instantiated with a a raw type that does not
             * represent a generic type, provided the list of actual type
             * arguments is empty.
             * If the ownerType argument is null, the declaring class of the
             * raw type is used as the owner type.
             * <p> This method throws a MalformedParameterizedTypeException
             * under the following circumstances:
             * If the number of actual type arguments (i.e., the size of the
             * array {@code typeArgs}) does not correspond to the number of
             * formal type arguments.
             * If any of the actual type arguments is not an instance of the
             * bounds on the corresponding formal.
             * @param rawType the Class representing the generic type declaration being
             * instantiated
             * @param actualTypeArguments - a (possibly empty) array of types
             * representing the actual type arguments to the parameterized type
             * @param ownerType - the enclosing type, if known.
             * @return An instance of {@code ParameterizedType}
             * @throws MalformedParameterizedTypeException - if the instantiation
             * is invalid
             */
            public static ParameterizedTypeImpl make(Class<?> rawType,
                                                     Type[] actualTypeArguments,
                                                     Type ownerType) {
                return new ParameterizedTypeImpl(rawType, actualTypeArguments,
                                                 ownerType);
            }


            /**
             * Returns an array of {@code Type} objects representing the actual type
             * arguments to this type.
             *
             * <p>Note that in some cases, the returned array be empty. This can occur
             * if this type represents a non-parameterized type nested within
             * a parameterized type.
             *
             * @return an array of {@code Type} objects representing the actual type
             *     arguments to this type
             * @throws {@code TypeNotPresentException} if any of the
             *     actual type arguments refers to a non-existent type declaration
             * @throws {@code MalformedParameterizedTypeException} if any of the
             *     actual type parameters refer to a parameterized type that cannot
             *     be instantiated for any reason
             * @since 1.5
             */
            public Type[] getActualTypeArguments() {
                return actualTypeArguments.clone();
            }

            /**
             * Returns the {@code Type} object representing the class or interface
             * that declared this type.
             *
             * @return the {@code Type} object representing the class or interface
             *     that declared this type
             */
            public Class<?> getRawType() {
                return rawType;
            }


            /**
             * Returns a {@code Type} object representing the type that this type
             * is a member of.  For example, if this type is {@code O<T>.I<S>},
             * return a representation of {@code O<T>}.
             *
             * <p>If this type is a top-level type, {@code null} is returned.
             *
             * @return a {@code Type} object representing the type that
             *     this type is a member of. If this type is a top-level type,
             *     {@code null} is returned
             */
            public Type getOwnerType() {
                return ownerType;
            }

            /*
             * From the JavaDoc for java.lang.reflect.ParameterizedType
             * "Instances of classes that implement this interface must
             * implement an equals() method that equates any two instances
             * that share the same generic type declaration and have equal
             * type parameters."
             */
            @Override
            public boolean equals(Object o) {
                if (o instanceof ParameterizedType) {
                    // Check that information is equivalent
                    ParameterizedType that = (ParameterizedType) o;

                    if (this == that)
                        return true;

                    Type thatOwner   = that.getOwnerType();
                    Type thatRawType = that.getRawType();

                    return Objects.equals(ownerType, thatOwner) &&
                        Objects.equals(rawType, thatRawType) &&
                        Arrays.equals(actualTypeArguments, // avoid clone
                                      that.getActualTypeArguments());
                } else
                    return false;
            }

            @Override
            public int hashCode() {
                return
                    Arrays.hashCode(actualTypeArguments) ^
                    Objects.hashCode(ownerType) ^
                    Objects.hashCode(rawType);
            }

            public String toString() {
                StringBuilder sb = new StringBuilder();

                if (ownerType != null) {
                    if (ownerType instanceof Class)
                        sb.append(((Class)ownerType).getName());
                    else
                        sb.append(ownerType.toString());

                    sb.append(".");

                    if (ownerType instanceof ParameterizedTypeImpl) {
                        // Find simple name of nested type by removing the
                        // shared prefix with owner.
                        sb.append(rawType.getName().replace( ((ParameterizedTypeImpl)ownerType).rawType.getName() + "$",
                                                             ""));
                    } else
                        sb.append(rawType.getName());
                } else
                    sb.append(rawType.getName());

                if (actualTypeArguments != null &&
                    actualTypeArguments.length > 0) {
                    sb.append("<");
                    boolean first = true;
                    for (Type t: actualTypeArguments) {
                        if (!first)
                            sb.append(", ");
                        if (t instanceof Class)
                            sb.append(((Class)t).getName());
                        else
                            sb.append(t.toString());
                        first = false;
                    }
                    sb.append(">");
                }

                return sb.toString();
            }
        }

    }

    private static class ErasedMethodType extends ExecutableMethodType implements javax.lang.model.type.ExecutableType {
        private final Method m;

        ErasedMethodType(Method m) {
            super(m);
            this.m = Objects.requireNonNull(m);
        }

        @Override
        public List<javax.lang.model.type.TypeVariable> getTypeVariables() {
            return Collections.emptyList();
        }

        @Override
        public List<? extends TypeMirror> getThrownTypes() {
            Class<?>[] exceptions = m.getExceptionTypes();
            int len = exceptions.length;

            if (len > 0) {
                List<TypeMirror> res = new ArrayList<TypeMirror>(len);
                for (Class<?> t : exceptions) {
                    res.add(TypeFactory.instance(t));
                }
                return Collections.unmodifiableList(res);
            } else {
                List<TypeMirror> ret = Collections.emptyList();
                return ret;
            }
        }

        @Override
        public List<? extends TypeMirror> getParameterTypes() {
            Class<?>[] params = m.getParameterTypes();
            int len = params.length;

            if (len > 0) {
                List<TypeMirror> res = new ArrayList<TypeMirror>(len);
                for (Class<?> t : params) {
                    res.add(TypeFactory.instance(t));
                }
                return Collections.unmodifiableList(res);
            } else {
                List<TypeMirror> ret = Collections.emptyList();
                return ret;
            }
        }

        @Override
        public TypeMirror getReturnType() {
            return TypeFactory.instance(m.getReturnType());
        }

        @Override
        TypeMirror erasure() {
            return this;
        }
    }

    private static class ErrorType extends AbstractTypeMirror implements javax.lang.model.type.ErrorType {
        private static ErrorType errorType = new ErrorType();

        public static ErrorType getErrorInstance() {
            return errorType;
        }

        private ErrorType() {
            super(TypeKind.ERROR);
        }

        @Override
        public List<? extends TypeMirror> getTypeArguments() {
            throw new UnsupportedOperationException();
        }

        @Override
        public TypeMirror getEnclosingType() {
            throw new UnsupportedOperationException();
        }

        @Override
        public Element asElement() {
            throw new UnsupportedOperationException();
        }

        @Override
        List<? extends TypeMirror> directSuperTypes() {
            throw new UnsupportedOperationException();
        }
    }

    private static class ExecutableMethodType extends AbstractTypeMirror
        implements javax.lang.model.type.ExecutableType {
        private final Method m;

        ExecutableMethodType(Method m) {
            super(TypeKind.EXECUTABLE);
            this.m = Objects.requireNonNull(m);
        }

        @Override
        public List<? extends TypeMirror> getThrownTypes() {
            Type[] exceptions = m.getGenericExceptionTypes();
            int len = exceptions.length;

            if (len > 0) {
                List<TypeMirror> res = new ArrayList<TypeMirror>(len);
                for (Type t : exceptions) {
                    res.add(TypeFactory.instance(t));
                }
                return Collections.unmodifiableList(res);
            } else {
                List<TypeMirror> ret = Collections.emptyList();
                return ret;
            }
        }

        @Override
        public List<javax.lang.model.type.TypeVariable> getTypeVariables() {
            java.lang.reflect.TypeVariable[] variables = m.getTypeParameters();
            int len = variables.length;

            if (len > 0) {
                List<javax.lang.model.type.TypeVariable> res = new ArrayList<>(len);
                for (java.lang.reflect.TypeVariable<?> t : variables) {
                    res.add(TypeFactory.typeVariableInstance(t));
                }
                return Collections.unmodifiableList(res);
            } else {
                return Collections.emptyList();
            }
        }

        @Override
        public TypeMirror getReturnType() {
            return TypeFactory.instance(m.getGenericReturnType());
        }

        @Override
        public List<? extends TypeMirror> getParameterTypes() {
            Type[] params = m.getGenericParameterTypes();
            int len = params.length;

            if (len > 0) {
                List<TypeMirror> res = new ArrayList<TypeMirror>(len);
                for (Type t : params) {
                    res.add(TypeFactory.instance(t));
                }
                return Collections.unmodifiableList(res);
            } else {
                return Collections.emptyList();
            }
        }

        @Override
        List<? extends TypeMirror> directSuperTypes() {
            // Spec says we don't need this
            throw new UnsupportedOperationException();
        }

        @Override
        TypeMirror erasure() {
            return new ErasedMethodType(m);
        }

        @Override
        public TypeMirror getReceiverType() {
            throw new UnsupportedOperationException();
        }

        boolean sameSignature(ExecutableMethodType other){
            if (!m.getName().equals(other.m.getName())) {
                return false;
            }

            List<? extends TypeMirror> thisParams = getParameterTypes();
            List<? extends TypeMirror> otherParams = other.getParameterTypes();
            if (thisParams.size() != otherParams.size()) {
                return false;
            }
            for (int i = 0; i < thisParams.size(); i++) {
                if (!CoreReflTypes.instance().isSameType(thisParams.get(i), otherParams.get(i))) {
                    return false;
                }
            }
            return true;
        }
    }

    private static class GenericTypes {
        public static boolean isSameGenericType(Type t1, Type t2) {
            if (t1 instanceof Class) {
                return ((Class)t1).equals(t2);
            } else if (t1 instanceof ParameterizedType) {
                return ((ParameterizedType)t1).equals(t2);
            }
            throw new UnsupportedOperationException();
        }

        public static Type getEnclosingType(Type t1) {
            if (t1 instanceof Class) {
                return ((Class)t1).getEnclosingClass();
            } else if (t1 instanceof ParameterizedType) {
                return ((ParameterizedType)t1).getOwnerType();
            }
            throw new UnsupportedOperationException();
        }
    }

    private static class IntersectionDeclaredType extends AbstractTypeMirror
        implements javax.lang.model.type.DeclaredType {
        private Type[] sources = null;

        IntersectionDeclaredType(Type[] sources) {
            super(TypeKind.DECLARED);
            this.sources = Arrays.copyOf(Objects.requireNonNull(sources),
                                         sources.length);
        }

        @Override
        public TypeMirror getEnclosingType() {
            return NoType.getNoneInstance();
        }

        @Override
        public  Element asElement() {
            throw new UnsupportedOperationException();
        }

        @Override
        public List<? extends TypeMirror> getTypeArguments() {
            throw new UnsupportedOperationException();
        }

        @Override
        List<? extends TypeMirror> directSuperTypes() {
            int len = sources.length;

            if (len > 0) {
                List<TypeMirror> res = new ArrayList<TypeMirror>(len);
                for (Type c : sources) {
                    res.add(TypeFactory.instance(c));
                }
                return Collections.unmodifiableList(res);
            } else {
                return Collections.emptyList();
            }
        }
    }

    private static class ModelWildcardType extends AbstractTypeMirror
        implements javax.lang.model.type.WildcardType {
        private java.lang.reflect.WildcardType genericSource;

        ModelWildcardType(java.lang.reflect.WildcardType genericSource) {
            super(TypeKind.WILDCARD);
            this.genericSource = Objects.requireNonNull(genericSource);
        }

        @Override
        List<? extends TypeMirror> directSuperTypes() {
            // TODO Add support for this operation
            throw new UnsupportedOperationException();
        }

        @Override
        public TypeMirror getExtendsBound() {
            Type[] t = genericSource.getUpperBounds();

            if (t.length == 1) {
                if (t[0].equals(Object.class) && getSuperBound() != null) { // can't have both lower and upper explicit
                    return null;
                }
                return TypeFactory.instance(t[0]);
            }
            throw new UnsupportedOperationException(); // TODO: intersection type?
        }

        @Override
        public TypeMirror getSuperBound() {
            Type[] t = genericSource.getLowerBounds();

            if (t.length == 0) { // bound is null
                return null;
            } else if (t.length == 1) {
                return TypeFactory.instance(t[0]);
            }
            throw new UnsupportedOperationException(); // TODO: intersection type?
        }

        @Override
        public String toString() {
            return getKind() + " " + genericSource.toString();
        }
    }

    private static class NoType extends AbstractTypeMirror
        implements javax.lang.model.type.NoType {
        private static NoType noneType = new NoType(TypeKind.NONE, "none");
        private static NoType packageType = new NoType(TypeKind.PACKAGE, "package");
        private static NoType voidType = new NoType(TypeKind.VOID, "void");

        private String str;

        public static NoType getNoneInstance() {
            return noneType;
        }

        public static NoType getPackageInstance() {
            return packageType;
        }

        public static NoType getVoidInstance() {
            return voidType;
        }

        private NoType(TypeKind k, String str) {
            super(k);
            this.str = str;
        }

        @Override
        List<? extends TypeMirror> directSuperTypes() {
            // TODO We don't need this for the Package instance, how about the others?
            throw new UnsupportedOperationException();
        }

        @Override
        public String toString() {
            return str;
        }
    }

    private static class CoreReflNullType extends AbstractTypeMirror
        implements javax.lang.model.type.NullType {
        private static CoreReflNullType nullType = new CoreReflNullType();

        public static NullType getInstance() {
            return nullType;
        }

        private CoreReflNullType() {
            super(TypeKind.NULL);
        }

        @Override
        List<? extends TypeMirror> directSuperTypes() {
            // JLS 4.10.2 says:
            // "The direct supertypes of the null type are all reference types other than the null type itself."
            // TODO return null? an empty list? the error type? anyhow fix this
            throw new UnsupportedOperationException();
        }
    }

    private static interface Reifiable {
        Class<?> getSource();
    }

    private static class PrimitiveType extends AbstractTypeMirror
        implements javax.lang.model.type.PrimitiveType,
                   Reifiable {
        private Class<?> source;

        private static PrimitiveType booleanInstance = new PrimitiveType(TypeKind.BOOLEAN, boolean.class);
        private static PrimitiveType byteInstance =    new PrimitiveType(TypeKind.BYTE, byte.class);
        private static PrimitiveType charInstance =    new PrimitiveType(TypeKind.CHAR, char.class);
        private static PrimitiveType shortInstance =   new PrimitiveType(TypeKind.SHORT, short.class);
        private static PrimitiveType intInstance =     new PrimitiveType(TypeKind.INT, int.class);
        private static PrimitiveType longInstance =    new PrimitiveType(TypeKind.LONG, long.class);
        private static PrimitiveType floatInstance =   new PrimitiveType(TypeKind.FLOAT, float.class);
        private static PrimitiveType doubleInstance =  new PrimitiveType(TypeKind.DOUBLE, double.class);

        private PrimitiveType(TypeKind kind, Class<?> source) {
            super(kind);
            this.source = source;
        }

        @Override
        public Class<?> getSource() {
            return source;
        }

        static PrimitiveType instance(Class<?> c) {
            switch(c.getName()) {
            case "boolean":
                return booleanInstance;
            case "byte":
                return byteInstance;
            case "char":
                return charInstance;
            case "short":
                return shortInstance;
            case "int":
                return intInstance;
            case "long":
                return longInstance;
            case "float":
                return floatInstance;
            case "double":
                return doubleInstance;
            default:
                throw new IllegalArgumentException();
            }
        }

        static PrimitiveType instance(TypeKind k) {
            switch(k) {
            case BOOLEAN:
                return booleanInstance;
            case BYTE:
                return byteInstance;
            case CHAR:
                return charInstance;
            case SHORT:
                return shortInstance;
            case INT:
                return intInstance;
            case LONG:
                return longInstance;
            case FLOAT:
                return floatInstance;
            case DOUBLE:
                return doubleInstance;
            default:
                throw new IllegalArgumentException();
            }
        }

        @Override
        public String toString() {
            return source.getName();
        }

        //Types methods
        @Override
        List<? extends TypeMirror> directSuperTypes() {
            switch (getKind()) {
            case DOUBLE:
                return Collections.emptyList();
            case FLOAT:
                return Arrays.asList(doubleInstance);
            case LONG:
                return Arrays.asList(floatInstance);
            case INT:
                return Arrays.asList(longInstance);
            case CHAR:
                return Arrays.asList(intInstance);
            case SHORT:
                return Arrays.asList(intInstance);
            case BYTE:
                return Arrays.asList(shortInstance);
            default:
                return Collections.emptyList();
            }
        }
    }

    private static class TypeFactory {
        private TypeFactory() { }// no instances for you

        public static TypeMirror instance(Class<?> c) {
            if (c.isPrimitive()) {
                if (c.getName().equals("void")) {
                    return NoType.getVoidInstance();
                } else {
                    return PrimitiveType.instance(c);
                }
            } else if (c.isArray()) {
                return new CoreReflArrayType(c);
            } else if (c.isAnonymousClass() ||
                       c.isLocalClass() ||
                       c.isMemberClass() ||
                       c.isInterface() || // covers annotations
                       c.isEnum()) {
                return CoreReflDeclaredType.instance(c);
            } else { // plain old class ??
                return CoreReflDeclaredType.instance(c);
            }
        }

        public static TypeMirror instance(Type t) {
            if (t instanceof Class) {
                return instance((Class)t);
            } else if (t instanceof ParameterizedType) {
                ParameterizedType tmp = (ParameterizedType)t;
                Type raw = tmp.getRawType();
                if (!(raw instanceof Class)) {
                    throw new IllegalArgumentException(t + " " + raw );
                }
                return CoreReflDeclaredType.instance((Class)raw, tmp);
            } else if (t instanceof java.lang.reflect.WildcardType) {
                return new ModelWildcardType((java.lang.reflect.WildcardType)t);
            } else if (t instanceof java.lang.reflect.TypeVariable) {
            return new CoreReflTypeVariable((java.lang.reflect.TypeVariable)t);
            }
            throw new IllegalArgumentException("Don't know how to make instance from: " + t.getClass());
        }

        public static TypeMirror instance(Field f) {
            return CoreReflDeclaredType.instance(f.getType(), f.getGenericType());
        }

        public static ExecutableType instance(Method m) {
            return new ExecutableMethodType(m);
        }

        public static javax.lang.model.type.TypeVariable typeVariableInstance(java.lang.reflect.TypeVariable<?> v) {
            return new CoreReflTypeVariable(v);
        }

        public static javax.lang.model.type.TypeVariable typeVariableInstance(TypeMirror source,
                                                        TypeMirror upperBound,
                                                        TypeMirror lowerBound) {
            return new CaptureTypeVariable(source, upperBound, lowerBound);
        }
    }

    private static class CoreReflTypeVariable extends AbstractTypeMirror
        implements javax.lang.model.type.TypeVariable {
        private final java.lang.reflect.TypeVariable<?> source;
        private boolean isCapture = false;

        protected CoreReflTypeVariable(java.lang.reflect.TypeVariable<?> source) {
            super(TypeKind.TYPEVAR);
            Objects.requireNonNull(source);
            this.source = source;
        }

        @Override
        public TypeMirror getUpperBound() {
            return new IntersectionDeclaredType(source.getBounds());
        }

        @Override
        public TypeMirror getLowerBound() {
            return CoreReflTypes.instance().getNullType();
        }

        @Override
        public Element asElement() {
            return CoreReflectionFactory.createMirror(source);
        }

        @Override
        List<? extends TypeMirror> directSuperTypes() {
            return ((AbstractTypeMirror)getUpperBound()).directSuperTypes();
        }

        @Override
        public int hashCode() {
            return source.hashCode();
        }

        @Override
        public boolean equals(Object other) {
            if (other instanceof CoreReflTypeVariable) {
                return this.source.equals(((CoreReflTypeVariable)other).source);
            } else {
                return false;
            }
        }
    }
}
