/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package org.netbeans.api.java.source;

import com.sun.tools.javac.api.JavacTaskImpl;
import com.sun.tools.javac.code.ModuleFinder;
import com.sun.tools.javac.code.Symbol;
import com.sun.tools.javac.code.Symtab;
import com.sun.tools.javac.jvm.Target;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.util.Name;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Logger;
import java.util.logging.Level;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.ModuleElement;
import javax.lang.model.element.PackageElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.TypeParameterElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeKind;

import org.netbeans.api.annotations.common.CheckForNull;
import org.netbeans.api.annotations.common.NonNull;
import org.netbeans.modules.java.source.ElementHandleAccessor;
import org.netbeans.modules.java.source.ElementUtils;
import org.netbeans.modules.java.source.usages.ClassFileUtil;
import org.openide.util.Parameters;
import org.openide.util.WeakSet;

/**
 * Represents a handle for {@link Element} which can be kept and later resolved
 * by another javac. The javac {@link Element}s are valid only in a single
 * {@link javax.tools.JavaCompiler.CompilationTask} or a single run of a
 * {@link CancellableTask}. A client needing to
 * keep a reference to an {@link Element} and use it in another {@link CancellableTask}
 * must serialize it into an {@link ElementHandle}.
 * Currently not all {@link Element}s can be serialized. See {@link #create} for details.
 * <div class="nonnormative">
 * <p>
 * Typical usage of {@link ElementHandle} is as follows:
 * </p>
 * <pre>
 * final ElementHandle[] elementHandle = new ElementHandle[1];
 * javaSource.runUserActionTask(new Task&lt;CompilationController>() {
 *     public void run(CompilationController compilationController) {
 *         compilationController.toPhase(Phase.RESOLVED);
 *         CompilationUnitTree cu = compilationController.getTree();
 *         List&lt;? extends Tree> types = getTypeDecls(cu);
 *         Tree tree = getInterestingElementTree(types);
 *         Element element = compilationController.getElement(tree);
 *         elementHandle[0] = ElementHandle.create(element);
 *    }
 * }, true);
 *
 * otherJavaSource.runUserActionTask(new Task&lt;CompilationController>() {
 *     public void run(CompilationController compilationController) {
 *         compilationController.toPhase(Phase.RESOLVED);
 *         Element element = elementHandle[0].resolve(compilationController);
 *         // ....
 *    }
 * }, true);
 * </pre>
 * </div>
 * @author Tomas Zezula
 */
public final class ElementHandle<T extends Element> {
    private static final Logger log = Logger.getLogger(ElementHandle.class.getName());
    static {
        ElementHandleAccessor.setInstance(new ElementHandleAccessorImpl ());
    }
    
