| /******************************************************************************* |
| * Copyright (c) 2004, 2005 Sybase, Inc. and others. |
| * |
| * All rights reserved. This program and the accompanying materials |
| * are 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: |
| * Sybase, Inc. - initial API and implementation |
| *******************************************************************************/ |
| |
| package org.eclipse.jst.jsf.facesconfig.ui.util; |
| |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Comparator; |
| import java.util.Iterator; |
| import java.util.List; |
| |
| import org.eclipse.core.resources.IFile; |
| import org.eclipse.core.resources.IProject; |
| import org.eclipse.jdt.core.Flags; |
| import org.eclipse.jdt.core.ICompilationUnit; |
| import org.eclipse.jdt.core.IJavaProject; |
| import org.eclipse.jdt.core.IMethod; |
| import org.eclipse.jdt.core.IPackageDeclaration; |
| import org.eclipse.jdt.core.IType; |
| import org.eclipse.jdt.core.ITypeHierarchy; |
| import org.eclipse.jdt.core.JavaCore; |
| import org.eclipse.jdt.core.JavaModelException; |
| import org.eclipse.jdt.core.Signature; |
| import org.eclipse.jdt.ui.JavaUI; |
| import org.eclipse.jst.jsf.common.ui.IFileFolderConstants; |
| import org.eclipse.jst.jsf.common.ui.internal.utils.JavaModelUtil; |
| import org.eclipse.ui.IEditorPart; |
| import org.eclipse.ui.PartInitException; |
| |
| /** |
| * This utility class defines typical operations on java class, such as check |
| * public constructor, and check type is primitive or not, etc. |
| * |
| * @author Jane Cantz, Xiao-guang Zhang |
| */ |
| public class JavaClassUtils { |
| /** |
| * Determines if a string contains any illegal characters |
| * |
| * @param text - |
| * the string to test |
| * @return boolean - true if an illegal character is found, otherwise false |
| */ |
| public static boolean hasIllegalCharacters(String text) { |
| if (text.length() == 0 |
| || !Character.isJavaIdentifierStart(text.charAt(0))) { |
| return true; |
| } |
| for (int i = 1; i < text.length(); i++) { |
| if (!Character.isJavaIdentifierPart(text.charAt(i))) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| /** |
| * Test for constructor. |
| * <p> |
| * This test determines if the class has any constructors |
| * </p> |
| * |
| * @param methods - |
| * the IMethod array to examine |
| * @return boolean - true, if method has no constructors |
| */ |
| public static boolean hasNoConstructor(IMethod[] methods) { |
| for (int m = 0; m < methods.length; m++) { |
| try { |
| if (methods[m].isConstructor()) { |
| return false; |
| } |
| } catch (JavaModelException e) { |
| // suppress: this is possible; fall through |
| } |
| } |
| return true; |
| } |
| |
| /** |
| * check whether the method is public or not. |
| * |
| * @param method |
| * @return true if method is public |
| */ |
| public static boolean isPublicMethod(IMethod method) { |
| int accessFlags = 0; |
| |
| try { |
| accessFlags = method.getFlags(); |
| } catch (JavaModelException e) { |
| return false; |
| } |
| |
| boolean isPublic = Flags.isPublic(accessFlags); |
| if ((!Flags.isPrivate(accessFlags)) |
| && (!Flags.isProtected(accessFlags)) |
| && (!Flags.isPublic(accessFlags))) { |
| // No specific modifier was set, so assume to be public |
| isPublic = true; |
| } |
| if (!isPublic) { |
| return false; |
| } |
| return true; |
| } |
| |
| /** |
| * Test for constructor. |
| * <p> |
| * This test has the following conditions: |
| * </p> |
| * <ul> |
| * <li>method takes 0 arguments and the method name is the class name: |
| * <ul> |
| * <li>takes 0 arguments</li> |
| * <li>the method name is the class name</li> |
| * <li>the method returns void</code></li> |
| * </ul> |
| * </li> |
| * </ul> |
| * |
| * @param methods - |
| * the IMethod array to examine |
| * @return boolean - true, if method is a constructor |
| */ |
| public static boolean hasPublicConstructor(IMethod[] methods) { |
| for (int m = 0; m < methods.length; m++) { |
| try { |
| if (methods[m].isConstructor() && isPublicMethod(methods[m])) { |
| // Constructor must have the following 0 arguments |
| String[] params = methods[m].getParameterTypes(); |
| if (params.length == 0) { |
| // And must return a void |
| String rtn = methods[m].getReturnType(); |
| if (rtn.equals(Signature.SIG_VOID)) { |
| return true; |
| } |
| break; |
| } |
| } |
| } catch (JavaModelException e) { |
| // Nothing to do. |
| } |
| } |
| return false; |
| } |
| |
| /** |
| * Determines if a datatype is primitive type or part of java.lang or |
| * java.util package. If not, it is considered to be a bean reference |
| * |
| * @param classType - |
| * the parent class compilation unit |
| * @param signatureName - |
| * the datatype of the property |
| * @return boolean - true, if the datatype is primitive or part of java.lang |
| * or java.util package |
| */ |
| public static boolean isPrimitiveType(IType classType, String signatureName) { |
| while (signatureName.startsWith("[")) { //$NON-NLS-1$ |
| signatureName = signatureName.substring(1); |
| } |
| int kind = Signature.getTypeSignatureKind(signatureName); |
| if (kind == Signature.BASE_TYPE_SIGNATURE |
| || signatureName.equals(Signature.SIG_VOID)) { |
| // These are true primitive types |
| return true; |
| } |
| |
| String qualifiedName = getQualifiedTypeNameInTypeHierarchy(classType, |
| signatureName); |
| |
| if ((qualifiedName.startsWith("java.lang")) || (qualifiedName.startsWith("java.util"))) //$NON-NLS-1$ //$NON-NLS-2$ |
| { |
| return true; |
| } |
| return false; |
| } |
| |
| /** |
| * get the type from the input class name |
| * |
| * @param project |
| * @param className |
| * @return - can be null. |
| */ |
| public static IType getType(IProject project, String className) { |
| if (project == null) { |
| return null; |
| } |
| IType cunit = null; |
| if (className.length() > 0) { |
| |
| IJavaProject jProject = JavaCore.create(project); |
| try { |
| cunit = jProject.findType(className); |
| } catch (JavaModelException e) { |
| // suppress: fall-through and return null |
| } |
| } |
| return cunit; |
| } |
| |
| /** |
| * open the type in the editor. |
| * |
| * @param type |
| * @return true if the type could opened in an editor |
| */ |
| public static boolean openType(IType type) { |
| if (type == null || !type.exists()) { |
| return false; |
| } |
| |
| try { |
| IEditorPart editorPart = JavaUI.openInEditor(type |
| .getPrimaryElement()); |
| if (editorPart != null) { |
| JavaUI.revealInEditor(editorPart, type.getPrimaryElement()); |
| return true; |
| } |
| } catch (PartInitException e) { |
| // ignore this error. |
| } catch (JavaModelException e) { |
| // ignore this error. |
| } |
| return false; |
| } |
| |
| /** |
| * get package name from java source file |
| * |
| * @param javaFile |
| * @return - can be null. |
| */ |
| public static String getPackageName(IFile javaFile) { |
| if (javaFile == null) { |
| return null; |
| } |
| String ext = "." + javaFile.getFileExtension(); //$NON-NLS-1$ |
| // See if the file is a java file |
| if (!ext.equalsIgnoreCase(IFileFolderConstants.EXT_JAVA)) { |
| return null; |
| } |
| String packagename = new String(); |
| ICompilationUnit cunit = JavaCore.createCompilationUnitFrom(javaFile); |
| try { |
| IPackageDeclaration[] packages = cunit.getPackageDeclarations(); |
| if (packages.length == 0) { |
| packagename = new String(); |
| } else { |
| packagename = packages[0].getElementName(); |
| } |
| } catch (JavaModelException jme) { |
| // suppress: fall-through and return an empty string?? TODO:? |
| } |
| return packagename; |
| } |
| |
| /** |
| * copy the array to the list. |
| * |
| * @param methodList |
| * @param methods |
| */ |
| private static void copyToMethodList(List methodList, IMethod[] methods) { |
| if (methods != null && methods.length > 0) { |
| for (int i = 0; i < methods.length; i++) { |
| if (!isDuplicateMethod(methodList, methods[i])) { |
| methodList.add(methods[i]); |
| } |
| } |
| } |
| } |
| |
| /** |
| * check whether this method is duplicated or not in the existing method |
| * list. |
| * |
| * @param methodList |
| * @param method |
| * @return |
| */ |
| private static boolean isDuplicateMethod(List methodList, IMethod method) { |
| if (method == null || !method.exists()) { |
| return false; |
| } |
| |
| String[] paramTypes = method.getParameterTypes(); |
| String methodName = method.getElementName(); |
| |
| for (Iterator iter = methodList.iterator(); iter.hasNext();) { |
| IMethod existedMethod = (IMethod) iter.next(); |
| if (isSameMethodSignature(methodName, paramTypes, existedMethod)) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| /** |
| * Tests if a method equals to the given signature. Parameter types are only |
| * compared by the simple name, no resolving for the fully qualified type |
| * name is done. Constructors are only compared by parameters, not the name. |
| * |
| * @param name |
| * Name of the method |
| * @param paramTypes |
| * The type signatures of the parameters e.g. |
| * <code>{"QString;","I"}</code> |
| * @param curr |
| * @return Returns <code>true</code> if the method has the given name and |
| * parameter types and constructor state. |
| */ |
| public static boolean isSameMethodSignature(String name, |
| String[] paramTypes, IMethod curr) { |
| if (name.equals(curr.getElementName())) { |
| String[] currParamTypes = curr.getParameterTypes(); |
| if (paramTypes.length == currParamTypes.length) { |
| for (int i = 0; i < paramTypes.length; i++) { |
| String t1 = Signature.getSimpleName(Signature |
| .toString(paramTypes[i])); |
| String t2 = Signature.getSimpleName(Signature |
| .toString(currParamTypes[i])); |
| if (!t1.equals(t2)) { |
| return false; |
| } |
| } |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| /** |
| * get methods for the class Type including its super class |
| * |
| * @param classType |
| * @return - can be null |
| * @throws JavaModelException |
| */ |
| public static IMethod[] getMethods(IType classType) |
| throws JavaModelException { |
| if (classType == null) { |
| return null; |
| } |
| List methodList = new ArrayList(); |
| IMethod[] methods = classType.getMethods(); |
| copyToMethodList(methodList, methods); |
| |
| ITypeHierarchy typeHierarchy = classType.newSupertypeHierarchy(null); |
| |
| if (typeHierarchy != null) { |
| IType[] superTypes = typeHierarchy.getAllSuperclasses(classType); |
| |
| if (superTypes != null && superTypes.length > 0) { |
| for (int i = 0; i < superTypes.length; i++) { |
| if (!superTypes[i].getFullyQualifiedName().equals( |
| "java.lang.Object")) { //$NON-NLS-1$ |
| methods = superTypes[i].getMethods(); |
| |
| copyToMethodList(methodList, methods); |
| } |
| } |
| } |
| } |
| |
| if (methodList != null && methodList.size() > 0) { |
| IMethod[] validMethods = (IMethod[]) methodList |
| .toArray(new IMethod[methodList.size()]); |
| |
| Arrays.sort(validMethods, new Comparator() { |
| public int compare(Object o1, Object o2) { |
| String name1 = ((IMethod) o1).getElementName(); |
| String name2 = ((IMethod) o2).getElementName(); |
| return name1.compareTo(name2); |
| } |
| }); |
| return validMethods; |
| } |
| return null; |
| } |
| |
| /** |
| * resolve and get the qualified name for the incomplete typename |
| * |
| * @param classType |
| * @param signatureName |
| * @return - at least equal to Signature.toString(signatureName). |
| */ |
| public static String getQualifiedTypeNameInTypeHierarchy(IType classType, |
| String signatureName) { |
| int arrayNum = 0; |
| while (signatureName.startsWith("[")) { //$NON-NLS-1$ |
| arrayNum++; |
| signatureName = signatureName.substring(1); |
| } |
| |
| String qualifiedTypeName = Signature.toString(signatureName); |
| int kind = Signature.getTypeSignatureKind(signatureName); |
| if (kind == Signature.BASE_TYPE_SIGNATURE |
| || signatureName.equals(Signature.SIG_VOID)) { |
| // Add back array identifiers |
| while (arrayNum > 0) { |
| qualifiedTypeName = qualifiedTypeName + "[]"; //$NON-NLS-1$ |
| arrayNum--; |
| } |
| return qualifiedTypeName; |
| } |
| |
| String typeName = Signature.toString(signatureName); |
| |
| String foundName = getQualifiedTypeName(classType, typeName); |
| // if found in current type |
| if (foundName != null) { |
| qualifiedTypeName = foundName; |
| } else // else found in the type hierachy. |
| { |
| ITypeHierarchy typeHierarchy = null; |
| try { |
| typeHierarchy = classType.newSupertypeHierarchy(null); |
| } catch (JavaModelException e) { |
| // Nothing to do. |
| } |
| if (typeHierarchy != null) { |
| IType[] superTypes = typeHierarchy.getAllSupertypes(classType); |
| |
| if (superTypes != null && superTypes.length > 0) { |
| for (int i = 0; i < superTypes.length; i++) { |
| if (!superTypes[i].getFullyQualifiedName().equals( |
| "java.lang.Object")) { //$NON-NLS-1$ |
| foundName = getQualifiedTypeName(superTypes[i], |
| typeName); |
| if (foundName != null) { |
| qualifiedTypeName = foundName; |
| break; |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| // Add back array identifiers |
| while (arrayNum > 0) { |
| qualifiedTypeName = qualifiedTypeName + "[]"; //$NON-NLS-1$ |
| arrayNum--; |
| } |
| return qualifiedTypeName; |
| } |
| |
| /** |
| * resolve and get the qualified name for the incomplete typename |
| * |
| * @param classType |
| * @param typeName |
| * @return can be null. |
| */ |
| public static String getQualifiedTypeName(IType classType, String typeName) { |
| String qualifiedTypeName = null; |
| |
| try { |
| String[][] resolvedNames = classType.resolveType(typeName); |
| if (resolvedNames != null && resolvedNames.length > 0) { |
| qualifiedTypeName = JavaModelUtil.concatenateName( |
| resolvedNames[0][0], resolvedNames[0][1]); |
| } |
| } catch (JavaModelException e1) { |
| // Nothing to do. |
| } |
| |
| return qualifiedTypeName; |
| } |
| |
| /** |
| * check whether subclass is sub class of supperclass |
| * |
| * @param jProject |
| * @param subClass - |
| * fully qualified name of sub class |
| * @param superClass - |
| * fully qualified name of super class |
| * |
| * @return true if subClass is a sub of superClass |
| */ |
| public static boolean isSubClassOf(IJavaProject jProject, String subClass, |
| String superClass) { |
| if (jProject == null || subClass == null || superClass == null) { |
| return false; |
| } |
| |
| try { |
| IType subClassType = jProject.findType(subClass); |
| |
| if (subClassType != null) { |
| ITypeHierarchy typeHierarchy = null; |
| try { |
| typeHierarchy = subClassType.newSupertypeHierarchy(null); |
| } catch (JavaModelException e) { |
| // Nothing to do. |
| } |
| IType[] superTypes = typeHierarchy |
| .getAllSupertypes(subClassType); |
| |
| if (superTypes != null && superTypes.length > 0) { |
| for (int i = 0; i < superTypes.length; i++) { |
| if (superTypes[i].getFullyQualifiedName().equals( |
| superClass)) { |
| return true; |
| } |
| } |
| } |
| } |
| } catch (JavaModelException e) { |
| // Nothing to do. |
| } |
| return false; |
| } |
| } |