package com.baselet.plugin.refactoring;
import java.util.Collections;
import java.util.List;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.refactoring.CompilationUnitChange;
import org.eclipse.ltk.core.refactoring.Change;
import org.eclipse.ltk.core.refactoring.CompositeChange;
import org.eclipse.text.edits.MultiTextEdit;
import org.eclipse.text.edits.ReplaceEdit;
import com.baselet.plugin.UmletPluginUtils;
/**
* Processor used by multiple refactoring participants to update image references
* in JavaDoc comments.
*/
public abstract class UpdateImgReferencesProcessor implements UmletRefactoringProcessor {
private final IJavaProject project;
protected static class Destination {
IFile cuDestination;
IFile imgFileDestination;
}
public UpdateImgReferencesProcessor(IJavaProject project) {
if (project == null) {
throw new IllegalArgumentException("project may not be null");
}
this.project = project;
}
@Override
public List<? extends Change> createChange(IProgressMonitor pm) throws CoreException {
// calculate target location
CompositeChange imgRefChange = new CompositeChange("Update <img> references");
// iterate all Compilation units
for (ICompilationUnit cu : UmletPluginUtils.collectCompilationUnits(project)) {
if (!(cu.getCorrespondingResource() instanceof IFile)) {
continue;
}
IFile cuResource = (IFile) cu.getCorrespondingResource();
if (cu.getBuffer() == null) {
continue;
}
CompilationUnitChange change = null;
for (ImageReference reference : UmletPluginUtils.collectUxfImgRefs(cu)) {
IFile originalImg = UmletPluginUtils.getReferencedImgFile(cu, reference.srcAttr.value.getValue());
Destination dest = new Destination();
dest.cuDestination = cuResource;
dest.imgFileDestination = originalImg;
calculateDestination(originalImg, cu, dest);
IPath oldImgRelativePath = originalImg.getFullPath().makeRelativeTo(cuResource.getFullPath());
IPath newImgRelativePath = dest.imgFileDestination.getFullPath().makeRelativeTo(dest.cuDestination.getFullPath());
if (!oldImgRelativePath.equals(newImgRelativePath)) {
// the src attribute references the diagram beeing moved, update the reference
if (change == null) {
change = new CompilationUnitChange(cu.getElementName(), cu);
change.setKeepPreviewEdits(true);
change.setEdit(new MultiTextEdit());
imgRefChange.add(change);
}
IPath destinationImgPath = UmletPluginUtils.getPackageFragmentRootRelativePath(project, dest.imgFileDestination);
IPath javaResourceParentPath = UmletPluginUtils.getPackageFragmentRootRelativePath(cu.getJavaProject(), dest.cuDestination.getParent());
String imgRef = UmletPluginUtils.calculateImageRef(javaResourceParentPath, destinationImgPath);
change.addEdit(new ReplaceEdit(reference.srcAttr.value.start, reference.srcAttr.value.length(), imgRef));
}
}
}
if (imgRefChange.getChildren().length == 0) {
return Collections.emptyList();
}
return Collections.singletonList(imgRefChange);
}
/**
* Calculate the destination of the given umlet diagram. Return null if the diagram reference does not need to be updated
*/
protected void calculateDestination(IFile uxf, ICompilationUnit referencingCompilationUnit, Destination dest) throws CoreException {
IFile uxfDest = calculateImgDestination(uxf, referencingCompilationUnit);
if (uxfDest != null) {
dest.imgFileDestination = uxfDest;
}
}
/**
* Calculate the destination of the given umlet diagram. Return null if the diagram reference does not need to be updated
*/
protected abstract IFile calculateImgDestination(IFile uxf, ICompilationUnit referencingCompilationUnit) throws CoreException;
}