/**
* <p>Copyright: Copyright (c) 2009</p>
* <p>Company: �������ӹɷ�����˾</p>
*/
package com.hundsun.ares.studio.internal.core;
import java.io.InputStream;
import org.apache.log4j.Logger;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceStatus;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.core.runtime.jobs.ISchedulingRule;
import com.hundsun.ares.studio.core.ARESModelException;
import com.hundsun.ares.studio.core.ARESModelStatus;
import com.hundsun.ares.studio.core.IARESElement;
import com.hundsun.ares.studio.core.IARESModelStatus;
import com.hundsun.ares.studio.core.IARESModelStatusConstants;
/**
* ARESģ�Ͳ�����Operation,ʵ����IWorkspaceRunnable�ӿڣ��Եײ���Դ�������з�װ��
* �����Դ���������γ���һ��IWorkspaceRunnable���У����������Դ�ı��¼���
* @author sundl
*/
public abstract class ARESModelOperation implements IWorkspaceRunnable {
/**
* The progress monitor passed into this operation
*/
public IProgressMonitor progressMonitor= null;
/**
* The elements this operation operates on,
* or <code>null</code> if this operation
* does not operate on specific elements.
*/
protected IARESElement[] elementsToProcess;
/**
* The parent elements this operation operates with
* or <code>null</code> if this operation
* does not operate with specific parent elements.
*/
protected IARESElement[] parentElements;
/**
* An empty collection of <code>IJavaElement</code>s - the common
* empty result if no elements are created, or if this
* operation is not actually executed.
*/
protected static final IARESElement[] NO_ELEMENTS= new IARESElement[] {};
/**
* The elements created by this operation - empty
* until the operation actually creates elements.
*/
protected IARESElement[] resultElements = NO_ELEMENTS;
/**
* A flag indicating whether this operation is nested.
*/
protected boolean isNested = false;
/**
* Conflict resolution policy - by default do not force (fail on a conflict).
*/
protected boolean force = false;
public ARESModelOperation(IARESElement[] elementsToProElements, IARESElement[] parentElements, boolean force) {
this.elementsToProcess = elementsToProElements;
this.parentElements = parentElements;
this.force = force;
}
public void beginTask(String name, int totalWork) {
if (this.progressMonitor != null)
this.progressMonitor.beginTask(name, totalWork);
}
protected void checkCanceled() {
if (isCanceled()) {
throw new OperationCanceledException();
}
}
/**
* @see IProgressMonitor
*/
public boolean isCanceled() {
if (this.progressMonitor != null) {
return this.progressMonitor.isCanceled();
}
return false;
}
/**
* @see IProgressMonitor
*/
public void worked(int work) {
if (this.progressMonitor != null) {
this.progressMonitor.worked(work);
checkCanceled();
}
}
/**
* @see IProgressMonitor
*/
public void done() {
if (this.progressMonitor != null) {
this.progressMonitor.done();
}
}
/* (non-Javadoc)
* @see org.eclipse.core.resources.IWorkspaceRunnable#run(org.eclipse.core.runtime.IProgressMonitor)
*/
public void run(IProgressMonitor monitor) throws CoreException {
try {
excuteOperation();
} finally {
}
}
public void runOperation(IProgressMonitor monitor) throws ARESModelException{
IARESModelStatus status = verify();
if (!status.isOK()) {
throw new ARESModelException(status);
}
try {
if (isReadOnly()) {
run(monitor);
} else {
ResourcesPlugin.getWorkspace().run(this, getSchedulingRule(), IWorkspace.AVOID_UPDATE, monitor);
}
} catch (CoreException e) {
if (e instanceof ARESModelException) {
throw (ARESModelException)e;
} else {
if (e.getStatus().getCode() == IResourceStatus.OPERATION_FAILED) {
Throwable ee = e.getStatus().getException();
if (ee instanceof ARESModelException) {
throw (ARESModelException)ee;
}
}
throw new ARESModelException(e);
}
}
}
/**
* @throws ARESModelException
*/
protected abstract void excuteOperation() throws ARESModelException;
/**
* Common code used to verify the elements this operation is processing.
* @see ARESModelOperation#verify()
*/
protected IARESModelStatus commonVerify() {
if (this.elementsToProcess == null || this.elementsToProcess.length == 0) {
return new ARESModelStatus(IARESModelStatusConstants.NO_ELEMENTS_TO_PROCESS);
}
for (int i = 0; i < this.elementsToProcess.length; i++) {
if (this.elementsToProcess[i] == null) {
return new ARESModelStatus(IARESModelStatusConstants.NO_ELEMENTS_TO_PROCESS);
}
}
return ARESModelStatus.VERIFIED_OK;
}
/**
* Convenience method to copy resources
*/
protected void copyResources(IResource[] resources, IPath container) throws ARESModelException {
IProgressMonitor subProgressMonitor = getSubProgressMonitor(resources.length);
IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
try {
for (int i = 0, length = resources.length; i < length; i++) {
IResource resource = resources[i];
IPath destination = container.append(resource.getName());
if (root.findMember(destination) == null) {
resource.copy(destination, false, subProgressMonitor);
}
}
//setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE);
} catch (CoreException e) {
throw new ARESModelException(e);
}
}
/**
* Convenience method to create a file
*/
protected void createFile(IContainer folder, String name, InputStream contents, boolean forceFlag) throws ARESModelException {
IFile file= folder.getFile(new Path(name));
try {
file.create(
contents,
forceFlag ? IResource.FORCE | IResource.KEEP_HISTORY : IResource.KEEP_HISTORY,
getSubProgressMonitor(1));
//setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE);
} catch (CoreException e) {
throw new ARESModelException(e);
}
}
/**
* Convenience method to create a folder
*/
protected void createFolder(IContainer parentFolder, String name, boolean forceFlag) throws ARESModelException {
IFolder folder= parentFolder.getFolder(new Path(name));
try {
// we should use true to create the file locally. Only VCM should use tru/false
folder.create(
forceFlag ? IResource.FORCE | IResource.KEEP_HISTORY : IResource.KEEP_HISTORY,
true, // local
getSubProgressMonitor(1));
//setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE);
} catch (CoreException e) {
throw new ARESModelException(e);
}
}
/**
* Convenience method to delete a resource
*/
protected void deleteResource(IResource resource,int flags) throws ARESModelException {
try {
resource.delete(flags, getSubProgressMonitor(1));
//setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE);
} catch (CoreException e) {
throw new ARESModelException(e);
}
}
/**
* Convenience method to delete resources
*/
protected void deleteResources(IResource[] resources, boolean forceFlag) throws ARESModelException {
if (resources == null || resources.length == 0) return;
IProgressMonitor subProgressMonitor = getSubProgressMonitor(resources.length);
IWorkspace workspace = resources[0].getWorkspace();
try {
workspace.delete(
resources,
forceFlag ? IResource.FORCE | IResource.KEEP_HISTORY : IResource.KEEP_HISTORY,
subProgressMonitor);
//setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE);
} catch (CoreException e) {
throw new ARESModelException(e);
}
}
/**
* Convenience method to move resources
*/
protected void moveResources(IResource[] resources, IPath container) throws ARESModelException {
IProgressMonitor subProgressMonitor = null;
if (this.progressMonitor != null) {
subProgressMonitor = new SubProgressMonitor(this.progressMonitor, resources.length, SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK);
}
IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
try {
for (int i = 0, length = resources.length; i < length; i++) {
IResource resource = resources[i];
IPath destination = container.append(resource.getName());
if (root.findMember(destination) == null) {
resource.move(destination, false, subProgressMonitor);
}
}
//setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE);
} catch (CoreException e) {
throw new ARESModelException(e);
}
}
/**
* Creates and returns a subprogress monitor if appropriate.
*/
protected IProgressMonitor getSubProgressMonitor(int workAmount) {
IProgressMonitor sub = null;
if (this.progressMonitor != null) {
sub = new SubProgressMonitor(this.progressMonitor, workAmount, SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK);
}
return sub;
}
/*
* Returns the scheduling rule for this operation (i.e. the resource that needs to be locked
* while this operation is running.
* Subclasses can override.
*/
protected ISchedulingRule getSchedulingRule() {
return ResourcesPlugin.getWorkspace().getRoot();
}
/**
* Returns <code>true</code> if this operation performs no resource modifications,
* otherwise <code>false</code>. Subclasses must override.
*/
public boolean isReadOnly() {
return false;
}
/**
* Returns a status indicating if there is any known reason
* this operation will fail. Operations are verified before they
* are run.
*
* Subclasses must override if they have any conditions to verify
* before this operation executes.
*
* @see IARESModelStatus
*/
protected IARESModelStatus verify() {
return commonVerify();
}
}