MNGECLIPSE-2690 create new framework for doing large scale edits of multiple pom files. using wst's IDOMModel. solves problems with long undo chains, shall be reusable for both in-editor and outside-of-editor changes.
diff --git a/org.eclipse.m2e.editor/src/org/eclipse/m2e/editor/composites/DependenciesComposite.java b/org.eclipse.m2e.editor/src/org/eclipse/m2e/editor/composites/DependenciesComposite.java
index 83ba71d..42eb461 100644
--- a/org.eclipse.m2e.editor/src/org/eclipse/m2e/editor/composites/DependenciesComposite.java
+++ b/org.eclipse.m2e.editor/src/org/eclipse/m2e/editor/composites/DependenciesComposite.java
@@ -697,7 +697,7 @@
     }
     
     final ManageDependenciesDialog manageDepDialog = new ManageDependenciesDialog(getShell(), model, hierarchy,
-        pomEditor.getEditingDomain(), dependenciesEditor.getSelection());
+        dependenciesEditor.getSelection());
     manageDepDialog.open();
   }
 
diff --git a/org.eclipse.m2e.editor/src/org/eclipse/m2e/editor/dialogs/ManageDependenciesDialog.java b/org.eclipse.m2e.editor/src/org/eclipse/m2e/editor/dialogs/ManageDependenciesDialog.java
index 4781492..6ea84a0 100644
--- a/org.eclipse.m2e.editor/src/org/eclipse/m2e/editor/dialogs/ManageDependenciesDialog.java
+++ b/org.eclipse.m2e.editor/src/org/eclipse/m2e/editor/dialogs/ManageDependenciesDialog.java
@@ -43,6 +43,7 @@
 import org.eclipse.m2e.editor.MavenEditorPlugin;
 import org.eclipse.m2e.editor.composites.DependencyLabelProvider;
 import org.eclipse.m2e.editor.composites.ListEditorContentProvider;
+import org.eclipse.m2e.editor.internal.PomEdits;
 import org.eclipse.m2e.model.edit.pom.Dependency;
 import org.eclipse.m2e.model.edit.pom.DependencyManagement;
 import org.eclipse.m2e.model.edit.pom.Model;
@@ -66,6 +67,11 @@
 import org.eclipse.swt.widgets.Table;
 import org.eclipse.swt.widgets.TableColumn;
 import org.eclipse.swt.widgets.Tree;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocument;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.Text;
 
 
 /**
@@ -86,8 +92,6 @@
 
   LinkedList<MavenProject> projectHierarchy;
 
-  final protected EditingDomain editingDomain;
-
   private IStatus status;
   
   private List<Object> originalSelection;
@@ -96,13 +100,12 @@
    * Hierarchy is a LinkedList representing the hierarchy relationship between POM represented by model and its parents.
    * The head of the list should be the child, while the tail should be the root parent, with the others in between.
    */
