/** * Copyright (C) 2005 - 2012 Eric Van Dewoestine * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.eclim.plugin.jdt.command.impl; import java.util.ArrayList; import java.util.List; import java.util.Set; import org.apache.commons.lang.StringUtils; import org.eclim.Services; import org.eclim.annotation.Command; import org.eclim.command.CommandLine; import org.eclim.command.Options; import org.eclim.plugin.jdt.command.impl.ImplCommand; import org.eclim.plugin.jdt.util.JavaUtils; import org.eclim.plugin.jdt.util.TypeUtils; import org.eclipse.core.resources.IWorkspaceRunnable; import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.core.IField; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.IType; import org.eclipse.jdt.core.Signature; import org.eclipse.jdt.core.dom.CompilationUnit; import org.eclipse.jdt.core.dom.IMethodBinding; import org.eclipse.jdt.core.dom.ITypeBinding; import org.eclipse.jdt.core.dom.IVariableBinding; import org.eclipse.jdt.internal.corext.codemanipulation.AddDelegateMethodsOperation; import org.eclipse.jdt.internal.corext.codemanipulation.AddDelegateMethodsOperation.DelegateEntry; import org.eclipse.jdt.internal.corext.codemanipulation.CodeGenerationSettings; import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility2; import org.eclipse.jdt.internal.corext.dom.ASTNodes; import org.eclipse.jdt.internal.corext.refactoring.structure.ASTNodeSearchUtil; import org.eclipse.jdt.internal.corext.refactoring.util.RefactoringASTParser; import org.eclipse.jdt.internal.ui.javaeditor.ASTProvider; import org.eclipse.jdt.internal.ui.preferences.JavaPreferencesSettings; /** * Command to handle creation of delegate methods. * * @author Eric Van Dewoestine */ @Command( name = "java_delegate", options = "REQUIRED p project ARG," + "REQUIRED f file ARG," + "OPTIONAL o offset ARG," + "OPTIONAL e encoding ARG," + "OPTIONAL v variable ARG," + "OPTIONAL s superType ARG," + "OPTIONAL m methods ARG" ) public class DelegateCommand extends ImplCommand { private ThreadLocal<IField> field = new ThreadLocal<IField>(); @Override public Object execute(CommandLine commandLine) throws Exception { String project = commandLine.getValue(Options.PROJECT_OPTION); String file = commandLine.getValue(Options.FILE_OPTION); ICompilationUnit src = JavaUtils.getCompilationUnit(project, file); IJavaElement element = null; if (commandLine.hasOption(Options.VARIABLE_OPTION)){ String var = commandLine.getValue(Options.VARIABLE_OPTION); String[] parts = StringUtils.split(var, "."); String varName = parts[parts.length - 1]; IType type = getType(src, commandLine); element = type.getField(varName); }else{ element = src.getElementAt(getOffset(commandLine)); } if(element == null || element.getElementType() != IJavaElement.FIELD){ return Services.getMessage("not.a.field"); } IField field = (IField)element; String signature = field.getTypeSignature(); IType delegateType = TypeUtils.findUnqualifiedType( src, Signature.getSignatureSimpleName(signature)); if(delegateType == null){ return Services.getMessage("type.not.found", src.getJavaProject().getElementName(), Signature.getSignatureSimpleName(signature)) + " " + Services.getMessage("check.import"); } this.field.set(field); return super.execute(commandLine); } @Override protected IType getType(ICompilationUnit src, CommandLine commandLine) throws Exception { if (commandLine.hasOption(Options.VARIABLE_OPTION)){ String var = commandLine.getValue(Options.VARIABLE_OPTION); String[] parts = StringUtils.split(var, "."); String typeName = StringUtils.join(parts, '.', 0, parts.length - 1); return src.getJavaProject().findType(typeName.replace('$', '.')); } return super.getType(src, commandLine); } @Override protected IWorkspaceRunnable getImplOperation( ICompilationUnit src, IType type, Set<String> chosen, IJavaElement sibling, int pos, CommandLine commandLine) throws Exception { RefactoringASTParser parser = new RefactoringASTParser(ASTProvider.SHARED_AST_LEVEL); CompilationUnit cu = parser.parse(type.getCompilationUnit(), true); ITypeBinding typeBinding = ASTNodes.getTypeBinding(cu, type); String superType = commandLine.getValue(Options.SUPERTYPE_OPTION); List<DelegateEntry> delegatable = getDelegatableMethods(cu, typeBinding); List<DelegateEntry> delegate = new ArrayList<DelegateEntry>(); for (DelegateEntry entry : delegatable){ ITypeBinding declBinding = entry.delegateMethod.getDeclaringClass(); String fqn = declBinding.getQualifiedName().replaceAll("<.*?>", ""); if (fqn.equals(superType) && isChosen(chosen, entry.delegateMethod)){ delegate.add(entry); } } if (delegate.size() > 0){ CodeGenerationSettings settings = JavaPreferencesSettings.getCodeGenerationSettings(src.getJavaProject()); settings.createComments = true; return new AddDelegateMethodsOperation( cu, delegate.toArray(new DelegateEntry[delegate.size()]), sibling, settings, true, true); } return null; } @Override protected ImplResult getImplResult(ICompilationUnit src, IType type) throws Exception { List<DelegateEntry> delegatable = getDelegatableMethods(src, type); List<IMethodBinding> methods = new ArrayList<IMethodBinding>(delegatable.size()); for (DelegateEntry entry : delegatable){ methods.add(entry.delegateMethod); } String name = type.getFullyQualifiedName() + '.' + field.get().getElementName(); return getImplResult(name, methods); } private List<DelegateEntry> getDelegatableMethods( ICompilationUnit src, IType type) throws Exception { RefactoringASTParser parser = new RefactoringASTParser(ASTProvider.SHARED_AST_LEVEL); CompilationUnit cu = parser.parse(type.getCompilationUnit(), true); ITypeBinding typeBinding = ASTNodes.getTypeBinding(cu, type); return getDelegatableMethods(cu, typeBinding); } private List<DelegateEntry> getDelegatableMethods( CompilationUnit cu, ITypeBinding typeBinding) throws Exception { IVariableBinding variable = ASTNodeSearchUtil .getFieldDeclarationFragmentNode(field.get(), cu).resolveBinding(); DelegateEntry[] entries = StubUtility2.getDelegatableMethods(typeBinding); ArrayList<DelegateEntry> delegatable = new ArrayList<DelegateEntry>(); for (DelegateEntry entry : entries) { if (entry.field.equals(variable)){ delegatable.add(entry); } } return delegatable; } }