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);
 }
  /**
   * 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);
    }
  }
  /**
   * 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);
      }
    }
  }