cvs commit: xml-xindice/java/tests/src/org/apache/xindice/integration/client/services XUpdateQueryTest.java

[email protected]
Newsgroups gmane.text.xml.xindice.devel
Message-ID <[email protected]>
vgritsenko    2005/05/25 18:17:11

  Modified:    .        status.xml
               java/src/org/apache/xindice/core/xupdate XUpdateImpl.java
               java/tests/src/org/apache/xindice/integration/client/services
                        XUpdateQueryTest.java
  Log:
  apply patch from Todd Byrne, fix xupdate bug #30878
  
  Revision  Changes    Path
  1.52      +8 -1      xml-xindice/status.xml
  
  Index: status.xml
  ===================================================================
  RCS file: /home/cvs/xml-xindice/status.xml,v
  retrieving revision 1.51
  retrieving revision 1.52
  diff -u -r1.51 -r1.52
  --- status.xml	4 Mar 2005 03:38:14 -0000	1.51
  +++ status.xml	26 May 2005 01:17:11 -0000	1.52
  @@ -73,7 +73,14 @@
       </todo>
   
       <changes>
  -        <release version="1.1b5-dev" date="March 3 2005">
  +        <release version="1.1b5-dev" date="May 25 2005">
  +            <action dev="VG" type="fix" fixes-bug="30878" due-to="Todd Byrne">
  +                Make sure that XUpdate commands are run only once per document.
  +                In case XUpdate command does not complete successfully, revert
  +                all affected documents to the original state. This requires
  +                buffering of modified documents - so XUpdate on large collection
  +                might require lots of memory.
  +            </action>
               <action dev="VG" type="update" fixes-bug="33657" due-to="Dave Brosius">
                   Added support for current Xalan CVS (post 2.6.0 release).
               </action>
  
  
  
  1.13      +34 -21    xml-xindice/java/src/org/apache/xindice/core/xupdate/XUpdateImpl.java
  
  Index: XUpdateImpl.java
  ===================================================================
  RCS file: /home/cvs/xml-xindice/java/src/org/apache/xindice/core/xupdate/XUpdateImpl.java,v
  retrieving revision 1.12
  retrieving revision 1.13
  diff -u -r1.12 -r1.13
  --- XUpdateImpl.java	8 Feb 2004 02:50:54 -0000	1.12
  +++ XUpdateImpl.java	26 May 2005 01:17:11 -0000	1.13
  @@ -1,5 +1,5 @@
   /*
  - * Copyright 1999-2004 The Apache Software Foundation.
  + * Copyright 1999-2005 The Apache Software Foundation.
    *
    * Licensed under the Apache License, Version 2.0 (the "License");
    * you may not use this file except in compliance with the License.
  @@ -34,27 +34,30 @@
   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.
    *
    * For more detail about XUpdate look at the
  - * <a href="http://www.xmldb.org/xupdate/xupdate-wd.html">XUpdate Working Draft</a>.
  + * <a href="http://xmldb-org.sourceforge.net/xupdate/xupdate-wd.html">XUpdate Working Draft</a>.
    *
    * @version CVS $Revision$, $Date$
    */
   public class XUpdateImpl extends XUpdateQueryImpl {
   
  -    protected int nodesModified = 0;
  -    protected NamespaceMap nsMap;
  -
       /**
        * If set to true, then namespaces set explicitly via an API call will take precendence.
        * If set to false, then namespaces set implicitly within query string will take precedence.
        */
       private static final boolean API_NS_PRECEDENCE = true;
   
  +    protected int nodesModified;
  +    protected NamespaceMap nsMap;
  +
       /**
        * Set the namespace map to be used when resolving queries
        */
  @@ -148,44 +151,54 @@
        * @exception Exception Description of Exception
        */
       public void execute(Collection col) throws Exception {
  -
           int attribIndex = 0;
  +
  +        // TODO: Don't cache all the documents in memory.
  +        // Need to keep updated documents in memory so that can
  +        // 'rollback' all the changes in case of failure.
  +        // Won't need this in case underlying collection supports
  +        // transaction.
  +        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");
  +                attribIndex++;
   
  -                // If we found an XPath selector we need to execute the commands.
  -                if (selector != null) {
  +                // 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();
   
  -                        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);
  +                        execute(doc.getDocumentElement());
                       }
                   }
               }
           }
  +
  +        // Update all documents at once
  +        // this way we don't get any half run xupdate commands.
  +        Iterator i = docsUpdated.entrySet().iterator();
  +        while (i.hasNext()) {
  +            Map.Entry set = (Map.Entry) i.next();
  +            col.setDocument(set.getKey(), (Document) set.getValue());
  +        }
       }
   
       public int getModifiedCount() {
           return nodesModified;
       }
   }
  -
  
  
  
  1.8       +44 -7     xml-xindice/java/tests/src/org/apache/xindice/integration/client/services/XUpdateQueryTest.java
  
  Index: XUpdateQueryTest.java
  ===================================================================
  RCS file: /home/cvs/xml-xindice/java/tests/src/org/apache/xindice/integration/client/services/XUpdateQueryTest.java,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- XUpdateQueryTest.java	1 Apr 2005 02:46:43 -0000	1.7
  +++ XUpdateQueryTest.java	26 May 2005 01:17:11 -0000	1.8
  @@ -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$, $Date$
  @@ -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.