    private final ElementKind kind;
    private final String[] signatures;
        
       
    private ElementHandle(final ElementKind kind, String... signatures) {
        assert kind != null;
        assert signatures != null;
        this.kind = kind;
        this.signatures = signatures;
    }
    
    
    /**
     * Resolves an {@link Element} from the {@link ElementHandle}.
     * @param compilationInfo representing the {@link javax.tools.JavaCompiler.CompilationTask}
     * in which the {@link Element} should be resolved.
     * @return resolved subclass of {@link Element} or null if the elment does not exist on
     * the classpath/sourcepath of {@link javax.tools.JavaCompiler.CompilationTask}.
     */
    @SuppressWarnings ("unchecked")     // NOI18N
    public @CheckForNull T resolve (@NonNull final CompilationInfo compilationInfo) {
        Parameters.notNull("compilationInfo", compilationInfo); // NOI18N
        ModuleElement module;

        if (compilationInfo.getFileObject() != null) {
            JCTree.JCCompilationUnit cut = (JCTree.JCCompilationUnit)compilationInfo.getCompilationUnit();
            if (cut != null) {
                module = cut.modle;
            } else if (compilationInfo.getTopLevelElements().iterator().hasNext()) {
                module = ((Symbol) compilationInfo.getTopLevelElements().iterator().next()).packge().modle;
            } else {
                module = null;
            }
        } else {
            module = null;
        }
        T result = resolveImpl (module, compilationInfo.impl.getJavacTask());
        if (result == null) {
            if (log.isLoggable(Level.INFO))
                log.log(Level.INFO, "Cannot resolve: {0}", toString()); //NOI18N                
        } else {
            if (log.isLoggable(Level.FINE))
                log.log(Level.FINE, "Resolved element = {0}", result);
        }
        return result;
    }
        
    
    private T resolveImpl (final ModuleElement module, final JavacTaskImpl jt) {
        if (log.isLoggable(Level.FINE))
            log.log(Level.FINE, "Resolving element kind: {0}", this.kind); // NOI18N       
        ElementKind simplifiedKind = this.kind;
        if (simplifiedKind.name().equals("RECORD")) {
            simplifiedKind = ElementKind.CLASS; //TODO: test
        }
        if (simplifiedKind.name().equals("RECORD_COMPONENT")) {
            simplifiedKind = ElementKind.FIELD; //TODO: test
        }
        switch (simplifiedKind) {
            case PACKAGE:
                assert signatures.length == 1;
                return (T) jt.getElements().getPackageElement(signatures[0]);
            case CLASS:
            case INTERFACE:
            case ENUM:
            case ANNOTATION_TYPE: {
                assert signatures.length == 1;
                final Element type = getTypeElementByBinaryName (module, signatures[0], jt);
                if (type instanceof TypeElement) {
                    return (T) type;
                } else  {
                    log.log(Level.INFO, "Resolved type is null for kind = {0}", this.kind);  // NOI18N
                }
                break;
            }
            case OTHER:
                assert signatures.length == 1;
                return (T) getTypeElementByBinaryName (module, signatures[0], jt);
            case METHOD:
            case CONSTRUCTOR:            
            {
                assert signatures.length == 3;
                final Element type = getTypeElementByBinaryName (module, signatures[0], jt);
                if (type instanceof TypeElement) {
                   final List<? extends Element> members = type.getEnclosedElements();
                   for (Element member : members) {
                       if (this.kind == member.getKind()) {
                           String[] desc = ClassFileUtil.createExecutableDescriptor((ExecutableElement)member);
                           assert desc.length == 3;
                           if (this.signatures[1].equals(desc[1]) && this.signatures[2].equals(desc[2])) {
                               return (T) member;
                           }
                       }
                   }
                } else if (type != null) {
                    return (T) new Symbol.MethodSymbol(0, (Name) jt.getElements().getName(this.signatures[1]), Symtab.instance(jt.getContext()).unknownType, (Symbol)type);
                } else 
                    log.log(Level.INFO, "Resolved type is null for kind = {0}", this.kind);  // NOI18N
                break;
            }
            case INSTANCE_INIT:
            case STATIC_INIT:
            {
                assert signatures.length == 2;
                final Element type = getTypeElementByBinaryName (module, signatures[0], jt);
                if (type instanceof TypeElement) {
                   final List<? extends Element> members = type.getEnclosedElements();
                   for (Element member : members) {
                       if (this.kind == member.getKind()) {
                           String[] desc = ClassFileUtil.createExecutableDescriptor((ExecutableElement)member);
                           assert desc.length == 2;
                           if (this.signatures[1].equals(desc[1])) {
                               return (T) member;
                           }
                       }
                   }
                } else
                    log.log(Level.INFO, "Resolved type is null for kind = {0}", this.kind); // NOI18N
                break;
            }
            case FIELD:
            case ENUM_CONSTANT:
            {
                assert signatures.length == 3;
                final Element type = getTypeElementByBinaryName (module, signatures[0], jt);
                if (type instanceof TypeElement) {
                    final List<? extends Element> members = type.getEnclosedElements();
                    for (Element member : members) {
                        if (this.kind == member.getKind()) {
                            String[] desc = ClassFileUtil.createFieldDescriptor((VariableElement)member);
                            assert desc.length == 3;
                            if (this.signatures[1].equals(desc[1]) && this.signatures[2].equals(desc[2])) {
                                return (T) member;
                            }
                        }
                    }
                } else if (type != null) {
                    return (T) new Symbol.VarSymbol(0, (Name) jt.getElements().getName(this.signatures[1]), Symtab.instance(jt.getContext()).unknownType, (Symbol)type);
                } else 
                    log.log(Level.INFO, "Resolved type is null for kind = {0}", this.kind); // NOI18N
                break;
            }
            case PARAMETER:
            {
                assert signatures.length == 3;
                final Element type = getTypeElementByBinaryName (module, signatures[0], jt);
                if (type instanceof TypeElement) {
                    final List<? extends Element> members = type.getEnclosedElements();
                    for (Element member : members) {
                        if (member.getKind() == ElementKind.METHOD || member.getKind() == ElementKind.CONSTRUCTOR) {
                            String[] desc = ClassFileUtil.createExecutableDescriptor((ExecutableElement)member);
                            assert desc.length == 3;
                            if (this.signatures[1].equals(desc[1]) && this.signatures[2].equals(desc[2])) {
                                assert member instanceof ExecutableElement;
                                List<? extends VariableElement> ves =((ExecutableElement)member).getParameters();
                                for (VariableElement ve : ves) {
                                    if (ve.getSimpleName().contentEquals(signatures[3])) {
                                        return (T) ve;
                                    }
                                }
                            }
                        }
                    }
                } else
                    log.log(Level.INFO, "Resolved type is null for kind = {0} signatures.length = {1}", new Object[] {this.kind, signatures.length}); // NOI18N
                break;
            }
            case TYPE_PARAMETER:
            {
                if (signatures.length == 2) {
                     Element type = getTypeElementByBinaryName (module, signatures[0], jt);
                     if (type instanceof TypeElement) {
                         List<? extends TypeParameterElement> tpes = ((TypeElement)type).getTypeParameters();
                         for (TypeParameterElement tpe : tpes) {
                             if (tpe.getSimpleName().contentEquals(signatures[1])) {
                                 return (T)tpe;
                             }
                         }
                     } else 
                        log.log(Level.INFO, "Resolved type is null for kind = {0} signatures.length = {1}", new Object[] {this.kind, signatures.length});   // NOI18N
                }
                else if (signatures.length == 4) {
                    final Element type = getTypeElementByBinaryName (module, signatures[0], jt);
                    if (type instanceof TypeElement) {
                        final List<? extends Element> members = type.getEnclosedElements();
                        for (Element member : members) {
                            if (member.getKind() == ElementKind.METHOD || member.getKind() == ElementKind.CONSTRUCTOR) {
                                String[] desc = ClassFileUtil.createExecutableDescriptor((ExecutableElement)member);
                                assert desc.length == 3;
                                if (this.signatures[1].equals(desc[1]) && this.signatures[2].equals(desc[2])) {
                                    assert member instanceof ExecutableElement;
                                    List<? extends TypeParameterElement> tpes =((ExecutableElement)member).getTypeParameters();
                                    for (TypeParameterElement tpe : tpes) {
                                        if (tpe.getSimpleName().contentEquals(signatures[3])) {
                                            return (T) tpe;
                                        }
                                    }
                                }
                            }
                        }
                    } else 
                        log.log(Level.INFO, "Resolved type is null for kind = {0} signatures.length = {1}", new Object[] {this.kind, signatures.length}); // NOI18N
                }
                else {
                    throw new IllegalStateException ();
                }
                break;
            }
            case MODULE:
                assert signatures.length == 1;
                final ModuleFinder cml = ModuleFinder.instance(jt.getContext());
                final Element me = cml.findModule((Name)jt.getElements().getName(this.signatures[0]));
                if (me != null) {
                    return (T) me;
                } else {
                    log.log(Level.INFO, "Cannot resolve module: {0}", this.signatures[0]);  // NOI18N
                }
                break;
            default:
                throw new IllegalStateException ();
        }
        if (log.isLoggable(Level.FINE))
            log.log(Level.FINE, "All resolvings failed. Returning null.");  // NOI18N
        return null;
    }
    
    
    /**
     * Tests if the handle has the same signature as the parameter.
     * The handles with the same signatures are resolved into the same
     * element in the same {@link javax.tools.JavaCompiler} task, but may be resolved into
     * the different {@link Element}s in the different {@link javax.tools.JavaCompiler} tasks.
     * @param handle to be checked
     * @return true if the handles resolve into the same {@link Element}s
     * in the same {@link javax.tools.JavaCompiler} task.
     */
    public boolean signatureEquals (@NonNull final ElementHandle<? extends Element> handle) {
         if (!isSameKind (this.kind, handle.kind) || this.signatures.length != handle.signatures.length) {
             return false;
         }
         for (int i=0; i<signatures.length; i++) {
             if (!signatures[i].equals(handle.signatures[i])) {
                 return false;
             }
         }
         return true;
    }
    
    
    private static boolean isSameKind (ElementKind k1, ElementKind k2) {
        if ((k1 == k2) ||
           (k1 == ElementKind.OTHER && (k2.isClass() || k2.isInterface())) ||     
           (k2 == ElementKind.OTHER && (k1.isClass() || k1.isInterface()))) {
            return true;
        }
        return false;
    }
    
    
    /**
     * Returns a binary name of the {@link TypeElement} represented by this
     * {@link ElementHandle}. When the {@link ElementHandle} doesn't represent
     * a {@link TypeElement} it throws a {@link IllegalStateException}
     * @return the qualified name
     * @throws IllegalStateException when this {@link ElementHandle} 
     * isn't created for the {@link TypeElement}.
     */
    public @NonNull String getBinaryName () throws IllegalStateException {
        if ((this.kind.isClass() && !isArray(signatures[0])) ||
                this.kind.isInterface() ||
                this.kind == ElementKind.MODULE ||
                this.kind == ElementKind.OTHER) {
            return this.signatures[0];
        }
        else {
            throw new IllegalStateException ();
        }
    }
    
    
    /**
     * Returns a qualified name of the {@link TypeElement} represented by this
     * {@link ElementHandle}. When the {@link ElementHandle} doesn't represent
     * a {@link TypeElement} it throws a {@link IllegalStateException}
     * @return the qualified name
     * @throws IllegalStateException when this {@link ElementHandle} 
     * isn't creatred for the {@link TypeElement}.
     */
    public @NonNull String getQualifiedName () throws IllegalStateException {
        if ((this.kind.isClass() && !isArray(signatures[0])) ||
                this.kind.isInterface() ||
                this.kind == ElementKind.MODULE ||
                this.kind == ElementKind.OTHER) {
            return this.signatures[0].replace (Target.DEFAULT.syntheticNameChar(),'.');    //NOI18N
        }
        else {
            throw new IllegalStateException ();
        }
    }
    
    
    /**
     * Tests if the handle has this same signature as the parameter.
     * The handles has the same signatures if it is resolved into the same
     * element in the same {@link javax.tools.JavaCompiler} task, but may be resolved into
     * the different {@link Element} in the different {@link javax.tools.JavaCompiler} task.
     * @param element to be checked
     * @return true if this handle resolves into the same {@link Element}
     * in the same {@link javax.tools.JavaCompiler} task.
     */
    public boolean signatureEquals (@NonNull final T element) {
        final ElementKind ek = element.getKind();
        final ElementKind thisKind = getKind();
        if ((ek != thisKind) && !(thisKind == ElementKind.OTHER && (ek.isClass() || ek.isInterface()))) {
            return false;
        }
        final ElementHandle<T> handle = create (element);
        return signatureEquals (handle);
    }
    
