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);
}
}