diff options
Diffstat (limited to 'web/bundles/org.eclipse.jst.jsp.ui/src/org/eclipse/jst/jsp/ui/internal/java/refactoring/JSPRenameParticipant.java')
-rw-r--r-- | web/bundles/org.eclipse.jst.jsp.ui/src/org/eclipse/jst/jsp/ui/internal/java/refactoring/JSPRenameParticipant.java | 245 |
1 files changed, 245 insertions, 0 deletions
diff --git a/web/bundles/org.eclipse.jst.jsp.ui/src/org/eclipse/jst/jsp/ui/internal/java/refactoring/JSPRenameParticipant.java b/web/bundles/org.eclipse.jst.jsp.ui/src/org/eclipse/jst/jsp/ui/internal/java/refactoring/JSPRenameParticipant.java new file mode 100644 index 0000000000..5bbf86f500 --- /dev/null +++ b/web/bundles/org.eclipse.jst.jsp.ui/src/org/eclipse/jst/jsp/ui/internal/java/refactoring/JSPRenameParticipant.java @@ -0,0 +1,245 @@ +/******************************************************************************* + * Copyright (c) 2009, 2011 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.jst.jsp.ui.internal.java.refactoring; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.jdt.core.IJavaElement; +import org.eclipse.jst.jsp.core.internal.java.search.JSPSearchScope; +import org.eclipse.jst.jsp.core.internal.java.search.JSPSearchSupport; +import org.eclipse.jst.jsp.ui.internal.JSPUIMessages; +import org.eclipse.ltk.core.refactoring.Change; +import org.eclipse.ltk.core.refactoring.CompositeChange; +import org.eclipse.ltk.core.refactoring.RefactoringStatus; +import org.eclipse.ltk.core.refactoring.TextChange; +import org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext; +import org.eclipse.ltk.core.refactoring.participants.ISharableParticipant; +import org.eclipse.ltk.core.refactoring.participants.RefactoringArguments; +import org.eclipse.ltk.core.refactoring.participants.RefactoringParticipant; +import org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor; +import org.eclipse.ltk.core.refactoring.participants.RenameArguments; +import org.eclipse.ltk.core.refactoring.participants.RenameParticipant; +import org.eclipse.text.edits.TextEdit; + +/** + * Abstract {@link ISharableParticipant} {@link RenameParticipant} for editing JSP documents + */ +public abstract class JSPRenameParticipant extends RenameParticipant implements ISharableParticipant { + /** + * The name of this participant. + * Should be initialized by implementers in {@link #initialize(Object)} + */ + protected String fName; + + /** + * A map of {@link IJavaElement} names to pairs of {@link IJavaElement}s + * and their associated {@link RenameArguments} that have been added to + * this {@link ISharableParticipant}. + * + * key: {@link String} - Element name<br/> + * value: {@link ElementAndArgumentsPair} + */ + private Map fElementAndArgumentPairs; + + /** + * When new changes are being safely created {@link #getTextChange(Object)} + * is called first to check for existing {@link TextChange}s, but those + * results do not usually include the changes that have been created thus far + * locally by this {@link RenameParticipant}. This is to keep track of those + * changes so the overridden version of {@link #getTextChange(Object)}s will take + * these local {@link TextChange}s into account. + */ + private Map fLocalTextChanges; + + /** + * Groups an {@link IJavaElement} with its associated {@link RenameArguments} + * that have been added to this {@link ISharableParticipant} + */ + private class ElementAndArgumentsPair { + protected IJavaElement fElement; + protected RenameArguments fArgs; + + public ElementAndArgumentsPair(IJavaElement element, RenameArguments args) { + this.fElement = element; + this.fArgs = args; + } + } + + /** + * <p>Do local initialization. This is done here instead of in an implementation of + * {@link RefactoringParticipant#initialize(java.lang.Object)} because implementers + * of this class are not expected to have to call super when they implement + * {@link RefactoringParticipant#initialize(java.lang.Object)}</p> + * + * + * @see org.eclipse.ltk.core.refactoring.participants.RefactoringParticipant#initialize( + * org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor, java.lang.Object, + * org.eclipse.ltk.core.refactoring.participants.RefactoringArguments) + */ + public boolean initialize(RefactoringProcessor processor, Object element, + RefactoringArguments arguments) { + + this.fElementAndArgumentPairs = new HashMap(); + this.addElement(element, arguments); + this.fLocalTextChanges = new HashMap(); + this.fName = ""; //$NON-NLS-1$ + + return super.initialize(processor, element, arguments); + } + + /** + * <p>When an element is added to this {@link ISharableParticipant} it must be + * a {@link IJavaElement} and be a legal element type ({@link #isLegalElementType(IJavaElement)} + * and the given arguments must be {@link RenameArguments}. Also the new <code>element</code> + * will not be added if and {@link IJavaElement} of that name has already been added to + * this {@link ISharableParticipant}. This protects against elements being added more + * then once.</p> + * + * @see org.eclipse.ltk.core.refactoring.participants.ISharableParticipant#addElement(java.lang.Object, + * org.eclipse.ltk.core.refactoring.participants.RefactoringArguments) + */ + public void addElement(Object element, RefactoringArguments arguments) { + if(element instanceof IJavaElement && + isLegalElementType((IJavaElement)element) && + arguments instanceof RenameArguments) { + + //don't add elements that have already been added + String elementName = ((IJavaElement)element).getElementName(); + if(!this.fElementAndArgumentPairs.containsKey(elementName)) { + this.fElementAndArgumentPairs.put(elementName, + new ElementAndArgumentsPair((IJavaElement)element, (RenameArguments)arguments)); + } + } + } + + /** + * <p>As of now the conditions are always {@link RefactoringStatus#OK}</p> + * + * @see org.eclipse.ltk.core.refactoring.participants.RefactoringParticipant#checkConditions( + * org.eclipse.core.runtime.IProgressMonitor, org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext) + */ + public RefactoringStatus checkConditions(IProgressMonitor pm, CheckConditionsContext context) { + return new RefactoringStatus(); + } + + /** + * + * + * @see org.eclipse.ltk.core.refactoring.participants.RefactoringParticipant#createChange( + * org.eclipse.core.runtime.IProgressMonitor) + */ + public Change createChange(IProgressMonitor pm) throws CoreException { + this.getTextChange(""); //$NON-NLS-1$ + + //create one multi change to contain all new created changes + CompositeChange multiChange = new CompositeChange(JSPUIMessages.JSP_changes); + + //for each element get the changes for it and add it to the multi change + Iterator iter = fElementAndArgumentPairs.values().iterator(); + while(iter.hasNext()) { + ElementAndArgumentsPair elemArgsPair = (ElementAndArgumentsPair)iter.next(); + Change[] changes = createChangesFor(elemArgsPair.fElement, elemArgsPair.fArgs.getNewName(), pm); + + /* add all new text changes to the local list of text changes so that + * future iterations through the while loop will be aware of already + * existing changes + */ + for(int i = 0; i < changes.length; ++i) { + if(changes[i] instanceof TextChange) { + fLocalTextChanges.put(((TextChange)changes[i]).getModifiedElement(), changes[i]); + } + } + + if(changes.length > 0) { + multiChange.addAll(changes); + } + } + + //unless there are actually new changes return null + Change result = null; + if(multiChange.getChildren().length > 0) { + result = multiChange; + } + + return result; + } + + /** + * @see org.eclipse.ltk.core.refactoring.participants.RefactoringParticipant#getName() + */ + public String getName() { + return fName; + } + + /** + * <p>Overridden to include locally created {@link TextChange}s that have not yet be returned by + * {@link #createChange(IProgressMonitor)}.</p> + * + * @see org.eclipse.ltk.core.refactoring.participants.RefactoringParticipant#getTextChange(java.lang.Object) + */ + public TextChange getTextChange(Object element) { + TextChange existingChange = (TextChange)fLocalTextChanges.get(element); + if(existingChange == null) { + existingChange = super.getTextChange(element); + } + + return existingChange; + } + + /** + * + * @param element the {@link IJavaElement} to create new changes for + * @param newName the new name of the given {@link IJavaElement} + * + * @return any newly created {@link Change}s. It is important to note + * that while no NEW {@link Change}s maybe returned it is possible that + * new {@link TextEdit}s will still added to existing {@link Change}s. + */ + protected Change[] createChangesFor(IJavaElement element, String newName, IProgressMonitor monitor) { + Change[] changes; + BasicRefactorSearchRequestor requestor = getSearchRequestor(element, newName); + if(requestor != null) { + JSPSearchSupport support = JSPSearchSupport.getInstance(); + support.searchRunnable(element, new JSPSearchScope(), requestor, monitor); + changes = requestor.getChanges(this); + } else { + changes = new Change[0]; + } + + return changes; + } + + /** + * <p>Should be implemented to return the {@link BasicRefactorSearchRequestor} associated + * with the implementers {@link JSPRenameParticipantParticipant}.</p> + * + * @param element the {@link IJavaElement} to create the {@link BasicRefactorSearchRequestor} from + * @param newName the new name of the {@link IJavaElement} to use when + * creating the {@link BasicRefactorSearchRequestor} + * + * @return a new {@link BasicRefactorSearchRequestor} based on the given parameters + */ + protected abstract BasicRefactorSearchRequestor getSearchRequestor(IJavaElement element, String newName); + + /** + * @param element check that this {@link IJavaElement} is of the type the + * implementers {@link JSPRenameParticipant} is configured to deal with. + * + * @return <code>true</code> if the given {@link IJavaElement} is of a type + * the implementers {@link JSPRenameParticipant} is configured to deal with, + * <code>false</code> otherwise. + */ + protected abstract boolean isLegalElementType(IJavaElement element); +} |