    /**
     * Returns the {@link ElementKind} of this element handle,
     * it is the kind of the {@link Element} from which the handle
     * was created.
     * @return {@link ElementKind}
     *
     */
    public @NonNull ElementKind getKind () {
        return this.kind;
    }
    
    private static final WeakSet<ElementHandle<?>> NORMALIZATION_CACHE = new WeakSet<ElementHandle<?>>();

    /**
     * Factory method for creating {@link ElementHandle}.
     * @param element for which the {@link ElementHandle} should be created. Permitted
     * {@link ElementKind}s
     * are: {@link ElementKind#PACKAGE}, {@link ElementKind#CLASS},
     * {@link ElementKind#INTERFACE}, {@link ElementKind#ENUM}, {@link ElementKind#ANNOTATION_TYPE}, {@link ElementKind#METHOD},
     * {@link ElementKind#CONSTRUCTOR}, {@link ElementKind#INSTANCE_INIT}, {@link ElementKind#STATIC_INIT},
     * {@link ElementKind#FIELD}, and {@link ElementKind#ENUM_CONSTANT}.
     * @return a new {@link ElementHandle}
     * @throws IllegalArgumentException if the element is of an unsupported {@link ElementKind}
     */
    public static @NonNull <T extends Element> ElementHandle<T> create (@NonNull final T element) throws IllegalArgumentException {
        ElementHandle<T> eh = createImpl(element);

        return (ElementHandle<T>) NORMALIZATION_CACHE.putIfAbsent(eh);
    }
    
