Skip to main content
summaryrefslogblamecommitdiffstats
blob: 7f75aa9ef505b5fc7853444367c2fc19777c77f7 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
                                                                                
                                                       
                                                                   
                                                                        
                                                           
                                            
  


                                                                                 
                                               

                                       
                                                   







                                      
 








































































































































































































































































                                                                                                                                                                                                    
                                                                           













































                                                                                                                                                                                                   















                                                                                                                                      








                                                                                                                                                                                                   
                                                  
                                                                                                              
                         
                                                  
                                                                                                                                                                                                                                         




                            
/*******************************************************************************
 * Copyright (c) 2001, 2006 IBM Corporation 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:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.jem.internal.adapters.jdom;
/*
 *  $RCSfile: JDOMSearchHelper.java,v $
 *  $Revision: 1.8 $  $Date: 2006/05/17 20:13:58 $ 
 */

import java.io.File;
import java.util.*;

import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.jdt.core.*;

import org.eclipse.jem.internal.java.adapters.nls.ResourceHandler;
/**
 * Insert the type's description here.
 * Creation date: (9/26/2001 11:09:30 AM)
 * @author: Administrator
 */
public class JDOMSearchHelper {
	
	private static final String RESOLVED_NAME = " :: RESOLVED_NAME :: "; //$NON-NLS-1$
	private static final String PERIOD = "."; //$NON-NLS-1$
	private static final String BOOLEAN = "boolean"; //$NON-NLS-1$
	private static final String BYTE = "byte"; //$NON-NLS-1$
	private static final String CHAR = "char"; //$NON-NLS-1$
	private static final String SHORT = "short"; //$NON-NLS-1$
	private static final String INT = "int"; //$NON-NLS-1$
	private static final String LONG = "long"; //$NON-NLS-1$
	private static final String FLOAT = "float"; //$NON-NLS-1$
	private static final String DOUBLE = "double"; //$NON-NLS-1$
	private static final String VOID = "void"; //$NON-NLS-1$
	/**
	 * JDOMSearchHelper constructor comment.
	 */
	public JDOMSearchHelper() {
		super();
	}
	/**
	 * If the @simpleName is an inner class, we need to resolve only the declaring class.
	 */
	private static String[][] getTypeNameInfo(IType type, String simpleName, boolean isForReflection) throws JavaModelException {
		String[][] result = null;
		String declaringName, typeName;
		typeName = simpleName;
		if (type != null) {
			if (isForReflection)
				typeName = typeName.replace('.', '$');
			int index = typeName.indexOf("$"); //$NON-NLS-1$
			if (index > 0) {
				declaringName = typeName.substring(0, index);
				result = type.resolveType(declaringName);
				if (result != null) {
					if (isForReflection)
						result[0][1] = result[0][1].replace('.', '$');
					result[0][1] += typeName.substring(index, typeName.length());
				}
			} else {
				index = typeName.indexOf("["); //$NON-NLS-1$
				if (index > 0) {
					declaringName = typeName.substring(0, index);
					result = type.resolveType(declaringName);
					if (result != null)
						result[0][1] = result[0][1] + typeName.substring(index);
				} else
					result = type.resolveType(typeName);
			}
		}
		return result;
	}
	/**
	 * Returns true if the type is a primitive.
	 */
	public final static boolean isPrimitive(String type) {
		return (BOOLEAN.equals(type) || INT.equals(type) || CHAR.equals(type) || SHORT.equals(type) || LONG.equals(type) || FLOAT.equals(type) || DOUBLE.equals(type) || BYTE.equals(type));
	}
	/**
	 * Returns true if the type is a primitive.
	 */
	public final static boolean isPrimitiveOrVoid(String type) {
		return isPrimitive(type) || isVoid(type);
	}
	/**
	 * Returns true if the type is a primitive.
	 */
	public final static boolean isVoid(String type) {
		return VOID.equals(type);
	}
	/**
	 * Returns true if the two signatures match within the scope of the specified type.
	 */
	public static boolean matchTypeSignatures(IType type, String signature1, String signature2) throws JavaModelException {
		return matchTypeSignatures(type, signature1, signature2, null);
	}
	/**
	 * Returns true if the two signatures match within the scope of the specified type.
	 */
	public static boolean matchTypeSignatures(IType type, String signature1, String signature2, Map resolvedNameCache) throws JavaModelException {
		boolean result = false;
		String sig1 = signature1;
		String sig2 = signature2;
		// First check array count.
		if (Signature.getArrayCount(sig1) == Signature.getArrayCount(sig2)) {
			// We have the same array count, get the element types for consideration.
			sig1 = Signature.getElementType(sig1);
			sig2 = Signature.getElementType(sig2);

			// There are three cases:
			//		1) Both are unqualified (both being primitive will fall into this),
			//		2) Both are qualified, and
			//		3) One is qualified and the other is not (one could be primitive).

			// For the first two cases a compare of the readable names will always do.
			if (!((sig1.indexOf('.') == -1) ^ (sig2.indexOf('.') == -1))) {
				result = Signature.toString(sig1).equals(Signature.toString(sig2));
			} else {
				// This is case 3.
				// First root out one being primitive.
				if (((sig1.charAt(0) == 'Q') || (sig1.charAt(0) == 'L')) && ((sig2.charAt(0) == 'Q') || (sig2.charAt(0) == 'L'))) {
					// Get the readable name of the qualified signature
					// and the simple name of the other.
					String qualifiedName = null;
					String simpleName = null;
					if (sig1.indexOf('.') == -1) {
						qualifiedName = Signature.toString(sig2);
						simpleName = Signature.toString(sig1);
					} else {
						qualifiedName = Signature.toString(sig1);
						simpleName = Signature.toString(sig2);
					}

					// If the simple name resolves to the qualified name, we have a match.
					result = qualifiedName.equals(resolveSimpleTypeName(type, simpleName, resolvedNameCache));
				}
			}
		}

		return result;
	}
	private static boolean needsToResolveName(IType type, String simpleName, boolean isForReflection) {
		return !(type.isBinary() || (!isForReflection && simpleName.indexOf(PERIOD) > -1) || isPrimitiveOrVoid(simpleName));
	}
	/**
	 * Returns the qualified name for the simple name within the scope of the type.
	 * Returns null if the name can not be resolved.
	 */
	public static String resolveSimpleTypeName(IType type, String simpleName) throws JavaModelException {
		return resolveSimpleTypeName(type, simpleName, null);
	}
	/**
	 * Returns the qualified name for the simple name within the scope of the type.
	 * Returns null if the name can not be resolved.
	 */
	public static String resolveSimpleTypeName(IType type, String simpleName, Map resolvedNameCache) throws JavaModelException {
		return resolveSimpleTypeName(type, simpleName, resolvedNameCache, false);
	}

