org.jboss.tools.common.util.EclipseJavaUtil.java Source code

Java tutorial

Introduction

Here is the source code for org.jboss.tools.common.util.EclipseJavaUtil.java

Source

/*******************************************************************************
 * Copyright (c) 2007 Exadel, Inc. and Red Hat, Inc.
 * Distributed under license by Red Hat, Inc. All rights reserved.
 * This program is made available under the terms of the
 * Eclipse Public License v1.0 which accompanies this distribution,
 * and is available at http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     Exadel, Inc. and Red Hat, Inc. - initial API and implementation
 ******************************************************************************/
package org.jboss.tools.common.util;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.jdt.core.IAnnotatable;
import org.eclipse.jdt.core.IAnnotation;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IField;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IMember;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.ITypeHierarchy;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.Signature;
import org.jboss.tools.common.core.CommonCorePlugin;

public class EclipseJavaUtil {

    public static String getMemberTypeAsString(IMember member) {
        if (member instanceof IField)
            return getMemberTypeAsString((IField) member);
        if (member instanceof IMethod)
            return getMemberTypeAsString((IMethod) member);
        return null;
    }

    public static String getMemberTypeAsString(IField f) {
        if (f == null)
            return null;
        try {
            String typeName = new String(Signature.toCharArray(f.getTypeSignature().toCharArray()));
            return resolveType(f.getDeclaringType(), typeName);
        } catch (JavaModelException e) {
            CommonCorePlugin.getPluginLog().logError(e);
        }
        return null;
    }

    public static String getMemberTypeAsString(IMethod m) {
        if (m == null)
            return null;
        try {
            return resolveTypeAsString(m.getDeclaringType(), m.getReturnType());
        } catch (JavaModelException e) {
            CommonCorePlugin.getPluginLog().logError(e);
        }
        return null;
    }

    public static String resolveTypeAsString(IType type, String typeName) {
        if (type == null || typeName == null)
            return null;
        typeName = new String(Signature.toCharArray(typeName.toCharArray()));
        int i = typeName.indexOf(Signature.C_GENERIC_START);
        if (i > 0)
            typeName = typeName.substring(0, i);
        return resolveType(type, typeName);
    }

    public static String resolveType(IType type, String typeName) {
        return TypeResolutionCache.getInstance().resolveType(type, typeName);
    }

    static Map<String, Map<String, IType>> typeCache = new Hashtable<String, Map<String, IType>>();

    /**
     * Returns IType found in a Java project by its qualified name.
     * The cache is used that is should be cleared explicitly by 
     * TypeResolutionCache.getInstance().clear();
     * Currently, it is done by KBBuilder so that this method works fine for all clients that 
     * request only projects with KB nature. Otherwise, non-existent object may be 
     * returned from the cache.
     * 
     * Now, it is not clear if the search over package roots, 
     * fulfilled when IJavaProject.findType(String) fails, makes sense.
     * There are neither tests nor use-cases that would support the need of it.
     * 
     * @param javaProject
     * @param qualifiedName
     * @return
     * @throws JavaModelException
     */
    public static IType findType(IJavaProject javaProject, String qualifiedName) throws JavaModelException {
        if (qualifiedName == null || qualifiedName.length() == 0 || "void".equals(qualifiedName))
            return null;
        Map<String, IType> cache = typeCache.get(javaProject.getElementName());
        if (cache == null) {
            cache = new Hashtable<String, IType>();
            typeCache.put(javaProject.getElementName(), cache);
        } else {
            IType type = cache.get(qualifiedName);
            if (type != null) {
                if (type.exists()) {
                    return type;
                } else {
                    cache.remove(qualifiedName);
                }
            }
        }
        IType type = javaProject.findType(qualifiedName);
        if (type != null && type.exists()) {
            return register(cache, qualifiedName, type);
        }

        //TODO Either provide use-case that justifies the 
        //     direct search over roots when IJavaProject.findType(String) fails
        //     or remove this obsolete code.
        //      int dot = qualifiedName.lastIndexOf('.');
        //      String packageName = (dot < 0) ? "" : qualifiedName.substring(0, dot); //$NON-NLS-1$
        //      String shortName = qualifiedName.substring(dot + 1);
        //      IPackageFragmentRoot[] rs = javaProject.getPackageFragmentRoots();
        //      for (int i = 0; i < rs.length; i++) {
        //         IPackageFragment f = rs[i].getPackageFragment(packageName);
        //         if(f == null || !f.exists()) continue;
        //         ICompilationUnit[] us = f.getCompilationUnits();
        //         for (int j = 0; j < us.length; j++) {
        //            IType t = us[j].getType(shortName);
        //            if(t != null && t.exists()) return register(cache, qualifiedName, t);
        //         }
        //      }
        return null;
    }

    private static IType register(Map<String, IType> cache, String qualifiedName, IType type) {
        cache.put(qualifiedName, type);
        return type;
    }

