/******************************************************************************* * Copyright (c) 2000, 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.rubypeople.rdt.internal.ui.commands; import org.eclipse.core.commands.AbstractParameterValueConverter; import org.eclipse.core.commands.ParameterValueConversionException; import org.eclipse.core.resources.ResourcesPlugin; import org.rubypeople.rdt.core.IField; import org.rubypeople.rdt.core.IMethod; import org.rubypeople.rdt.core.IRubyElement; import org.rubypeople.rdt.core.IRubyModel; import org.rubypeople.rdt.core.IRubyProject; import org.rubypeople.rdt.core.IType; import org.rubypeople.rdt.core.RubyCore; import org.rubypeople.rdt.core.RubyModelException; /** * A command parameter value converter to convert between Ruby elements and * String references that identify them. * <p> * References can be made to Ruby 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.jdt.core.Signature Signature} class. * </p> * * @since 3.2 */ public class RubyElementReferenceConverter extends AbstractParameterValueConverter { private static final char PROJECT_END_CHAR= '/'; private static final char TYPE_END_CHAR= '#'; 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); IRubyModel javaModel= RubyCore.create(ResourcesPlugin.getWorkspace().getRoot()); assertExists(javaModel); IRubyProject javaProject= javaModel.getRubyProject(projectName); assertExists(javaProject); final int typeEndPosition= javaElementRef.indexOf(TYPE_END_CHAR); String typeName; if (typeEndPosition == -1) { typeName= javaElementRef; } else { typeName= javaElementRef.substring(0, typeEndPosition); } IType type= null; try { type= javaProject.findType(typeName); } catch (RubyModelException 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); if (field != null && field.exists()){ // 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); IMethod method= type.getMethod(memberRef, 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(IRubyElement javaElement) throws ParameterValueConversionException { if ((javaElement == null) || (!javaElement.exists())) { throw new ParameterValueConversionException("parameterValue must reference an existing IRubyElement"); //$NON-NLS-1$ } } public String convertToString(Object parameterValue) throws ParameterValueConversionException { if (!(parameterValue instanceof IRubyElement)) { throw new ParameterValueConversionException("parameterValue must be an IRubyElement"); //$NON-NLS-1$ } IRubyElement javaElement= (IRubyElement) parameterValue; IRubyProject javaProject= javaElement.getRubyProject(); if (javaProject == null) { throw new ParameterValueConversionException("Could not get IRubyProject for element"); //$NON-NLS-1$ } StringBuffer buffer; if (javaElement instanceof IType) { IType type= (IType) javaElement; buffer= composeTypeReference(type); } else if (javaElement instanceof IMethod) { IMethod method= (IMethod) 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 IRubyElement type"); //$NON-NLS-1$ } return buffer.toString(); } private StringBuffer composeTypeReference(IType type) { StringBuffer buffer= new StringBuffer(); buffer.append(type.getRubyProject().getElementName()); buffer.append(PROJECT_END_CHAR); buffer.append(type.getFullyQualifiedName()); return buffer; } }