XUpdate Patch 2.0

Todd Byrne <[email protected]>
Newsgroups gmane.text.xml.xindice.devel
Message-ID <[email protected]>
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
XUpdateImpl.java.patch (text/x-patch, 3.5 KB)
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() {
XUpdateQueryTest.java.patch (text/x-patch, 3.7 KB)
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);
     }
 }
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.