/*******************************************************************************
 * Copyright (c) 2000, 2011 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 API and implementation
 *******************************************************************************/
package org.eclipse.jdt.internal.core;

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.core.runtime.jobs.ISchedulingRule;
import org.eclipse.core.runtime.jobs.MultiRule;
import org.eclipse.jdt.core.*;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.ASTParser;
import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.Javadoc;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.Name;
import org.eclipse.jdt.core.dom.PackageDeclaration;
import org.eclipse.jdt.core.dom.SimpleName;
import org.eclipse.jdt.core.dom.rewrite.ASTRewrite;
import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
import org.eclipse.jdt.internal.core.util.Messages;
import org.eclipse.jdt.internal.core.util.Util;
import org.eclipse.text.edits.TextEdit;

/**
 * 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>ASTParser</code> used to manipulate the source code of
	 * <code>ICompilationUnit</code>.
	 */
	protected ASTParser parser;
	/**
	 * 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);
		initializeASTParser();
	}
	private void initializeASTParser() {
		this.parser = ASTParser.newParser(AST.JLS4);
	}
	/**
	 * 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(((JavaElement) child).resource());
			}
		}
		// 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.resource();
		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, this.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);
				}
				this.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) this.deltasPerProject.get(javaProject);
		if (delta == null) {
			delta = new JavaElementDelta(javaProject);
			this.deltasPerProject.put(javaProject, delta);
		}
		return delta;
	}
	/**
	 * @see MultiOperation
	 */
	protected String getMainTaskName() {
		return Messages.operation_copyResourceProgress;
	}
	protected ISchedulingRule getSchedulingRule() {
		if (this.elementsToProcess == null)
			return null;
		int length = this.elementsToProcess.length;
		if (length == 1)
			return getSchedulingRule(this.elementsToProcess[0]);
		ISchedulingRule[] rules = new ISchedulingRule[length];
		int index = 0;
		for (int i = 0; i < length; i++) {
			ISchedulingRule rule = getSchedulingRule(this.elementsToProcess[i]);
			if (rule != null) {
				rules[index++] = rule;
			}
		}
		if (index != length)
			System.arraycopy(rules, 0, rules = new ISchedulingRule[index], 0, index);
		return new MultiRule(rules);
	}
	private ISchedulingRule getSchedulingRule(IJavaElement element) {
		if (element == null)
			return null;
		IResource sourceResource = getResource(element);
		IResource destContainer = getResource(getDestinationParent(element));
		if (!(destContainer instanceof IContainer)) {
			return null;
		}
		String newName;
		try {
			newName = getNewNameFor(element);
		} catch (JavaModelException e) {
			return null;
		}
		if (newName == null)
			newName = element.getElementName();
		IResource destResource;
		String sourceEncoding = null;
		if (sourceResource.getType() == IResource.FILE) {
			destResource = ((IContainer) destContainer).getFile(new Path(newName));
			try {
				sourceEncoding = ((IFile) sourceResource).getCharset(false);
			} catch (CoreException ce) {
				// use default encoding
			}
		} else {
			destResource = ((IContainer) destContainer).getFolder(new Path(newName));
		}
		IResourceRuleFactory factory = ResourcesPlugin.getWorkspace().getRuleFactory();
		ISchedulingRule rule;
		if (isMove()) {
			rule = factory.moveRule(sourceResource, destResource);
		} else {
			rule = factory.copyRule(sourceResource, destResource);
		}
		if (sourceEncoding != null) {
			rule = new MultiRule(new ISchedulingRule[] {rule, factory.charsetRule(destResource)});
		}
		return rule;
	}
	private IResource getResource(IJavaElement element) {
		if (element == null)
			return null;
		if (element.getElementType() == IJavaElement.PACKAGE_FRAGMENT) {
			String pkgName = element.getElementName();
			int firstDot = pkgName.indexOf('.');
			if (firstDot != -1) {
				element = ((IPackageFragmentRoot) element.getParent()).getPackageFragment(pkgName.substring(0, firstDot));
			}
		}
		return element.getResource();
	}
	/**
	 * 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();
		TextEdit edit = updateContent(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));
		org.eclipse.jdt.internal.core.CompilationUnit destCU = new org.eclipse.jdt.internal.core.CompilationUnit(dest, destName, DefaultWorkingCopyOwner.PRIMARY);
		if (!destFile.equals(sourceResource)) {
			try {
				if (!destCU.isWorkingCopy()) {
					if (destFile.exists()) {
						if (this.force) {
							// we can remove it
							deleteResource(destFile, IResource.KEEP_HISTORY);
							destCU.close(); // ensure the in-memory buffer for the dest CU is closed
						} else {
							// abort
							throw new JavaModelException(new JavaModelStatus(
								IJavaModelStatusConstants.NAME_COLLISION,
								Messages.bind(Messages.status_nameCollision, destFile.getFullPath().toString())));
						}
					}
					int flags = this.force ? IResource.FORCE : IResource.NONE;
					if (isMove()) {
						flags |= IResource.KEEP_HISTORY;
						sourceResource.move(destFile.getFullPath(), flags, getSubProgressMonitor(1));
					} else {
						if (edit != null) flags |= IResource.KEEP_HISTORY;
						sourceResource.copy(destFile.getFullPath(), flags, getSubProgressMonitor(1));
					}
					setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE);
				} else {
					destCU.getBuffer().setContents(source.getBuffer().getContents());
				}
			} catch (JavaModelException e) {
				throw e;
			} catch (CoreException e) {
				throw new JavaModelException(e);
			}

			// update new resource content
			if (edit != null){
				boolean wasReadOnly = destFile.isReadOnly();
				try {
					saveContent(dest, destName, edit, sourceEncoding, destFile);
				} catch (CoreException e) {
					if (e instanceof JavaModelException) throw (JavaModelException) e;
					throw new JavaModelException(e);
				} finally {
					Util.setReadOnly(destFile, wasReadOnly);
				}
			}

			// register the correct change deltas
			prepareDeltas(source, destCU, isMove());
			if (newCUName != null) {
				//the main type has been renamed
				String oldName = Util.getNameWithoutJavaLikeExtension(source.getElementName());
				String newName = Util.getNameWithoutJavaLikeExtension(newCUName);
				prepareDeltas(source.getType(oldName), destCU.getType(newName), isMove());
			}
		} else {
			if (!this.force) {
				throw new JavaModelException(new JavaModelStatus(
					IJavaModelStatusConstants.NAME_COLLISION,
					Messages.bind(Messages.status_nameCollision, destFile.getFullPath().toString())));
			}
			// 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
			if (edit != null){
				saveContent(dest, destName, edit, sourceEncoding, destFile);
			}
		}
	}
	/**
	 * 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);
				this.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 {
		this.createdElements = new ArrayList(this.elementsToProcess.length);
		try {
			super.processElements();
		} catch (JavaModelException jme) {
			throw jme;
		} finally {
			this.resultElements = new IJavaElement[this.createdElements.size()];
			this.createdElements.toArray(this.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
	 */
	private void processPackageFragmentResource(PackageFragment source, PackageFragmentRoot root, String newName) throws JavaModelException {
		try {
			String[] newFragName = (newName == null) ? source.names : Util.getTrimmedSimpleNames(newName);
			PackageFragment 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.resource().exists(); // if new pkg fragment exists, it is an override
			IFolder srcFolder = (IFolder)source.resource();
			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.parent.resource(), root, newFragName, shouldMoveFolder);
			boolean sourceIsReadOnly = Util.isReadOnly(srcFolder);

			// Process resources
			if (shouldMoveFolder) {
				// move underlying resource
				// TODO Revisit once bug 43044 is fixed
				if (sourceIsReadOnly) {
					Util.setReadOnly(srcFolder, false);
				}
				srcFolder.move(destPath, this.force, true /* keep history */, getSubProgressMonitor(1));
				if (sourceIsReadOnly) {
					Util.setReadOnly(srcFolder, true);
				}
				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 (this.force) {
									deleteResource(destinationResource, IResource.KEEP_HISTORY);
								} else {
									throw new JavaModelException(new JavaModelStatus(
										IJavaModelStatusConstants.NAME_COLLISION,
										Messages.bind(Messages.status_nameCollision, destinationResource.getFullPath().toString())));
								}
							}
						}
						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 (this.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,
										Messages.bind(Messages.status_nameCollision, destinationResource.getFullPath().toString())));
								}
							}
						}
						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;
						this.parser.setSource(cu);
						CompilationUnit astCU = (CompilationUnit) this.parser.createAST(this.progressMonitor);
						AST ast = astCU.getAST();
						ASTRewrite rewrite = ASTRewrite.create(ast);
						updatePackageStatement(astCU, newFragName, rewrite, cu);
						TextEdit edits = rewrite.rewriteAST();
						applyTextEdit(cu, edits);
						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.parent.resource(), 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 (Util.isReadOnly(file)) {
								Util.setReadOnly(file, false);
							}
							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.resource();
					} else {
						rootResource =  source.parent.resource();
					}

					// delete recursively empty folders
					deleteEmptyPackageFragment(source, false, rootResource);
				}
			} else if (containsReadOnlySubPackageFragments) {
				// in case of a copy
				updateReadOnlyPackageFragmentsForCopy((IContainer) source.parent.resource(), 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 (JavaModelException e) {
			throw e;
		} catch (CoreException ce) {
			throw new JavaModelException(ce);
		}
	}
	private void saveContent(PackageFragment dest, String destName, TextEdit edits, String sourceEncoding, IFile destFile) throws JavaModelException {
		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
		}
		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 interfere with repository providers as this is a new resource that cannot be under
		// version control yet
		Util.setReadOnly(destFile, false);
		ICompilationUnit destCU = dest.getCompilationUnit(destName);
		applyTextEdit(destCU, edits);
		destCU.save(getSubProgressMonitor(1), this.force);
	}
	/**
	 * Updates the content of <code>cu</code>, modifying the type name and/or package
	 * declaration as necessary.
	 *
	 * @return an AST rewrite or null if no rewrite needed
	 */
	private TextEdit updateContent(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 {
			// ensure cu is consistent (noop if already consistent)
			cu.makeConsistent(this.progressMonitor);
			this.parser.setSource(cu);
			CompilationUnit astCU = (CompilationUnit) this.parser.createAST(this.progressMonitor);
			AST ast = astCU.getAST();
			ASTRewrite rewrite = ASTRewrite.create(ast);
			updateTypeName(cu, astCU, cu.getElementName(), newName, rewrite);
			updatePackageStatement(astCU, destPackageName, rewrite, cu);
			return rewrite.rewriteAST();
		}
	}
	private void updatePackageStatement(CompilationUnit astCU, String[] pkgName, ASTRewrite rewriter, ICompilationUnit cu) throws JavaModelException {
		boolean defaultPackage = pkgName.length == 0;
		AST ast = astCU.getAST();
		if (defaultPackage) {
			// remove existing package statement
			PackageDeclaration pkg = astCU.getPackage();
			if (pkg != null) {
				int pkgStart;
				Javadoc javadoc = pkg.getJavadoc();
				if (javadoc != null) {
					pkgStart = javadoc.getStartPosition() + javadoc.getLength() + 1;
				} else {
					pkgStart = pkg.getStartPosition();
				}
				int extendedStart = astCU.getExtendedStartPosition(pkg);
				if (pkgStart != extendedStart) {
					// keep the comments associated with package declaration
					// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=247757
					String commentSource = cu.getSource().substring(extendedStart, pkgStart);
					ASTNode comment = rewriter.createStringPlaceholder(commentSource, ASTNode.PACKAGE_DECLARATION);
					rewriter.set(astCU, CompilationUnit.PACKAGE_PROPERTY, comment, null);
				} else {
					rewriter.set(astCU, CompilationUnit.PACKAGE_PROPERTY, null, null);
				}
			}
		} else {
			org.eclipse.jdt.core.dom.PackageDeclaration pkg = astCU.getPackage();
			if (pkg != null) {
				// rename package statement
				Name name = ast.newName(pkgName);
				rewriter.set(pkg, PackageDeclaration.NAME_PROPERTY, name, null);
			} else {
				// create new package statement
				pkg = ast.newPackageDeclaration();
				pkg.setName(ast.newName(pkgName));
				rewriter.set(astCU, CompilationUnit.PACKAGE_PROPERTY, pkg, null);
			}
		}
	}

	private void updateReadOnlyPackageFragmentsForCopy(IContainer sourceFolder, PackageFragmentRoot root, String[] newFragName) {
		IContainer parentFolder = (IContainer) root.resource();
		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, PackageFragmentRoot root, String[] newFragName, boolean sourceFolderIsReadOnly) {
		IContainer parentFolder = (IContainer) root.resource();
		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>.
		 */
		private void updateTypeName(ICompilationUnit cu, CompilationUnit astCU, String oldName, String newName, ASTRewrite rewriter) throws JavaModelException {
			if (newName != null) {
				String oldTypeName= Util.getNameWithoutJavaLikeExtension(oldName);
				String newTypeName= Util.getNameWithoutJavaLikeExtension(newName);
				AST ast = astCU.getAST();
				// 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)) {
						AbstractTypeDeclaration typeNode = (AbstractTypeDeclaration) ((JavaElement) currentType).findNode(astCU);
						if (typeNode != null) {
							// rename type
							rewriter.replace(typeNode.getName(), ast.newSimpleName(newTypeName), null);
							// rename constructors
							Iterator bodyDeclarations = typeNode.bodyDeclarations().iterator();
							while (bodyDeclarations.hasNext()) {
								Object bodyDeclaration = bodyDeclarations.next();
								if (bodyDeclaration instanceof MethodDeclaration) {
									MethodDeclaration methodDeclaration = (MethodDeclaration) bodyDeclaration;
									if (methodDeclaration.isConstructor()) {
										SimpleName methodName = methodDeclaration.getName();
										if (methodName.getIdentifier().equals(oldTypeName)) {
											rewriter.replace(methodName, ast.newSimpleName(newTypeName), null);
										}
									}
								}
							}
						}
					}
				}
			}
		}
	/**
	 * 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 != this.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 = ((JavaElement) element).resource();
		if (resource instanceof IFolder) {
			if (resource.isLinked()) {
				error(IJavaModelStatusConstants.INVALID_RESOURCE, element);
			}
		}

		int elementType = element.getElementType();

		if (elementType == IJavaElement.COMPILATION_UNIT) {
			org.eclipse.jdt.internal.core.CompilationUnit compilationUnit = (org.eclipse.jdt.internal.core.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);
		}
}
}