	/**
	 * Returns the qualified name for the simple name within the scope of the type.
	 * Returns null if the name can not be resolved.
	 */
	public static String resolveSimpleTypeName(IType type, String simpleName, Map resolvedNameCache, boolean isForReflection) throws JavaModelException {
		if (!needsToResolveName(type, simpleName, isForReflection))
			return simpleName;
		String key = null, qualifiedName = null;
		if (resolvedNameCache != null) {
			key = type.getFullyQualifiedName() + RESOLVED_NAME + simpleName;
			qualifiedName = (String) resolvedNameCache.get(key);
		}
		if (qualifiedName == null) {
			String[][] result = getTypeNameInfo(type, simpleName, isForReflection);
			if (result != null) {
				String packName = result[0][0];
				if (packName.length() == 0) {
					qualifiedName = result[0][1];
					if (isForReflection)
						qualifiedName = qualifiedName.replace('.', '$');					
				} else {
					StringBuffer b = new StringBuffer();
					b.append(result[0][0]).append(PERIOD);
					String typeName = result[0][1];
					if (isForReflection)
						typeName = typeName.replace('.', '$');
					b.append(typeName);
					qualifiedName = b.toString();
				}
			} else {
				qualifiedName = simpleName;
			}
			if (resolvedNameCache != null)
				resolvedNameCache.put(key, qualifiedName);
		}
		return qualifiedName;
	}
	/**
	 * Searches for a matching method and sets it in the
	 * descriptor if found.
	 */
	public static IMethod searchForMatchingMethod(IType type, String methodName, String[] parmSigs) throws JavaModelException {
		return searchForMatchingMethod(type, methodName, parmSigs, null);
	}
	/**
	 * Searches for a matching method and sets it in the
	 * descriptor if found.
	 */
	public static IMethod searchForMatchingMethod(IType type, String methodName, String[] parmSigs, Map resolvedNameCache) throws JavaModelException {

		// First get all the methods by this name and with this many parms.
		IMethod[] allMethods = type.getMethods();
		List candidateMethods = new ArrayList();
		for (int i = 0; i < allMethods.length; i++) {
			int parmSigsLength = (parmSigs != null ? parmSigs.length : 0);
			if ((allMethods[i].getElementName().equals(methodName)) && (allMethods[i].getNumberOfParameters() == parmSigsLength))
				candidateMethods.add(allMethods[i]);
		}

		// For each candidate consider each parm for a match.
		// Take the first one that matches on all parms.
		IMethod next = null;
		String[] nextParmSigs = null;
		boolean found = false;
		Iterator candidateIter = candidateMethods.iterator();
		while (!found && (candidateIter.hasNext())) {
			next = (IMethod) candidateIter.next();
			nextParmSigs = next.getParameterTypes();
			found = true;
			for (int i = 0;(found && (i < nextParmSigs.length)); i++)
				found &= matchTypeSignatures(type, parmSigs[i], nextParmSigs[i], resolvedNameCache);
		}
		return found ? next : null;
	}

