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