    /**
     * Creates an {@link ElementHandle} representing a {@link PackageElement}.
     * @param packageName the name of the package
     * @return the created {@link ElementHandle}
     * @since 0.98
     */
    @NonNull
    public static ElementHandle<PackageElement> createPackageElementHandle (
        @NonNull final String packageName) {
        Parameters.notNull("packageName", packageName); //NOI18N
        return new ElementHandle<PackageElement>(ElementKind.PACKAGE, packageName);
    }
    
    /**
     * Creates an {@link ElementHandle} representing a {@link TypeElement}.
     * @param kind the {@link ElementKind} of the {@link TypeElement},
     * allowed values are {@link ElementKind#CLASS}, {@link ElementKind#INTERFACE},
     * {@link ElementKind#ENUM} and {@link ElementKind#ANNOTATION_TYPE}.
     * @param binaryName the class binary name as specified by JLS §13.1
     * @return the created {@link ElementHandle}
     * @throws IllegalArgumentException if kind is neither class nor interface
     * @since 0.98
     */
    @NonNull
    public static ElementHandle<TypeElement> createTypeElementHandle(
        @NonNull final ElementKind kind,
        @NonNull final String binaryName) throws IllegalArgumentException {
        Parameters.notNull("kind", kind);   //NOI18N
        Parameters.notNull("binaryName", binaryName);   //NOI18N
        if (!kind.isClass() && !kind.isInterface()) {
            throw new IllegalArgumentException(kind.toString());
        }
        return new ElementHandle<TypeElement>(kind, binaryName);
    }

