/*******************************************************************************
* Copyright (c) 2007 Exadel, Inc. and 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:
* Exadel, Inc. and Red Hat, Inc. - initial API and implementation
******************************************************************************/
package org.jboss.tools.common.model.refactoring;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jdt.internal.corext.refactoring.changes.TextChangeCompatibility;
import org.eclipse.ltk.core.refactoring.Change;
import org.eclipse.ltk.core.refactoring.TextFileChange;
import org.eclipse.text.edits.ReplaceEdit;
import org.jboss.tools.common.model.XModelObject;
import org.jboss.tools.common.model.filesystems.impl.FileAnyImpl;
import org.jboss.tools.common.model.impl.XModelObjectImpl;
import org.jboss.tools.common.model.util.EclipseResourceUtil;
import org.jboss.tools.common.model.util.PositionSearcher;
/**
* @author glory
*
* This change receives an array of objects which reference
* to a renamed object, name of attribute by which they
* reference to it, and new value. The change implementation
* presents and performs the change as a text change.
*
* Use restrictions:
* 1. All objects must belong to the same file object.
* 2. If you need process two sets of objects from one file with different
* attributes affected, use method addEdits(XModelObject[], String, String)
* repeatedly.
*/
public class RenameModelObjectChange extends TextFileChange {
boolean ok = false;
private String newName;
class ObjectSet {
XModelObject[] objects;
String attributeName;
ObjectSet(XModelObject[] objects, String attributeName) {
this.objects = objects;
this.attributeName = attributeName;
}
}
List<ObjectSet> list = new ArrayList<ObjectSet>();
public static RenameModelObjectChange createChange(XModelObject[] objects, String newName, String attributeName) {
if(objects == null || objects.length == 0) return null;
String name = objects[0].getPresentationString();
IFile f = getFile(objects[0]);
if(f == null) return null;
return new RenameModelObjectChange(name, f, objects, newName, attributeName);
}
/**
* Creates empty change, for which one has to add edits
* by calling addEdits(XModelObject[], String, String)
*
* @param fileObject
* @param newName
* @return
*/
public static RenameModelObjectChange createChange(XModelObject fileObject, String newName) {
String name = fileObject.getPresentationString();
IFile f = getFile(fileObject);
if(f == null) return null;
return new RenameModelObjectChange(name, f, newName);
}
private RenameModelObjectChange(String name, IFile file, String newName) {
super(name, file);
this.newName = newName;
}
private RenameModelObjectChange(String name, IFile file, XModelObject[] objects, String newName, String attributeName) {
this(name, file, newName);
addEdits(objects, attributeName, "Update field reference");
}
public void addEdits(XModelObject[] objects, String attributeName, String textEditName) {
list.add(new ObjectSet(objects, attributeName));
PositionSearcher searcher = new PositionSearcher();
XModelObject o = ((XModelObjectImpl)objects[0]).getResourceAncestor();
String text = ((FileAnyImpl)o).getAsText();
for (int i = 0; i < objects.length; i++) {
searcher.init(text, objects[i], attributeName);
searcher.execute();
int bp = searcher.getStartPosition();
int ep = searcher.getEndPosition();
ok = false;
if(bp >= 0 && ep >= ep) {
ReplaceEdit edit = new ReplaceEdit(bp, ep - bp, newName);
TextChangeCompatibility.addTextEdit(this, textEditName, edit);
ok = true;
}
}
}
protected static IFile getFile(XModelObject object) {
XModelObject o = ((XModelObjectImpl)object).getResourceAncestor();
return o == null ? null : (IFile)EclipseResourceUtil.getResource(o);
}
public Change perform(IProgressMonitor pm) throws CoreException {
Change result = null;
if(ok) {
result = super.perform(pm);
} else {
for (ObjectSet set: list) {
for (int i = 0; i < set.objects.length; i++) {
set.objects[i].getModel().changeObjectAttribute(set.objects[i], set.attributeName, newName);
}
}
}
return result;
}
public Object getModifiedElement() {
return null;
}
public String getName() {
return MessageFormat.format("Edit {0}", list.get(0).attributeName);
}
}