public void run(ISelection selection) {

    String errorTitle = CompareMessages.AddFromHistory_title;
    String errorMessage = CompareMessages.AddFromHistory_internalErrorMessage;
    Shell shell = getShell();

    ICompilationUnit cu = null;
    IParent parent = null;
    IMember input = null;

    // analyze selection
    if (selection.isEmpty()) {
      // no selection: we try to use the editor's input
      JavaEditor editor = getEditor();
      if (editor != null) {
        IEditorInput editorInput = editor.getEditorInput();
        IWorkingCopyManager manager = JavaPlugin.getDefault().getWorkingCopyManager();
        if (manager != null) {
          cu = manager.getWorkingCopy(editorInput);
          parent = cu;
        }
      }
    } else {
      input = getEditionElement(selection);
      if (input != null) {
        cu = input.getCompilationUnit();
        parent = input;
        input = null;

      } else {
        if (selection instanceof IStructuredSelection) {
          Object o = ((IStructuredSelection) selection).getFirstElement();
          if (o instanceof ICompilationUnit) {
            cu = (ICompilationUnit) o;
            parent = cu;
          }
        }
      }
    }

    if (parent == null || cu == null) {
      String invalidSelectionMessage = CompareMessages.AddFromHistory_invalidSelectionMessage;
      MessageDialog.openInformation(shell, errorTitle, invalidSelectionMessage);
      return;
    }

    IFile file = getFile(parent);
    if (file == null) {
      MessageDialog.openError(shell, errorTitle, errorMessage);
      return;
    }

    boolean inEditor = beingEdited(file);

    IStatus status = Resources.makeCommittable(file, shell);
    if (!status.isOK()) {
      return;
    }

    // get the document where to insert the text
    IPath path = file.getFullPath();
    ITextFileBufferManager bufferManager = FileBuffers.getTextFileBufferManager();
    ITextFileBuffer textFileBuffer = null;
    try {
      bufferManager.connect(path, LocationKind.IFILE, null);
      textFileBuffer = bufferManager.getTextFileBuffer(path, LocationKind.IFILE);
      IDocument document = textFileBuffer.getDocument();

      // configure EditionSelectionDialog and let user select an edition
      ITypedElement target = new JavaTextBufferNode(file, document, inEditor);
      ITypedElement[] editions = buildEditions(target, file);

      ResourceBundle bundle = ResourceBundle.getBundle(BUNDLE_NAME);
      EditionSelectionDialog d = new EditionSelectionDialog(shell, bundle);
      d.setAddMode(true);
      d.setHelpContextId(IJavaHelpContextIds.ADD_ELEMENT_FROM_HISTORY_DIALOG);
      ITypedElement selected = d.selectEdition(target, editions, parent);
      if (selected == null) return; // user cancel

      ICompilationUnit cu2 = cu;
      if (parent instanceof IMember) cu2 = ((IMember) parent).getCompilationUnit();

      CompilationUnit root = parsePartialCompilationUnit(cu2);
      ASTRewrite rewriter = ASTRewrite.create(root.getAST());

      ITypedElement[] results = d.getSelection();
      for (int i = 0; i < results.length; i++) {

        // create an AST node
        ASTNode newNode =
            createASTNode(
                rewriter,
                results[i],
                TextUtilities.getDefaultLineDelimiter(document),
                cu.getJavaProject());
        if (newNode == null) {
          MessageDialog.openError(shell, errorTitle, errorMessage);
          return;
        }

        // now determine where to put the new node
        if (newNode instanceof PackageDeclaration) {
          rewriter.set(root, CompilationUnit.PACKAGE_PROPERTY, newNode, null);

        } else if (newNode instanceof ImportDeclaration) {
          ListRewrite lw = rewriter.getListRewrite(root, CompilationUnit.IMPORTS_PROPERTY);
          lw.insertFirst(newNode, null);

        } else { // class, interface, enum, annotation, method, field

          if (parent instanceof ICompilationUnit) { // top level
            ListRewrite lw = rewriter.getListRewrite(root, CompilationUnit.TYPES_PROPERTY);
            int index = ASTNodes.getInsertionIndex((BodyDeclaration) newNode, root.types());
            lw.insertAt(newNode, index, null);

          } else if (parent instanceof IType) {
            ASTNode declaration = getBodyContainer(root, (IType) parent);
            if (declaration instanceof TypeDeclaration
                || declaration instanceof AnnotationTypeDeclaration) {
              List container = ASTNodes.getBodyDeclarations(declaration);
              int index = ASTNodes.getInsertionIndex((BodyDeclaration) newNode, container);
              ListRewrite lw =
                  rewriter.getListRewrite(
                      declaration, ASTNodes.getBodyDeclarationsProperty(declaration));
              lw.insertAt(newNode, index, null);
            } else if (declaration instanceof EnumDeclaration) {
              List container = ((EnumDeclaration) declaration).enumConstants();
              int index = ASTNodes.getInsertionIndex((FieldDeclaration) newNode, container);
              ListRewrite lw =
                  rewriter.getListRewrite(declaration, EnumDeclaration.ENUM_CONSTANTS_PROPERTY);
              lw.insertAt(newNode, index, null);
            }
          } else {
            JavaPlugin.logErrorMessage(
                "JavaAddElementFromHistoryImpl: unknown container " + parent); // $NON-NLS-1$
          }
        }
      }

      Map options = null;
      IJavaProject javaProject = cu2.getJavaProject();
      if (javaProject != null) options = javaProject.getOptions(true);
      applyChanges(rewriter, document, textFileBuffer, shell, inEditor, options);

    } catch (InvocationTargetException ex) {
      ExceptionHandler.handle(ex, shell, errorTitle, errorMessage);

    } catch (InterruptedException ex) {
      // shouldn't be called because is not cancelable
      Assert.isTrue(false);

    } catch (CoreException ex) {
      ExceptionHandler.handle(ex, shell, errorTitle, errorMessage);

    } finally {
      try {
        if (textFileBuffer != null) bufferManager.disconnect(path, LocationKind.IFILE, null);
      } catch (CoreException e) {
        JavaPlugin.log(e);
      }
    }
  }
 public void perform() {
   ASTNode cuNode = ASTNodes.getParent(fTempDeclaration, CompilationUnit.class);
   cuNode.accept(this);
 }