/*******************************************************************************
* Copyright (c) 2012 VMware, Inc.
* 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:
* VMware, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.eclipse.quickfix.proposals;
import java.lang.reflect.InvocationTargetException;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.internal.ui.JavaPluginImages;
import org.eclipse.jdt.ui.refactoring.RenameSupport;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
import org.eclipse.jface.text.link.ILinkedModeListener;
import org.eclipse.jface.text.link.LinkedModeModel;
import org.eclipse.jface.text.link.LinkedModeUI;
import org.eclipse.jface.text.link.LinkedPosition;
import org.eclipse.jface.text.link.LinkedPositionGroup;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.ide.IDE;
import org.eclipse.ui.part.EditorPart;
import org.eclipse.wst.sse.ui.StructuredTextEditor;
import org.eclipse.wst.xml.ui.internal.tabletree.XMLMultiPageEditorPart;
import org.springframework.ide.eclipse.config.core.IConfigEditor;
import org.springframework.ide.eclipse.core.java.Introspector;
import org.springframework.ide.eclipse.core.java.JdtUtils;
import org.springframework.ide.eclipse.core.java.Introspector.Public;
import org.springframework.ide.eclipse.core.java.Introspector.Static;
import org.springframework.util.StringUtils;
/**
* @author Terry Denney
* @author Christian Dupuis
*/
public class RenamePropertyQuickfixProposal extends BeanAttributeQuickFixProposal implements ICompletionProposal {
private final String className;
private final String existingPropertyName;
private final IFile beanFile;
private final IProject project;
private IEditorPart editor;
public RenamePropertyQuickfixProposal(int offset, int length, String text, String className,
boolean missingEndQuote, IFile beanFile, IProject project) {
super(offset, length, missingEndQuote);
this.className = className;
this.beanFile = beanFile;
this.existingPropertyName = text;
this.project = project;
}
@Override
public void applyQuickFix(final IDocument document) {
final LinkedPosition position = new LinkedPosition(document, getOffset(), getLength());
LinkedPositionGroup group = new LinkedPositionGroup();
LinkedModeModel model = new LinkedModeModel();
try {
group.addPosition(position);
model.addGroup(group);
model.forceInstall();
ITextViewer viewer = getViewer(document);
if (viewer == null) {
return;
}
Point originalSelection = viewer.getSelectedRange();
LinkedModeUI ui = new LinkedModeUI(model, viewer);
ui.setExitPosition(viewer, getOffset(), 0, Integer.MAX_VALUE);
model.addLinkingListener(new ILinkedModeListener() {
public void left(LinkedModeModel model, int flags) {
if ((flags & ILinkedModeListener.UPDATE_CARET) > 0) {
try {
String newName = position.getContent();
Shell shell = PlatformUI.getWorkbench().getDisplay().getActiveShell();
doRename(newName, shell);
}
catch (BadLocationException e) {
}
}
}
public void resume(LinkedModeModel model, int flags) {
}
public void suspend(LinkedModeModel model) {
}
});
ui.enter();
viewer.setSelectedRange(originalSelection.x, originalSelection.y);
}
catch (BadLocationException e) {
}
}
private String convertToMethodName(String property) {
return "set" + StringUtils.capitalize(property);
}
// public for testing
public void doRename(String newPropertyName, Shell shell) {
String newName = convertToMethodName(newPropertyName);
try {
IType type = JdtUtils.getJavaType(project, className);
if (type != null) {
IMethod method = Introspector.findMethod(type, convertToMethodName(existingPropertyName), 1,
Public.DONT_CARE, Static.DONT_CARE);
if (method != null) {
RenameSupport renameSupport = RenameSupport
.create(method, newName, RenameSupport.UPDATE_REFERENCES);
renameSupport.perform(shell, PlatformUI.getWorkbench().getActiveWorkbenchWindow());
if (editor instanceof EditorPart) {
((EditorPart) editor).doSave(new NullProgressMonitor());
}
}
}
}
catch (JavaModelException e) {
}
catch (CoreException e) {
}
catch (InterruptedException e) {
}
catch (InvocationTargetException e) {
}
}
public String getDisplayString() {
return "Rename property in file";
}
public Image getImage() {
return JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_LINKED_RENAME);
}
private ITextViewer getViewer(IDocument document) {
try {
if (editor == null) {
editor = IDE.openEditor(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(), beanFile);
}
return getViewer(editor);
}
catch (PartInitException e) {
}
return null;
}
private ITextViewer getViewer(IEditorPart editorPart) {
if (editorPart instanceof IConfigEditor) {
IConfigEditor configEditor = (IConfigEditor) editorPart;
return configEditor.getTextViewer();
}
if (editorPart instanceof StructuredTextEditor) {
return ((StructuredTextEditor) editorPart).getTextViewer();
}
if (editorPart instanceof XMLMultiPageEditorPart) {
Object result = QuickfixReflectionUtils.callProtectedMethod(editorPart, "getTextEditor");
return getViewer((IEditorPart) result);
}
return null;
}
}