	/**
	* The returned Object[] will contain two entries.  The
	* first will be the IJavaElement that was found and the
	* second will be the qualifiedName used to find it.
	*/
	protected static Object[] findActualJavaElement(String qualifiedName, IJavaProject javaProject, JDOMAdaptor adaptor) {
		Object[] result = new Object[2];
		if (adaptor == null)
			result[1] = qualifiedName;
		else 
			//Ensure the name is qualified
			result[1] = getResolvedTypeName(qualifiedName, adaptor.getType(), adaptor.getTypeResolutionCache());
		
		result[0] = findJavaElement((String) result[1], javaProject, adaptor);
		if (result[0] == null)
			findInnerJavaElement(result, javaProject, adaptor);
		return result;
	}

	/**
	 * The returned Object[] will contain two entries.  The
	 * first will be the IJavaElement that was found and the
	 * second will be the qualifiedName used to find it.
	 */
	protected static void findInnerJavaElement(Object[] info, IJavaProject javaProject, JDOMAdaptor adaptor) {
		String qualifiedName, innerName;
		qualifiedName = (String) info[1];
		int index = qualifiedName.lastIndexOf("."); //$NON-NLS-1$
		if (index > 0) {
			innerName = qualifiedName.substring(0, index);
			innerName += "$"; //$NON-NLS-1$
			innerName += qualifiedName.substring(index + 1, qualifiedName.length());
			if (adaptor != null) {
				//Ensure the name is qualified which it may not be if an inner class
				innerName = getResolvedTypeName(innerName, adaptor.getType(), adaptor.getTypeResolutionCache());
			}
			info[1] = innerName;
			info[0] = findJavaElement(innerName, javaProject, adaptor);
			if (info[0] == null)
				findInnerJavaElement(info, javaProject, adaptor);
		}
	}

