I made the changes to the XUpdateImpl.java.patch that where requested. I used cvs diff -u this time to create the diff its easier then having two source trees and doing manual diffs. Let me know of that works.

I fixed up the XUpdateQueryTest to include an append test case to specifically check for duplicate node bug. I also changed all of the assertEqual to the XMLAssert.assertXMLEqual for a tad bit smarter xml matching.

Todd
Index: java/src/org/apache/xindice/core/xupdate/XUpdateImpl.java
===================================================================
RCS file: /home/cvspublic/xml-xindice/java/src/org/apache/xindice/core/xupdate/XUpdateImpl.java,v
retrieving revision 1.12
diff -u -r1.12 XUpdateImpl.java
--- java/src/org/apache/xindice/core/xupdate/XUpdateImpl.java	8 Feb 2004 02:50:54 -0000	1.12
+++ java/src/org/apache/xindice/core/xupdate/XUpdateImpl.java	24 May 2005 16:09:02 -0000
@@ -24,6 +24,7 @@
 import org.apache.xindice.xml.NodeSource;
 import org.apache.xindice.xml.dom.CompressedNode;
 import org.apache.xindice.xml.dom.DBNode;
+import org.apache.xindice.core.data.Key;
 
 import org.w3c.dom.Document;
 import org.w3c.dom.Node;
@@ -34,8 +35,10 @@
 import org.xmldb.xupdate.lexus.commands.DefaultCommand;
 
 import java.util.Enumeration;
+import java.util.HashMap;
 import java.util.Hashtable;
-
+import java.util.Iterator;
+import java.util.Map;
 /**
  * Provides Collection and document based XUpdate capabilities.
  *
@@ -150,38 +153,43 @@
     public void execute(Collection col) throws Exception {
 
         int attribIndex = 0;
+        /** @todo Don't cache the documents in memory */
+        HashMap docsUpdated = new HashMap();
         for (int i = 0; i < super.query[0].size(); i++) {
             int cmdID = ((Integer) super.query[0].elementAt(i)).intValue();
 
             if (cmdID == CommandConstants.ATTRIBUTES) {
                 Hashtable attribs = (Hashtable) super.query[1].elementAt(attribIndex);
-                attribIndex++;
                 String selector = (String) attribs.get("select");
-
-                // If we found an XPath selector we need to execute the commands.
-                if (selector != null) {
+                attribIndex++;
+                // If we found an XPath selector we need to execute the commands,
+                // but we can not execute xupdate variables again.
+                // all variables start with a '$'
+                if (selector != null && !selector.startsWith("$")) {
                     NodeSet ns = col.queryCollection("XPath", selector, nsMap);
-                    Document lastDoc = null;
                     while (ns != null && ns.hasMoreNodes()) {
                         DBNode node = (DBNode) ns.getNextNode();
                         Document doc = node.getOwnerDocument();
+                        NodeSource source = node.getSource();
+                        Node contextNode = doc.getDocumentElement();
 
-                        if (doc == lastDoc) {
+                        if (docsUpdated.containsKey(source.getKey())) {
                             continue; // We only have to process it once
                         } else {
-                            lastDoc = doc;
+                            docsUpdated.put(source.getKey(), doc);
                         }
-
-                        NodeSource source = node.getSource();
-
-                        Node contextNode = doc.getDocumentElement();
                         execute(contextNode);
-
-                        col.setDocument(source.getKey(), doc);
                     }
                 }
             }
         }
+        // update all documents at once
+        // this way we don't get any half run xupdate commands.
+        Iterator keys = docsUpdated.entrySet().iterator();
+        while(keys.hasNext()) {
+            Map.Entry set = (Map.Entry)keys.next();
+            col.setDocument((Key)set.getKey(), (Document)set.getValue());
+        }
     }
 
     public int getModifiedCount() {
Index: java/tests/src/org/apache/xindice/integration/client/services/XUpdateQueryTest.java
===================================================================
RCS file: /home/cvspublic/xml-xindice/java/tests/src/org/apache/xindice/integration/client/services/XUpdateQueryTest.java,v
retrieving revision 1.7
diff -u -r1.7 XUpdateQueryTest.java
--- java/tests/src/org/apache/xindice/integration/client/services/XUpdateQueryTest.java	1 Apr 2005 02:46:43 -0000	1.7
+++ java/tests/src/org/apache/xindice/integration/client/services/XUpdateQueryTest.java	24 May 2005 16:07:57 -0000
@@ -22,6 +22,9 @@
 
 import org.xmldb.api.modules.XUpdateQueryService;
 import org.xmldb.api.base.Collection;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.custommonkey.xmlunit.XMLAssert;
 
 /**
  * @version CVS $Revision: 1.7 $, $Date: 2005/04/01 02:46:43 $
@@ -29,7 +32,7 @@
  */
 public class XUpdateQueryTest
         extends AbstractXmlDbClientTest {
-
+    private static final Log log = LogFactory.getLog(XUpdateQueryTest.class);
     public void setUp() throws Exception {
         super.setUp();
 
@@ -96,6 +99,7 @@
                 "<last>Smith</last>" +
                 "<phone type=\"work\">480-300-3003</phone>" +
                 "</person>";
+
         String updatedDocument2 = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
                 "<person status=\"divorced\">" +
                 "<first>Ben</first>" +
@@ -103,18 +107,51 @@
                 "<phone type=\"work\">480-300-3003</phone>" +
                 "</person>";
 
+        String query2 =
+                "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
+                "<xupdate:modifications version=\"1.0\" xmlns:xupdate=\"http://www.xmldb.org/xupdate\";>" +
+                "<xupdate:append select=\"/person/first\">" +
+                "<xupdate:element name=\"test2\"/>" +
+                "</xupdate:append>" +
+                "<xupdate:append select=\"/person/last\">" +
+                "<xupdate:element name=\"test1\"/>" +
+                "</xupdate:append>" +
+                "</xupdate:modifications>";
+
+        String updatedDocument3 = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
+                "<person status=\"divorced\">" +
+                "<first>Ben" +
+                "<test2 />" +
+                "</first>" +
+                "<last>Benton"+
+                "<test1 />" +
+                "</last>" +
+                "<phone type=\"work\">480-300-3003</phone>" +
+                "</person>";
+
         Collection col = this.client.getCollection(TEST_COLLECTION_PATH);
         XUpdateQueryService service = (XUpdateQueryService) col.getService("XUpdateQueryService", "1.0");
-
         long count = service.update(query);
-        assertEquals(6, count);
+        // Fixed: was 6 should be 2. The old code would cause multiple updates.
+        assertEquals(2, count);
 
         String doc = this.client.getDocument(TEST_COLLECTION_PATH, "doc1");
         assertNotNull(doc);
-        assertEquals(updatedDocument1, doc);
+        XMLAssert.assertXMLEqual(updatedDocument1, doc);
 
         doc = this.client.getDocument(TEST_COLLECTION_PATH, "doc2");
         assertNotNull(doc);
-        assertEquals(updatedDocument2, doc);
+        XMLAssert.assertXMLEqual(updatedDocument2, doc);
+
+        // test the second query should update 2 docs
+        count = service.update(query2);
+        assertEquals(2,count);
+
+        // check the second doc to make sure its correct
+        doc = this.client.getDocument(TEST_COLLECTION_PATH, "doc2");
+
+        log.debug("Doc2:=\n " + doc);
+        log.debug("UpdatedDoc3:\n " + updatedDocument3);
+        XMLAssert.assertXMLEqual(updatedDocument3,doc);
     }
 }

Reply via email to