    public static List<IType> getSupperTypes(IType type) throws JavaModelException {
        ITypeHierarchy typeHierarchy = type.newSupertypeHierarchy(new NullProgressMonitor());
        IType[] superTypes = typeHierarchy == null ? null : typeHierarchy.getAllSupertypes(type);
        if (superTypes == null) {
            return Collections.emptyList();
        }
        List<IType> suppers = new ArrayList<IType>();
        for (int i = 0; i < superTypes.length; i++) {
            suppers.add(superTypes[i]);
        }
        return suppers;
    }

    public static IAnnotation findAnnotation(IType sourceType, IAnnotatable member, String qulifiedAnnotationName)
            throws JavaModelException {
        IAnnotation[] annotations = member.getAnnotations();
        String simpleAnnotationTypeName = qulifiedAnnotationName;
        int lastDot = qulifiedAnnotationName.lastIndexOf('.');
        if (lastDot > -1) {
            simpleAnnotationTypeName = simpleAnnotationTypeName.substring(lastDot + 1);
        }
        for (IAnnotation annotation : annotations) {
            if (qulifiedAnnotationName.equals(annotation.getElementName())) {
                return annotation;
            }
            if (simpleAnnotationTypeName.equals(annotation.getElementName())) {
                String fullAnnotationclassName = EclipseJavaUtil.resolveType(sourceType, simpleAnnotationTypeName);
                if (fullAnnotationclassName != null) {
                    IType annotationType = sourceType.getJavaProject().findType(fullAnnotationclassName);
                    if (annotationType != null
                            && annotationType.getFullyQualifiedName().equals(qulifiedAnnotationName)) {
                        return annotation;
                    }
                }
            }
        }
        return null;
    }

    /**
     * Finds field declared in the given type or its super types.
     * 
     * @param type
     * @param name
     * @return
     * @throws CoreException
     */
    public static IField findField(IType type, String name) throws CoreException {
        return findField(type, name, new HashSet<IType>());
    }

    private static IField findField(IType type, String name, Set<IType> processed) throws CoreException {
        if (!type.exists() || processed.contains(type)) {
            return null;
        }
        processed.add(type);
        if (type.getField(name).exists()) {
            return type.getField(name);
        }
        IField f = findField(type, type.getSuperclassName(), name, processed);
        String[] is = type.getSuperInterfaceNames();
        for (int i = 0; f == null && i < is.length; i++) {
            f = findField(type, is[i], name, processed);
        }
        if (f == null) {
            IType d = type.getDeclaringType();
            if (d != null && d != type && d.exists()) {
                f = findField(d, name);
            }
        }

        return f;
    }

    private static IField findField(IType context, String typeName, String fieldName, Set<IType> processed)
            throws CoreException {
        typeName = resolveType(context, typeName);
        if (typeName != null) {
            IType s = findType(context.getJavaProject(), typeName);
            return (s != null) ? findField(s, fieldName, processed) : null;
        }
        return null;
    }

    /**
     * Returns true if the given annotation has the given full name
     * @param annotation
     * @param fullName
     * @return
     * @throws JavaModelException
     */
    public static boolean checkAnnotationByFulltName(IAnnotation annotation, String fullName)
            throws JavaModelException {
        if (annotation.getElementName().equals(fullName)) {
            return true;
        }
        boolean result = true;
        IType sourceType = null;
        IJavaElement parent = annotation.getParent();
        if (parent instanceof IMember) {
            if (parent instanceof IType) {
                sourceType = (IType) parent;
            } else {
                sourceType = ((IMember) parent).getDeclaringType();
            }
            String fullAnnotationName = EclipseJavaUtil.resolveType(sourceType, annotation.getElementName());
            if (fullAnnotationName != null) {
                IType annotationType = sourceType.getJavaProject().findType(fullAnnotationName);
                result = annotationType != null && annotationType.getFullyQualifiedName().equals(fullName);
            } else {
                result = false;
            }
        }
        return result;
    }

    /**
     * Returns annotation by the short name declared for the given java member and its parents.
     * Returns null if no annotation found.
     * @param member
     * @param name
     * @param checkParents
     * @return
     * @throws JavaModelException
     */
    public static Set<IAnnotation> findAnnotationsByShortName(IJavaElement element, String name,
            boolean checkParents) throws JavaModelException {
        return findAnnotationsByShortName(null, element, name, checkParents);
    }

    private static Set<IAnnotation> findAnnotationsByShortName(Set<IAnnotation> result, IJavaElement element,
            String name, boolean checkParents) throws JavaModelException {
        if (element instanceof IAnnotatable) {
            IAnnotation[] annotations = ((IAnnotatable) element).getAnnotations();
            for (IAnnotation annotation : annotations) {
                String aName = annotation.getElementName();
                int i = aName.lastIndexOf('.');
                if (i > -1) {
                    aName = aName.substring(i + 1);
                }
                if (aName.equals(name)) {
                    if (result == null) {
                        result = new HashSet<IAnnotation>();
                    }
                    result.add(annotation);
                    break;
                }
            }
        }
        if (checkParents) {
            IJavaElement parent = element.getParent();
            if (parent instanceof IAnnotatable) {
                return findAnnotationsByShortName(result, parent, name, true);
            }
        }
        return result;
    }
}