	protected static IJavaElement findJavaElement(String qualifiedName, IJavaProject javaProject, JDOMAdaptor adaptor) {
		try {
			if (javaProject != null) {
				return javaProject.findType(qualifiedName);
			}
		} catch (JavaModelException jme) {
			System.out.println(ResourceHandler.getString("Error_Looking_Up_Type_ERROR_", (new Object[] { qualifiedName, jme.getMessage()}))); //$NON-NLS-1$ = "Error looking up type: "
		}
		return null;
	}
	
	protected static IPath getPathFromQualifiedName(String qualifiedName) {
		return new Path(qualifiedName.replace('.', File.separatorChar) + ".java"); //$NON-NLS-1$
	}
	/* 
	* Resolve a type name in the context of a Type.
	* (Borrowed from org.eclipse.jdt.ui.codemanipulation.StubUtility.getResolvedTypeName())
	* The input is a simple or qualified name, NOT a signature
	* The output will be a qualified name, NOT a signature
	*/
	public static String getResolvedTypeName(String typeName, IType declaringType, Map typeCache) {
		String name = typeName;
		try {
			name = JDOMSearchHelper.resolveSimpleTypeName(declaringType, typeName, typeCache, true);
		} catch (JavaModelException e) {
			// ignore
		}
		return name;
	}

	public static IType findType(String qualifiedName, boolean useAdvancedForInners, IJavaProject javaProject, JDOMAdaptor adaptor) {
		try {
			IJavaElement found = null;
			String resolvedName = qualifiedName;
			if (useAdvancedForInners) {
				Object[] result = findActualJavaElement(qualifiedName, javaProject, adaptor);
				found = (IJavaElement) result[0];
				resolvedName = (String) result[1];
			} else
				found = findJavaElement(qualifiedName, javaProject, adaptor);
			if (found != null)
				if (found instanceof IClassFile)
					return ((IClassFile) found).getType();
				else if (found instanceof ICompilationUnit) {
					ICompilationUnit foundCU = (ICompilationUnit) found;
					// strip the ".java", lifted from CompilationUnit.getMainTypeName()
					String cuMainTypeName = foundCU.getElementName();
					cuMainTypeName = cuMainTypeName.substring(0, cuMainTypeName.length() - 5);
					return foundCU.getType(cuMainTypeName);
				} else if (found instanceof IType) {
					IType type = ((IType) found);
					if (!type.getFullyQualifiedName('$').equals(resolvedName)) {
						// I don't know why this is here. Sometime in the past for an inner class, the
						// IType returned was for the outer class, so you would need to search again
						// for the inner class against the outer class. I don't know how this now can
						// happen. The code followed above is extremelly complicated, especially when
						// it is an inner class that isn't fully-qualified that is inside a source file.
						// It goes through some gyrations for that. I don't know what it would
						// return in that case. But just in case, the test is here to be safe.
						int index = resolvedName.lastIndexOf('$'); //$NON-NLS-1$
						if (index > -1)
							return type.getType(resolvedName.substring(index + 1, resolvedName.length()));
						else
							return type;
					} else
						return type;
				}
		} catch (JavaModelException jme) {
			System.out.println(ResourceHandler.getString("Error_Looking_Up_Type_ERROR_", (new Object[] { qualifiedName, jme.getMessage()}))); //$NON-NLS-1$ = "Error looking up type: "
		}
		return null;
	}
	
	public static IType findType(String packageName, String qualifiedTypeName, IJavaProject javaProject) {
		try {
			if (javaProject != null) {
				return javaProject.findType(packageName, qualifiedTypeName.replace('$', '.'));
			}
		} catch (JavaModelException jme) {
			System.out.println(ResourceHandler.getString("Error_Looking_Up_Type_ERROR_", (new Object[] { packageName + "." + qualifiedTypeName, jme.getMessage()}))); //$NON-NLS-1$ //$NON-NLS-2$ = "Error looking up type: "
		}
		return null;
	}

}

Back to the top