@Nullable
  private XmlFile createAnnotationsXml(
      @NotNull VirtualFile root, @NonNls @NotNull String packageName) {
    final String[] dirs = packageName.split("[\\.]");
    for (String dir : dirs) {
      if (dir.isEmpty()) break;
      VirtualFile subdir = root.findChild(dir);
      if (subdir == null) {
        try {
          subdir = root.createChildDirectory(null, dir);
        } catch (IOException e) {
          LOG.error(e);
        }
      }
      root = subdir;
    }
    final PsiDirectory directory = myPsiManager.findDirectory(root);
    if (directory == null) return null;

    final PsiFile psiFile = directory.findFile(ANNOTATIONS_XML);
    if (psiFile instanceof XmlFile) {
      return (XmlFile) psiFile;
    }

    try {
      final PsiFileFactory factory = PsiFileFactory.getInstance(myPsiManager.getProject());
      return (XmlFile)
          directory.add(
              factory.createFileFromText(ANNOTATIONS_XML, XmlFileType.INSTANCE, "<root></root>"));
    } catch (IncorrectOperationException e) {
      LOG.error(e);
    }
    return null;
  }
  protected void performRefactoring(
      Project project,
      PsiDirectory directory,
      PsiPackage aPackage,
      boolean searchInComments,
      boolean searchForTextOccurences) {
    final VirtualFile sourceRoot =
        ProjectRootManager.getInstance(project)
            .getFileIndex()
            .getSourceRootForFile(directory.getVirtualFile());
    if (sourceRoot == null) {
      Messages.showErrorDialog(
          project,
          RefactoringBundle.message("destination.directory.does.not.correspond.to.any.package"),
          RefactoringBundle.message("cannot.move"));
      return;
    }
    final JavaRefactoringFactory factory = JavaRefactoringFactory.getInstance(project);
    final MoveDestination destination =
        myPreserveSourceRoot.isSelected() && myPreserveSourceRoot.isVisible()
            ? factory.createSourceFolderPreservingMoveDestination(aPackage.getQualifiedName())
            : factory.createSourceRootMoveDestination(aPackage.getQualifiedName(), sourceRoot);

    MoveClassesOrPackagesProcessor processor =
        new MoveClassesOrPackagesProcessor(
            myDirectory.getProject(),
            myElementsToMove,
            destination,
            searchInComments,
            searchForTextOccurences,
            myMoveCallback);
    if (processor.verifyValidPackageName()) {
      processor.run();
    }
  }
  protected void doOKAction() {
    final String path = FileUtil.toSystemIndependentName(myDestDirectoryField.getText());
    final Project project = myDirectory.getProject();
    PsiDirectory directory =
        ApplicationManager.getApplication()
            .runWriteAction(
                new Computable<PsiDirectory>() {
                  public PsiDirectory compute() {
                    try {
                      return DirectoryUtil.mkdirs(PsiManager.getInstance(project), path);
                    } catch (IncorrectOperationException e) {
                      LOG.error(e);
                      return null;
                    }
                  }
                });
    if (directory == null) {
      Messages.showErrorDialog(
          project,
          RefactoringBundle.message("cannot.find.or.create.destination.directory"),
          RefactoringBundle.message("cannot.move"));
      return;
    }

    super.doOKAction();
    final PsiPackage aPackage = JavaDirectoryService.getInstance().getPackage(directory);
    if (aPackage == null) {
      Messages.showErrorDialog(
          project,
          RefactoringBundle.message("destination.directory.does.not.correspond.to.any.package"),
          RefactoringBundle.message("cannot.move"));
      return;
    }

    final JavaRefactoringSettings refactoringSettings = JavaRefactoringSettings.getInstance();
    final boolean searchInComments = isSearchInComments();
    final boolean searchForTextOccurences = isSearchInNonJavaFiles();
    refactoringSettings.MOVE_SEARCH_IN_COMMENTS = searchInComments;
    refactoringSettings.MOVE_SEARCH_FOR_TEXT = searchForTextOccurences;

    performRefactoring(project, directory, aPackage, searchInComments, searchForTextOccurences);
  }
  @NotNull
  private static PsiClass createBeanClass(final WizardData wizardData) throws MyException {
    final PsiManager psiManager = PsiManager.getInstance(wizardData.myProject);

    final ProjectRootManager projectRootManager =
        ProjectRootManager.getInstance(wizardData.myProject);
    final ProjectFileIndex fileIndex = projectRootManager.getFileIndex();
    final VirtualFile sourceRoot = fileIndex.getSourceRootForFile(wizardData.myFormFile);
    if (sourceRoot == null) {
      throw new MyException(UIDesignerBundle.message("error.form.file.is.not.in.source.root"));
    }

    final PsiDirectory rootDirectory = psiManager.findDirectory(sourceRoot);
    LOG.assertTrue(rootDirectory != null);

    final PsiPackage aPackage =
        JavaPsiFacade.getInstance(psiManager.getProject()).findPackage(wizardData.myPackageName);
    if (aPackage == null) {
      throw new MyException(
          UIDesignerBundle.message("error.package.does.not.exist", wizardData.myPackageName));
    }

    PsiDirectory targetDir = null;

    final PsiDirectory[] directories = aPackage.getDirectories();
    for (final PsiDirectory psiDirectory : directories) {
      if (PsiTreeUtil.isAncestor(rootDirectory, psiDirectory, false)) {
        targetDir = psiDirectory;
        break;
      }
    }

    if (targetDir == null) {
      // todo
      throw new MyException(
          UIDesignerBundle.message("error.cannot.find.package", wizardData.myPackageName));
    }

    //noinspection HardCodedStringLiteral
    final String body =
        "public class "
            + wizardData.myShortClassName
            + "{\n"
            + "public "
            + wizardData.myShortClassName
            + "(){}\n"
            + "}";

    try {
      PsiFile sourceFile =
          PsiFileFactory.getInstance(psiManager.getProject())
              .createFileFromText(wizardData.myShortClassName + ".java", body);
      sourceFile = (PsiFile) targetDir.add(sourceFile);

      final PsiClass beanClass = ((PsiJavaFile) sourceFile).getClasses()[0];

      final ArrayList<String> properties = new ArrayList<String>();
      final HashMap<String, String> property2fqClassName = new HashMap<String, String>();

      final FormProperty2BeanProperty[] bindings = wizardData.myBindings;
      for (final FormProperty2BeanProperty binding : bindings) {
        if (binding == null || binding.myBeanProperty == null) {
          continue;
        }

        properties.add(binding.myBeanProperty.myName);

        // todo: handle "casts" ?

        final String propertyClassName = binding.myFormProperty.getComponentPropertyClassName();

        property2fqClassName.put(binding.myBeanProperty.myName, propertyClassName);
      }

      generateBean(beanClass, ArrayUtil.toStringArray(properties), property2fqClassName);

      return beanClass;
    } catch (IncorrectOperationException e) {
      throw new MyException(e.getMessage());
    }
  }
  public MoveClassesOrPackagesToNewDirectoryDialog(
      @NotNull final PsiDirectory directory,
      PsiElement[] elementsToMove,
      boolean canShowPreserveSourceRoots,
      final MoveCallback moveCallback) {
    super(false);
    setTitle(MoveHandler.REFACTORING_NAME);
    myDirectory = directory;
    myElementsToMove = elementsToMove;
    myMoveCallback = moveCallback;
    myDestDirectoryField.setText(
        FileUtil.toSystemDependentName(directory.getVirtualFile().getPath()));
    final FileChooserDescriptor descriptor =
        new FileChooserDescriptor(false, true, false, false, false, false);
    myDestDirectoryField
        .getButton()
        .addActionListener(
            new ActionListener() {
              public void actionPerformed(ActionEvent e) {
                final VirtualFile[] files =
                    FileChooser.chooseFiles(
                        myDirectory.getProject(), descriptor, directory.getVirtualFile());
                if (files.length == 1) {
                  myDestDirectoryField.setText(FileUtil.toSystemDependentName(files[0].getPath()));
                }
              }
            });
    if (elementsToMove.length == 1) {
      PsiElement firstElement = elementsToMove[0];
      myNameLabel.setText(
          RefactoringBundle.message(
              "move.single.class.or.package.name.label",
              UsageViewUtil.getType(firstElement),
              UsageViewUtil.getLongName(firstElement)));
    } else if (elementsToMove.length > 1) {
      myNameLabel.setText(
          elementsToMove[0] instanceof PsiClass
              ? RefactoringBundle.message("move.specified.classes")
              : RefactoringBundle.message("move.specified.packages"));
    }
    final JavaRefactoringSettings refactoringSettings = JavaRefactoringSettings.getInstance();
    mySearchInCommentsAndStringsCheckBox.setSelected(refactoringSettings.MOVE_SEARCH_IN_COMMENTS);
    mySearchForTextOccurrencesCheckBox.setSelected(refactoringSettings.MOVE_SEARCH_FOR_TEXT);

    myDestDirectoryField
        .getTextField()
        .getDocument()
        .addDocumentListener(
            new DocumentAdapter() {
              public void textChanged(DocumentEvent event) {
                setOKActionEnabled(myDestDirectoryField.getText().length() > 0);
              }
            });

    if (canShowPreserveSourceRoots) {
      final Set<VirtualFile> sourceRoots = new HashSet<VirtualFile>();
      final ProjectFileIndex fileIndex =
          ProjectRootManager.getInstance(directory.getProject()).getFileIndex();
      for (PsiElement element : elementsToMove) {
        if (element instanceof PsiPackage) {
          for (PsiDirectory psiDirectory : ((PsiPackage) element).getDirectories()) {
            sourceRoots.add(fileIndex.getSourceRootForFile(psiDirectory.getVirtualFile()));
          }
        } else if (element instanceof PsiClass) {
          final PsiDirectory psiDirectory = element.getContainingFile().getContainingDirectory();
          LOG.assertTrue(psiDirectory != null);
          if (psiDirectory != null) {
            sourceRoots.add(psiDirectory.getVirtualFile());
          }
        }
      }
      myPreserveSourceRoot.setVisible(sourceRoots.size() > 1);
    }
    init();
  }