/*******************************************************************************
* Copyright (c) 2007-2010 Red Hat, Inc.
* Distributed under license by Red Hat, Inc. All rights reserved.
* This program is 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:
* Red Hat, Inc. - initial API and implementation
******************************************************************************/
package org.jboss.tools.jsf.jsf2.refactoring.action.rename;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.jdt.internal.corext.refactoring.changes.TextChangeCompatibility;
import org.eclipse.jdt.internal.corext.refactoring.tagging.INameUpdating;
import org.eclipse.ltk.core.refactoring.Change;
import org.eclipse.ltk.core.refactoring.GroupCategorySet;
import org.eclipse.ltk.core.refactoring.RefactoringStatus;
import org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext;
import org.eclipse.ltk.core.refactoring.participants.RefactoringParticipant;
import org.eclipse.ltk.core.refactoring.participants.RenameProcessor;
import org.eclipse.ltk.core.refactoring.participants.SharableParticipants;
import org.jboss.tools.jsf.jsf2.model.JSF2ComponentModelManager;
import org.jboss.tools.jsf.jsf2.refactoring.core.StructuredChanges;
import org.jboss.tools.jsf.jsf2.refactoring.core.StructuredTextFileChange;
import org.jboss.tools.jsf.jsf2.util.JSF2ComponentUtil;
import org.jboss.tools.jsf.messages.JSFUIMessages;
import org.w3c.dom.Attr;
import org.eclipse.ltk.core.refactoring.GroupCategory;
import org.eclipse.text.edits.ReplaceEdit;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMAttr;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMElement;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
/**
*
* @author yzhishko
*
*/
@SuppressWarnings("restriction")
public class CompositeAttributeRenameProcessor extends RenameProcessor
implements INameUpdating {
private static final Pattern PATTERN = Pattern.compile("[a-zA-Z_][a-zA-Z0-9_.]*+"); //$NON-NLS-1$
private static final GroupCategorySet CATEGORY_COMPOSITE_ATTR_RENAME = new GroupCategorySet(
new GroupCategory(
"org.jboss.tools.jsf.jsf2.refactoring.rename.composite.attr.type", JSFUIMessages.Refactoring_JSF_2_Rename_Composite_Attr_Changes, JSFUIMessages.Refactoring_JSF_2_Changes_Rename_Composite_Attr)); //$NON-NLS-1$
public static final String IDENTIFIER = "org.jboss.tools.jsf.jsf2.refactor.compositeattrrenameprocessor"; //$NON-NLS-1$
private String newAttrName;
private String currentAttrName;
private IProject project;
private String URI;
private IFile baseFile;
private IDOMAttr attrToRename;
public void setCurrentAttrName(String currentAttrName) {
this.currentAttrName = currentAttrName;
}
public CompositeAttributeRenameProcessor(IProject project) {
this.setProject(project);
}
@Override
public RefactoringStatus checkFinalConditions(IProgressMonitor pm,
CheckConditionsContext context) throws CoreException,
OperationCanceledException {
return null;
}
@Override
public RefactoringStatus checkInitialConditions(IProgressMonitor pm)
throws CoreException, OperationCanceledException {
return null;
}
@Override
public Change createChange(IProgressMonitor pm) throws CoreException,
OperationCanceledException {
StructuredChanges changes = new StructuredChanges(
JSFUIMessages.Refactoring_JSF_2_Composite_Attr_Rename_Changes);
changes.add(createBaseFileChange());
Map<IFile, List<IDOMNode>> nodesMap = JSF2ComponentUtil
.findCompositeComponentsWithURI(getProject(), getURI());
Set<Entry<IFile, List<IDOMNode>>> entries = nodesMap.entrySet();
for (Entry<IFile, List<IDOMNode>> entry : entries) {
StructuredTextFileChange fileChange = createFileChange(entry
.getKey(), entry.getValue());
if (fileChange != null) {
changes.add(fileChange);
}
}
return changes;
}
private StructuredTextFileChange createBaseFileChange(){
StructuredTextFileChange baseFileChange = new StructuredTextFileChange(baseFile.getFullPath().toOSString(), baseFile);
ReplaceEdit edit = new ReplaceEdit(attrToRename.getValueRegionStartOffset()+1, attrToRename.getValue().length(), getNewElementName());
TextChangeCompatibility.addTextEdit(baseFileChange, JSFUIMessages.Refactoring_JSF_2_Rename_Composite_Attr_Name, edit, CATEGORY_COMPOSITE_ATTR_RENAME);
IDOMElement element = JSF2ComponentUtil.findCompositeImpl(JSF2ComponentModelManager.getReadableDOMDocument(baseFile));
if (element != null) {
IDOMAttr[] attrs = JSF2ComponentUtil.extractAttrsWithValue(element, computeAttrOldValue());
for (int i = 0; i < attrs.length; i++) {
edit = new ReplaceEdit(attrs[i].getValueRegionStartOffset()+1, attrs[i].getValue().length(), computeAttrNewValue());
TextChangeCompatibility.addTextEdit(baseFileChange, JSFUIMessages.Refactoring_JSF_2_Rename_Attr_Ref_Decl, edit, CATEGORY_COMPOSITE_ATTR_RENAME);
}
}
return baseFileChange;
}
private String computeAttrOldValue(){
return "#{cc.attrs." + getCurrentElementName() + "}"; //$NON-NLS-1$//$NON-NLS-2$
}
private String computeAttrNewValue(){
return "#{cc.attrs." + getNewElementName() + "}"; //$NON-NLS-1$//$NON-NLS-2$
}
private StructuredTextFileChange createFileChange(IFile file,
List<IDOMNode> nodeList) {
StructuredTextFileChange fileChange = null;
for (IDOMNode domNode : nodeList) {
if (domNode instanceof IDOMElement) {
IDOMElement element = (IDOMElement) domNode;
Attr attr = element.getAttributeNode(getCurrentElementName());
if (attr instanceof IDOMAttr) {
IDOMAttr domAttr = (IDOMAttr) attr;
if (fileChange == null) {
fileChange = new StructuredTextFileChange(file
.getFullPath().toOSString(), file);
}
ReplaceEdit edit = new ReplaceEdit(
domAttr.getStartOffset(), domAttr.getName()
.length(), getNewElementName());
TextChangeCompatibility
.addTextEdit(
fileChange,
JSFUIMessages.Refactoring_JSF_2_Rename_Composite_Attr, edit, CATEGORY_COMPOSITE_ATTR_RENAME);
}
}
}
return fileChange;
}
@Override
public Object[] getElements() {
return null;
}
@Override
public String getIdentifier() {
return IDENTIFIER;
}
@Override
public String getProcessorName() {
return JSFUIMessages.Refactoring_JSF_2_Rename_Composite_Attr;
}
@Override
public boolean isApplicable() throws CoreException {
return true;
}
@Override
public RefactoringParticipant[] loadParticipants(RefactoringStatus status,
SharableParticipants sharedParticipants) throws CoreException {
return null;
}
public RefactoringStatus checkNewElementName(String newName)
throws CoreException {
RefactoringStatus status = null;
Matcher matcher = PATTERN.matcher(getNewElementName());
int includings = 0;
String matchString = null;
while (matcher.find()) {
includings++;
matchString = matcher.group();
}
if (includings != 1 || !matchString.equals(getNewElementName())) {
status = RefactoringStatus.createFatalErrorStatus(JSFUIMessages.Refactoring_JSF_2_Invalid_Attr);
}
return status;
}
public String getCurrentElementName() {
return currentAttrName;
}
public Object getNewElement() throws CoreException {
return null;
}
public String getNewElementName() {
return newAttrName;
}
public void setNewElementName(String newName) {
this.newAttrName = newName;
}
public void setProject(IProject project) {
this.project = project;
}
public IProject getProject() {
return project;
}
public void setURI(String uRI) {
URI = uRI;
}
public String getURI() {
return URI;
}
public void setBaseFile(IFile baseFile) {
this.baseFile = baseFile;
}
public IFile getBaseFile() {
return baseFile;
}
public void setAttrToRename(IDOMAttr attrToRename) {
this.attrToRename = attrToRename;
}
public IDOMAttr getAttrToRename() {
return attrToRename;
}
}