Clover coverage report -
Coverage timestamp: Sun Nov 1 2009 23:08:24 UTC
file stats: LOC: 205   Methods: 5
NCLOC: 117   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
XUpdateImpl.java 76.3% 90.2% 100% 85.6%
coverage coverage
 1    /*
 2    * Licensed to the Apache Software Foundation (ASF) under one or more
 3    * contributor license agreements. See the NOTICE file distributed with
 4    * this work for additional information regarding copyright ownership.
 5    * The ASF licenses this file to You under the Apache License, Version 2.0
 6    * (the "License"); you may not use this file except in compliance with
 7    * the License. You may obtain a copy of the License at
 8    *
 9    * http://www.apache.org/licenses/LICENSE-2.0
 10    *
 11    * Unless required by applicable law or agreed to in writing, software
 12    * distributed under the License is distributed on an "AS IS" BASIS,
 13    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14    * See the License for the specific language governing permissions and
 15    * limitations under the License.
 16    *
 17    * $Id: XUpdateImpl.java 541508 2007-05-25 01:54:12Z vgritsenko $
 18    */
 19   
 20    package org.apache.xindice.core.xupdate;
 21   
 22    import org.apache.xindice.core.Collection;
 23    import org.apache.xindice.core.data.NodeSet;
 24    import org.apache.xindice.xml.NamespaceMap;
 25    import org.apache.xindice.xml.NodeSource;
 26    import org.apache.xindice.xml.dom.CompressedNode;
 27    import org.apache.xindice.xml.dom.DBNode;
 28   
 29    import org.w3c.dom.Document;
 30    import org.w3c.dom.Node;
 31    import org.xml.sax.SAXException;
 32    import org.xmldb.xupdate.lexus.XUpdateQueryImpl;
 33    import org.xmldb.xupdate.lexus.commands.CommandConstants;
 34    import org.xmldb.xupdate.lexus.commands.CommandObject;
 35    import org.xmldb.xupdate.lexus.commands.DefaultCommand;
 36   
 37    import java.util.Enumeration;
 38    import java.util.HashMap;
 39    import java.util.Hashtable;
 40    import java.util.Iterator;
 41    import java.util.Map;
 42   
 43    /**
 44    * Provides Collection and document based XUpdate capabilities.
 45    *
 46    * For more detail about XUpdate look at the
 47    * <a href="http://xmldb-org.sourceforge.net/xupdate/xupdate-wd.html">XUpdate Working Draft</a>.
 48    *
 49    * @version $Revision: 541508 $, $Date: 2007-05-24 18:54:12 -0700 (Thu, 24 May 2007) $
 50    */
 51    public class XUpdateImpl extends XUpdateQueryImpl {
 52   
 53    /**
 54    * If set to true, then namespaces set explicitly via an API call will take precendence.
 55    * If set to false, then namespaces set implicitly within query string will take precedence.
 56    */
 57    private static final boolean API_NS_PRECEDENCE = true;
 58   
 59    protected int nodesModified;
 60    protected NamespaceMap nsMap;
 61   
 62    /**
 63    * Set the namespace map to be used when resolving queries
 64    */
 65  12 public void setNamespaceMap(NamespaceMap nsMap) {
 66  12 if (nsMap == null) {
 67  12 return;
 68    }
 69   
 70  0 if (this.nsMap == null) {
 71  0 this.nsMap = nsMap;
 72    } else {
 73  0 this.nsMap.includeNamespaces(nsMap, API_NS_PRECEDENCE);
 74    }
 75    }
 76   
 77   
 78    /**
 79    * Sets the query string to be used when executing update
 80    */
 81  12 public void setQString(String query) throws SAXException {
 82  12 super.setQString(query);
 83  12 if (nsMap == null) {
 84  12 nsMap = new NamespaceMap();
 85    }
 86  12 nsMap.includeNamespaces(super.namespaces, !API_NS_PRECEDENCE);
 87    }
 88   
 89   
 90    /**
 91    * Execute the XUpdate commands against a document.
 92    */
 93  18 public void execute(Node contextNode) throws Exception {
 94  18 CommandObject currentCommand = new DefaultCommand(contextNode);
 95  18 Enumeration commands = super.query[0].elements();
 96  18 Enumeration attributes = super.query[1].elements();
 97  18 Enumeration characters = super.query[2].elements();
 98  18 Node origNode = contextNode;
 99  18 CommandObject.getXPath().setNamespace(nsMap.getContextNode());
 100   
 101  18 while (commands.hasMoreElements()) {
 102  219 int id = ((Integer) commands.nextElement()).intValue();
 103   
 104  219 if (id == CommandConstants.ATTRIBUTES) {
 105  57 currentCommand.submitAttributes((Hashtable) attributes.nextElement());
 106  162 } else if (id == CommandConstants.CHARACTERS) {
 107  48 currentCommand.submitCharacters((String) characters.nextElement());
 108  114 } else if (id > 0) {
 109  57 if (!currentCommand.submitInstruction(id)) {
 110  42 super.commandConstants.setContextNode(contextNode);
 111  42 currentCommand = super.commandConstants.commandForID(id);
 112  42 if (currentCommand == null) {
 113  0 throw new Exception("Operation can not have any XUpdate-instruction!");
 114    }
 115  42 currentCommand.reset();
 116    }
 117    } else {
 118  57 if (!currentCommand.executeInstruction()) {
 119  42 try {
 120  42 contextNode = currentCommand.execute();
 121    } catch (Exception e) {
 122    // While not ideal, CommandObject.execute throws
 123    // Exception("no nodes selected !") if nothing is
 124    // selected for modification we trap that case
 125    // and ignore allowing continued processing
 126    // of remaining xupdate instructions that may be present
 127  0 if (!"no nodes selected !".equals(e.getMessage())) {
 128  0 throw e;
 129    }
 130    }
 131    // Default do-nothing command will soak up anything
 132    // (characters, attributes, etc.) encountered until we
 133    // come across the next xupdate instruction
 134    // (e.g. remove, append, insert, etc.)
 135  42 currentCommand = new DefaultCommand(contextNode);
 136    }
 137    }
 138    }
 139   
 140  18 if (origNode instanceof CompressedNode) {
 141  18 CompressedNode cn = (CompressedNode) origNode;
 142  18 if (cn.isDirty()) {
 143  18 nodesModified++;
 144    }
 145    }
 146    }
 147   
 148    /**
 149    * Execute the set of XUpdate commands against a collection.
 150    *
 151    * @param col The collection against which the command will be executed
 152    * @exception Exception Description of Exception
 153    */
 154  6 public void execute(Collection col) throws Exception {
 155  6 int attribIndex = 0;
 156   
 157    // TODO: Don't cache all the documents in memory.
 158    // Need to keep updated documents in memory so that can
 159    // 'rollback' all the changes in case of failure.
 160    // Won't need this in case underlying collection supports
 161    // transaction.
 162  6 HashMap docsUpdated = new HashMap();
 163  6 for (int i = 0; i < super.query[0].size(); i++) {
 164  78 int cmdID = ((Integer) super.query[0].elementAt(i)).intValue();
 165   
 166  78 if (cmdID == CommandConstants.ATTRIBUTES) {
 167  21 Hashtable attribs = (Hashtable) super.query[1].elementAt(attribIndex);
 168  21 String selector = (String) attribs.get("select");
 169  21 attribIndex++;
 170   
 171    // If we found an XPath selector we need to execute the commands,
 172    // but we can not execute xupdate variables again.
 173    // all variables start with a '$'
 174  21 if (selector != null && !selector.startsWith("$")) {
 175  15 NodeSet ns = col.queryCollection("XPath", selector, nsMap);
 176  15 while (ns != null && ns.hasMoreNodes()) {
 177  30 DBNode node = (DBNode) ns.getNextNode();
 178  30 Document doc = node.getOwnerDocument();
 179  30 NodeSource source = node.getSource();
 180   
 181  30 if (docsUpdated.containsKey(source.getKey())) {
 182  18 continue; // We only have to process it once
 183    } else {
 184  12 docsUpdated.put(source.getKey(), doc);
 185    }
 186   
 187  12 execute(doc.getDocumentElement());
 188    }
 189    }
 190    }
 191    }
 192   
 193    // Update all documents at once
 194    // this way we don't get any half run xupdate commands.
 195  6 Iterator i = docsUpdated.entrySet().iterator();
 196  6 while (i.hasNext()) {
 197  12 Map.Entry set = (Map.Entry) i.next();
 198  12 col.setDocument(set.getKey(), (Document) set.getValue());
 199    }
 200    }
 201   
 202  12 public int getModifiedCount() {
 203  12 return nodesModified;
 204    }
 205    }