/*******************************************************************************
 * Copyright (c) 2000, 2004 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials 
 * are made available under the terms of the Common Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/cpl-v10.html
 * 
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.jdt.internal.core;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.*;

import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.jdt.core.*;
import org.eclipse.jdt.core.jdom.*;
import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
import org.eclipse.jdt.internal.core.util.Util;

/**
 * This operation copies/moves/renames a collection of resources from their current
 * container to a new container, optionally renaming the
 * elements.
 * <p>Notes:<ul>
 *    <li>If there is already an resource with the same name in
 *    the new container, the operation either overwrites or aborts,
 *    depending on the collision policy setting. The default setting is
 *	  abort.
 *
 *    <li>When a compilation unit is copied to a new package, the
 *    package declaration in the compilation unit is automatically updated.
 *
 *    <li>The collection of elements being copied must all share the
 *    same type of container.
 *
 *    <li>This operation can be used to copy and rename elements within
 *    the same container. 
 *
 *    <li>This operation only copies compilation units and package fragments.
 *    It does not copy package fragment roots - a platform operation must be used for that.
 * </ul>
 *
 */
public class CopyResourceElementsOperation extends MultiOperation implements SuffixConstants {
	/**
	 * The list of new resources created during this operation.
	 */
	protected ArrayList createdElements;
	/**
	 * Table specifying deltas for elements being 
	 * copied/moved/renamed. Keyed by elements' project(s), and
	 * values are the corresponding deltas.
	 */
	protected Map deltasPerProject = new HashMap(1);
	/**
	 * The <code>DOMFactory</code> used to manipulate the source code of
	 * <code>ICompilationUnit</code>.
	 * @deprecated JDOM is obsolete
	 */
    // TODO - JDOM - remove once model ported off of JDOM
	protected DOMFactory fFactory;
	/**
	 * A collection of renamed compilation units.  These cus do
	 * not need to be saved as they no longer exist.
	 */
	protected ArrayList fRenamedCompilationUnits = null;
	/**
	 * When executed, this operation will copy the given resources to the
	 * given container.
	 */
	public CopyResourceElementsOperation(IJavaElement[] resourcesToCopy, IJavaElement destContainer, boolean force) {
		this(resourcesToCopy, new IJavaElement[]{destContainer}, force);
	}
	/**
	 * When executed, this operation will copy the given resources to the
	 * given containers.  The resources and destination containers must be in
	 * the correct order. If there is > 1 destination, the number of destinations
	 * must be the same as the number of resources being copied/moved.
	 */
	public CopyResourceElementsOperation(IJavaElement[] resourcesToCopy, IJavaElement[] destContainers, boolean force) {
		super(resourcesToCopy, destContainers, force);
		initializeDOMFactory();
	}
	/**
	 * @deprecated marked deprecated to suppress JDOM-related deprecation warnings
	 */
    // TODO - JDOM - remove once model ported off of JDOM
	private void initializeDOMFactory() {
		fFactory = new DOMFactory();
	}
	/**
	 * Returns the children of <code>source</code> which are affected by this operation.
	 * If <code>source</code> is a <code>K_SOURCE</code>, these are the <code>.java</code>
	 * files, if it is a <code>K_BINARY</code>, they are the <code>.class</code> files.
	 */
	private IResource[] collectResourcesOfInterest(IPackageFragment source) throws JavaModelException {
		IJavaElement[] children = source.getChildren();
		int childOfInterest = IJavaElement.COMPILATION_UNIT;
		if (source.getKind() == IPackageFragmentRoot.K_BINARY) {
			childOfInterest = IJavaElement.CLASS_FILE;
		}
		ArrayList correctKindChildren = new ArrayList(children.length);
		for (int i = 0; i < children.length; i++) {
			IJavaElement child = children[i];
			if (child.getElementType() == childOfInterest) {
				correctKindChildren.add(child.getResource());
			}
		}
		// Gather non-java resources
		Object[] nonJavaResources = source.getNonJavaResources();
		int actualNonJavaResourceCount = 0;
		for (int i = 0, max = nonJavaResources.length; i < max; i++){
			if (nonJavaResources[i] instanceof IResource) actualNonJavaResourceCount++;
		}
		IResource[] actualNonJavaResources = new IResource[actualNonJavaResourceCount];
		for (int i = 0, max = nonJavaResources.length, index = 0; i < max; i++){
			if (nonJavaResources[i] instanceof IResource) actualNonJavaResources[index++] = (IResource)nonJavaResources[i];
		}
		
		if (actualNonJavaResourceCount != 0) {
			int correctKindChildrenSize = correctKindChildren.size();
			IResource[] result = new IResource[correctKindChildrenSize + actualNonJavaResourceCount];
			correctKindChildren.toArray(result);
			System.arraycopy(actualNonJavaResources, 0, result, correctKindChildrenSize, actualNonJavaResourceCount);
			return result;
		} else {
			IResource[] result = new IResource[correctKindChildren.size()];
			correctKindChildren.toArray(result);
			return result;
		}
	}
	/**
	 * Creates any destination package fragment(s) which do not exists yet.
	 * Return true if a read-only package fragment has been found among package fragments, false otherwise
	 */
	private boolean createNeededPackageFragments(IContainer sourceFolder, PackageFragmentRoot root, String[] newFragName, boolean moveFolder) throws JavaModelException {
		boolean containsReadOnlyPackageFragment = false;
		IContainer parentFolder = (IContainer) root.getResource();
		JavaElementDelta projectDelta = null;
		String[] sideEffectPackageName = null;
		char[][] inclusionPatterns = root.fullInclusionPatternChars();
		char[][] exclusionPatterns = root.fullExclusionPatternChars();
		for (int i = 0; i < newFragName.length; i++) {
			String subFolderName = newFragName[i];
			sideEffectPackageName = Util.arrayConcat(sideEffectPackageName, subFolderName);
			IResource subFolder = parentFolder.findMember(subFolderName);
			if (subFolder == null) {
				// create deepest folder only if not a move (folder will be moved in processPackageFragmentResource)
				if (!(moveFolder && i == newFragName.length-1)) {
					createFolder(parentFolder, subFolderName, force);
				}
				parentFolder = parentFolder.getFolder(new Path(subFolderName));
				sourceFolder = sourceFolder.getFolder(new Path(subFolderName));
				if (Util.isReadOnly(sourceFolder)) {
					containsReadOnlyPackageFragment = true;
				}
				IPackageFragment sideEffectPackage = root.getPackageFragment(sideEffectPackageName);
				if (i < newFragName.length - 1 // all but the last one are side effect packages
						&& !Util.isExcluded(parentFolder, inclusionPatterns, exclusionPatterns)) { 
					if (projectDelta == null) {
						projectDelta = getDeltaFor(root.getJavaProject());
					}
					projectDelta.added(sideEffectPackage);
				}
				createdElements.add(sideEffectPackage);
			} else {
				parentFolder = (IContainer) subFolder;
			}
		}
		return containsReadOnlyPackageFragment;
	}
	
