BranchNode n = null; boolean after = false; MarkableBaseNode dest = null; if( editNode ) { int op = 0;   switch(op) { case 0: System.err.println("DEL"); dest = getLargestDelTree(base); if( dest == null ) { System.err.println("-- Nothing suitable to del found"); break; } _checkNotMarked(dest); dest.lock(); dest.lockSubtree(); editTrees(dest,null,null,false,false,mergeLog,branchLog); break; case 1: System.err.println("INS"); org.xml.sax.helpers.AttributesImpl atts = new org.xml.sax.helpers.AttributesImpl(); atts.addAttribute("","","id","CDATA", ""+(idCounter++) ); XMLElementNode content = new XMLElementNode("editgen:insert",atts); after = rnd.nextDouble() > 0.5; base.lock(!after,after); editTrees(null,base,new BranchNode( content),after,false,mergeLog,branchLog); break; case 2: System.err.println("UPD"); break; case 3: System.err.println("MOV");  base.lock(); dest = getRandomNode( baseRoot, true, base ); after = rnd.nextDouble() > 0.5; dest.lock(!after,after);  n = dest.getLeft().getFullMatch(); Node n2 = after ? n.getRightSibling() : n.getLeftSibling(); if( base.getContent() instanceof XMLTextNode && ( (n.getContent() instanceof XMLTextNode) || ( n2 != null && n2.getContent() instanceof XMLTextNode ))) {   System.err.println("-- Abort: copying text node adjacent to other text node not possible"); break; }  editTrees(base,dest,null,after,true,mergeLog,branchLog); break; case 4:   System.err.println("CPY");  base.lock();  dest = getRandomNode( baseRoot, true, base ); after = rnd.nextDouble() > 0.5; dest.lock(!after,after); n = dest.getLeft().getFullMatch(); n2 = after ? n.getRightSibling() : n.getLeftSibling(); if( base.getContent() instanceof XMLTextNode && ( (n.getContent() instanceof XMLTextNode) || ( n2 != null && n2.getContent() instanceof XMLTextNode ))) {   System.err.println("-- Abort: copying text node adjacent to other text node not possible"); break; } editTrees(null,dest,base,after,true,mergeLog,branchLog); break; } }  for( int i=0;i<base.getChildCount();i++) transform((MarkableBaseNode) base.getChild(i),baseRoot,mergeLog,branchLog);
  public void transform( MarkableBaseNode base,MarkableBaseNode baseRoot,                         EditLog mergeLog, EditLog branchLog ) {    boolean editNode = false;    // Decide if node should be edited    if( ! base.isMarked() ) {      _visitCount++;      editNode = rnd.nextDouble() > 0.5;    }    BranchNode n = null; // used by edit ops    boolean after = false;    MarkableBaseNode dest = null;    if( editNode ) {      int op = 0; //(int) (rnd.nextDouble() *5.0);//      if( op==1) op = 4;//      if( op==0) op = 3;      switch(op) {        case 0: // Delete node          System.err.println("DEL");          dest = getLargestDelTree(base);          if( dest == null ) {            System.err.println("-- Nothing suitable to del found");            break;          }          _checkNotMarked(dest);          dest.lock();          dest.lockSubtree();          editTrees(dest,null,null,false,false,mergeLog,branchLog);          break;        case 1: // Insert node          System.err.println("INS");          org.xml.sax.helpers.AttributesImpl atts = new org.xml.sax.helpers.AttributesImpl();          atts.addAttribute("","","id","CDATA",             ""+(idCounter++) ); //  rnd.nextLong()+"@"+ System.currentTimeMillis());          XMLElementNode content = new XMLElementNode("editgen:insert",atts);          after = rnd.nextDouble() > 0.5;          base.lock(!after,after);          editTrees(null,base,new BranchNode( content),after,false,mergeLog,branchLog);          break;        case 2: // Update node          System.err.println("UPD");          break; // N/A for now...        case 3: // Move subtree          System.err.println("MOV");          // Delete from base (src of move) (=delete code block)          base.lock();          dest = getRandomNode( baseRoot, true, base ); // NOTE! Dest must be fetched AFTER src is locked!          after = rnd.nextDouble() > 0.5;          dest.lock(!after,after);          // Text node move check          n = dest.getLeft().getFullMatch();          Node n2 = after ? n.getRightSibling() : n.getLeftSibling();          if( base.getContent() instanceof XMLTextNode &&              ( (n.getContent() instanceof XMLTextNode) ||               ( n2 != null && n2.getContent() instanceof XMLTextNode ))) {            // NOTE: Unfortunately we have locked the dst and src, so they are no            // longer eligable for other ops after the abort :( (unlocking is not trivial)            System.err.println("-- Abort: copying text node adjacent to other text node not possible");            break;          }          editTrees(base,dest,null,after,true,mergeLog,branchLog);          break;        case 4: // Copy subtree          // NOTE: Will currently never copy as child of a node,          // if the node does not already have children (always inserts in childlist)          System.err.println("CPY");          // Lock src of copy          base.lock();          // Insert at dest (=insert code block)          dest = getRandomNode( baseRoot, true, base ); // NOTE! Dest must be fetched AFTER src is locked!          after = rnd.nextDouble() > 0.5;          dest.lock(!after,after);          n = dest.getLeft().getFullMatch();          n2 = after ? n.getRightSibling() : n.getLeftSibling();          if( base.getContent() instanceof XMLTextNode &&              ( (n.getContent() instanceof XMLTextNode) ||               ( n2 != null && n2.getContent() instanceof XMLTextNode ))) {            // NOTE: Unfortunately we have locked the dst and src, so they are no            // longer eligable for other ops after the abort :( (unlocking is not trivial)            System.err.println("-- Abort: copying text node adjacent to other text node not possible");            break;          }          editTrees(null,dest,base,after,true,mergeLog,branchLog);          break;      }    } // if edit node    // recurse    for( int i=0;i<base.getChildCount();i++)      transform((MarkableBaseNode) base.getChild(i),baseRoot,mergeLog,branchLog);  }