    /**
     * Creates an {@link ElementHandle} representing a {@link ModuleElement}.
     * @param moduleName the name of the module
     * @return the created {@link ElementHandle}
     * @since 2.26
     */
    @NonNull
    public static ElementHandle<ModuleElement> createModuleElementHandle(
            @NonNull final String moduleName) {
        Parameters.notNull("moduleName", moduleName); //NOI18N
        return new ElementHandle<>(ElementKind.MODULE, moduleName);
    }

    private static @NonNull <T extends Element> ElementHandle<T> createImpl (@NonNull final T element) throws IllegalArgumentException {
        Parameters.notNull("element", element);
        ElementKind kind = element.getKind();
        ElementKind simplifiedKind = kind;
        String[] signatures;
        switch (simplifiedKind) {
            case PACKAGE:
                assert element instanceof PackageElement;
                signatures = new String[]{((PackageElement)element).getQualifiedName().toString()};
                break;
            case CLASS:
            case INTERFACE:
            case ENUM:
            case ANNOTATION_TYPE:
            case RECORD:
                assert element instanceof TypeElement;
                signatures = new String[] {ClassFileUtil.encodeClassNameOrArray((TypeElement)element)};
                break;
            case METHOD:
            case CONSTRUCTOR:                
            case INSTANCE_INIT:
            case STATIC_INIT:
                assert element instanceof ExecutableElement;
                signatures = ClassFileUtil.createExecutableDescriptor((ExecutableElement)element);
                break;
            case FIELD:
            case ENUM_CONSTANT:
            case RECORD_COMPONENT:
                assert element instanceof VariableElement;
                signatures = ClassFileUtil.createFieldDescriptor((VariableElement)element);
                break;
            case PARAMETER:
                assert element instanceof VariableElement;
                Element ee = element.getEnclosingElement();
                ElementKind eek = ee.getKind();
                if (eek == ElementKind.METHOD || eek == ElementKind.CONSTRUCTOR) {
                    assert ee instanceof ExecutableElement;
                    String[] _sigs = ClassFileUtil.createExecutableDescriptor((ExecutableElement)ee);
                    signatures = new String[_sigs.length + 1];
                    System.arraycopy(_sigs, 0, signatures, 0, _sigs.length);
                    signatures[_sigs.length] = element.getSimpleName().toString();
                }
                else {
                    throw new IllegalArgumentException(eek.toString());
                }
                break;
            case TYPE_PARAMETER:
                assert element instanceof TypeParameterElement;
                TypeParameterElement tpe = (TypeParameterElement) element;
                Element ge = tpe.getGenericElement();
                ElementKind gek = ge.getKind();
                if (gek.isClass() || gek.isInterface()) {
                    assert ge instanceof TypeElement;
                    signatures = new String[2];
                    signatures[0] = ClassFileUtil.encodeClassNameOrArray((TypeElement)ge);
                    signatures[1] = tpe.getSimpleName().toString();
                }
                else if (gek == ElementKind.METHOD || gek == ElementKind.CONSTRUCTOR) {
                    assert ge instanceof ExecutableElement;
                    String[] _sigs = ClassFileUtil.createExecutableDescriptor((ExecutableElement)ge);
                    signatures = new String[_sigs.length + 1];
                    System.arraycopy(_sigs, 0, signatures, 0, _sigs.length);
                    signatures[_sigs.length] = tpe.getSimpleName().toString();
                }
                else {
                    throw new IllegalArgumentException(gek.toString());
                }
                break;
            case MODULE:
                signatures = new String[]{((ModuleElement)element).getQualifiedName().toString()};
                break;
            default:
                throw new IllegalArgumentException(kind.toString());
        }
        return new ElementHandle<T> (kind, signatures);
    }
    