	/**
	 * Returns the <code>JavaElementDelta</code> for <code>javaProject</code>,
	 * creating it and putting it in <code>fDeltasPerProject</code> if
	 * it does not exist yet.
	 */
	private JavaElementDelta getDeltaFor(IJavaProject javaProject) {
		JavaElementDelta delta = (JavaElementDelta) deltasPerProject.get(javaProject);
		if (delta == null) {
			delta = new JavaElementDelta(javaProject);
			deltasPerProject.put(javaProject, delta);
		}
		return delta;
	}
	/**
	 * @see MultiOperation
	 */
	protected String getMainTaskName() {
		return Util.bind("operation.copyResourceProgress"); //$NON-NLS-1$
	}
	/**
	 * Sets the deltas to register the changes resulting from this operation
	 * for this source element and its destination.
	 * If the operation is a cross project operation<ul>
	 * <li>On a copy, the delta should be rooted in the dest project
	 * <li>On a move, two deltas are generated<ul>
	 * 			<li>one rooted in the source project
	 *			<li>one rooted in the destination project</ul></ul>
	 * If the operation is rooted in a single project, the delta is rooted in that project
	 * 	 
	 */
	protected void prepareDeltas(IJavaElement sourceElement, IJavaElement destinationElement, boolean isMove) {
		if (Util.isExcluded(sourceElement) || Util.isExcluded(destinationElement)) return;
		IJavaProject destProject = destinationElement.getJavaProject();
		if (isMove) {
			IJavaProject sourceProject = sourceElement.getJavaProject();
			getDeltaFor(sourceProject).movedFrom(sourceElement, destinationElement);
			getDeltaFor(destProject).movedTo(destinationElement, sourceElement);
		} else {
			getDeltaFor(destProject).added(destinationElement);
		}
	}
	/**
	 * Copies/moves a compilation unit with the name <code>newCUName</code>
	 * to the destination package.<br>
	 * The package statement in the compilation unit is updated if necessary.
	 * The main type of the compilation unit is renamed if necessary.
	 *
	 * @exception JavaModelException if the operation is unable to
	 * complete
	 */
	private void processCompilationUnitResource(ICompilationUnit source, PackageFragment dest) throws JavaModelException {
		String newCUName = getNewNameFor(source);
		String destName = (newCUName != null) ? newCUName : source.getElementName();
		String newContent = updatedContent(source, dest, newCUName); // null if unchanged
	
		// TODO (frederic) remove when bug 67606 will be fixed (bug 67823)
		// store encoding (fix bug 66898)
		IFile sourceResource = (IFile)source.getResource();
		String sourceEncoding = null;
		try {
			sourceEncoding = sourceResource.getCharset(false);
		}
		catch (CoreException ce) {
			// no problem, use default encoding
		}
		// end todo
		// copy resource
		IContainer destFolder = (IContainer)dest.getResource(); // can be an IFolder or an IProject
		IFile destFile = destFolder.getFile(new Path(destName));
		if (!destFile.equals(sourceResource)) {
			try {
				if (destFile.exists()) {
					if (force) {
						// we can remove it
						deleteResource(destFile, IResource.KEEP_HISTORY);
					} else {
						// abort
						throw new JavaModelException(new JavaModelStatus(
							IJavaModelStatusConstants.NAME_COLLISION, 
							Util.bind("status.nameCollision", destFile.getFullPath().toString()))); //$NON-NLS-1$
					}
				}
				int flags = force ? IResource.FORCE : IResource.NONE;
				if (this.isMove()) {
					flags |= IResource.KEEP_HISTORY;
					sourceResource.move(destFile.getFullPath(), flags, getSubProgressMonitor(1));
				} else {
					if (newContent != null) flags |= IResource.KEEP_HISTORY;
					sourceResource.copy(destFile.getFullPath(), flags, getSubProgressMonitor(1));
				}
				this.setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE); 
			} catch (JavaModelException e) {
				throw e;
			} catch (CoreException e) {
				throw new JavaModelException(e);
			}
	
			// update new resource content
			if (newContent != null){
				boolean wasReadOnly = destFile.isReadOnly();
				try {
					String encoding = null;
					try {
						// TODO (frederic) remove when bug 67606 will be fixed (bug 67823)
						// fix bug 66898
						if (sourceEncoding != null) destFile.setCharset(sourceEncoding, this.progressMonitor);
						// end todo
						encoding = destFile.getCharset();
					}
					catch (CoreException ce) {
						// use no encoding
					}
					// when the file was copied, its read-only flag was preserved -> temporary set it to false
					// note this doesn't interfer with repository providers as this is a new resource that cannot be under
					// version control yet
					Util.setReadOnly(destFile, false);
					
					destFile.setContents(
						new ByteArrayInputStream(encoding == null ? newContent.getBytes() : newContent.getBytes(encoding)), 
						force ? IResource.FORCE | IResource.KEEP_HISTORY : IResource.KEEP_HISTORY,
						getSubProgressMonitor(1));
				} catch(IOException e) {
					throw new JavaModelException(e, IJavaModelStatusConstants.IO_EXCEPTION);
				} catch (CoreException e) {
					throw new JavaModelException(e);
				} finally {
					Util.setReadOnly(destFile, wasReadOnly);
				}
			}
		
			// register the correct change deltas
			ICompilationUnit destCU = dest.getCompilationUnit(destName);
			prepareDeltas(source, destCU, isMove());
			if (newCUName != null) {
				//the main type has been renamed
				String oldName = source.getElementName();
				oldName = oldName.substring(0, oldName.length() - 5);
				String newName = newCUName;
				newName = newName.substring(0, newName.length() - 5);
				prepareDeltas(source.getType(oldName), destCU.getType(newName), isMove());
			}
		} else {
			if (!force) {
				throw new JavaModelException(new JavaModelStatus(
					IJavaModelStatusConstants.NAME_COLLISION, 
					Util.bind("status.nameCollision", destFile.getFullPath().toString()))); //$NON-NLS-1$
			}
			// update new resource content
			// in case we do a saveas on the same resource we have to simply update the contents
			// see http://dev.eclipse.org/bugs/show_bug.cgi?id=9351
			try {
				if (newContent != null){
					String encoding = null;
					try {
						// TODO (frederic) remove when bug 67606 will be fixed (bug 67823)
						// fix bug 66898
						if (sourceEncoding != null) destFile.setCharset(sourceEncoding, this.progressMonitor);
						// end todo
						encoding = destFile.getCharset();
					}
					catch (CoreException ce) {
						// use no encoding
					}
					destFile.setContents(
						new ByteArrayInputStream(encoding == null ? newContent.getBytes() : newContent.getBytes(encoding)), 
						force ? IResource.FORCE | IResource.KEEP_HISTORY : IResource.KEEP_HISTORY, 
						getSubProgressMonitor(1));
				}
			} catch(IOException e) {
				throw new JavaModelException(e, IJavaModelStatusConstants.IO_EXCEPTION);
			} catch (CoreException e) {
				throw new JavaModelException(e);
			}
		}
	}
	/**
	 * Process all of the changed deltas generated by this operation.
	 */
	protected void processDeltas() {
		for (Iterator deltas = this.deltasPerProject.values().iterator(); deltas.hasNext();){
			addDelta((IJavaElementDelta) deltas.next());
		}
	}
	/**
	 * @see MultiOperation
	 * This method delegates to <code>processCompilationUnitResource</code> or
	 * <code>processPackageFragmentResource</code>, depending on the type of
	 * <code>element</code>.
	 */
	protected void processElement(IJavaElement element) throws JavaModelException {
		IJavaElement dest = getDestinationParent(element);
		switch (element.getElementType()) {
			case IJavaElement.COMPILATION_UNIT :
				processCompilationUnitResource((ICompilationUnit) element, (PackageFragment) dest);
				createdElements.add(((IPackageFragment) dest).getCompilationUnit(element.getElementName()));
				break;
			case IJavaElement.PACKAGE_FRAGMENT :
				processPackageFragmentResource((PackageFragment) element, (PackageFragmentRoot) dest, getNewNameFor(element));
				break;
			default :
				throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.INVALID_ELEMENT_TYPES, element));
		}
	}
	/**
	 * @see MultiOperation
	 * Overridden to allow special processing of <code>JavaElementDelta</code>s
	 * and <code>fResultElements</code>.
	 */
	protected void processElements() throws JavaModelException {
		createdElements = new ArrayList(elementsToProcess.length);
		try {
			super.processElements();
		} catch (JavaModelException jme) {
			throw jme;
		} finally {
			resultElements = new IJavaElement[createdElements.size()];
			createdElements.toArray(resultElements);
			processDeltas();
		}
	}
	/**
	 * Copies/moves a package fragment with the name <code>newName</code>
	 * to the destination package.<br>
	 *
	 * @exception JavaModelException if the operation is unable to
	 * complete
	 * @deprecated marked deprecated to suppress JDOM-related deprecation warnings
	 */
    // TODO - JDOM - remove once model ported off of JDOM
	private void processPackageFragmentResource(PackageFragment source, PackageFragmentRoot root, String newName) throws JavaModelException {
		try {
			String[] newFragName = (newName == null) ? source.names : Util.getTrimmedSimpleNames(newName);
			IPackageFragment newFrag = root.getPackageFragment(newFragName);
			IResource[] resources = collectResourcesOfInterest(source);
			
			// if isMove() can we move the folder itself ? (see http://bugs.eclipse.org/bugs/show_bug.cgi?id=22458)
			boolean shouldMoveFolder = isMove() && !newFrag.getResource().exists(); // if new pkg fragment exists, it is an override
			IFolder srcFolder = (IFolder)source.getResource();
			IPath destPath = newFrag.getPath();
			if (shouldMoveFolder) {
				// check if destination is not included in source
				if (srcFolder.getFullPath().isPrefixOf(destPath)) {
					shouldMoveFolder = false;
				} else {
					// check if there are no sub-packages
					IResource[] members = srcFolder.members();
					for (int i = 0; i < members.length; i++) {
						if ( members[i] instanceof IFolder) {
							shouldMoveFolder = false;
							break;
						}
					}
				}	
			}
			boolean containsReadOnlySubPackageFragments = createNeededPackageFragments((IContainer) source.getParent().getResource(), root, newFragName, shouldMoveFolder);
			boolean sourceIsReadOnly = srcFolder.isReadOnly();
	
			// Process resources
			if (shouldMoveFolder) {
				// move underlying resource
				// TODO Revisit once bug 43044 is fixed
				if (sourceIsReadOnly) {
					srcFolder.setReadOnly(false);
				}
				srcFolder.move(destPath, force, true /* keep history */, getSubProgressMonitor(1));
				if (sourceIsReadOnly) {
					srcFolder.setReadOnly(true);
				}
				this.setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE); 
			} else {
				// process the leaf resources
				if (resources.length > 0) {
					if (isRename()) {
						if (! destPath.equals(source.getPath())) {
							moveResources(resources, destPath);
						}
					} else if (isMove()) {
						// we need to delete this resource if this operation wants to override existing resources
						for (int i = 0, max = resources.length; i < max; i++) {
							IResource destinationResource = ResourcesPlugin.getWorkspace().getRoot().findMember(destPath.append(resources[i].getName()));
							if (destinationResource != null) {
								if (force) {
									deleteResource(destinationResource, IResource.KEEP_HISTORY);
								} else {
									throw new JavaModelException(new JavaModelStatus(
										IJavaModelStatusConstants.NAME_COLLISION, 
										Util.bind("status.nameCollision", destinationResource.getFullPath().toString()))); //$NON-NLS-1$
								}
							}
						}
						moveResources(resources, destPath);
					} else {
						// we need to delete this resource if this operation wants to override existing resources
						for (int i = 0, max = resources.length; i < max; i++) {
							IResource destinationResource = ResourcesPlugin.getWorkspace().getRoot().findMember(destPath.append(resources[i].getName()));
							if (destinationResource != null) {
								if (force) {
									// we need to delete this resource if this operation wants to override existing resources
									deleteResource(destinationResource, IResource.KEEP_HISTORY);
								} else {
									throw new JavaModelException(new JavaModelStatus(
										IJavaModelStatusConstants.NAME_COLLISION, 
										Util.bind("status.nameCollision", destinationResource.getFullPath().toString()))); //$NON-NLS-1$
								}
							}
						}
						copyResources(resources, destPath);
					}
				}
			}
	
			// Update package statement in compilation unit if needed
			if (!Util.equalArraysOrNull(newFragName, source.names)) { // if package has been renamed, update the compilation units
				char[][] inclusionPatterns = root.fullInclusionPatternChars();
				char[][] exclusionPatterns = root.fullExclusionPatternChars();
				for (int i = 0; i < resources.length; i++) {
					String resourceName = resources[i].getName();
					if (Util.isJavaLikeFileName(resourceName)) {
						// we only consider potential compilation units
						ICompilationUnit cu = newFrag.getCompilationUnit(resourceName);
						if (Util.isExcluded(cu.getPath(), inclusionPatterns, exclusionPatterns, false/*not a folder*/)) continue;
						IDOMCompilationUnit domCU = fFactory.createCompilationUnit(cu.getSource(), cu.getElementName());
						if (domCU != null) {
							updatePackageStatement(domCU, newFragName);
							IBuffer buffer = cu.getBuffer();
							if (buffer == null) continue;
							String bufferContents = buffer.getContents();
							if (bufferContents == null) continue;
							String domCUContents = domCU.getContents();
							String cuContents = null;
							if (domCUContents != null) {
								cuContents = Util.normalizeCRs(domCU.getContents(), bufferContents);
							} else {
								// See PR http://dev.eclipse.org/bugs/show_bug.cgi?id=11285
								cuContents = bufferContents;//$NON-NLS-1$
							}
							buffer.setContents(cuContents);
							cu.save(null, false);
						}
					}
				}
			}
			
			// Discard empty old package (if still empty after the rename)
			boolean isEmpty = true;
			if (isMove()) {
				// delete remaining files in this package (.class file in the case where Proj=src=bin)
				// in case of a copy
				updateReadOnlyPackageFragmentsForMove((IContainer) source.getParent().getResource(), root, newFragName, sourceIsReadOnly);
				if (srcFolder.exists()) {
					IResource[] remaining = srcFolder.members();
					for (int i = 0, length = remaining.length; i < length; i++) {
						IResource file = remaining[i];
						if (file instanceof IFile) {
							if (file.isReadOnly()) {
								file.setReadOnly(false);
							}
							this.deleteResource(file, IResource.FORCE | IResource.KEEP_HISTORY);
						} else {
							isEmpty = false;
						}
					}
				}
				if (isEmpty) {
					IResource rootResource;
					// check if source is included in destination
					if (destPath.isPrefixOf(srcFolder.getFullPath())) {
						rootResource = newFrag.getResource();
					} else {
						rootResource =  source.getParent().getResource();
					}
					
					// delete recursively empty folders
					deleteEmptyPackageFragment(source, false, rootResource);
				}
			} else if (containsReadOnlySubPackageFragments) {
				// in case of a copy
				updateReadOnlyPackageFragmentsForCopy((IContainer) source.getParent().getResource(), root, newFragName);
			}
			// workaround for bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=24505
			if (isEmpty && isMove() && !(Util.isExcluded(source) || Util.isExcluded(newFrag))) {
				IJavaProject sourceProject = source.getJavaProject();
				getDeltaFor(sourceProject).movedFrom(source, newFrag);
				IJavaProject destProject = newFrag.getJavaProject();
				getDeltaFor(destProject).movedTo(newFrag, source);
			}
		} catch (DOMException dom) {
			throw new JavaModelException(dom, IJavaModelStatusConstants.DOM_EXCEPTION);
		} catch (JavaModelException e) {
			throw e;
		} catch (CoreException ce) {
			throw new JavaModelException(ce);
		}
	}
	/**
	 * Updates the content of <code>cu</code>, modifying the type name and/or package
	 * declaration as necessary.
	 *
	 * @return the new source
	 * @deprecated marked deprecated to suppress JDOM-related deprecation warnings
	 */
    // TODO - JDOM - remove once model ported off of JDOM
	private String updatedContent(ICompilationUnit cu, PackageFragment dest, String newName) throws JavaModelException {
		String[] currPackageName = ((PackageFragment) cu.getParent()).names;
		String[] destPackageName = dest.names;
		if (Util.equalArraysOrNull(currPackageName, destPackageName) && newName == null) {
			return null; //nothing to change
		} else {
			String typeName = cu.getElementName();
			typeName = typeName.substring(0, typeName.length() - 5);
			IDOMCompilationUnit cuDOM = null;
			IBuffer buffer = cu.getBuffer();
			if (buffer == null) return null;
			char[] contents = buffer.getCharacters();
			if (contents == null) return null;
			cuDOM = fFactory.createCompilationUnit(contents, typeName);
			updateTypeName(cu, cuDOM, cu.getElementName(), newName);
			updatePackageStatement(cuDOM, destPackageName);
			return cuDOM.getContents();
		}
	}
	/**
	 * Makes sure that <code>cu</code> declares to be in the <code>pkgName</code> package.
	 * @deprecated marked deprecated to suppress JDOM-related deprecation warnings
	 */
    // TODO - JDOM - remove once model ported off of JDOM
	private void updatePackageStatement(IDOMCompilationUnit domCU, String[] pkgName) {
		boolean defaultPackage = pkgName.length == 0;
		boolean seenPackageNode = false;
		Enumeration nodes = domCU.getChildren();
		while (nodes.hasMoreElements()) {
			IDOMNode node = (IDOMNode) nodes.nextElement();
			if (node.getNodeType() == IDOMNode.PACKAGE) {
				if (! defaultPackage) {
					node.setName(Util.concatWith(pkgName, '.'));
				} else {
					node.remove();
				}
				seenPackageNode = true;
				break;
			}
		}
		if (!seenPackageNode && !defaultPackage) {
			//the cu was in a default package...no package declaration
			//create the new package declaration as the first child of the cu
			IDOMPackage pkg = fFactory.createPackage("package " + Util.concatWith(pkgName, '.') + ";" + org.eclipse.jdt.internal.compiler.util.Util.LINE_SEPARATOR); //$NON-NLS-1$ //$NON-NLS-2$
			IDOMNode firstChild = domCU.getFirstChild();
			if (firstChild != null) {
				firstChild.insertSibling(pkg);
			} // else the cu was empty: leave it empty
		}
	}
	
	private void updateReadOnlyPackageFragmentsForCopy(IContainer sourceFolder, IPackageFragmentRoot root, String[] newFragName) {
		IContainer parentFolder = (IContainer) root.getResource();
		for (int i = 0, length = newFragName.length; i <length; i++) {
			String subFolderName = newFragName[i];
			parentFolder = parentFolder.getFolder(new Path(subFolderName));
			sourceFolder = sourceFolder.getFolder(new Path(subFolderName));
			if (sourceFolder.exists() && Util.isReadOnly(sourceFolder)) {
				Util.setReadOnly(parentFolder, true);
			}
		}
	}

	private void updateReadOnlyPackageFragmentsForMove(IContainer sourceFolder, IPackageFragmentRoot root, String[] newFragName, boolean sourceFolderIsReadOnly) {
		IContainer parentFolder = (IContainer) root.getResource();
		for (int i = 0, length = newFragName.length; i < length; i++) {
			String subFolderName = newFragName[i];
			parentFolder = parentFolder.getFolder(new Path(subFolderName));
			sourceFolder = sourceFolder.getFolder(new Path(subFolderName));
			if ((sourceFolder.exists() && Util.isReadOnly(sourceFolder)) || (i == length - 1 && sourceFolderIsReadOnly)) {
				Util.setReadOnly(parentFolder, true);
				// the source folder will be deleted anyway (move operation)
				Util.setReadOnly(sourceFolder, false);
			}
		}
	}
		/**
		 * Renames the main type in <code>cu</code>.
	     * @deprecated marked deprecated to suppress JDOM-related deprecation warnings
		 */
        // TODO - JDOM - remove once model ported off of JDOM
		private void updateTypeName(ICompilationUnit cu, IDOMCompilationUnit domCU, String oldName, String newName) throws JavaModelException {
			if (newName != null) {
				if (fRenamedCompilationUnits == null) {
					fRenamedCompilationUnits= new ArrayList(1);
				}
				fRenamedCompilationUnits.add(cu);
				String oldTypeName= oldName.substring(0, oldName.length() - 5);
				String newTypeName= newName.substring(0, newName.length() - 5);
				// update main type name
				IType[] types = cu.getTypes();
				for (int i = 0, max = types.length; i < max; i++) {
					IType currentType = types[i];
					if (currentType.getElementName().equals(oldTypeName)) {
						IDOMNode typeNode = ((JavaElement) currentType).findNode(domCU);
						if (typeNode != null) {
							typeNode.setName(newTypeName);
						}
					}
				}
			}
		}
	/**
	 * Possible failures:
	 * <ul>
	 *  <li>NO_ELEMENTS_TO_PROCESS - no elements supplied to the operation
	 *	<li>INDEX_OUT_OF_BOUNDS - the number of renamings supplied to the operation
	 *		does not match the number of elements that were supplied.
	 * </ul>
	 */
	protected IJavaModelStatus verify() {
		IJavaModelStatus status = super.verify();
		if (!status.isOK()) {
			return status;
		}
	
		if (this.renamingsList != null && this.renamingsList.length != elementsToProcess.length) {
			return new JavaModelStatus(IJavaModelStatusConstants.INDEX_OUT_OF_BOUNDS);
		}
		return JavaModelStatus.VERIFIED_OK;
	}
	/**
	 * @see MultiOperation
	 */
	protected void verify(IJavaElement element) throws JavaModelException {
		if (element == null || !element.exists())
			error(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST, element);
			
		if (element.isReadOnly() && (isRename() || isMove()))
			error(IJavaModelStatusConstants.READ_ONLY, element);

		IResource resource = element.getResource();
		if (resource instanceof IFolder) {
			if (resource.isLinked()) {
				error(IJavaModelStatusConstants.INVALID_RESOURCE, element);
			}
		}
	
		int elementType = element.getElementType();
	
		if (elementType == IJavaElement.COMPILATION_UNIT) {
			CompilationUnit compilationUnit = (CompilationUnit)element;
			if (isMove() && compilationUnit.isWorkingCopy() && !compilationUnit.isPrimary())
				error(IJavaModelStatusConstants.INVALID_ELEMENT_TYPES, element);
		} else if (elementType != IJavaElement.PACKAGE_FRAGMENT) {
			error(IJavaModelStatusConstants.INVALID_ELEMENT_TYPES, element);
		}
		
		JavaElement dest = (JavaElement) getDestinationParent(element);
		verifyDestination(element, dest);
		if (this.renamings != null) {
			verifyRenaming(element);
		}
}
}
