/*******************************************************************************
* Copyright (c) 2009, 2010 Innovation Gate GmbH.
* All rights reserved. This program and the accompanying materials
* are 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:
* Innovation Gate GmbH - initial API and implementation
******************************************************************************/
package de.innovationgate.eclipse.wgadesigner.refactoring;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.jface.text.FindReplaceDocumentAdapter;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.ltk.core.refactoring.Change;
import org.eclipse.ltk.core.refactoring.CompositeChange;
import org.eclipse.ltk.core.refactoring.TextFileChange;
import org.eclipse.ltk.core.refactoring.participants.DeleteArguments;
import org.eclipse.ltk.core.refactoring.participants.MoveArguments;
import org.eclipse.ltk.core.refactoring.participants.RefactoringArguments;
import org.eclipse.ltk.core.refactoring.participants.RenameArguments;
import org.eclipse.text.edits.ReplaceEdit;
import org.eclipse.text.edits.TextEdit;
import de.innovationgate.eclipse.utils.wga.WGADesignStructureHelper;
import de.innovationgate.eclipse.wgadesigner.WGADesignerPlugin;
import de.innovationgate.eclipse.wgadesigner.natures.IncompatibleWGAConfigVersion;
import de.innovationgate.eclipse.wgadesigner.natures.WGARuntime;
import de.innovationgate.utils.WGUtils;
import de.innovationgate.wga.common.Constants;
import de.innovationgate.wga.config.ContentStore;
import de.innovationgate.wga.config.Design;
import de.innovationgate.wga.config.WGAConfiguration;
import de.innovationgate.wga.model.ValidationError;
public class RefactoringManager {
public static List<RefactoringInfo> getAffectedResources(IContainer container, RefactoringArguments arguments) throws IOException, IncompatibleWGAConfigVersion {
List<RefactoringInfo> links = new ArrayList<RefactoringInfo>();
// iterate over runtimes and check for affected dirlinks
Map<String, WGARuntime> allRuntimes = WGADesignerPlugin.getAllRuntimes();
Iterator<String> itRT = allRuntimes.keySet().iterator();
while (itRT.hasNext()) {
WGARuntime currentRuntime = allRuntimes.get(itRT.next());
IFolder[] designs = currentRuntime.getDesignsAsFolder(false);
for (IFolder folder : designs) {
if (WGADesignStructureHelper.isDirlinkFolder(folder)) {
File target = WGUtils.resolveDirLink(folder.getLocation().toFile());
IPath targetPath;
targetPath = new Path(target.getCanonicalPath());
// check if targetpath is effected by change
if (container.getLocation().isPrefixOf(targetPath)) {
DirlinkRefactoringInformation info = new DirlinkRefactoringInformation(container, arguments);
info.setFile(folder.getFile(WGUtils.DIRLINK_FILE));
links.add(info);
}
}
}
IFolder[] plugins = currentRuntime.getPluginsAsFolder(false);
for (IFolder folder : plugins) {
if (WGADesignStructureHelper.isDirlinkFolder(folder)) {
File target = WGUtils.resolveDirLink(folder.getLocation().toFile());
IPath targetPath;
targetPath = new Path(target.getCanonicalPath());
// check if targetpath is effected by change
if (container.getLocation().isPrefixOf(targetPath)) {
DirlinkRefactoringInformation info = new DirlinkRefactoringInformation(container, arguments);
info.setFile(folder.getFile(WGUtils.DIRLINK_FILE));
links.add(info);
}
}
}
// iterate over contentstores and check design references
Iterator<ContentStore> itCS = currentRuntime.retrieveWGAConfig(false).getContentStores().iterator();
while (itCS.hasNext()) {
ContentStore currentContentStore = itCS.next();
Design currentDesign = currentContentStore.getDesign();
if (currentDesign != null && currentDesign.getSource() != null && currentDesign.getSource().equals(Constants.DESIGNCOL_FILESYSTEM)) {
//IPath designPath = currentRuntime.getDesignRoot().getFullPath().append(currentDesign.getName());
if (container.getParent() != null && container.getParent().equals(currentRuntime.getDesignRoot()) && container.getName().equals(currentDesign.getName())) {
ContentStoreRefactoringInfo info = new ContentStoreRefactoringInfo(container, arguments);
info.setRuntime(currentRuntime);
info.setContentStoreUID(currentContentStore.getUid());
links.add(info);
}
}
}
}
return links;
}
public static Change createChange(RefactoringInfo refactoringInfo) throws Exception {
if (refactoringInfo instanceof DirlinkRefactoringInformation) {
return createDirlinkChange((DirlinkRefactoringInformation)refactoringInfo);
} else if (refactoringInfo instanceof ContentStoreRefactoringInfo) {
return createRenameDesignReferenceChange((ContentStoreRefactoringInfo)refactoringInfo);
} else {
return null;
}
}
private static Change createDirlinkChange(DirlinkRefactoringInformation info) throws Exception {
if(info.getArguments() instanceof MoveArguments || info.getArguments() instanceof RenameArguments){
TextFileChange change = new TextFileChange("", info.getFile());
IDocument doc = change.getCurrentDocument(new NullProgressMonitor());
// create Textedit
FindReplaceDocumentAdapter find = new FindReplaceDocumentAdapter(doc);
IRegion resultStart = find.find(0, "location\\s*=\\s*\"", true, true, false, true);
IRegion resultStop = find.find(resultStart.getOffset() + resultStart.getLength(), "\"", true, true, false, false);
String linkTarget = WGADesignStructureHelper.computeDirLinkTarget(info.getFile().getParent(), computeNewLinkTarget(info));
TextEdit edit = new ReplaceEdit(resultStart.getLength() + resultStart.getOffset(), resultStop.getOffset() - (resultStart.getLength() + resultStart.getOffset()), linkTarget);
change.setEdit(edit);
return change;
}else if (info.getArguments() instanceof DeleteArguments) {
// check if resource to delete will still exists after parent deletion is performed - otherwise we can skip any change here
if (!info.getElement().getFullPath().isPrefixOf(info.getFile().getParent().getFullPath())) {
CompositeChange delChange = new CompositeChange("Deletions");
delChange.add(new DeleteWGAResourceChange(info.getFile().getParent().getFullPath(),false));
for(RefactoringInfo currentInfo : getAffectedResources(info.getFile().getParent(), new DeleteArguments())){
delChange.add(createChange(currentInfo));
}
return delChange;
}
}
return null;
}
private static Change createRenameDesignReferenceChange(ContentStoreRefactoringInfo info) throws Exception {
TextFileChange change = new TextFileChange("", info.getRuntime().getWGAConfigFile());
WGAConfiguration config = info.getRuntime().retrieveWGAConfig(false);
ContentStore currentContentStore = (ContentStore)config.getByUid(info.getContentStoreUID());
boolean configChanged = false;
if(info.getArguments() instanceof RenameArguments){
currentContentStore.getDesign().setName(computeNewDesignReference(info));
configChanged=true;
}else if(info.getArguments() instanceof MoveArguments){
currentContentStore.setEnabled(false);
configChanged=true;
}else if(info.getArguments() instanceof DeleteArguments) {
// check if wgaconfig will still exists after deletion is performed - otherwise we can skip any change here
if (!info.getElement().getFullPath().isPrefixOf(info.getRuntime().getWGAConfigFile().getFullPath())) {
currentContentStore.setEnabled(false);
configChanged=true;
}
}
if(configChanged){
List<ValidationError> errors = config.validate();
if(errors.isEmpty()) {
ByteArrayOutputStream configContent = new ByteArrayOutputStream();
WGAConfiguration.write(config, configContent);
change.setEdit(new ReplaceEdit(0, change.getCurrentDocument((new NullProgressMonitor())).getLength(), configContent.toString()));
return change;
} else {
for(ValidationError current : errors){
WGADesignerPlugin.getDefault().logError(current.getMessage());
}
}
}
return null;
}
private static String computeNewDesignReference(ContentStoreRefactoringInfo info) {
if (info.getArguments() instanceof RenameArguments) {
RenameArguments arguments = (RenameArguments) info.getArguments();
return arguments.getNewName();
}
return null;
}
private static IPath computeNewLinkTarget(DirlinkRefactoringInformation info) {
if (info.getArguments() instanceof RenameArguments) {
RenameArguments arguments = (RenameArguments) info.getArguments();
IContainer currentDirLinkTarget = WGADesignStructureHelper.resolveDirLink(info.getFile());
// compute newTargetPath up to renamed resource
IPath newTarget = info.getElement().getLocation().removeLastSegments(1).append(arguments.getNewName());
// build full target path
int segments = currentDirLinkTarget.getLocation().matchingFirstSegments(newTarget);
newTarget = newTarget.append(currentDirLinkTarget.getLocation().removeFirstSegments(segments + 1));
return newTarget;
}else if(info.getArguments() instanceof MoveArguments){
MoveArguments moveArguments = (MoveArguments) info.getArguments();
IContainer currentDirLinkTarget = WGADesignStructureHelper.resolveDirLink(info.getFile());
if(moveArguments.getDestination() instanceof IContainer){
IContainer destinationContainer = (IContainer)moveArguments.getDestination();
IPath newTarget = destinationContainer.getLocation().append(info.getElement().getName());
int segments = currentDirLinkTarget.getLocation().matchingFirstSegments(((IFolder)info.getElement()).getLocation());
newTarget = newTarget.append(currentDirLinkTarget.getLocation().removeFirstSegments(segments));
return newTarget;
}
}
return null;
}
}