/******************************************************************************* * 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; } }