//------------------------------------------------------------------------------
// Copyright (c) 2005, 2006 IBM Corporation and others.
// 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:
// IBM Corporation - initial implementation
//------------------------------------------------------------------------------
package org.eclipse.epf.library.edit.process.command;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Status;
import org.eclipse.emf.common.notify.AdapterFactory;
import org.eclipse.emf.common.util.AbstractTreeIterator;
import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.xml.type.XMLTypePackage.Literals;
import org.eclipse.emf.edit.provider.ITreeItemContentProvider;
import org.eclipse.epf.library.edit.IConfigurator;
import org.eclipse.epf.library.edit.LibraryEditPlugin;
import org.eclipse.epf.library.edit.LibraryEditResources;
import org.eclipse.epf.library.edit.TngAdapterFactory;
import org.eclipse.epf.library.edit.ui.IActionTypeProvider;
import org.eclipse.epf.library.edit.ui.UserInteractionHelper;
import org.eclipse.epf.library.edit.util.ActivityHandler;
import org.eclipse.epf.library.edit.util.ExtensionManager;
import org.eclipse.epf.library.edit.util.IResourceScanner;
import org.eclipse.epf.library.edit.util.IRunnableWithProgress;
import org.eclipse.epf.library.edit.util.ITextReferenceReplacer;
import org.eclipse.epf.library.edit.util.ProcessUtil;
import org.eclipse.epf.library.edit.util.ResourceFileCopyHandler;
import org.eclipse.epf.library.edit.util.Suppression;
import org.eclipse.epf.library.edit.util.TngUtil;
import org.eclipse.epf.library.edit.validation.DependencyChecker;
import org.eclipse.epf.uma.Activity;
import org.eclipse.epf.uma.BreakdownElement;
import org.eclipse.epf.uma.CapabilityPattern;
import org.eclipse.epf.uma.DeliveryProcess;
import org.eclipse.epf.uma.DescribableElement;
import org.eclipse.epf.uma.Descriptor;
import org.eclipse.epf.uma.MethodConfiguration;
import org.eclipse.epf.uma.MethodElement;
import org.eclipse.epf.uma.MethodPackage;
import org.eclipse.epf.uma.MethodPlugin;
import org.eclipse.epf.uma.Process;
import org.eclipse.epf.uma.ProcessPackage;
import org.eclipse.epf.uma.TeamProfile;
import org.eclipse.epf.uma.util.UmaUtil;


/**
 * Drop command for activity that supports extend, copy, and deep copy.
 * 
 * @author Phong Nguyen Le
 * @since 1.0
 */
public class ActivityDropCommand extends BSDropCommand {

	private Object viewer;

	private List<CapabilityPattern> oldPatterns;

	private List<CapabilityPattern> patterns;

	protected Process targetProcess;

	private boolean isDeliveryProcess;

	private int type;
	
	private Collection<Activity> appliedActivities;

	protected AdapterFactory adapterFactory;

	protected ActivityHandler activityHandler;

	protected boolean preExecuted;

	protected HashSet<?> addedObjects;
	
	protected IConfigurator activityDeepCopyConfigurator;
	
	private ResourceFileCopyHandler resourceFileCopyHandler;

	public ActivityDropCommand(Activity target, List activities, Object viewer, AdapterFactory adapterFactory) {
		super(target, activities);
		setLabel(LibraryEditResources.ActivityDropCommand_label); 
		this.viewer = viewer;
		this.adapterFactory = adapterFactory;
		targetProcess = TngUtil.getOwningProcess(target);
		
		isDeliveryProcess = targetProcess instanceof DeliveryProcess;
		if (isDeliveryProcess) {
			oldPatterns = new ArrayList(((DeliveryProcess) targetProcess)
					.getIncludesPatterns());
		}
		
		initResouceFileCopyHandler(activities);
		
	}