-  public ManageDependenciesDialog(Shell parent, Model model, LinkedList<MavenProject> hierarchy,
-      EditingDomain editingDomain) {
-    this(parent, model, hierarchy, editingDomain, null);
+  public ManageDependenciesDialog(Shell parent, Model model, LinkedList<MavenProject> hierarchy) {
+    this(parent, model, hierarchy, null);
   }
 
   public ManageDependenciesDialog(Shell parent, Model model, LinkedList<MavenProject> hierarchy,
-      EditingDomain editingDomain, List<Object> selection) {
+      List<Object> selection) {
     super(parent, DIALOG_SETTINGS);
 
     setShellStyle(getShellStyle() | SWT.RESIZE);
@@ -110,7 +113,6 @@
 
     this.model = model;
     this.projectHierarchy = hierarchy;
-    this.editingDomain = editingDomain;
     this.originalSelection = selection;
   }
 
@@ -234,89 +236,79 @@
    */
   protected void computeResult() {
     MavenProject targetPOM = getTargetPOM();
-    IMavenProjectFacade facade = MavenPlugin.getDefault().getMavenProjectManager()
+    IMavenProjectFacade targetFacade = MavenPlugin.getDefault().getMavenProjectManager()
         .getMavenProject(targetPOM.getGroupId(), targetPOM.getArtifactId(), targetPOM.getVersion());
+    MavenProject currentPOM = projectHierarchy.getFirst();
+    IMavenProjectFacade currentFacade = MavenPlugin.getDefault().getMavenProjectManager()
+        .getMavenProject(currentPOM.getGroupId(), currentPOM.getArtifactId(), currentPOM.getVersion());
 
-    /*
-     * Load the target model so we can make modifications to it
-     */
-    Model targetModel = null;
-    if(targetPOM.equals(getProjectHierarchy().getFirst())) {
-      //Editing the same models in both cases
-      targetModel = model;
-    } else {
-      targetModel = loadTargetModel(facade);
-      if(targetModel == null) {
-        return;
-      }
+    if (targetFacade == null || currentFacade == null) {
+      return;
     }
+    boolean same = targetPOM.equals(currentPOM);
 
-    LinkedList<Dependency> dependencies = getDependenciesList();
-
-    /*
-     * 1) Remove version values from the dependencies from the current POM
-     * 2) Add dependencies to dependencyManagement of targetPOM
-     */
-
-    CompoundCommand command = new CompoundCommand();
-
-    //First we remove the version from the original dependency
-    for(Dependency dep : dependencies) {
-      Command unset = SetCommand.create(editingDomain, dep, PomPackage.eINSTANCE.getDependency_Version(),
-          SetCommand.UNSET_VALUE);
-      command.append(unset);
-    }
-
-    DependencyManagement management = targetModel.getDependencyManagement();
-    if(management == null) {
-      //Add dependency management element if it does not exist
-      management = PomFactory.eINSTANCE.createDependencyManagement();
-      Command createDepManagement = SetCommand.create(editingDomain, targetModel,
-          PomPackage.eINSTANCE.getModel_DependencyManagement(), management);
-      command.append(createDepManagement);
-    } else {
-      //Filter out of the  list of dependencies for which we need new entries in the dependency management section. 
-      for(Dependency depFromTarget : management.getDependencies()) {
-        Iterator<Dependency> iter = dependencies.iterator();
-        while(iter.hasNext()) {
-          Dependency depFromSource = iter.next();
-          if(depFromSource.getGroupId().equals(depFromTarget.getGroupId())
-              && depFromSource.getArtifactId().equals(depFromTarget.getArtifactId())) {
-            /* 
-             * Dependency already exists in the target's dependencyManagement,
-             * so we don't need to add it.
-             */
-            iter.remove();
-            //TODO: mkleint: what if the existing managed version differs from the version in the child pom?
+    final LinkedList<Dependency> modelDeps = getDependenciesList();
+    
+    PomEdits.Operation removeVersionsOperation = new PomEdits.Operation() {
+      public void process(Document document) {
+        //we assume <dependencies> element exists here..
+        List<Element> dependencies = PomEdits.findDependencies(document.getDocumentElement());
+        assert dependencies != null;
+        for (Element dep : dependencies) {
+          String artifactId = PomEdits.getTextValue(PomEdits.findChild(dep, "artifactId"));
+          String groupId = PomEdits.getTextValue(PomEdits.findChild(dep, "groupId"));
+          //TODO: mkleint: nested cycles are ugly..
+          for (Dependency md : modelDeps) {
+            if (artifactId.equals(md.getArtifactId()) && groupId.equals(md.getGroupId())) {
+              PomEdits.removeChild(dep, "version");
+              break;
+            }
           }
         }
       }
-    }
-
-    //Add new entry in dependency mgt section 
-    for(Dependency dep : dependencies) {
-      Dependency clone = PomFactory.eINSTANCE.createDependency();
-      clone.setGroupId(dep.getGroupId());
-      clone.setArtifactId(dep.getArtifactId());
-      clone.setVersion(dep.getVersion());
-
-      Command addDepCommand = AddCommand.create(editingDomain, management,
-          PomPackage.eINSTANCE.getDependencyManagement_Dependencies(), clone);
-
-      command.append(addDepCommand);
-    }
-    editingDomain.getCommandStack().execute(command);
-
-  }
-
-  protected Model loadTargetModel(IMavenProjectFacade facade) {
+    };
+    
+    PomEdits.Operation manageOperation = new PomEdits.Operation() {
+      public void process(Document document) {
+        Element mands = PomEdits.getManagedDependencies(document.getDocumentElement());
+        List<Dependency> modelDependencies = new ArrayList<Dependency>(modelDeps);
+        List<Element> existing = PomEdits.findChilds(mands, "dependency");
+        if (existing != null) {
+          for (Element dep : existing) {
+            String artifactId = PomEdits.getTextValue(PomEdits.findChild(dep, "artifactId"));
+            String groupId = PomEdits.getTextValue(PomEdits.findChild(dep, "groupId"));
+            //TODO: mkleint: nested cycles are ugly..
+            //clone list, shall not modify shared resource (used by the remove operation)
+            Iterator<Dependency> mdIter = modelDependencies.iterator();
+            while (mdIter.hasNext()) {
+              //TODO: here we iterate to find existing managed dependencies and decide not to overwrite them.
+              // but this could eventually break the current project when the versions are diametrally different
+              // we should have shown this information to the user in the UI in the first place (for him to decide what to do)
+              Dependency md = mdIter.next();
+              if (artifactId.equals(md.getArtifactId()) && groupId.equals(md.getGroupId())) {
+                mdIter.remove();
+                break;
+              }
+            }
+          }
+        }
+        for (Dependency md : modelDependencies) {
+          PomEdits.createDependency(mands, md.getGroupId(), md.getArtifactId(), md.getVersion());
+        }
+      }
+    };
+    
     try {
-      PomResourceImpl resource = MavenPlugin.getDefault().getMavenModelManager().loadResource(facade.getPom());
-      resource.load(Collections.EMPTY_MAP);
-      return resource.getModel();
-    } catch(Exception e) {
-      MavenLogger.log("Can't load model " + facade.getPomFile().getPath(), e); //$NON-NLS-1$
-      return null;
+      if (same) {
+        PomEdits.performOnDOMDocument(currentFacade.getPom(), new PomEdits.CompoundOperation(manageOperation, removeVersionsOperation));
+      } else {
+        PomEdits.performOnDOMDocument(targetFacade.getPom(), manageOperation);
+        PomEdits.performOnDOMDocument(currentFacade.getPom(), removeVersionsOperation);
+      }
+    } catch(IOException e) {
+      MavenLogger.log("", e);
+    } catch(CoreException e) {
+      MavenLogger.log(e);
     }
   }
 
diff --git a/org.eclipse.m2e.editor/src/org/eclipse/m2e/editor/internal/PomEdits.java b/org.eclipse.m2e.editor/src/org/eclipse/m2e/editor/internal/PomEdits.java
new file mode 100644
index 0000000..6845a02
--- /dev/null
+++ b/org.eclipse.m2e.editor/src/org/eclipse/m2e/editor/internal/PomEdits.java
@@ -0,0 +1,202 @@
+package org.eclipse.m2e.editor.internal;
+
+import java.io.IOException;
+import java.util.List;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.m2e.core.internal.project.MavenMarkerManager;
+import org.eclipse.wst.sse.core.StructuredModelManager;
+import org.eclipse.wst.sse.core.internal.format.IStructuredFormatProcessor;
+import org.eclipse.wst.sse.core.internal.undo.IStructuredTextUndoManager;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
+import org.eclipse.wst.xml.core.internal.provisional.format.FormatProcessorXML;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.Text;
+
+/**
+ * this class contains tools for editing the pom files using dom tree operations.
+ * @author mkleint
+ *
+ */
+public class PomEdits {
+
+  
+  public static Element findChild(Element parent, String name) {
+    return MavenMarkerManager.findChildElement(parent, name);
+  }
+
+  public static List<Element> findChilds(Element parent, String name) {
+    return MavenMarkerManager.findChildElements(parent, name);
+  }
+
+  public static String getTextValue(Node element) {
+    return MavenMarkerManager.getElementTextValue(element);
+  }
+  
+  /**
+   * node is expected to be the node containing <dependencies> node, so <project>, <dependencyManagement> etc..
+   * @param node
+   * @return
+   */
+  public static List<Element> findDependencies(Element node) {
+    return findChilds(findChild(node, "dependencies"), "dependency");
+  }
+  
+  /** for the root <project> node (or equivalent) finds or creates the <dm> and <dependencies> sections.
+   * returns the <dependencies> section element.
+   *  
+   * @param root
+   * @return
+   */
+  public static Element getManagedDependencies(Element root) {
+    Element toRet = getChild(root, "dependencyManagement");
+    toRet = getChild(toRet, "dependencies");
+    return toRet;
+  }
+  
+  /**
+   * creates and adds new dependency to the parent.
+   * @param parentList
+   * @param groupId null or value
+   * @param artifactId never null
+   * @param version null or value
+   * @return
+   */
+  public static Element createDependency(Element parentList, String groupId, String artifactId, String version) {
+    Document doc = parentList.getOwnerDocument();
+    Element dep = doc.createElement("dependency");
+    parentList.appendChild(dep);
+    
+    if (groupId != null) {
+      Element grid = doc.createElement("groupId");
+      dep.appendChild(grid);
+      grid.appendChild(doc.createTextNode(groupId));
+    }
+    Element artid = doc.createElement("artifactId");
+    dep.appendChild(artid);
+    artid.appendChild(doc.createTextNode(artifactId));
+    if (version != null) {
+      Element vers = doc.createElement("version");
+      dep.appendChild(vers);
+      vers.appendChild(doc.createTextNode(version));
+    }
+    format(dep);
+    return dep;
+  }
+  
+  /**
+   * unlike the findChild() equivalent, this one creates the element if not present and returns it.
+   * Therefore it shall only be invoked within the PomEdits.Operation
+   * @param parent
+   * @param name
+   * @return
+   */
+  public static Element getChild(Element parent, String name) {
+    Element toRet = findChild(parent, name);
+    if (toRet == null) {
+      toRet = parent.getOwnerDocument().createElement(name);
+      parent.appendChild(toRet);
+      format(toRet);
+    }
+    return toRet;
+  }
+  
+  /**
+   * proper remove of a child element
+   * @param parent
+   * @param name
+   */
+  public static void removeChild(Element parent, String name) {
+    Element child = PomEdits.findChild(parent, name);
+    if (child != null) {
+      Node prev = child.getPreviousSibling();
+      if (prev instanceof Text) {
+        Text txt = (Text)prev;
+        int lastnewline = txt.getData().lastIndexOf("\n");
+        txt.setData(txt.getData().substring(0, lastnewline));
+      }
+      parent.removeChild(child);
+    }
+  }
+  
+  /**
+   * formats the node (and content). please make sure to only format the node you have created..
+   * @param newNode
+   */
+  public static void format(Node newNode) {
+    if (newNode.getParentNode() != null && newNode.equals(newNode.getParentNode().getLastChild())) {
+      //add a new line to get the newly generated content correctly formatted.
+      newNode.getParentNode().appendChild(newNode.getParentNode().getOwnerDocument().createTextNode("\n"));
+    }
+    IStructuredFormatProcessor formatProcessor = new FormatProcessorXML();
+    formatProcessor.formatNode(newNode);
+  }
+
+  /**
+   * performs an modifying operation on top the  
+   * @param file
+   * @param operation
+   * @throws IOException
+   * @throws CoreException
+   */
+  public static void performOnDOMDocument(IFile file, PomEdits.Operation operation) throws IOException, CoreException {
+    assert file != null;
+    assert operation != null;
+    IDOMModel domModel = null;
+    //TODO we might want to attempt iterating opened editors and somehow initialize those
+    // that were not yet initialized. Then we could avoid saving a file that is actually opened, but was never used so far (after restart)
+    try {
+      domModel = (IDOMModel) StructuredModelManager.getModelManager().getModelForEdit(file);
+      domModel.aboutToChangeModel();
+      IStructuredTextUndoManager undo = domModel.getStructuredDocument().getUndoManager();
+      undo.beginRecording(domModel);
+      try {
+        operation.process(domModel.getDocument());
+      } finally {
+        undo.endRecording(domModel);
+        domModel.changedModel();
+      }
+    } finally {
+      if (domModel != null) {
+        //saving shall only happen when the model is not held elsewhere (eg. in opened view)
+        if (domModel.isSaveNeeded() && domModel.getReferenceCountForEdit() == 1) {
+          domModel.save();
+        }
+        domModel.releaseFromEdit();
+      }
+    }
+  }
+  
+  /**
+   * operation to perform on top of the DOM document. see performOnDOMDocument()
+   * @author mkleint
+   *
+   */
+  public static interface Operation {
+    void process(Document document);    
+  }
+  
+  /**
+   * an Operation instance that aggregates multiple operations and performs then in given order.
+   * @author mkleint
+   *
+   */
+  public static final class CompoundOperation implements Operation {
+    
+    private final Operation[] operations;
+
+    public CompoundOperation(Operation... operations) {
+      this.operations = operations;
+    }
+    
+    public void process(Document document) {
+      for (Operation oper : operations) {
+        oper.process(document);
+      }
+    }
+    
+  }
+}