private static boolean copyOneClass(Map<PsiFile, PsiClass[]> classes) {
   if (classes.size() == 1) {
     final PsiClass[] psiClasses = classes.values().iterator().next();
     return psiClasses != null && psiClasses.length == 1;
   }
   return false;
 }
 @Override
 public boolean forbidToClone(PsiElement[] elements, boolean fromUpdate) {
   final Map<PsiFile, PsiClass[]> fileMap =
       convertToTopLevelClasses(elements, fromUpdate, null, null);
   if (fileMap != null && fileMap.size() == 1) {
     final PsiClass[] psiClasses = fileMap.values().iterator().next();
     return psiClasses != null && psiClasses.length > 1;
   }
   return true;
 }
  @Nullable
  public static PsiElement doCopyClasses(
      final Map<PsiFile, PsiClass[]> fileToClasses,
      @Nullable HashMap<PsiFile, String> map,
      final String copyClassName,
      final PsiDirectory targetDirectory,
      final Project project)
      throws IncorrectOperationException {
    PsiElement newElement = null;
    final Map<PsiClass, PsiElement> oldToNewMap = new HashMap<PsiClass, PsiElement>();
    for (final PsiClass[] psiClasses : fileToClasses.values()) {
      if (psiClasses != null) {
        for (PsiClass aClass : psiClasses) {
          if (aClass instanceof SyntheticElement) {
            continue;
          }
          oldToNewMap.put(aClass, null);
        }
      }
    }
    final List<PsiFile> createdFiles = new ArrayList<PsiFile>(fileToClasses.size());
    int[] choice = fileToClasses.size() > 1 ? new int[] {-1} : null;
    List<PsiFile> files = new ArrayList<PsiFile>();
    for (final Map.Entry<PsiFile, PsiClass[]> entry : fileToClasses.entrySet()) {
      final PsiFile psiFile = entry.getKey();
      final PsiClass[] sources = entry.getValue();
      if (psiFile instanceof PsiClassOwner && sources != null) {
        final PsiFile createdFile =
            copy(
                psiFile,
                targetDirectory,
                copyClassName,
                map == null ? null : map.get(psiFile),
                choice);
        if (createdFile == null) return null;
        for (final PsiClass destination : ((PsiClassOwner) createdFile).getClasses()) {
          if (destination instanceof SyntheticElement) {
            continue;
          }
          PsiClass source = findByName(sources, destination.getName());
          if (source != null) {
            final PsiClass copy = copy(source, copyClassName);
            newElement = destination.replace(copy);
            oldToNewMap.put(source, newElement);
          } else {
            destination.delete();
          }
        }
        createdFiles.add(createdFile);
      } else {
        files.add(psiFile);
      }
    }

    for (PsiFile file : files) {
      try {
        PsiDirectory finalTarget = targetDirectory;
        final String relativePath = map != null ? map.get(file) : null;
        if (relativePath != null && !relativePath.isEmpty()) {
          finalTarget =
              buildRelativeDir(targetDirectory, relativePath).findOrCreateTargetDirectory();
        }
        final PsiFile fileCopy =
            CopyFilesOrDirectoriesHandler.copyToDirectory(
                file, getNewFileName(file, copyClassName), finalTarget, choice);
        if (fileCopy != null) {
          createdFiles.add(fileCopy);
        }
      } catch (IOException e) {
        throw new IncorrectOperationException(e.getMessage());
      }
    }

    final Set<PsiElement> rebindExpressions = new HashSet<PsiElement>();
    for (PsiElement element : oldToNewMap.values()) {
      if (element == null) {
        LOG.error(oldToNewMap.keySet());
        continue;
      }
      decodeRefs(element, oldToNewMap, rebindExpressions);
    }

    final JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(project);
    for (PsiFile psiFile : createdFiles) {
      if (psiFile instanceof PsiJavaFile) {
        codeStyleManager.removeRedundantImports((PsiJavaFile) psiFile);
      }
    }
    for (PsiElement expression : rebindExpressions) {
      codeStyleManager.shortenClassReferences(expression);
    }
    new OptimizeImportsProcessor(
            project, createdFiles.toArray(new PsiFile[createdFiles.size()]), null)
        .run();
    return newElement != null ? newElement : createdFiles.size() > 0 ? createdFiles.get(0) : null;
  }