/*******************************************************************************
* 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;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.content.IContentType;
import org.eclipse.jdt.internal.corext.refactoring.changes.TextChangeCompatibility;
import org.eclipse.ltk.core.refactoring.GroupCategory;
import org.eclipse.ltk.core.refactoring.GroupCategorySet;
import org.eclipse.text.edits.ReplaceEdit;
import org.eclipse.ui.ide.IDE;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMAttr;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMElement;
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.Element;
/**
*
* @author yzhishko
*
*/
@SuppressWarnings("restriction")
public class RefactoringChangesFactory {
private static final String JSF_CONTENT_TYPE = "jsf.facelet";
private static final String JSP_CONTENT_TYPE = "org.eclipse.jst.jsp.core.jspsource";
private static final String HTML_CONTENT_TYPE = "org.eclipse.wst.html.core.htmlsource";
private static final GroupCategorySet CATEGORY_COMPOSITE_URI_RENAME = new GroupCategorySet(
new GroupCategory(
"org.jboss.tools.jsf.jsf2.refactoring.rename.composite.uri.type", JSFUIMessages.Refactoring_JSF_2_Rename_Composite_URI_Changes, JSFUIMessages.Refactoring_JSF_2_Changes_Rename_Composite_URI)); //$NON-NLS-1$
private static final GroupCategorySet CATEGORY_COMPOSITE_COMPONENT_RENAME = new GroupCategorySet(
new GroupCategory(
"org.jboss.tools.jsf.jsf2.refactoring.rename.composite.uri.type", JSFUIMessages.Refactoring_JSF_2_Rename_Composite_Component_Changes, JSFUIMessages.Refactoring_JSF_2_Changes_Rename_Composite_Component)); //$NON-NLS-1$
public static StructuredChanges createRenameURIChanges(IResource resource,
Map<String, String> urisMap) throws CoreException {
StructuredChanges changes = new StructuredChanges(
JSFUIMessages.Refactoring_JSF_2_Rename_Composite_URI_Changes);
createRenameURIChangesRecursively(resource, urisMap, changes);
if (changes.getChildren() == null || changes.getChildren().length == 0) {
return null;
}
return changes;
}
public static StructuredChanges createRenameCompositeComponentsChanges(
IResource resource, String uri, String oldFileName,
String newFileName) throws CoreException {
StructuredChanges changes = new StructuredChanges(
JSFUIMessages.Refactoring_JSF_2_Rename_Composite_Component_Changes);
createRenameComponentChangesRecursively(resource, uri, oldFileName,
newFileName, changes);
if (changes.getChildren() == null || changes.getChildren().length == 0) {
return null;
}
return changes;
}
private static void createRenameComponentChangesRecursively(
IResource resource, String uri, String oldFileName,
String newFileName, StructuredChanges changes) throws CoreException {
if (resource instanceof IFile) {
IFile file = (IFile) resource;
StructuredTextFileChange change = createRanameComponentChange(file,
uri, oldFileName, newFileName);
if (change != null) {
changes.add(change);
}
} else if (resource instanceof IProject) {
IResource[] children = ((IProject) resource).members();
if (children != null) {
for (int i = 0; i < children.length; i++) {
createRenameComponentChangesRecursively(children[i], uri,
oldFileName, newFileName, changes);
}
}
} else if (resource instanceof IFolder) {
if(resource.getName().startsWith(".")) //$NON-NLS-1$
return;
IResource[] children = ((IFolder) resource).members();
if (children != null) {
for (int i = 0; i < children.length; i++) {
createRenameComponentChangesRecursively(children[i], uri,
oldFileName, newFileName, changes);
}
}
}
}
private static StructuredTextFileChange createRanameComponentChange(
IFile file, String uri, String oldName, String newName) {
if (!isFileCorrect(file)) {
return null;
}
StructuredTextFileChange fileChange = null;
Map<String, List<Element>> compositeComponentsMap = JSF2ComponentUtil
.findCompositeComponents(JSF2ComponentModelManager
.getReadableDOMDocument(file));
List<Element> compositeComponents = compositeComponentsMap.get(uri);
if (compositeComponents != null) {
for (Element element : compositeComponents) {
if (oldName.equals(element.getLocalName())) {
if (element instanceof IDOMElement) {
IDOMElement domElement = (IDOMElement) element;
if (fileChange == null) {
fileChange = new StructuredTextFileChange(file
.getFullPath().toOSString(), file);
}
ReplaceEdit[] edits = createReplaceEditsForElement(domElement, oldName, newName);
for (int i = 0; i < edits.length; i++) {
TextChangeCompatibility.addTextEdit(fileChange,
JSFUIMessages.Refactoring_JSF_2_Rename_Composite_Component,
edits[i], CATEGORY_COMPOSITE_COMPONENT_RENAME);
}
}
}
}
}
return fileChange;
}
private static ReplaceEdit[] createReplaceEditsForElement(IDOMElement element, String oldName, String newName){
List<ReplaceEdit> edits = new ArrayList<ReplaceEdit>();
String sourceString = element.getSource();
int startOffset = element.getStartOffset();
int endStartOffset = element.getEndStartOffset();
int endOffset = element.getEndOffset();
if (endOffset != endStartOffset) {
ReplaceEdit edit = new ReplaceEdit(sourceString.lastIndexOf(oldName) + startOffset, oldName.length(), newName);
edits.add(edit);
}
ReplaceEdit edit = new ReplaceEdit(startOffset + sourceString.indexOf(oldName), oldName.length(), newName);
edits.add(edit);
return edits.toArray(new ReplaceEdit[0]);
}
private static void createRenameURIChangesRecursively(IResource resource,
Map<String, String> urisMap, StructuredChanges changes)
throws CoreException {
if (resource instanceof IFile) {
IFile file = (IFile) resource;
StructuredTextFileChange change = createRanameURIChange(file,
urisMap);
if (change != null) {
changes.add(change);
}
} else if (resource instanceof IProject) {
IResource[] children = ((IProject) resource).members();
if (children != null) {
for (int i = 0; i < children.length; i++) {
createRenameURIChangesRecursively(children[i], urisMap,
changes);
}
}
} else if (resource instanceof IFolder) {
if(resource.getName().startsWith(".")) //$NON-NLS-1$
return;
IResource[] children = ((IFolder) resource).members();
if (children != null) {
for (int i = 0; i < children.length; i++) {
createRenameURIChangesRecursively(children[i], urisMap,
changes);
}
}
}
}
private static StructuredTextFileChange createRanameURIChange(IFile file,
Map<String, String> urisMap) {
if (!isFileCorrect(file)) {
return null;
}
StructuredTextFileChange fileChange = null;
IDOMAttr[] uriAttrs = JSF2ComponentUtil
.findURIContainers(JSF2ComponentModelManager
.getReadableDOMDocument(file));
for (IDOMAttr uriAttr : uriAttrs) {
String valueToBeReplaced = uriAttr.getValue();
if (urisMap.containsKey(valueToBeReplaced)) {
if (fileChange == null) {
fileChange = new StructuredTextFileChange(file
.getFullPath().toOSString(), file);
}
ReplaceEdit edit = new ReplaceEdit(uriAttr
.getValueRegionStartOffset() + 1, valueToBeReplaced
.length(), urisMap.get(valueToBeReplaced));
TextChangeCompatibility.addTextEdit(fileChange,
JSFUIMessages.Refactoring_JSF_2_Rename_Composite_URI,
edit, CATEGORY_COMPOSITE_URI_RENAME);
}
}
return fileChange;
}
private static boolean isFileCorrect(IFile file) {
if (file == null) {
return false;
}
if(!file.isSynchronized(IResource.DEPTH_ZERO)){
return false;
}else if(file.isPhantom()){
return false;
}else if(file.isReadOnly()){
return false;
}
if (!"xhtml".equals(file.getFileExtension()) && !"jsp".equals(file.getFileExtension())) { //$NON-NLS-1$ //$NON-NLS-2$
IContentType contentType = IDE.getContentType(file);
if (contentType == null) {
return false;
}
String id = contentType.getId();
if (!JSP_CONTENT_TYPE.equals(id) && ! HTML_CONTENT_TYPE.equals(id) && !JSF_CONTENT_TYPE.equals(id)) { //$NON-NLS-1$ //$NON-NLS-2$
return false;
}
}
return true;
}
}