    /**
     * Gets {@link ElementHandle} from {@link TypeMirrorHandle} representing {@link DeclaredType}.
     * @param typeMirrorHandle from which the {@link ElementHandle} should be retrieved. Permitted
     * {@link TypeKind} is {@link TypeKind#DECLARED}.
     * @return an {@link ElementHandle}
     * @since 0.29.0
     */
    public static @NonNull ElementHandle<? extends TypeElement> from (@NonNull final TypeMirrorHandle<? extends DeclaredType> typeMirrorHandle) {
        Parameters.notNull("typeMirrorHandle", typeMirrorHandle);
        if (typeMirrorHandle.getKind() != TypeKind.DECLARED) {
            throw new IllegalStateException("Incorrect kind: " + typeMirrorHandle.getKind());
        }
        return (ElementHandle<TypeElement>)typeMirrorHandle.getElementHandle();
    }
    
    public @Override String toString () {
        final StringBuilder result = new StringBuilder ();
        result.append (this.getClass().getSimpleName());
        result.append ('[');                                // NOI18N
        result.append ("kind=").append (this.kind.toString());      // NOI18N
        result.append ("; sigs=");                          // NOI18N
        for (String sig : this.signatures) {
            result.append (sig);
            result.append (' ');                            // NOI18N
        }
        result.append (']');                                // NOI18N
        return result.toString();
    }
    
    
    /**{@inheritDoc}*/
    @Override
    public int hashCode () {
        int hashCode = 0;
        
        for (String sig : signatures) {
            hashCode = hashCode ^ (sig != null ? sig.hashCode() : 0);
        }
        
        return hashCode;
    }
    
