/******************************************************************************* * Copyright (c) 2000, 2008 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.wst.jsdt.internal.ui.commands; import org.eclipse.core.commands.AbstractParameterValueConverter; import org.eclipse.core.commands.ParameterValueConversionException; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.wst.jsdt.core.IField; import org.eclipse.wst.jsdt.core.IJavaScriptElement; import org.eclipse.wst.jsdt.core.IJavaScriptModel; import org.eclipse.wst.jsdt.core.IJavaScriptProject; import org.eclipse.wst.jsdt.core.IFunction; import org.eclipse.wst.jsdt.core.IType; import org.eclipse.wst.jsdt.core.ITypeRoot; import org.eclipse.wst.jsdt.core.JavaScriptCore; import org.eclipse.wst.jsdt.core.JavaScriptModelException; import org.eclipse.wst.jsdt.core.Signature; import org.eclipse.wst.jsdt.internal.core.util.Util; /** * A command parameter value converter to convert between Java elements and * String references that identify them. * <p> * References can be made to Java types, methods and fields. The reference * identifies the project to use as a search scope as well as the java element * information. Note that non-source elements may be referenced (such as * java.lang.Object), but they must be resolved within the scope of some * project. * </p> * <p> * References take the form: * * <pre> * elementRef := typeRef | fieldRef | methodRef * typeRef := projectName '/' fullyQualifiedTypeName * fieldRef := typeRef '#' fieldName * methodRef := typeRef '#' methodName '(' parameterSignatures ')' * </pre> * * where <code>parameterSignatures</code> uses the signature format documented * in the {@link org.eclipse.wst.jsdt.core.Signature Signature} class. * </p> * * */ public class JavaElementReferenceConverter extends AbstractParameterValueConverter { private static final char PROJECT_END_CHAR= '/'; private static final char TYPE_END_CHAR= '#'; private static final char PARAM_START_CHAR= Signature.C_PARAM_START; private static final char PARAM_END_CHAR= Signature.C_PARAM_END; public Object convertToObject(String parameterValue) throws ParameterValueConversionException { assertWellFormed(parameterValue != null); final int projectEndPosition= parameterValue.indexOf(PROJECT_END_CHAR); assertWellFormed(projectEndPosition != -1); String projectName= parameterValue.substring(0, projectEndPosition); String javaElementRef= parameterValue.substring(projectEndPosition + 1); IJavaScriptModel javaModel= JavaScriptCore.create(ResourcesPlugin.getWorkspace().getRoot()); assertExists(javaModel); IJavaScriptProject javaProject= javaModel.getJavaScriptProject(projectName); assertExists(javaProject); final int typeEndPosition= javaElementRef.indexOf(TYPE_END_CHAR); String typeName; if (typeEndPosition == -1) { typeName= javaElementRef; } else { typeName= javaElementRef.substring(0, typeEndPosition); } if (Util.isJavaLikeFileName(typeName)) { ITypeRoot typeRoot=null; try { typeRoot=javaProject.findTypeRoot(typeName); } catch (JavaScriptModelException e) { } assertExists(typeRoot); if (typeEndPosition == -1) { return typeRoot; } String memberRef= javaElementRef.substring(typeEndPosition + 1); final int paramStartPosition= memberRef.indexOf(PARAM_START_CHAR); if (paramStartPosition == -1) { IField field= typeRoot.getField(memberRef); assertExists(field); return field; } String methodName= memberRef.substring(0, paramStartPosition); String signature= memberRef.substring(paramStartPosition); String[] parameterTypes= null; try { parameterTypes= Signature.getParameterTypes(signature); } catch (IllegalArgumentException ex) { // parameterTypes == null } assertWellFormed(parameterTypes != null); IFunction method= typeRoot.getFunction(methodName, parameterTypes); assertExists(method); return method; } IType type= null; try { type= javaProject.findType(typeName); } catch (JavaScriptModelException ex) { // type == null } assertExists(type); if (typeEndPosition == -1) { return type; } String memberRef= javaElementRef.substring(typeEndPosition + 1); final int paramStartPosition= memberRef.indexOf(PARAM_START_CHAR); if (paramStartPosition == -1) { IField field= type.getField(memberRef); assertExists(field); return field; } String methodName= memberRef.substring(0, paramStartPosition); String signature= memberRef.substring(paramStartPosition); String[] parameterTypes= null; try { parameterTypes= Signature.getParameterTypes(signature); } catch (IllegalArgumentException ex) { // parameterTypes == null } assertWellFormed(parameterTypes != null); IFunction method= type.getFunction(methodName, parameterTypes); assertExists(method); return method; } /** * Throws a <code>ParameterValueConversionException</code> if the java * element reference string does not meet some well-formedness condition. * * @param assertion * a boolean check for well-formedness * @throws ParameterValueConversionException */ private void assertWellFormed(boolean assertion) throws ParameterValueConversionException { if (!assertion) { throw new ParameterValueConversionException("Malformed parameterValue"); //$NON-NLS-1$ } } /** * Throws a <code>ParameterValueConversionException</code> if the java * element reference string identifies an element that does not exist. * * @param javaElement * an element to check for existence * @throws ParameterValueConversionException */ private void assertExists(IJavaScriptElement javaElement) throws ParameterValueConversionException { if ((javaElement == null) || (!javaElement.exists())) { throw new ParameterValueConversionException("parameterValue must reference an existing IJavaScriptElement"); //$NON-NLS-1$ } } public String convertToString(Object parameterValue) throws ParameterValueConversionException { if (!(parameterValue instanceof IJavaScriptElement)) { throw new ParameterValueConversionException("parameterValue must be an IJavaScriptElement"); //$NON-NLS-1$ } IJavaScriptElement javaElement= (IJavaScriptElement) parameterValue; IJavaScriptProject javaProject= javaElement.getJavaScriptProject(); if (javaProject == null) { throw new ParameterValueConversionException("Could not get IJavaScriptProject for element"); //$NON-NLS-1$ } StringBuffer buffer; if (javaElement instanceof IType) { IType type= (IType) javaElement; buffer= composeTypeReference(type); } else if (javaElement instanceof IFunction) { IFunction method= (IFunction) javaElement; buffer= composeTypeReference(method.getDeclaringType()); buffer.append(TYPE_END_CHAR); buffer.append(method.getElementName()); String[] parameterTypes= method.getParameterTypes(); buffer.append(PARAM_START_CHAR); for (int i= 0; i < parameterTypes.length; i++) { buffer.append(parameterTypes[i]); } buffer.append(PARAM_END_CHAR); } else if (javaElement instanceof IField) { IField field= (IField) javaElement; buffer= composeTypeReference(field.getDeclaringType()); buffer.append(TYPE_END_CHAR); buffer.append(field.getElementName()); } else { throw new ParameterValueConversionException("Unsupported IJavaScriptElement type"); //$NON-NLS-1$ } return buffer.toString(); } private StringBuffer composeTypeReference(IType type) { StringBuffer buffer= new StringBuffer(); buffer.append(type.getJavaScriptProject().getElementName()); buffer.append(PROJECT_END_CHAR); buffer.append(type.getFullyQualifiedName()); return buffer; } }