	private void initResouceFileCopyHandler(List activities) {
		if (activities != null && ! activities.isEmpty() &&
				 activities.get(0) instanceof BreakdownElement) {
			BreakdownElement dropElement0 = (BreakdownElement) activities.get(0);
			
			MethodPlugin srcPlugin = UmaUtil.getMethodPlugin(targetProcess);
			MethodPlugin tgtPlugin = UmaUtil.getMethodPlugin(dropElement0);
			
			boolean toCreateHandler = true;
			if (srcPlugin == tgtPlugin) {
				Process sourceProcess = TngUtil.getOwningProcess(dropElement0);
				boolean sIsDeliveryProcess = sourceProcess instanceof DeliveryProcess;
				if (isDeliveryProcess == sIsDeliveryProcess) {
					toCreateHandler = false;
				}
			}
			
			if (toCreateHandler) {
				ITextReferenceReplacer txtRefReplacer = ExtensionManager.getTextReferenceReplacer();
				if (txtRefReplacer != null) {
					IResourceScanner resourceScanner = txtRefReplacer.getResourceScanner();				
					resourceScanner.init(srcPlugin, tgtPlugin);				
					resourceFileCopyHandler = new ResourceFileCopyHandler(resourceScanner);
				}
			}
		}
	}

		
	/**
	 * If textual descriptions in the copied elements contain references (URLs)
	 * to other elements within the same copied process then replace these
	 * references with references that point to the new elements in the copied
	 * structures.
	 */
	private Collection replaceTextReferences(Map<MethodElement, MethodElement> originalToCopyMap_
			) {
		Collection modifiedResources = new HashSet();
		ITextReferenceReplacer txtRefReplacer = ExtensionManager
				.getTextReferenceReplacer();
		if (txtRefReplacer == null)
			return modifiedResources;
		
		for (Map.Entry<MethodElement, MethodElement> entry: originalToCopyMap_.entrySet()) {		
			if (entry.getValue() instanceof BreakdownElement) {
				EObject element = (EObject) entry.getValue();
				for (Iterator childIter = element.eAllContents(); childIter
						.hasNext();) {
					EObject child = (EObject) childIter.next();
					for (Iterator attributes = child.eClass()
							.getEAllAttributes().iterator(); attributes
							.hasNext();) {
						EAttribute attribute = (EAttribute) attributes.next();
						if (attribute.isChangeable()
								&& !attribute.isDerived()
								&& (attribute.isMany() || child
										.eIsSet(attribute))
								&& attribute.getEAttributeType()
										.getInstanceClass() == Literals.STRING
										.getInstanceClass()) {
							String text = (String) child.eGet(attribute);
							if (text != null) {
								String newtext = txtRefReplacer.replace(text,
										child, originalToCopyMap_);
								if (!newtext.equals(text)) {
									child.eSet(attribute, newtext);
									modifiedResources.add(child.eResource());
								}
							}
						}
					}
				}
			}		
		}
		originalToCopyMap_ = null;
		return modifiedResources;
	}
	
	
	public ActivityDropCommand(Activity target, List activities, Object viewer, 
			AdapterFactory adapterFactory,IConfigurator deepCopyConfigurator){
		this(target, activities, viewer, adapterFactory);
		this.activityDeepCopyConfigurator = deepCopyConfigurator;
	}
	
	@Override
	protected void prepareDropElements() {
		// remove any drop element that is suppress
		//
		for (Iterator<?> iter = dropElements.iterator(); iter.hasNext();) {
			Object element = (Object) iter.next();
			Process proc = TngUtil.getOwningProcess(element);
			if(proc != null) {
				Suppression supp = Suppression.getSuppression(proc);
				if(supp.isSuppressed(element)) {
					iter.remove();
				}
			}
		}

		super.prepareDropElements();		
	}
	
	public void setType(int type) {
		this.type = type;
		if(type == IActionTypeProvider.DEEP_COPY) {
			runAsJob = true;
		}
	}
	
	public IStatus checkCopy() {
		for (Object e : dropElements) {
			if(e instanceof Activity) {
				IStatus status = checkCircular((Activity) e);
				if(!status.isOK()) {
					return status;
				}
			}
		}
		return Status.OK_STATUS;
	}
	