    /**{@inheritDoc}*/
    @Override
    public boolean equals (Object other) {
        if (other instanceof ElementHandle) {
            return signatureEquals((ElementHandle)other);
        }
        return false;
    }
    
    
    /**
     * Returns the element signature.
     * Package private, used by ClassIndex.
     */
    String[] getSignature () {
        return this.signatures;
    }
        
    
    private static class ElementHandleAccessorImpl extends ElementHandleAccessor {
        
        @Override
        public ElementHandle create(ElementKind kind, String... descriptors) {
            assert kind != null;
            assert descriptors != null;
            switch (kind) {
                case PACKAGE:
                    if (descriptors.length != 1) {
                        throw new IllegalArgumentException ();
                    }
                    return new ElementHandle<PackageElement> (kind, descriptors);
                case MODULE:
                case CLASS:
                case INTERFACE:
                case ENUM:
                case ANNOTATION_TYPE:
                case RECORD:
                case OTHER:
                    if (descriptors.length != 1) {
                        throw new IllegalArgumentException ();
                    }
                    return new ElementHandle<TypeElement> (kind, descriptors);
                case METHOD:
                case CONSTRUCTOR:                
                    if (descriptors.length != 3) {
                        throw new IllegalArgumentException ();
                    }
                    return new ElementHandle<ExecutableElement> (kind, descriptors);
                case INSTANCE_INIT:
                case STATIC_INIT:
                    if (descriptors.length != 2) {
                        throw new IllegalArgumentException ();
                    }
                    return new ElementHandle<ExecutableElement> (kind, descriptors);
                case FIELD:
                case ENUM_CONSTANT:
                    if (descriptors.length != 3) {
                        throw new IllegalArgumentException ();
                    }
                    return new ElementHandle<VariableElement> (kind, descriptors);
                default:
                    throw new IllegalArgumentException();
                    
            }            
        }

        @Override
        public <T extends Element> T resolve(ElementHandle<T> handle, JavacTaskImpl jti) {
            return handle.resolveImpl (null, jti);
        }

        @Override
        @NonNull
        public String[] getJVMSignature(@NonNull final ElementHandle<?> handle) {
            return Arrays.copyOf(handle.signatures, handle.signatures.length);
        }

    }
    
    private static Element getTypeElementByBinaryName (final ModuleElement module, final String signature, final JavacTaskImpl jt) {
        if (log.isLoggable(Level.FINE))
            log.log(Level.FINE, "Calling getTypeElementByBinaryName: signature = {0}", signature);
        if (isNone(signature)) {
            return Symtab.instance(jt.getContext()).noSymbol;
        }
        else if (isArray(signature)) {
            return Symtab.instance(jt.getContext()).arrayClass;
        }
        else {
            return (TypeElement) (module != null
                    ? ElementUtils.getTypeElementByBinaryName(jt, module, signature)
                    : ElementUtils.getTypeElementByBinaryName(jt, signature));
        }
    }
    
    private static boolean isNone (String signature) {
        return signature.length() == 0;
    }

    private static boolean isArray (String signature) {
        return signature.length() == 1 && signature.charAt(0) == '[';
    }
}
