/*
* JBoss, Home of Professional Open Source.
*
* See the LEGAL.txt file distributed with this work for information regarding copyright ownership and licensing.
*
* See the AUTHORS.txt file distributed with this work for a full listing of individual contributors.
*/
package org.teiid.designer.vdb.refactor;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.ltk.core.refactoring.Change;
import org.eclipse.ltk.core.refactoring.resource.ResourceChange;
import org.teiid.core.designer.util.CoreArgCheck;
import org.teiid.designer.core.ModelerCore;
import org.teiid.designer.core.refactor.PathPair;
import org.teiid.designer.core.workspace.WorkspaceResourceFinderUtil;
import org.teiid.designer.vdb.Vdb;
import org.teiid.designer.vdb.VdbConstants;
import org.teiid.designer.vdb.VdbEntry;
import org.teiid.designer.vdb.VdbPlugin;
import org.teiid.designer.vdb.VdbUtil;
import org.teiid.designer.vdb.XmiVdb;
/**
*
*/
public class VdbResourceChange extends ResourceChange {
private final Set<PathPair> replacements = new HashSet<PathPair>();
private String projectName;
private String parentFolder;
private String vdbName;
/**
* @param projectName
* @param parentFolder
* @param vdbName
*/
public VdbResourceChange(String projectName, String parentFolder, String vdbName) {
super();
CoreArgCheck.isNotNull(projectName);
CoreArgCheck.isNotNull(parentFolder);
CoreArgCheck.isNotNull(vdbName);
this.projectName = projectName;
this.parentFolder = parentFolder;
this.vdbName = vdbName;
}
/**
* @param vdbFile
*/
public VdbResourceChange(IFile vdbFile) {
super();
CoreArgCheck.isNotNull(vdbFile);
this.projectName = vdbFile.getProject().getName();
this.parentFolder = vdbFile.getParent().getName();
this.vdbName = vdbFile.getName();
}
private IFile findVdb(IWorkspaceRoot workspaceRoot, IProject project) {
if (! project.isAccessible())
return null;
Collection<IFile> resources = WorkspaceResourceFinderUtil.findIResourceInProjectByName(vdbName, project);
if (resources.isEmpty())
return null;
for (IFile vdbFile : resources) {
IContainer container = vdbFile.getParent();
if (parentFolder.equals(container.getName()))
return vdbFile;
/*
* We have a vdb file but its parent does not match so either
* a) the parent folder is being renamed
* b) there is genuinely 2 vdb files with the same name in the project
*
* Ask the replacement about the containing folder
*/
for (PathPair pathPair : replacements) {
IPath sourcePath = new Path(pathPair.getSourcePath());
IPath targetPath = new Path(pathPair.getTargetPath());
if (container.getFullPath().isPrefixOf(sourcePath) || container.getFullPath().isPrefixOf(targetPath))
return vdbFile;
}
}
// Genuinely cannot find the vdb file
return null;
}
private IFile findVdb() {
IWorkspaceRoot workspaceRoot = ModelerCore.getWorkspace().getRoot();
IProject vdbProject = workspaceRoot.getProject(projectName);
if (! vdbProject.isAccessible()) {
/*
* The project has been renamed and this vdbFile needs a bit of work to be found.
* Try the first segment of the target path in the replacements.
*/
for (PathPair pathPair : replacements) {
IPath sourcePath = new Path(pathPair.getSourcePath());
IPath targetPath = new Path(pathPair.getTargetPath());
vdbProject = workspaceRoot.getProject(sourcePath.segment(0));
IFile vdbFile = findVdb(workspaceRoot, vdbProject);
if (vdbFile != null)
return vdbFile;
vdbProject = workspaceRoot.getProject(targetPath.segment(0));
vdbFile = findVdb(workspaceRoot, vdbProject);
if (vdbFile != null)
return vdbFile;
}
}
IFile vdbFile = findVdb(workspaceRoot, vdbProject);
return vdbFile;
}
/**
* @return the parentFolder
*/
public String getParentFolder() {
return this.parentFolder;
}
/**
* @return the vdbName
*/
public String getVdbName() {
return this.vdbName;
}
/**
* @see org.eclipse.ltk.core.refactoring.resource.ResourceChange#getModifiedResource()
*/
@Override
protected IResource getModifiedResource() {
return findVdb();
}
private Change getUndoChange() {
VdbResourceChange change = new VdbResourceChange(projectName, parentFolder, vdbName);
for (PathPair pathPair : replacements) {
// Creates a reversed path pair
change.addReplacement(pathPair.getTargetPath(), pathPair.getSourcePath());
}
return change;
}
/**
* @param monitor
* @return status
*/
protected IStatus performTask(IProgressMonitor monitor) {
// Refresh the project so that the new resource may be found
// and a model resource extracted
IFile vdbFile = findVdb();
if (vdbFile == null) {
/*
* Cannot find the vdb file so cannot do any refreshing
*/
String msg = VdbPlugin.UTIL.getString(getClass().getSimpleName() + ".syncVdbFailure", projectName, parentFolder, vdbName); //$NON-NLS-1$
IStatus status = new Status(IStatus.WARNING, VdbConstants.PLUGIN_ID, msg);
return status;
}
try {
vdbFile.getProject().refreshLocal(IResource.DEPTH_INFINITE, monitor);
// Synchronise will add the new resource
VdbUtil.synchronizeVdb(vdbFile, false, true);
// This should clean up and remove old resources
Vdb actualVdb = new XmiVdb(vdbFile);
for (VdbEntry entry : actualVdb.getModelEntries()) {
for (PathPair pathPair : replacements) {
if (entry.getPath().equals(pathPair.getSourcePath())) {
actualVdb.removeEntry(entry);
actualVdb.save();
}
}
}
} catch (Exception ex) {
return new Status(IStatus.ERROR, VdbConstants.PLUGIN_ID, ex.getMessage());
}
return Status.OK_STATUS;
}
/**
* @param replacedResourcePaths
*/
public void addReplacements(Set<PathPair> replacedResourcePaths) {
replacements.addAll(replacedResourcePaths);
}
/**
* @param invalidResourcePath
* @param newResourcePath
*/
public void addReplacement(String invalidResourcePath, String newResourcePath) {
PathPair resourcePair = new PathPair(invalidResourcePath, newResourcePath);
replacements.add(resourcePair);
}
/**
* @return the resource replacement paths
*/
public Set<PathPair> getReplacedResources() {
return replacements;
}
/**
* @see org.eclipse.ltk.core.refactoring.Change#getName()
*/
@Override
public String getName() {
return VdbPlugin.UTIL.getString(getClass().getSimpleName() + ".name", vdbName); //$NON-NLS-1$
}
/**
* @see org.eclipse.ltk.core.refactoring.Change#perform(org.eclipse.core.runtime.IProgressMonitor)
*/
@Override
public Change perform(IProgressMonitor pm) {
Job job = new Job(getName()) {
@Override
protected IStatus run(IProgressMonitor monitor) {
return performTask(monitor);
}
};
// Start the Job
job.schedule();
return getUndoChange();
}
}