	public IStatus checkExtend() {
		for (Iterator iter = dropElements.iterator(); iter.hasNext();) {
//			BreakdownElement element = (BreakdownElement) iter.next();
//			
//			if ((ProcessUtil.hasContributorOrReplacer((Activity) element))){
//				canExtend = false;
//				break;
//			}
//			
//			Process proc = TngUtil.getOwningProcess(element);
//			if (targetProcess.getVariabilityBasedOnElement() == proc) {
//				canExtend = false;
//				break;
//			}
//			
//			if (proc instanceof CapabilityPattern && proc != targetProcess) {
//				canExtend = true;
//				break;
//			}
			
			Activity act = (Activity) iter.next();
			Process srcProc = TngUtil.getOwningProcess(act);
			if(srcProc instanceof DeliveryProcess && srcProc != targetProcess) {
				// cannot extend a different delivery process or any of its activities
				//
				return new Status(IStatus.ERROR, LibraryEditPlugin.PLUGIN_ID, 0,
						LibraryEditResources.cannot_copy_or_extend_delivery_process,
						null);
			}
			IStatus status = checkCircular(act);
			if(!status.isOK()) {
				return status;
			}
		}
		return Status.OK_STATUS;
	}
	
	private IStatus checkCircular(Activity act) {
		boolean result;
		if (DependencyChecker.newCheckAct) {
			result = DependencyChecker.checkCircularForMovingVariabilityElement
							(activity, Collections.singletonList(act), true);
		} else {
			result = DependencyChecker.checkCircularDependency(act, activity).isOK();
		}
		if(!result) {
			return new Status(IStatus.ERROR, LibraryEditPlugin.PLUGIN_ID, 0,
					LibraryEditResources.circular_dependency_error_msg,
					null);
		}
		return Status.OK_STATUS;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.ibm.library.edit.process.command.BSDropCommand#execute()
	 */
	public void execute() {
		IActionTypeProvider actionTypeProvider = (IActionTypeProvider) viewer;
		if ( viewer != null) {
			viewer = null;
			boolean canCopy = checkCopy().isOK();
			boolean canExtend = checkExtend().isOK();
			int[] choices = new int[1 + (canCopy ? 1 : 0) + (canExtend ? 1 : 0)];
			int i = 0;
			if(canCopy) {
				choices[i++] = IActionTypeProvider.COPY;
			}
			if(canExtend) {
				choices[i++] = IActionTypeProvider.EXTEND;
			}
			choices[i] = IActionTypeProvider.DEEP_COPY;
			
			// delegate the execution of this command
			//
			actionTypeProvider.execute(this, choices);

			return;
		}

		activityHandler = new ActivityHandler();
		try {
			if (type == IActionTypeProvider.DEEP_COPY) {
				doDeepCopy();
			} else {
				super.execute();
			}
		} finally {			
			originalToCopyMap = activityHandler.cloneOrignaltoCopyMap();
			activityHandler.dispose();
		}
		
		if (type == IActionTypeProvider.COPY) {
			replaceTextReferences(originalToCopyMap);
		}
		
		
		if(TngUtil.DEBUG) {
			System.out.println("ActivityDropCommand.execute(): done"); //$NON-NLS-1$
		}
	}

	/**
	 * 
	 */
	protected void doDeepCopy() {
		if(!UserInteractionHelper.confirmDeepCopy(dropElements)) {
			return;
		}
		MethodConfiguration deepCopyConfig = null;
		try {
			deepCopyConfig = UserInteractionHelper.chooseDeepCopyConfiguration(targetProcess, adapterFactory);
		}
		catch(OperationCanceledException e) {
			getModifiedResources().clear();
			return;
		}
		
		boolean copyExternalVariations;
		try {
			copyExternalVariations = UserInteractionHelper.copyExternalVariationsAllowed(targetProcess, adapterFactory);
		}
		catch(OperationCanceledException e) {
			getModifiedResources().clear();
			return;			
		}
		activityHandler.setCopyExternalVariations(copyExternalVariations);
		activityHandler.setDeepCopyConfig(deepCopyConfig);
		activityHandler.setTargetProcess(targetProcess);
		
		// Set a configurator to resolve and deep copy contributors and replacers
		activityHandler.setActivityDeepCopyConfigurator(activityDeepCopyConfigurator);
		
		IRunnableWithProgress runnable = new IRunnableWithProgress() {

			public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
				activityHandler.setMonitor(monitor);
				preExecuted = preExecute();
			}
			
		};
		UserInteractionHelper.runWithProgress(runnable, getLabel());			
		if (preExecuted) {
			redo();
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.ibm.library.edit.process.command.BSDropCommand#preExecute()
	 */
	protected boolean preExecute() {
		if (!super.preExecute())
			return false;

		// process the selected activities and deep-copy the valid ones
		//
		if (isDeliveryProcess) {
			patterns = new ArrayList<CapabilityPattern>();
		}
		
		for (Iterator iter = dropElements.iterator(); iter.hasNext();) {
			Object element = (Object) iter.next();
			if ((element instanceof Activity)
			// && element != target
			) {
				Activity act = (Activity) element;
				
//				if(type == IActionTypeProvider.DEEP_COPY) {
//					activityHandler.deepCopy(act);
//				}
//				else {
//					Process proc = TngUtil.getOwningProcess(act);
//					if (proc instanceof CapabilityPattern && proc != targetProcess) {
//						if (type == IActionTypeProvider.EXTEND) {
//							activityHandler.extend(act);
//							if (patterns != null)
//								patterns.add(proc);
//						} else {
//							activityHandler.copy(act);
//						}
//					} else {
//						activityHandler.copy(act);
//					}
//				}
				
				switch(type) {
				case IActionTypeProvider.DEEP_COPY:
					activityHandler.deepCopy(element);
					break;
				case IActionTypeProvider.EXTEND:
					activityHandler.extend(act);
					if (patterns != null) {
						Process proc = TngUtil.getOwningProcess(act);
						if(proc instanceof CapabilityPattern) {
							patterns.add((CapabilityPattern) proc);
						}
					}
					break;
				case IActionTypeProvider.COPY:
					activityHandler.copy(act);
					break;
				}
			}
		}

		appliedActivities = new ArrayList<Activity>(activityHandler.getActivities());

		return !appliedActivities.isEmpty();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.ibm.library.edit.process.command.BSDropCommand#doExecute()
	 */
	protected void doExecute() {
		Iterator<Activity> itor = appliedActivities.iterator();

		ProcessPackage pkg = (ProcessPackage) activity.eContainer();
		while (itor.hasNext()) {
			Activity act = (Activity) itor.next();

			if (act.eContainer() != null
					&& act.eContainer().eContainer() != pkg) {
				pkg.getChildPackages().add((MethodPackage) act.eContainer());
			}

			if (patterns != null && !patterns.isEmpty()) {
				DeliveryProcess proc = (DeliveryProcess) targetProcess;
				for (CapabilityPattern pattern : patterns) {
					if (!proc.getIncludesPatterns().contains(pattern)) {
						proc.getIncludesPatterns().add(pattern);
					}
				}
			}
		}
		long time = 0;
		if(TngUtil.DEBUG) {
			time = System.currentTimeMillis();
		}
		activity.getBreakdownElements().addAll(appliedActivities);
		if(TngUtil.DEBUG) {
			System.out.println("ActivityDropCommand.doExecute(): new activities added. " + (System.currentTimeMillis() - time)); //$NON-NLS-1$
		}
		if(!activityHandler.getDeepCopies().isEmpty()) {
			if(TngUtil.DEBUG) {
				time = System.currentTimeMillis();
			}
			postDeepCopy();
			if(TngUtil.DEBUG) {
				System.out.println("ActivityDropCommand.doExecute(): postDeepCopy(). " + (System.currentTimeMillis() - time)); //$NON-NLS-1$
			}
		}

		// Hack to refresh providers forcefully before calling fixDuplicateNames
		ITreeItemContentProvider adapter = (ITreeItemContentProvider) adapterFactory.adapt(activity, ITreeItemContentProvider.class);
		adapter.getChildren(activity);
		
		// fix duplicate names of newly added elements
		fixDuplicateNames();
		
		getModifiedResources().add(activity.eResource());
	}

	/**
	 * 
	 */
	private void postDeepCopy() {
		Runnable runnable = new Runnable() {

			public void run() {
				// add to default configuratation of the target process any missing content
				//
				if(addedObjects == null) {
					addedObjects = new HashSet();
				}
				else {
					addedObjects.clear();
				}
				boolean defaultConfigChanged = false;
//				// disable notification on change to default configuration of target process to avoid excessive UI refreshes
//				//
//				boolean oldNotify = targetProcess.getDefaultContext().eDeliver();
//				targetProcess.getDefaultContext().eSetDeliver(false);
//				try {
				for (Iterator iter = activityHandler.getDeepCopies().iterator(); iter.hasNext();) {
					Iterator iterator = new AbstractTreeIterator(iter.next()) {

						/**
						 * Comment for <code>serialVersionUID</code>
						 */
						private static final long serialVersionUID = 1L;

						protected Iterator getChildren(Object object) {
							if(object instanceof Activity) {
								return ((Activity)object).getBreakdownElements().iterator();
							}
							return Collections.EMPTY_LIST.iterator();
						}

					};					
					while(iterator.hasNext()) {
						Object e = iterator.next();
						if(e instanceof Descriptor) {
							MethodElement me = ProcessUtil.getAssociatedElement((Descriptor) e);
							int size = addedObjects.size();
							ProcessUtil.addToDefaultConfiguration(targetProcess, me, addedObjects);
							if(!defaultConfigChanged && (size != addedObjects.size())) {
								getModifiedResources().add(targetProcess.getDefaultContext().eResource());
								defaultConfigChanged = true;
							}
						}
					}
				}
//				}
//				finally {
//					targetProcess.getDefaultContext().eSetDeliver(oldNotify);
//				}
			}
			
		};
		
		UserInteractionHelper.runWithProgress(runnable, getLabel());
		
		// synchronize the deep copies with default configuration of the target process				
		//
		final SynchronizeCommand synchCmd = new SynchronizeCommand(activityHandler.getDeepCopies(), targetProcess.getDefaultContext(), null, false);
		try {
			runnable = new Runnable() {

				public void run() {
					synchCmd.initilize();
				}
				
			};
			UserInteractionHelper.runWithProgress(runnable, LibraryEditResources.ProcessAutoSynchronizeAction_prepare);
			if(synchCmd.isIntialized()) {
				synchCmd.execute();
			}
		}
		finally {
			synchCmd.dispose();
		}
	}
	
	protected Suppression getSuppression() {
		return Suppression.getSuppression(targetProcess);
	}

	/**
	 * Fixes duplicate names of newly added elements
	 */
	private void fixDuplicateNames() {
		Suppression suppression = getSuppression();
		for (Iterator iter = appliedActivities.iterator(); iter.hasNext();) {
			Activity act = (Activity) iter.next();
			fixDuplicateNames(act, suppression);
			fixTeamProfileDuplicateNames(act, suppression);
		}			
	}
	
	private void fixDuplicateNames(BreakdownElement e, Suppression suppression) {
		fixDuplicateNames(e, suppression, adapterFactory);
	}
	
	private static void fixDuplicateNames(BreakdownElement e, Suppression suppression, AdapterFactory adapterFactory) {
		String baseName = e.getName();
		if (ProcessUtil.checkBreakdownElementName(adapterFactory, e, baseName, suppression) != null) {
			for (int i = 1; true; i++) {
				String name = baseName + '_' + i;
				if (ProcessUtil.checkBreakdownElementName(adapterFactory, e, name, suppression) == null) {
					e.setName(name);
					break;
				}
			}
		}
		baseName = ProcessUtil.getPresentationName(e);
		if (ProcessUtil.checkBreakdownElementPresentationName(adapterFactory, e, baseName, suppression) != null) {
			for (int i = 1; true; i++) {
				String name = baseName + '_' + i;
				if (ProcessUtil.checkBreakdownElementPresentationName(adapterFactory, e, name, suppression) == null) {
					e.setPresentationName(name);
					break;
				}
			}
		}
	}		
	
	private void fixTeamProfileDuplicateNames(Activity act, Suppression suppression) {
		for (int i = act.getBreakdownElements().size() - 1; i > -1; i--) {
			Object element = act.getBreakdownElements().get(i);
			if(element instanceof TeamProfile) {
				fixDuplicateNames((BreakdownElement) element, suppression, TngAdapterFactory.INSTANCE.getOBS_ComposedAdapterFactory());
			}
			else if(element instanceof Activity) {
				fixTeamProfileDuplicateNames((Activity) element, suppression);
			}
		}
	}
		

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.ibm.library.edit.process.command.BSDropCommand#doUndo()
	 */
	protected void doUndo() {
		activity.getBreakdownElements().removeAll(appliedActivities);
		if (isDeliveryProcess) {
			DeliveryProcess proc = (DeliveryProcess) targetProcess;
			proc.getIncludesPatterns().clear();
			proc.getIncludesPatterns().addAll(oldPatterns);
		}
	}

	public static void setName(List siblings, Activity e) {
		String baseName = e.getName();
		if (!isNameTaken(siblings, e, baseName)) {
			return;
		}
		for (int i = 1; true; i++) {
			String name = baseName + '_' + i;
			if (!isNameTaken(siblings, e, name)) {
				e.setName(name);
				return;
			}
		}
	}

	public static void setDefaultPresentationName(List siblings, Activity e) {
		// if(e.getPresentationName() != null &&
		// e.getPresentationName().trim().length() > 0) return;

		String basePresentationName = ProcessUtil.getPresentationName(e);
		if (!isPresentationNameTaken(siblings, e, basePresentationName)) {
			// e.setPresentationName(basePresentationName);
			return;
		}
		for (int i = 1; true; i++) {
			String name = basePresentationName + '_' + i;
			if (!isPresentationNameTaken(siblings, e, name)) {
				e.setPresentationName(name);
				return;
			}
		}
	}

	private static boolean isNameTaken(List siblings, DescribableElement e,
			String name) {
		for (int i = siblings.size() - 1; i > -1; i--) {
			BreakdownElement sibling = (BreakdownElement) siblings.get(i);
			// if(sibling != e && name.equals(sibling.getPresentationName())) {
			if (sibling != e && name.equals(sibling.getName())) {
				return true;
			}
		}
		return false;
	}

	private static boolean isPresentationNameTaken(List siblings,
			DescribableElement e, String name) {
		for (int i = siblings.size() - 1; i > -1; i--) {
			BreakdownElement sibling = (BreakdownElement) siblings.get(i);
			// if(sibling != e && name.equals(sibling.getPresentationName())) {
			if (sibling != e
					&& name.equals(ProcessUtil.getPresentationName(sibling))) {
				return true;
			}
		}
		return false;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.emf.common.command.AbstractCommand#getAffectedObjects()
	 */
	public Collection<?> getAffectedObjects() {
		if(executed) {
			return appliedActivities;
		}
		else {
			return Collections.EMPTY_LIST;
		}
	}
	
	/* (non-Javadoc)
	 * @see org.eclipse.emf.common.command.AbstractCommand#getResult()
	 */
	public Collection<?> getResult() {
		return getAffectedObjects();
	}

	public ActivityHandler getActivityHandler() {
		return activityHandler;
	}
	public Activity getActivity(){
		return activity;
	}
	public int getType(){
		return type;
	}

	public void setActivityDeepCopyConfigurator(
			IConfigurator activityDeepCopyConfigurator) {
		this.activityDeepCopyConfigurator = activityDeepCopyConfigurator;
	}
	
	private Map originalToCopyMap;
	
	public void scanAndCopyResources() {
		if (resourceFileCopyHandler == null) {
			return;
		}
		try {
			resourceFileCopyHandler.execute(originalToCopyMap);
		} catch (Throwable e){
			LibraryEditPlugin.getDefault().getLogger().logError(e);
		} finally {
			resourceFileCopyHandler.getScanner().init(null, null);
			originalToCopyMap = null;
		}
	}

	public ResourceFileCopyHandler getResourceFileCopyHandler() {
		return resourceFileCopyHandler;
	}
	
}