You are viewing a plain text version of this content. The canonical link for it is here.
Posted to xindice-dev@xml.apache.org by ke...@apache.org on 2003/07/15 17:44:37 UTC

cvs commit: xml-xindice/java/src/org/apache/xindice/tools/command XPathQuery.java

kevinross    2003/07/15 08:44:36

  Modified:    java/src/org/apache/xindice/xml/dom ContainerNodeImpl.java
                        DocumentImpl.java CharacterDataImpl.java
                        ProcessingInstructionImpl.java ElementImpl.java
                        EntityReferenceImpl.java
               java/src/org/apache/xindice/core DBObserver.java
                        CollectionManager.java SystemCollection.java
                        Collection.java
               java/src/org/apache/xindice/core/filer FSFiler.java
                        BTree.java HashFiler.java BTreeFiler.java
               java/src/org/apache/xindice/core/xupdate
                        XUpdateQueryResolver.java
               java/src/org/apache/xindice/xml/jaxp
                        DocumentBuilderImpl.java
               java/src/org/apache/xindice/core/indexer IndexManager.java
                        NameIndexer.java ValueIndexer.java
               java/src/org/apache/xindice/util Configuration.java
               java/src/org/apache/xindice/core/request URIMapper.java
               java/src/org/apache/xindice/core/query QueryEngine.java
                        XPathQueryResolver.java
               java/src/org/apache/xindice/xml TextWriter.java
               java/src/org/apache/xindice/tools/command XPathQuery.java
  Log:
  Losing Exceptions fix:
  1.  change any catch(and no throw) with log.debug("No message", e) to log.warn(e);
  2.  format (of course)
  3.  org imports
  
  Revision  Changes    Path
  1.6       +416 -417  xml-xindice/java/src/org/apache/xindice/xml/dom/ContainerNodeImpl.java
  
  Index: ContainerNodeImpl.java
  ===================================================================
  RCS file: /home/cvs/xml-xindice/java/src/org/apache/xindice/xml/dom/ContainerNodeImpl.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- ContainerNodeImpl.java	4 Nov 2002 06:39:55 -0000	1.5
  +++ ContainerNodeImpl.java	15 Jul 2003 15:44:34 -0000	1.6
  @@ -59,20 +59,25 @@
    * $Id$
    */
   
  -import org.apache.xindice.util.ByteArrayInput;
  -import org.apache.xindice.xml.SymbolTable;
  -import org.apache.xindice.xml.XMLCompressedInput;
  -
  -import org.apache.commons.logging.Log;
  -import org.apache.commons.logging.LogFactory;
  -
  -import org.w3c.dom.*;
  -import org.w3c.dom.traversal.*;
  -
   import java.io.IOException;
   import java.util.ArrayList;
   import java.util.List;
   
  +import org.apache.commons.logging.Log;
  +import org.apache.commons.logging.LogFactory;
  +import org.apache.xindice.util.ByteArrayInput;
  +import org.apache.xindice.xml.SymbolTable;
  +import org.apache.xindice.xml.XMLCompressedInput;
  +import org.w3c.dom.DOMException;
  +import org.w3c.dom.DocumentFragment;
  +import org.w3c.dom.Element;
  +import org.w3c.dom.Node;
  +import org.w3c.dom.NodeList;
  +import org.w3c.dom.Text;
  +import org.w3c.dom.traversal.DocumentTraversal;
  +import org.w3c.dom.traversal.NodeFilter;
  +import org.w3c.dom.traversal.NodeIterator;
  +
   /**
    * ContainerNodeImpl performs most of the child-rearing behavior of the
    * Element and Document implementations.
  @@ -80,310 +85,306 @@
   
   public abstract class ContainerNodeImpl extends NodeImpl {
   
  -   private static Log log = LogFactory.getLog("org.apache.xindice.xml");
  +    private static Log log = LogFactory.getLog("org.apache.xindice.xml");
   
  -   protected NodeListImpl childNodes = new NodeListImpl(this);
  +    protected NodeListImpl childNodes = new NodeListImpl(this);
   
  -   public ContainerNodeImpl() {
  -   }
  -   
  -   public ContainerNodeImpl(NodeImpl parentNode, byte[] data, int pos, int len) {
  -      super(parentNode, data, pos, len);
  -   }
  -
  -   public ContainerNodeImpl(NodeImpl parentNode, boolean dirty) {
  -      super(parentNode, dirty);
  -   }
  -
  -   protected boolean isNodeTypeValid(short type) {
  -      return true;
  -   }
  -
  -   protected final Node getPreviousSibling(Node node) {
  -      checkLoaded();
  -      int pos = childNodes.indexOf(node)-1;
  -      return pos >= 0 ? childNodes.item(pos)
  -                      : null;
  -   }
  -
  -   protected final Node getNextSibling(Node node) {
  -      checkLoaded();
  -      int pos = childNodes.indexOf(node)+1;
  -      return pos < childNodes.getLength() ? childNodes.item(pos)
  -                                          : null;
  -   }
  -
  -   protected void checkLoaded() {
  -      if ( loaded )
  -         return;
  -      else
  -         loaded = true;
  -
  -      try {
  -         if ( data != null ) {
  -            DocumentImpl doc = (DocumentImpl)getOwnerDocument();
  -            loadChildren(doc.getSymbols());
  -         }
  -      }
  -      catch ( Exception e ) {
  -         if (log.isDebugEnabled()) {
  -            log.debug("No message", e);
  -         }
  -      }
  -   }
  -
  -   protected final void loadChildren(SymbolTable st) throws IOException {
  -      ByteArrayInput bis = new ByteArrayInput(data, pos, len);
  -      XMLCompressedInput in = new XMLCompressedInput(bis, st);
  -
  -      if ( getNodeType() == Node.ELEMENT_NODE ) {
  -         // Have to skip the attributes
  -         in.readSignature();
  -         in.readContentSize();
  -         in.readShort();             // Element Symbol
  -         int attrCount = in.readAttributeCount();
  -         for ( int i = 0 ; i < attrCount; i++ ) {
  -            in.readShort();          // Attribute Symbol
  -            in.skip(in.readShort()); // Attribute Length
  -         }
  -      }
  -      else {
  -         in.readInt();
  -      }
  -
  -      while ( bis.available() > 0 ) {
  -         int pos = bis.getPos();
  -         /* TODO why is it used for? byte signature = */ in.readSignature();
  -         int len = in.readContentSize();
  -         if ( len == 0 )
  -            len = 1;
  -
  -         switch ( in.getNodeType() ) {
  -
  -            case Node.ELEMENT_NODE:
  -               childNodes.add(new ElementImpl(this, data, pos, len));
  -               break;
  -
  -            case Node.TEXT_NODE:
  -               childNodes.add(new TextImpl(this, data, pos, len));
  -               break;
  -
  -            case Node.CDATA_SECTION_NODE:
  -               childNodes.add(new CDATASectionImpl(this, data, pos, len));
  -               break;
  -
  -            case Node.ENTITY_REFERENCE_NODE:
  -               childNodes.add(new EntityReferenceImpl(this, data, pos, len));
  -               break;
  -
  -            case Node.ENTITY_NODE:
  -               childNodes.add(new EntityImpl(this, data, pos, len));
  -               break;
  -
  -            case Node.PROCESSING_INSTRUCTION_NODE:
  -               childNodes.add(new ProcessingInstructionImpl(this, data, pos, len));
  -               break;
  -
  -            case Node.COMMENT_NODE:
  -               childNodes.add(new CommentImpl(this, data, pos, len));
  -               break;
  -
  -            case Node.NOTATION_NODE:
  -               childNodes.add(new NotationImpl(this, data, pos, len));
  -               break;
  -         }
  -
  -         bis.setPos(pos);
  -         bis.skip(len);
  -      }
  -   }
  -
  -   /**
  -    *  This is a convenience method to allow easy determination of whether a
  -    * node has any children.
  -    * @return  <code>true</code> if the node has any children,
  -    *   <code>false</code> if the node has no children.
  -    */
  -   public final boolean hasChildNodes() {
  -      checkLoaded();
  -      return childNodes.getLength() > 0;
  -   }
  -
  -   public final NodeList getChildNodes() {
  -      checkLoaded();
  -      return childNodes;
  -   }
  -
  -   /**
  -    * The first child of this node. If there is no such node, this returns
  -    * <code>null</code>.
  -    */
  -   public final Node getFirstChild() {
  -      checkLoaded();
  -      if ( childNodes.size() > 0 )
  -         return childNodes.item(0);
  -      else
  -         return null;
  -   }
  -
  -   /**
  -    * The last child of this node. If there is no such node, this returns
  -    * <code>null</code>.
  -    */
  -   public final Node getLastChild() {
  -      checkLoaded();
  -      if ( childNodes.size() > 0 )
  -         return childNodes.item(childNodes.getLength()-1);
  -      else
  -         return null;
  -   }
  -
  -   /**
  -    * Replaces the child node <code>oldChild</code> with <code>newChild</code>
  -    * in the list of children, and returns the <code>oldChild</code> node. If
  -    * the <code>newChild</code> is already in the tree, it is first removed.
  -    * @param newChild The new node to put in the child list.
  -    * @param oldChild The node being replaced in the list.
  -    * @return The node replaced.
  -    * @exception DOMException
  -    *   HIERARCHY_REQUEST_ERR: Raised if this node is of a type that does not
  -    *   allow children of the type of the <code>newChild</code> node, or it
  -    *   the node to put in is one of this node's ancestors.
  -    *   <br>WRONG_DOCUMENT_ERR: Raised if <code>newChild</code> was created
  -    *   from a different document than the one that created this node.
  -    *   <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
  -    *   <br>NOT_FOUND_ERR: Raised if <code>oldChild</code> is not a child of
  -    *   this node.
  -    */
  -   public final synchronized Node replaceChild(Node newChild, Node oldChild) throws DOMException {
  -      checkLoaded();
  -      checkReadOnly();
  -      if ( !isNodeTypeValid(newChild.getNodeType()) )
  -         throw EX_HIERARCHY_REQUEST;
  -      int idx = childNodes.indexOf(oldChild);
  -      if ( idx >= 0 ) {
  -         if ( newChild.getNodeType() == DOCUMENT_FRAGMENT_NODE ) {
  -            childNodes.remove(idx);
  -            NodeList nl = ((DocumentFragment)newChild).getChildNodes();
  -            for ( int i = 0; i < nl.getLength(); i++ ) {
  -               NodeImpl impl = (NodeImpl)nl.item(i);
  -               impl.setParentNode(this);
  -               childNodes.add(idx+i, impl);
  -            }
  -         }
  -         else {
  -            NodeImpl impl = (NodeImpl)newChild;
  -            impl.setParentNode(this);
  -            childNodes.set(idx, impl);
  -         }
  -      }
  -      setDirty();
  -      return oldChild;
  -   }
  -
  -   /**
  -    * Inserts the node <code>newChild</code> before the existing child node
  -    * <code>refChild</code>. If <code>refChild</code> is <code>null</code>,
  -    * insert <code>newChild</code> at the end of the list of children.
  -    * <br>If <code>newChild</code> is a <code>DocumentFragment</code> object,
  -    * all of its children are inserted, in the same order, before
  -    * <code>refChild</code>. If the <code>newChild</code> is already in the
  -    * tree, it is first removed.
  -    * @param newChild The node to insert.
  -    * @param refChild The reference node, i.e., the node before which the new
  -    *   node must be inserted.
  -    * @return The node being inserted.
  -    * @exception DOMException
  -    *   HIERARCHY_REQUEST_ERR: Raised if this node is of a type that does not
  -    *   allow children of the type of the <code>newChild</code> node, or if
  -    *   the node to insert is one of this node's ancestors.
  -    *   <br>WRONG_DOCUMENT_ERR: Raised if <code>newChild</code> was created
  -    *   from a different document than the one that created this node.
  -    *   <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
  -    *   <br>NOT_FOUND_ERR: Raised if <code>refChild</code> is not a child of
  -    *   this node.
  -    */
  -   public final synchronized Node insertBefore(Node newChild, Node refChild) throws DOMException {
  -      checkLoaded();
  -      checkReadOnly();
  -      int idx = childNodes.indexOf(refChild);
  -      if ( idx >= 0 ) {
  -         if ( !isNodeTypeValid(newChild.getNodeType()) )
  -             throw EX_HIERARCHY_REQUEST;
  -         if ( newChild.getNodeType() == DOCUMENT_FRAGMENT_NODE ) {
  -            NodeList nl = ((DocumentFragment)newChild).getChildNodes();
  -            for ( int i = 0; i < nl.getLength(); i++ ) {
  -               NodeImpl impl = (NodeImpl)nl.item(i);
  -               impl.setParentNode(this);
  -               childNodes.add(idx+i, impl);
  -            }
  -         }
  -         else {
  -            NodeImpl impl = (NodeImpl)newChild;
  -            impl.setParentNode(this);
  -            childNodes.add(idx, impl);
  -         }
  -      }
  -      setDirty();
  -      return newChild;
  -   }
  -
  -   /**
  -    * Removes the child node indicated by <code>oldChild</code> from the list
  -    * of children, and returns it.
  -    * @param oldChild The node being removed.
  -    * @return The node removed.
  -    * @exception DOMException
  -    *   NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
  -    *   <br>NOT_FOUND_ERR: Raised if <code>oldChild</code> is not a child of
  -    *   this node.
  -    */
  -   public final synchronized Node removeChild(Node oldChild) throws DOMException {
  -      checkLoaded();
  -      checkReadOnly();
  -      if ( !childNodes.remove(oldChild) )
  -         throw EX_NOT_FOUND;
  -      setDirty();
  -      return oldChild;
  -   }
  -
  -   /**
  -    * Adds the node <code>newChild</code> to the end of the list of children of
  -    * this node. If the <code>newChild</code> is already in the tree, it is
  -    * first removed.
  -    * @param newChild The node to add.If it is a  <code>DocumentFragment</code>
  -    *   object, the entire contents of the document fragment are moved into
  -    *   the child list of this node
  -    * @return The node added.
  -    * @exception DOMException
  -    *   HIERARCHY_REQUEST_ERR: Raised if this node is of a type that does not
  -    *   allow children of the type of the <code>newChild</code> node, or if
  -    *   the node to append is one of this node's ancestors.
  -    *   <br>WRONG_DOCUMENT_ERR: Raised if <code>newChild</code> was created
  -    *   from a different document than the one that created this node.
  -    *   <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
  -    */
  -   public final synchronized Node appendChild(Node newChild) throws DOMException {
  -      checkLoaded();
  -      checkReadOnly();
  -      if ( !isNodeTypeValid(newChild.getNodeType()) )
  -         throw EX_HIERARCHY_REQUEST;
  -      if ( newChild.getNodeType() == DOCUMENT_FRAGMENT_NODE ) {
  -         NodeList nl = ((DocumentFragment)newChild).getChildNodes();
  -         for ( int i = 0; i < nl.getLength(); i++ ) {
  -            NodeImpl impl = (NodeImpl)nl.item(i);
  +    public ContainerNodeImpl() {}
  +
  +    public ContainerNodeImpl(NodeImpl parentNode, byte[] data, int pos, int len) {
  +        super(parentNode, data, pos, len);
  +    }
  +
  +    public ContainerNodeImpl(NodeImpl parentNode, boolean dirty) {
  +        super(parentNode, dirty);
  +    }
  +
  +    protected boolean isNodeTypeValid(short type) {
  +        return true;
  +    }
  +
  +    protected final Node getPreviousSibling(Node node) {
  +        checkLoaded();
  +        int pos = childNodes.indexOf(node) - 1;
  +        return pos >= 0 ? childNodes.item(pos) : null;
  +    }
  +
  +    protected final Node getNextSibling(Node node) {
  +        checkLoaded();
  +        int pos = childNodes.indexOf(node) + 1;
  +        return pos < childNodes.getLength() ? childNodes.item(pos) : null;
  +    }
  +
  +    protected void checkLoaded() {
  +        if (loaded)
  +            return;
  +        else
  +            loaded = true;
  +
  +        try {
  +            if (data != null) {
  +                DocumentImpl doc = (DocumentImpl) getOwnerDocument();
  +                loadChildren(doc.getSymbols());
  +            }
  +        }
  +        catch (Exception e) {
  +            log.warn(e);
  +        }
  +    }
  +
  +    protected final void loadChildren(SymbolTable st) throws IOException {
  +        ByteArrayInput bis = new ByteArrayInput(data, pos, len);
  +        XMLCompressedInput in = new XMLCompressedInput(bis, st);
  +
  +        if (getNodeType() == Node.ELEMENT_NODE) {
  +            // Have to skip the attributes
  +            in.readSignature();
  +            in.readContentSize();
  +            in.readShort(); // Element Symbol
  +            int attrCount = in.readAttributeCount();
  +            for (int i = 0; i < attrCount; i++) {
  +                in.readShort(); // Attribute Symbol
  +                in.skip(in.readShort()); // Attribute Length
  +            }
  +        }
  +        else {
  +            in.readInt();
  +        }
  +
  +        while (bis.available() > 0) {
  +            int pos = bis.getPos();
  +            /* TODO why is it used for? byte signature = */
  +            in.readSignature();
  +            int len = in.readContentSize();
  +            if (len == 0)
  +                len = 1;
  +
  +            switch (in.getNodeType()) {
  +
  +                case Node.ELEMENT_NODE :
  +                    childNodes.add(new ElementImpl(this, data, pos, len));
  +                    break;
  +
  +                case Node.TEXT_NODE :
  +                    childNodes.add(new TextImpl(this, data, pos, len));
  +                    break;
  +
  +                case Node.CDATA_SECTION_NODE :
  +                    childNodes.add(new CDATASectionImpl(this, data, pos, len));
  +                    break;
  +
  +                case Node.ENTITY_REFERENCE_NODE :
  +                    childNodes.add(new EntityReferenceImpl(this, data, pos, len));
  +                    break;
  +
  +                case Node.ENTITY_NODE :
  +                    childNodes.add(new EntityImpl(this, data, pos, len));
  +                    break;
  +
  +                case Node.PROCESSING_INSTRUCTION_NODE :
  +                    childNodes.add(new ProcessingInstructionImpl(this, data, pos, len));
  +                    break;
  +
  +                case Node.COMMENT_NODE :
  +                    childNodes.add(new CommentImpl(this, data, pos, len));
  +                    break;
  +
  +                case Node.NOTATION_NODE :
  +                    childNodes.add(new NotationImpl(this, data, pos, len));
  +                    break;
  +            }
  +
  +            bis.setPos(pos);
  +            bis.skip(len);
  +        }
  +    }
  +
  +    /**
  +     *  This is a convenience method to allow easy determination of whether a
  +     * node has any children.
  +     * @return  <code>true</code> if the node has any children,
  +     *   <code>false</code> if the node has no children.
  +     */
  +    public final boolean hasChildNodes() {
  +        checkLoaded();
  +        return childNodes.getLength() > 0;
  +    }
  +
  +    public final NodeList getChildNodes() {
  +        checkLoaded();
  +        return childNodes;
  +    }
  +
  +    /**
  +     * The first child of this node. If there is no such node, this returns
  +     * <code>null</code>.
  +     */
  +    public final Node getFirstChild() {
  +        checkLoaded();
  +        if (childNodes.size() > 0)
  +            return childNodes.item(0);
  +        else
  +            return null;
  +    }
  +
  +    /**
  +     * The last child of this node. If there is no such node, this returns
  +     * <code>null</code>.
  +     */
  +    public final Node getLastChild() {
  +        checkLoaded();
  +        if (childNodes.size() > 0)
  +            return childNodes.item(childNodes.getLength() - 1);
  +        else
  +            return null;
  +    }
  +
  +    /**
  +     * Replaces the child node <code>oldChild</code> with <code>newChild</code>
  +     * in the list of children, and returns the <code>oldChild</code> node. If
  +     * the <code>newChild</code> is already in the tree, it is first removed.
  +     * @param newChild The new node to put in the child list.
  +     * @param oldChild The node being replaced in the list.
  +     * @return The node replaced.
  +     * @exception DOMException
  +     *   HIERARCHY_REQUEST_ERR: Raised if this node is of a type that does not
  +     *   allow children of the type of the <code>newChild</code> node, or it
  +     *   the node to put in is one of this node's ancestors.
  +     *   <br>WRONG_DOCUMENT_ERR: Raised if <code>newChild</code> was created
  +     *   from a different document than the one that created this node.
  +     *   <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
  +     *   <br>NOT_FOUND_ERR: Raised if <code>oldChild</code> is not a child of
  +     *   this node.
  +     */
  +    public final synchronized Node replaceChild(Node newChild, Node oldChild) throws DOMException {
  +        checkLoaded();
  +        checkReadOnly();
  +        if (!isNodeTypeValid(newChild.getNodeType()))
  +            throw EX_HIERARCHY_REQUEST;
  +        int idx = childNodes.indexOf(oldChild);
  +        if (idx >= 0) {
  +            if (newChild.getNodeType() == DOCUMENT_FRAGMENT_NODE) {
  +                childNodes.remove(idx);
  +                NodeList nl = ((DocumentFragment) newChild).getChildNodes();
  +                for (int i = 0; i < nl.getLength(); i++) {
  +                    NodeImpl impl = (NodeImpl) nl.item(i);
  +                    impl.setParentNode(this);
  +                    childNodes.add(idx + i, impl);
  +                }
  +            }
  +            else {
  +                NodeImpl impl = (NodeImpl) newChild;
  +                impl.setParentNode(this);
  +                childNodes.set(idx, impl);
  +            }
  +        }
  +        setDirty();
  +        return oldChild;
  +    }
  +
  +    /**
  +     * Inserts the node <code>newChild</code> before the existing child node
  +     * <code>refChild</code>. If <code>refChild</code> is <code>null</code>,
  +     * insert <code>newChild</code> at the end of the list of children.
  +     * <br>If <code>newChild</code> is a <code>DocumentFragment</code> object,
  +     * all of its children are inserted, in the same order, before
  +     * <code>refChild</code>. If the <code>newChild</code> is already in the
  +     * tree, it is first removed.
  +     * @param newChild The node to insert.
  +     * @param refChild The reference node, i.e., the node before which the new
  +     *   node must be inserted.
  +     * @return The node being inserted.
  +     * @exception DOMException
  +     *   HIERARCHY_REQUEST_ERR: Raised if this node is of a type that does not
  +     *   allow children of the type of the <code>newChild</code> node, or if
  +     *   the node to insert is one of this node's ancestors.
  +     *   <br>WRONG_DOCUMENT_ERR: Raised if <code>newChild</code> was created
  +     *   from a different document than the one that created this node.
  +     *   <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
  +     *   <br>NOT_FOUND_ERR: Raised if <code>refChild</code> is not a child of
  +     *   this node.
  +     */
  +    public final synchronized Node insertBefore(Node newChild, Node refChild) throws DOMException {
  +        checkLoaded();
  +        checkReadOnly();
  +        int idx = childNodes.indexOf(refChild);
  +        if (idx >= 0) {
  +            if (!isNodeTypeValid(newChild.getNodeType()))
  +                throw EX_HIERARCHY_REQUEST;
  +            if (newChild.getNodeType() == DOCUMENT_FRAGMENT_NODE) {
  +                NodeList nl = ((DocumentFragment) newChild).getChildNodes();
  +                for (int i = 0; i < nl.getLength(); i++) {
  +                    NodeImpl impl = (NodeImpl) nl.item(i);
  +                    impl.setParentNode(this);
  +                    childNodes.add(idx + i, impl);
  +                }
  +            }
  +            else {
  +                NodeImpl impl = (NodeImpl) newChild;
  +                impl.setParentNode(this);
  +                childNodes.add(idx, impl);
  +            }
  +        }
  +        setDirty();
  +        return newChild;
  +    }
  +
  +    /**
  +     * Removes the child node indicated by <code>oldChild</code> from the list
  +     * of children, and returns it.
  +     * @param oldChild The node being removed.
  +     * @return The node removed.
  +     * @exception DOMException
  +     *   NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
  +     *   <br>NOT_FOUND_ERR: Raised if <code>oldChild</code> is not a child of
  +     *   this node.
  +     */
  +    public final synchronized Node removeChild(Node oldChild) throws DOMException {
  +        checkLoaded();
  +        checkReadOnly();
  +        if (!childNodes.remove(oldChild))
  +            throw EX_NOT_FOUND;
  +        setDirty();
  +        return oldChild;
  +    }
  +
  +    /**
  +     * Adds the node <code>newChild</code> to the end of the list of children of
  +     * this node. If the <code>newChild</code> is already in the tree, it is
  +     * first removed.
  +     * @param newChild The node to add.If it is a  <code>DocumentFragment</code>
  +     *   object, the entire contents of the document fragment are moved into
  +     *   the child list of this node
  +     * @return The node added.
  +     * @exception DOMException
  +     *   HIERARCHY_REQUEST_ERR: Raised if this node is of a type that does not
  +     *   allow children of the type of the <code>newChild</code> node, or if
  +     *   the node to append is one of this node's ancestors.
  +     *   <br>WRONG_DOCUMENT_ERR: Raised if <code>newChild</code> was created
  +     *   from a different document than the one that created this node.
  +     *   <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
  +     */
  +    public final synchronized Node appendChild(Node newChild) throws DOMException {
  +        checkLoaded();
  +        checkReadOnly();
  +        if (!isNodeTypeValid(newChild.getNodeType()))
  +            throw EX_HIERARCHY_REQUEST;
  +        if (newChild.getNodeType() == DOCUMENT_FRAGMENT_NODE) {
  +            NodeList nl = ((DocumentFragment) newChild).getChildNodes();
  +            for (int i = 0; i < nl.getLength(); i++) {
  +                NodeImpl impl = (NodeImpl) nl.item(i);
  +                impl.setParentNode(this);
  +                childNodes.add(impl);
  +            }
  +        }
  +        else {
  +            NodeImpl impl = (NodeImpl) newChild;
               impl.setParentNode(this);
               childNodes.add(impl);
  -         }
  -      }
  -      else {
  -         NodeImpl impl = (NodeImpl)newChild;
  -         impl.setParentNode(this);
  -         childNodes.add(impl);
  -      }
  -      setDirty();
  -      return newChild;
  -   }
  +        }
  +        setDirty();
  +        return newChild;
  +    }
   
       /**
        *  Puts all <code>Text</code> nodes in the full depth of the sub-tree
  @@ -401,110 +402,108 @@
        * <code>Text</code> nodes and <code>CDATASection</code> nodes.
        * @since DOM Level 2
        */
  -   public final synchronized void normalize() {
  -      checkLoaded();
  -      checkReadOnly();
  -      List set = new ArrayList();
  -
  -      NodeListImpl newList = new NodeListImpl(this);
  -      boolean modified = false;
  -
  -      int size = childNodes.size();
  -      for ( int i = 0; i < size; i++ ) {
  -         Node add = null;
  -         Node n = (Node)childNodes.get(i);
  -         short type = n.getNodeType();
  -
  -         switch ( type ) {
  -            case Node.TEXT_NODE:
  -               set.add(n);
  -               break;
  -            case Node.ELEMENT_NODE:
  -               n.normalize();
  -            default:
  -               add = n;
  -         }
  -
  -         if ( !set.isEmpty() && ( type != Node.TEXT_NODE || i == size-1 ) ) {
  -            Text s = (Text)set.get(0);
  -            int len = set.size();
  -            for ( int j = 1 ; j < len; j++ ) {
  -               modified = true;
  -               Text a = (Text)set.get(j);
  -               s.appendData(a.getData());
  -            }
  -            newList.add(s);
  -            set.clear();
  -         }
  -         if ( add != null )
  -            newList.add(add);
  -      }
  -
  -      if ( modified ) {
  -         childNodes = newList;
  -         setDirty();
  -      }
  -   }
  -
  -   /**
  -    * Returns a <code>NodeList</code> of all descendant elements with a given
  -    * tag name, in the order in which they would be encountered in a preorder
  -    * traversal of the <code>Element</code> tree.
  -    * @param name The name of the tag to match on. The special value "*"
  -    *   matches all tags.
  -    * @return A list of matching <code>Element</code> nodes.
  -    */
  -   public final NodeList getElementsByTagName(final String name) {
  -      checkLoaded();
  -      NodeListImpl list = new NodeListImpl(this);
  -
  -      NodeFilter filter = new NodeFilter() {
  -         public short acceptNode(Node node) {
  -            if ( node.getNodeName().equals(name) )
  -               return (short)NodeFilter.FILTER_ACCEPT;
  -            else
  -               return (short)NodeFilter.FILTER_SKIP;
  -         }
  -      };
  -
  -      NodeIterator enum = ((DocumentTraversal)getOwnerDocument()).createNodeIterator(this, NodeFilter.SHOW_ELEMENT, filter, false);
  -      Node node = null;
  -      do {
  -         node = enum.nextNode();
  -         if ( node != null )
  -            list.add(node);
  -      }
  -      while ( node != null );
  -      return list;
  -   }
  -
  -   public final NodeList getElementsByTagNameNS(final String namespaceURI, final String localName) {
  -      checkLoaded();
  -      NodeListImpl list = new NodeListImpl(this);
  -
  -      NodeFilter filter = new NodeFilter() {
  -         public short acceptNode(Node node) {
  -            if ( node.getLocalName().equals(localName)
  -              && node.getNamespaceURI().equals(namespaceURI) )
  -               return (short)NodeFilter.FILTER_ACCEPT;
  -            else
  -               return (short)NodeFilter.FILTER_SKIP;
  -         }
  -      };
  -
  -      NodeIterator enum = ((DocumentTraversal)getOwnerDocument()).createNodeIterator(this, NodeFilter.SHOW_ELEMENT, filter, false);
  -      Node node = null;
  -      do {
  -         node = enum.nextNode();
  -         if ( node != null )
  -            list.add(node);
  -      }
  -      while ( node != null );
  -      return list;
  -   }
  -
  -   public final Element getElementById(String elementId) {
  -      return null;
  -   }
  -}
  +    public final synchronized void normalize() {
  +        checkLoaded();
  +        checkReadOnly();
  +        List set = new ArrayList();
  +
  +        NodeListImpl newList = new NodeListImpl(this);
  +        boolean modified = false;
  +
  +        int size = childNodes.size();
  +        for (int i = 0; i < size; i++) {
  +            Node add = null;
  +            Node n = (Node) childNodes.get(i);
  +            short type = n.getNodeType();
  +
  +            switch (type) {
  +                case Node.TEXT_NODE :
  +                    set.add(n);
  +                    break;
  +                case Node.ELEMENT_NODE :
  +                    n.normalize();
  +                default :
  +                    add = n;
  +            }
  +
  +            if (!set.isEmpty() && (type != Node.TEXT_NODE || i == size - 1)) {
  +                Text s = (Text) set.get(0);
  +                int len = set.size();
  +                for (int j = 1; j < len; j++) {
  +                    modified = true;
  +                    Text a = (Text) set.get(j);
  +                    s.appendData(a.getData());
  +                }
  +                newList.add(s);
  +                set.clear();
  +            }
  +            if (add != null)
  +                newList.add(add);
  +        }
  +
  +        if (modified) {
  +            childNodes = newList;
  +            setDirty();
  +        }
  +    }
   
  +    /**
  +     * Returns a <code>NodeList</code> of all descendant elements with a given
  +     * tag name, in the order in which they would be encountered in a preorder
  +     * traversal of the <code>Element</code> tree.
  +     * @param name The name of the tag to match on. The special value "*"
  +     *   matches all tags.
  +     * @return A list of matching <code>Element</code> nodes.
  +     */
  +    public final NodeList getElementsByTagName(final String name) {
  +        checkLoaded();
  +        NodeListImpl list = new NodeListImpl(this);
  +
  +        NodeFilter filter = new NodeFilter() {
  +            public short acceptNode(Node node) {
  +                if (node.getNodeName().equals(name))
  +                    return (short) NodeFilter.FILTER_ACCEPT;
  +                else
  +                    return (short) NodeFilter.FILTER_SKIP;
  +            }
  +        };
  +
  +        NodeIterator enum = ((DocumentTraversal) getOwnerDocument()).createNodeIterator(this, NodeFilter.SHOW_ELEMENT, filter, false);
  +        Node node = null;
  +        do {
  +            node = enum.nextNode();
  +            if (node != null)
  +                list.add(node);
  +        }
  +        while (node != null);
  +        return list;
  +    }
  +
  +    public final NodeList getElementsByTagNameNS(final String namespaceURI, final String localName) {
  +        checkLoaded();
  +        NodeListImpl list = new NodeListImpl(this);
  +
  +        NodeFilter filter = new NodeFilter() {
  +            public short acceptNode(Node node) {
  +                if (node.getLocalName().equals(localName) && node.getNamespaceURI().equals(namespaceURI))
  +                    return (short) NodeFilter.FILTER_ACCEPT;
  +                else
  +                    return (short) NodeFilter.FILTER_SKIP;
  +            }
  +        };
  +
  +        NodeIterator enum = ((DocumentTraversal) getOwnerDocument()).createNodeIterator(this, NodeFilter.SHOW_ELEMENT, filter, false);
  +        Node node = null;
  +        do {
  +            node = enum.nextNode();
  +            if (node != null)
  +                list.add(node);
  +        }
  +        while (node != null);
  +        return list;
  +    }
  +
  +    public final Element getElementById(String elementId) {
  +        return null;
  +    }
  +}
  
  
  
  1.6       +478 -473  xml-xindice/java/src/org/apache/xindice/xml/dom/DocumentImpl.java
  
  Index: DocumentImpl.java
  ===================================================================
  RCS file: /home/cvs/xml-xindice/java/src/org/apache/xindice/xml/dom/DocumentImpl.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- DocumentImpl.java	31 Oct 2002 07:16:52 -0000	1.5
  +++ DocumentImpl.java	15 Jul 2003 15:44:34 -0000	1.6
  @@ -59,20 +59,35 @@
    * $Id$
    */
   
  +import java.util.HashSet;
  +import java.util.Iterator;
  +import java.util.Set;
  +
  +import org.apache.commons.logging.Log;
  +import org.apache.commons.logging.LogFactory;
   import org.apache.xindice.util.XindiceException;
   import org.apache.xindice.xml.NodeSource;
   import org.apache.xindice.xml.SymbolTable;
   import org.apache.xindice.xml.dom.traversal.TreeWalkerImpl;
  -
  -import org.apache.commons.logging.Log;
  -import org.apache.commons.logging.LogFactory;
  -
  -import org.w3c.dom.*;
  -import org.w3c.dom.traversal.*;
  -
  -import java.util.HashSet;
  -import java.util.Iterator;
  -import java.util.Set;
  +import org.w3c.dom.Attr;
  +import org.w3c.dom.CDATASection;
  +import org.w3c.dom.Comment;
  +import org.w3c.dom.DOMException;
  +import org.w3c.dom.DOMImplementation;
  +import org.w3c.dom.Document;
  +import org.w3c.dom.DocumentFragment;
  +import org.w3c.dom.DocumentType;
  +import org.w3c.dom.Element;
  +import org.w3c.dom.EntityReference;
  +import org.w3c.dom.NamedNodeMap;
  +import org.w3c.dom.Node;
  +import org.w3c.dom.NodeList;
  +import org.w3c.dom.ProcessingInstruction;
  +import org.w3c.dom.Text;
  +import org.w3c.dom.traversal.DocumentTraversal;
  +import org.w3c.dom.traversal.NodeFilter;
  +import org.w3c.dom.traversal.NodeIterator;
  +import org.w3c.dom.traversal.TreeWalker;
   
   /**
    * DocumentImpl
  @@ -80,474 +95,464 @@
   
   public final class DocumentImpl extends ContainerNodeImpl implements CompressedDocument, DBDocument, DocumentTraversal {
   
  -   private static Log log = LogFactory.getLog("org.apache.xindice.xml");
  +    private static Log log = LogFactory.getLog("org.apache.xindice.xml");
  +
  +    private DocumentType docType = null;
  +    private String version = null;
  +    private String actualEncoding = null;
  +    private String encoding = null;
  +    private boolean standalone = false;
  +    private boolean strictErrorChecking = false;
  +    private SymbolTable symbols = null;
  +    private boolean readOnly = false;
  +
  +    public DocumentImpl() {
  +        super(null, true);
  +    }
  +
  +    public DocumentImpl(byte[] data, int pos, int len) {
  +        super(null, data, pos, len);
  +    }
  +
  +    public DocumentImpl(byte[] data) {
  +        this(data, 0, data.length);
  +    }
  +
  +    public DocumentImpl(byte[] data, SymbolTable symbols, NodeSource source) {
  +        this(data);
  +        this.symbols = symbols;
  +        this.source = source;
  +    }
  +
  +    public DocumentImpl(Document doc) throws XindiceException {
  +        super(null, true);
  +
  +        boolean compress = true;
  +
  +        if (doc instanceof CompressedDocument) {
  +            CompressedDocument c = (CompressedDocument) doc;
  +            symbols = c.getSymbols();
  +            if (!c.isDirty()) {
  +                data = c.getDataBytes();
  +                pos = c.getDataPos();
  +                len = c.getDataLen();
  +                compress = false;
  +            }
  +        }
  +
  +        if (compress) {
  +            if (symbols == null)
  +                symbols = new SymbolTable();
  +            data = DOMCompressor.Compress(doc, symbols);
  +            pos = 0;
  +            len = data.length;
  +        }
  +
  +        if (doc instanceof DBDocument) {
  +            DBDocument d = (DBDocument) doc;
  +            source = d.getSource();
  +        }
  +    }
  +
  +    public boolean isReadOnly() {
  +        return readOnly;
  +    }
   
  -   private DocumentType docType = null;
  -   private String version = null;
  -   private String actualEncoding = null;
  -   private String encoding = null;
  -   private boolean standalone = false;
  -   private boolean strictErrorChecking = false;
  -   private SymbolTable symbols = null;
  -   private boolean readOnly = false;
  -
  -   public DocumentImpl() {
  -      super(null, true);
  -   }
  -
  -   public DocumentImpl(byte[] data, int pos, int len) {
  -      super(null, data, pos, len);
  -   }
  -
  -   public DocumentImpl(byte[] data) {
  -      this(data, 0, data.length);
  -   }
  -
  -   public DocumentImpl(byte[] data, SymbolTable symbols, NodeSource source) {
  -      this(data);
  -      this.symbols = symbols;
  -      this.source = source;
  -   }
  -
  -   public DocumentImpl(Document doc) throws XindiceException {
  -      super(null, true);
  -
  -      boolean compress = true;
  -
  -      if ( doc instanceof CompressedDocument ) {
  -         CompressedDocument c = (CompressedDocument)doc;
  -         symbols = c.getSymbols();
  -         if ( !c.isDirty() ) {
  -            data = c.getDataBytes();
  -            pos = c.getDataPos();
  -            len = c.getDataLen();
  -            compress = false;
  -         }
  -      }
  -
  -      if ( compress ) {
  -         if ( symbols == null )
  -            symbols = new SymbolTable();
  -         data = DOMCompressor.Compress(doc, symbols);
  -         pos = 0;
  -         len = data.length;
  -      }
  -
  -      if ( doc instanceof DBDocument ) {
  -         DBDocument d = (DBDocument)doc;
  -         source = d.getSource();
  -      }
  -   }
  -
  -   public boolean isReadOnly() {
  -      return readOnly;
  -   }
  -
  -   protected void checkLoaded() {
  -      if ( loaded )
  -         return;
  -      else
  -         loaded = true;
  -
  -      try {
  -         if ( data != null )
  -            loadChildren(symbols);
  -      }
  -      catch ( Exception e ) {
  -         if (log.isDebugEnabled()) {
  -            log.debug("No message", e);
  -         }
  -      }
  -   }
  -
  -   public boolean isCaching() {
  -      String cache = DBDocument.CACHE;
  -
  -      int size = childNodes.getLength();
  -      for ( int i = 0; i < size; i++ ) {
  -         Node n = childNodes.item(i);
  -         if ( n.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE
  -           && n.getNodeName().equals(CACHE_CONTROL) ) {
  -            cache = n.getNodeValue().trim();
  -            break;
  -         }
  -      }
  -
  -      return (cache != null && cache.equals(CACHE));
  -   }
  -
  -   public void setCaching(boolean caching) {
  -      // TODO delete String cache = DBDocument.CACHE;
  -
  -      int size = childNodes.getLength();
  -      for ( int i = 0; i < size; i++ ) {
  -         Node n = childNodes.item(i);
  -         if ( n.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE
  -           && n.getNodeName().equals(CACHE_CONTROL) ) {
  -              n.setNodeValue(caching ? CACHE : NOCACHE);
  +    protected void checkLoaded() {
  +        if (loaded)
               return;
  -         }
  -      }
  +        else
  +            loaded = true;
   
  -      ProcessingInstruction pi = createProcessingInstruction(CACHE_CONTROL, caching ? CACHE : NOCACHE);
  -      insertBefore(pi, getDocumentElement());
  -   }
  -
  -   public SymbolTable getSymbols() {
  -      return symbols;
  -   }
  -
  -   public void setSymbols(SymbolTable symbols) {
  -      this.symbols = symbols;
  -   }
  -
  -   public void expandSource() {
  -      ElementImpl e = (ElementImpl)getDocumentElement();
  -      if ( e != null )
  -         e.expandSource();
  -   }
  -
  -   public Node getNodeAtPos(int pos) {
  -      return null; // TODO: This
  -   }
  -
  -   public short getNodeType() {
  -      return Node.DOCUMENT_NODE;
  -   }
  -
  -   public String getNodeName() {
  -      return "#document";
  -   }
  -
  -   /**
  -    * The Document Type Declaration (see <code>DocumentType</code>) associated
  -    * with  this document. For HTML documents as well as XML documents without
  -    * a document type declaration this returns <code>null</code>. The DOM Level
  -    *  1 does not support editing the Document Type Declaration, therefore
  -    * <code>docType</code> cannot be altered in any way.
  -    */
  -   public DocumentType getDoctype() {
  -      return docType;
  -   }
  -
  -   public void setDoctype(DocumentType docType) {
  -      this.docType = docType;
  -   }
  -
  -   /**
  -    * The <code>DOMImplementation</code> object that handles this document. A
  -    * DOM application may use objects from multiple  implementations.
  -    */
  -   public DOMImplementation getImplementation() {
  -      return DOMImplementationImpl.getInstance();
  -   }
  -
  -   /**
  -    * Creates a <code>Text</code> node given the specified string.
  -    * @param data The data for the node.
  -    * @return The new <code>Text</code> object.
  -    */
  -   public Text createTextNode(String data) {
  -      return new TextImpl(this, data);
  -   }
  -
  -   /**
  -    * This is a convenience attribute that allows direct access to the child
  -    * node that is the root element of  the document. For HTML documents, this
  -    * is the element with the tagName "HTML".
  -    */
  -   public Element getDocumentElement() {
  -      checkLoaded();
  -      Iterator enum = childNodes.iterator();
  -      while ( enum.hasNext() ) {
  -         Node node = (Node)enum.next();
  -         if ( node.getNodeType() == Node.ELEMENT_NODE )
  -            return (Element)node;
  -      }
  -      return null;
  -   }
  -
  -   /**
  -    * Creates a <code>CDATASection</code> node whose value  is the specified
  -    * string.
  -    * @param data The data for the <code>CDATASection</code> contents.
  -    * @return The new <code>CDATASection</code> object.
  -    * @exception DOMException
  -    *   NOT_SUPPORTED_ERR: Raised if this document is an HTML document.
  -    */
  -   public CDATASection createCDATASection(String data) throws DOMException {
  -      return new CDATASectionImpl(this, data);
  -   }
  -
  -   /**
  -    * Creates an element of the type specified. Note that the instance returned
  -    * implements the Element interface, so attributes can be specified
  -    * directly  on the returned object.
  -    * @param tagName The name of the element type to instantiate. For XML, this
  -    *   is case-sensitive. For HTML, the  <code>tagName</code> parameter may
  -    *   be provided in any case,  but it must be mapped to the canonical
  -    *   uppercase form by  the DOM implementation.
  -    * @return A new <code>Element</code> object.
  -    * @exception DOMException
  -    *   INVALID_CHARACTER_ERR: Raised if the specified name contains an
  -    *   invalid character.
  -    */
  -   public Element createElement(String tagName) throws DOMException {
  -      return new ElementImpl(this, tagName);
  -   }
  -
  -   /**
  -    * Creates an empty <code>DocumentFragment</code> object.
  -    * @return A new <code>DocumentFragment</code>.
  -    */
  -   public DocumentFragment createDocumentFragment() {
  -      return new DocumentFragmentImpl(this);
  -   }
  -
  -   /**
  -    * Creates an <code>Attr</code> of the given name. Note that the
  -    * <code>Attr</code> instance can then be set on an <code>Element</code>
  -    * using the <code>setAttribute</code> method.
  -    * @param name The name of the attribute.
  -    * @return A new <code>Attr</code> object.
  -    * @exception DOMException
  -    *   INVALID_CHARACTER_ERR: Raised if the specified name contains an
  -    *   invalid character.
  -    */
  -   public Attr createAttribute(String name) throws DOMException {
  -      return new AttrImpl(this, name);
  -   }
  -
  -   /**
  -    * Creates a <code>Comment</code> node given the specified string.
  -    * @param data The data for the node.
  -    * @return The new <code>Comment</code> object.
  -    */
  -   public Comment createComment(String data) {
  -      return new CommentImpl(this, data);
  -   }
  -
  -   /**
  -    * Creates a <code>ProcessingInstruction</code> node given the specified
  -    * name and data strings.
  -    * @param target The target part of the processing instruction.
  -    * @param data The data for the node.
  -    * @return The new <code>ProcessingInstruction</code> object.
  -    * @exception DOMException
  -    *   INVALID_CHARACTER_ERR: Raised if an invalid character is specified.
  -    *   <br>NOT_SUPPORTED_ERR: Raised if this document is an HTML document.
  -    */
  -   public ProcessingInstruction createProcessingInstruction(String target, String data) throws DOMException {
  -      return new ProcessingInstructionImpl(this, target, data);
  -   }
  -
  -   /**
  -    * Creates an EntityReference object.
  -    * @param name The name of the entity to reference.
  -    * @return The new <code>EntityReference</code> object.
  -    * @exception DOMException
  -    *   INVALID_CHARACTER_ERR: Raised if the specified name contains an
  -    *   invalid character.
  -    *   <br>NOT_SUPPORTED_ERR: Raised if this document is an HTML document.
  -    */
  -   public EntityReference createEntityReference(String name) throws DOMException {
  -      return new EntityReferenceImpl(this, name);
  -   }
  -
  -   private void importNamespaces(Node source, Node target) {
  -      if ( target.getNodeType() == Node.ELEMENT_NODE ) {
  -         // Retrieve Namespace definitions in scope
  -         Set set = new HashSet();
  -         Node n = source;
  -         Element elem = (Element)target;
  -         while ( n != null ) {
  -            NamedNodeMap nm = n.getAttributes();
  -            for ( int i = 0; i < nm.getLength(); i++ ) {
  -               Attr a = (Attr)nm.item(i);
  -               String name = a.getNodeName();
  -               if ( ( name.startsWith("xmlns:")
  -                 || name.equals("xmlns") )
  -                 && !set.contains(name) ) {
  -                  set.add(name);
  -                  elem.setAttribute(name, a.getValue());
  -               }
  +        try {
  +            if (data != null)
  +                loadChildren(symbols);
  +        }
  +        catch (Exception e) {
  +            log.warn(e);
  +        }
  +    }
  +
  +    public boolean isCaching() {
  +        String cache = DBDocument.CACHE;
  +
  +        int size = childNodes.getLength();
  +        for (int i = 0; i < size; i++) {
  +            Node n = childNodes.item(i);
  +            if (n.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE && n.getNodeName().equals(CACHE_CONTROL)) {
  +                cache = n.getNodeValue().trim();
  +                break;
               }
  -            n = n.getParentNode();
  -            if ( n.getNodeType() == DOCUMENT_NODE
  -              || n.getNodeType() == DOCUMENT_FRAGMENT_NODE )
  -               n = null;
  -         }
  -      }
  -   }
  -
  -   public Node importNode(Node importedNode, boolean deep) {
  -      try {
  -         // If we're a Xindice DOM Node and share the same symbol table,
  -         // then we're golden
  -         if ( importedNode instanceof NodeImpl ) {
  -            NodeImpl impl = (NodeImpl)importedNode;
  -            DocumentImpl docImpl = (DocumentImpl)impl.getOwnerDocument();
  -            if ( docImpl.getSymbols() != null && ( docImpl.getSymbols() == symbols ) ) {
  -               NodeImpl clone = (NodeImpl)impl.cloneNode(deep);
  -               clone.setParentNode(this);
  -               importNamespaces(importedNode, clone);
  -               return clone;
  +        }
  +
  +        return (cache != null && cache.equals(CACHE));
  +    }
  +
  +    public void setCaching(boolean caching) {
  +        // TODO delete String cache = DBDocument.CACHE;
  +
  +        int size = childNodes.getLength();
  +        for (int i = 0; i < size; i++) {
  +            Node n = childNodes.item(i);
  +            if (n.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE && n.getNodeName().equals(CACHE_CONTROL)) {
  +                n.setNodeValue(caching ? CACHE : NOCACHE);
  +                return;
               }
  -         }
  +        }
   
  -         // Crap, we have to do a full graph copy
  -         Node result = null;
  -         switch ( importedNode.getNodeType() ) {
  -            case Node.ATTRIBUTE_NODE:
  -               Attr sattr = (Attr)importedNode;
  -               Attr attr = createAttribute(sattr.getName());
  -               attr.setValue(sattr.getValue());
  -               result = attr;
  -               break;
  -
  -            case Node.CDATA_SECTION_NODE:
  -               result = createCDATASection(importedNode.getNodeValue());
  -               break;
  -
  -            case Node.COMMENT_NODE:
  -               result = createComment(importedNode.getNodeValue());
  -               break;
  -
  -            case Node.ELEMENT_NODE:
  -               Element selem = (Element)importedNode;
  -               Element elem = createElement(selem.getTagName());
  -               NamedNodeMap attrs = selem.getAttributes();
  -               int size = attrs.getLength();
  -               for ( int i = 0; i < size; i++ ) {
  -                  Attr a = (Attr)attrs.item(i);
  -                  Attr ai = createAttribute(a.getName());
  -                  ai.setValue(a.getValue());
  -                  elem.setAttributeNode(ai);
  -               }
  -               result = elem;
  -               importNamespaces(importedNode, result);
  -               break;
  -
  -            case Node.ENTITY_REFERENCE_NODE:
  -               result = createEntityReference(importedNode.getNodeValue());
  -               break;
  -
  -            case Node.PROCESSING_INSTRUCTION_NODE:
  -               result = createProcessingInstruction(importedNode.getNodeName(), importedNode.getNodeValue());
  -               break;
  -
  -            case Node.TEXT_NODE:
  -               result = createTextNode(importedNode.getNodeValue());
  -               break;
  -
  -            default:
  -         }
  -
  -         if ( deep && result != null ) {
  -            NodeList list = importedNode.getChildNodes();
  -            int size = list.getLength();
  -            for ( int i = 0; i < size; i++ ) {
  -               Node n = list.item(i);
  -               result.appendChild(importNode(n, deep));
  +        ProcessingInstruction pi = createProcessingInstruction(CACHE_CONTROL, caching ? CACHE : NOCACHE);
  +        insertBefore(pi, getDocumentElement());
  +    }
  +
  +    public SymbolTable getSymbols() {
  +        return symbols;
  +    }
  +
  +    public void setSymbols(SymbolTable symbols) {
  +        this.symbols = symbols;
  +    }
  +
  +    public void expandSource() {
  +        ElementImpl e = (ElementImpl) getDocumentElement();
  +        if (e != null)
  +            e.expandSource();
  +    }
  +
  +    public Node getNodeAtPos(int pos) {
  +        return null; // TODO: This
  +    }
  +
  +    public short getNodeType() {
  +        return Node.DOCUMENT_NODE;
  +    }
  +
  +    public String getNodeName() {
  +        return "#document";
  +    }
  +
  +    /**
  +     * The Document Type Declaration (see <code>DocumentType</code>) associated
  +     * with  this document. For HTML documents as well as XML documents without
  +     * a document type declaration this returns <code>null</code>. The DOM Level
  +     *  1 does not support editing the Document Type Declaration, therefore
  +     * <code>docType</code> cannot be altered in any way.
  +     */
  +    public DocumentType getDoctype() {
  +        return docType;
  +    }
  +
  +    public void setDoctype(DocumentType docType) {
  +        this.docType = docType;
  +    }
  +
  +    /**
  +     * The <code>DOMImplementation</code> object that handles this document. A
  +     * DOM application may use objects from multiple  implementations.
  +     */
  +    public DOMImplementation getImplementation() {
  +        return DOMImplementationImpl.getInstance();
  +    }
  +
  +    /**
  +     * Creates a <code>Text</code> node given the specified string.
  +     * @param data The data for the node.
  +     * @return The new <code>Text</code> object.
  +     */
  +    public Text createTextNode(String data) {
  +        return new TextImpl(this, data);
  +    }
  +
  +    /**
  +     * This is a convenience attribute that allows direct access to the child
  +     * node that is the root element of  the document. For HTML documents, this
  +     * is the element with the tagName "HTML".
  +     */
  +    public Element getDocumentElement() {
  +        checkLoaded();
  +        Iterator enum = childNodes.iterator();
  +        while (enum.hasNext()) {
  +            Node node = (Node) enum.next();
  +            if (node.getNodeType() == Node.ELEMENT_NODE)
  +                return (Element) node;
  +        }
  +        return null;
  +    }
  +
  +    /**
  +     * Creates a <code>CDATASection</code> node whose value  is the specified
  +     * string.
  +     * @param data The data for the <code>CDATASection</code> contents.
  +     * @return The new <code>CDATASection</code> object.
  +     * @exception DOMException
  +     *   NOT_SUPPORTED_ERR: Raised if this document is an HTML document.
  +     */
  +    public CDATASection createCDATASection(String data) throws DOMException {
  +        return new CDATASectionImpl(this, data);
  +    }
  +
  +    /**
  +     * Creates an element of the type specified. Note that the instance returned
  +     * implements the Element interface, so attributes can be specified
  +     * directly  on the returned object.
  +     * @param tagName The name of the element type to instantiate. For XML, this
  +     *   is case-sensitive. For HTML, the  <code>tagName</code> parameter may
  +     *   be provided in any case,  but it must be mapped to the canonical
  +     *   uppercase form by  the DOM implementation.
  +     * @return A new <code>Element</code> object.
  +     * @exception DOMException
  +     *   INVALID_CHARACTER_ERR: Raised if the specified name contains an
  +     *   invalid character.
  +     */
  +    public Element createElement(String tagName) throws DOMException {
  +        return new ElementImpl(this, tagName);
  +    }
  +
  +    /**
  +     * Creates an empty <code>DocumentFragment</code> object.
  +     * @return A new <code>DocumentFragment</code>.
  +     */
  +    public DocumentFragment createDocumentFragment() {
  +        return new DocumentFragmentImpl(this);
  +    }
  +
  +    /**
  +     * Creates an <code>Attr</code> of the given name. Note that the
  +     * <code>Attr</code> instance can then be set on an <code>Element</code>
  +     * using the <code>setAttribute</code> method.
  +     * @param name The name of the attribute.
  +     * @return A new <code>Attr</code> object.
  +     * @exception DOMException
  +     *   INVALID_CHARACTER_ERR: Raised if the specified name contains an
  +     *   invalid character.
  +     */
  +    public Attr createAttribute(String name) throws DOMException {
  +        return new AttrImpl(this, name);
  +    }
  +
  +    /**
  +     * Creates a <code>Comment</code> node given the specified string.
  +     * @param data The data for the node.
  +     * @return The new <code>Comment</code> object.
  +     */
  +    public Comment createComment(String data) {
  +        return new CommentImpl(this, data);
  +    }
  +
  +    /**
  +     * Creates a <code>ProcessingInstruction</code> node given the specified
  +     * name and data strings.
  +     * @param target The target part of the processing instruction.
  +     * @param data The data for the node.
  +     * @return The new <code>ProcessingInstruction</code> object.
  +     * @exception DOMException
  +     *   INVALID_CHARACTER_ERR: Raised if an invalid character is specified.
  +     *   <br>NOT_SUPPORTED_ERR: Raised if this document is an HTML document.
  +     */
  +    public ProcessingInstruction createProcessingInstruction(String target, String data) throws DOMException {
  +        return new ProcessingInstructionImpl(this, target, data);
  +    }
  +
  +    /**
  +     * Creates an EntityReference object.
  +     * @param name The name of the entity to reference.
  +     * @return The new <code>EntityReference</code> object.
  +     * @exception DOMException
  +     *   INVALID_CHARACTER_ERR: Raised if the specified name contains an
  +     *   invalid character.
  +     *   <br>NOT_SUPPORTED_ERR: Raised if this document is an HTML document.
  +     */
  +    public EntityReference createEntityReference(String name) throws DOMException {
  +        return new EntityReferenceImpl(this, name);
  +    }
  +
  +    private void importNamespaces(Node source, Node target) {
  +        if (target.getNodeType() == Node.ELEMENT_NODE) {
  +            // Retrieve Namespace definitions in scope
  +            Set set = new HashSet();
  +            Node n = source;
  +            Element elem = (Element) target;
  +            while (n != null) {
  +                NamedNodeMap nm = n.getAttributes();
  +                for (int i = 0; i < nm.getLength(); i++) {
  +                    Attr a = (Attr) nm.item(i);
  +                    String name = a.getNodeName();
  +                    if ((name.startsWith("xmlns:") || name.equals("xmlns")) && !set.contains(name)) {
  +                        set.add(name);
  +                        elem.setAttribute(name, a.getValue());
  +                    }
  +                }
  +                n = n.getParentNode();
  +                if (n.getNodeType() == DOCUMENT_NODE || n.getNodeType() == DOCUMENT_FRAGMENT_NODE)
  +                    n = null;
               }
  -         }
  +        }
  +    }
   
  -         return result;
  -      }
  -      catch ( Exception e ) {
  -         if (log.isDebugEnabled()) {
  -            log.debug("No message", e);
  -         }
  -         return null;
  -      }
  -   }
  -
  -   public Element createElementNS(String namespaceURI, String qualifiedName) {
  -      return new ElementImpl(this, qualifiedName);
  -   }
  -
  -   public Attr createAttributeNS(String namespaceURI, String qualifiedName) {
  -      return new AttrImpl(this, qualifiedName);
  -   }
  -
  -   public NodeIterator createNodeIterator(Node root, int whatToShow, NodeFilter filter, boolean entityReferenceExpansion) throws DOMException {
  -      return new TreeWalkerImpl(root, whatToShow, filter, entityReferenceExpansion);
  -   }
  -
  -   public TreeWalker createTreeWalker(Node root, int whatToShow, NodeFilter filter, boolean entityReferenceExpansion) throws DOMException {
  -      return new TreeWalkerImpl(root, whatToShow, filter, entityReferenceExpansion);
  -   }
  -
  -   // DOM Level 3 Stuff
  -
  -   public Node adoptNode(Node src) {
  -      // If we're a Xindice DOM Node and share the same symbol table
  -      // or the adopted node has no symbol table, then we're golden
  -      if ( src instanceof NodeImpl ) {
  -         NodeImpl impl = (NodeImpl)src;
  -         DocumentImpl docImpl = (DocumentImpl)impl.getOwnerDocument();
  -         if ( docImpl.getSymbols() == null || docImpl.getSymbols() == symbols ) {
  -            impl.getParentNode().removeChild(impl);
  -            impl.setParentNode(this);
  -            return impl;
  -         }
  -      }
  -      return importNode(src, true);
  -   }
  -
  -   public String getActualEncoding() {
  -      checkLoaded();
  -      return actualEncoding;
  -   }
  -
  -   public void setActualEncoding(String actualEncoding) {
  -      checkReadOnly();
  -      checkLoaded();
  -      this.actualEncoding = actualEncoding;
  -   }
  -
  -   public String getEncoding() {
  -      checkLoaded();
  -      return encoding;
  -   }
  -
  -   public void setEncoding(String encoding) {
  -      checkReadOnly();
  -      checkLoaded();
  -      this.encoding = encoding;
  -   }
  -
  -   public String getVersion() {
  -      checkLoaded();
  -      return version;
  -   }
  -
  -   public void setVersion(String version) {
  -      checkReadOnly();
  -      checkLoaded();
  -      this.version = version;
  -   }
  -
  -   public boolean getStandalone() {
  -      checkLoaded();
  -      return standalone;
  -   }
  -
  -   public void setStandalone(boolean standalone) {
  -      checkReadOnly();
  -      checkLoaded();
  -      this.standalone = standalone;
  -   }
  -
  -   public boolean getStrictErrorChecking() {
  -      checkLoaded();
  -      return strictErrorChecking;
  -   }
  -
  -   public void setStrictErrorChecking(boolean strictErrorChecking) {
  -      checkReadOnly();
  -      checkLoaded();
  -      this.strictErrorChecking = strictErrorChecking;
  -   }
  -}
  +    public Node importNode(Node importedNode, boolean deep) {
  +        try {
  +            // If we're a Xindice DOM Node and share the same symbol table,
  +            // then we're golden
  +            if (importedNode instanceof NodeImpl) {
  +                NodeImpl impl = (NodeImpl) importedNode;
  +                DocumentImpl docImpl = (DocumentImpl) impl.getOwnerDocument();
  +                if (docImpl.getSymbols() != null && (docImpl.getSymbols() == symbols)) {
  +                    NodeImpl clone = (NodeImpl) impl.cloneNode(deep);
  +                    clone.setParentNode(this);
  +                    importNamespaces(importedNode, clone);
  +                    return clone;
  +                }
  +            }
  +
  +            // Crap, we have to do a full graph copy
  +            Node result = null;
  +            switch (importedNode.getNodeType()) {
  +                case Node.ATTRIBUTE_NODE :
  +                    Attr sattr = (Attr) importedNode;
  +                    Attr attr = createAttribute(sattr.getName());
  +                    attr.setValue(sattr.getValue());
  +                    result = attr;
  +                    break;
  +
  +                case Node.CDATA_SECTION_NODE :
  +                    result = createCDATASection(importedNode.getNodeValue());
  +                    break;
  +
  +                case Node.COMMENT_NODE :
  +                    result = createComment(importedNode.getNodeValue());
  +                    break;
  +
  +                case Node.ELEMENT_NODE :
  +                    Element selem = (Element) importedNode;
  +                    Element elem = createElement(selem.getTagName());
  +                    NamedNodeMap attrs = selem.getAttributes();
  +                    int size = attrs.getLength();
  +                    for (int i = 0; i < size; i++) {
  +                        Attr a = (Attr) attrs.item(i);
  +                        Attr ai = createAttribute(a.getName());
  +                        ai.setValue(a.getValue());
  +                        elem.setAttributeNode(ai);
  +                    }
  +                    result = elem;
  +                    importNamespaces(importedNode, result);
  +                    break;
  +
  +                case Node.ENTITY_REFERENCE_NODE :
  +                    result = createEntityReference(importedNode.getNodeValue());
  +                    break;
  +
  +                case Node.PROCESSING_INSTRUCTION_NODE :
  +                    result = createProcessingInstruction(importedNode.getNodeName(), importedNode.getNodeValue());
  +                    break;
  +
  +                case Node.TEXT_NODE :
  +                    result = createTextNode(importedNode.getNodeValue());
  +                    break;
  +
  +                default :
  +                    }
  +
  +            if (deep && result != null) {
  +                NodeList list = importedNode.getChildNodes();
  +                int size = list.getLength();
  +                for (int i = 0; i < size; i++) {
  +                    Node n = list.item(i);
  +                    result.appendChild(importNode(n, deep));
  +                }
  +            }
   
  +            return result;
  +        }
  +        catch (Exception e) {
  +            log.warn(e);
  +            return null;
  +        }
  +    }
  +
  +    public Element createElementNS(String namespaceURI, String qualifiedName) {
  +        return new ElementImpl(this, qualifiedName);
  +    }
  +
  +    public Attr createAttributeNS(String namespaceURI, String qualifiedName) {
  +        return new AttrImpl(this, qualifiedName);
  +    }
  +
  +    public NodeIterator createNodeIterator(Node root, int whatToShow, NodeFilter filter, boolean entityReferenceExpansion) throws DOMException {
  +        return new TreeWalkerImpl(root, whatToShow, filter, entityReferenceExpansion);
  +    }
  +
  +    public TreeWalker createTreeWalker(Node root, int whatToShow, NodeFilter filter, boolean entityReferenceExpansion) throws DOMException {
  +        return new TreeWalkerImpl(root, whatToShow, filter, entityReferenceExpansion);
  +    }
  +
  +    // DOM Level 3 Stuff
  +
  +    public Node adoptNode(Node src) {
  +        // If we're a Xindice DOM Node and share the same symbol table
  +        // or the adopted node has no symbol table, then we're golden
  +        if (src instanceof NodeImpl) {
  +            NodeImpl impl = (NodeImpl) src;
  +            DocumentImpl docImpl = (DocumentImpl) impl.getOwnerDocument();
  +            if (docImpl.getSymbols() == null || docImpl.getSymbols() == symbols) {
  +                impl.getParentNode().removeChild(impl);
  +                impl.setParentNode(this);
  +                return impl;
  +            }
  +        }
  +        return importNode(src, true);
  +    }
  +
  +    public String getActualEncoding() {
  +        checkLoaded();
  +        return actualEncoding;
  +    }
  +
  +    public void setActualEncoding(String actualEncoding) {
  +        checkReadOnly();
  +        checkLoaded();
  +        this.actualEncoding = actualEncoding;
  +    }
  +
  +    public String getEncoding() {
  +        checkLoaded();
  +        return encoding;
  +    }
  +
  +    public void setEncoding(String encoding) {
  +        checkReadOnly();
  +        checkLoaded();
  +        this.encoding = encoding;
  +    }
  +
  +    public String getVersion() {
  +        checkLoaded();
  +        return version;
  +    }
  +
  +    public void setVersion(String version) {
  +        checkReadOnly();
  +        checkLoaded();
  +        this.version = version;
  +    }
  +
  +    public boolean getStandalone() {
  +        checkLoaded();
  +        return standalone;
  +    }
  +
  +    public void setStandalone(boolean standalone) {
  +        checkReadOnly();
  +        checkLoaded();
  +        this.standalone = standalone;
  +    }
  +
  +    public boolean getStrictErrorChecking() {
  +        checkLoaded();
  +        return strictErrorChecking;
  +    }
  +
  +    public void setStrictErrorChecking(boolean strictErrorChecking) {
  +        checkReadOnly();
  +        checkLoaded();
  +        this.strictErrorChecking = strictErrorChecking;
  +    }
  +}
  
  
  
  1.5       +203 -208  xml-xindice/java/src/org/apache/xindice/xml/dom/CharacterDataImpl.java
  
  Index: CharacterDataImpl.java
  ===================================================================
  RCS file: /home/cvs/xml-xindice/java/src/org/apache/xindice/xml/dom/CharacterDataImpl.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- CharacterDataImpl.java	31 Oct 2002 07:02:23 -0000	1.4
  +++ CharacterDataImpl.java	15 Jul 2003 15:44:34 -0000	1.5
  @@ -59,14 +59,13 @@
    * $Id$
    */
   
  +import org.apache.commons.logging.Log;
  +import org.apache.commons.logging.LogFactory;
   import org.apache.xindice.util.ByteArrayInput;
   import org.apache.xindice.xml.SymbolTable;
   import org.apache.xindice.xml.XMLCompressedInput;
  -
  -import org.apache.commons.logging.Log;
  -import org.apache.commons.logging.LogFactory;
  -
  -import org.w3c.dom.*;
  +import org.w3c.dom.CharacterData;
  +import org.w3c.dom.DOMException;
   
   /**
    * CharacterDataImpl
  @@ -74,207 +73,203 @@
   
   public abstract class CharacterDataImpl extends NodeImpl implements CharacterData {
   
  -   private static Log log = LogFactory.getLog("org.apache.xindice.xml");
  +    private static Log log = LogFactory.getLog("org.apache.xindice.xml");
   
  -   public CharacterDataImpl() {
  -   }
  -   
  -   public CharacterDataImpl(NodeImpl parentNode, byte[] data, int pos, int len) {
  -      super(parentNode, data, pos, len);
  -   }
  -
  -   public CharacterDataImpl(NodeImpl parentNode, boolean dirty) {
  -      super(parentNode, dirty);
  -   }
  -
  -   public CharacterDataImpl(NodeImpl parentNode, String nodeValue) {
  -      super(parentNode, true);
  -      if ( nodeValue == null )
  -         nodeValue = "";
  -      this.nodeValue = nodeValue;
  -   }
  -
  -   protected final void checkLoaded() {
  -       if ( loaded )
  -         return;
  -      else
  -         loaded = true;
  -
  -      try {
  -         if ( data != null ) {
  -            DocumentImpl doc = (DocumentImpl)getOwnerDocument();
  -            SymbolTable st = doc.getSymbols();
  -
  -            ByteArrayInput bis = new ByteArrayInput(data, pos, len);
  -            XMLCompressedInput xci = new XMLCompressedInput(bis, st);
  -
  -            xci.readSignature(); // Skip The Signature
  -            if ( getNodeType() == TEXT_NODE)
  -               xci.readContentSize();
  -            else
  -               xci.readInt();
  -
  -            byte[] buf = new byte[bis.available()];
  -            xci.read(buf);
  -            nodeValue = new String(buf, "UTF-8");
  -         }
  -      }
  -      catch ( Exception e ) {
  -         if (log.isDebugEnabled()) {
  -            log.debug("No message", e);
  -         }
  -      }
  -   }
  -
  -   public final void setNodeValue(String nodeValue) throws DOMException {
  -      checkLoaded();
  -      checkReadOnly();
  -      if ( nodeValue == null )
  -         nodeValue = "";
  -      this.nodeValue = nodeValue;
  -      setDirty();
  -   }
  -
  -   /**
  -    * Extracts a range of data from the node.
  -    * @param offset Start offset of substring to extract.
  -    * @param count The number of characters to extract.
  -    * @return The specified substring. If the sum of <code>offset</code> and
  -    *   <code>count</code> exceeds the <code>length</code>, then all
  -    *   characters to the end of the data are returned.
  -    * @exception DOMException
  -    *   INDEX_SIZE_ERR: Raised if the specified offset is negative or greater
  -    *   than the number of characters in <code>data</code>, or if the
  -    *   specified <code>count</code> is negative.
  -    *   <br>DOMSTRING_SIZE_ERR: Raised if the specified range of text does not
  -    *   fit into a <code>DOMString</code>.
  -    */
  -   public final String substringData(int offset, int count) throws DOMException {
  -      try {
  -         return nodeValue.substring(offset, offset+count);
  -      }
  -      catch ( Exception e ) {
  -         throw EX_INDEX_SIZE;
  -      }
  -   }
  -
  -   /**
  -    * The character data of the node that implements this interface. The DOM
  -    * implementation may not put arbitrary limits on the amount of data that
  -    * may be stored in a  <code>CharacterData</code> node. However,
  -    * implementation limits may  mean that the entirety of a node's data may
  -    * not fit into a single <code>DOMString</code>. In such cases, the user
  -    * may call <code>substringData</code> to retrieve the data in
  -    * appropriately sized pieces.
  -    * @exception DOMException
  -    *   NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly.
  -    * @exception DOMException
  -    *   DOMSTRING_SIZE_ERR: Raised when it would return more characters than
  -    *   fit in a <code>DOMString</code> variable on the implementation
  -    *   platform.
  -    */
  -   public final String getData() throws DOMException {
  -      return getNodeValue();
  -   }
  -
  -   public final void setData(String data) throws DOMException {
  -      setNodeValue(data);
  -   }
  -
  -   /**
  -    * Insert a string at the specified character offset.
  -    * @param offset The character offset at which to insert.
  -    * @param arg The <code>DOMString</code> to insert.
  -    * @exception DOMException
  -    *   INDEX_SIZE_ERR: Raised if the specified offset is negative or greater
  -    *   than the number of characters in <code>data</code>.
  -    *   <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
  -    */
  -   public final void insertData(int offset, String arg) throws DOMException {
  -      String value = getNodeValue();
  -      checkReadOnly();
  -      try {
  -         setNodeValue(value.substring(0, offset) + arg + value.substring(offset+1));
  -      }
  -      catch ( Exception e ) {
  -         throw EX_INDEX_SIZE;
  -      }
  -   }
  -
  -   /**
  -    * The number of characters that are available through <code>data</code> and
  -    * the <code>substringData</code> method below.  This may have the value
  -    * zero,  i.e., <code>CharacterData</code> nodes may be empty.
  -    */
  -   public final int getLength() {
  -      return getNodeValue().length();
  -   }
  -
  -   /**
  -    * Replace the characters starting at the specified character offset with
  -    * the specified string.
  -    * @param offset The offset from which to start replacing.
  -    * @param count The number of characters to replace. If the sum of
  -    *   <code>offset</code> and <code>count</code> exceeds <code>length</code>
  -    *   , then all characters to the end of the data are replaced (i.e., the
  -    *   effect is the same as a <code>remove</code> method call with the same
  -    *   range, followed by an <code>append</code> method invocation).
  -    * @param arg The <code>DOMString</code> with which the range must be
  -    *   replaced.
  -    * @exception DOMException
  -    *   INDEX_SIZE_ERR: Raised if the specified offset is negative or greater
  -    *   than the number of characters in <code>data</code>, or if the
  -    *   specified <code>count</code> is negative.
  -    *   <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
  -    */
  -   public final void replaceData(int offset, int count, String arg) throws DOMException {
  -      String value = getNodeValue();
  -      checkReadOnly();
  -      try {
  -         setNodeValue(value.substring(0, offset) + arg + value.substring(offset+count));
  -      }
  -      catch ( Exception e ) {
  -         throw EX_INDEX_SIZE;
  -      }
  -   }
  -
  -   /**
  -    * Append the string to the end of the character data of the node. Upon
  -    * success, <code>data</code> provides access to the concatenation of
  -    * <code>data</code> and the <code>DOMString</code> specified.
  -    * @param arg The <code>DOMString</code> to append.
  -    * @exception DOMException
  -    *   NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
  -    */
  -   public final void appendData(String arg) throws DOMException {
  -      String value = getNodeValue();
  -      checkReadOnly();
  -      setNodeValue(value + arg);
  -   }
  -
  -   /**
  -    * Remove a range of characters from the node. Upon success,
  -    * <code>data</code> and <code>length</code> reflect the change.
  -    * @param offset The offset from which to remove characters.
  -    * @param count The number of characters to delete. If the sum of
  -    *   <code>offset</code> and <code>count</code> exceeds <code>length</code>
  -    *   then all characters from <code>offset</code> to the end of the data
  -    *   are deleted.
  -    * @exception DOMException
  -    *   INDEX_SIZE_ERR: Raised if the specified offset is negative or greater
  -    *   than the number of characters in <code>data</code>, or if the
  -    *   specified <code>count</code> is negative.
  -    *   <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
  -    */
  -   public final void deleteData(int offset, int count) throws DOMException {
  -      String value = getNodeValue();
  -      checkReadOnly();
  -      try {
  -         setNodeValue(value.substring(0, offset) + value.substring(offset+count));
  -      }
  -      catch ( Exception e ) {
  -         throw EX_INDEX_SIZE;
  -      }
  -   }
  -}
  +    public CharacterDataImpl() {}
   
  +    public CharacterDataImpl(NodeImpl parentNode, byte[] data, int pos, int len) {
  +        super(parentNode, data, pos, len);
  +    }
  +
  +    public CharacterDataImpl(NodeImpl parentNode, boolean dirty) {
  +        super(parentNode, dirty);
  +    }
  +
  +    public CharacterDataImpl(NodeImpl parentNode, String nodeValue) {
  +        super(parentNode, true);
  +        if (nodeValue == null)
  +            nodeValue = "";
  +        this.nodeValue = nodeValue;
  +    }
  +
  +    protected final void checkLoaded() {
  +        if (loaded)
  +            return;
  +        else
  +            loaded = true;
  +
  +        try {
  +            if (data != null) {
  +                DocumentImpl doc = (DocumentImpl) getOwnerDocument();
  +                SymbolTable st = doc.getSymbols();
  +
  +                ByteArrayInput bis = new ByteArrayInput(data, pos, len);
  +                XMLCompressedInput xci = new XMLCompressedInput(bis, st);
  +
  +                xci.readSignature(); // Skip The Signature
  +                if (getNodeType() == TEXT_NODE)
  +                    xci.readContentSize();
  +                else
  +                    xci.readInt();
  +
  +                byte[] buf = new byte[bis.available()];
  +                xci.read(buf);
  +                nodeValue = new String(buf, "UTF-8");
  +            }
  +        }
  +        catch (Exception e) {
  +            log.warn(e);
  +        }
  +    }
  +
  +    public final void setNodeValue(String nodeValue) throws DOMException {
  +        checkLoaded();
  +        checkReadOnly();
  +        if (nodeValue == null)
  +            nodeValue = "";
  +        this.nodeValue = nodeValue;
  +        setDirty();
  +    }
  +
  +    /**
  +     * Extracts a range of data from the node.
  +     * @param offset Start offset of substring to extract.
  +     * @param count The number of characters to extract.
  +     * @return The specified substring. If the sum of <code>offset</code> and
  +     *   <code>count</code> exceeds the <code>length</code>, then all
  +     *   characters to the end of the data are returned.
  +     * @exception DOMException
  +     *   INDEX_SIZE_ERR: Raised if the specified offset is negative or greater
  +     *   than the number of characters in <code>data</code>, or if the
  +     *   specified <code>count</code> is negative.
  +     *   <br>DOMSTRING_SIZE_ERR: Raised if the specified range of text does not
  +     *   fit into a <code>DOMString</code>.
  +     */
  +    public final String substringData(int offset, int count) throws DOMException {
  +        try {
  +            return nodeValue.substring(offset, offset + count);
  +        }
  +        catch (Exception e) {
  +            throw EX_INDEX_SIZE;
  +        }
  +    }
  +
  +    /**
  +     * The character data of the node that implements this interface. The DOM
  +     * implementation may not put arbitrary limits on the amount of data that
  +     * may be stored in a  <code>CharacterData</code> node. However,
  +     * implementation limits may  mean that the entirety of a node's data may
  +     * not fit into a single <code>DOMString</code>. In such cases, the user
  +     * may call <code>substringData</code> to retrieve the data in
  +     * appropriately sized pieces.
  +     * @exception DOMException
  +     *   NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly.
  +     * @exception DOMException
  +     *   DOMSTRING_SIZE_ERR: Raised when it would return more characters than
  +     *   fit in a <code>DOMString</code> variable on the implementation
  +     *   platform.
  +     */
  +    public final String getData() throws DOMException {
  +        return getNodeValue();
  +    }
  +
  +    public final void setData(String data) throws DOMException {
  +        setNodeValue(data);
  +    }
  +
  +    /**
  +     * Insert a string at the specified character offset.
  +     * @param offset The character offset at which to insert.
  +     * @param arg The <code>DOMString</code> to insert.
  +     * @exception DOMException
  +     *   INDEX_SIZE_ERR: Raised if the specified offset is negative or greater
  +     *   than the number of characters in <code>data</code>.
  +     *   <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
  +     */
  +    public final void insertData(int offset, String arg) throws DOMException {
  +        String value = getNodeValue();
  +        checkReadOnly();
  +        try {
  +            setNodeValue(value.substring(0, offset) + arg + value.substring(offset + 1));
  +        }
  +        catch (Exception e) {
  +            throw EX_INDEX_SIZE;
  +        }
  +    }
  +
  +    /**
  +     * The number of characters that are available through <code>data</code> and
  +     * the <code>substringData</code> method below.  This may have the value
  +     * zero,  i.e., <code>CharacterData</code> nodes may be empty.
  +     */
  +    public final int getLength() {
  +        return getNodeValue().length();
  +    }
  +
  +    /**
  +     * Replace the characters starting at the specified character offset with
  +     * the specified string.
  +     * @param offset The offset from which to start replacing.
  +     * @param count The number of characters to replace. If the sum of
  +     *   <code>offset</code> and <code>count</code> exceeds <code>length</code>
  +     *   , then all characters to the end of the data are replaced (i.e., the
  +     *   effect is the same as a <code>remove</code> method call with the same
  +     *   range, followed by an <code>append</code> method invocation).
  +     * @param arg The <code>DOMString</code> with which the range must be
  +     *   replaced.
  +     * @exception DOMException
  +     *   INDEX_SIZE_ERR: Raised if the specified offset is negative or greater
  +     *   than the number of characters in <code>data</code>, or if the
  +     *   specified <code>count</code> is negative.
  +     *   <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
  +     */
  +    public final void replaceData(int offset, int count, String arg) throws DOMException {
  +        String value = getNodeValue();
  +        checkReadOnly();
  +        try {
  +            setNodeValue(value.substring(0, offset) + arg + value.substring(offset + count));
  +        }
  +        catch (Exception e) {
  +            throw EX_INDEX_SIZE;
  +        }
  +    }
  +
  +    /**
  +     * Append the string to the end of the character data of the node. Upon
  +     * success, <code>data</code> provides access to the concatenation of
  +     * <code>data</code> and the <code>DOMString</code> specified.
  +     * @param arg The <code>DOMString</code> to append.
  +     * @exception DOMException
  +     *   NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
  +     */
  +    public final void appendData(String arg) throws DOMException {
  +        String value = getNodeValue();
  +        checkReadOnly();
  +        setNodeValue(value + arg);
  +    }
  +
  +    /**
  +     * Remove a range of characters from the node. Upon success,
  +     * <code>data</code> and <code>length</code> reflect the change.
  +     * @param offset The offset from which to remove characters.
  +     * @param count The number of characters to delete. If the sum of
  +     *   <code>offset</code> and <code>count</code> exceeds <code>length</code>
  +     *   then all characters from <code>offset</code> to the end of the data
  +     *   are deleted.
  +     * @exception DOMException
  +     *   INDEX_SIZE_ERR: Raised if the specified offset is negative or greater
  +     *   than the number of characters in <code>data</code>, or if the
  +     *   specified <code>count</code> is negative.
  +     *   <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
  +     */
  +    public final void deleteData(int offset, int count) throws DOMException {
  +        String value = getNodeValue();
  +        checkReadOnly();
  +        try {
  +            setNodeValue(value.substring(0, offset) + value.substring(offset + count));
  +        }
  +        catch (Exception e) {
  +            throw EX_INDEX_SIZE;
  +        }
  +    }
  +}
  
  
  
  1.6       +88 -92    xml-xindice/java/src/org/apache/xindice/xml/dom/ProcessingInstructionImpl.java
  
  Index: ProcessingInstructionImpl.java
  ===================================================================
  RCS file: /home/cvs/xml-xindice/java/src/org/apache/xindice/xml/dom/ProcessingInstructionImpl.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- ProcessingInstructionImpl.java	4 Nov 2002 06:39:55 -0000	1.5
  +++ ProcessingInstructionImpl.java	15 Jul 2003 15:44:34 -0000	1.6
  @@ -59,14 +59,14 @@
    * $Id$
    */
   
  +import org.apache.commons.logging.Log;
  +import org.apache.commons.logging.LogFactory;
   import org.apache.xindice.util.ByteArrayInput;
   import org.apache.xindice.xml.SymbolTable;
   import org.apache.xindice.xml.XMLCompressedInput;
  -
  -import org.apache.commons.logging.Log;
  -import org.apache.commons.logging.LogFactory;
  -
  -import org.w3c.dom.*;
  +import org.w3c.dom.DOMException;
  +import org.w3c.dom.Node;
  +import org.w3c.dom.ProcessingInstruction;
   
   /**
    * ProcessingInstructionImpl
  @@ -74,91 +74,87 @@
   
   public final class ProcessingInstructionImpl extends NodeImpl implements ProcessingInstruction {
   
  -   private static Log log = LogFactory.getLog("org.apache.xindice.xml");
  -
  -   public ProcessingInstructionImpl() {
  -   }
  -   
  -   public ProcessingInstructionImpl(NodeImpl parentNode, byte[] data, int pos, int len) {
  -      super(parentNode, data, pos, len);
  -   }
  -
  -   public ProcessingInstructionImpl(NodeImpl parentNode, boolean dirty) {
  -      super(parentNode, dirty);
  -   }
  -
  -   public ProcessingInstructionImpl(NodeImpl parentNode, String nodeName, String nodeValue) {
  -      super(parentNode, true);
  -      this.nodeName = nodeName;
  -      this.nodeValue = nodeValue;
  -   }
  -
  -   protected void checkLoaded() {
  -      if ( loaded )
  -         return;
  -      else
  -         loaded = true;
  -
  -      try {
  -         if ( data != null ) {
  -            DocumentImpl doc = (DocumentImpl)getOwnerDocument();
  -            SymbolTable st = doc.getSymbols();
  -
  -            ByteArrayInput bis = new ByteArrayInput(data, pos, len);
  -            XMLCompressedInput xci = new XMLCompressedInput(bis, st);
  -
  -            xci.readSignature();      // Skip The Signature
  -            /* TODO why is it used for? int size = */ xci.readInt();
  -
  -            byte[] buf = new byte[bis.available()];
  -            xci.read(buf);
  -
  -            String value = new String(buf, "UTF-8");
  -            int i = value.indexOf(' ');
  -            nodeName = value.substring(0, i);
  -            nodeValue = value.substring(i+1);
  -         }
  -      }
  -      catch ( Exception e ) {
  -         if (log.isDebugEnabled()) {
  -            log.debug("No message", e);
  -         }
  -      }
  -   }
  -
  -   public short getNodeType() {
  -      return Node.PROCESSING_INSTRUCTION_NODE;
  -   }
  -
  -   public void setNodeValue(String nodeValue) throws DOMException {
  -      checkLoaded();
  -      checkReadOnly();
  -      this.nodeValue = nodeValue;
  -      setDirty();
  -   }
  -
  -   /**
  -    * The target of this processing instruction. XML defines this as being the
  -    * first token following the markup that begins the processing instruction.
  -    */
  -   public String getTarget() {
  -      return getNodeName();
  -   }
  -
  -   /**
  -    * The content of this processing instruction. This is from the first non
  -    * white space character after the target to the character immediately
  -    * preceding the <code>?&gt;</code>.
  -    * @exception DOMException
  -    *   NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly.
  -    */
  -   public String getData() {
  -      return getNodeValue();
  -   }
  -
  -   public void setData(String data) throws DOMException {
  -      setNodeValue(data);
  -   }
  -}
  +    private static Log log = LogFactory.getLog("org.apache.xindice.xml");
   
  +    public ProcessingInstructionImpl() {}
   
  +    public ProcessingInstructionImpl(NodeImpl parentNode, byte[] data, int pos, int len) {
  +        super(parentNode, data, pos, len);
  +    }
  +
  +    public ProcessingInstructionImpl(NodeImpl parentNode, boolean dirty) {
  +        super(parentNode, dirty);
  +    }
  +
  +    public ProcessingInstructionImpl(NodeImpl parentNode, String nodeName, String nodeValue) {
  +        super(parentNode, true);
  +        this.nodeName = nodeName;
  +        this.nodeValue = nodeValue;
  +    }
  +
  +    protected void checkLoaded() {
  +        if (loaded)
  +            return;
  +        else
  +            loaded = true;
  +
  +        try {
  +            if (data != null) {
  +                DocumentImpl doc = (DocumentImpl) getOwnerDocument();
  +                SymbolTable st = doc.getSymbols();
  +
  +                ByteArrayInput bis = new ByteArrayInput(data, pos, len);
  +                XMLCompressedInput xci = new XMLCompressedInput(bis, st);
  +
  +                xci.readSignature(); // Skip The Signature
  +                /* TODO why is it used for? int size = */
  +                xci.readInt();
  +
  +                byte[] buf = new byte[bis.available()];
  +                xci.read(buf);
  +
  +                String value = new String(buf, "UTF-8");
  +                int i = value.indexOf(' ');
  +                nodeName = value.substring(0, i);
  +                nodeValue = value.substring(i + 1);
  +            }
  +        }
  +        catch (Exception e) {
  +            log.warn(e);
  +        }
  +    }
  +
  +    public short getNodeType() {
  +        return Node.PROCESSING_INSTRUCTION_NODE;
  +    }
  +
  +    public void setNodeValue(String nodeValue) throws DOMException {
  +        checkLoaded();
  +        checkReadOnly();
  +        this.nodeValue = nodeValue;
  +        setDirty();
  +    }
  +
  +    /**
  +     * The target of this processing instruction. XML defines this as being the
  +     * first token following the markup that begins the processing instruction.
  +     */
  +    public String getTarget() {
  +        return getNodeName();
  +    }
  +
  +    /**
  +     * The content of this processing instruction. This is from the first non
  +     * white space character after the target to the character immediately
  +     * preceding the <code>?&gt;</code>.
  +     * @exception DOMException
  +     *   NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly.
  +     */
  +    public String getData() {
  +        return getNodeValue();
  +    }
  +
  +    public void setData(String data) throws DOMException {
  +        setNodeValue(data);
  +    }
  +}
  
  
  
  1.9       +288 -296  xml-xindice/java/src/org/apache/xindice/xml/dom/ElementImpl.java
  
  Index: ElementImpl.java
  ===================================================================
  RCS file: /home/cvs/xml-xindice/java/src/org/apache/xindice/xml/dom/ElementImpl.java,v
  retrieving revision 1.8
  retrieving revision 1.9
  diff -u -r1.8 -r1.9
  --- ElementImpl.java	4 Nov 2002 06:39:55 -0000	1.8
  +++ ElementImpl.java	15 Jul 2003 15:44:34 -0000	1.9
  @@ -59,18 +59,20 @@
    * $Id$
    */
   
  +import java.io.IOException;
  +
  +import org.apache.commons.logging.Log;
  +import org.apache.commons.logging.LogFactory;
   import org.apache.xindice.core.data.Key;
   import org.apache.xindice.util.ByteArrayInput;
   import org.apache.xindice.xml.NodeSource;
   import org.apache.xindice.xml.SymbolTable;
   import org.apache.xindice.xml.XMLCompressedInput;
  -
  -import org.apache.commons.logging.Log;
  -import org.apache.commons.logging.LogFactory;
  -
  -import org.w3c.dom.*;
  -
  -import java.io.IOException;
  +import org.w3c.dom.Attr;
  +import org.w3c.dom.DOMException;
  +import org.w3c.dom.Element;
  +import org.w3c.dom.NamedNodeMap;
  +import org.w3c.dom.Node;
   
   /**
    * ElementImpl
  @@ -78,267 +80,258 @@
   
   public final class ElementImpl extends ContainerNodeImpl implements Element {
   
  -   private static Log log = LogFactory.getLog("org.apache.xindice.xml");
  +    private static Log log = LogFactory.getLog("org.apache.xindice.xml");
  +
  +    private static final String SRC_NS = XMLNS_PREFIX + ":src";
  +    private static final String SRC_COL = "src:" + NodeSource.SOURCE_COL;
  +    private static final String SRC_KEY = "src:" + NodeSource.SOURCE_KEY;
  +
  +    private NamedNodeMapImpl attributes = new NamedNodeMapImpl(this);
  +    private short symbolID = -1;
  +
  +    public ElementImpl() {}
  +
  +    public ElementImpl(NodeImpl parentNode, byte[] data, int pos, int len) {
  +        super(parentNode, data, pos, len);
  +        DocumentImpl doc = (DocumentImpl) getOwnerDocument();
  +        try {
  +            loadAttributes(doc.getSymbols());
  +        }
  +        catch (Exception e) {
  +            log.warn(e);
  +        }
  +    }
  +
  +    public ElementImpl(NodeImpl parentNode, boolean dirty) {
  +        super(parentNode, dirty);
  +    }
  +
  +    public ElementImpl(NodeImpl parentNode, String nodeName) {
  +        super(parentNode, true);
  +        this.nodeName = nodeName;
  +    }
  +
  +    protected boolean isNodeTypeValid(short type) {
  +        return type == Node.ELEMENT_NODE || type == Node.COMMENT_NODE || type == Node.TEXT_NODE || type == Node.CDATA_SECTION_NODE || type == Node.ENTITY_REFERENCE_NODE;
  +    }
  +
  +    protected void checkLoaded() {
  +        if (loaded)
  +            return;
  +        else
  +            loaded = true;
  +
  +        try {
  +            if (data != null) {
  +                DocumentImpl doc = (DocumentImpl) getOwnerDocument();
  +                SymbolTable st = doc.getSymbols();
  +
  +                ByteArrayInput bis = new ByteArrayInput(data, pos, len);
  +                XMLCompressedInput in = new XMLCompressedInput(bis, st);
  +
  +                in.readSignature(); // Skip The Signature
  +                in.readContentSize(); // Skip The Content Size
  +
  +                symbolID = in.readShort();
  +                SymbolTable.SymbolInfo si = st.getSymbolInfo(symbolID);
  +                nodeName = si.getQName();
  +                nsURI = si.getNamespaceURI();
  +
  +                loadChildren(st);
  +            }
  +        }
  +        catch (Exception e) {
  +            log.warn(e);
  +        }
  +    }
  +
  +    public short getSymbolID() {
  +        return symbolID;
  +    }
  +
  +    public void expandSource() {
  +        NodeSource src = getSource();
  +        if (src != null) {
  +            setAttribute(SRC_NS, NodeSource.SOURCE_NS);
  +            setAttribute(SRC_COL, src.getCollection().getCanonicalName());
  +            Key k = src.getKey();
  +            if (k != null)
  +                setAttribute(SRC_KEY, k.toString());
  +        }
  +    }
  +
  +    protected void loadAttributes(SymbolTable st) throws IOException {
  +        ByteArrayInput bis = new ByteArrayInput(data, pos, len);
  +        XMLCompressedInput in = new XMLCompressedInput(bis, st);
  +
  +        in.readSignature();
  +        in.readContentSize();
  +        /* TODO why is it used for? short elemSymbol = */
  +        in.readShort();
  +        int attrCount = in.readAttributeCount();
  +
  +        for (int i = 0; i < attrCount; i++) {
  +            short symbol = in.readShort();
  +            short strLen = in.readShort();
  +            byte[] b = new byte[strLen];
  +            in.read(b);
  +            SymbolTable.SymbolInfo si = st.getSymbolInfo(symbol);
  +            String name = si.getQName();
  +            String nsURI = si.getNamespaceURI();
  +            AttrImpl attr = new AttrImpl(this, name, nsURI, symbol, new String(b, "UTF-8"));
  +            attributes.setNamedItem(attr);
  +        }
  +    }
  +
  +    public short getNodeType() {
  +        return Node.ELEMENT_NODE;
  +    }
  +
  +    /**
  +     * A <code>NamedNodeMap</code> containing the attributes of this node (if it
  +     * is an <code>Element</code>) or <code>null</code> otherwise.
  +     */
  +    public NamedNodeMap getAttributes() {
  +        return attributes;
  +    }
  +
  +    public boolean hasAttributes() {
  +        return attributes.size() > 0;
  +    }
  +
  +    public boolean hasAttribute(String name) {
  +        return attributes.getNamedItem(name) != null;
  +    }
  +
  +    /**
  +     * Removes an attribute by name. If the removed attribute has a
  +     * default value it is immediately replaced.  If the named
  +     * attribute does not exist, this method has no effect.
  +     *
  +     * @param name The name of the attribute to remove.
  +     * @exception DOMException
  +     *   NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
  +     **/
  +    public void removeAttribute(String name) throws DOMException {
  +        checkReadOnly();
  +        AttrImpl attr = (AttrImpl) attributes.removeNamedItem(name);
  +        if (attr != null) {
  +            attr.setParentNode((NodeImpl) this.getOwnerDocument());
  +        }
  +        setDirty();
  +    }
  +
  +    /**
  +     * The name of the element. For example, in: &lt;elementExample
  +     * id="demo"&gt;  ... &lt;/elementExample&gt; , <code>tagName</code> has
  +     * the value <code>"elementExample"</code>. Note that this is
  +     * case-preserving in XML, as are all of the operations of the DOM. The
  +     * HTML DOM returns the <code>tagName</code> of an HTML element in the
  +     * canonical uppercase form, regardless of the case in the  source HTML
  +     * document.
  +     */
  +    public String getTagName() {
  +        return getNodeName();
  +    }
   
  -   private static final String SRC_NS = XMLNS_PREFIX+":src";
  -   private static final String SRC_COL = "src:"+NodeSource.SOURCE_COL;
  -   private static final String SRC_KEY = "src:"+NodeSource.SOURCE_KEY;
  -
  -   private NamedNodeMapImpl attributes = new NamedNodeMapImpl(this);
  -   private short symbolID = -1;
  -
  -   public ElementImpl() {
  -   }
  -   
  -   public ElementImpl(NodeImpl parentNode, byte[] data, int pos, int len) {
  -      super(parentNode, data, pos, len);
  -      DocumentImpl doc = (DocumentImpl)getOwnerDocument();
  -      try {
  -         loadAttributes(doc.getSymbols());
  -      }
  -      catch ( Exception e ) {
  -         if (log.isDebugEnabled()) {
  -            log.debug("No message", e);
  -         }
  -      }
  -   }
  -
  -   public ElementImpl(NodeImpl parentNode, boolean dirty) {
  -      super(parentNode, dirty);
  -   }
  -
  -   public ElementImpl(NodeImpl parentNode, String nodeName) {
  -      super(parentNode, true);
  -      this.nodeName = nodeName;
  -   }
  -
  -   protected boolean isNodeTypeValid(short type) {
  -      return type == Node.ELEMENT_NODE
  -          || type == Node.COMMENT_NODE
  -          || type == Node.TEXT_NODE
  -          || type == Node.CDATA_SECTION_NODE
  -          || type == Node.ENTITY_REFERENCE_NODE;
  -   }
  -
  -   protected void checkLoaded() {
  -      if ( loaded )
  -         return;
  -      else
  -         loaded = true;
  -
  -      try {
  -         if ( data != null ) {
  -            DocumentImpl doc = (DocumentImpl)getOwnerDocument();
  -            SymbolTable st = doc.getSymbols();
  -
  -            ByteArrayInput bis = new ByteArrayInput(data, pos, len);
  -            XMLCompressedInput in = new XMLCompressedInput(bis, st);
  -
  -            in.readSignature();   // Skip The Signature
  -            in.readContentSize(); // Skip The Content Size
  -
  -            symbolID = in.readShort();
  -            SymbolTable.SymbolInfo si = st.getSymbolInfo(symbolID);
  -            nodeName = si.getQName();
  -            nsURI = si.getNamespaceURI();
  -
  -            loadChildren(st);
  -         }
  -      }
  -      catch ( Exception e ) {
  -         if (log.isDebugEnabled()) {
  -            log.debug("No message", e);
  -         }
  -      }
  -   }
  -
  -   public short getSymbolID() {
  -      return symbolID;
  -   }
  -
  -   public void expandSource() {
  -      NodeSource src = getSource();
  -      if ( src != null ) {
  -         setAttribute(SRC_NS, NodeSource.SOURCE_NS);
  -         setAttribute(SRC_COL, src.getCollection().getCanonicalName());
  -         Key k = src.getKey();
  -         if ( k != null )
  -            setAttribute(SRC_KEY, k.toString());
  -      }
  -   }
  -
  -   protected void loadAttributes(SymbolTable st) throws IOException {
  -      ByteArrayInput bis = new ByteArrayInput(data, pos, len);
  -      XMLCompressedInput in = new XMLCompressedInput(bis, st);
  -
  -      in.readSignature();
  -      in.readContentSize();
  -      /* TODO why is it used for? short elemSymbol = */ in.readShort();
  -      int attrCount = in.readAttributeCount();
  -
  -      for ( int i = 0 ; i < attrCount; i++ ) {
  -         short symbol = in.readShort();
  -         short strLen = in.readShort();
  -         byte[] b = new byte[strLen];
  -         in.read(b);
  -         SymbolTable.SymbolInfo si = st.getSymbolInfo(symbol);
  -         String name = si.getQName();
  -         String nsURI = si.getNamespaceURI();
  -         AttrImpl attr = new AttrImpl(this, name, nsURI, symbol, new String(b, "UTF-8"));
  -         attributes.setNamedItem(attr);
  -      }
  -   }
  -
  -   public short getNodeType() {
  -      return Node.ELEMENT_NODE;
  -   }
  -
  -   /**
  -    * A <code>NamedNodeMap</code> containing the attributes of this node (if it
  -    * is an <code>Element</code>) or <code>null</code> otherwise.
  -    */
  -   public NamedNodeMap getAttributes() {
  -      return attributes;
  -   }
  -
  -   public boolean hasAttributes() {
  -      return attributes.size() > 0;
  -   }
  -
  -   public boolean hasAttribute(String name) {
  -      return attributes.getNamedItem(name) != null;
  -   }
  -
  -   /**
  -    * Removes an attribute by name. If the removed attribute has a
  -    * default value it is immediately replaced.  If the named
  -    * attribute does not exist, this method has no effect.
  -    *
  -    * @param name The name of the attribute to remove.
  -    * @exception DOMException
  -    *   NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
  -    **/
  -   public void removeAttribute( String name ) throws DOMException {
  -      checkReadOnly();
  -      AttrImpl attr = (AttrImpl) attributes.removeNamedItem(name);
  -      if ( attr != null ) {
  -	  attr.setParentNode( (NodeImpl)this.getOwnerDocument() );
  -      }
  -      setDirty();
  -   }
  -
  -   /**
  -    * The name of the element. For example, in: &lt;elementExample
  -    * id="demo"&gt;  ... &lt;/elementExample&gt; , <code>tagName</code> has
  -    * the value <code>"elementExample"</code>. Note that this is
  -    * case-preserving in XML, as are all of the operations of the DOM. The
  -    * HTML DOM returns the <code>tagName</code> of an HTML element in the
  -    * canonical uppercase form, regardless of the case in the  source HTML
  -    * document.
  -    */
  -   public String getTagName() {
  -      return getNodeName();
  -   }
  -
  -   /**
  -    * Retrieves an attribute value by name.
  -    * @param name The name of the attribute to retrieve.
  -    * @return The <code>Attr</code> value as a string, or the empty  string if
  -    *   that attribute does not have a specified or default value.
  -    */
  -   public String getAttribute(String name) {
  -      Attr attr = (Attr)attributes.getNamedItem(name);
  -      return attr != null ? attr.getValue()
  -                          : "";
  -   }
  -
  -   /**
  -    * Adds a new attribute. If an attribute with that name is already present
  -    * in the element, it is replaced by the new one.
  -    * @param newAttr The <code>Attr</code> node to add to the attribute list.
  -    * @return If the <code>newAttr</code> attribute replaces an existing
  -    *   attribute with the same name, the  previously existing
  -    *   <code>Attr</code> node is returned, otherwise <code>null</code> is
  -    *   returned.
  -    * @exception DOMException
  -    *   WRONG_DOCUMENT_ERR: Raised if <code>newAttr</code> was created from a
  -    *   different document than the one that created the element.
  -    *   <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
  -    *   <br>INUSE_ATTRIBUTE_ERR: Raised if <code>newAttr</code> is already an
  -    *   attribute of another <code>Element</code> object. The DOM user must
  -    *   explicitly clone <code>Attr</code> nodes to re-use them in other
  -    *   elements.
  -    */
  -   public Attr setAttributeNode(Attr newAttr) throws DOMException {
  -      checkReadOnly();
  -      Attr oldAttr = (Attr)attributes.getNamedItem(newAttr.getName());
  -      DocumentImpl doc = (DocumentImpl)getOwnerDocument();
  -      if ( newAttr.getParentNode().getNodeType() == Node.ELEMENT_NODE )
  -         throw EX_INUSE_ATTRIBUTE;
  -      if ( doc != newAttr.getOwnerDocument() )
  -         throw EX_WRONG_DOCUMENT;
  -      ((AttrImpl)newAttr).setParentNode(this);
  -      attributes.setNamedItem(newAttr);
  -      setDirty();
  -      return oldAttr;
  -   }
  -
  -   /**
  -    * Adds a new attribute. If an attribute with that name is already present
  -    * in the element, its value is changed to be that of the value parameter.
  -    * This value is a simple string, it is not parsed as it is being set. So
  -    * any markup (such as syntax to be recognized as an entity reference) is
  -    * treated as literal text, and needs to be appropriately escaped by the
  -    * implementation when it is written out. In order to assign an attribute
  -    * value that contains entity references, the user must create an
  -    * <code>Attr</code> node plus any <code>Text</code> and
  -    * <code>EntityReference</code> nodes, build the appropriate subtree, and
  -    * use <code>setAttributeNode</code> to assign it as the value of an
  -    * attribute.
  -    * @param name The name of the attribute to create or alter.
  -    * @param value Value to set in string form.
  -    * @exception DOMException
  -    *   INVALID_CHARACTER_ERR: Raised if the specified name contains an
  -    *   invalid character.
  -    *   <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
  -    */
  -   public void setAttribute(String name, String value) throws DOMException {
  -      Attr attr = getOwnerDocument().createAttribute(name);
  -      attr.setValue(value);
  -      setAttributeNode(attr);
  -   }
  -
  -   /**
  -    * Retrieves an <code>Attr</code> node by name.
  -    * @param name The name of the attribute to retrieve.
  -    * @return The <code>Attr</code> node with the specified attribute name or
  -    *   <code>null</code> if there is no such attribute.
  -    */
  -   public Attr getAttributeNode(String name) {
  -      return (Attr)attributes.getNamedItem(name);
  -   }
  -
  -   /**
  -    * Removes the specified attribute.
  -    * @param oldAttr The <code>Attr</code> node to remove from the attribute
  -    *   list. If the removed <code>Attr</code> has a default value it is
  -    *   immediately replaced.
  -    * @return The <code>Attr</code> node that was removed.
  -    * @exception DOMException
  -    *   NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
  -    *   <br>NOT_FOUND_ERR: Raised if <code>oldAttr</code> is not an attribute
  -    *   of the element.
  -    **/
  -   public Attr removeAttributeNode( Attr oldAttr ) throws DOMException {
  -      checkReadOnly();
  -      if ( oldAttr.getParentNode() != this ) {
  -	  throw EX_NOT_FOUND;
  -      }
  -      attributes.remove( oldAttr.getName() );
  -      ((AttrImpl)oldAttr).setParentNode( (NodeImpl)this.getOwnerDocument() );
  -      setDirty();
  -      return oldAttr;
  -   }
  +    /**
  +     * Retrieves an attribute value by name.
  +     * @param name The name of the attribute to retrieve.
  +     * @return The <code>Attr</code> value as a string, or the empty  string if
  +     *   that attribute does not have a specified or default value.
  +     */
  +    public String getAttribute(String name) {
  +        Attr attr = (Attr) attributes.getNamedItem(name);
  +        return attr != null ? attr.getValue() : "";
  +    }
  +
  +    /**
  +     * Adds a new attribute. If an attribute with that name is already present
  +     * in the element, it is replaced by the new one.
  +     * @param newAttr The <code>Attr</code> node to add to the attribute list.
  +     * @return If the <code>newAttr</code> attribute replaces an existing
  +     *   attribute with the same name, the  previously existing
  +     *   <code>Attr</code> node is returned, otherwise <code>null</code> is
  +     *   returned.
  +     * @exception DOMException
  +     *   WRONG_DOCUMENT_ERR: Raised if <code>newAttr</code> was created from a
  +     *   different document than the one that created the element.
  +     *   <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
  +     *   <br>INUSE_ATTRIBUTE_ERR: Raised if <code>newAttr</code> is already an
  +     *   attribute of another <code>Element</code> object. The DOM user must
  +     *   explicitly clone <code>Attr</code> nodes to re-use them in other
  +     *   elements.
  +     */
  +    public Attr setAttributeNode(Attr newAttr) throws DOMException {
  +        checkReadOnly();
  +        Attr oldAttr = (Attr) attributes.getNamedItem(newAttr.getName());
  +        DocumentImpl doc = (DocumentImpl) getOwnerDocument();
  +        if (newAttr.getParentNode().getNodeType() == Node.ELEMENT_NODE)
  +            throw EX_INUSE_ATTRIBUTE;
  +        if (doc != newAttr.getOwnerDocument())
  +            throw EX_WRONG_DOCUMENT;
  +        ((AttrImpl) newAttr).setParentNode(this);
  +        attributes.setNamedItem(newAttr);
  +        setDirty();
  +        return oldAttr;
  +    }
  +
  +    /**
  +     * Adds a new attribute. If an attribute with that name is already present
  +     * in the element, its value is changed to be that of the value parameter.
  +     * This value is a simple string, it is not parsed as it is being set. So
  +     * any markup (such as syntax to be recognized as an entity reference) is
  +     * treated as literal text, and needs to be appropriately escaped by the
  +     * implementation when it is written out. In order to assign an attribute
  +     * value that contains entity references, the user must create an
  +     * <code>Attr</code> node plus any <code>Text</code> and
  +     * <code>EntityReference</code> nodes, build the appropriate subtree, and
  +     * use <code>setAttributeNode</code> to assign it as the value of an
  +     * attribute.
  +     * @param name The name of the attribute to create or alter.
  +     * @param value Value to set in string form.
  +     * @exception DOMException
  +     *   INVALID_CHARACTER_ERR: Raised if the specified name contains an
  +     *   invalid character.
  +     *   <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
  +     */
  +    public void setAttribute(String name, String value) throws DOMException {
  +        Attr attr = getOwnerDocument().createAttribute(name);
  +        attr.setValue(value);
  +        setAttributeNode(attr);
  +    }
  +
  +    /**
  +     * Retrieves an <code>Attr</code> node by name.
  +     * @param name The name of the attribute to retrieve.
  +     * @return The <code>Attr</code> node with the specified attribute name or
  +     *   <code>null</code> if there is no such attribute.
  +     */
  +    public Attr getAttributeNode(String name) {
  +        return (Attr) attributes.getNamedItem(name);
  +    }
  +
  +    /**
  +     * Removes the specified attribute.
  +     * @param oldAttr The <code>Attr</code> node to remove from the attribute
  +     *   list. If the removed <code>Attr</code> has a default value it is
  +     *   immediately replaced.
  +     * @return The <code>Attr</code> node that was removed.
  +     * @exception DOMException
  +     *   NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
  +     *   <br>NOT_FOUND_ERR: Raised if <code>oldAttr</code> is not an attribute
  +     *   of the element.
  +     **/
  +    public Attr removeAttributeNode(Attr oldAttr) throws DOMException {
  +        checkReadOnly();
  +        if (oldAttr.getParentNode() != this) {
  +            throw EX_NOT_FOUND;
  +        }
  +        attributes.remove(oldAttr.getName());
  +        ((AttrImpl) oldAttr).setParentNode((NodeImpl) this.getOwnerDocument());
  +        setDirty();
  +        return oldAttr;
  +    }
   
       /**
        *  Retrieves an attribute value by local name and namespace URI.
  @@ -350,11 +343,10 @@
        *   value.
        * @since DOM Level 2
        */
  -   public String getAttributeNS(String namespaceURI, String localName) {
  -      Attr attr = (Attr)attributes.getNamedItemNS(namespaceURI, localName);
  -      return attr != null ? attr.getValue()
  -                          : "";
  -   }
  +    public String getAttributeNS(String namespaceURI, String localName) {
  +        Attr attr = (Attr) attributes.getNamedItemNS(namespaceURI, localName);
  +        return attr != null ? attr.getValue() : "";
  +    }
   
       /**
        *  Adds a new attribute. If an attribute with the same local name and
  @@ -393,11 +385,11 @@
        *   "http://www.w3.org/2000/xmlns/".
        * @since DOM Level 2
        */
  -   public void setAttributeNS(String namespaceURI, String qualifiedName, String value) {
  -      Attr attr = getOwnerDocument().createAttributeNS(namespaceURI, qualifiedName);
  -      attr.setValue(value);
  -      setAttributeNodeNS(attr);
  -   }
  +    public void setAttributeNS(String namespaceURI, String qualifiedName, String value) {
  +        Attr attr = getOwnerDocument().createAttributeNS(namespaceURI, qualifiedName);
  +        attr.setValue(value);
  +        setAttributeNodeNS(attr);
  +    }
   
       /**
        * Removes an attribute by local name and namespace URI. If the
  @@ -414,14 +406,14 @@
        *    NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
        * @since DOM Level 2
        **/
  -   public void removeAttributeNS( String namespaceURI, String localName ) {
  -      checkReadOnly();
  -      AttrImpl attr = (AttrImpl) attributes.removeNamedItemNS( namespaceURI, localName );
  -      if ( attr != null ) {
  -	  attr.setParentNode( (NodeImpl)this.getOwnerDocument() );
  -      }
  -      setDirty();
  -   }
  +    public void removeAttributeNS(String namespaceURI, String localName) {
  +        checkReadOnly();
  +        AttrImpl attr = (AttrImpl) attributes.removeNamedItemNS(namespaceURI, localName);
  +        if (attr != null) {
  +            attr.setParentNode((NodeImpl) this.getOwnerDocument());
  +        }
  +        setDirty();
  +    }
   
       /**
        *  Retrieves an <code>Attr</code> node by local name and namespace URI.
  @@ -433,9 +425,9 @@
        *   attribute.
        * @since DOM Level 2
        */
  -   public Attr getAttributeNodeNS(String namespaceURI, String localName) {
  -      return (Attr)attributes.getNamedItemNS(namespaceURI, localName);
  -   }
  +    public Attr getAttributeNodeNS(String namespaceURI, String localName) {
  +        return (Attr) attributes.getNamedItemNS(namespaceURI, localName);
  +    }
   
       /**
        *  Adds a new attribute. If an attribute with that local name and that
  @@ -457,11 +449,11 @@
        *   other elements.
        * @since DOM Level 2
        */
  -   public Attr setAttributeNodeNS(Attr newAttr) {
  -      return setAttributeNode(newAttr);
  -   }
  -
  -   public boolean hasAttributeNS(String namespaceURI, String localName) {
  -      return attributes.getNamedItemNS(namespaceURI, localName) != null;
  -   }
  +    public Attr setAttributeNodeNS(Attr newAttr) {
  +        return setAttributeNode(newAttr);
  +    }
  +
  +    public boolean hasAttributeNS(String namespaceURI, String localName) {
  +        return attributes.getNamedItemNS(namespaceURI, localName) != null;
  +    }
   }
  
  
  
  1.4       +83 -89    xml-xindice/java/src/org/apache/xindice/xml/dom/EntityReferenceImpl.java
  
  Index: EntityReferenceImpl.java
  ===================================================================
  RCS file: /home/cvs/xml-xindice/java/src/org/apache/xindice/xml/dom/EntityReferenceImpl.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- EntityReferenceImpl.java	31 Oct 2002 07:02:23 -0000	1.3
  +++ EntityReferenceImpl.java	15 Jul 2003 15:44:34 -0000	1.4
  @@ -59,15 +59,14 @@
    * $Id$
    */
   
  +import org.apache.commons.logging.Log;
  +import org.apache.commons.logging.LogFactory;
   import org.apache.xindice.util.ByteArrayInput;
   import org.apache.xindice.xml.Signatures;
   import org.apache.xindice.xml.SymbolTable;
   import org.apache.xindice.xml.XMLCompressedInput;
  -
  -import org.apache.commons.logging.Log;
  -import org.apache.commons.logging.LogFactory;
  -
  -import org.w3c.dom.*;
  +import org.w3c.dom.EntityReference;
  +import org.w3c.dom.Node;
   
   /**
    * EntityReferenceImpl
  @@ -75,91 +74,86 @@
   
   public final class EntityReferenceImpl extends NodeImpl implements EntityReference {
   
  -   private static Log log = LogFactory.getLog("org.apache.xindice.xml");
  +    private static Log log = LogFactory.getLog("org.apache.xindice.xml");
  +
  +    private short symbolID = -1;
   
  -   private short symbolID = -1;
  +    public EntityReferenceImpl() {}
   
  -   public EntityReferenceImpl() {
  -   }
  -   
  -   public EntityReferenceImpl(NodeImpl parentNode, byte[] data, int pos, int len) {
  -      super(parentNode, data, pos, len);
  -   }
  -
  -   public EntityReferenceImpl(NodeImpl parentNode, boolean dirty) {
  -      super(parentNode, dirty);
  -   }
  -
  -   public EntityReferenceImpl(NodeImpl parentNode, String nodeName) {
  -      super(parentNode, true);
  -      this.nodeName = nodeName;
  -   }
  -
  -   protected void checkLoaded() {
  -      if ( loaded )
  -         return;
  -      else
  -         loaded = true;
  -
  -      try {
  -         if ( data != null ) {
  -            DocumentImpl doc = (DocumentImpl)getOwnerDocument();
  -            SymbolTable st = doc.getSymbols();
  -
  -            ByteArrayInput bis = new ByteArrayInput(data, pos, len);
  -            XMLCompressedInput xci = new XMLCompressedInput(bis, st);
  -
  -            byte signature = xci.readByte();
  -            byte entityType = (byte)(signature & 0x1F);
  -            switch ( entityType ) {
  -
  -               case Signatures.EntUnknown:
  -                  nodeName = null;
  -                  break;
  -
  -               case Signatures.EntDefined:
  -                  symbolID = xci.readShort();
  -                  nodeName = st.getName(symbolID);
  -                  break;
  -
  -               case Signatures.EntAmp:
  -                  nodeName = "&amp;";
  -                  break;
  -
  -               case Signatures.EntLt:
  -                  nodeName = "&lt;";
  -                  break;
  -
  -               case Signatures.EntGt:
  -                  nodeName = "&gt;";
  -                  break;
  -
  -               case Signatures.EntQuot:
  -                  nodeName = "&quot;";
  -                  break;
  -
  -               case Signatures.EntApos:
  -                  nodeName = "&apos;";
  -                  break;
  -
  -               case Signatures.EntUnicode:
  -                  nodeName = "";
  -                  // TODO: This
  -                  break;
  +    public EntityReferenceImpl(NodeImpl parentNode, byte[] data, int pos, int len) {
  +        super(parentNode, data, pos, len);
  +    }
  +
  +    public EntityReferenceImpl(NodeImpl parentNode, boolean dirty) {
  +        super(parentNode, dirty);
  +    }
  +
  +    public EntityReferenceImpl(NodeImpl parentNode, String nodeName) {
  +        super(parentNode, true);
  +        this.nodeName = nodeName;
  +    }
  +
  +    protected void checkLoaded() {
  +        if (loaded)
  +            return;
  +        else
  +            loaded = true;
  +
  +        try {
  +            if (data != null) {
  +                DocumentImpl doc = (DocumentImpl) getOwnerDocument();
  +                SymbolTable st = doc.getSymbols();
  +
  +                ByteArrayInput bis = new ByteArrayInput(data, pos, len);
  +                XMLCompressedInput xci = new XMLCompressedInput(bis, st);
  +
  +                byte signature = xci.readByte();
  +                byte entityType = (byte) (signature & 0x1F);
  +                switch (entityType) {
  +
  +                    case Signatures.EntUnknown :
  +                        nodeName = null;
  +                        break;
  +
  +                    case Signatures.EntDefined :
  +                        symbolID = xci.readShort();
  +                        nodeName = st.getName(symbolID);
  +                        break;
  +
  +                    case Signatures.EntAmp :
  +                        nodeName = "&amp;";
  +                        break;
  +
  +                    case Signatures.EntLt :
  +                        nodeName = "&lt;";
  +                        break;
  +
  +                    case Signatures.EntGt :
  +                        nodeName = "&gt;";
  +                        break;
  +
  +                    case Signatures.EntQuot :
  +                        nodeName = "&quot;";
  +                        break;
  +
  +                    case Signatures.EntApos :
  +                        nodeName = "&apos;";
  +                        break;
  +
  +                    case Signatures.EntUnicode :
  +                        nodeName = "";
  +                        // TODO: This
  +                        break;
   
  +                }
               }
  -         }
  -      }
  -      catch ( Exception e ) {
  -         if (log.isDebugEnabled()) {
  -            log.debug("No message", e);
  -         }
  -      }
  -   }
  -
  -   public short getNodeType() {
  -      return Node.ENTITY_REFERENCE_NODE;
  -   }
  +        }
  +        catch (Exception e) {
  +            log.warn(e);
  +        }
  +    }
  +
  +    public short getNodeType() {
  +        return Node.ENTITY_REFERENCE_NODE;
  +    }
   }
  -
  -
  
  
  
  1.5       +1 -1      xml-xindice/java/src/org/apache/xindice/core/DBObserver.java
  
  Index: DBObserver.java
  ===================================================================
  RCS file: /home/cvs/xml-xindice/java/src/org/apache/xindice/core/DBObserver.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- DBObserver.java	14 Jul 2003 19:07:14 -0000	1.4
  +++ DBObserver.java	15 Jul 2003 15:44:35 -0000	1.5
  @@ -11,7 +11,7 @@
    * Observer for Xindice DB activities
    */
   public abstract class DBObserver {
  -    
  +
       private static final DBObserver NOOP = new DBObserver() {
           public void setDatabaseConfig(Database db, Map collections, Configuration cfg) {}
   
  
  
  
  1.12      +195 -200  xml-xindice/java/src/org/apache/xindice/core/CollectionManager.java
  
  Index: CollectionManager.java
  ===================================================================
  RCS file: /home/cvs/xml-xindice/java/src/org/apache/xindice/core/CollectionManager.java,v
  retrieving revision 1.11
  retrieving revision 1.12
  diff -u -r1.11 -r1.12
  --- CollectionManager.java	14 Jul 2003 19:07:15 -0000	1.11
  +++ CollectionManager.java	15 Jul 2003 15:44:35 -0000	1.12
  @@ -59,229 +59,224 @@
    * $Id$
    */
   
  +import java.util.HashMap;
  +import java.util.Map;
  +import java.util.StringTokenizer;
  +
  +import org.apache.commons.logging.Log;
  +import org.apache.commons.logging.LogFactory;
   import org.apache.xindice.util.Configurable;
   import org.apache.xindice.util.Configuration;
   import org.apache.xindice.util.ConfigurationCallback;
   import org.apache.xindice.util.Disposable;
   import org.apache.xindice.util.XindiceException;
   
  -import org.apache.commons.logging.Log;
  -import org.apache.commons.logging.LogFactory;
  -
  -import java.util.HashMap;
  -import java.util.Map;
  -import java.util.StringTokenizer;
  -
   /**
    * CollectionManager is the base class for both Database and Collection.
    */
   
   public class CollectionManager implements Configurable, Disposable {
  -	private static final String COLLECTION = "collection";
  -	private static final String COLLECTIONS = "collections";
  -	private static final String[] EmptyStrings = new String[0];
  -	private static Log log = LogFactory.getLog("org.apache.xindice.core");
  -	private static final String NAME = "name";
  -	private Map collections = new HashMap(); // Collection
  -	private Configuration config = null;
  -	
  -	protected CollectionManager() {}
  -	
  -	/**
  -	 * 
  -	 * @param collection
  -	 */
  -	protected void addCollection(Collection collection){
  -
  -		this.collections.put(collection.getName(), collection);		
  -	}
  -
  -	/**
  -	 * Returns number of child collections
  -	 *
  -	 * @return number of collections
  -	 */
  -	public final long countCollections() throws DBException {
  -		return (long) collections.size();
  -	}
  -
  -	/**
  -	 * createCollection creates a new Collection object and any associated
  -	 * system resources that the Collection will need.
  -	 *
  -	 * @param path The relative path of the Collection
  -	 * @param cfg The Collection's configuration
  -	 * @return The newly created Collection
  -	 */
  -	public Collection createCollection(String path, Configuration cfg) throws DBException {
  -		if (path.indexOf("/") != -1) {
  -			CollectionManager cm = this;
  -			StringTokenizer st = new StringTokenizer(path, "/");
  -			while (cm != null && st.hasMoreTokens()) {
  -				path = st.nextToken().trim();
  -				if (path.length() == 0)
  -					continue;
  -				if (st.hasMoreTokens())
  -					cm = (CollectionManager) cm.collections.get(path);
  -				else
  -					return cm.createCollection(path, cfg);
  -			}
  -			throw new DBException(FaultCodes.COL_COLLECTION_NOT_FOUND, "Parent Collection '" + path + "' doesn't exist");
  -		}
  -
  -		Collection collection = null;
  -
  -		if (CollectionManager.this instanceof Database)
  -			collection = new Collection((Database) CollectionManager.this);
  -		else
  -			collection = new Collection((Collection) CollectionManager.this);
  -
  -		try {
  -			// Do a name check to see if all is well
  -			String n = cfg.getAttribute(NAME);
  -			if (n == null || n.trim().equals(""))
  -				throw new DBException(FaultCodes.COL_CANNOT_CREATE, "No name specified");
  -
  -			if (getCollection(n) != null)
  -				throw new DBException(FaultCodes.COL_DUPLICATE_COLLECTION, "Duplicate Collection '" + n + "'");
  -
  -			Configuration colConfig = this.config.getChild(COLLECTIONS, true);
  -			colConfig.add(cfg);
  -
  -			collection.setConfig(cfg);
  -			collection.create();
  -			collections.put(n, collection);
  -			if (log.isInfoEnabled()) {
  -				log.info("Created a new collection named '" + n + "'");
  -			}
  -		}
  -		catch (DBException e) {
  -			throw e;
  -		}
  -		catch (Exception e) {
  -			throw new DBException(FaultCodes.COL_CANNOT_CREATE, "Error Creating Collection '" + path + "'", e);
  -		}
  -		return collection;
  -	}
  +    private static final String COLLECTION = "collection";
  +    private static final String COLLECTIONS = "collections";
  +    private static final String[] EmptyStrings = new String[0];
  +    private static Log log = LogFactory.getLog("org.apache.xindice.core");
  +    private static final String NAME = "name";
  +    private Map collections = new HashMap(); // Collection
  +    private Configuration config = null;
  +
  +    protected CollectionManager() {}
  +
  +    /**
  +     * 
  +     * @param collection
  +     */
  +    protected void addCollection(Collection collection) {
  +
  +        this.collections.put(collection.getName(), collection);
  +    }
  +
  +    /**
  +     * Returns number of child collections
  +     *
  +     * @return number of collections
  +     */
  +    public final long countCollections() throws DBException {
  +        return (long) collections.size();
  +    }
  +
  +    /**
  +     * createCollection creates a new Collection object and any associated
  +     * system resources that the Collection will need.
  +     *
  +     * @param path The relative path of the Collection
  +     * @param cfg The Collection's configuration
  +     * @return The newly created Collection
  +     */
  +    public Collection createCollection(String path, Configuration cfg) throws DBException {
  +        if (path.indexOf("/") != -1) {
  +            CollectionManager cm = this;
  +            StringTokenizer st = new StringTokenizer(path, "/");
  +            while (cm != null && st.hasMoreTokens()) {
  +                path = st.nextToken().trim();
  +                if (path.length() == 0)
  +                    continue;
  +                if (st.hasMoreTokens())
  +                    cm = (CollectionManager) cm.collections.get(path);
  +                else
  +                    return cm.createCollection(path, cfg);
  +            }
  +            throw new DBException(FaultCodes.COL_COLLECTION_NOT_FOUND, "Parent Collection '" + path + "' doesn't exist");
  +        }
  +
  +        Collection collection = null;
  +
  +        if (CollectionManager.this instanceof Database)
  +            collection = new Collection((Database) CollectionManager.this);
  +        else
  +            collection = new Collection((Collection) CollectionManager.this);
  +
  +        try {
  +            // Do a name check to see if all is well
  +            String n = cfg.getAttribute(NAME);
  +            if (n == null || n.trim().equals(""))
  +                throw new DBException(FaultCodes.COL_CANNOT_CREATE, "No name specified");
  +
  +            if (getCollection(n) != null)
  +                throw new DBException(FaultCodes.COL_DUPLICATE_COLLECTION, "Duplicate Collection '" + n + "'");
  +
  +            Configuration colConfig = this.config.getChild(COLLECTIONS, true);
  +            colConfig.add(cfg);
  +
  +            collection.setConfig(cfg);
  +            collection.create();
  +            collections.put(n, collection);
  +            log.info("Created a new collection named '" + n + "'");
  +        }
  +        catch (DBException e) {
  +            throw e;
  +        }
  +        catch (Exception e) {
  +            throw new DBException(FaultCodes.COL_CANNOT_CREATE, "Error Creating Collection '" + path + "'", e);
  +        }
  +        return collection;
  +    }
   
  -	/**
  +    /**
        * @see org.apache.xindice.util.Disposable#dispose()
        */
       public void dispose() {}
   
  -	/**
  -	 * dropCollection physically removes the specified Collection and any
  -	 * associated system resources that the Collection uses.
  -	 *
  -	 * @param collection The Collection to drop
  -	 * @return Whether or not the Collection was dropped
  -	 */
  -	public boolean dropCollection(Collection collection) throws DBException {
  -		if (collection == null)
  -			throw new DBException(FaultCodes.COL_COLLECTION_NOT_FOUND, "Collection Value Null");
  -
  -		Collection cm = collection.getParentCollection();
  -
  -		if (cm == null)
  -			throw new DBException(FaultCodes.DBE_CANNOT_DROP, "You Cannot Drop The Database");
  -
  -		if (cm != this)
  -			return cm.dropCollection(collection);
  -		else {
  -			final String name = collection.getName();
  -			boolean dropped = collection.drop();
  -			if (dropped) {
  -				collections.remove(name);
  -				Configuration colConfig = config.getChild(COLLECTIONS);
  -				colConfig.processChildren(COLLECTION, new ConfigurationCallback() {
  -					public void process(Configuration cfg) {
  -						try {
  -							if (cfg.getAttribute(NAME).equals(name))
  -								cfg.delete();
  -						}
  -						catch (Exception e) {
  -							if (log.isDebugEnabled()) {
  -								log.debug("No message", e);
  -							}
  -						}
  -					}
  -				});
  -			}
  -			return dropped;
  -		}
  -	}
  -
  -	/**
  -	 * getCollection retrieves a Collection by name.
  -	 *
  -	 * @param path The Collection path
  -	 * @return The Collection (or null)
  -	 */
  -	public Collection getCollection(String path) throws DBException {
  -		if (path.indexOf("/") != -1) {
  -			CollectionManager cm = this;
  -			StringTokenizer st = new StringTokenizer(path, "/");
  -			while (cm != null && st.hasMoreTokens()) {
  -				path = st.nextToken();
  -				cm = (CollectionManager) cm.collections.get(path);
  -			}
  -			return (Collection) cm;
  -		}
  -		else
  -			return (Collection) collections.get(path);
  -	}
  -	
  -	/**
  -	 * @return
  -	 */
  -	protected Map getCollections() {
  -		return this.collections;
  -	}	
  +    /**
  +     * dropCollection physically removes the specified Collection and any
  +     * associated system resources that the Collection uses.
  +     *
  +     * @param collection The Collection to drop
  +     * @return Whether or not the Collection was dropped
  +     */
  +    public boolean dropCollection(Collection collection) throws DBException {
  +        if (collection == null)
  +            throw new DBException(FaultCodes.COL_COLLECTION_NOT_FOUND, "Collection Value Null");
  +
  +        Collection cm = collection.getParentCollection();
  +
  +        if (cm == null)
  +            throw new DBException(FaultCodes.DBE_CANNOT_DROP, "You Cannot Drop The Database");
  +
  +        if (cm != this)
  +            return cm.dropCollection(collection);
  +        else {
  +            final String name = collection.getName();
  +            boolean dropped = collection.drop();
  +            if (dropped) {
  +                collections.remove(name);
  +                Configuration colConfig = config.getChild(COLLECTIONS);
  +                colConfig.processChildren(COLLECTION, new ConfigurationCallback() {
  +                    public void process(Configuration cfg) {
  +                        try {
  +                            if (cfg.getAttribute(NAME).equals(name))
  +                                cfg.delete();
  +                        }
  +                        catch (Exception e) {
  +                            log.warn(e);
  +                        }
  +                    }
  +                });
  +            }
  +            return dropped;
  +        }
  +    }
  +
  +    /**
  +     * getCollection retrieves a Collection by name.
  +     *
  +     * @param path The Collection path
  +     * @return The Collection (or null)
  +     */
  +    public Collection getCollection(String path) throws DBException {
  +        if (path.indexOf("/") != -1) {
  +            CollectionManager cm = this;
  +            StringTokenizer st = new StringTokenizer(path, "/");
  +            while (cm != null && st.hasMoreTokens()) {
  +                path = st.nextToken();
  +                cm = (CollectionManager) cm.collections.get(path);
  +            }
  +            return (Collection) cm;
  +        }
  +        else
  +            return (Collection) collections.get(path);
  +    }
   
  -	/**
  +    /**
  +     * @return
  +     */
  +    protected Map getCollections() {
  +        return this.collections;
  +    }
  +
  +    /**
        * @see org.apache.xindice.util.Configurable#getConfig()
        */
       public Configuration getConfig() {
  -		return config;
  -	}
  +        return config;
  +    }
   
  -	/**
  -	 * listCollections retrieves a list of Collections as an array of
  -	 * Strings.
  -	 *
  -	 * @return The Collection list
  -	 */
  -	public final String[] listCollections() throws DBException {
  -		return (String[]) collections.keySet().toArray(EmptyStrings);
  -	}
  +    /**
  +     * listCollections retrieves a list of Collections as an array of
  +     * Strings.
  +     *
  +     * @return The Collection list
  +     */
  +    public final String[] listCollections() throws DBException {
  +        return (String[]) collections.keySet().toArray(EmptyStrings);
  +    }
   
  -	/**
  +    /**
        * @see org.apache.xindice.util.Configurable#setConfig(org.apache.xindice.util.Configuration)
        */
       public void setConfig(Configuration config) throws XindiceException {
  -		this.config = config;
  +        this.config = config;
   
  -		Configuration colConfig = config.getChild(COLLECTIONS);
  -		if (colConfig != null) {
  -			colConfig.processChildren(COLLECTION, new ConfigurationCallback() {
  -				public void process(Configuration cfg) throws XindiceException {
  -					// check for an existing Collection by name and, if found, skip creating a new Collection
  -					// else, create a new child Collection, configure it an add it
  -					// if the Collection already exists in our collections list,
  -					// creating a new one will cause the old one to be discarded
  -					// while holding open file handles, etc.
  -					Collection col = (Collection) collections.get(cfg.getAttribute(NAME));
  -					if (col == null) {
  -						col = new Collection((Collection) CollectionManager.this);
  -						col.setConfig(cfg);
  -						collections.put(col.getName(), col);
  -					}
  -					// else, assume col is configured elsewhere...
  -					// I'm not sure this should be happening, but it does
  -					// it is not safe to call col.setConfig again since it does a bunch
  -					// of stuff (like creating a new Filer and overwriting the existing one, etc.)
  -				}
  -			});
  -		}
  -	}
  +        Configuration colConfig = config.getChild(COLLECTIONS);
  +        if (colConfig != null) {
  +            colConfig.processChildren(COLLECTION, new ConfigurationCallback() {
  +                public void process(Configuration cfg) throws XindiceException {
  +                    // check for an existing Collection by name and, if found, skip creating a new Collection
  +                    // else, create a new child Collection, configure it an add it
  +                    // if the Collection already exists in our collections list,
  +                    // creating a new one will cause the old one to be discarded
  +                    // while holding open file handles, etc.
  +                    Collection col = (Collection) collections.get(cfg.getAttribute(NAME));
  +                    if (col == null) {
  +                        col = new Collection((Collection) CollectionManager.this);
  +                        col.setConfig(cfg);
  +                        collections.put(col.getName(), col);
  +                    }
  +                    // else, assume col is configured elsewhere...
  +                    // I'm not sure this should be happening, but it does
  +                    // it is not safe to call col.setConfig again since it does a bunch
  +                    // of stuff (like creating a new Filer and overwriting the existing one, etc.)
  +                }
  +            });
  +        }
  +    }
   }
  
  
  
  1.15      +12 -12    xml-xindice/java/src/org/apache/xindice/core/SystemCollection.java
  
  Index: SystemCollection.java
  ===================================================================
  RCS file: /home/cvs/xml-xindice/java/src/org/apache/xindice/core/SystemCollection.java,v
  retrieving revision 1.14
  retrieving revision 1.15
  diff -u -r1.14 -r1.15
  --- SystemCollection.java	14 Jul 2003 19:08:16 -0000	1.14
  +++ SystemCollection.java	15 Jul 2003 15:44:35 -0000	1.15
  @@ -96,19 +96,19 @@
   
           String SysCol = "<collection name=\"" + SYSCOL + "\">"
               // System Collections
  -    		+"   <collections>"
  +    +"   <collections>"
               // Symbol Tables Collection
  -    		+"      <collection name=\"" + SYMBOLS + "\" compressed=\"true\">" + "         <filer class=\"org.apache.xindice.core.filer.BTreeFiler\" />"
  +    +"      <collection name=\"" + SYMBOLS + "\" compressed=\"true\">" + "         <filer class=\"org.apache.xindice.core.filer.BTreeFiler\" />"
               // Textual Representation of Hard-coded Symbol Table
  -    		+SymbolTableSymbols.getDefinition() + "      </collection>"
  +    +SymbolTableSymbols.getDefinition() + "      </collection>"
               // System Configuration Collection
  -    		+"      <collection name=\""
  -        	+ CONFIGS
  -        	+ "\" compressed=\"false\">"
  -        	+ "         <filer class=\"org.apache.xindice.core.filer.BTreeFiler\" />"
  -        	+ "      </collection>"
  -        	+ "   </collections>"
  -        	+ "</collection>";
  +    +"      <collection name=\""
  +        + CONFIGS
  +        + "\" compressed=\"false\">"
  +        + "         <filer class=\"org.apache.xindice.core.filer.BTreeFiler\" />"
  +        + "      </collection>"
  +        + "   </collections>"
  +        + "</collection>";
   
           try {
               Document sysDoc = DOMParser.toDocument(SysCol);
  @@ -119,7 +119,7 @@
               if (log.isFatalEnabled()) {
                   log.fatal("FATAL ERROR: Generating System Collection '" + SYSCOL + "'", e);
               }
  -            
  +
               // TODO: System.exit() CANNOT be good here.  
               System.exit(1);
           }
  
  
  
  1.22      +5 -13     xml-xindice/java/src/org/apache/xindice/core/Collection.java
  
  Index: Collection.java
  ===================================================================
  RCS file: /home/cvs/xml-xindice/java/src/org/apache/xindice/core/Collection.java,v
  retrieving revision 1.21
  retrieving revision 1.22
  diff -u -r1.21 -r1.22
  --- Collection.java	14 Jul 2003 19:07:15 -0000	1.21
  +++ Collection.java	15 Jul 2003 15:44:35 -0000	1.22
  @@ -181,9 +181,7 @@
                               return new ColContainer(key, DOMParser.toDocument(val));
                       }
                       catch (Exception e) {
  -                        if (log.isDebugEnabled()) {
  -                            log.debug("No message", e);
  -                        }
  +                        log.warn(e);
                       }
                   }
               }
  @@ -369,9 +367,7 @@
               ((Collection) this).close();
           }
           catch (Exception e) {
  -            if (log.isDebugEnabled()) {
  -                log.debug("No message", e);
  -            }
  +            log.warn(e);
           }
       }
   
  @@ -847,9 +843,7 @@
                       return obj;
                   }
                   catch (Exception e) {
  -                    if (log.isDebugEnabled()) {
  -                        log.debug("No message", e);
  -                    }
  +                    log.warn(e);
                   }
               }
           }
  @@ -1431,9 +1425,7 @@
                   indexManager.setConfig(idxConfig);
               }
               catch (Exception e) {
  -                if (log.isDebugEnabled()) {
  -                    log.debug("No message", e);
  -                }
  +                log.warn(e);
               }
           }
   
  
  
  
  1.8       +231 -243  xml-xindice/java/src/org/apache/xindice/core/filer/FSFiler.java
  
  Index: FSFiler.java
  ===================================================================
  RCS file: /home/cvs/xml-xindice/java/src/org/apache/xindice/core/filer/FSFiler.java,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- FSFiler.java	14 Jul 2003 13:58:17 -0000	1.7
  +++ FSFiler.java	15 Jul 2003 15:44:35 -0000	1.8
  @@ -59,6 +59,16 @@
    * $Id$
    */
   
  +import java.io.File;
  +import java.io.FileFilter;
  +import java.io.FileOutputStream;
  +import java.util.HashMap;
  +import java.util.HashSet;
  +import java.util.Set;
  +import java.util.StringTokenizer;
  +
  +import org.apache.commons.logging.Log;
  +import org.apache.commons.logging.LogFactory;
   import org.apache.xindice.core.DBException;
   import org.apache.xindice.core.FaultCodes;
   import org.apache.xindice.core.data.Key;
  @@ -71,259 +81,237 @@
   import org.apache.xindice.util.SimpleConfigurable;
   import org.apache.xindice.util.XindiceException;
   
  -import org.apache.commons.logging.Log;
  -import org.apache.commons.logging.LogFactory;
  -
  -import java.io.File;
  -import java.io.FileFilter;
  -import java.io.FileOutputStream;
  -import java.util.HashMap;
  -import java.util.HashSet;
  -import java.util.Set;
  -import java.util.StringTokenizer;
  -
   /**
    * FSFiler allows you to use existing file systems withing Xindice.
    */
   
   public final class FSFiler extends SimpleConfigurable implements Filer {
  -   private static final String LOCATION = "location";
  -   private static final String EXT = "ext";
  -   private static final String READONLY = "readonly";
  -
  -   private static Log log = LogFactory.getLog("org.apache.xindice.core");
  -
  -   private FileCache cache = new FileCache();
  -   private LockManager locks = new LockManager(16);
  -
  -   private Set extensions = null;
  -
  -   private String location;
  -   private File dir;
  -   private boolean opened = false;
  -   private boolean readOnly = false;
  -
  -   public FSFiler() {
  -   }
  -
  -   public String getName() {
  -      return "FSFiler";
  -   }
  -
  -   public void setLocation(File root, String location) {
  -   }
  -   
  -   public void setConfig(Configuration config) throws XindiceException {
  -      super.setConfig(config);
  -      location = config.getAttribute(LOCATION);
  -      readOnly = config.getBooleanAttribute(READONLY, readOnly);
  -      String exts = config.getAttribute(EXT);
  -      if ( exts != null && exts.trim().length() > 0 ) {
  -         extensions = new HashSet();
  -         StringTokenizer st = new StringTokenizer(exts);
  -         while ( st.hasMoreTokens() )
  -            extensions.add(st.nextToken());
  -      }
  -      dir = new File(location);
  -      opened = false;
  -   }
  -
  -   private void checkOpened() throws DBException {
  -      if ( !opened )
  -         throw new FilerException(FaultCodes.COL_COLLECTION_CLOSED, "Filer is closed");
  -   }
  -
  -   private void checkReadOnly() throws DBException {
  -      if ( readOnly )
  -         throw new FilerException(FaultCodes.COL_COLLECTION_READ_ONLY, "Filer is read-only");
  -   }
  -
  -   public boolean close() {
  -      opened = false;
  -      return true;
  -   }
  -
  -   public boolean open() {
  -      opened = (dir.exists() && dir.isDirectory());
  -      return opened;
  -   }
  -
  -   public boolean drop() {
  -      opened = false;
  -      return true;
  -   }
  -
  -   public boolean isOpened() {
  -      return opened;
  -   }
  -
  -   public boolean exists() {
  -      return dir.exists();
  -   }
  -
  -   public boolean create() {
  -      if ( !dir.exists() )
  -         return dir.mkdirs();
  -      else
  -         return true;
  -   }
  -
  -   public void flush() {
  -   }
  -
  -   public Record readRecord(Key key) throws DBException {
  -      if ( key == null || key.equals("") ) {
  -         return null;
  -      }
  -      checkOpened();
  -
  -      String fname = key.toString();
  -      if ( !isExtensionValid(fname) )
  -         return null;
  -
  -      File file = new File(dir, fname);
  -      try {
  -         locks.acquireSharedLock(file);
  -
  -         HashMap meta = new HashMap(2);
  -         meta.put(Record.MODIFIED, new Long(file.lastModified()));
  -
  -         byte[] valueData = cache.getFile(file);
  -         if ( valueData != null )
  -            return new Record(key, new Value(valueData), meta);
  -      }
  -      catch ( Exception e ) {
  -         if (log.isDebugEnabled()) {
  -            log.debug("No message", e);
  -         }
  -      }
  -      finally {
  -         locks.releaseSharedLock(file);
  -      }
  -      return null;
  -   }
  -
  -   public boolean writeRecord(Key key, Value value) throws DBException {
  -      if ( key == null || key.equals("") ) {
  -         throw new FilerException(FaultCodes.DBE_CANNOT_CREATE, "Invalid key: '" + key + "'");
  -      }
  -      if (value == null ) {
  -         throw new FilerException(FaultCodes.DBE_CANNOT_CREATE, "Invalid null value");
  -      }
  -      checkOpened();
  -      checkReadOnly();
  -
  -      String fname = key.toString();
  -      if ( !isExtensionValid(fname) )
  -         return false;
  -
  -      File file = new File(dir, fname);
  -      try {
  -         locks.acquireExclusiveLock(file);
  -         FileOutputStream fos = new FileOutputStream(file);
  -         value.streamTo(fos);
  -         fos.close();
  -         return true;
  -      }
  -      catch ( Exception e ) {
  -         if (log.isDebugEnabled()) {
  -            log.debug("No message", e);
  -         }
  -      }
  -      finally {
  -         locks.releaseExclusiveLock(file);
  -      }
  -      return true;
  -   }
  -
  -   public boolean deleteRecord(Key key) throws DBException {
  -      if ( key == null || key.equals("") ) {
  -         return false;
  -      }
  -      checkOpened();
  -      checkReadOnly();
  -
  -      String fname = key.toString();
  -      if ( !isExtensionValid(fname) )
  -         return false;
  -
  -      File file = new File(dir, fname);
  -      try {
  -         locks.acquireExclusiveLock(file);
  -         return file.delete();
  -      }
  -      catch ( Exception e ) {
  -         if (log.isDebugEnabled()) {
  -            log.debug("No message", e);
  -         }
  -      }
  -      finally {
  -         locks.releaseExclusiveLock(file);
  -      }
  -      return true;
  -   }
  -
  -   public long getRecordCount() throws DBException {
  -      checkOpened();
  -
  -      File[] files = dir.listFiles(new FileFilter() {
  -         public boolean accept(File file) {
  -            return file.isFile() && isExtensionValid(file.getName());
  -         }
  -      });
  -      return files.length;
  -   }
  -
  -   public RecordSet getRecordSet() throws DBException {
  -      checkOpened();
  -      return new FSRecordSet();
  -   }
  -
  -   private boolean isExtensionValid(String fname) {
  -      if ( extensions != null ) {
  -         int idx = fname.lastIndexOf('.');
  -         if ( idx == -1 )
  +    private static final String LOCATION = "location";
  +    private static final String EXT = "ext";
  +    private static final String READONLY = "readonly";
  +
  +    private static Log log = LogFactory.getLog("org.apache.xindice.core");
  +
  +    private FileCache cache = new FileCache();
  +    private LockManager locks = new LockManager(16);
  +
  +    private Set extensions = null;
  +
  +    private String location;
  +    private File dir;
  +    private boolean opened = false;
  +    private boolean readOnly = false;
  +
  +    public FSFiler() {}
  +
  +    public String getName() {
  +        return "FSFiler";
  +    }
  +
  +    public void setLocation(File root, String location) {}
  +
  +    public void setConfig(Configuration config) throws XindiceException {
  +        super.setConfig(config);
  +        location = config.getAttribute(LOCATION);
  +        readOnly = config.getBooleanAttribute(READONLY, readOnly);
  +        String exts = config.getAttribute(EXT);
  +        if (exts != null && exts.trim().length() > 0) {
  +            extensions = new HashSet();
  +            StringTokenizer st = new StringTokenizer(exts);
  +            while (st.hasMoreTokens())
  +                extensions.add(st.nextToken());
  +        }
  +        dir = new File(location);
  +        opened = false;
  +    }
  +
  +    private void checkOpened() throws DBException {
  +        if (!opened)
  +            throw new FilerException(FaultCodes.COL_COLLECTION_CLOSED, "Filer is closed");
  +    }
  +
  +    private void checkReadOnly() throws DBException {
  +        if (readOnly)
  +            throw new FilerException(FaultCodes.COL_COLLECTION_READ_ONLY, "Filer is read-only");
  +    }
  +
  +    public boolean close() {
  +        opened = false;
  +        return true;
  +    }
  +
  +    public boolean open() {
  +        opened = (dir.exists() && dir.isDirectory());
  +        return opened;
  +    }
  +
  +    public boolean drop() {
  +        opened = false;
  +        return true;
  +    }
  +
  +    public boolean isOpened() {
  +        return opened;
  +    }
  +
  +    public boolean exists() {
  +        return dir.exists();
  +    }
  +
  +    public boolean create() {
  +        if (!dir.exists())
  +            return dir.mkdirs();
  +        else
  +            return true;
  +    }
  +
  +    public void flush() {}
  +
  +    public Record readRecord(Key key) throws DBException {
  +        if (key == null || key.equals("")) {
  +            return null;
  +        }
  +        checkOpened();
  +
  +        String fname = key.toString();
  +        if (!isExtensionValid(fname))
  +            return null;
  +
  +        File file = new File(dir, fname);
  +        try {
  +            locks.acquireSharedLock(file);
  +
  +            HashMap meta = new HashMap(2);
  +            meta.put(Record.MODIFIED, new Long(file.lastModified()));
  +
  +            byte[] valueData = cache.getFile(file);
  +            if (valueData != null)
  +                return new Record(key, new Value(valueData), meta);
  +        }
  +        catch (Exception e) {
  +            log.warn(e);
  +        }
  +        finally {
  +            locks.releaseSharedLock(file);
  +        }
  +        return null;
  +    }
  +
  +    public boolean writeRecord(Key key, Value value) throws DBException {
  +        if (key == null || key.equals("")) {
  +            throw new FilerException(FaultCodes.DBE_CANNOT_CREATE, "Invalid key: '" + key + "'");
  +        }
  +        if (value == null) {
  +            throw new FilerException(FaultCodes.DBE_CANNOT_CREATE, "Invalid null value");
  +        }
  +        checkOpened();
  +        checkReadOnly();
  +
  +        String fname = key.toString();
  +        if (!isExtensionValid(fname))
               return false;
  -         String ext = fname.substring(idx + 1);
  -         if ( !extensions.contains(ext) )
  +
  +        File file = new File(dir, fname);
  +        try {
  +            locks.acquireExclusiveLock(file);
  +            FileOutputStream fos = new FileOutputStream(file);
  +            value.streamTo(fos);
  +            fos.close();
  +            return true;
  +        }
  +        catch (Exception e) {
  +            log.warn(e);
  +        }
  +        finally {
  +            locks.releaseExclusiveLock(file);
  +        }
  +        return true;
  +    }
  +
  +    public boolean deleteRecord(Key key) throws DBException {
  +        if (key == null || key.equals("")) {
               return false;
  -      }
  -      return true;
  -   }
  +        }
  +        checkOpened();
  +        checkReadOnly();
   
  +        String fname = key.toString();
  +        if (!isExtensionValid(fname))
  +            return false;
   
  -   /**
  -    * FSRecordSet
  -    */
  +        File file = new File(dir, fname);
  +        try {
  +            locks.acquireExclusiveLock(file);
  +            return file.delete();
  +        }
  +        catch (Exception e) {
  +            log.warn(e);
  +        }
  +        finally {
  +            locks.releaseExclusiveLock(file);
  +        }
  +        return true;
  +    }
   
  -   private class FSRecordSet implements RecordSet {
  -      public File[] files;
  -      public int pos = 0;
  +    public long getRecordCount() throws DBException {
  +        checkOpened();
   
  -      public FSRecordSet() {
  -         files = dir.listFiles(new FileFilter() {
  +        File[] files = dir.listFiles(new FileFilter() {
               public boolean accept(File file) {
  -               return file.isFile() && isExtensionValid(file.getName());
  +                return file.isFile() && isExtensionValid(file.getName());
               }
  -         });
  -      }
  -
  -      public synchronized boolean hasMoreRecords() {
  -         return pos < files.length;
  -      }
  -
  -      public synchronized Record getNextRecord() throws DBException {
  -         File file = files[pos++];
  -         return readRecord(new Key(file.getName()));
  -      }
  -
  -      public synchronized Value getNextValue() throws DBException {
  -         return getNextRecord().getValue();
  -      }
  -
  -      public synchronized Key getNextKey() {
  -         return new Key(files[pos++].getName());
  -      }
  -   }
  +        });
  +        return files.length;
  +    }
  +
  +    public RecordSet getRecordSet() throws DBException {
  +        checkOpened();
  +        return new FSRecordSet();
  +    }
  +
  +    private boolean isExtensionValid(String fname) {
  +        if (extensions != null) {
  +            int idx = fname.lastIndexOf('.');
  +            if (idx == -1)
  +                return false;
  +            String ext = fname.substring(idx + 1);
  +            if (!extensions.contains(ext))
  +                return false;
  +        }
  +        return true;
  +    }
  +
  +    /**
  +     * FSRecordSet
  +     */
  +
  +    private class FSRecordSet implements RecordSet {
  +        public File[] files;
  +        public int pos = 0;
  +
  +        public FSRecordSet() {
  +            files = dir.listFiles(new FileFilter() {
  +                public boolean accept(File file) {
  +                    return file.isFile() && isExtensionValid(file.getName());
  +                }
  +            });
  +        }
  +
  +        public synchronized boolean hasMoreRecords() {
  +            return pos < files.length;
  +        }
  +
  +        public synchronized Record getNextRecord() throws DBException {
  +            File file = files[pos++];
  +            return readRecord(new Key(file.getName()));
  +        }
  +
  +        public synchronized Value getNextValue() throws DBException {
  +            return getNextRecord().getValue();
  +        }
  +
  +        public synchronized Key getNextKey() {
  +            return new Key(files[pos++].getName());
  +        }
  +    }
   }
  -
  
  
  
  1.11      +918 -927  xml-xindice/java/src/org/apache/xindice/core/filer/BTree.java
  
  Index: BTree.java
  ===================================================================
  RCS file: /home/cvs/xml-xindice/java/src/org/apache/xindice/core/filer/BTree.java,v
  retrieving revision 1.10
  retrieving revision 1.11
  diff -u -r1.10 -r1.11
  --- BTree.java	22 Nov 2002 10:15:34 -0000	1.10
  +++ BTree.java	15 Jul 2003 15:44:35 -0000	1.11
  @@ -104,956 +104,947 @@
    */
   
   public class BTree extends Paged {
  -   protected static final byte LEAF = 1;
  -   protected static final byte BRANCH = 2;
  -   protected static final byte STREAM = 3;
  -
  -   private static Log log = LogFactory.getLog("org.apache.xindice.core");
  -
  -   private Map cache = new WeakHashMap();
  -
  -   private BTreeFileHeader fileHeader;
  -   private BTreeRootInfo rootInfo;
  -   private BTreeNode rootNode;
  -
  -   public BTree() {
  -      super();
  -      fileHeader = (BTreeFileHeader)getFileHeader();
  -      fileHeader.setPageCount(1);
  -      fileHeader.setTotalCount(1);
  -   }
  -
  -   public BTree(File file) {
  -      this();
  -      setFile(file);
  -   }
  -
  -   public boolean open() throws DBException {
  -      if ( super.open() ) {
  -         long p = fileHeader.getRootPage();
  -         rootInfo = new BTreeRootInfo(p);
  -         rootNode = getBTreeNode(rootInfo, p, null);
  -         return true;
  -      }
  -      else
  -         return false;
  -   }
  -
  -   public boolean create() throws DBException {
  -      if ( super.create() ) {
  -         try {
  -            open();
  +    protected static final byte LEAF = 1;
  +    protected static final byte BRANCH = 2;
  +    protected static final byte STREAM = 3;
  +
  +    private static Log log = LogFactory.getLog("org.apache.xindice.core");
  +
  +    private Map cache = new WeakHashMap();
  +
  +    private BTreeFileHeader fileHeader;
  +    private BTreeRootInfo rootInfo;
  +    private BTreeNode rootNode;
  +
  +    public BTree() {
  +        super();
  +        fileHeader = (BTreeFileHeader) getFileHeader();
  +        fileHeader.setPageCount(1);
  +        fileHeader.setTotalCount(1);
  +    }
  +
  +    public BTree(File file) {
  +        this();
  +        setFile(file);
  +    }
  +
  +    public boolean open() throws DBException {
  +        if (super.open()) {
               long p = fileHeader.getRootPage();
               rootInfo = new BTreeRootInfo(p);
  -            rootNode = new BTreeNode(rootInfo, getPage(p));
  -            rootNode.ph.setStatus(LEAF);
  -            rootNode.setValues(new Value[0]);
  -            rootNode.setPointers(new long[0]);
  -            rootNode.write();
  -            close();
  +            rootNode = getBTreeNode(rootInfo, p, null);
               return true;
  -         }
  -         catch ( Exception e ) {
  -            if (log.isDebugEnabled()) {
  -               log.debug("No message", e);
  -            }
  -         }
  -      }
  -      return false;
  -   }
  -
  -   /**
  -    * addValue adds a Value to the BTree and associates a pointer with
  -    * it.  The pointer can be used for referencing any type of data, it
  -    * just so happens that Xindice uses it for referencing pages of
  -    * associated data in the BTree file or other files.
  -    *
  -    * @param value The Value to add
  -    * @param pointer The pointer to associate with it
  -    * @return The previous value for the pointer (or -1)
  -    */
  -   public long addValue(Value value, long pointer) throws IOException, BTreeException {
  -      return getRootNode().addValue(value, pointer);
  -   }
  -
  -   /**
  -    * addValue adds a Value to the BTree and associates a pointer with
  -    * it.  The pointer can be used for referencing any type of data, it
  -    * just so happens that Xindice uses it for referencing pages of
  -    * associated data in the BTree file or other files.
  -    *
  -    * @param root The BTree's root information (for nested trees)
  -    * @param value The Value to add
  -    * @param pointer The pointer to associate with it
  -    * @return The previous value for the pointer (or -1)
  -    */
  -   public long addValue(BTreeRootInfo root, Value value, long pointer) throws IOException, BTreeException {
  -      return getRootNode(root).addValue(value, pointer);
  -   }
  -
  -   /**
  -    * removeValue removes a Value from the BTree and returns the
  -    * associated pointer for it.
  -    *
  -    * @param value The Value to remove
  -    * @return The pointer that was associated with it
  -    */
  -   public long removeValue(Value value) throws IOException, BTreeException {
  -      return getRootNode().removeValue(value);
  -   }
  -
  -   /**
  -    * removeValue removes a Value from the BTree and returns the
  -    * associated pointer for it.
  -    *
  -    * @param root The BTree's root information (for nested trees)
  -    * @param value The Value to remove
  -    * @return The pointer that was associated with it
  -    */
  -   public long removeValue(BTreeRootInfo root, Value value) throws IOException, BTreeException {
  -      return getRootNode(root).removeValue(value);
  -   }
  -
  -   /**
  -    * findValue finds a Value in the BTree and returns the associated
  -    * pointer for it.
  -    *
  -    * @param value The Value to find
  -    * @return The pointer that was associated with it
  -    */
  -   public long findValue(Value value) throws IOException, BTreeException {
  -      return getRootNode().findValue(value);
  -   }
  -
  -   /**
  -    * findValue finds a Value in the BTree and returns the associated
  -    * pointer for it.
  -    *
  -    * @param root The BTree's root information (for nested trees)
  -    * @param value The Value to find
  -    * @return The pointer that was associated with it
  -    */
  -   public long findValue(BTreeRootInfo root, Value value) throws IOException, BTreeException {
  -      return getRootNode(root).findValue(value);
  -   }
  -
  -   /**
  -    * query performs a query against the BTree and performs callback
  -    * operations to report the search results.
  -    *
  -    * @param query The IndexQuery to use (or null for everything)
  -    * @param callback The callback instance
  -    */
  -   public void query(IndexQuery query, BTreeCallback callback) throws IOException, BTreeException {
  -      getRootNode().query(query, callback);
  -   }
  -
  -   /**
  -    * query performs a query against the BTree and performs callback
  -    * operations to report the search results.
  -    *
  -    * @param root The BTree's root information (for nested trees)
  -    * @param query The IndexQuery to use (or null for everything)
  -    * @param callback The callback instance
  -    */
  -   public void query(BTreeRootInfo root, IndexQuery query, BTreeCallback callback) throws IOException, BTreeException {
  -      getRootNode(root).query(query, callback);
  -   }
  -
  -   /**
  -    * createBTreeRoot creates a new BTree root node in the BTree file
  -    * based on the provided value for the main tree.
  -    *
  -    * @param v The sub-tree Value to create
  -    * @return The new BTreeRootInfo instance
  -    */
  -   protected final BTreeRootInfo createBTreeRoot(Value v) throws IOException, BTreeException {
  -      BTreeNode n = createBTreeNode(rootInfo, BTree.LEAF, null);
  -      n.write();
  -
  -      long position = n.page.getPageNum();
  -      addValue(v, position);
  -      return new BTreeRootInfo(v, position);
  -   }
  -
  -   /**
  -    * createBTreeRoot creates a new BTree root node in the BTree file
  -    * based on the provided root information, and value for the tree.
  -    *
  -    * @param root The BTreeRootInfo to build off of
  -    * @param v The sub-tree Value to create
  -    * @return The new BTreeRootInfo instance
  -    */
  -   protected final BTreeRootInfo createBTreeRoot(BTreeRootInfo root, Value v) throws IOException, BTreeException {
  -      BTreeNode n = createBTreeNode(root, BTree.LEAF, null);
  -      n.write();
  -
  -      long position = n.page.getPageNum();
  -      addValue(v, position);
  -      return new BTreeRootInfo(root, v, position);
  -   }
  -
  -   /**
  -    * findBTreeRoot searches for a BTreeRoot in the file and returns
  -    * the BTreeRootInfo for the specified value based on the main tree.
  -    *
  -    * @param v The sub-tree Value to search for
  -    * @return The new BTreeRootInfo instance
  -    */
  -   protected final BTreeRootInfo findBTreeRoot(Value v) throws IOException, BTreeException {
  -      long position = findValue(v);
  -      return new BTreeRootInfo(v, position);
  -   }
  -
  -   /**
  -    * findBTreeRoot searches for a BTreeRoot in the file and returns
  -    * the BTreeRootInfo for the specified value based on the provided
  -    * BTreeRootInfo value.
  -    *
  -    * @param root The BTreeRootInfo to search from
  -    * @param v The sub-tree Value to search for
  -    * @return The new BTreeRootInfo instance
  -    */
  -   protected final BTreeRootInfo findBTreeRoot(BTreeRootInfo root, Value v) throws IOException, BTreeException {
  -      long position = findValue(root, v);
  -      return new BTreeRootInfo(root, v, position);
  -   }
  -
  -   /**
  -    * setRootNode resets the root for the specified root object to the
  -    * provided BTreeNode's page number.
  -    *
  -    * @param root The root to reset
  -    * @param newRoot the new root node to use
  -    */
  -   protected final void setRootNode(BTreeRootInfo root, BTreeNode newRoot) throws IOException, BTreeException {
  -      BTreeRootInfo parent = root.getParent();
  -      if ( parent == null ) {
  -         rootNode = newRoot;
  -         long p = rootNode.page.getPageNum();
  -         rootInfo.setPage(p);
  -         fileHeader.setRootPage(p);
  -      }
  -      else {
  -         long p = newRoot.page.getPageNum();
  -         root.setPage(p);
  -         addValue(parent, root.name, p);
  -      }
  -   }
  -
  -   /**
  -    * setRootNode resets the file's root to the provided
  -    * BTreeNode's page number.
  -    *
  -    * @param rootNode the new root node to use
  -    */
  -   protected final void setRootNode(BTreeNode rootNode) throws IOException, BTreeException {
  -      setRootNode(rootInfo, rootNode);
  -   }
  -
  -   /**
  -    * getRootNode retreives the BTree node for the specified
  -    * root object.
  -    *
  -    * @param root The root object to retrieve with
  -    * @return The root node
  -    */
  -   protected final BTreeNode getRootNode(BTreeRootInfo root) {
  -      if ( root.page == rootInfo.page )
  -         return rootNode;
  -      else
  -         return getBTreeNode(root, root.getPage(), null);
  -   }
  -
  -   /**
  -    * getRootNode retreives the BTree node for the file's root.
  -    *
  -    * @return The root node
  -    */
  -   protected final BTreeNode getRootNode() {
  -      return rootNode;
  -   }
  -
  -   private BTreeNode getBTreeNode(BTreeRootInfo root, long page, BTreeNode parent) {
  -      try {
  -         BTreeNode node;
  -         synchronized ( this ) {
  -            Long pNum = new Long(page);
  -            node = (BTreeNode)cache.get(pNum);
  -            if ( node == null ) {
  -               Page p = getPage(pNum);
  -               node = new BTreeNode(root, p, parent);
  +        }
  +        else
  +            return false;
  +    }
  +
  +    public boolean create() throws DBException {
  +        if (super.create()) {
  +            try {
  +                open();
  +                long p = fileHeader.getRootPage();
  +                rootInfo = new BTreeRootInfo(p);
  +                rootNode = new BTreeNode(rootInfo, getPage(p));
  +                rootNode.ph.setStatus(LEAF);
  +                rootNode.setValues(new Value[0]);
  +                rootNode.setPointers(new long[0]);
  +                rootNode.write();
  +                close();
  +                return true;
               }
  -            else {
  -               node.root = root;
  -               node.parent = parent;
  +            catch (Exception e) {
  +                log.warn(e);
               }
  -         }
  -         synchronized ( node ) {
  -            if ( !node.isLoaded() ) {
  -               node.read();
  -               node.setLoaded(true);
  -            }
  -         }
  -         return node;
  -      }
  -      catch ( Exception e ) {
  -         return null;
  -      }
  -   }
  -
  -   private BTreeNode createBTreeNode(BTreeRootInfo root, byte status, BTreeNode parent) {
  -      try {
  -         Page p = getFreePage();
  -         BTreeNode node = new BTreeNode(root, p, parent);
  -         node.ph.setStatus(status);
  -         node.setValues(new Value[0]);
  -         node.setPointers(new long[0]);
  -         return node;
  -      }
  -      catch ( Exception e ) {
  -         return null;
  -      }
  -   }
  -
  -
  -   /**
  -    * BTreeRootInfo
  -    */
  -
  -   public final class BTreeRootInfo {
  -      private BTreeRootInfo parent;
  -      private Value name;
  -      private long page;
  -
  -      public BTreeRootInfo(BTreeRootInfo parent, String name, long page) {
  -         this.parent = parent;
  -         this.name = new Value(name);
  -         this.page = page;
  -      }
  -
  -      public BTreeRootInfo(BTreeRootInfo parent, Value name, long page) {
  -         this.parent = parent;
  -         this.name = name;
  -         this.page = page;
  -      }
  -
  -      public BTreeRootInfo(String name, long page) {
  -         this.parent = rootInfo;
  -         this.name = new Value(name);
  -         this.page = page;
  -      }
  -
  -      public BTreeRootInfo(Value name, long page) {
  -         this.parent = rootInfo;
  -         this.name = name;
  -         this.page = page;
  -      }
  -
  -      private BTreeRootInfo(long page) {
  -         parent = null;
  -         name = null;
  -         this.page = page;
  -      }
  -
  -      public synchronized BTreeRootInfo getParent() {
  -         return parent;
  -      }
  -
  -      public synchronized Value getName() {
  -         return name;
  -      }
  -
  -      public synchronized long getPage() {
  -         return page;
  -      }
  -
  -      public synchronized void setPage(long page) {
  -         this.page = page;
  -      }
  -   }
  -
  -
  -   /**
  -    * BTreeNode
  -    */
  -
  -   private final class BTreeNode {
  -      private BTreeRootInfo root;
  -      private Page page;
  -      private BTreePageHeader ph;
  -      private Value[] values;
  -      private long[] ptrs;
  -      private BTreeNode parent;
  -      private boolean loaded;
  -
  -      public BTreeNode(BTreeRootInfo root, Page page, BTreeNode parent) {
  -         this.root = root;
  -         this.page = page;
  -         this.parent = parent;
  -         ph = (BTreePageHeader)page.getPageHeader();
  -      }
  -
  -      public BTreeNode(BTreeRootInfo root, Page page) {
  -         this.root = root;
  -         this.page = page;
  -         ph = (BTreePageHeader)page.getPageHeader();
  -      }
  -
  -      public synchronized void setValues(Value[] values) {
  -         this.values = values;
  -         ph.setValueCount((short)values.length);
  -      }
  -
  -      public synchronized Value[] getValues() {
  -         return values;
  -      }
  -
  -      public synchronized void setPointers(long[] ptrs) {
  -         this.ptrs = ptrs;
  -      }
  -
  -      public synchronized long[] getPointers() {
  -         return ptrs;
  -      }
  -
  -      public synchronized boolean isLoaded() {
  -         return loaded;
  -      }
  -
  -      public synchronized void setLoaded(boolean loaded) {
  -         this.loaded = loaded;
  -      }
  -
  -      public synchronized void read() throws IOException {
  -         Value v = readValue(page);
  -         DataInputStream is = new DataInputStream(v.getInputStream());
  -
  -         // Read in the Values
  -         values = new Value[ph.getValueCount()];
  -         for ( int i = 0; i < values.length; i++ ) {
  -            short valSize = is.readShort();
  -            byte[] b = new byte[valSize];
  -
  -            is.read(b);
  -            values[i] = new Value(b);
  -         }
  -
  -         // Read in the pointers
  -         ptrs = new long[ph.getPointerCount()];
  -         for ( int i = 0; i < ptrs.length; i++ )
  -            ptrs[i] = is.readLong();
  -
  -         cache.put(new Long(page.getPageNum()), this);
  -      }
  -
  -      public synchronized void write() throws IOException {
  -         ByteArrayOutputStream bos = new ByteArrayOutputStream((int)fileHeader.getWorkSize());
  -         DataOutputStream os = new DataOutputStream(bos);
  -
  -         // Write out the Values
  -         for ( int i = 0; i < values.length; i++ ) {
  -            os.writeShort(values[i].getLength());
  -            values[i].streamTo(os);
  -         }
  -
  -         // Write out the pointers
  -         for ( int i = 0; i < ptrs.length; i++ )
  -            os.writeLong(ptrs[i]);
  -
  -         writeValue(page, new Value(bos.toByteArray()));
  -
  -         cache.put(new Long(page.getPageNum()), this);
  -      }
  -
  -      public BTreeNode getChildNode(int idx) throws IOException {
  -         boolean load;
  -         BTreeRootInfo loadNode;
  -         long loadPtr;
  -         synchronized ( this ) {
  -            if ( ph.getStatus() == BRANCH && idx >= 0 && idx < ptrs.length ) {
  -               load = true;
  -               loadNode = root;
  -               loadPtr = ptrs[idx];
  +        }
  +        return false;
  +    }
  +
  +    /**
  +     * addValue adds a Value to the BTree and associates a pointer with
  +     * it.  The pointer can be used for referencing any type of data, it
  +     * just so happens that Xindice uses it for referencing pages of
  +     * associated data in the BTree file or other files.
  +     *
  +     * @param value The Value to add
  +     * @param pointer The pointer to associate with it
  +     * @return The previous value for the pointer (or -1)
  +     */
  +    public long addValue(Value value, long pointer) throws IOException, BTreeException {
  +        return getRootNode().addValue(value, pointer);
  +    }
  +
  +    /**
  +     * addValue adds a Value to the BTree and associates a pointer with
  +     * it.  The pointer can be used for referencing any type of data, it
  +     * just so happens that Xindice uses it for referencing pages of
  +     * associated data in the BTree file or other files.
  +     *
  +     * @param root The BTree's root information (for nested trees)
  +     * @param value The Value to add
  +     * @param pointer The pointer to associate with it
  +     * @return The previous value for the pointer (or -1)
  +     */
  +    public long addValue(BTreeRootInfo root, Value value, long pointer) throws IOException, BTreeException {
  +        return getRootNode(root).addValue(value, pointer);
  +    }
  +
  +    /**
  +     * removeValue removes a Value from the BTree and returns the
  +     * associated pointer for it.
  +     *
  +     * @param value The Value to remove
  +     * @return The pointer that was associated with it
  +     */
  +    public long removeValue(Value value) throws IOException, BTreeException {
  +        return getRootNode().removeValue(value);
  +    }
  +
  +    /**
  +     * removeValue removes a Value from the BTree and returns the
  +     * associated pointer for it.
  +     *
  +     * @param root The BTree's root information (for nested trees)
  +     * @param value The Value to remove
  +     * @return The pointer that was associated with it
  +     */
  +    public long removeValue(BTreeRootInfo root, Value value) throws IOException, BTreeException {
  +        return getRootNode(root).removeValue(value);
  +    }
  +
  +    /**
  +     * findValue finds a Value in the BTree and returns the associated
  +     * pointer for it.
  +     *
  +     * @param value The Value to find
  +     * @return The pointer that was associated with it
  +     */
  +    public long findValue(Value value) throws IOException, BTreeException {
  +        return getRootNode().findValue(value);
  +    }
  +
  +    /**
  +     * findValue finds a Value in the BTree and returns the associated
  +     * pointer for it.
  +     *
  +     * @param root The BTree's root information (for nested trees)
  +     * @param value The Value to find
  +     * @return The pointer that was associated with it
  +     */
  +    public long findValue(BTreeRootInfo root, Value value) throws IOException, BTreeException {
  +        return getRootNode(root).findValue(value);
  +    }
  +
  +    /**
  +     * query performs a query against the BTree and performs callback
  +     * operations to report the search results.
  +     *
  +     * @param query The IndexQuery to use (or null for everything)
  +     * @param callback The callback instance
  +     */
  +    public void query(IndexQuery query, BTreeCallback callback) throws IOException, BTreeException {
  +        getRootNode().query(query, callback);
  +    }
  +
  +    /**
  +     * query performs a query against the BTree and performs callback
  +     * operations to report the search results.
  +     *
  +     * @param root The BTree's root information (for nested trees)
  +     * @param query The IndexQuery to use (or null for everything)
  +     * @param callback The callback instance
  +     */
  +    public void query(BTreeRootInfo root, IndexQuery query, BTreeCallback callback) throws IOException, BTreeException {
  +        getRootNode(root).query(query, callback);
  +    }
  +
  +    /**
  +     * createBTreeRoot creates a new BTree root node in the BTree file
  +     * based on the provided value for the main tree.
  +     *
  +     * @param v The sub-tree Value to create
  +     * @return The new BTreeRootInfo instance
  +     */
  +    protected final BTreeRootInfo createBTreeRoot(Value v) throws IOException, BTreeException {
  +        BTreeNode n = createBTreeNode(rootInfo, BTree.LEAF, null);
  +        n.write();
  +
  +        long position = n.page.getPageNum();
  +        addValue(v, position);
  +        return new BTreeRootInfo(v, position);
  +    }
  +
  +    /**
  +     * createBTreeRoot creates a new BTree root node in the BTree file
  +     * based on the provided root information, and value for the tree.
  +     *
  +     * @param root The BTreeRootInfo to build off of
  +     * @param v The sub-tree Value to create
  +     * @return The new BTreeRootInfo instance
  +     */
  +    protected final BTreeRootInfo createBTreeRoot(BTreeRootInfo root, Value v) throws IOException, BTreeException {
  +        BTreeNode n = createBTreeNode(root, BTree.LEAF, null);
  +        n.write();
  +
  +        long position = n.page.getPageNum();
  +        addValue(v, position);
  +        return new BTreeRootInfo(root, v, position);
  +    }
  +
  +    /**
  +     * findBTreeRoot searches for a BTreeRoot in the file and returns
  +     * the BTreeRootInfo for the specified value based on the main tree.
  +     *
  +     * @param v The sub-tree Value to search for
  +     * @return The new BTreeRootInfo instance
  +     */
  +    protected final BTreeRootInfo findBTreeRoot(Value v) throws IOException, BTreeException {
  +        long position = findValue(v);
  +        return new BTreeRootInfo(v, position);
  +    }
  +
  +    /**
  +     * findBTreeRoot searches for a BTreeRoot in the file and returns
  +     * the BTreeRootInfo for the specified value based on the provided
  +     * BTreeRootInfo value.
  +     *
  +     * @param root The BTreeRootInfo to search from
  +     * @param v The sub-tree Value to search for
  +     * @return The new BTreeRootInfo instance
  +     */
  +    protected final BTreeRootInfo findBTreeRoot(BTreeRootInfo root, Value v) throws IOException, BTreeException {
  +        long position = findValue(root, v);
  +        return new BTreeRootInfo(root, v, position);
  +    }
  +
  +    /**
  +     * setRootNode resets the root for the specified root object to the
  +     * provided BTreeNode's page number.
  +     *
  +     * @param root The root to reset
  +     * @param newRoot the new root node to use
  +     */
  +    protected final void setRootNode(BTreeRootInfo root, BTreeNode newRoot) throws IOException, BTreeException {
  +        BTreeRootInfo parent = root.getParent();
  +        if (parent == null) {
  +            rootNode = newRoot;
  +            long p = rootNode.page.getPageNum();
  +            rootInfo.setPage(p);
  +            fileHeader.setRootPage(p);
  +        }
  +        else {
  +            long p = newRoot.page.getPageNum();
  +            root.setPage(p);
  +            addValue(parent, root.name, p);
  +        }
  +    }
  +
  +    /**
  +     * setRootNode resets the file's root to the provided
  +     * BTreeNode's page number.
  +     *
  +     * @param rootNode the new root node to use
  +     */
  +    protected final void setRootNode(BTreeNode rootNode) throws IOException, BTreeException {
  +        setRootNode(rootInfo, rootNode);
  +    }
  +
  +    /**
  +     * getRootNode retreives the BTree node for the specified
  +     * root object.
  +     *
  +     * @param root The root object to retrieve with
  +     * @return The root node
  +     */
  +    protected final BTreeNode getRootNode(BTreeRootInfo root) {
  +        if (root.page == rootInfo.page)
  +            return rootNode;
  +        else
  +            return getBTreeNode(root, root.getPage(), null);
  +    }
  +
  +    /**
  +     * getRootNode retreives the BTree node for the file's root.
  +     *
  +     * @return The root node
  +     */
  +    protected final BTreeNode getRootNode() {
  +        return rootNode;
  +    }
  +
  +    private BTreeNode getBTreeNode(BTreeRootInfo root, long page, BTreeNode parent) {
  +        try {
  +            BTreeNode node;
  +            synchronized (this) {
  +                Long pNum = new Long(page);
  +                node = (BTreeNode) cache.get(pNum);
  +                if (node == null) {
  +                    Page p = getPage(pNum);
  +                    node = new BTreeNode(root, p, parent);
  +                }
  +                else {
  +                    node.root = root;
  +                    node.parent = parent;
  +                }
               }
  -            else {
  -               load = false;
  -               loadNode = null;
  -               loadPtr = 0;
  -            }
  -         }
  -         if ( load )
  -            return getBTreeNode(loadNode, loadPtr, this);
  -         else
  +            synchronized (node) {
  +                if (!node.isLoaded()) {
  +                    node.read();
  +                    node.setLoaded(true);
  +                }
  +            }
  +            return node;
  +        }
  +        catch (Exception e) {
               return null;
  -      }
  +        }
  +    }
   
  -      public synchronized void getChildStream(int idx, Streamable stream) throws IOException {
  -         if ( ph.getStatus() == LEAF && idx >= 0 && idx < ptrs.length ) {
  -            Value v = readValue(ptrs[idx]);
  -            DataInputStream dis = new DataInputStream(v.getInputStream());
  -            stream.read(dis);
  -         }
  -      }
  -
  -      public synchronized long removeValue(Value value) throws IOException, BTreeException {
  -         int idx = Arrays.binarySearch(values, value);
  -         switch ( ph.getStatus() ) {
  -            case BRANCH:
  -               idx = idx < 0 ? -(idx + 1) : idx + 1;
  -               return getChildNode(idx).removeValue(value);
  -
  -            case LEAF:
  -               if ( idx < 0 )
  -                  throw new BTreeNotFoundException("Value '" + value.toString() + "' doesn't exist");
  -               else {
  -                  long oldPtr = ptrs[idx];
  -
  -                  setValues(deleteArrayValue(values, idx));
  -                  setPointers(deleteArrayLong(ptrs, idx));
  -
  -                  write();
  -                  return oldPtr;
  -               }
  -
  -            default:
  -               throw new BTreeCorruptException("Invalid Page Type In removeValue");
  -         }
  -      }
  -
  -      public synchronized long addValue(Value value, long pointer) throws IOException, BTreeException {
  -         if (value == null) {
  -            throw new BTreeException(FaultCodes.DBE_CANNOT_CREATE, "Can't add a null Value");
  -         }
  -         
  -         int idx = Arrays.binarySearch(values, value);
  -
  -         switch ( ph.getStatus() ) {
  -            case BRANCH:
  -               idx = idx < 0 ? -(idx + 1) : idx + 1;
  -               return getChildNode(idx).addValue(value, pointer);
  -
  -            case LEAF:
  -               if ( idx >= 0 ) {
  -                  // Value was found... Overwrite
  -                  long oldPtr = ptrs[idx];
  -                  ptrs[idx] = pointer;
  -
  -                  setValues(values);
  -                  setPointers(ptrs);
  -
  -                  write();
  -                  return oldPtr;
  -               }
  -               else {
  -                  // Value was not found
  -                  idx = -(idx + 1);
  -
  -                  // Check to see if we've exhausted the block
  -                  boolean split = ph.getDataLen() + 6 + value.getLength() > fileHeader.getWorkSize();
  -
  -                  setValues(insertArrayValue(values, value, idx));
  -                  setPointers(insertArrayLong(ptrs, pointer, idx));
  -
  -                  if ( split )
  -                     split();
  -                  else
  -                     write();
  -               }
  -               return -1;
  -
  -            default:
  -               throw new BTreeCorruptException("Invalid Page Type In addValue");
  -         }
  -      }
  -
  -      public synchronized void promoteValue(Value value, long rightPointer) throws IOException, BTreeException {
  -         // Check to see if we've exhausted the block
  -         boolean split = ph.getDataLen() + 6 + value.getLength() > fileHeader.getWorkSize();
  -
  -         int idx = Arrays.binarySearch(values, value);
  -         idx = idx < 0 ? -(idx + 1) : idx + 1;
  -
  -         setValues(insertArrayValue(values, value, idx));
  -         setPointers(insertArrayLong(ptrs, rightPointer, idx + 1));
  -
  -         if ( split )
  -            split();
  -         else
  -            write();
  -      }
  -
  -      public Value getSeparator(Value value1, Value value2) {
  -         int idx = value1.compareTo(value2);
  -         byte[] b = new byte[Math.abs(idx)];
  -         System.arraycopy(value2.getData(), 0, b, 0, b.length);
  -         return new Value(b);
  -      }
  -
  -      public synchronized void split() throws IOException, BTreeException {
  -         Value[] leftVals;
  -         Value[] rightVals;
  -         long[] leftPtrs;
  -         long[] rightPtrs;
  -         Value separator;
  -
  -         short vc = ph.getValueCount();
  -         int pivot = vc / 2;
  -
  -         // Split the node into two nodes
  -         switch ( ph.getStatus() ) {
  -            case BRANCH:
  -               leftVals = new Value[pivot];
  -               leftPtrs = new long[leftVals.length + 1];
  -               rightVals = new Value[vc - (pivot + 1)];
  -               rightPtrs = new long[rightVals.length + 1];
  -
  -               System.arraycopy(values, 0, leftVals, 0, leftVals.length);
  -               System.arraycopy(ptrs, 0, leftPtrs, 0, leftPtrs.length);
  -               System.arraycopy(values, leftVals.length + 1, rightVals, 0, rightVals.length);
  -               System.arraycopy(ptrs, leftPtrs.length, rightPtrs, 0, rightPtrs.length);
  -
  -               separator = values[leftVals.length];
  -               break;
  -
  -            case LEAF:
  -               leftVals = new Value[pivot];
  -               leftPtrs = new long[leftVals.length];
  -               rightVals = new Value[vc - pivot];
  -               rightPtrs = new long[rightVals.length];
  -
  -               System.arraycopy(values, 0, leftVals, 0, leftVals.length);
  -               System.arraycopy(ptrs, 0, leftPtrs, 0, leftPtrs.length);
  -               System.arraycopy(values, leftVals.length, rightVals, 0, rightVals.length);
  -               System.arraycopy(ptrs, leftPtrs.length, rightPtrs, 0, rightPtrs.length);
  -
  -               separator = getSeparator(leftVals[leftVals.length - 1], rightVals[0]);
  -               break;
  -
  -            default:
  -               throw new BTreeCorruptException("Invalid Page Type In split");
  -         }
  -
  -         setValues(leftVals);
  -         setPointers(leftPtrs);
  -
  -         // Promote the pivot to the parent branch
  -         if ( parent == null ) {
  -            // This can only happen if this is the root
  -            BTreeNode np = createBTreeNode(root, BRANCH, null);
  -
  -            BTreeNode rNode = createBTreeNode(root, ph.getStatus(), np);
  -            rNode.setValues(rightVals);
  -            rNode.setPointers(rightPtrs);
  -
  -            np.setValues(new Value[]{separator});
  -            np.setPointers(new long[]{page.getPageNum(), rNode.page.getPageNum()});
  -
  -            parent = np;
  -
  -            setRootNode(root, np);
  -
  -            write();
  -            rNode.write();
  -            np.write();
  -         }
  -         else {
  -            BTreeNode rNode = createBTreeNode(root, ph.getStatus(), parent);
  -            rNode.setValues(rightVals);
  -            rNode.setPointers(rightPtrs);
  -
  -            write();
  -            rNode.write();
  -            parent.promoteValue(separator, rNode.page.getPageNum());
  -         }
  -      }
  -
  -      /////////////////////////////////////////////////////////////////
  -
  -      public synchronized long findValue(Value value) throws IOException, BTreeException {
  -         if (value == null) {
  -            throw new BTreeNotFoundException("Can't search on null Value");
  -         }
  -         
  -         int idx = Arrays.binarySearch(values, value);
  -         
  -         switch ( ph.getStatus() ) {
  -            case BRANCH:
  -               idx = idx < 0 ? -(idx + 1) : idx + 1;
  -               return getChildNode(idx).findValue(value);
  -
  -            case LEAF:
  -               if ( idx < 0 )
  -                  throw new BTreeNotFoundException("Value '" + value.toString() + "' doesn't exist");
  -               else
  -                  return ptrs[idx];
  -
  -            default:
  -               throw new BTreeCorruptException("Invalid Page Type In findValue");
  -         }
  -      }
  -
  -      // query is a BEAST of a method
  -      public synchronized void query(IndexQuery query, BTreeCallback callback) throws IOException, BTreeException {
  -         if ( query != null && query.getOperator() != IndexQuery.ANY ) {
  -            Value[] qvals = query.getValues();
  -            int leftIdx = Arrays.binarySearch(values, qvals[0]);
  -            int rightIdx = qvals.length > 1 ? Arrays.binarySearch(values, qvals[qvals.length - 1])
  -               : leftIdx;
  -
  -            switch ( ph.getStatus() ) {
  -               case BRANCH:
  -                  leftIdx = leftIdx < 0 ? -(leftIdx + 1) : leftIdx + 1;
  -                  rightIdx = rightIdx < 0 ? -(rightIdx + 1) : rightIdx + 1;
  -
  -                  switch ( query.getOperator() ) {
  -                     case IndexQuery.BWX:
  -                     case IndexQuery.BW:
  -                     case IndexQuery.IN:
  -                     case IndexQuery.SW:
  -                        for ( int i = 0; i < ptrs.length; i++ )
  -                           if ( i >= leftIdx && i <= rightIdx )
  -                              getChildNode(i).query(query, callback);
  -                        break;
  +    private BTreeNode createBTreeNode(BTreeRootInfo root, byte status, BTreeNode parent) {
  +        try {
  +            Page p = getFreePage();
  +            BTreeNode node = new BTreeNode(root, p, parent);
  +            node.ph.setStatus(status);
  +            node.setValues(new Value[0]);
  +            node.setPointers(new long[0]);
  +            return node;
  +        }
  +        catch (Exception e) {
  +            return null;
  +        }
  +    }
   
  -                     case IndexQuery.NBWX:
  -                     case IndexQuery.NBW:
  -                     case IndexQuery.NIN:
  -                     case IndexQuery.NSW:
  -                        for ( int i = 0; i < ptrs.length; i++ )
  -                           if ( i <= leftIdx || i >= rightIdx )
  -                              getChildNode(i).query(query, callback);
  -                        break;
  +    /**
  +     * BTreeRootInfo
  +     */
  +
  +    public final class BTreeRootInfo {
  +        private BTreeRootInfo parent;
  +        private Value name;
  +        private long page;
  +
  +        public BTreeRootInfo(BTreeRootInfo parent, String name, long page) {
  +            this.parent = parent;
  +            this.name = new Value(name);
  +            this.page = page;
  +        }
  +
  +        public BTreeRootInfo(BTreeRootInfo parent, Value name, long page) {
  +            this.parent = parent;
  +            this.name = name;
  +            this.page = page;
  +        }
  +
  +        public BTreeRootInfo(String name, long page) {
  +            this.parent = rootInfo;
  +            this.name = new Value(name);
  +            this.page = page;
  +        }
  +
  +        public BTreeRootInfo(Value name, long page) {
  +            this.parent = rootInfo;
  +            this.name = name;
  +            this.page = page;
  +        }
  +
  +        private BTreeRootInfo(long page) {
  +            parent = null;
  +            name = null;
  +            this.page = page;
  +        }
  +
  +        public synchronized BTreeRootInfo getParent() {
  +            return parent;
  +        }
  +
  +        public synchronized Value getName() {
  +            return name;
  +        }
  +
  +        public synchronized long getPage() {
  +            return page;
  +        }
  +
  +        public synchronized void setPage(long page) {
  +            this.page = page;
  +        }
  +    }
  +
  +    /**
  +     * BTreeNode
  +     */
  +
  +    private final class BTreeNode {
  +        private BTreeRootInfo root;
  +        private Page page;
  +        private BTreePageHeader ph;
  +        private Value[] values;
  +        private long[] ptrs;
  +        private BTreeNode parent;
  +        private boolean loaded;
  +
  +        public BTreeNode(BTreeRootInfo root, Page page, BTreeNode parent) {
  +            this.root = root;
  +            this.page = page;
  +            this.parent = parent;
  +            ph = (BTreePageHeader) page.getPageHeader();
  +        }
  +
  +        public BTreeNode(BTreeRootInfo root, Page page) {
  +            this.root = root;
  +            this.page = page;
  +            ph = (BTreePageHeader) page.getPageHeader();
  +        }
  +
  +        public synchronized void setValues(Value[] values) {
  +            this.values = values;
  +            ph.setValueCount((short) values.length);
  +        }
  +
  +        public synchronized Value[] getValues() {
  +            return values;
  +        }
  +
  +        public synchronized void setPointers(long[] ptrs) {
  +            this.ptrs = ptrs;
  +        }
  +
  +        public synchronized long[] getPointers() {
  +            return ptrs;
  +        }
  +
  +        public synchronized boolean isLoaded() {
  +            return loaded;
  +        }
  +
  +        public synchronized void setLoaded(boolean loaded) {
  +            this.loaded = loaded;
  +        }
  +
  +        public synchronized void read() throws IOException {
  +            Value v = readValue(page);
  +            DataInputStream is = new DataInputStream(v.getInputStream());
  +
  +            // Read in the Values
  +            values = new Value[ph.getValueCount()];
  +            for (int i = 0; i < values.length; i++) {
  +                short valSize = is.readShort();
  +                byte[] b = new byte[valSize];
   
  -                     case IndexQuery.EQ:
  -                        getChildNode(leftIdx).query(query, callback);
  -                        break;
  +                is.read(b);
  +                values[i] = new Value(b);
  +            }
   
  -                     case IndexQuery.LT:
  -                     case IndexQuery.LEQ:
  -                        for ( int i = 0; i < ptrs.length; i++ )
  -                           if ( i <= leftIdx )
  -                              getChildNode(i).query(query, callback);
  -                        break;
  +            // Read in the pointers
  +            ptrs = new long[ph.getPointerCount()];
  +            for (int i = 0; i < ptrs.length; i++)
  +                ptrs[i] = is.readLong();
  +
  +            cache.put(new Long(page.getPageNum()), this);
  +        }
  +
  +        public synchronized void write() throws IOException {
  +            ByteArrayOutputStream bos = new ByteArrayOutputStream((int) fileHeader.getWorkSize());
  +            DataOutputStream os = new DataOutputStream(bos);
  +
  +            // Write out the Values
  +            for (int i = 0; i < values.length; i++) {
  +                os.writeShort(values[i].getLength());
  +                values[i].streamTo(os);
  +            }
   
  -                     case IndexQuery.GT:
  -                     case IndexQuery.GEQ:
  -                        for ( int i = 0; i < ptrs.length; i++ )
  -                           if ( i >= rightIdx )
  -                              getChildNode(i).query(query, callback);
  -                        break;
  +            // Write out the pointers
  +            for (int i = 0; i < ptrs.length; i++)
  +                os.writeLong(ptrs[i]);
  +
  +            writeValue(page, new Value(bos.toByteArray()));
  +
  +            cache.put(new Long(page.getPageNum()), this);
  +        }
  +
  +        public BTreeNode getChildNode(int idx) throws IOException {
  +            boolean load;
  +            BTreeRootInfo loadNode;
  +            long loadPtr;
  +            synchronized (this) {
  +                if (ph.getStatus() == BRANCH && idx >= 0 && idx < ptrs.length) {
  +                    load = true;
  +                    loadNode = root;
  +                    loadPtr = ptrs[idx];
  +                }
  +                else {
  +                    load = false;
  +                    loadNode = null;
  +                    loadPtr = 0;
  +                }
  +            }
  +            if (load)
  +                return getBTreeNode(loadNode, loadPtr, this);
  +            else
  +                return null;
  +        }
  +
  +        public synchronized void getChildStream(int idx, Streamable stream) throws IOException {
  +            if (ph.getStatus() == LEAF && idx >= 0 && idx < ptrs.length) {
  +                Value v = readValue(ptrs[idx]);
  +                DataInputStream dis = new DataInputStream(v.getInputStream());
  +                stream.read(dis);
  +            }
  +        }
   
  -                     case IndexQuery.NEQ:
  -                     default:
  -                        for ( int i = 0; i < ptrs.length; i++ )
  -                           getChildNode(i).query(query, callback);
  -                        break;
  -                  }
  -                  break;
  +        public synchronized long removeValue(Value value) throws IOException, BTreeException {
  +            int idx = Arrays.binarySearch(values, value);
  +            switch (ph.getStatus()) {
  +                case BRANCH :
  +                    idx = idx < 0 ? - (idx + 1) : idx + 1;
  +                    return getChildNode(idx).removeValue(value);
  +
  +                case LEAF :
  +                    if (idx < 0)
  +                        throw new BTreeNotFoundException("Value '" + value.toString() + "' doesn't exist");
  +                    else {
  +                        long oldPtr = ptrs[idx];
  +
  +                        setValues(deleteArrayValue(values, idx));
  +                        setPointers(deleteArrayLong(ptrs, idx));
  +
  +                        write();
  +                        return oldPtr;
  +                    }
   
  -               case LEAF:
  -                  switch ( query.getOperator() ) {
  -                     case IndexQuery.EQ:
  -                        if ( leftIdx >= 0 )
  -                           callback.indexInfo(values[leftIdx], ptrs[leftIdx]);
  -                        break;
  +                default :
  +                    throw new BTreeCorruptException("Invalid Page Type In removeValue");
  +            }
  +        }
   
  -                     case IndexQuery.NEQ:
  -                        for ( int i = 0; i < ptrs.length; i++ )
  -                           if ( i != leftIdx )
  -                              callback.indexInfo(values[i], ptrs[i]);
  -                        break;
  +        public synchronized long addValue(Value value, long pointer) throws IOException, BTreeException {
  +            if (value == null) {
  +                throw new BTreeException(FaultCodes.DBE_CANNOT_CREATE, "Can't add a null Value");
  +            }
   
  -                     case IndexQuery.BWX:
  -                     case IndexQuery.BW:
  -                     case IndexQuery.SW:
  -                     case IndexQuery.IN:
  -                        if ( leftIdx < 0 )
  -                           leftIdx = -(leftIdx + 1);
  -                        if ( rightIdx < 0 )
  -                           rightIdx = -(rightIdx + 1);
  -                        for ( int i = 0; i < ptrs.length; i++ )
  -                           if ( i >= leftIdx && i <= rightIdx && query.testValue(values[i]) )
  -                              callback.indexInfo(values[i], ptrs[i]);
  -                        break;
  +            int idx = Arrays.binarySearch(values, value);
   
  -                     case IndexQuery.NBWX:
  -                     case IndexQuery.NBW:
  -                     case IndexQuery.NSW:
  -                        if ( leftIdx < 0 )
  -                           leftIdx = -(leftIdx + 1);
  -                        if ( rightIdx < 0 )
  -                           rightIdx = -(rightIdx + 1);
  -                        for ( int i = 0; i < ptrs.length; i++ )
  -                           if ( (i <= leftIdx || i >= rightIdx) && query.testValue(values[i]) )
  -                              callback.indexInfo(values[i], ptrs[i]);
  -                        break;
  +            switch (ph.getStatus()) {
  +                case BRANCH :
  +                    idx = idx < 0 ? - (idx + 1) : idx + 1;
  +                    return getChildNode(idx).addValue(value, pointer);
  +
  +                case LEAF :
  +                    if (idx >= 0) {
  +                        // Value was found... Overwrite
  +                        long oldPtr = ptrs[idx];
  +                        ptrs[idx] = pointer;
  +
  +                        setValues(values);
  +                        setPointers(ptrs);
  +
  +                        write();
  +                        return oldPtr;
  +                    }
  +                    else {
  +                        // Value was not found
  +                        idx = - (idx + 1);
  +
  +                        // Check to see if we've exhausted the block
  +                        boolean split = ph.getDataLen() + 6 + value.getLength() > fileHeader.getWorkSize();
  +
  +                        setValues(insertArrayValue(values, value, idx));
  +                        setPointers(insertArrayLong(ptrs, pointer, idx));
  +
  +                        if (split)
  +                            split();
  +                        else
  +                            write();
  +                    }
  +                    return -1;
   
  -                     case IndexQuery.LT:
  -                     case IndexQuery.LEQ:
  -                        if ( leftIdx < 0 )
  -                           leftIdx = -(leftIdx + 1);
  -                        for ( int i = 0; i < ptrs.length; i++ )
  -                           if ( i <= leftIdx && query.testValue(values[i]) )
  -                              callback.indexInfo(values[i], ptrs[i]);
  -                        break;
  +                default :
  +                    throw new BTreeCorruptException("Invalid Page Type In addValue");
  +            }
  +        }
  +
  +        public synchronized void promoteValue(Value value, long rightPointer) throws IOException, BTreeException {
  +            // Check to see if we've exhausted the block
  +            boolean split = ph.getDataLen() + 6 + value.getLength() > fileHeader.getWorkSize();
  +
  +            int idx = Arrays.binarySearch(values, value);
  +            idx = idx < 0 ? - (idx + 1) : idx + 1;
  +
  +            setValues(insertArrayValue(values, value, idx));
  +            setPointers(insertArrayLong(ptrs, rightPointer, idx + 1));
  +
  +            if (split)
  +                split();
  +            else
  +                write();
  +        }
  +
  +        public Value getSeparator(Value value1, Value value2) {
  +            int idx = value1.compareTo(value2);
  +            byte[] b = new byte[Math.abs(idx)];
  +            System.arraycopy(value2.getData(), 0, b, 0, b.length);
  +            return new Value(b);
  +        }
  +
  +        public synchronized void split() throws IOException, BTreeException {
  +            Value[] leftVals;
  +            Value[] rightVals;
  +            long[] leftPtrs;
  +            long[] rightPtrs;
  +            Value separator;
  +
  +            short vc = ph.getValueCount();
  +            int pivot = vc / 2;
  +
  +            // Split the node into two nodes
  +            switch (ph.getStatus()) {
  +                case BRANCH :
  +                    leftVals = new Value[pivot];
  +                    leftPtrs = new long[leftVals.length + 1];
  +                    rightVals = new Value[vc - (pivot + 1)];
  +                    rightPtrs = new long[rightVals.length + 1];
  +
  +                    System.arraycopy(values, 0, leftVals, 0, leftVals.length);
  +                    System.arraycopy(ptrs, 0, leftPtrs, 0, leftPtrs.length);
  +                    System.arraycopy(values, leftVals.length + 1, rightVals, 0, rightVals.length);
  +                    System.arraycopy(ptrs, leftPtrs.length, rightPtrs, 0, rightPtrs.length);
  +
  +                    separator = values[leftVals.length];
  +                    break;
  +
  +                case LEAF :
  +                    leftVals = new Value[pivot];
  +                    leftPtrs = new long[leftVals.length];
  +                    rightVals = new Value[vc - pivot];
  +                    rightPtrs = new long[rightVals.length];
  +
  +                    System.arraycopy(values, 0, leftVals, 0, leftVals.length);
  +                    System.arraycopy(ptrs, 0, leftPtrs, 0, leftPtrs.length);
  +                    System.arraycopy(values, leftVals.length, rightVals, 0, rightVals.length);
  +                    System.arraycopy(ptrs, leftPtrs.length, rightPtrs, 0, rightPtrs.length);
  +
  +                    separator = getSeparator(leftVals[leftVals.length - 1], rightVals[0]);
  +                    break;
  +
  +                default :
  +                    throw new BTreeCorruptException("Invalid Page Type In split");
  +            }
  +
  +            setValues(leftVals);
  +            setPointers(leftPtrs);
  +
  +            // Promote the pivot to the parent branch
  +            if (parent == null) {
  +                // This can only happen if this is the root
  +                BTreeNode np = createBTreeNode(root, BRANCH, null);
  +
  +                BTreeNode rNode = createBTreeNode(root, ph.getStatus(), np);
  +                rNode.setValues(rightVals);
  +                rNode.setPointers(rightPtrs);
  +
  +                np.setValues(new Value[] { separator });
  +                np.setPointers(new long[] { page.getPageNum(), rNode.page.getPageNum()});
  +
  +                parent = np;
  +
  +                setRootNode(root, np);
  +
  +                write();
  +                rNode.write();
  +                np.write();
  +            }
  +            else {
  +                BTreeNode rNode = createBTreeNode(root, ph.getStatus(), parent);
  +                rNode.setValues(rightVals);
  +                rNode.setPointers(rightPtrs);
  +
  +                write();
  +                rNode.write();
  +                parent.promoteValue(separator, rNode.page.getPageNum());
  +            }
  +        }
   
  -                     case IndexQuery.GT:
  -                     case IndexQuery.GEQ:
  -                        if ( rightIdx < 0 )
  -                           rightIdx = -(rightIdx + 1);
  -                        for ( int i = 0; i < ptrs.length; i++ )
  -                           if ( i >= rightIdx && query.testValue(values[i]) )
  -                              callback.indexInfo(values[i], ptrs[i]);
  +        /////////////////////////////////////////////////////////////////
  +
  +        public synchronized long findValue(Value value) throws IOException, BTreeException {
  +            if (value == null) {
  +                throw new BTreeNotFoundException("Can't search on null Value");
  +            }
  +
  +            int idx = Arrays.binarySearch(values, value);
  +
  +            switch (ph.getStatus()) {
  +                case BRANCH :
  +                    idx = idx < 0 ? - (idx + 1) : idx + 1;
  +                    return getChildNode(idx).findValue(value);
  +
  +                case LEAF :
  +                    if (idx < 0)
  +                        throw new BTreeNotFoundException("Value '" + value.toString() + "' doesn't exist");
  +                    else
  +                        return ptrs[idx];
  +
  +                default :
  +                    throw new BTreeCorruptException("Invalid Page Type In findValue");
  +            }
  +        }
  +
  +        // query is a BEAST of a method
  +        public synchronized void query(IndexQuery query, BTreeCallback callback) throws IOException, BTreeException {
  +            if (query != null && query.getOperator() != IndexQuery.ANY) {
  +                Value[] qvals = query.getValues();
  +                int leftIdx = Arrays.binarySearch(values, qvals[0]);
  +                int rightIdx = qvals.length > 1 ? Arrays.binarySearch(values, qvals[qvals.length - 1]) : leftIdx;
  +
  +                switch (ph.getStatus()) {
  +                    case BRANCH :
  +                        leftIdx = leftIdx < 0 ? - (leftIdx + 1) : leftIdx + 1;
  +                        rightIdx = rightIdx < 0 ? - (rightIdx + 1) : rightIdx + 1;
  +
  +                        switch (query.getOperator()) {
  +                            case IndexQuery.BWX :
  +                            case IndexQuery.BW :
  +                            case IndexQuery.IN :
  +                            case IndexQuery.SW :
  +                                for (int i = 0; i < ptrs.length; i++)
  +                                    if (i >= leftIdx && i <= rightIdx)
  +                                        getChildNode(i).query(query, callback);
  +                                break;
  +
  +                            case IndexQuery.NBWX :
  +                            case IndexQuery.NBW :
  +                            case IndexQuery.NIN :
  +                            case IndexQuery.NSW :
  +                                for (int i = 0; i < ptrs.length; i++)
  +                                    if (i <= leftIdx || i >= rightIdx)
  +                                        getChildNode(i).query(query, callback);
  +                                break;
  +
  +                            case IndexQuery.EQ :
  +                                getChildNode(leftIdx).query(query, callback);
  +                                break;
  +
  +                            case IndexQuery.LT :
  +                            case IndexQuery.LEQ :
  +                                for (int i = 0; i < ptrs.length; i++)
  +                                    if (i <= leftIdx)
  +                                        getChildNode(i).query(query, callback);
  +                                break;
  +
  +                            case IndexQuery.GT :
  +                            case IndexQuery.GEQ :
  +                                for (int i = 0; i < ptrs.length; i++)
  +                                    if (i >= rightIdx)
  +                                        getChildNode(i).query(query, callback);
  +                                break;
  +
  +                            case IndexQuery.NEQ :
  +                            default :
  +                                for (int i = 0; i < ptrs.length; i++)
  +                                    getChildNode(i).query(query, callback);
  +                                break;
  +                        }
  +                        break;
  +
  +                    case LEAF :
  +                        switch (query.getOperator()) {
  +                            case IndexQuery.EQ :
  +                                if (leftIdx >= 0)
  +                                    callback.indexInfo(values[leftIdx], ptrs[leftIdx]);
  +                                break;
  +
  +                            case IndexQuery.NEQ :
  +                                for (int i = 0; i < ptrs.length; i++)
  +                                    if (i != leftIdx)
  +                                        callback.indexInfo(values[i], ptrs[i]);
  +                                break;
  +
  +                            case IndexQuery.BWX :
  +                            case IndexQuery.BW :
  +                            case IndexQuery.SW :
  +                            case IndexQuery.IN :
  +                                if (leftIdx < 0)
  +                                    leftIdx = - (leftIdx + 1);
  +                                if (rightIdx < 0)
  +                                    rightIdx = - (rightIdx + 1);
  +                                for (int i = 0; i < ptrs.length; i++)
  +                                    if (i >= leftIdx && i <= rightIdx && query.testValue(values[i]))
  +                                        callback.indexInfo(values[i], ptrs[i]);
  +                                break;
  +
  +                            case IndexQuery.NBWX :
  +                            case IndexQuery.NBW :
  +                            case IndexQuery.NSW :
  +                                if (leftIdx < 0)
  +                                    leftIdx = - (leftIdx + 1);
  +                                if (rightIdx < 0)
  +                                    rightIdx = - (rightIdx + 1);
  +                                for (int i = 0; i < ptrs.length; i++)
  +                                    if ((i <= leftIdx || i >= rightIdx) && query.testValue(values[i]))
  +                                        callback.indexInfo(values[i], ptrs[i]);
  +                                break;
  +
  +                            case IndexQuery.LT :
  +                            case IndexQuery.LEQ :
  +                                if (leftIdx < 0)
  +                                    leftIdx = - (leftIdx + 1);
  +                                for (int i = 0; i < ptrs.length; i++)
  +                                    if (i <= leftIdx && query.testValue(values[i]))
  +                                        callback.indexInfo(values[i], ptrs[i]);
  +                                break;
  +
  +                            case IndexQuery.GT :
  +                            case IndexQuery.GEQ :
  +                                if (rightIdx < 0)
  +                                    rightIdx = - (rightIdx + 1);
  +                                for (int i = 0; i < ptrs.length; i++)
  +                                    if (i >= rightIdx && query.testValue(values[i]))
  +                                        callback.indexInfo(values[i], ptrs[i]);
  +                                break;
  +
  +                            case IndexQuery.NIN :
  +                            default :
  +                                for (int i = 0; i < ptrs.length; i++)
  +                                    if (query.testValue(values[i]))
  +                                        callback.indexInfo(values[i], ptrs[i]);
  +                                break;
  +                        }
  +                        break;
  +
  +                    default :
  +                        throw new BTreeCorruptException("Invalid Page Type In query");
  +                }
  +
  +            }
  +            else {
  +                // No Query - Just Walk The Tree
  +                switch (ph.getStatus()) {
  +                    case BRANCH :
  +                        for (int i = 0; i < ptrs.length; i++)
  +                            getChildNode(i).query(query, callback);
                           break;
   
  -                     case IndexQuery.NIN:
  -                     default:
  -                        for ( int i = 0; i < ptrs.length; i++ )
  -                           if ( query.testValue(values[i]) )
  -                              callback.indexInfo(values[i], ptrs[i]);
  +                    case LEAF :
  +                        for (int i = 0; i < values.length; i++)
  +                            callback.indexInfo(values[i], ptrs[i]);
                           break;
  -                  }
  -                  break;
   
  -               default:
  -                  throw new BTreeCorruptException("Invalid Page Type In query");
  +                    default :
  +                        throw new BTreeCorruptException("Invalid Page Type In query");
  +                }
               }
  +        }
  +    }
  +
  +    ////////////////////////////////////////////////////////////////////
  +
  +    public FileHeader createFileHeader() {
  +        return new BTreeFileHeader();
  +    }
  +
  +    public FileHeader createFileHeader(boolean read) throws IOException {
  +        return new BTreeFileHeader(read);
  +    }
  +
  +    public FileHeader createFileHeader(long pageCount) {
  +        return new BTreeFileHeader(pageCount);
  +    }
  +
  +    public FileHeader createFileHeader(long pageCount, int pageSize) {
  +        return new BTreeFileHeader(pageCount, pageSize);
  +    }
  +
  +    public PageHeader createPageHeader() {
  +        return new BTreePageHeader();
  +    }
  +
  +    /**
  +     * BTreeFileHeader
  +     */
  +
  +    protected class BTreeFileHeader extends FileHeader {
  +        private long rootPage = 0;
   
  -         }
  -         else {
  -            // No Query - Just Walk The Tree
  -            switch ( ph.getStatus() ) {
  -               case BRANCH:
  -                  for ( int i = 0; i < ptrs.length; i++ )
  -                     getChildNode(i).query(query, callback);
  -                  break;
  -
  -               case LEAF:
  -                  for ( int i = 0; i < values.length; i++ )
  -                     callback.indexInfo(values[i], ptrs[i]);
  -                  break;
  -
  -               default:
  -                  throw new BTreeCorruptException("Invalid Page Type In query");
  -            }
  -         }
  -      }
  -   }
  -
  -   ////////////////////////////////////////////////////////////////////
  -
  -   public FileHeader createFileHeader() {
  -      return new BTreeFileHeader();
  -   }
  -
  -   public FileHeader createFileHeader(boolean read) throws IOException {
  -      return new BTreeFileHeader(read);
  -   }
  -
  -   public FileHeader createFileHeader(long pageCount) {
  -      return new BTreeFileHeader(pageCount);
  -   }
  -
  -   public FileHeader createFileHeader(long pageCount, int pageSize) {
  -      return new BTreeFileHeader(pageCount, pageSize);
  -   }
  -
  -   public PageHeader createPageHeader() {
  -      return new BTreePageHeader();
  -   }
  -
  -
  -   /**
  -    * BTreeFileHeader
  -    */
  -
  -   protected class BTreeFileHeader extends FileHeader {
  -      private long rootPage = 0;
  -
  -      public BTreeFileHeader() {
  -      }
  -
  -      public BTreeFileHeader(long pageCount) {
  -         super(pageCount);
  -      }
  -
  -      public BTreeFileHeader(long pageCount, int pageSize) {
  -         super(pageCount, pageSize);
  -      }
  -
  -      public BTreeFileHeader(boolean read) throws IOException {
  -         super(read);
  -      }
  -
  -      public synchronized void read(RandomAccessFile raf) throws IOException {
  -         super.read(raf);
  -         rootPage = raf.readLong();
  -      }
  -
  -      public synchronized void write(RandomAccessFile raf) throws IOException {
  -         super.write(raf);
  -         raf.writeLong(rootPage);
  -      }
  -
  -      /** The root page of the storage tree */
  -      public synchronized final void setRootPage(long rootPage) {
  -         this.rootPage = rootPage;
  -         setDirty();
  -      }
  -
  -      /** The root page of the storage tree */
  -      public synchronized final long getRootPage() {
  -         return rootPage;
  -      }
  -   }
  -
  -
  -   /**
  -    * BTreePageHeader
  -    */
  -
  -   protected class BTreePageHeader extends PageHeader {
  -      private short valueCount = 0;
  -
  -      public BTreePageHeader() {
  -      }
  -
  -      public BTreePageHeader(DataInputStream dis) throws IOException {
  -         super(dis);
  -      }
  -
  -      public synchronized void read(DataInputStream dis) throws IOException {
  -         super.read(dis);
  -
  -         if ( getStatus() == UNUSED )
  -            return;
  -
  -         valueCount = dis.readShort();
  -      }
  -
  -      public synchronized void write(DataOutputStream dos) throws IOException {
  -         super.write(dos);
  -         dos.writeShort(valueCount);
  -      }
  -
  -      /** The number of values stored by this page */
  -      public synchronized final void setValueCount(short valueCount) {
  -         this.valueCount = valueCount;
  -         setDirty();
  -      }
  -
  -      /** The number of values stored by this page */
  -      public synchronized final short getValueCount() {
  -         return valueCount;
  -      }
  -
  -      /** The number of pointers stored by this page */
  -      public synchronized final short getPointerCount() {
  -         if ( getStatus() == BRANCH )
  -            return (short)(valueCount + 1);
  -         else
  +        public BTreeFileHeader() {}
  +
  +        public BTreeFileHeader(long pageCount) {
  +            super(pageCount);
  +        }
  +
  +        public BTreeFileHeader(long pageCount, int pageSize) {
  +            super(pageCount, pageSize);
  +        }
  +
  +        public BTreeFileHeader(boolean read) throws IOException {
  +            super(read);
  +        }
  +
  +        public synchronized void read(RandomAccessFile raf) throws IOException {
  +            super.read(raf);
  +            rootPage = raf.readLong();
  +        }
  +
  +        public synchronized void write(RandomAccessFile raf) throws IOException {
  +            super.write(raf);
  +            raf.writeLong(rootPage);
  +        }
  +
  +        /** The root page of the storage tree */
  +        public synchronized final void setRootPage(long rootPage) {
  +            this.rootPage = rootPage;
  +            setDirty();
  +        }
  +
  +        /** The root page of the storage tree */
  +        public synchronized final long getRootPage() {
  +            return rootPage;
  +        }
  +    }
  +
  +    /**
  +     * BTreePageHeader
  +     */
  +
  +    protected class BTreePageHeader extends PageHeader {
  +        private short valueCount = 0;
  +
  +        public BTreePageHeader() {}
  +
  +        public BTreePageHeader(DataInputStream dis) throws IOException {
  +            super(dis);
  +        }
  +
  +        public synchronized void read(DataInputStream dis) throws IOException {
  +            super.read(dis);
  +
  +            if (getStatus() == UNUSED)
  +                return;
  +
  +            valueCount = dis.readShort();
  +        }
  +
  +        public synchronized void write(DataOutputStream dos) throws IOException {
  +            super.write(dos);
  +            dos.writeShort(valueCount);
  +        }
  +
  +        /** The number of values stored by this page */
  +        public synchronized final void setValueCount(short valueCount) {
  +            this.valueCount = valueCount;
  +            setDirty();
  +        }
  +
  +        /** The number of values stored by this page */
  +        public synchronized final short getValueCount() {
               return valueCount;
  -      }
  -   }
  +        }
  +
  +        /** The number of pointers stored by this page */
  +        public synchronized final short getPointerCount() {
  +            if (getStatus() == BRANCH)
  +                return (short) (valueCount + 1);
  +            else
  +                return valueCount;
  +        }
  +    }
   }
  
  
  
  1.11      +431 -450  xml-xindice/java/src/org/apache/xindice/core/filer/HashFiler.java
  
  Index: HashFiler.java
  ===================================================================
  RCS file: /home/cvs/xml-xindice/java/src/org/apache/xindice/core/filer/HashFiler.java,v
  retrieving revision 1.10
  retrieving revision 1.11
  diff -u -r1.10 -r1.11
  --- HashFiler.java	6 Apr 2003 05:56:03 -0000	1.10
  +++ HashFiler.java	15 Jul 2003 15:44:35 -0000	1.11
  @@ -59,18 +59,6 @@
    * $Id$
    */
   
  -import org.apache.xindice.core.DBException;
  -import org.apache.xindice.core.FaultCodes;
  -import org.apache.xindice.core.data.Key;
  -import org.apache.xindice.core.data.Record;
  -import org.apache.xindice.core.data.RecordSet;
  -import org.apache.xindice.core.data.Value;
  -import org.apache.xindice.util.Configurable;
  -import org.apache.xindice.util.Configuration;
  -
  -import org.apache.commons.logging.Log;
  -import org.apache.commons.logging.LogFactory;
  -
   import java.io.DataInputStream;
   import java.io.DataOutputStream;
   import java.io.File;
  @@ -81,6 +69,17 @@
   import java.util.Iterator;
   import java.util.List;
   
  +import org.apache.commons.logging.Log;
  +import org.apache.commons.logging.LogFactory;
  +import org.apache.xindice.core.DBException;
  +import org.apache.xindice.core.FaultCodes;
  +import org.apache.xindice.core.data.Key;
  +import org.apache.xindice.core.data.Record;
  +import org.apache.xindice.core.data.RecordSet;
  +import org.apache.xindice.core.data.Value;
  +import org.apache.xindice.util.Configurable;
  +import org.apache.xindice.util.Configuration;
  +
   /**
    * HashFiler is a Filer implementation based on the Paged class.  By
    * extending Paged, HashFiler inherits the ability to maintain Record
  @@ -93,465 +92,447 @@
    **/
   
   public final class HashFiler extends Paged implements Configurable, Filer {
  -   protected static final byte RECORD = 1;
  +    protected static final byte RECORD = 1;
  +
  +    private static final String PAGECOUNT = "pagecount";
  +    private static final String PAGESIZE = "pagesize";
  +    private static final String MAXKEYSIZE = "maxkeysize";
  +
  +    private static Log log = LogFactory.getLog("org.apache.xindice.core");
  +
  +    private Configuration config;
  +    private HashFileHeader fileHeader;
  +    //private BTree btree;
  +
  +    public HashFiler() {
  +        super();
  +        fileHeader = (HashFileHeader) getFileHeader();
  +    }
  +
  +    public void setConfig(Configuration config) {
  +        this.config = config;
  +    }
  +
  +    public Configuration getConfig() {
  +        return config;
  +    }
  +
  +    public void setLocation(File root, String location) {
  +        setFile(new File(root, location + ".tbl"));
  +        // btree = new BTree(new File(root, location + ".pkx"));
  +    }
  +
  +    public String getName() {
  +        return "HashFiler";
  +    }
  +
  +    public boolean open() throws DBException {
  +        if (super.open()) {
  +            // These are the only properties that can be changed after creation
  +            fileHeader.setMaxKeySize(config.getShortAttribute(MAXKEYSIZE, fileHeader.getMaxKeySize()));
  +            // btree.open();
  +            return true;
  +        }
  +        else
  +            return false;
  +    }
  +
  +    public boolean create() throws DBException {
  +        fileHeader.setPageCount(config.getLongAttribute(PAGECOUNT, fileHeader.getPageCount()));
  +        fileHeader.setPageSize(config.getIntAttribute(PAGESIZE, fileHeader.getPageSize()));
  +        fileHeader.setMaxKeySize(config.getShortAttribute(MAXKEYSIZE, fileHeader.getMaxKeySize()));
  +        //btree.create();
  +        return super.create();
  +    }
  +
  +    private Page seekRecordPage(Key key) throws IOException {
  +        int hash = key.getHash();
  +        long pageNum = hash % fileHeader.getPageCount();
  +        Page p = null;
  +        HashPageHeader ph = null;
  +        while (true) {
  +            p = getPage(pageNum);
  +            ph = (HashPageHeader) p.getPageHeader();
  +            if (ph.getStatus() == RECORD && ph.getKeyHash() == key.getHash() && p.getKey().equals(key)) {
  +                return p;
  +            }
   
  -   private static final String PAGECOUNT = "pagecount";
  -   private static final String PAGESIZE = "pagesize";
  -   private static final String MAXKEYSIZE = "maxkeysize";
  -
  -   private static Log log = LogFactory.getLog("org.apache.xindice.core");
  -
  -   private Configuration config;
  -   private HashFileHeader fileHeader;
  -   //private BTree btree;
  -
  -   public HashFiler() {
  -      super();
  -      fileHeader = (HashFileHeader)getFileHeader();
  -   }
  -
  -   public void setConfig(Configuration config) {
  -      this.config = config;
  -   }
  -
  -   public Configuration getConfig() {
  -      return config;
  -   }
  -
  -   public void setLocation(File root, String location) {
  -      setFile(new File(root, location + ".tbl"));
  -     // btree = new BTree(new File(root, location + ".pkx"));
  -   }
  -
  -   public String getName() {
  -      return "HashFiler";
  -   }
  -
  -   public boolean open() throws DBException {
  -      if ( super.open() ) {
  -         // These are the only properties that can be changed after creation
  -         fileHeader.setMaxKeySize(config.getShortAttribute(MAXKEYSIZE, fileHeader.getMaxKeySize()));
  -        // btree.open();
  -         return true;
  -      }
  -      else
  -         return false;
  -   }
  -
  -   public boolean create() throws DBException {
  -      fileHeader.setPageCount(config.getLongAttribute(PAGECOUNT, fileHeader.getPageCount()));
  -      fileHeader.setPageSize(config.getIntAttribute(PAGESIZE, fileHeader.getPageSize()));
  -      fileHeader.setMaxKeySize(config.getShortAttribute(MAXKEYSIZE, fileHeader.getMaxKeySize()));
  -      //btree.create();
  -      return super.create();
  -   }
  -
  -   private Page seekRecordPage(Key key) throws IOException {
  -      int hash = key.getHash();
  -      long pageNum = hash % fileHeader.getPageCount();
  -      Page p = null;
  -      HashPageHeader ph = null;
  -      while ( true ) {
  -         p = getPage(pageNum);
  -         ph = (HashPageHeader)p.getPageHeader();
  -         if ( ph.getStatus() == RECORD
  -              && ph.getKeyHash() == key.getHash()
  -              && p.getKey().equals(key) ) {
  -            return p;
  -         }
  +            pageNum = ph.getNextCollision();
  +            if (pageNum == -1)
  +                return null;
  +        }
  +    }
  +
  +    private Page seekInsertionPage(Key key) throws IOException {
  +        int hash = key.getHash();
  +        long pageNum = hash % fileHeader.getPageCount();
  +
  +        log.trace("Hash page  " + pageNum);
  +
  +        Page p = null;
  +        HashPageHeader ph = null;
  +        while (true) {
  +            p = getPage(pageNum);
  +            ph = (HashPageHeader) p.getPageHeader();
  +            if ((ph.getStatus() == UNUSED || ph.getStatus() == DELETED) || (ph.getStatus() == RECORD && ph.getKeyHash() == key.getHash() && p.getKey().equals(key)))
  +                return p;
  +            pageNum = ph.getNextCollision();
  +            if (pageNum == -1) {
  +                Page np = getFreePage();
  +                ph.setNextCollision(np.getPageNum());
  +                p.write();
  +                return np;
  +            }
  +        }
  +    }
   
  -         pageNum = ph.getNextCollision();
  -         if ( pageNum == -1 )
  +    public Record readRecord(Key key) throws DBException {
  +        if (key == null || key.equals("")) {
               return null;
  -      }
  -   }
  +        }
  +        checkOpened();
  +        try {
  +            Page startPage = seekRecordPage(key);
  +            if (startPage != null) {
  +                Value v = readValue(startPage);
  +                HashPageHeader sph = (HashPageHeader) startPage.getPageHeader();
  +
  +                HashMap meta = new HashMap(2);
  +                meta.put(Record.CREATED, new Long(sph.getCreated()));
  +                meta.put(Record.MODIFIED, new Long(sph.getModified()));
   
  -   private Page seekInsertionPage(Key key) throws IOException {
  -      int hash = key.getHash();
  -      long pageNum = hash % fileHeader.getPageCount();
  -      
  -      log.trace("Hash page  " + pageNum);
  -      
  -      Page p = null;
  -      HashPageHeader ph = null;
  -      while ( true ) {
  -         p = getPage(pageNum);
  -         ph = (HashPageHeader)p.getPageHeader();
  -         if ( (ph.getStatus() == UNUSED || ph.getStatus() == DELETED)
  -            || (ph.getStatus() == RECORD
  -            && ph.getKeyHash() == key.getHash()
  -            && p.getKey().equals(key)) )
  -            return p;
  -         pageNum = ph.getNextCollision();
  -         if ( pageNum == -1 ) {
  -            Page np = getFreePage();
  -            ph.setNextCollision(np.getPageNum());
  -            p.write();
  -            return np;
  -         }
  -      }
  -   }
  -
  -   public Record readRecord(Key key) throws DBException {
  -      if ( key == null || key.equals("") ) {
  -         return null;
  -      }
  -      checkOpened();
  -      try {
  -         Page startPage = seekRecordPage(key);
  -         if ( startPage != null ) {
  -            Value v = readValue(startPage);
  -            HashPageHeader sph = (HashPageHeader)startPage.getPageHeader();
  -
  -            HashMap meta = new HashMap(2);
  -            meta.put(Record.CREATED, new Long(sph.getCreated()));
  -            meta.put(Record.MODIFIED, new Long(sph.getModified()));
  -
  -            return new Record(key, v, meta);
  -         }
  -      }
  -      catch ( Exception e ) {
  -         if (log.isDebugEnabled()) {
  -            log.debug("No message", e);
  -         }
  -      }
  -      return null;
  -   }
  -
  -   public boolean writeRecord(Key key, Value value) throws DBException {
  -      if ( key == null || key.equals("") ) {
  -         throw new FilerException(FaultCodes.DBE_CANNOT_CREATE, "Invalid key: '" + key + "'");
  -      }
  -      if (value == null ) {
  -         throw new FilerException(FaultCodes.DBE_CANNOT_CREATE, "Invalid null value");
  -      }
  -      checkOpened();
  -      try {
  -         Page p = seekInsertionPage(key);
  -         HashPageHeader ph = (HashPageHeader)p.getPageHeader();
  +                return new Record(key, v, meta);
  +            }
  +        }
  +        catch (Exception e) {
  +            log.warn(e);
  +        }
  +        return null;
  +    }
  +
  +    public boolean writeRecord(Key key, Value value) throws DBException {
  +        if (key == null || key.equals("")) {
  +            throw new FilerException(FaultCodes.DBE_CANNOT_CREATE, "Invalid key: '" + key + "'");
  +        }
  +        if (value == null) {
  +            throw new FilerException(FaultCodes.DBE_CANNOT_CREATE, "Invalid null value");
  +        }
  +        checkOpened();
  +        try {
  +            Page p = seekInsertionPage(key);
  +            HashPageHeader ph = (HashPageHeader) p.getPageHeader();
   
  -         long t = System.currentTimeMillis();
  +            long t = System.currentTimeMillis();
   
  -        // if ( ph.getStatus() == UNUSED ) {
  +            // if ( ph.getStatus() == UNUSED ) {
               // This is a new Record
               fileHeader.incRecordCount();
   
  -           // btree.addValue(key, p.getPageNum());
  +            // btree.addValue(key, p.getPageNum());
   
               ph.setCreated(t);
   
  -        // }
  +            // }
   
  -         ph.setModified(t);
  -         ph.setStatus(RECORD);
  +            ph.setModified(t);
  +            ph.setStatus(RECORD);
   
  -         p.setKey(key);
  -         writeValue(p, value);
  +            p.setKey(key);
  +            writeValue(p, value);
   
  -         flush();
  -      }
  -      catch ( Exception e ) {
  -         if (log.isDebugEnabled()) {
  -            log.debug("No message", e);
  -         }
  -      }
  -      return true;
  -   }
  -
  -   public boolean deleteRecord(Key key) throws DBException {
  -      if ( key == null || key.equals("") ) {
  -         return false;
  -      }
  -      checkOpened();
  -      try {
  -         int hash = key.getHash();
  -         long pageNum = hash % fileHeader.getPageCount();
  -         Page prev = null;
  -         Page page = null;
  -
  -         HashPageHeader prevHead = null;
  -         HashPageHeader pageHead = null;
  -
  -         while ( true ) {
  -            page = getPage(pageNum);
  -            pageHead = (HashPageHeader)page.getPageHeader();
  -            if ( pageHead.getStatus() == RECORD
  -               && pageHead.getKeyHash() == key.getHash()
  -               && page.getKey().equals(key) )
  -               break;
  -            pageNum = pageHead.getNextCollision();
  -            if ( pageNum == -1 )
  -               return false;
  -            prev = page;
  -            prevHead = pageHead;
  -         }
  +            flush();
  +        }
  +        catch (Exception e) {
  +            log.warn(e);
  +        }
  +        return true;
  +    }
   
  -         if ( page == null )
  +    public boolean deleteRecord(Key key) throws DBException {
  +        if (key == null || key.equals("")) {
               return false;
  +        }
  +        checkOpened();
  +        try {
  +            int hash = key.getHash();
  +            long pageNum = hash % fileHeader.getPageCount();
  +            Page prev = null;
  +            Page page = null;
  +
  +            HashPageHeader prevHead = null;
  +            HashPageHeader pageHead = null;
  +
  +            while (true) {
  +                page = getPage(pageNum);
  +                pageHead = (HashPageHeader) page.getPageHeader();
  +                if (pageHead.getStatus() == RECORD && pageHead.getKeyHash() == key.getHash() && page.getKey().equals(key))
  +                    break;
  +                pageNum = pageHead.getNextCollision();
  +                if (pageNum == -1)
  +                    return false;
  +                prev = page;
  +                prevHead = pageHead;
  +            }
   
  -         if ( prev != null ) {
  -            prevHead.setNextCollision(pageHead.nextCollision);
  -            prev.write();
  -         }
  -
  -         //btree.removeValue(key);
  -         unlinkPages(page);
  -
  -         fileHeader.decRecordCount();
  -
  -         flush();
  -
  -         return true;
  -      }
  -      catch ( Exception e ) {
  -         if (log.isDebugEnabled()) {
  -            log.debug("No message", e);
  -         }
  -      }
  -      return false;
  -   }
  -
  -   public long getRecordCount() throws DBException {
  -      checkOpened();
  -      return fileHeader.getRecordCount();
  -   }
  -
  -   public RecordSet getRecordSet() throws DBException {
  -      checkOpened();
  -      return new HashFilerRecordSet();
  -   }
  -
  -   public void flush() throws DBException {
  -      super.flush();
  -   }
  -
  -   /**
  -    * HashFilerRecordSet that does not use a BTree.
  -    */
  -   private class HashFilerRecordSet implements RecordSet {
  -      private List keys = new ArrayList();
  -      private Iterator enum;
  -
  -      public HashFilerRecordSet() {
  -         try {
  -            Page p = null;
  -            HashPageHeader ph = null;
  -            long pageNum = 0;
  -
  -            while ( pageNum < fileHeader.getTotalCount() ) {
  -               p = getPage(pageNum);
  -               ph = (HashPageHeader)p.getPageHeader();
  -               if ( ph.getStatus() == RECORD ) {
  -                  keys.add(p.getKey());
  -               }
  +            if (page == null)
  +                return false;
   
  -               pageNum++;
  +            if (prev != null) {
  +                prevHead.setNextCollision(pageHead.nextCollision);
  +                prev.write();
               }
   
  -            enum = keys.iterator();
  -         }
  -         catch ( Exception e ) {
  -            if (log.isDebugEnabled()) {
  -               log.debug("No message", e);
  -            }
  -         }
  -      }
  +            //btree.removeValue(key);
  +            unlinkPages(page);
  +
  +            fileHeader.decRecordCount();
   
  -      public synchronized Key getNextKey() {
  -         return (Key)enum.next();
  -      }
  -
  -      public synchronized Record getNextRecord() throws DBException {
  -         return readRecord((Key)enum.next());
  -      }
  -
  -      public synchronized Value getNextValue() throws DBException {
  -         return getNextRecord().getValue();
  -      }
  -
  -      public synchronized boolean hasMoreRecords() {
  -         return enum.hasNext();
  -      }
  -   }
  -
  -   /**
  -    * HashFilerRecordSet
  -    */
  -/*   private class HashFilerRecordSet implements RecordSet, BTreeCallback {
  -      private List keys = new ArrayList();
  -      private Iterator enum;
  -
  -      public HashFilerRecordSet() {
  -         try {
  -            btree.query(null, this);
  -            enum = keys.iterator();
  -         }
  -         catch ( Exception e ) {
  -            if (log.isDebugEnabled()) {
  -               log.debug("No message", e);
  +            flush();
  +
  +            return true;
  +        }
  +        catch (Exception e) {
  +            log.warn(e);
  +        }
  +        return false;
  +    }
  +
  +    public long getRecordCount() throws DBException {
  +        checkOpened();
  +        return fileHeader.getRecordCount();
  +    }
  +
  +    public RecordSet getRecordSet() throws DBException {
  +        checkOpened();
  +        return new HashFilerRecordSet();
  +    }
  +
  +    public void flush() throws DBException {
  +        super.flush();
  +    }
  +
  +    /**
  +     * HashFilerRecordSet that does not use a BTree.
  +     */
  +    private class HashFilerRecordSet implements RecordSet {
  +        private List keys = new ArrayList();
  +        private Iterator enum;
  +
  +        public HashFilerRecordSet() {
  +            try {
  +                Page p = null;
  +                HashPageHeader ph = null;
  +                long pageNum = 0;
  +
  +                while (pageNum < fileHeader.getTotalCount()) {
  +                    p = getPage(pageNum);
  +                    ph = (HashPageHeader) p.getPageHeader();
  +                    if (ph.getStatus() == RECORD) {
  +                        keys.add(p.getKey());
  +                    }
  +
  +                    pageNum++;
  +                }
  +
  +                enum = keys.iterator();
  +            }
  +            catch (Exception e) {
  +                log.warn(e);
               }
  -         }
  -      }
  +        }
   
  -      public synchronized boolean indexInfo(Value value, long pointer) {
  -         keys.add(new Key(value));
  -         return true;
  -      }
  -
  -      public synchronized Key getNextKey() {
  -         return (Key)enum.next();
  -      }
  -
  -      public synchronized Record getNextRecord() throws DBException {
  -         return readRecord((Key)enum.next());
  -      }
  -
  -      public synchronized Value getNextValue() throws DBException {
  -         return getNextRecord().getValue();
  -      }
  -
  -      public synchronized boolean hasMoreRecords() {
  -         return enum.hasNext();
  -      }
  -   }*/
  -
  -   ////////////////////////////////////////////////////////////////////
  -
  -   public FileHeader createFileHeader() {
  -      return new HashFileHeader();
  -   }
  -
  -   public FileHeader createFileHeader(boolean read) throws IOException {
  -      return new HashFileHeader(read);
  -   }
  -
  -   public FileHeader createFileHeader(long pageCount) {
  -      return new HashFileHeader(pageCount);
  -   }
  -
  -   public FileHeader createFileHeader(long pageCount, int pageSize) {
  -      return new HashFileHeader(pageCount, pageSize);
  -   }
  -
  -   public PageHeader createPageHeader() {
  -      return new HashPageHeader();
  -   }
  -
  -
  -   /**
  -    * HashFileHeader
  -    */
  -
  -   private final class HashFileHeader extends FileHeader {
  -      private long totalBytes = 0;
  -
  -      public HashFileHeader() {
  -      }
  -
  -      public HashFileHeader(long pageCount) {
  -         super(pageCount);
  -      }
  -
  -      public HashFileHeader(long pageCount, int pageSize) {
  -         super(pageCount, pageSize);
  -      }
  -
  -      public HashFileHeader(boolean read) throws IOException {
  -         super(read);
  -      }
  -
  -      public synchronized void read(RandomAccessFile raf) throws IOException {
  -         super.read(raf);
  -         totalBytes = raf.readLong();
  -      }
  -
  -      public synchronized void write(RandomAccessFile raf) throws IOException {
  -         super.write(raf);
  -         raf.writeLong(totalBytes);
  -      }
  -
  -      /** The total number of bytes in use by the file */
  -      public synchronized void setTotalBytes(long totalBytes) {
  -         this.totalBytes = totalBytes;
  -         setDirty();
  -      }
  -
  -      /** The total number of bytes in use by the file */
  -      public synchronized long getTotalBytes() {
  -         return totalBytes;
  -      }
  -   }
  -
  -   /**
  -    * HashPageHeader
  -    */
  -
  -   private final class HashPageHeader extends PageHeader {
  -      private long created = 0;
  -      private long modified = 0;
  -      private long nextCollision = -1;
  -
  -      public HashPageHeader() {
  -      }
  -
  -      public HashPageHeader(DataInputStream dis) throws IOException {
  -         super(dis);
  -      }
  -
  -      public synchronized void read(DataInputStream dis) throws IOException {
  -         super.read(dis);
  -
  -         if ( getStatus() == UNUSED )
  -            return;
  -
  -         created = dis.readLong();
  -         modified = dis.readLong();
  -         nextCollision = dis.readLong();
  -      }
  -
  -      public synchronized void write(DataOutputStream dos) throws IOException {
  -         super.write(dos);
  -         dos.writeLong(created);
  -         dos.writeLong(modified);
  -         dos.writeLong(nextCollision);
  -      }
  -
  -      public synchronized void setRecordLen(int recordLen) {
  -         fileHeader.setTotalBytes((fileHeader.totalBytes - getRecordLen()) + recordLen);
  -         super.setRecordLen(recordLen);
  -      }
  -
  -      /** UNIX-time when this record was created */
  -      public synchronized void setCreated(long created) {
  -         this.created = created;
  -         setDirty();
  -      }
  -
  -      /** UNIX-time when this record was created */
  -      public synchronized long getCreated() {
  -         return created;
  -      }
  -
  -      /** UNIX-time when this record was last modified */
  -      public synchronized void setModified(long modified) {
  -         this.modified = modified;
  -         setDirty();
  -      }
  -
  -      /** UNIX-time when this record was last modified */
  -      public synchronized long getModified() {
  -         return modified;
  -      }
  -
  -      /** The next page for a Record collision (if any) */
  -      public synchronized void setNextCollision(long nextCollision) {
  -         this.nextCollision = nextCollision;
  -         setDirty();
  -      }
  -
  -      /** The next page for a Record collision (if any) */
  -      public synchronized long getNextCollision() {
  -         return nextCollision;
  -      }
  -   }
  +        public synchronized Key getNextKey() {
  +            return (Key) enum.next();
  +        }
  +
  +        public synchronized Record getNextRecord() throws DBException {
  +            return readRecord((Key) enum.next());
  +        }
  +
  +        public synchronized Value getNextValue() throws DBException {
  +            return getNextRecord().getValue();
  +        }
  +
  +        public synchronized boolean hasMoreRecords() {
  +            return enum.hasNext();
  +        }
  +    }
  +
  +    /**
  +     * HashFilerRecordSet
  +     */
  +    /*   private class HashFilerRecordSet implements RecordSet, BTreeCallback {
  +          private List keys = new ArrayList();
  +          private Iterator enum;
  +    
  +          public HashFilerRecordSet() {
  +             try {
  +                btree.query(null, this);
  +                enum = keys.iterator();
  +             }
  +             catch ( Exception e ) {
  +                if (log.isDebugEnabled()) {
  +                   log.debug("No message", e);
  +                }
  +             }
  +          }
  +    
  +          public synchronized boolean indexInfo(Value value, long pointer) {
  +             keys.add(new Key(value));
  +             return true;
  +          }
  +    
  +          public synchronized Key getNextKey() {
  +             return (Key)enum.next();
  +          }
  +    
  +          public synchronized Record getNextRecord() throws DBException {
  +             return readRecord((Key)enum.next());
  +          }
  +    
  +          public synchronized Value getNextValue() throws DBException {
  +             return getNextRecord().getValue();
  +          }
  +    
  +          public synchronized boolean hasMoreRecords() {
  +             return enum.hasNext();
  +          }
  +       }*/
  +
  +    ////////////////////////////////////////////////////////////////////
  +
  +    public FileHeader createFileHeader() {
  +        return new HashFileHeader();
  +    }
  +
  +    public FileHeader createFileHeader(boolean read) throws IOException {
  +        return new HashFileHeader(read);
  +    }
  +
  +    public FileHeader createFileHeader(long pageCount) {
  +        return new HashFileHeader(pageCount);
  +    }
  +
  +    public FileHeader createFileHeader(long pageCount, int pageSize) {
  +        return new HashFileHeader(pageCount, pageSize);
  +    }
  +
  +    public PageHeader createPageHeader() {
  +        return new HashPageHeader();
  +    }
  +
  +    /**
  +     * HashFileHeader
  +     */
  +
  +    private final class HashFileHeader extends FileHeader {
  +        private long totalBytes = 0;
  +
  +        public HashFileHeader() {}
  +
  +        public HashFileHeader(long pageCount) {
  +            super(pageCount);
  +        }
  +
  +        public HashFileHeader(long pageCount, int pageSize) {
  +            super(pageCount, pageSize);
  +        }
  +
  +        public HashFileHeader(boolean read) throws IOException {
  +            super(read);
  +        }
  +
  +        public synchronized void read(RandomAccessFile raf) throws IOException {
  +            super.read(raf);
  +            totalBytes = raf.readLong();
  +        }
  +
  +        public synchronized void write(RandomAccessFile raf) throws IOException {
  +            super.write(raf);
  +            raf.writeLong(totalBytes);
  +        }
  +
  +        /** The total number of bytes in use by the file */
  +        public synchronized void setTotalBytes(long totalBytes) {
  +            this.totalBytes = totalBytes;
  +            setDirty();
  +        }
  +
  +        /** The total number of bytes in use by the file */
  +        public synchronized long getTotalBytes() {
  +            return totalBytes;
  +        }
  +    }
  +
  +    /**
  +     * HashPageHeader
  +     */
  +
  +    private final class HashPageHeader extends PageHeader {
  +        private long created = 0;
  +        private long modified = 0;
  +        private long nextCollision = -1;
  +
  +        public HashPageHeader() {}
  +
  +        public HashPageHeader(DataInputStream dis) throws IOException {
  +            super(dis);
  +        }
  +
  +        public synchronized void read(DataInputStream dis) throws IOException {
  +            super.read(dis);
  +
  +            if (getStatus() == UNUSED)
  +                return;
  +
  +            created = dis.readLong();
  +            modified = dis.readLong();
  +            nextCollision = dis.readLong();
  +        }
  +
  +        public synchronized void write(DataOutputStream dos) throws IOException {
  +            super.write(dos);
  +            dos.writeLong(created);
  +            dos.writeLong(modified);
  +            dos.writeLong(nextCollision);
  +        }
  +
  +        public synchronized void setRecordLen(int recordLen) {
  +            fileHeader.setTotalBytes((fileHeader.totalBytes - getRecordLen()) + recordLen);
  +            super.setRecordLen(recordLen);
  +        }
  +
  +        /** UNIX-time when this record was created */
  +        public synchronized void setCreated(long created) {
  +            this.created = created;
  +            setDirty();
  +        }
  +
  +        /** UNIX-time when this record was created */
  +        public synchronized long getCreated() {
  +            return created;
  +        }
  +
  +        /** UNIX-time when this record was last modified */
  +        public synchronized void setModified(long modified) {
  +            this.modified = modified;
  +            setDirty();
  +        }
  +
  +        /** UNIX-time when this record was last modified */
  +        public synchronized long getModified() {
  +            return modified;
  +        }
  +
  +        /** The next page for a Record collision (if any) */
  +        public synchronized void setNextCollision(long nextCollision) {
  +            this.nextCollision = nextCollision;
  +            setDirty();
  +        }
  +
  +        /** The next page for a Record collision (if any) */
  +        public synchronized long getNextCollision() {
  +            return nextCollision;
  +        }
  +    }
   }
  
  
  
  1.9       +330 -344  xml-xindice/java/src/org/apache/xindice/core/filer/BTreeFiler.java
  
  Index: BTreeFiler.java
  ===================================================================
  RCS file: /home/cvs/xml-xindice/java/src/org/apache/xindice/core/filer/BTreeFiler.java,v
  retrieving revision 1.8
  retrieving revision 1.9
  diff -u -r1.8 -r1.9
  --- BTreeFiler.java	19 Nov 2002 05:16:58 -0000	1.8
  +++ BTreeFiler.java	15 Jul 2003 15:44:35 -0000	1.9
  @@ -59,18 +59,6 @@
    * $Id$
    */
   
  -import org.apache.xindice.core.DBException;
  -import org.apache.xindice.core.FaultCodes;
  -import org.apache.xindice.core.data.Key;
  -import org.apache.xindice.core.data.Record;
  -import org.apache.xindice.core.data.RecordSet;
  -import org.apache.xindice.core.data.Value;
  -import org.apache.xindice.util.Configurable;
  -import org.apache.xindice.util.Configuration;
  -
  -import org.apache.commons.logging.Log;
  -import org.apache.commons.logging.LogFactory;
  -
   import java.io.DataInputStream;
   import java.io.DataOutputStream;
   import java.io.File;
  @@ -81,346 +69,344 @@
   import java.util.Iterator;
   import java.util.List;
   
  +import org.apache.commons.logging.Log;
  +import org.apache.commons.logging.LogFactory;
  +import org.apache.xindice.core.DBException;
  +import org.apache.xindice.core.FaultCodes;
  +import org.apache.xindice.core.data.Key;
  +import org.apache.xindice.core.data.Record;
  +import org.apache.xindice.core.data.RecordSet;
  +import org.apache.xindice.core.data.Value;
  +import org.apache.xindice.util.Configurable;
  +import org.apache.xindice.util.Configuration;
  +
   /**
    * BTreeFiler is a Filer implementation based on the BTree class.
    */
   
   public final class BTreeFiler extends BTree implements Configurable, Filer {
  -   protected static final byte RECORD = 20;
  +    protected static final byte RECORD = 20;
   
  -   private static final String PAGESIZE = "pagesize";
  -   private static final String MAXKEYSIZE = "maxkeysize";
  +    private static final String PAGESIZE = "pagesize";
  +    private static final String MAXKEYSIZE = "maxkeysize";
   
  -   private static Log log = LogFactory.getLog("org.apache.xindice.core");
  +    private static Log log = LogFactory.getLog("org.apache.xindice.core");
   
  -   private Configuration config;
  -   private BTreeFilerHeader fileHeader;
  -
  -   public BTreeFiler() {
  -      super();
  -      fileHeader = (BTreeFilerHeader)getFileHeader();
  -   }
  -
  -   public void setConfig(Configuration config) {
  -      this.config = config;
  -   }
  -
  -   public Configuration getConfig() {
  -      return config;
  -   }
  -
  -   public void setLocation(File root, String location) {
  -      setFile(new File(root, location + ".tbl"));
  -   }
  -   
  -   public String getName() {
  -      return "BTreeFiler";
  -   }
  -
  -   public boolean open() throws DBException {
  -      if ( super.open() ) {
  -         // These are the only properties that can be changed after creation
  -         fileHeader.setMaxKeySize(config.getShortAttribute(MAXKEYSIZE, fileHeader.getMaxKeySize()));
  -         return true;
  -      }
  -      else
  -         return false;
  -   }
  -
  -   public boolean create() throws DBException {
  -      fileHeader.setPageSize(config.getIntAttribute(PAGESIZE, fileHeader.getPageSize()));
  -      fileHeader.setMaxKeySize(config.getShortAttribute(MAXKEYSIZE, fileHeader.getMaxKeySize()));
  -      return super.create();
  -   }
  -
  -   public Record readRecord(Key key) throws DBException {
  -      if ( key == null || key.equals("") ) {
  -         return null;
  -      }
  -      checkOpened();
  -      try {
  -         long pos = findValue(key);
  -         Page startPage = getPage(pos);
  -         Value v = readValue(startPage);
  -         BTreeFilerPageHeader sph = (BTreeFilerPageHeader)startPage.getPageHeader();
  -
  -         HashMap meta = new HashMap(2);
  -         meta.put(Record.CREATED, new Long(sph.getCreated()));
  -         meta.put(Record.MODIFIED, new Long(sph.getModified()));
  -
  -         return new Record(key, v, meta);
  -      }
  -      catch ( BTreeNotFoundException e ) {
  -      }
  -      catch ( BTreeException e ) {
  -         throw e;
  -      }
  -      catch ( Exception e ) {
  -         if (log.isDebugEnabled()) {
  -            log.debug("No message", e);
  -         }
  -      }
  -      return null;
  -   }
  -
  -   public boolean writeRecord(Key key, Value value) throws DBException {
  -      if ( key == null || key.equals("") ) {
  -         throw new FilerException(FaultCodes.DBE_CANNOT_CREATE, "Invalid key: '" + key + "'");
  -      }
  -      if (value == null ) {
  -         throw new FilerException(FaultCodes.DBE_CANNOT_CREATE, "Invalid null value");
  -      }
  -      checkOpened();
  -      try {
  -         Page p;
  -         try {
  +    private Configuration config;
  +    private BTreeFilerHeader fileHeader;
  +
  +    public BTreeFiler() {
  +        super();
  +        fileHeader = (BTreeFilerHeader) getFileHeader();
  +    }
  +
  +    public void setConfig(Configuration config) {
  +        this.config = config;
  +    }
  +
  +    public Configuration getConfig() {
  +        return config;
  +    }
  +
  +    public void setLocation(File root, String location) {
  +        setFile(new File(root, location + ".tbl"));
  +    }
  +
  +    public String getName() {
  +        return "BTreeFiler";
  +    }
  +
  +    public boolean open() throws DBException {
  +        if (super.open()) {
  +            // These are the only properties that can be changed after creation
  +            fileHeader.setMaxKeySize(config.getShortAttribute(MAXKEYSIZE, fileHeader.getMaxKeySize()));
  +            return true;
  +        }
  +        else
  +            return false;
  +    }
  +
  +    public boolean create() throws DBException {
  +        fileHeader.setPageSize(config.getIntAttribute(PAGESIZE, fileHeader.getPageSize()));
  +        fileHeader.setMaxKeySize(config.getShortAttribute(MAXKEYSIZE, fileHeader.getMaxKeySize()));
  +        return super.create();
  +    }
  +
  +    public Record readRecord(Key key) throws DBException {
  +        if (key == null || key.equals("")) {
  +            return null;
  +        }
  +        checkOpened();
  +        try {
               long pos = findValue(key);
  -            p = getPage(pos);
  -         }
  -         catch ( BTreeNotFoundException e ) {
  -            p = getFreePage();
  -            addValue(key, p.getPageNum());
  -            fileHeader.incRecordCount();
  -         }
  -         BTreeFilerPageHeader ph = (BTreeFilerPageHeader)p.getPageHeader();
  -
  -         long t = System.currentTimeMillis();
  -         if ( ph.getStatus() == UNUSED )
  -            ph.setCreated(t);
  -
  -         ph.setModified(t);
  -         ph.setStatus(RECORD);
  -
  -         writeValue(p, value);
  -
  -         flush();
  -      }
  -      catch ( DBException e ) {
  -         throw e;
  -      }
  -      catch ( IOException e ) {
  -         throw new FilerException(FaultCodes.DBE_CANNOT_CREATE, e.getMessage(), e);
  -      }
  -      catch ( Exception e ) {
  -         if (log.isDebugEnabled()) {
  -            log.debug("No message", e);
  -         }
  -      }
  -      return true;
  -   }
  -
  -   public boolean deleteRecord(Key key) throws DBException {
  -      if ( key == null || key.equals("") ) {
  -         return false;
  -      }
  -      checkOpened();
  -      try {
  -         long pos = findValue(key);
  -         Page p = getPage(pos);
  -
  -         removeValue(key);
  -         unlinkPages(p.getPageNum());
  -
  -         fileHeader.decRecordCount();
  -
  -         flush();
  -
  -         return true;
  -      }
  -      catch ( BTreeNotFoundException e ) {
  -      }
  -      catch ( BTreeException e ) {
  -         throw e;
  -      }
  -      catch ( Exception e ) {
  -         if (log.isDebugEnabled()) {
  -            log.debug("No message", e);
  -         }
  -      }
  -      return false;
  -   }
  -
  -   public long getRecordCount() throws DBException {
  -      checkOpened();
  -      return fileHeader.getRecordCount();
  -   }
  -
  -   public RecordSet getRecordSet() throws DBException {
  -      checkOpened();
  -      return new BTreeFilerRecordSet();
  -   }
  -
  -   public void flush() throws DBException {
  -      super.flush();
  -   }
  -
  -
  -   /**
  -    * BTreeFilerRecordSet
  -    */
  -
  -   private class BTreeFilerRecordSet implements RecordSet, BTreeCallback {
  -      private List keys = new ArrayList();
  -      private Iterator enum;
  -
  -      public BTreeFilerRecordSet() throws DBException {
  -         try {
  -            query(null, this);
  -            enum = keys.iterator();
  -         }
  -         catch ( IOException e ) {
  -            throw new FilerException(FaultCodes.GEN_CRITICAL_ERROR, "Error generating RecordSet", e);
  -         }
  -      }
  -
  -      public synchronized boolean indexInfo(Value value, long pointer) {
  -         keys.add(new Key(value));
  -         return true;
  -      }
  -
  -      public synchronized Key getNextKey() {
  -         return (Key)enum.next();
  -      }
  -
  -      public synchronized Record getNextRecord() throws DBException {
  -         return readRecord((Key)enum.next());
  -      }
  -
  -      public synchronized Value getNextValue() throws DBException {
  -         return getNextRecord().getValue();
  -      }
  -
  -      public synchronized boolean hasMoreRecords() {
  -         return enum.hasNext();
  -      }
  -   }
  -
  -   ////////////////////////////////////////////////////////////////////
  -
  -   public FileHeader createFileHeader() {
  -      return new BTreeFilerHeader();
  -   }
  -
  -   public FileHeader createFileHeader(boolean read) throws IOException {
  -      return new BTreeFilerHeader(read);
  -   }
  -
  -   public FileHeader createFileHeader(long pageCount) {
  -      return new BTreeFilerHeader(pageCount);
  -   }
  -
  -   public FileHeader createFileHeader(long pageCount, int pageSize) {
  -      return new BTreeFilerHeader(pageCount, pageSize);
  -   }
  -
  -   public PageHeader createPageHeader() {
  -      return new BTreeFilerPageHeader();
  -   }
  -
  -
  -   /**
  -    * BTreeFilerHeader
  -    */
  -
  -   private final class BTreeFilerHeader extends BTreeFileHeader {
  -      private long totalBytes = 0;
  -
  -      public BTreeFilerHeader() {
  -      }
  -
  -      public BTreeFilerHeader(long pageCount) {
  -         super(pageCount);
  -      }
  -
  -      public BTreeFilerHeader(long pageCount, int pageSize) {
  -         super(pageCount, pageSize);
  -      }
  -
  -      public BTreeFilerHeader(boolean read) throws IOException {
  -         super(read);
  -      }
  -
  -      public synchronized void read(RandomAccessFile raf) throws IOException {
  -         super.read(raf);
  -         totalBytes = raf.readLong();
  -      }
  -
  -      public synchronized void write(RandomAccessFile raf) throws IOException {
  -         super.write(raf);
  -         raf.writeLong(totalBytes);
  -      }
  -
  -      /** The total number of bytes in use by the file */
  -      public synchronized void setTotalBytes(long totalBytes) {
  -         this.totalBytes = totalBytes;
  -         setDirty();
  -      }
  -
  -      /** The total number of bytes in use by the file */
  -      public synchronized long getTotalBytes() {
  -         return totalBytes;
  -      }
  -   }
  -
  -   /**
  -    * BTreeFilerPageHeader
  -    */
  -
  -   private final class BTreeFilerPageHeader extends BTreePageHeader {
  -      private long created = 0;
  -      private long modified = 0;
  -
  -      public BTreeFilerPageHeader() {
  -      }
  -
  -      public BTreeFilerPageHeader(DataInputStream dis) throws IOException {
  -         super(dis);
  -      }
  -
  -      public synchronized void read(DataInputStream dis) throws IOException {
  -         super.read(dis);
  -
  -         if ( getStatus() == UNUSED )
  -            return;
  -
  -         created = dis.readLong();
  -         modified = dis.readLong();
  -      }
  -
  -      public synchronized void write(DataOutputStream dos) throws IOException {
  -         super.write(dos);
  -         dos.writeLong(created);
  -         dos.writeLong(modified);
  -      }
  -
  -      public synchronized void setRecordLen(int recordLen) {
  -         fileHeader.setTotalBytes((fileHeader.totalBytes - getRecordLen()) + recordLen);
  -         super.setRecordLen(recordLen);
  -      }
  -
  -      /** UNIX-time when this record was created */
  -      public synchronized void setCreated(long created) {
  -         this.created = created;
  -         setDirty();
  -      }
  -
  -      /** UNIX-time when this record was created */
  -      public synchronized long getCreated() {
  -         return created;
  -      }
  -
  -      /** UNIX-time when this record was last modified */
  -      public synchronized void setModified(long modified) {
  -         this.modified = modified;
  -         setDirty();
  -      }
  -
  -      /** UNIX-time when this record was last modified */
  -      public synchronized long getModified() {
  -         return modified;
  -      }
  -   }
  -}
  +            Page startPage = getPage(pos);
  +            Value v = readValue(startPage);
  +            BTreeFilerPageHeader sph = (BTreeFilerPageHeader) startPage.getPageHeader();
  +
  +            HashMap meta = new HashMap(2);
  +            meta.put(Record.CREATED, new Long(sph.getCreated()));
  +            meta.put(Record.MODIFIED, new Long(sph.getModified()));
  +
  +            return new Record(key, v, meta);
  +        }
  +        catch (BTreeNotFoundException e) {}
  +        catch (BTreeException e) {
  +            throw e;
  +        }
  +        catch (Exception e) {
  +            log.warn(e);
  +        }
  +        return null;
  +    }
  +
  +    public boolean writeRecord(Key key, Value value) throws DBException {
  +        if (key == null || key.equals("")) {
  +            throw new FilerException(FaultCodes.DBE_CANNOT_CREATE, "Invalid key: '" + key + "'");
  +        }
  +        if (value == null) {
  +            throw new FilerException(FaultCodes.DBE_CANNOT_CREATE, "Invalid null value");
  +        }
  +        checkOpened();
  +        try {
  +            Page p;
  +            try {
  +                long pos = findValue(key);
  +                p = getPage(pos);
  +            }
  +            catch (BTreeNotFoundException e) {
  +                p = getFreePage();
  +                addValue(key, p.getPageNum());
  +                fileHeader.incRecordCount();
  +            }
  +            BTreeFilerPageHeader ph = (BTreeFilerPageHeader) p.getPageHeader();
  +
  +            long t = System.currentTimeMillis();
  +            if (ph.getStatus() == UNUSED)
  +                ph.setCreated(t);
  +
  +            ph.setModified(t);
  +            ph.setStatus(RECORD);
  +
  +            writeValue(p, value);
  +
  +            flush();
  +        }
  +        catch (DBException e) {
  +            throw e;
  +        }
  +        catch (IOException e) {
  +            throw new FilerException(FaultCodes.DBE_CANNOT_CREATE, e.getMessage(), e);
  +        }
  +        catch (Exception e) {
  +            log.warn(e);
  +        }
  +        return true;
  +    }
  +
  +    public boolean deleteRecord(Key key) throws DBException {
  +        if (key == null || key.equals("")) {
  +            return false;
  +        }
  +        checkOpened();
  +        try {
  +            long pos = findValue(key);
  +            Page p = getPage(pos);
  +
  +            removeValue(key);
  +            unlinkPages(p.getPageNum());
   
  +            fileHeader.decRecordCount();
   
  +            flush();
   
  +            return true;
  +        }
  +        catch (BTreeNotFoundException e) {
  +            log.warn(e);
  +        }
  +        catch (BTreeException e) {
  +            throw e;
  +        }
  +        catch (Exception e) {
  +            log.warn(e);
  +        }
  +        return false;
  +    }
  +
  +    public long getRecordCount() throws DBException {
  +        checkOpened();
  +        return fileHeader.getRecordCount();
  +    }
  +
  +    public RecordSet getRecordSet() throws DBException {
  +        checkOpened();
  +        return new BTreeFilerRecordSet();
  +    }
  +
  +    public void flush() throws DBException {
  +        super.flush();
  +    }
  +
  +    /**
  +     * BTreeFilerRecordSet
  +     */
  +
  +    private class BTreeFilerRecordSet implements RecordSet, BTreeCallback {
  +        private List keys = new ArrayList();
  +        private Iterator enum;
  +
  +        public BTreeFilerRecordSet() throws DBException {
  +            try {
  +                query(null, this);
  +                enum = keys.iterator();
  +            }
  +            catch (IOException e) {
  +                throw new FilerException(FaultCodes.GEN_CRITICAL_ERROR, "Error generating RecordSet", e);
  +            }
  +        }
  +
  +        public synchronized boolean indexInfo(Value value, long pointer) {
  +            keys.add(new Key(value));
  +            return true;
  +        }
  +
  +        public synchronized Key getNextKey() {
  +            return (Key) enum.next();
  +        }
  +
  +        public synchronized Record getNextRecord() throws DBException {
  +            return readRecord((Key) enum.next());
  +        }
  +
  +        public synchronized Value getNextValue() throws DBException {
  +            return getNextRecord().getValue();
  +        }
  +
  +        public synchronized boolean hasMoreRecords() {
  +            return enum.hasNext();
  +        }
  +    }
  +
  +    ////////////////////////////////////////////////////////////////////
  +
  +    public FileHeader createFileHeader() {
  +        return new BTreeFilerHeader();
  +    }
  +
  +    public FileHeader createFileHeader(boolean read) throws IOException {
  +        return new BTreeFilerHeader(read);
  +    }
  +
  +    public FileHeader createFileHeader(long pageCount) {
  +        return new BTreeFilerHeader(pageCount);
  +    }
  +
  +    public FileHeader createFileHeader(long pageCount, int pageSize) {
  +        return new BTreeFilerHeader(pageCount, pageSize);
  +    }
  +
  +    public PageHeader createPageHeader() {
  +        return new BTreeFilerPageHeader();
  +    }
  +
  +    /**
  +     * BTreeFilerHeader
  +     */
  +
  +    private final class BTreeFilerHeader extends BTreeFileHeader {
  +        private long totalBytes = 0;
  +
  +        public BTreeFilerHeader() {}
  +
  +        public BTreeFilerHeader(long pageCount) {
  +            super(pageCount);
  +        }
  +
  +        public BTreeFilerHeader(long pageCount, int pageSize) {
  +            super(pageCount, pageSize);
  +        }
  +
  +        public BTreeFilerHeader(boolean read) throws IOException {
  +            super(read);
  +        }
  +
  +        public synchronized void read(RandomAccessFile raf) throws IOException {
  +            super.read(raf);
  +            totalBytes = raf.readLong();
  +        }
  +
  +        public synchronized void write(RandomAccessFile raf) throws IOException {
  +            super.write(raf);
  +            raf.writeLong(totalBytes);
  +        }
  +
  +        /** The total number of bytes in use by the file */
  +        public synchronized void setTotalBytes(long totalBytes) {
  +            this.totalBytes = totalBytes;
  +            setDirty();
  +        }
  +
  +        /** The total number of bytes in use by the file */
  +        public synchronized long getTotalBytes() {
  +            return totalBytes;
  +        }
  +    }
  +
  +    /**
  +     * BTreeFilerPageHeader
  +     */
  +
  +    private final class BTreeFilerPageHeader extends BTreePageHeader {
  +        private long created = 0;
  +        private long modified = 0;
  +
  +        public BTreeFilerPageHeader() {}
  +
  +        public BTreeFilerPageHeader(DataInputStream dis) throws IOException {
  +            super(dis);
  +        }
  +
  +        public synchronized void read(DataInputStream dis) throws IOException {
  +            super.read(dis);
  +
  +            if (getStatus() == UNUSED)
  +                return;
  +
  +            created = dis.readLong();
  +            modified = dis.readLong();
  +        }
  +
  +        public synchronized void write(DataOutputStream dos) throws IOException {
  +            super.write(dos);
  +            dos.writeLong(created);
  +            dos.writeLong(modified);
  +        }
  +
  +        public synchronized void setRecordLen(int recordLen) {
  +            fileHeader.setTotalBytes((fileHeader.totalBytes - getRecordLen()) + recordLen);
  +            super.setRecordLen(recordLen);
  +        }
  +
  +        /** UNIX-time when this record was created */
  +        public synchronized void setCreated(long created) {
  +            this.created = created;
  +            setDirty();
  +        }
  +
  +        /** UNIX-time when this record was created */
  +        public synchronized long getCreated() {
  +            return created;
  +        }
  +
  +        /** UNIX-time when this record was last modified */
  +        public synchronized void setModified(long modified) {
  +            this.modified = modified;
  +            setDirty();
  +        }
  +
  +        /** UNIX-time when this record was last modified */
  +        public synchronized long getModified() {
  +            return modified;
  +        }
  +    }
  +}
  
  
  
  1.8       +119 -121  xml-xindice/java/src/org/apache/xindice/core/xupdate/XUpdateQueryResolver.java
  
  Index: XUpdateQueryResolver.java
  ===================================================================
  RCS file: /home/cvs/xml-xindice/java/src/org/apache/xindice/core/xupdate/XUpdateQueryResolver.java,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- XUpdateQueryResolver.java	17 Jun 2003 02:39:12 -0000	1.7
  +++ XUpdateQueryResolver.java	15 Jul 2003 15:44:35 -0000	1.8
  @@ -86,124 +86,122 @@
    * XUpdateQueryResolver
    */
   public class XUpdateQueryResolver extends SimpleConfigurable implements QueryResolver {
  -	private static final String XUPDATE_XPATH_PROP = "org.xmldb.common.xml.queries.XPathQueryFactory";
  -	private static final String XUPDATE_XPATH_IMPL = "org.apache.xindice.core.xupdate.XPathQueryFactoryImpl";
  -	static {
  -		System.setProperty(XUPDATE_XPATH_PROP, XUPDATE_XPATH_IMPL);
  -	}
  -
  -	private static Log log = LogFactory.getLog("org.apache.xindice.core");
  -
  -	public static final String STYLE_XUPDATE = "XUpdate";
  -
  -	private QueryEngine engine;
  -
  -	public void setConfig(Configuration config) throws XindiceException {
  -		super.setConfig(config);
  -	}
  -
  -	public String getQueryStyle() {
  -		return STYLE_XUPDATE;
  -	}
  -
  -	public void setQueryEngine(QueryEngine engine) {
  -		this.engine = engine;
  -	}
  -
  -	public Query compileQuery(Collection context, String query, NamespaceMap nsMap, Key[] keys) throws QueryException {
  -		return new XUpdateQuery(context, query, nsMap, keys);
  -	}
  -
  -	public NodeSet query(Collection context, String query, NamespaceMap nsMap, Key[] keys) throws QueryException {
  -		XUpdateQuery xq = new XUpdateQuery(context, query, nsMap, keys);
  -		return xq.execute();
  -	}
  -
  -	/**
  -	 * XUpdateQuery
  -	 */
  -
  -	private class XUpdateQuery implements Query {
  -		public Collection context;
  -		public String query;
  -		public NamespaceMap nsMap;
  -		public XUpdateImpl xu;
  -		public Key[] keys;
  -
  -		public XUpdateQuery(Collection context, String query, NamespaceMap nsMap, Key[] keys) throws QueryException {
  -			this.context = context;
  -			this.query = query;
  -			this.nsMap = nsMap;
  -			this.keys = keys;
  -
  -			try {
  -				xu = new XUpdateImpl();
  -				xu.setQString(query);
  -				xu.setNamespaceMap(nsMap);
  -			}
  -			catch (Exception e) {
  -				if (e instanceof QueryException) {
  -					throw (QueryException) e.fillInStackTrace();
  -				}
  -				throw new CompilationException("Error Compiling XUpdate Query", e);
  -			}
  -		}
  -
  -		public String getQueryStyle() {
  -			return STYLE_XUPDATE;
  -		}
  -
  -		public Collection getQueryContext() {
  -			return context;
  -		}
  -
  -		public String getQueryString() {
  -			return query;
  -		}
  -
  -		public NamespaceMap getNamespaceMap() {
  -			return nsMap;
  -		}
  -
  -		public Key[] getKeySet() {
  -			return keys;
  -		}
  -
  -		public NodeSet execute() throws QueryException {
  -			try {
  -				if (keys != null) {
  -					try {
  -						for (int i = 0; i < keys.length; i++) {
  -							Document doc = context.getDocument(keys[i]);
  -							xu.execute(doc.getDocumentElement());
  -							context.setDocument(keys[i], doc);
  -						}
  -					}
  -					catch (Exception e) {
  -						if (log.isDebugEnabled()) {
  -							log.debug("No message", e);
  -						}
  -					}
  -				}
  -				else {
  -					xu.execute(context);
  -				}
  -
  -				DocumentImpl doc = new DocumentImpl();
  -				Element elem = doc.createElementNS(NodeSource.SOURCE_NS, "src:" + NodeSource.SOURCE_MODIFIED);
  -				elem.setAttribute(NodeImpl.XMLNS_PREFIX + ":src", NodeSource.SOURCE_NS);
  -				doc.appendChild(elem);
  -				Text count = doc.createTextNode(Integer.toString(xu.getModifiedCount()));
  -				elem.appendChild(count);
  -
  -				return new NodeListSet(doc.getChildNodes());
  -			}
  -			catch (Exception e) {
  -				if (e instanceof QueryException) {
  -					throw (QueryException) e.fillInStackTrace();
  -				}
  -				throw new ProcessingException("Error executing XUpdate query", e);
  -			}
  -		}
  -	}
  +    private static final String XUPDATE_XPATH_PROP = "org.xmldb.common.xml.queries.XPathQueryFactory";
  +    private static final String XUPDATE_XPATH_IMPL = "org.apache.xindice.core.xupdate.XPathQueryFactoryImpl";
  +    static {
  +        System.setProperty(XUPDATE_XPATH_PROP, XUPDATE_XPATH_IMPL);
  +    }
  +
  +    private static Log log = LogFactory.getLog("org.apache.xindice.core");
  +
  +    public static final String STYLE_XUPDATE = "XUpdate";
  +
  +    private QueryEngine engine;
  +
  +    public void setConfig(Configuration config) throws XindiceException {
  +        super.setConfig(config);
  +    }
  +
  +    public String getQueryStyle() {
  +        return STYLE_XUPDATE;
  +    }
  +
  +    public void setQueryEngine(QueryEngine engine) {
  +        this.engine = engine;
  +    }
  +
  +    public Query compileQuery(Collection context, String query, NamespaceMap nsMap, Key[] keys) throws QueryException {
  +        return new XUpdateQuery(context, query, nsMap, keys);
  +    }
  +
  +    public NodeSet query(Collection context, String query, NamespaceMap nsMap, Key[] keys) throws QueryException {
  +        XUpdateQuery xq = new XUpdateQuery(context, query, nsMap, keys);
  +        return xq.execute();
  +    }
  +
  +    /**
  +     * XUpdateQuery
  +     */
  +
  +    private class XUpdateQuery implements Query {
  +        public Collection context;
  +        public String query;
  +        public NamespaceMap nsMap;
  +        public XUpdateImpl xu;
  +        public Key[] keys;
  +
  +        public XUpdateQuery(Collection context, String query, NamespaceMap nsMap, Key[] keys) throws QueryException {
  +            this.context = context;
  +            this.query = query;
  +            this.nsMap = nsMap;
  +            this.keys = keys;
  +
  +            try {
  +                xu = new XUpdateImpl();
  +                xu.setQString(query);
  +                xu.setNamespaceMap(nsMap);
  +            }
  +            catch (Exception e) {
  +                if (e instanceof QueryException) {
  +                    throw (QueryException) e.fillInStackTrace();
  +                }
  +                throw new CompilationException("Error Compiling XUpdate Query", e);
  +            }
  +        }
  +
  +        public String getQueryStyle() {
  +            return STYLE_XUPDATE;
  +        }
  +
  +        public Collection getQueryContext() {
  +            return context;
  +        }
  +
  +        public String getQueryString() {
  +            return query;
  +        }
  +
  +        public NamespaceMap getNamespaceMap() {
  +            return nsMap;
  +        }
  +
  +        public Key[] getKeySet() {
  +            return keys;
  +        }
  +
  +        public NodeSet execute() throws QueryException {
  +            try {
  +                if (keys != null) {
  +                    try {
  +                        for (int i = 0; i < keys.length; i++) {
  +                            Document doc = context.getDocument(keys[i]);
  +                            xu.execute(doc.getDocumentElement());
  +                            context.setDocument(keys[i], doc);
  +                        }
  +                    }
  +                    catch (Exception e) {
  +                        log.warn(e);
  +                    }
  +                }
  +                else {
  +                    xu.execute(context);
  +                }
  +
  +                DocumentImpl doc = new DocumentImpl();
  +                Element elem = doc.createElementNS(NodeSource.SOURCE_NS, "src:" + NodeSource.SOURCE_MODIFIED);
  +                elem.setAttribute(NodeImpl.XMLNS_PREFIX + ":src", NodeSource.SOURCE_NS);
  +                doc.appendChild(elem);
  +                Text count = doc.createTextNode(Integer.toString(xu.getModifiedCount()));
  +                elem.appendChild(count);
  +
  +                return new NodeListSet(doc.getChildNodes());
  +            }
  +            catch (Exception e) {
  +                if (e instanceof QueryException) {
  +                    throw (QueryException) e.fillInStackTrace();
  +                }
  +                throw new ProcessingException("Error executing XUpdate query", e);
  +            }
  +        }
  +    }
   }
  
  
  
  1.4       +55 -58    xml-xindice/java/src/org/apache/xindice/xml/jaxp/DocumentBuilderImpl.java
  
  Index: DocumentBuilderImpl.java
  ===================================================================
  RCS file: /home/cvs/xml-xindice/java/src/org/apache/xindice/xml/jaxp/DocumentBuilderImpl.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- DocumentBuilderImpl.java	31 Oct 2002 07:02:23 -0000	1.3
  +++ DocumentBuilderImpl.java	15 Jul 2003 15:44:35 -0000	1.4
  @@ -59,76 +59,73 @@
    * $Id$
    */
   
  -import org.apache.xindice.xml.dom.DOMImplementationImpl;
  -import org.apache.xindice.xml.dom.DOMParser;
  -import org.apache.xindice.xml.dom.DocumentImpl;
  +import java.io.IOException;
  +
  +import javax.xml.parsers.DocumentBuilder;
  +import javax.xml.parsers.ParserConfigurationException;
   
   import org.apache.commons.logging.Log;
   import org.apache.commons.logging.LogFactory;
  -
  -import org.w3c.dom.*;
  +import org.apache.xindice.xml.dom.DOMImplementationImpl;
  +import org.apache.xindice.xml.dom.DOMParser;
  +import org.apache.xindice.xml.dom.DocumentImpl;
  +import org.w3c.dom.DOMImplementation;
  +import org.w3c.dom.Document;
   import org.xml.sax.EntityResolver;
   import org.xml.sax.ErrorHandler;
   import org.xml.sax.InputSource;
   import org.xml.sax.SAXException;
   
  -import java.io.IOException;
  -import javax.xml.parsers.DocumentBuilder;
  -import javax.xml.parsers.ParserConfigurationException;
  -
   /**
    * DocumentBuilderImpl
    */
   
   public class DocumentBuilderImpl extends DocumentBuilder {
   
  -   private static Log log = LogFactory.getLog("org.apache.xindice.xml");
  +    private static Log log = LogFactory.getLog("org.apache.xindice.xml");
   
  -   private DOMParser parser = null;
  -   private ErrorHandler errors = null;
  -   private EntityResolver entities = null;
  -
  -   protected DocumentBuilderImpl() throws ParserConfigurationException {
  -      try {
  -         parser = new DOMParser();
  -      }
  -      catch ( Exception e ) {
  -         if (log.isDebugEnabled()) {
  -            log.debug("No message", e);
  -         }
  -      }
  -   }
  -
  -   public DOMImplementation getDOMImplementation() {
  -      return DOMImplementationImpl.getInstance();
  -   }
  -   
  -   public boolean isNamespaceAware() {
  -      return true;
  -   }
  -   
  -   public boolean isValidating() {
  -      return false;
  -   }
  -   
  -   public void setErrorHandler(ErrorHandler errors) {
  -      this.errors = errors;
  -   }
  -   
  -   public void setEntityResolver(EntityResolver entities) {
  -      this.entities = entities;
  -   }
  -   
  -   public Document parse(InputSource source) throws SAXException, IOException, IllegalArgumentException {
  -      if ( source == null )
  -         throw new IllegalArgumentException();
  -      else
  -         parser.parse(source);
  -      return parser.getDocument();
  -   }
  -
  -   public Document newDocument() {
  -      return new DocumentImpl();
  -   }
  +    private DOMParser parser = null;
  +    private ErrorHandler errors = null;
  +    private EntityResolver entities = null;
  +
  +    protected DocumentBuilderImpl() throws ParserConfigurationException {
  +        try {
  +            parser = new DOMParser();
  +        }
  +        catch (Exception e) {
  +            log.warn(e);
  +        }
  +    }
  +
  +    public DOMImplementation getDOMImplementation() {
  +        return DOMImplementationImpl.getInstance();
  +    }
  +
  +    public boolean isNamespaceAware() {
  +        return true;
  +    }
  +
  +    public boolean isValidating() {
  +        return false;
  +    }
  +
  +    public void setErrorHandler(ErrorHandler errors) {
  +        this.errors = errors;
  +    }
  +
  +    public void setEntityResolver(EntityResolver entities) {
  +        this.entities = entities;
  +    }
  +
  +    public Document parse(InputSource source) throws SAXException, IOException, IllegalArgumentException {
  +        if (source == null)
  +            throw new IllegalArgumentException();
  +        else
  +            parser.parse(source);
  +        return parser.getDocument();
  +    }
  +
  +    public Document newDocument() {
  +        return new DocumentImpl();
  +    }
   }
  -
  
  
  
  1.12      +514 -546  xml-xindice/java/src/org/apache/xindice/core/indexer/IndexManager.java
  
  Index: IndexManager.java
  ===================================================================
  RCS file: /home/cvs/xml-xindice/java/src/org/apache/xindice/core/indexer/IndexManager.java,v
  retrieving revision 1.11
  retrieving revision 1.12
  diff -u -r1.11 -r1.12
  --- IndexManager.java	22 Nov 2002 10:15:35 -0000	1.11
  +++ IndexManager.java	15 Jul 2003 15:44:35 -0000	1.12
  @@ -59,6 +59,17 @@
    * $Id$
    */
   
  +import java.util.ArrayList;
  +import java.util.HashMap;
  +import java.util.Iterator;
  +import java.util.List;
  +import java.util.Map;
  +import java.util.Timer;
  +import java.util.TimerTask;
  +import java.util.WeakHashMap;
  +
  +import org.apache.commons.logging.Log;
  +import org.apache.commons.logging.LogFactory;
   import org.apache.xindice.core.Collection;
   import org.apache.xindice.core.DBException;
   import org.apache.xindice.core.data.Key;
  @@ -74,571 +85,528 @@
   import org.apache.xindice.xml.dom.DocumentImpl;
   import org.apache.xindice.xml.sax.CompressionHandler;
   import org.apache.xindice.xml.sax.SAXEventGenerator;
  -
  -import org.apache.commons.logging.Log;
  -import org.apache.commons.logging.LogFactory;
  -
  -import org.w3c.dom.*;
  +import org.w3c.dom.Document;
   import org.xml.sax.Attributes;
   import org.xml.sax.ContentHandler;
   import org.xml.sax.Locator;
   
  -import java.util.ArrayList;
  -import java.util.HashMap;
  -import java.util.Iterator;
  -import java.util.List;
  -import java.util.Map;
  -import java.util.Timer;
  -import java.util.TimerTask;
  -import java.util.WeakHashMap;
  -
   /**
    * IndexManager is a class that manages Indexes.  Good description, eh?
    * I should win a Pulitzer Prize for that one.
    */
   
   public final class IndexManager extends SimpleConfigurable {
  -   private static final String[] EmptyStrings = new String[0];
  -   private static final IndexerInfo[] EmptyIndexerInfo = new IndexerInfo[0];
  +    private static final String[] EmptyStrings = new String[0];
  +    private static final IndexerInfo[] EmptyIndexerInfo = new IndexerInfo[0];
   
  -   private static final String INDEX = "index";
  -   private static final String NAME = "name";
  -   private static final String CLASS = "class";
  -
  -   private static final int STATUS_READY = 0;
  -   private static final int STATUS_BUSY = 1;
  -   // private static final int STATUS_DELETED = 2;
  -
  -   private static final int ACTION_CREATE = 0;
  -   private static final int ACTION_UPDATE = 1;
  -   private static final int ACTION_DELETE = 2;
  -
  -   private static Log log = LogFactory.getLog("org.apache.xindice.core");
  -
  -    private static final Timer indexTimer = new Timer( true );
  -
  -   private Map patternMap = new HashMap();   // IndexPattern to IndexerInfo
  -   private Map indexes = new HashMap();      // String to IndexerInfo
  -   private Map bestIndexers = new HashMap(); // String to SoftRefTab
  -                                             // of IndexPattern to Indexer
  -
  -   private IndexerInfo[] idxList = EmptyIndexerInfo;
  -
  -   private Collection collection;
  -   private SymbolTable symbols;
  -   private List newIndexers = new ArrayList(); // of IndexerInfo
  -
  -   public IndexManager(Collection collection) {
  -      this.collection = collection;
  -      try {
  -         symbols = collection.getSymbols();
  -      }
  -      catch ( Exception e ) {
  -         if (log.isDebugEnabled()) {
  -            log.debug("No message", e);
  -         }
  -      }
  -   }
  -
  -   public void setConfig(Configuration config) throws XindiceException {
  -      super.setConfig(config);
  -
  -      try {
  -         config.processChildren(INDEX,
  -            new ConfigurationCallback() {
  -               public void process(Configuration cfg) {
  -                  String className = cfg.getAttribute(CLASS);
  -                  try {
  -                     register(Class.forName(className), cfg);
  -                  }
  -                  catch ( Exception e ) {
  -                     if (log.isDebugEnabled()) {
  -                        log.debug("No message", e);
  -                     }
  -                  }
  -               }
  -         });
  -      }
  -      catch ( Exception e ) {
  -         if (log.isWarnEnabled()) {
  -            log.warn("setConfig", e);
  -         }
  -      }
  -   }
  -
  -   /**
  -    * list returns a list of the Indexers that this IndexerManager has
  -    * registered.
  -    *
  -    * @return An array containing the Indexer names
  -    */
  -   public String[] list() {
  -      return (String[])indexes.keySet().toArray(EmptyStrings);
  -   }
  -
  -   /**
  -    * drop physically removes the specified Indexer and any
  -    * associated system resources that the Indexer uses.
  -    *
  -    * @param name The Indexer to drop
  -    * @return Whether or not the Indexer was dropped
  -    */
  -   public boolean drop(final String name) {
  -      Indexer idx = get(name);
  -      unregister(name);
  -      config.processChildren(INDEX,
  -         new ConfigurationCallback() {
  +    private static final String INDEX = "index";
  +    private static final String NAME = "name";
  +    private static final String CLASS = "class";
  +
  +    private static final int STATUS_READY = 0;
  +    private static final int STATUS_BUSY = 1;
  +    // private static final int STATUS_DELETED = 2;
  +
  +    private static final int ACTION_CREATE = 0;
  +    private static final int ACTION_UPDATE = 1;
  +    private static final int ACTION_DELETE = 2;
  +
  +    private static Log log = LogFactory.getLog("org.apache.xindice.core");
  +
  +    private static final Timer indexTimer = new Timer(true);
  +
  +    private Map patternMap = new HashMap(); // IndexPattern to IndexerInfo
  +    private Map indexes = new HashMap(); // String to IndexerInfo
  +    private Map bestIndexers = new HashMap(); // String to SoftRefTab
  +    // of IndexPattern to Indexer
  +
  +    private IndexerInfo[] idxList = EmptyIndexerInfo;
  +
  +    private Collection collection;
  +    private SymbolTable symbols;
  +    private List newIndexers = new ArrayList(); // of IndexerInfo
  +
  +    public IndexManager(Collection collection) {
  +        this.collection = collection;
  +        try {
  +            symbols = collection.getSymbols();
  +        }
  +        catch (Exception e) {
  +            log.warn(e);
  +        }
  +    }
  +
  +    public void setConfig(Configuration config) throws XindiceException {
  +        super.setConfig(config);
  +
  +        try {
  +            config.processChildren(INDEX, new ConfigurationCallback() {
  +                public void process(Configuration cfg) {
  +                    String className = cfg.getAttribute(CLASS);
  +                    try {
  +                        register(Class.forName(className), cfg);
  +                    }
  +                    catch (Exception e) {
  +                        log.warn(e);
  +                    }
  +                }
  +            });
  +        }
  +        catch (Exception e) {
  +            if (log.isWarnEnabled()) {
  +                log.warn("setConfig", e);
  +            }
  +        }
  +    }
  +
  +    /**
  +     * list returns a list of the Indexers that this IndexerManager has
  +     * registered.
  +     *
  +     * @return An array containing the Indexer names
  +     */
  +    public String[] list() {
  +        return (String[]) indexes.keySet().toArray(EmptyStrings);
  +    }
  +
  +    /**
  +     * drop physically removes the specified Indexer and any
  +     * associated system resources that the Indexer uses.
  +     *
  +     * @param name The Indexer to drop
  +     * @return Whether or not the Indexer was dropped
  +     */
  +    public boolean drop(final String name) {
  +        Indexer idx = get(name);
  +        unregister(name);
  +        config.processChildren(INDEX, new ConfigurationCallback() {
               public void process(Configuration cfg) {
  -               try {
  -                  if ( cfg.getAttribute(NAME).equals(name) )
  -                     cfg.delete();
  -               }
  -               catch ( Exception e ) {
  -                  if (log.isDebugEnabled()) {
  -                     log.debug("No message", e);
  -                  }
  -               }
  -            }
  -      });
  -
  -      boolean res = false;
  -      try {
  -         res = idx.drop();
  -      }
  -      catch ( Exception e ) {
  -         if (log.isDebugEnabled()) {
  -            log.debug("No message", e);
  -         }
  -      }
  -      return res;
  -   }
  -
  -   /**
  -    * create creates a new Indexer object and any associated
  -    * system resources that the Indexer will need.
  -    *
  -    * @param cfg The Indexer's configuration
  -    * @return The Indexer that was created
  -    */
  -   public Indexer create(Configuration cfg) throws DBException {
  -      String className = cfg.getAttribute(CLASS);
  -      try {
  -         // Check for duplicates
  -         String name = cfg.getAttribute(NAME);
  -         Configuration[] cfgs = config.getChildren();
  -         for ( int i = 0; i < cfgs.length; i++ )
  -            if ( cfgs[i].getAttribute(NAME).equals(name) )
  -               throw new DuplicateIndexException("Duplicate Index '"+name+"'");
  -
  -         config.add(cfg);
  -         
  -         Class c = Class.forName(className);
  -         Indexer idx = register(c, cfg);
  -
  -         return idx;
  -      }
  -      catch ( DBException e ) {
  -         throw e;
  -      }
  -      catch ( Exception e ) {
  -         throw new CannotCreateException("Cannot create Index", e);
  -      }
  -   }
  -
  -   public Indexer register(Class c, Configuration cfg) throws DBException {
  -      String name = null;
  -      try {
  -         Indexer idx = (Indexer)c.newInstance();
  -         initialize(idx, cfg);
  -         name = idx.getName();
  -         
  -         if ( name == null || name.trim().equals("") )
  -            throw new CannotCreateException("No name specified");
  -
  -         IndexPattern pattern = new IndexPattern(symbols, idx.getPattern(), null);
  -         String style = idx.getIndexStyle();
  -         IndexerInfo info = new IndexerInfo(name, style, pattern, idx);
  -
  -         if ( !idx.exists() ) {
  -            info.status = STATUS_BUSY;
  -	    synchronized ( newIndexers ) {
  -		newIndexers.add(info);
  -	    }
  -	    indexTimer.schedule( new PopulateIndexersTimerTask( this ), 0 );
  -         }
  -         else {
  -            info.status = STATUS_READY;
  -            idx.open();
  -         }
  +                try {
  +                    if (cfg.getAttribute(NAME).equals(name))
  +                        cfg.delete();
  +                }
  +                catch (Exception e) {
  +                    log.warn(e);
  +                }
  +            }
  +        });
  +
  +        boolean res = false;
  +        try {
  +            res = idx.drop();
  +        }
  +        catch (Exception e) {
  +            log.warn(e);
  +        }
  +        return res;
  +    }
  +
  +    /**
  +     * create creates a new Indexer object and any associated
  +     * system resources that the Indexer will need.
  +     *
  +     * @param cfg The Indexer's configuration
  +     * @return The Indexer that was created
  +     */
  +    public Indexer create(Configuration cfg) throws DBException {
  +        String className = cfg.getAttribute(CLASS);
  +        try {
  +            // Check for duplicates
  +            String name = cfg.getAttribute(NAME);
  +            Configuration[] cfgs = config.getChildren();
  +            for (int i = 0; i < cfgs.length; i++)
  +                if (cfgs[i].getAttribute(NAME).equals(name))
  +                    throw new DuplicateIndexException("Duplicate Index '" + name + "'");
  +
  +            config.add(cfg);
  +
  +            Class c = Class.forName(className);
  +            Indexer idx = register(c, cfg);
  +
  +            return idx;
  +        }
  +        catch (DBException e) {
  +            throw e;
  +        }
  +        catch (Exception e) {
  +            throw new CannotCreateException("Cannot create Index", e);
  +        }
  +    }
  +
  +    public Indexer register(Class c, Configuration cfg) throws DBException {
  +        String name = null;
  +        try {
  +            Indexer idx = (Indexer) c.newInstance();
  +            initialize(idx, cfg);
  +            name = idx.getName();
  +
  +            if (name == null || name.trim().equals(""))
  +                throw new CannotCreateException("No name specified");
  +
  +            IndexPattern pattern = new IndexPattern(symbols, idx.getPattern(), null);
  +            String style = idx.getIndexStyle();
  +            IndexerInfo info = new IndexerInfo(name, style, pattern, idx);
  +
  +            if (!idx.exists()) {
  +                info.status = STATUS_BUSY;
  +                synchronized (newIndexers) {
  +                    newIndexers.add(info);
  +                }
  +                indexTimer.schedule(new PopulateIndexersTimerTask(this), 0);
  +            }
  +            else {
  +                info.status = STATUS_READY;
  +                idx.open();
  +            }
   
  -         indexes.put(name, info);
  -         patternMap.put(pattern, info);
  +            indexes.put(name, info);
  +            patternMap.put(pattern, info);
   
  -         Map tbl = (Map)bestIndexers.get(style);
  -         if ( tbl == null ) {
  +            Map tbl = (Map) bestIndexers.get(style);
  +            if (tbl == null) {
  +                tbl = new WeakHashMap();
  +                bestIndexers.put(style, tbl);
  +            }
  +            tbl.clear();
  +            idxList = (IndexerInfo[]) indexes.values().toArray(EmptyIndexerInfo);
  +
  +            return idx;
  +        }
  +        catch (DBException e) {
  +            throw e;
  +        }
  +        catch (Exception e) {
  +            throw new CannotCreateException("Cannot create Index '" + name + "'", e);
  +        }
  +    }
  +
  +    public void unregister(String name) {
  +        IndexerInfo idx = (IndexerInfo) indexes.remove(name);
  +        String style = idx.style;
  +        patternMap.remove(idx.pattern);
  +
  +        Map tbl = (Map) bestIndexers.get(style);
  +        if (tbl == null) {
               tbl = new WeakHashMap();
               bestIndexers.put(style, tbl);
  -         }
  -         tbl.clear();
  -         idxList = (IndexerInfo[])indexes.values().toArray(EmptyIndexerInfo);
  -         
  -         return idx;
  -      }
  -      catch ( DBException e ) {
  -         throw e;
  -      }
  -      catch ( Exception e ) {
  -         throw new CannotCreateException("Cannot create Index '"+name+"'", e);
  -      }
  -   }
  -
  -   public void unregister(String name) {
  -      IndexerInfo idx = (IndexerInfo)indexes.remove(name);
  -      String style = idx.style;
  -      patternMap.remove(idx.pattern);
  -
  -      Map tbl = (Map)bestIndexers.get(style);
  -      if ( tbl == null ) {
  -         tbl = new WeakHashMap();
  -         bestIndexers.put(style, tbl);
  -      }
  -      tbl.clear();
  -
  -      idxList = (IndexerInfo[])indexes.values().toArray(EmptyIndexerInfo);
  -   }
  -
  -   private void initialize(Indexer idx, Configuration cfg) throws XindiceException {
  -      idx.setCollection(collection);
  -      idx.setConfig(cfg);
  -   }
  -
  -   private void populateNewIndexers() throws DBException {
  -       IndexerInfo[] list = null;
  -       synchronized ( newIndexers ) {
  -	   list = (IndexerInfo[])newIndexers.toArray(EmptyIndexerInfo);
  -	   newIndexers.clear();
  -       }
  -
  -      if ( list.length > 0 ) {
  -         if ( true ) {
  -            if (log.isDebugEnabled()) {
  -               for ( int i = 0; i < list.length; i++ ) {
  -                  log.debug("Index Creation: "+list[i].indexer.getName());
  -               }
  -            }
  -         }
  -         
  -org.apache.xindice.Stopwatch sw = new org.apache.xindice.Stopwatch("Populated Indexes", true);
  -         for ( int i = 0; i < list.length; i++ ) {
  -            try {
  -               if ( !list[i].indexer.exists() )
  -                  list[i].indexer.create();
  -               list[i].indexer.open();
  -            }
  -            catch ( Exception e ) {
  -               if (log.isDebugEnabled()) {
  -                  log.debug("No message", e);
  -               }
  -            }
  -         }
  -         
  -         RecordSet rs = collection.getFiler().getRecordSet();
  -         while ( rs.hasMoreRecords() ) {
  -            Record rec = rs.getNextRecord();
  -
  -            if ( rec == null )
  -               continue;
  -            
  -            Key key = rec.getKey();
  -            Document doc = new DocumentImpl(rec.getValue().getData(), symbols, new NodeSource(collection, key));
  -            try {
  -               new SAXHandler(key, doc, ACTION_CREATE, list);
  -            }
  -            catch ( Exception e ) {
  -               if (log.isDebugEnabled()) {
  -                  log.debug("No message", e);
  -               }
  -            }
  -         }
  +        }
  +        tbl.clear();
   
  -         for ( int i = 0; i < list.length; i++ ) {
  -            try {
  -               list[i].indexer.flush();
  -            }
  -            catch ( Exception e ) {
  -               if (log.isDebugEnabled()) {
  -                  log.debug("No message", e);
  -               }
  -            }
  -            list[i].status = STATUS_READY;
  -         }
  -sw.stop();
  -         
  -         if ( true ) {
  -            if (log.isDebugEnabled()) {
  -               for ( int i = 0; i < list.length; i++ ) {
  -                  log.debug("Index Complete: "+list[i].indexer.getName());
  -               }
  -               log.debug(sw.toString());
  -            }
  -         }
  -      }
  -   }
  -
  -   /**
  -    * get retrieves an Indexer by name.
  -    *
  -    * @param name The Indexer name
  -    * @return The Indexer
  -    */
  -   public Indexer get(String name) {
  -      IndexerInfo info = (IndexerInfo)indexes.get(name);
  -      return info != null ? info.indexer
  -                          : null;
  -   }
  -
  -   /**
  -    * getBestIndexer retrieves the best Indexer to use for the specified
  -    * IndexPattern.
  -    *
  -    * @param style The Indexer Style (ex: Node, Value)
  -    * @param pattern The IndexPattern to use
  -    * @return The best Indexer (or null)
  -    */
  -   public Indexer getBestIndexer(String style, IndexPattern pattern) {
  -      Map tbl = (Map)bestIndexers.get(style);
  -      if ( tbl == null ) {
  -         tbl = new WeakHashMap();
  -         bestIndexers.put(style, tbl);
  -      }
  -      Indexer idx = (Indexer)tbl.get(pattern);
  -      if ( idx == null ) {
  -         int highScore = 0;
  -         Iterator enum = indexes.values().iterator();
  -         while ( enum.hasNext() ) {
  -            IndexerInfo info = (IndexerInfo)enum.next();
  -            if ( info.status != STATUS_READY
  -              || !info.indexer.getIndexStyle().equals(style) )
  -               continue;
  -            int score = pattern.getMatchLevel(info.pattern);
  -            if ( score > highScore ) {
  -               idx = info.indexer;
  -               highScore = score;
  -            }
  -         }
  -         tbl.put(pattern, idx);
  -      }
  -      return idx;
  -   }
  -   
  -   public void addDocument(Key key, Document doc) {
  -      if ( idxList.length > 0 ) {
  -         new SAXHandler(key, doc, ACTION_CREATE);
  -         for ( int i = 0; i < idxList.length; i++ ) {
  -            try {
  -               idxList[i].indexer.flush();
  -            }
  -            catch ( Exception e ) {
  -            }
  -         }
  -      }
  -   }
  -
  -   public void removeDocument(Key key, Document doc) {
  -      if ( idxList.length > 0 ) {
  -         new SAXHandler(key, doc, ACTION_DELETE);
  -         for ( int i = 0; i < idxList.length; i++ ) {
  -            try {
  -               idxList[i].indexer.flush();
  -            }
  -            catch ( Exception e ) {
  -            }
  -         }
  -      }
  -   }
  -
  -
  -   /**
  -    * IndexerInfo
  -    */
  -
  -   private class IndexerInfo {
  -      public String name;
  -      public String style;
  -      public IndexPattern pattern;
  -      public Indexer indexer;
  -      public int status;
  -
  -      public IndexerInfo(String name, String style, IndexPattern pattern, Indexer indexer) {
  -         this.name = name;
  -         this.style = style;
  -         this.pattern = pattern;
  -         this.indexer = indexer;
  -      }
  -   }
  -
  -
  -   /**
  -    * SAXHandler actually performs the work of adding and removing Indexer
  -    * entries.
  -    */
  -
  -   private class SAXHandler implements ContentHandler, CompressionHandler {
  -      private ObjectStack stack = new ObjectStack();
  -      private IndexerInfo[] list;
  -
  -      public Key key;
  -      public Document doc;
  -      public int action;
  -
  -      public StackInfo info; // Current State
  -
  -      public SAXHandler(Key key, Document doc, int action, IndexerInfo[] list) {
  -         this.list = list;
  -         this.key = key;
  -         this.doc = doc;
  -         this.action = action;
  -
  -         try {
  -            SAXEventGenerator events = new SAXEventGenerator(doc);
  -            events.setContentHandler(this);
  -            events.setProperty(HANDLER, this);
  -            events.start();
  -            
  -            if ( action == ACTION_CREATE || action == ACTION_UPDATE ) {
  -               try {
  -                  collection.flushSymbolTable();
  -               }
  -               catch ( Exception e ) {
  -               }
  -            }
  -         }
  -         catch ( Exception e ) {
  -            if (log.isDebugEnabled()) {
  -               log.debug("No message", e);
  -            }
  -         }
  -      }
  -      
  -      public SAXHandler(Key key, Document doc, int action) {
  -         this(key, doc, action, idxList);
  -      }
  -
  -      // These are all NO-OPs
  -      public void setDocumentLocator(Locator locator) {}
  -      public void startDocument() {}
  -      public void endDocument() {}
  -      public void startPrefixMapping(String prefix, String uri) {}
  -      public void endPrefixMapping(String prefix) {}
  -      public void ignorableWhitespace(char ch[], int start, int length) {}
  -      public void processingInstruction(String target, String data) {}
  -      public void skippedEntity(String name) {}
  -      public void symbols(SymbolTable symbols) {}
  -      public void dataBytes(byte[] data) {}
  -
  -      public void processEntry(IndexPattern pattern, String value, int pos, int len) {
  -         for ( int i = 0; i < list.length; i++ ) {
  -            if ( pattern.getMatchLevel(list[i].pattern) > 0 ) {
  -               try {
  -                  switch ( action ) {
  -                     case ACTION_CREATE:
  -                     case ACTION_UPDATE:
  -                        list[i].indexer.add(value, key, pos, len, pattern.getElementID(), pattern.getAttributeID());
  -                        break;
  -                     case ACTION_DELETE:
  -                        list[i].indexer.remove(value, key, pos, len, pattern.getElementID(), pattern.getAttributeID());
  -                        break;
  -                  }
  -               }
  -               catch ( Exception e ) {
  -                  if (log.isDebugEnabled()) {
  -                     log.debug("No message", e);
  -                  }
  -               }
  -            }
  -         }
  -      }
  -
  -      public void startElement(String namespaceURI, String localName, String qName, Attributes atts) {
  -         // Modify the stack info to normalize the symbolID
  -         if ( namespaceURI != null && namespaceURI.length() > 0 ) {
  -            String elemNSID = SymbolTable.getNormalizedLocalName(localName, namespaceURI);
  -            info.symbolID = symbols.getSymbol(elemNSID, namespaceURI, true);
  -         }
  -         
  -         int size = atts.getLength();
  -         for ( int i = 0; i < size; i++ ) {
  -            String nsURI = atts.getURI(i);
  -            if ( nsURI != null && nsURI.length() > 0 ) {
  -               String attrNSID = "ns"+Integer.toString(nsURI.hashCode())+":"+atts.getLocalName(i);
  -               short id = symbols.getSymbol(attrNSID, nsURI, true);
  -               processEntry(new IndexPattern(symbols, info.symbolID, id), atts.getValue(i), info.pos, info.len);
  -            }
  -            else {
  -               short id = symbols.getSymbol(atts.getQName(i));
  -               processEntry(new IndexPattern(symbols, info.symbolID, id), atts.getValue(i), info.pos, info.len);
  -            }
  -         }
  -      }
  +        idxList = (IndexerInfo[]) indexes.values().toArray(EmptyIndexerInfo);
  +    }
   
  -      public void endElement(String namespaceURI, String localName, String qName) {
  -         if ( info.sb != null )
  -            processEntry(new IndexPattern(symbols, info.symbolID), info.sb.toString(), info.pos, info.len);
  -         info = (StackInfo)stack.pop();
  -      }
  -
  -      public void characters(char ch[], int start, int length) {
  -         String val = new String(ch).trim();
  -         if ( info.sb == null )
  -            info.sb = new StringBuffer(ch.length);
  -         else if ( info.sb.length() > 0 )
  -            info.sb.append(' ');
  -         info.sb.append(val);
  -      }
  -
  -      public void symbolID(short symbolID) {
  -         if ( info != null )
  -            stack.push(info);
  -         info = new StackInfo(symbolID);
  -      }
  -
  -      public void dataLocation(int pos, int len) {
  -         info.pos = pos;
  -         info.len = len;
  -      }
  -   }
  -
  -
  -   /**
  -    * StackInfo
  -    */
  -
  -   private class StackInfo {
  -      public short symbolID;
  -      public StringBuffer sb = null;
  -      public int pos = -1;
  -      public int len = -1;
  -
  -      public StackInfo(short symbolID) {
  -         this.symbolID = symbolID;
  -      }
  -   }
  +    private void initialize(Indexer idx, Configuration cfg) throws XindiceException {
  +        idx.setCollection(collection);
  +        idx.setConfig(cfg);
  +    }
  +
  +    private void populateNewIndexers() throws DBException {
  +        IndexerInfo[] list = null;
  +        synchronized (newIndexers) {
  +            list = (IndexerInfo[]) newIndexers.toArray(EmptyIndexerInfo);
  +            newIndexers.clear();
  +        }
  +
  +        if (list.length > 0) {
  +            if (true) {
  +                if (log.isDebugEnabled()) {
  +                    for (int i = 0; i < list.length; i++) {
  +                        log.debug("Index Creation: " + list[i].indexer.getName());
  +                    }
  +                }
  +            }
  +
  +            org.apache.xindice.Stopwatch sw = new org.apache.xindice.Stopwatch("Populated Indexes", true);
  +            for (int i = 0; i < list.length; i++) {
  +                try {
  +                    if (!list[i].indexer.exists())
  +                        list[i].indexer.create();
  +                    list[i].indexer.open();
  +                }
  +                catch (Exception e) {
  +                    log.warn(e);
  +                }
  +            }
  +
  +            RecordSet rs = collection.getFiler().getRecordSet();
  +            while (rs.hasMoreRecords()) {
  +                Record rec = rs.getNextRecord();
  +
  +                if (rec == null)
  +                    continue;
  +
  +                Key key = rec.getKey();
  +                Document doc = new DocumentImpl(rec.getValue().getData(), symbols, new NodeSource(collection, key));
  +                try {
  +                    new SAXHandler(key, doc, ACTION_CREATE, list);
  +                }
  +                catch (Exception e) {
  +                    log.warn(e);
  +                }
  +            }
  +
  +            for (int i = 0; i < list.length; i++) {
  +                try {
  +                    list[i].indexer.flush();
  +                }
  +                catch (Exception e) {
  +                    log.warn(e);
  +                }
  +                list[i].status = STATUS_READY;
  +            }
  +            sw.stop();
  +
  +            if (true) {
  +                if (log.isDebugEnabled()) {
  +                    for (int i = 0; i < list.length; i++) {
  +                        log.debug("Index Complete: " + list[i].indexer.getName());
  +                    }
  +                    log.debug(sw.toString());
  +                }
  +            }
  +        }
  +    }
  +
  +    /**
  +     * get retrieves an Indexer by name.
  +     *
  +     * @param name The Indexer name
  +     * @return The Indexer
  +     */
  +    public Indexer get(String name) {
  +        IndexerInfo info = (IndexerInfo) indexes.get(name);
  +        return info != null ? info.indexer : null;
  +    }
  +
  +    /**
  +     * getBestIndexer retrieves the best Indexer to use for the specified
  +     * IndexPattern.
  +     *
  +     * @param style The Indexer Style (ex: Node, Value)
  +     * @param pattern The IndexPattern to use
  +     * @return The best Indexer (or null)
  +     */
  +    public Indexer getBestIndexer(String style, IndexPattern pattern) {
  +        Map tbl = (Map) bestIndexers.get(style);
  +        if (tbl == null) {
  +            tbl = new WeakHashMap();
  +            bestIndexers.put(style, tbl);
  +        }
  +        Indexer idx = (Indexer) tbl.get(pattern);
  +        if (idx == null) {
  +            int highScore = 0;
  +            Iterator enum = indexes.values().iterator();
  +            while (enum.hasNext()) {
  +                IndexerInfo info = (IndexerInfo) enum.next();
  +                if (info.status != STATUS_READY || !info.indexer.getIndexStyle().equals(style))
  +                    continue;
  +                int score = pattern.getMatchLevel(info.pattern);
  +                if (score > highScore) {
  +                    idx = info.indexer;
  +                    highScore = score;
  +                }
  +            }
  +            tbl.put(pattern, idx);
  +        }
  +        return idx;
  +    }
  +
  +    public void addDocument(Key key, Document doc) {
  +        if (idxList.length > 0) {
  +            new SAXHandler(key, doc, ACTION_CREATE);
  +            for (int i = 0; i < idxList.length; i++) {
  +                try {
  +                    idxList[i].indexer.flush();
  +                }
  +                catch (Exception e) {}
  +            }
  +        }
  +    }
  +
  +    public void removeDocument(Key key, Document doc) {
  +        if (idxList.length > 0) {
  +            new SAXHandler(key, doc, ACTION_DELETE);
  +            for (int i = 0; i < idxList.length; i++) {
  +                try {
  +                    idxList[i].indexer.flush();
  +                }
  +                catch (Exception e) {}
  +            }
  +        }
  +    }
  +
  +    /**
  +     * IndexerInfo
  +     */
  +
  +    private class IndexerInfo {
  +        public String name;
  +        public String style;
  +        public IndexPattern pattern;
  +        public Indexer indexer;
  +        public int status;
  +
  +        public IndexerInfo(String name, String style, IndexPattern pattern, Indexer indexer) {
  +            this.name = name;
  +            this.style = style;
  +            this.pattern = pattern;
  +            this.indexer = indexer;
  +        }
  +    }
  +
  +    /**
  +     * SAXHandler actually performs the work of adding and removing Indexer
  +     * entries.
  +     */
  +
  +    private class SAXHandler implements ContentHandler, CompressionHandler {
  +        private ObjectStack stack = new ObjectStack();
  +        private IndexerInfo[] list;
  +
  +        public Key key;
  +        public Document doc;
  +        public int action;
  +
  +        public StackInfo info; // Current State
  +
  +        public SAXHandler(Key key, Document doc, int action, IndexerInfo[] list) {
  +            this.list = list;
  +            this.key = key;
  +            this.doc = doc;
  +            this.action = action;
   
  +            try {
  +                SAXEventGenerator events = new SAXEventGenerator(doc);
  +                events.setContentHandler(this);
  +                events.setProperty(HANDLER, this);
  +                events.start();
  +
  +                if (action == ACTION_CREATE || action == ACTION_UPDATE) {
  +                    try {
  +                        collection.flushSymbolTable();
  +                    }
  +                    catch (Exception e) {}
  +                }
  +            }
  +            catch (Exception e) {
  +                log.warn(e);
  +            }
  +        }
  +
  +        public SAXHandler(Key key, Document doc, int action) {
  +            this(key, doc, action, idxList);
  +        }
  +
  +        // These are all NO-OPs
  +        public void setDocumentLocator(Locator locator) {}
  +        public void startDocument() {}
  +        public void endDocument() {}
  +        public void startPrefixMapping(String prefix, String uri) {}
  +        public void endPrefixMapping(String prefix) {}
  +        public void ignorableWhitespace(char ch[], int start, int length) {}
  +        public void processingInstruction(String target, String data) {}
  +        public void skippedEntity(String name) {}
  +        public void symbols(SymbolTable symbols) {}
  +        public void dataBytes(byte[] data) {}
  +
  +        public void processEntry(IndexPattern pattern, String value, int pos, int len) {
  +            for (int i = 0; i < list.length; i++) {
  +                if (pattern.getMatchLevel(list[i].pattern) > 0) {
  +                    try {
  +                        switch (action) {
  +                            case ACTION_CREATE :
  +                            case ACTION_UPDATE :
  +                                list[i].indexer.add(value, key, pos, len, pattern.getElementID(), pattern.getAttributeID());
  +                                break;
  +                            case ACTION_DELETE :
  +                                list[i].indexer.remove(value, key, pos, len, pattern.getElementID(), pattern.getAttributeID());
  +                                break;
  +                        }
  +                    }
  +                    catch (Exception e) {
  +                        log.warn(e);
  +                    }
  +                }
  +            }
  +        }
  +
  +        public void startElement(String namespaceURI, String localName, String qName, Attributes atts) {
  +            // Modify the stack info to normalize the symbolID
  +            if (namespaceURI != null && namespaceURI.length() > 0) {
  +                String elemNSID = SymbolTable.getNormalizedLocalName(localName, namespaceURI);
  +                info.symbolID = symbols.getSymbol(elemNSID, namespaceURI, true);
  +            }
  +
  +            int size = atts.getLength();
  +            for (int i = 0; i < size; i++) {
  +                String nsURI = atts.getURI(i);
  +                if (nsURI != null && nsURI.length() > 0) {
  +                    String attrNSID = "ns" + Integer.toString(nsURI.hashCode()) + ":" + atts.getLocalName(i);
  +                    short id = symbols.getSymbol(attrNSID, nsURI, true);
  +                    processEntry(new IndexPattern(symbols, info.symbolID, id), atts.getValue(i), info.pos, info.len);
  +                }
  +                else {
  +                    short id = symbols.getSymbol(atts.getQName(i));
  +                    processEntry(new IndexPattern(symbols, info.symbolID, id), atts.getValue(i), info.pos, info.len);
  +                }
  +            }
  +        }
  +
  +        public void endElement(String namespaceURI, String localName, String qName) {
  +            if (info.sb != null)
  +                processEntry(new IndexPattern(symbols, info.symbolID), info.sb.toString(), info.pos, info.len);
  +            info = (StackInfo) stack.pop();
  +        }
  +
  +        public void characters(char ch[], int start, int length) {
  +            String val = new String(ch).trim();
  +            if (info.sb == null)
  +                info.sb = new StringBuffer(ch.length);
  +            else if (info.sb.length() > 0)
  +                info.sb.append(' ');
  +            info.sb.append(val);
  +        }
  +
  +        public void symbolID(short symbolID) {
  +            if (info != null)
  +                stack.push(info);
  +            info = new StackInfo(symbolID);
  +        }
  +
  +        public void dataLocation(int pos, int len) {
  +            info.pos = pos;
  +            info.len = len;
  +        }
  +    }
  +
  +    /**
  +     * StackInfo
  +     */
  +
  +    private class StackInfo {
  +        public short symbolID;
  +        public StringBuffer sb = null;
  +        public int pos = -1;
  +        public int len = -1;
  +
  +        public StackInfo(short symbolID) {
  +            this.symbolID = symbolID;
  +        }
  +    }
   
       private static class PopulateIndexersTimerTask extends TimerTask {
  -	private IndexManager mgr;
  -	public PopulateIndexersTimerTask( IndexManager mgr ) {
  -	    this.mgr = mgr;
  -	}
  -	public void run() {
  -	    try {
  -		mgr.populateNewIndexers();
  -	    }
  -	    catch ( DBException e ) {
  -           if (log.isDebugEnabled()) {
  -              log.debug("No message", e);
  -           }
  -	    }
  -	}
  +        private IndexManager mgr;
  +        public PopulateIndexersTimerTask(IndexManager mgr) {
  +            this.mgr = mgr;
  +        }
  +        public void run() {
  +            try {
  +                mgr.populateNewIndexers();
  +            }
  +            catch (DBException e) {
  +                log.warn(e);
  +
  +            }
  +        }
       }
   }
  
  
  
  1.8       +121 -136  xml-xindice/java/src/org/apache/xindice/core/indexer/NameIndexer.java
  
  Index: NameIndexer.java
  ===================================================================
  RCS file: /home/cvs/xml-xindice/java/src/org/apache/xindice/core/indexer/NameIndexer.java,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- NameIndexer.java	19 Nov 2002 05:16:58 -0000	1.7
  +++ NameIndexer.java	15 Jul 2003 15:44:36 -0000	1.8
  @@ -59,6 +59,13 @@
    * $Id$
    */
   
  +import java.io.File;
  +import java.io.IOException;
  +import java.util.ArrayList;
  +import java.util.List;
  +
  +import org.apache.commons.logging.Log;
  +import org.apache.commons.logging.LogFactory;
   import org.apache.xindice.core.Collection;
   import org.apache.xindice.core.DBException;
   import org.apache.xindice.core.data.Key;
  @@ -69,14 +76,6 @@
   import org.apache.xindice.util.Configuration;
   import org.apache.xindice.xml.SymbolTable;
   
  -import org.apache.commons.logging.Log;
  -import org.apache.commons.logging.LogFactory;
  -
  -import java.io.File;
  -import java.io.IOException;
  -import java.util.ArrayList;
  -import java.util.List;
  -
   /**
    * NameIndexer is a basic implementation of the Indexer interface.
    * It is used for maintaining element and element@attribute unique
  @@ -84,133 +83,119 @@
    */
   
   public final class NameIndexer extends BTree implements Indexer {
  -   private static final IndexMatch[] EmptyMatches = new IndexMatch[0];
  +    private static final IndexMatch[] EmptyMatches = new IndexMatch[0];
   
  -   private static final String NAME = "name";
  -   private static final String PATTERN = "pattern";
  -   private static final String PAGESIZE = "pagesize";
  -   private static final String MAXKEYSIZE = "maxkeysize";
  -
  -   private static Log log = LogFactory.getLog("org.apache.xindice.core");
  -
  -   private Configuration config;
  -   private Collection collection;
  -   private SymbolTable symbols;
  -
  -   private String name;
  -   private String pattern;
  -   private boolean wildcard = false;
  -
  -   private FileHeader fileHeader;
  -
  -   public NameIndexer() {
  -      super();
  -      fileHeader = getFileHeader();
  -   }
  -
  -   public void setConfig(Configuration config) {
  -      this.config = config;
  -      try {
  -         name = config.getAttribute(NAME);
  -
  -         pattern = config.getAttribute(PATTERN);
  -         wildcard = pattern.indexOf('*') != -1;
  -
  -         fileHeader.setPageSize(config.getIntAttribute(PAGESIZE, fileHeader.getPageSize()));
  -         fileHeader.setMaxKeySize(config.getShortAttribute(MAXKEYSIZE, fileHeader.getMaxKeySize()));
  -
  -         setLocation(name);
  -      }
  -      catch ( Exception e ) {
  -         if (log.isDebugEnabled()) {
  -            log.debug("No message", e);
  -         }
  -      }
  -   }
  -
  -   public Configuration getConfig() {
  -      return config;
  -   }
  -
  -   public String getName() {
  -      return name;
  -   }
  -
  -   public void setLocation(String location) {
  -      setFile(new File(collection.getCollectionRoot(), location+".idx"));
  -   }
  -
  -   public void setCollection(Collection collection) {
  -      try {
  -         this.collection = collection;
  -         symbols = collection.getSymbols();
  -      }
  -      catch ( Exception e ) {
  -         if (log.isDebugEnabled()) {
  -            log.debug("No message", e);
  -         }
  -      }
  -   }
  -
  -   public String getIndexStyle() {
  -      return STYLE_NODENAME;
  -   }
  -
  -   public String getPattern() {
  -      return pattern;
  -   }
  -
  -   public void remove(String value, Key key, int pos, int len, short elemID, short attrID) throws DBException {
  -      try {
  -         removeValue(key);
  -      }
  -      catch ( IOException e ) {
  -         throw new BTreeCorruptException("Corruption detected on remove", e);
  -      }
  -   }
  -
  -   public void add(String value, Key key, int pos, int len, short elemID, short attrID) throws DBException {
  -      try {
  -         addValue(key, 0);
  -      }
  -      catch ( IOException e ) {
  -         throw new BTreeCorruptException("Corruption detected on add", e);
  -      }
  -   }
  -
  -   public void flush() throws DBException {
  -      super.flush();
  -   }
  -
  -   public IndexMatch[] queryMatches(final IndexQuery query) throws DBException {
  -      final List results = new ArrayList();
  -      final IndexPattern pattern = query.getPattern();
  -
  -      try {
  -         query(query, new BTreeCallback() {
  -            public boolean indexInfo(Value value, long pos) {
  -               results.add(new IndexMatch(new Key(value), pattern));
  -               return true;
  -            }
  -         });
  -      }
  -      catch ( DBException e ) {
  -         throw e;
  -      }
  -      catch ( Exception e ) {
  -         if (log.isDebugEnabled()) {
  -            log.debug("No message", e);
  -         }
  -      }
  +    private static final String NAME = "name";
  +    private static final String PATTERN = "pattern";
  +    private static final String PAGESIZE = "pagesize";
  +    private static final String MAXKEYSIZE = "maxkeysize";
  +
  +    private static Log log = LogFactory.getLog("org.apache.xindice.core");
  +
  +    private Configuration config;
  +    private Collection collection;
  +    private SymbolTable symbols;
  +
  +    private String name;
  +    private String pattern;
  +    private boolean wildcard = false;
  +
  +    private FileHeader fileHeader;
  +
  +    public NameIndexer() {
  +        super();
  +        fileHeader = getFileHeader();
  +    }
  +
  +    public void setConfig(Configuration config) {
  +        this.config = config;
  +        try {
  +            name = config.getAttribute(NAME);
  +
  +            pattern = config.getAttribute(PATTERN);
  +            wildcard = pattern.indexOf('*') != -1;
  +
  +            fileHeader.setPageSize(config.getIntAttribute(PAGESIZE, fileHeader.getPageSize()));
  +            fileHeader.setMaxKeySize(config.getShortAttribute(MAXKEYSIZE, fileHeader.getMaxKeySize()));
  +
  +            setLocation(name);
  +        }
  +        catch (Exception e) {
  +            log.warn(e);
  +        }
  +    }
  +
  +    public Configuration getConfig() {
  +        return config;
  +    }
  +
  +    public String getName() {
  +        return name;
  +    }
  +
  +    public void setLocation(String location) {
  +        setFile(new File(collection.getCollectionRoot(), location + ".idx"));
  +    }
  +
  +    public void setCollection(Collection collection) {
  +        try {
  +            this.collection = collection;
  +            symbols = collection.getSymbols();
  +        }
  +        catch (Exception e) {
  +            log.warn(e);
  +        }
  +    }
  +
  +    public String getIndexStyle() {
  +        return STYLE_NODENAME;
  +    }
  +
  +    public String getPattern() {
  +        return pattern;
  +    }
  +
  +    public void remove(String value, Key key, int pos, int len, short elemID, short attrID) throws DBException {
  +        try {
  +            removeValue(key);
  +        }
  +        catch (IOException e) {
  +            throw new BTreeCorruptException("Corruption detected on remove", e);
  +        }
  +    }
  +
  +    public void add(String value, Key key, int pos, int len, short elemID, short attrID) throws DBException {
  +        try {
  +            addValue(key, 0);
  +        }
  +        catch (IOException e) {
  +            throw new BTreeCorruptException("Corruption detected on add", e);
  +        }
  +    }
  +
  +    public void flush() throws DBException {
  +        super.flush();
  +    }
  +
  +    public IndexMatch[] queryMatches(final IndexQuery query) throws DBException {
  +        final List results = new ArrayList();
  +        final IndexPattern pattern = query.getPattern();
  +
  +        try {
  +            query(query, new BTreeCallback() {
  +                public boolean indexInfo(Value value, long pos) {
  +                    results.add(new IndexMatch(new Key(value), pattern));
  +                    return true;
  +                }
  +            });
  +        }
  +        catch (DBException e) {
  +            throw e;
  +        }
  +        catch (Exception e) {
  +            log.warn(e);
  +        }
   
  -      return (IndexMatch[])results.toArray(EmptyMatches);
  -   }
  +        return (IndexMatch[]) results.toArray(EmptyMatches);
  +    }
   }
  -
  -
  -
  -
  -
  -
  -
  -
  
  
  
  1.7       +346 -351  xml-xindice/java/src/org/apache/xindice/core/indexer/ValueIndexer.java
  
  Index: ValueIndexer.java
  ===================================================================
  RCS file: /home/cvs/xml-xindice/java/src/org/apache/xindice/core/indexer/ValueIndexer.java,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- ValueIndexer.java	19 Nov 2002 05:16:58 -0000	1.6
  +++ ValueIndexer.java	15 Jul 2003 15:44:36 -0000	1.7
  @@ -59,6 +59,13 @@
    * $Id$
    */
   
  +import java.io.File;
  +import java.io.IOException;
  +import java.util.ArrayList;
  +import java.util.List;
  +
  +import org.apache.commons.logging.Log;
  +import org.apache.commons.logging.LogFactory;
   import org.apache.xindice.core.Collection;
   import org.apache.xindice.core.DBException;
   import org.apache.xindice.core.data.Key;
  @@ -71,14 +78,6 @@
   import org.apache.xindice.util.Configuration;
   import org.apache.xindice.xml.SymbolTable;
   
  -import org.apache.commons.logging.Log;
  -import org.apache.commons.logging.LogFactory;
  -
  -import java.io.File;
  -import java.io.IOException;
  -import java.util.ArrayList;
  -import java.util.List;
  -
   /**
    * ValueIndexer is a basic implementation of the Indexer interface.
    * It is used for maintaining element and element@attribute value
  @@ -86,352 +85,348 @@
    */
   
   public final class ValueIndexer extends BTree implements Indexer {
  -   private static final IndexMatch[] EmptyMatches = new IndexMatch[0];
  -   private static final Value EmptyValue = new Value(new byte[0]);
  +    private static final IndexMatch[] EmptyMatches = new IndexMatch[0];
  +    private static final Value EmptyValue = new Value(new byte[0]);
   
  -   private static final long MATCH_INFO = -1000;
  +    private static final long MATCH_INFO = -1000;
   
  -   private static final String NAME = "name";
  -   private static final String PATTERN = "pattern";
  -   private static final String TYPE = "type";
  -   private static final String PAGESIZE = "pagesize";
  -   private static final String MAXKEYSIZE = "maxkeysize";
  -
  -   private static final int STRING = 0;
  -   private static final int TRIMMED = 1;
  -   private static final int INTEGER = 2;
  -   private static final int FLOAT = 3;
  -   private static final int BYTE = 4;
  -   private static final int CHAR = 5;
  -   private static final int BOOLEAN = 6;
  -
  -   private static final int[] sizes = { -1, -1, 8, 8, 1, 2, 1 };
  -
  -   private static final String STRING_VAL = "string";
  -   private static final String TRIMMED_VAL = "trimmed";
  -   private static final String SHORT_VAL = "short";
  -   private static final String INT_VAL = "int";
  -   private static final String LONG_VAL = "long";
  -   private static final String FLOAT_VAL = "float";
  -   private static final String DOUBLE_VAL = "double";
  -   private static final String BYTE_VAL = "byte";
  -   private static final String CHAR_VAL = "char";
  -   private static final String BOOLEAN_VAL = "boolean";
  -
  -   private static Log log = LogFactory.getLog("org.apache.xindice.core");
  -
  -   private Configuration config;
  -   private Collection collection;
  -   private SymbolTable symbols;
  -
  -   private String name;
  -   private String pattern;
  -   private int type;
  -   private int typeSize = 32;
  -   private boolean wildcard = false;
  -
  -   private FileHeader fileHeader;
  -
  -   public ValueIndexer() {
  -      super();
  -      fileHeader = getFileHeader();
  -      fileHeader.setPageSize(1024);
  -   }
  -
  -   public void setConfig(Configuration config) {
  -      this.config = config;
  -      try {
  -         name = config.getAttribute(NAME);
  -
  -         pattern = config.getAttribute(PATTERN);
  -         wildcard = pattern.indexOf('*') != -1;
  -
  -         // Determine the Index Type
  -         String tv = config.getAttribute(TYPE, STRING_VAL).toLowerCase();
  -         if ( tv.equals(STRING_VAL) )       type = STRING;
  -         else if ( tv.equals(TRIMMED_VAL) ) type = TRIMMED;
  -         else if ( tv.equals(SHORT_VAL) )   type = INTEGER;
  -         else if ( tv.equals(INT_VAL) )     type = INTEGER;
  -         else if ( tv.equals(LONG_VAL) )    type = INTEGER;
  -         else if ( tv.equals(FLOAT_VAL) )   type = FLOAT;
  -         else if ( tv.equals(DOUBLE_VAL) )  type = FLOAT;
  -         else if ( tv.equals(BYTE_VAL) )    type = BYTE;
  -         else if ( tv.equals(CHAR_VAL) )    type = CHAR;
  -         else if ( tv.equals(BOOLEAN_VAL) ) type = BOOLEAN;
  -         else {
  -            if ( pattern.indexOf('@') != -1 )
  -               type = STRING;
  -            else
  -               type = TRIMMED;
  -         }
  -
  -         typeSize = sizes[type];
  -
  -         fileHeader.setPageSize(config.getIntAttribute(PAGESIZE, fileHeader.getPageSize()));
  -         fileHeader.setMaxKeySize(config.getShortAttribute(MAXKEYSIZE, fileHeader.getMaxKeySize()));
  -
  -         setLocation(name);
  -      }
  -      catch ( Exception e ) {
  -         if (log.isDebugEnabled()) {
  -            log.debug("No message", e);
  -         }
  -      }
  -   }
  -
  -   public Configuration getConfig() {
  -      return config;
  -   }
  -
  -   public String getName() {
  -      return name;
  -   }
  -
  -   public void setLocation(String location) {
  -      setFile(new File(collection.getCollectionRoot(), location+".idx"));
  -   }
  -
  -   public void setCollection(Collection collection) {
  -      try {
  -         this.collection = collection;
  -         symbols = collection.getSymbols();
  -      }
  -      catch ( Exception e ) {
  -         if (log.isDebugEnabled()) {
  -            log.debug("No message", e);
  -         }
  -      }
  -   }
  -
  -   public String getIndexStyle() {
  -      return STYLE_NODEVALUE;
  -   }
  -
  -   public String getPattern() {
  -      return pattern;
  -   }
  -
  -   public Value getTypedValue(String value) {
  -      if ( type != STRING && type != TRIMMED ) {
  -         value = value.trim();
  -
  -         if ( value.length() == 0 )
  -            return EmptyValue;
  -
  -         byte[] b = new byte[typeSize];
  -         try {
  -            switch ( type ) {
  -               case INTEGER:
  -                  long l = Long.parseLong(value);
  -                  b[0] = (byte)((l >>> 56) & 0xFF);
  -                  b[1] = (byte)((l >>> 48) & 0xFF);
  -                  b[2] = (byte)((l >>> 40) & 0xFF);
  -                  b[3] = (byte)((l >>> 32) & 0xFF);
  -                  b[4] = (byte)((l >>> 24) & 0xFF);
  -                  b[5] = (byte)((l >>> 16) & 0xFF);
  -                  b[6] = (byte)((l >>> 8) & 0xFF);
  -                  b[7] = (byte)((l >>> 0) & 0xFF);
  -                  break;
  -               case FLOAT:
  -                  double d = Double.parseDouble(value);
  -                  int i1 = (int)Math.round(d);
  -                  int i2 = (int)Math.round((d-i1)*1000000000);
  -                  b[0] = (byte)((i1 >>> 24) & 0xFF);
  -                  b[1] = (byte)((i1 >>> 16) & 0xFF);
  -                  b[2] = (byte)((i1 >>> 8) & 0xFF);
  -                  b[3] = (byte)((i1 >>> 0) & 0xFF);
  -                  b[4] = (byte)((i2 >>> 24) & 0xFF);
  -                  b[5] = (byte)((i2 >>> 16) & 0xFF);
  -                  b[6] = (byte)((i2 >>> 8) & 0xFF);
  -                  b[7] = (byte)((i2 >>> 0) & 0xFF);
  -                  break;
  -               case BYTE:
  -                  b[0] = Byte.parseByte(value);
  -                  break;
  -               case CHAR:
  -                  char c = value.charAt(0);
  -                  b[0] = (byte)((c >>> 8) & 0xFF);
  -                  b[1] = (byte)((c >>> 0) & 0xFF);
  -                  break;
  -               case BOOLEAN:
  -                  if ( "[true][yes][1][y][on]".indexOf("["+value.toString().toLowerCase()+"]") != -1 )
  -                     b[0] = 1;
  -                  else if ( "[false][no][0][n][off]".indexOf("["+value.toString().toLowerCase()+"]") != -1 )
  -                     b[0] = 0;
  -                  else
  -                     return EmptyValue;
  -                  break;
  +    private static final String NAME = "name";
  +    private static final String PATTERN = "pattern";
  +    private static final String TYPE = "type";
  +    private static final String PAGESIZE = "pagesize";
  +    private static final String MAXKEYSIZE = "maxkeysize";
  +
  +    private static final int STRING = 0;
  +    private static final int TRIMMED = 1;
  +    private static final int INTEGER = 2;
  +    private static final int FLOAT = 3;
  +    private static final int BYTE = 4;
  +    private static final int CHAR = 5;
  +    private static final int BOOLEAN = 6;
  +
  +    private static final int[] sizes = { -1, -1, 8, 8, 1, 2, 1 };
  +
  +    private static final String STRING_VAL = "string";
  +    private static final String TRIMMED_VAL = "trimmed";
  +    private static final String SHORT_VAL = "short";
  +    private static final String INT_VAL = "int";
  +    private static final String LONG_VAL = "long";
  +    private static final String FLOAT_VAL = "float";
  +    private static final String DOUBLE_VAL = "double";
  +    private static final String BYTE_VAL = "byte";
  +    private static final String CHAR_VAL = "char";
  +    private static final String BOOLEAN_VAL = "boolean";
  +
  +    private static Log log = LogFactory.getLog("org.apache.xindice.core");
  +
  +    private Configuration config;
  +    private Collection collection;
  +    private SymbolTable symbols;
  +
  +    private String name;
  +    private String pattern;
  +    private int type;
  +    private int typeSize = 32;
  +    private boolean wildcard = false;
  +
  +    private FileHeader fileHeader;
  +
  +    public ValueIndexer() {
  +        super();
  +        fileHeader = getFileHeader();
  +        fileHeader.setPageSize(1024);
  +    }
  +
  +    public void setConfig(Configuration config) {
  +        this.config = config;
  +        try {
  +            name = config.getAttribute(NAME);
  +
  +            pattern = config.getAttribute(PATTERN);
  +            wildcard = pattern.indexOf('*') != -1;
  +
  +            // Determine the Index Type
  +            String tv = config.getAttribute(TYPE, STRING_VAL).toLowerCase();
  +            if (tv.equals(STRING_VAL))
  +                type = STRING;
  +            else if (tv.equals(TRIMMED_VAL))
  +                type = TRIMMED;
  +            else if (tv.equals(SHORT_VAL))
  +                type = INTEGER;
  +            else if (tv.equals(INT_VAL))
  +                type = INTEGER;
  +            else if (tv.equals(LONG_VAL))
  +                type = INTEGER;
  +            else if (tv.equals(FLOAT_VAL))
  +                type = FLOAT;
  +            else if (tv.equals(DOUBLE_VAL))
  +                type = FLOAT;
  +            else if (tv.equals(BYTE_VAL))
  +                type = BYTE;
  +            else if (tv.equals(CHAR_VAL))
  +                type = CHAR;
  +            else if (tv.equals(BOOLEAN_VAL))
  +                type = BOOLEAN;
  +            else {
  +                if (pattern.indexOf('@') != -1)
  +                    type = STRING;
  +                else
  +                    type = TRIMMED;
               }
  -            return new Value(b);
  -         }
  -         catch ( Exception e ) {
  -            return EmptyValue;
  -         }
  -      }
  -
  -      if ( type == TRIMMED )
  -         value = QueryEngine.normalizeString(value);
  -
  -      return new Value(value);
  -   }
  -
  -   private Value getCombinedValue(Key key, int pos, int len, short elemID, short attrID) {
  -      Value result;
  -      try {
  -         int l = key.getLength();
  -         byte[] b = new byte[l+13];
  -
  -         // Write the key
  -         System.arraycopy(key.getData(), 0, b, 0, l);
  -         b[l] = 0;
  -
  -         // Write the pos
  -         b[l+1] = (byte)((pos >>> 24) & 0xFF);
  -         b[l+2] = (byte)((pos >>> 16) & 0xFF);
  -         b[l+3] = (byte)((pos >>> 8)  & 0xFF);
  -         b[l+4] = (byte)((pos >>> 0)  & 0xFF);
  -
  -         // Write the len
  -         b[l+5] = (byte)((len >>> 24) & 0xFF);
  -         b[l+6] = (byte)((len >>> 16) & 0xFF);
  -         b[l+7] = (byte)((len >>> 8)  & 0xFF);
  -         b[l+8] = (byte)((len >>> 0)  & 0xFF);
  -
  -         // Write the elemID
  -         b[l+9] = (byte)((elemID >>> 8)  & 0xFF);
  -         b[l+10] = (byte)((elemID >>> 0) & 0xFF);
  -
  -         // Write the attrID
  -         b[l+11] = (byte)((attrID >>> 8) & 0xFF);
  -         b[l+12] = (byte)((attrID >>> 0) & 0xFF);
  -
  -         result = new Value(b);
  -      }
  -      catch ( Exception e ) {
  -         result = null; // This will never happen
  -      }
  -      return result;
  -   }
  -
  -   private IndexMatch getIndexMatch(Value v) {
  -      byte[] b = v.getData();
  -      int l = b.length-13;
  -      Key key = new Key(b, 0, b.length-13);
  -
  -      int pos = ((b[l+1] << 24) | (b[l+2] << 16) | (b[l+3] << 8) | b[l+4]);
  -      int len = ((b[l+5] << 24) | (b[l+6] << 16) | (b[l+7] << 8) | b[l+8]);
  -      short elemID = (short)((b[l+9] << 8) | b[l+10]);
  -      short attrID = (short)((b[l+11] << 8) | b[l+12]);
  -
  -      return new IndexMatch(key, pos, len, elemID, attrID);
  -   }
  -
  -   public void remove(String value, Key key, int pos, int len, short elemID, short attrID) throws DBException {
  -      Value v = getTypedValue(value);
  -      if ( type != STRING && type != TRIMMED && v.getLength() == 0 )
  -         return;
  -
  -      try {
  -         BTreeRootInfo root = findBTreeRoot(v);
  -         Value cv = getCombinedValue(key, pos, len, elemID, attrID);
  -         removeValue(root, cv);
  -      }
  -      catch ( DBException e ) {
  -         throw e;
  -      }
  -      catch ( Exception e ) {
  -         if (log.isDebugEnabled()) {
  -            log.debug("No message", e);
  -         }
  -      }
  -   }
  -
  -   public void add(String value, Key key, int pos, int len, short elemID, short attrID) throws DBException {
  -      Value v = getTypedValue(value);
  -      if ( type != STRING && type != TRIMMED && v.getLength() == 0 )
  -         return;
  -
  -      try {
  -         BTreeRootInfo root;
  -
  -         try {
  -            root = findBTreeRoot(v);
  -         }
  -         catch ( BTreeNotFoundException e ) {
  -            root = createBTreeRoot(v);
  -         }
  -
  -         Value cv = getCombinedValue(key, pos, len, elemID, attrID);
  -         addValue(root, cv, MATCH_INFO);
  -      }
  -      catch ( DBException e ) {
  -         throw e;
  -      }
  -      catch ( IOException e ) {
  -         throw new BTreeCorruptException("Corruption detected on add", e);
  -      }
  -      catch ( Exception e ) {
  -         if (log.isDebugEnabled()) {
  -            log.debug("No message", e);
  -         }
  -      }
  -   }
  -
  -   public void flush() throws DBException {
  -      super.flush();
  -   }
  -
  -   public IndexMatch[] queryMatches(final IndexQuery query) throws DBException {
  -      // Pre-process the value-set for typing and trimming
  -      if ( type != STRING ) {
  -         Value[] vals = query.getValues();
  -         for ( int i = 0; i < vals.length; i++ )
  -            vals[i] = getTypedValue(vals[i].toString());
  -      }
  -
  -      // Now issue the query
  -      final List results = new ArrayList();
  -
  -      try {
  -         query(query, new BTreeCallback() {
  -            public boolean indexInfo(Value value, long pos) {
  -               try {
  -                  if ( pos == MATCH_INFO ) {
  -                     IndexMatch match = getIndexMatch(value);
  -                     if ( !wildcard )
  -                        results.add(match);
  -                     else {
  -                        IndexPattern pt = new IndexPattern(symbols, match.getElement(), match.getAttribute());
  -                        if ( pt.getMatchLevel(query.getPattern()) > 0 )
  -                           results.add(match);
  -                     }
  -                  }
  -                  else {
  -                     BTreeRootInfo root = new BTreeRootInfo(value, pos);
  -                     query(root, null, this);
  -                  }
  -                  return true;
  -               }
  -               catch ( Exception e ) {
  -                  if (log.isDebugEnabled()) {
  -                     log.debug("No message", e);
  -                  }
  -               }
  -               return true;
  +
  +            typeSize = sizes[type];
  +
  +            fileHeader.setPageSize(config.getIntAttribute(PAGESIZE, fileHeader.getPageSize()));
  +            fileHeader.setMaxKeySize(config.getShortAttribute(MAXKEYSIZE, fileHeader.getMaxKeySize()));
  +
  +            setLocation(name);
  +        }
  +        catch (Exception e) {
  +            log.warn(e);
  +        }
  +    }
  +
  +    public Configuration getConfig() {
  +        return config;
  +    }
  +
  +    public String getName() {
  +        return name;
  +    }
  +
  +    public void setLocation(String location) {
  +        setFile(new File(collection.getCollectionRoot(), location + ".idx"));
  +    }
  +
  +    public void setCollection(Collection collection) {
  +        try {
  +            this.collection = collection;
  +            symbols = collection.getSymbols();
  +        }
  +        catch (Exception e) {
  +            log.warn(e);
  +        }
  +    }
  +
  +    public String getIndexStyle() {
  +        return STYLE_NODEVALUE;
  +    }
  +
  +    public String getPattern() {
  +        return pattern;
  +    }
  +
  +    public Value getTypedValue(String value) {
  +        if (type != STRING && type != TRIMMED) {
  +            value = value.trim();
  +
  +            if (value.length() == 0)
  +                return EmptyValue;
  +
  +            byte[] b = new byte[typeSize];
  +            try {
  +                switch (type) {
  +                    case INTEGER :
  +                        long l = Long.parseLong(value);
  +                        b[0] = (byte) ((l >>> 56) & 0xFF);
  +                        b[1] = (byte) ((l >>> 48) & 0xFF);
  +                        b[2] = (byte) ((l >>> 40) & 0xFF);
  +                        b[3] = (byte) ((l >>> 32) & 0xFF);
  +                        b[4] = (byte) ((l >>> 24) & 0xFF);
  +                        b[5] = (byte) ((l >>> 16) & 0xFF);
  +                        b[6] = (byte) ((l >>> 8) & 0xFF);
  +                        b[7] = (byte) ((l >>> 0) & 0xFF);
  +                        break;
  +                    case FLOAT :
  +                        double d = Double.parseDouble(value);
  +                        int i1 = (int) Math.round(d);
  +                        int i2 = (int) Math.round((d - i1) * 1000000000);
  +                        b[0] = (byte) ((i1 >>> 24) & 0xFF);
  +                        b[1] = (byte) ((i1 >>> 16) & 0xFF);
  +                        b[2] = (byte) ((i1 >>> 8) & 0xFF);
  +                        b[3] = (byte) ((i1 >>> 0) & 0xFF);
  +                        b[4] = (byte) ((i2 >>> 24) & 0xFF);
  +                        b[5] = (byte) ((i2 >>> 16) & 0xFF);
  +                        b[6] = (byte) ((i2 >>> 8) & 0xFF);
  +                        b[7] = (byte) ((i2 >>> 0) & 0xFF);
  +                        break;
  +                    case BYTE :
  +                        b[0] = Byte.parseByte(value);
  +                        break;
  +                    case CHAR :
  +                        char c = value.charAt(0);
  +                        b[0] = (byte) ((c >>> 8) & 0xFF);
  +                        b[1] = (byte) ((c >>> 0) & 0xFF);
  +                        break;
  +                    case BOOLEAN :
  +                        if ("[true][yes][1][y][on]".indexOf("[" + value.toString().toLowerCase() + "]") != -1)
  +                            b[0] = 1;
  +                        else if ("[false][no][0][n][off]".indexOf("[" + value.toString().toLowerCase() + "]") != -1)
  +                            b[0] = 0;
  +                        else
  +                            return EmptyValue;
  +                        break;
  +                }
  +                return new Value(b);
               }
  -         });
  -      }
  -      catch ( IOException e ) {
  -         throw new BTreeCorruptException("Corruption detected on query", e);
  -      }
  -      catch ( Exception e ) {
  -         if (log.isDebugEnabled()) {
  -            log.debug("No message", e);
  -         }
  -      }
  +            catch (Exception e) {
  +                return EmptyValue;
  +            }
  +        }
   
  -      return (IndexMatch[])results.toArray(EmptyMatches);
  -   }
  -}
  +        if (type == TRIMMED)
  +            value = QueryEngine.normalizeString(value);
  +
  +        return new Value(value);
  +    }
   
  +    private Value getCombinedValue(Key key, int pos, int len, short elemID, short attrID) {
  +        Value result;
  +        try {
  +            int l = key.getLength();
  +            byte[] b = new byte[l + 13];
  +
  +            // Write the key
  +            System.arraycopy(key.getData(), 0, b, 0, l);
  +            b[l] = 0;
  +
  +            // Write the pos
  +            b[l + 1] = (byte) ((pos >>> 24) & 0xFF);
  +            b[l + 2] = (byte) ((pos >>> 16) & 0xFF);
  +            b[l + 3] = (byte) ((pos >>> 8) & 0xFF);
  +            b[l + 4] = (byte) ((pos >>> 0) & 0xFF);
  +
  +            // Write the len
  +            b[l + 5] = (byte) ((len >>> 24) & 0xFF);
  +            b[l + 6] = (byte) ((len >>> 16) & 0xFF);
  +            b[l + 7] = (byte) ((len >>> 8) & 0xFF);
  +            b[l + 8] = (byte) ((len >>> 0) & 0xFF);
  +
  +            // Write the elemID
  +            b[l + 9] = (byte) ((elemID >>> 8) & 0xFF);
  +            b[l + 10] = (byte) ((elemID >>> 0) & 0xFF);
  +
  +            // Write the attrID
  +            b[l + 11] = (byte) ((attrID >>> 8) & 0xFF);
  +            b[l + 12] = (byte) ((attrID >>> 0) & 0xFF);
  +
  +            result = new Value(b);
  +        }
  +        catch (Exception e) {
  +            result = null; // This will never happen
  +        }
  +        return result;
  +    }
  +
  +    private IndexMatch getIndexMatch(Value v) {
  +        byte[] b = v.getData();
  +        int l = b.length - 13;
  +        Key key = new Key(b, 0, b.length - 13);
  +
  +        int pos = ((b[l + 1] << 24) | (b[l + 2] << 16) | (b[l + 3] << 8) | b[l + 4]);
  +        int len = ((b[l + 5] << 24) | (b[l + 6] << 16) | (b[l + 7] << 8) | b[l + 8]);
  +        short elemID = (short) ((b[l + 9] << 8) | b[l + 10]);
  +        short attrID = (short) ((b[l + 11] << 8) | b[l + 12]);
  +
  +        return new IndexMatch(key, pos, len, elemID, attrID);
  +    }
  +
  +    public void remove(String value, Key key, int pos, int len, short elemID, short attrID) throws DBException {
  +        Value v = getTypedValue(value);
  +        if (type != STRING && type != TRIMMED && v.getLength() == 0)
  +            return;
  +
  +        try {
  +            BTreeRootInfo root = findBTreeRoot(v);
  +            Value cv = getCombinedValue(key, pos, len, elemID, attrID);
  +            removeValue(root, cv);
  +        }
  +        catch (DBException e) {
  +            throw e;
  +        }
  +        catch (Exception e) {
  +            log.warn(e);
  +        }
  +    }
  +
  +    public void add(String value, Key key, int pos, int len, short elemID, short attrID) throws DBException {
  +        Value v = getTypedValue(value);
  +        if (type != STRING && type != TRIMMED && v.getLength() == 0)
  +            return;
   
  +        try {
  +            BTreeRootInfo root;
  +
  +            try {
  +                root = findBTreeRoot(v);
  +            }
  +            catch (BTreeNotFoundException e) {
  +                root = createBTreeRoot(v);
  +            }
  +
  +            Value cv = getCombinedValue(key, pos, len, elemID, attrID);
  +            addValue(root, cv, MATCH_INFO);
  +        }
  +        catch (DBException e) {
  +            throw e;
  +        }
  +        catch (IOException e) {
  +            throw new BTreeCorruptException("Corruption detected on add", e);
  +        }
  +        catch (Exception e) {
  +            log.warn(e);
  +        }
  +    }
  +
  +    public void flush() throws DBException {
  +        super.flush();
  +    }
  +
  +    public IndexMatch[] queryMatches(final IndexQuery query) throws DBException {
  +        // Pre-process the value-set for typing and trimming
  +        if (type != STRING) {
  +            Value[] vals = query.getValues();
  +            for (int i = 0; i < vals.length; i++)
  +                vals[i] = getTypedValue(vals[i].toString());
  +        }
  +
  +        // Now issue the query
  +        final List results = new ArrayList();
  +
  +        try {
  +            query(query, new BTreeCallback() {
  +                public boolean indexInfo(Value value, long pos) {
  +                    try {
  +                        if (pos == MATCH_INFO) {
  +                            IndexMatch match = getIndexMatch(value);
  +                            if (!wildcard)
  +                                results.add(match);
  +                            else {
  +                                IndexPattern pt = new IndexPattern(symbols, match.getElement(), match.getAttribute());
  +                                if (pt.getMatchLevel(query.getPattern()) > 0)
  +                                    results.add(match);
  +                            }
  +                        }
  +                        else {
  +                            BTreeRootInfo root = new BTreeRootInfo(value, pos);
  +                            query(root, null, this);
  +                        }
  +                        return true;
  +                    }
  +                    catch (Exception e) {
  +                        log.warn(e);
  +                    }
  +                    return true;
  +                }
  +            });
  +        }
  +        catch (IOException e) {
  +            throw new BTreeCorruptException("Corruption detected on query", e);
  +        }
  +        catch (Exception e) {
  +            log.warn(e);
  +        }
  +
  +        return (IndexMatch[]) results.toArray(EmptyMatches);
  +    }
  +}
  
  
  
  1.8       +925 -938  xml-xindice/java/src/org/apache/xindice/util/Configuration.java
  
  Index: Configuration.java
  ===================================================================
  RCS file: /home/cvs/xml-xindice/java/src/org/apache/xindice/util/Configuration.java,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- Configuration.java	22 Nov 2002 10:15:35 -0000	1.7
  +++ Configuration.java	15 Jul 2003 15:44:36 -0000	1.8
  @@ -59,14 +59,19 @@
    * $Id$
    */
   
  -import org.apache.commons.logging.Log;
  -import org.apache.commons.logging.LogFactory;
  -
  -import org.w3c.dom.*;
  -
   import java.util.ArrayList;
   import java.util.List;
   
  +import org.apache.commons.logging.Log;
  +import org.apache.commons.logging.LogFactory;
  +import org.w3c.dom.Attr;
  +import org.w3c.dom.Document;
  +import org.w3c.dom.Element;
  +import org.w3c.dom.NamedNodeMap;
  +import org.w3c.dom.Node;
  +import org.w3c.dom.NodeList;
  +import org.w3c.dom.Text;
  +
   /**
    * Configuration is a utility class that allows Configurable objects to
    * easily manage configuration information in a simple and consistent
  @@ -76,64 +81,64 @@
    */
   
   public final class Configuration {
  -   private static final Configuration[] EmptySet = new Configuration[0];
  +    private static final Configuration[] EmptySet = new Configuration[0];
   
       // commented out 2002-07-16: not used
       //private static final Map Modified = Collections.synchronizedMap(new HashMap()); // Temporary HACK
   
  -   private static Log log = LogFactory.getLog("org.apache.xindice.util");
  +    private static Log log = LogFactory.getLog("org.apache.xindice.util");
   
  -   private Element config = null;
  -   private boolean readOnly = true;
  +    private Element config = null;
  +    private boolean readOnly = true;
   
  -   public Configuration(Element config, boolean readOnly) {
  -      this.config = config;
  -      this.readOnly = readOnly;
  -   }
  -
  -   public Configuration(Document config, boolean readOnly) {
  -      this(config.getDocumentElement(), readOnly);
  -   }
  -
  -   public Configuration(Element config) {
  -      this(config, true);
  -   }
  -
  -   public Configuration(Document config) {
  -      this(config.getDocumentElement());
  -   }
  -
  -   /**
  -    * getElement returns the Element being managed by this
  -    * Configuration.
  -    *
  -    * @return The Configuration Element
  -    * @throws ReadOnlyException If the Configuration is Read-only
  -    */
  -   public Element getElement() throws ReadOnlyException {
  -      if ( readOnly )
  -         throw new ReadOnlyException();
  -      return config;
  -   }
  -
  -   /**
  -    * getName returns the name of the Configuration node.
  -    *
  -    * @return The Node name
  -    */
  -   public String getName() {
  -      return config.getNodeName();
  -   }
  -
  -   /**
  -    * hasAttributes returns whether or not the Configuration node has any
  -    * attributes associated with it.
  -    *
  -    * @return Whether or not attributes exist
  -    */
  -   public boolean hasAttributes() {
  -      return config.getAttributes().getLength() > 0;
  -   }
  +    public Configuration(Element config, boolean readOnly) {
  +        this.config = config;
  +        this.readOnly = readOnly;
  +    }
  +
  +    public Configuration(Document config, boolean readOnly) {
  +        this(config.getDocumentElement(), readOnly);
  +    }
  +
  +    public Configuration(Element config) {
  +        this(config, true);
  +    }
  +
  +    public Configuration(Document config) {
  +        this(config.getDocumentElement());
  +    }
  +
  +    /**
  +     * getElement returns the Element being managed by this
  +     * Configuration.
  +     *
  +     * @return The Configuration Element
  +     * @throws ReadOnlyException If the Configuration is Read-only
  +     */
  +    public Element getElement() throws ReadOnlyException {
  +        if (readOnly)
  +            throw new ReadOnlyException();
  +        return config;
  +    }
  +
  +    /**
  +     * getName returns the name of the Configuration node.
  +     *
  +     * @return The Node name
  +     */
  +    public String getName() {
  +        return config.getNodeName();
  +    }
  +
  +    /**
  +     * hasAttributes returns whether or not the Configuration node has any
  +     * attributes associated with it.
  +     *
  +     * @return Whether or not attributes exist
  +     */
  +    public boolean hasAttributes() {
  +        return config.getAttributes().getLength() > 0;
  +    }
   
       /*
         // commented out 2002-07-16: not doing anything
  @@ -142,884 +147,866 @@
         }
       */
   
  -   /**
  -    * getAttribute returns an attribute from the Configuration node.
  -    *
  -    * @param name The attribute name
  -    * @param defValue The default value
  -    * @return The attribute value
  -    */
  -   public String getAttribute(String name, String defValue) {
  -      String value = config.getAttribute(name);
  -      if ( value == null || value.length() == 0 )
  -         value = defValue;
  -      return value;
  -   }
  -
  -   /**
  -    * getAttribute returns an attribute from the Configuration node.
  -    *
  -    * @param name The attribute name
  -    * @return The attribute value
  -    */
  -   public String getAttribute(String name) {
  -      return getAttribute(name, "");
  -   }
  -
  -   /**
  -    * getBooleanAttribute returns an attribute from the Configuration node.
  -    *
  -    * @param name The attribute name
  -    * @param defValue The default value
  -    * @return The attribute value
  -    */
  -   public boolean getBooleanAttribute(String name, boolean defValue) {
  -      try {
  -         return "[true][yes][1][y][on]".indexOf("["+getAttribute(name, defValue ? "1" : "0").toLowerCase()+"]") != -1;
  -      }
  -      catch ( Exception e ) {
  -         return defValue;
  -      }
  -   }
  -
  -   /**
  -    * getBooleanAttribute returns an attribute from the Configuration node.
  -    *
  -    * @param name The attribute name
  -    * @return The attribute value
  -    */
  -   public boolean getBooleanAttribute(String name) {
  -      return getBooleanAttribute(name, false);
  -   }
  -
  -   /**
  -    * getIntAttribute returns an attribute from the Configuration node.
  -    *
  -    * @param name The attribute name
  -    * @param defValue The default value
  -    * @return The attribute value
  -    */
  -   public int getIntAttribute(String name, int defValue) {
  -      try {
  -         return Integer.parseInt(config.getAttribute(name));
  -      }
  -      catch ( Exception e ) {
  -         return defValue;
  -      }
  -   }
  -
  -   /**
  -    * getIntAttribute returns an attribute from the Configuration node.
  -    *
  -    * @param name The attribute name
  -    * @return The attribute value
  -    */
  -   public int getIntAttribute(String name) {
  -      return getIntAttribute(name, 0);
  -   }
  -
  -   /**
  -    * getShortAttribute returns an attribute from the Configuration node.
  -    *
  -    * @param name The attribute name
  -    * @param defValue The default value
  -    * @return The attribute value
  -    */
  -   public short getShortAttribute(String name, short defValue) {
  -      try {
  -         return Short.parseShort(config.getAttribute(name));
  -      }
  -      catch ( Exception e ) {
  -         return defValue;
  -      }
  -   }
  -
  -   /**
  -    * getShortAttribute returns an attribute from the Configuration node.
  -    *
  -    * @param name The attribute name
  -    * @return The attribute value
  -    */
  -   public short getShortAttribute(String name) {
  -      return getShortAttribute(name, (short)0);
  -   }
  -
  -   /**
  -    * getLongAttribute returns an attribute from the Configuration node.
  -    *
  -    * @param name The attribute name
  -    * @param defValue The default value
  -    * @return The attribute value
  -    */
  -   public long getLongAttribute(String name, long defValue) {
  -      try {
  -         return Long.parseLong(config.getAttribute(name));
  -      }
  -      catch ( Exception e ) {
  -         return defValue;
  -      }
  -   }
  -
  -   /**
  -    * getLongAttribute returns an attribute from the Configuration node.
  -    *
  -    * @param name The attribute name
  -    * @return The attribute value
  -    */
  -   public long getLongAttribute(String name) {
  -      return getLongAttribute(name, (long)0);
  -   }
  -
  -   /**
  -    * getFloatAttribute returns an attribute from the Configuration node.
  -    *
  -    * @param name The attribute name
  -    * @param defValue The default value
  -    * @return The attribute value
  -    */
  -   public float getFloatAttribute(String name, float defValue) {
  -      try {
  -         return Float.parseFloat(config.getAttribute(name));
  -      }
  -      catch ( Exception e ) {
  -         return defValue;
  -      }
  -   }
  -
  -   /**
  -    * getFloatAttribute returns an attribute from the Configuration node.
  -    *
  -    * @param name The attribute name
  -    * @return The attribute value
  -    */
  -   public float getFloatAttribute(String name) {
  -      return getFloatAttribute(name, (float)0.0);
  -   }
  -
  -   /**
  -    * getDoubleAttribute returns an attribute from the Configuration node.
  -    *
  -    * @param name The attribute name
  -    * @param defValue The default value
  -    * @return The attribute value
  -    */
  -   public double getDoubleAttribute(String name, double defValue) {
  -      try {
  -         return Double.parseDouble(config.getAttribute(name));
  -      }
  -      catch ( Exception e ) {
  -         return defValue;
  -      }
  -   }
  -
  -   /**
  -    * getDoubleAttribute returns an attribute from the Configuration node.
  -    *
  -    * @param name The attribute name
  -    * @return The attribute value
  -    */
  -   public double getDoubleAttribute(String name) {
  -      return getDoubleAttribute(name, (double)0.0);
  -   }
  -
  -   /**
  -    * getByteAttribute returns an attribute from the Configuration node.
  -    *
  -    * @param name The attribute name
  -    * @param defValue The default value
  -    * @return The attribute value
  -    */
  -   public byte getByteAttribute(String name, byte defValue) {
  -      try {
  -         return Byte.parseByte(config.getAttribute(name));
  -      }
  -      catch ( Exception e ) {
  -         return defValue;
  -      }
  -   }
  -
  -   /**
  -    * getByteAttribute returns an attribute from the Configuration node.
  -    *
  -    * @param name The attribute name
  -    * @return The attribute value
  -    */
  -   public byte getByteAttribute(String name) {
  -      return getByteAttribute(name, (byte)0);
  -   }
  -
  -   /**
  -    * getCharAttribute returns an attribute from the Configuration node.
  -    *
  -    * @param name The attribute name
  -    * @param defValue The default value
  -    * @return The attribute value
  -    */
  -   public char getCharAttribute(String name, char defValue) {
  -      try {
  -         return config.getAttribute(name).charAt(0);
  -      }
  -      catch ( Exception e ) {
  -         return defValue;
  -      }
  -   }
  -
  -   /**
  -    * getCharAttribute returns an attribute from the Configuration node.
  -    *
  -    * @param name The attribute name
  -    * @return The attribute value
  -    */
  -   public char getCharAttribute(String name) {
  -      return getCharAttribute(name, '\0');
  -   }
  -
  -   /**
  -    * listAttributes returns a list of the attribute names that exist for
  -    * this Configuration node.
  -    *
  -    * @return The Attribute names
  -    */
  -   public String[] listAttributes() {
  -      NamedNodeMap map = config.getAttributes();
  -      String[] result = new String[map.getLength()];
  -      int size = map.getLength();
  -      for ( int i = 0; i < size; i++ )
  -         result[i] = ((Attr)map.item(i)).getName();
  -      return result;
  -   }
  -
  -   /**
  -    * hasValue returns whether or not the Configuration node has a textual
  -    * value associated with it.
  -    *
  -    * @return Whether or not the node has a text value
  -    */
  -   public boolean hasValue() {
  -      NodeList list = config.getChildNodes();
  -      return ( list.getLength() > 0 && list.item(0).getNodeType() == Node.TEXT_NODE );
  -   }
  -
  -   /**
  -    * getValue returns the value from the Configuration node.
  -    *
  -    * @param defValue The default value
  -    * @return The value
  -    */
  -   public String getValue(String defValue) {
  -      NodeList list = config.getChildNodes();
  -      if ( list.getLength() == 1 && list.item(0).getNodeType() == Node.TEXT_NODE )
  -         return list.item(0).getNodeValue();
  -      else
  -         return defValue;
  -   }
  -
  -   /**
  -    * getValue returns the value from the Configuration node.
  -    *
  -    * @return The value
  -    */
  -   public String getValue() {
  -      return getValue("");
  -   }
  -
  -   /**
  -    * getBooleanValue returns the value from the Configuration node.
  -    *
  -    * @param defValue The default value
  -    * @return The value
  -    */
  -   public boolean getBooleanValue(boolean defValue) {
  -      try {
  -         return "[true][yes][1][y][on]".indexOf("["+getValue().toLowerCase()+"]") != -1;
  -      }
  -      catch ( Exception e ) {
  -         return defValue;
  -      }
  -   }
  -
  -   /**
  -    * getBooleanValue returns the value from the Configuration node.
  -    *
  -    * @return The value
  -    */
  -   public boolean getBooleanValue() {
  -      return getBooleanValue(false);
  -   }
  -
  -   /**
  -    * getIntValue returns the value from the Configuration node.
  -    *
  -    * @param defValue The default value
  -    * @return The value
  -    */
  -   public int getIntValue(int defValue) {
  -      try {
  -         return Integer.parseInt(getValue());
  -      }
  -      catch ( Exception e ) {
  -         return defValue;
  -      }
  -   }
  -
  -   /**
  -    * getIntValue returns the value from the Configuration node.
  -    *
  -    * @return The value
  -    */
  -   public int getIntValue() {
  -      return getIntValue(0);
  -   }
  -
  -   /**
  -    * getShortValue returns the value from the Configuration node.
  -    *
  -    * @param defValue The default value
  -    * @return The value
  -    */
  -   public short getShortValue(short defValue) {
  -      try {
  -         return Short.parseShort(getValue());
  -      }
  -      catch ( Exception e ) {
  -         return defValue;
  -      }
  -   }
  -
  -   /**
  -    * getShortValue returns the value from the Configuration node.
  -    *
  -    * @return The value
  -    */
  -   public short getShortValue() {
  -      return getShortValue((short)0);
  -   }
  -
  -   /**
  -    * getLongValue returns the value from the Configuration node.
  -    *
  -    * @param defValue The default value
  -    * @return The value
  -    */
  -   public long getLongValue(long defValue) {
  -      try {
  -         return Long.parseLong(getValue());
  -      }
  -      catch ( Exception e ) {
  -         return defValue;
  -      }
  -   }
  -
  -   /**
  -    * getLongValue returns the value from the Configuration node.
  -    *
  -    * @return The value
  -    */
  -   public long getLongValue() {
  -      return getLongValue(0);
  -   }
  -
  -   /**
  -    * getFloatValue returns the value from the Configuration node.
  -    *
  -    * @param defValue The default value
  -    * @return The value
  -    */
  -   public float getFloatValue(float defValue) {
  -      try {
  -         return Float.parseFloat(getValue());
  -      }
  -      catch ( Exception e ) {
  -         return defValue;
  -      }
  -   }
  -
  -   /**
  -    * getFloatValue returns the value from the Configuration node.
  -    *
  -    * @return The value
  -    */
  -   public float getFloatValue() {
  -      return getFloatValue((float)0.0);
  -   }
  -
  -   /**
  -    * getDoubleValue returns the value from the Configuration node.
  -    *
  -    * @param defValue The default value
  -    * @return The value
  -    */
  -   public double getDoubleValue(double defValue) {
  -      try {
  -         return Double.parseDouble(getValue());
  -      }
  -      catch ( Exception e ) {
  -         return defValue;
  -      }
  -   }
  -
  -   /**
  -    * getDoubleValue returns the value from the Configuration node.
  -    *
  -    * @return The value
  -    */
  -   public double getDoubleValue() {
  -      return getDoubleValue((double)0.0);
  -   }
  -
  -   /**
  -    * getByteValue returns the value from the Configuration node.
  -    *
  -    * @param defValue The default value
  -    * @return The value
  -    */
  -   public byte getByteValue(byte defValue) {
  -      try {
  -         return Byte.parseByte(getValue());
  -      }
  -      catch ( Exception e ) {
  -         return defValue;
  -      }
  -   }
  -
  -   /**
  -    * getByteValue returns the value from the Configuration node.
  -    *
  -    * @return The value
  -    */
  -   public byte getByteValue() {
  -      return getByteValue((byte)0);
  -   }
  -
  -   /**
  -    * getCharValue returns the value from the Configuration node.
  -    *
  -    * @param defValue The default value
  -    * @return The value
  -    */
  -   public char getCharValue(char defValue) {
  -      try {
  -         return getValue().charAt(0);
  -      }
  -      catch ( Exception e ) {
  -         return defValue;
  -      }
  -   }
  -
  -   /**
  -    * getCharValue returns the value from the Configuration node.
  -    *
  -    * @return The value
  -    */
  -   public char getCharValue() {
  -      return getCharValue('\0');
  -   }
  -
  -
  -
  -
  -
  -
  -   /**
  -    * hasChildren returns whether or not the Configuration node has child
  -    * Configuration elements.
  -    *
  -    * @return Whether or not children exist
  -    */
  -   public boolean hasChildren() {
  -      NodeList list = config.getChildNodes();
  -      int size = list.getLength();
  -      for ( int i = 0; i < size; i++ )
  -         if ( list.item(i).getNodeType() == Node.ELEMENT_NODE )
  -            return true;
  -      return false;
  -   }
  -
  -   /**
  -    * getChildren returns the child Configuration nodes for this Configuration
  -    * node.
  -    *
  -    * @return The children
  -    */
  -   public Configuration[] getChildren() {
  -      NodeList list = config.getChildNodes();
  -      if ( list == null )
  -         return EmptySet;
  -      List tmp = new ArrayList();
  -      int size = list.getLength();
  -      for ( int i = 0; i < size; i++ )
  -         if ( list.item(i).getNodeType() == Node.ELEMENT_NODE )
  -            tmp.add(new Configuration((Element)list.item(i), readOnly));
  -      return (Configuration[])tmp.toArray(EmptySet);
  -   }
  -
  -   /**
  -    * processChildren runs through the children of this Configuration and
  -    * performs prcessing callbacks to the ConfigurationCallback object.
  -    *
  -    * @param callback The callback object
  -    */
  -   public void processChildren(ConfigurationCallback callback) {
  -      NodeList list = config.getChildNodes();
  -      if ( list == null )
  -         return;
  -      int size = list.getLength();
  -      try {
  -         for ( int i = 0; i < size; i++ )
  -            if ( list.item(i).getNodeType() == Node.ELEMENT_NODE )
  -               callback.process(new Configuration((Element)list.item(i), readOnly));
  -      }
  -      catch (Exception e) {
  -         if (log.isDebugEnabled()) {
  -            log.debug("No message", e);
  -         }
  -      }
  -   }
  -
  -   /**
  -    * processChildren runs through the children of this Configuration and
  -    * performs prcessing callbacks to the ConfigurationCallback object.
  -    *
  -    * @param callback The callback object
  -    * @param name The Configuration name to process
  -    */
  -   public void processChildren(String name, ConfigurationCallback callback) {
  -      NodeList list = config.getChildNodes();
  -      if ( list == null )
  -         return;
  -
  -      Node[] nl = new Node[list.getLength()];
  -      for ( int i = 0; i < nl.length; i++ )
  -         nl[i] = list.item(i);
  -
  -      int size = nl.length;
  -
  -      try {
  -         for ( int i = 0; i < size; i++ )
  -            if ( nl[i].getNodeType() == Node.ELEMENT_NODE && nl[i].getNodeName().equals(name))
  -               callback.process(new Configuration((Element)nl[i], readOnly));
  -      }
  -      catch (Exception e) {
  -         if (log.isDebugEnabled()) {
  -            log.debug("No message", e);
  -         }
  -      }
  -   }
  -
  -   /**
  -    * getChild returns the first child Configuration node that matches the
  -    * specified name.
  -    *
  -    * @param name The Configuration node name
  -    * @param create Create Configuration if it doesn't exist
  -    * @return The child Configuration
  -    * @throws ReadOnlyException if the Configuration is read-only
  -    */
  -   public Configuration getChild(String name, boolean create) throws ReadOnlyException {
  -      NodeList list = config.getChildNodes();
  -      int size = list.getLength();
  -
  -      for ( int i = 0; i < size; i++ )
  -         if ( list.item(i).getNodeType() == Node.ELEMENT_NODE && list.item(i).getNodeName().equals(name) )
  -            return new Configuration((Element)list.item(i), readOnly);
  -      if ( create )
  -         return add(name);
  -      else
  -         return null;
  -   }
  -
  -   /**
  -    * getChild returns the first child Configuration node that matches the
  -    * specified name.
  -    *
  -    * @param name The Configuration node name
  -    * @return The child Configuration
  -    */
  -   public Configuration getChild(String name) {
  -      try {
  -         return getChild(name, false);
  -      }
  -      catch( Exception e ) {
  -         return null;
  -      }
  -   }
  -
  -
  -
  -   /**
  -    * isReadOnly returns whether or not this Configuration node is a
  -    * read-only node.
  -    *
  -    * @return The read-only status
  -    */
  -   public boolean isReadOnly() {
  -      return readOnly;
  -   }
  -
  -   /**
  -    * add adds a new Configuration node to this Configuration node.
  -    *
  -    * @param name The name of the Configuration node
  -    * @return The new Configuration node
  -    * @throws ReadOnlyException if the Configuration is read-only
  -    */
  -   public Configuration add(String name) throws ReadOnlyException {
  -      if ( readOnly )
  -         throw new ReadOnlyException();
  -      Element elem = config.getOwnerDocument().createElement(name);
  -      config.appendChild(elem);
  -      //setDirty();
  -      return new Configuration(elem, readOnly);
  -   }
  -
  -   /**
  -    * add adds an existing Configuration node to this Configuration node.
  -    * Note!  This method does NOT perform a deep copy on the DOM Node that
  -    * newConfig manages.
  -    *
  -    * @param newConfig The Configuration node to add
  -    * @throws ReadOnlyException if the Configuration is read-only
  -    */
  -   public void add(Configuration newConfig) throws ReadOnlyException {
  -      if ( readOnly )
  -         throw new ReadOnlyException();
  -      Node imported = config.getOwnerDocument().importNode(newConfig.config, true);
  -      config.appendChild(imported);
  -      newConfig.config = (Element)imported;
  -      //setDirty();
  -   }
  -
  -   /**
  -    * delete deletes this Configuration node from its parent Configuration.
  -    *
  -    * @throws ReadOnlyException if the Configuration is read-only
  -    */
  -   public void delete() throws ReadOnlyException {
  -      if ( readOnly )
  -         throw new ReadOnlyException();
  -      if ( config.getParentNode() != null )
  -         config.getParentNode().removeChild(config);
  -      //setDirty();
  -   }
  -
  -   /**
  -    * removeAttribute removes the named attribute from this Configuration.
  -    *
  -    * @param name The attribute name
  -    * @throws ReadOnlyException if the Configuration is read-only
  -    */
  -   public void removeAttribute(String name) throws ReadOnlyException {
  -      if ( readOnly )
  -         throw new ReadOnlyException();
  -      config.removeAttribute(name);
  -      //setDirty();
  -   }
  -
  -
  -
  -
  -   /**
  -    * setAttribute sets the attribute value for this Configuration.
  -    *
  -    * @param name The attribute name
  -    * @param value The attribute value
  -    * @throws ReadOnlyException if the Configuration is read-only
  -    */
  -   public void setAttribute(String name, String value) throws ReadOnlyException {
  -      if ( readOnly )
  -         throw new ReadOnlyException();
  -      config.setAttribute(name, value);
  -      //setDirty();
  -   }
  -
  -   /**
  -    * setAttribute sets the attribute value for this Configuration.
  -    *
  -    * @param name The attribute name
  -    * @param value The attribute value
  -    * @throws ReadOnlyException if the Configuration is read-only
  -    */
  -   public void setAttribute(String name, boolean value) throws ReadOnlyException {
  -       setAttribute( name, String.valueOf( value ) );
  -   }
  -
  -   /**
  -    * setAttribute sets the attribute value for this Configuration.
  -    *
  -    * @param name The attribute name
  -    * @param value The attribute value
  -    * @throws ReadOnlyException if the Configuration is read-only
  -    */
  -   public void setAttribute(String name, int value) throws ReadOnlyException {
  -       setAttribute( name, String.valueOf( value ) );
  -   }
  -
  -   /**
  -    * setAttribute sets the attribute value for this Configuration.
  -    *
  -    * @param name The attribute name
  -    * @param value The attribute value
  -    * @throws ReadOnlyException if the Configuration is read-only
  -    */
  -   public void setAttribute(String name, short value) throws ReadOnlyException {
  -       setAttribute( name, String.valueOf( value ) );
  -   }
  -
  -   /**
  -    * setAttribute sets the attribute value for this Configuration.
  -    *
  -    * @param name The attribute name
  -    * @param value The attribute value
  -    * @throws ReadOnlyException if the Configuration is read-only
  -    */
  -   public void setAttribute(String name, long value) throws ReadOnlyException {
  -       setAttribute( name, String.valueOf( value ) );
  -   }
  -
  -   /**
  -    * setAttribute sets the attribute value for this Configuration.
  -    *
  -    * @param name The attribute name
  -    * @param value The attribute value
  -    * @throws ReadOnlyException if the Configuration is read-only
  -    */
  -   public void setAttribute(String name, float value) throws ReadOnlyException {
  -       setAttribute( name, String.valueOf( value ) );
  -   }
  -
  -   /**
  -    * setAttribute sets the attribute value for this Configuration.
  -    *
  -    * @param name The attribute name
  -    * @param value The attribute value
  -    * @throws ReadOnlyException if the Configuration is read-only
  -    */
  -   public void setAttribute(String name, double value) throws ReadOnlyException {
  -       setAttribute( name, String.valueOf( value ) );
  -   }
  -
  -   /**
  -    * setAttribute sets the attribute value for this Configuration.
  -    *
  -    * @param name The attribute name
  -    * @param value The attribute value
  -    * @throws ReadOnlyException if the Configuration is read-only
  -    */
  -   public void setAttribute(String name, byte value) throws ReadOnlyException {
  -       setAttribute( name, String.valueOf( value ) );
  -   }
  -
  -   /**
  -    * setAttribute sets the attribute value for this Configuration.
  -    *
  -    * @param name The attribute name
  -    * @param value The attribute value
  -    * @throws ReadOnlyException if the Configuration is read-only
  -    */
  -   public void setAttribute(String name, char value) throws ReadOnlyException {
  -       setAttribute( name, String.valueOf( value ) );
  -   }
  -
  -
  -
  -
  -   /**
  -    * setValue sets the value of the Configuration node.
  -    *
  -    * @param value The New Value
  -    * @throws ReadOnlyException if the Configuration is read-only
  -    */
  -   public void setValue(String value) throws ReadOnlyException {
  -      if ( readOnly )
  -         throw new ReadOnlyException();
  -      NodeList list = config.getChildNodes();
  -      if ( list.getLength() == 1 && list.item(0).getNodeType() == Node.TEXT_NODE )
  -         list.item(0).setNodeValue(value);
  -      else {
  -         Text text = config.getOwnerDocument().createTextNode(value);
  -         config.appendChild(text);
  -      }
  -      //setDirty();
  -   }
  -
  -   /**
  -    * setValue sets the value of the Configuration node.
  -    *
  -    * @param value The New Value
  -    * @throws ReadOnlyException if the Configuration is read-only
  -    */
  -   public void setValue(boolean value) throws ReadOnlyException {
  -       setValue( String.valueOf( value ) );
  -   }
  -
  -   /**
  -    * setValue sets the value of the Configuration node.
  -    *
  -    * @param value The New Value
  -    * @throws ReadOnlyException if the Configuration is read-only
  -    */
  -   public void setValue(int value) throws ReadOnlyException {
  -      setValue(String.valueOf(value));
  -   }
  -
  -   /**
  -    * setValue sets the value of the Configuration node.
  -    *
  -    * @param value The New Value
  -    * @throws ReadOnlyException if the Configuration is read-only
  -    */
  -   public void setValue(short value) throws ReadOnlyException {
  -      setValue(String.valueOf(value));
  -   }
  -
  -   /**
  -    * setValue sets the value of the Configuration node.
  -    *
  -    * @param value The New Value
  -    * @throws ReadOnlyException if the Configuration is read-only
  -    */
  -   public void setValue(long value) throws ReadOnlyException {
  -      setValue(String.valueOf(value));
  -   }
  -
  -   /**
  -    * setValue sets the value of the Configuration node.
  -    *
  -    * @param value The New Value
  -    * @throws ReadOnlyException if the Configuration is read-only
  -    */
  -   public void setValue(float value) throws ReadOnlyException {
  -      setValue(String.valueOf(value));
  -   }
  -
  -   /**
  -    * setValue sets the value of the Configuration node.
  -    *
  -    * @param value The New Value
  -    * @throws ReadOnlyException if the Configuration is read-only
  -    */
  -   public void setValue(double value) throws ReadOnlyException {
  -      setValue(String.valueOf(value));
  -   }
  -
  -   /**
  -    * setValue sets the value of the Configuration node.
  -    *
  -    * @param value The New Value
  -    * @throws ReadOnlyException if the Configuration is read-only
  -    */
  -   public void setValue(byte value) throws ReadOnlyException {
  -      setValue(String.valueOf(value));
  -   }
  -
  -   /**
  -    * setValue sets the value of the Configuration node.
  -    *
  -    * @param value The New Value
  -    * @throws ReadOnlyException if the Configuration is read-only
  -    */
  -   public void setValue(char value) throws ReadOnlyException {
  -      setValue(String.valueOf(value));
  -   }
  +    /**
  +     * getAttribute returns an attribute from the Configuration node.
  +     *
  +     * @param name The attribute name
  +     * @param defValue The default value
  +     * @return The attribute value
  +     */
  +    public String getAttribute(String name, String defValue) {
  +        String value = config.getAttribute(name);
  +        if (value == null || value.length() == 0)
  +            value = defValue;
  +        return value;
  +    }
  +
  +    /**
  +     * getAttribute returns an attribute from the Configuration node.
  +     *
  +     * @param name The attribute name
  +     * @return The attribute value
  +     */
  +    public String getAttribute(String name) {
  +        return getAttribute(name, "");
  +    }
  +
  +    /**
  +     * getBooleanAttribute returns an attribute from the Configuration node.
  +     *
  +     * @param name The attribute name
  +     * @param defValue The default value
  +     * @return The attribute value
  +     */
  +    public boolean getBooleanAttribute(String name, boolean defValue) {
  +        try {
  +            return "[true][yes][1][y][on]".indexOf("[" + getAttribute(name, defValue ? "1" : "0").toLowerCase() + "]") != -1;
  +        }
  +        catch (Exception e) {
  +            return defValue;
  +        }
  +    }
  +
  +    /**
  +     * getBooleanAttribute returns an attribute from the Configuration node.
  +     *
  +     * @param name The attribute name
  +     * @return The attribute value
  +     */
  +    public boolean getBooleanAttribute(String name) {
  +        return getBooleanAttribute(name, false);
  +    }
  +
  +    /**
  +     * getIntAttribute returns an attribute from the Configuration node.
  +     *
  +     * @param name The attribute name
  +     * @param defValue The default value
  +     * @return The attribute value
  +     */
  +    public int getIntAttribute(String name, int defValue) {
  +        try {
  +            return Integer.parseInt(config.getAttribute(name));
  +        }
  +        catch (Exception e) {
  +            return defValue;
  +        }
  +    }
  +
  +    /**
  +     * getIntAttribute returns an attribute from the Configuration node.
  +     *
  +     * @param name The attribute name
  +     * @return The attribute value
  +     */
  +    public int getIntAttribute(String name) {
  +        return getIntAttribute(name, 0);
  +    }
  +
  +    /**
  +     * getShortAttribute returns an attribute from the Configuration node.
  +     *
  +     * @param name The attribute name
  +     * @param defValue The default value
  +     * @return The attribute value
  +     */
  +    public short getShortAttribute(String name, short defValue) {
  +        try {
  +            return Short.parseShort(config.getAttribute(name));
  +        }
  +        catch (Exception e) {
  +            return defValue;
  +        }
  +    }
  +
  +    /**
  +     * getShortAttribute returns an attribute from the Configuration node.
  +     *
  +     * @param name The attribute name
  +     * @return The attribute value
  +     */
  +    public short getShortAttribute(String name) {
  +        return getShortAttribute(name, (short) 0);
  +    }
  +
  +    /**
  +     * getLongAttribute returns an attribute from the Configuration node.
  +     *
  +     * @param name The attribute name
  +     * @param defValue The default value
  +     * @return The attribute value
  +     */
  +    public long getLongAttribute(String name, long defValue) {
  +        try {
  +            return Long.parseLong(config.getAttribute(name));
  +        }
  +        catch (Exception e) {
  +            return defValue;
  +        }
  +    }
  +
  +    /**
  +     * getLongAttribute returns an attribute from the Configuration node.
  +     *
  +     * @param name The attribute name
  +     * @return The attribute value
  +     */
  +    public long getLongAttribute(String name) {
  +        return getLongAttribute(name, (long) 0);
  +    }
  +
  +    /**
  +     * getFloatAttribute returns an attribute from the Configuration node.
  +     *
  +     * @param name The attribute name
  +     * @param defValue The default value
  +     * @return The attribute value
  +     */
  +    public float getFloatAttribute(String name, float defValue) {
  +        try {
  +            return Float.parseFloat(config.getAttribute(name));
  +        }
  +        catch (Exception e) {
  +            return defValue;
  +        }
  +    }
  +
  +    /**
  +     * getFloatAttribute returns an attribute from the Configuration node.
  +     *
  +     * @param name The attribute name
  +     * @return The attribute value
  +     */
  +    public float getFloatAttribute(String name) {
  +        return getFloatAttribute(name, (float) 0.0);
  +    }
  +
  +    /**
  +     * getDoubleAttribute returns an attribute from the Configuration node.
  +     *
  +     * @param name The attribute name
  +     * @param defValue The default value
  +     * @return The attribute value
  +     */
  +    public double getDoubleAttribute(String name, double defValue) {
  +        try {
  +            return Double.parseDouble(config.getAttribute(name));
  +        }
  +        catch (Exception e) {
  +            return defValue;
  +        }
  +    }
  +
  +    /**
  +     * getDoubleAttribute returns an attribute from the Configuration node.
  +     *
  +     * @param name The attribute name
  +     * @return The attribute value
  +     */
  +    public double getDoubleAttribute(String name) {
  +        return getDoubleAttribute(name, (double) 0.0);
  +    }
  +
  +    /**
  +     * getByteAttribute returns an attribute from the Configuration node.
  +     *
  +     * @param name The attribute name
  +     * @param defValue The default value
  +     * @return The attribute value
  +     */
  +    public byte getByteAttribute(String name, byte defValue) {
  +        try {
  +            return Byte.parseByte(config.getAttribute(name));
  +        }
  +        catch (Exception e) {
  +            return defValue;
  +        }
  +    }
  +
  +    /**
  +     * getByteAttribute returns an attribute from the Configuration node.
  +     *
  +     * @param name The attribute name
  +     * @return The attribute value
  +     */
  +    public byte getByteAttribute(String name) {
  +        return getByteAttribute(name, (byte) 0);
  +    }
  +
  +    /**
  +     * getCharAttribute returns an attribute from the Configuration node.
  +     *
  +     * @param name The attribute name
  +     * @param defValue The default value
  +     * @return The attribute value
  +     */
  +    public char getCharAttribute(String name, char defValue) {
  +        try {
  +            return config.getAttribute(name).charAt(0);
  +        }
  +        catch (Exception e) {
  +            return defValue;
  +        }
  +    }
  +
  +    /**
  +     * getCharAttribute returns an attribute from the Configuration node.
  +     *
  +     * @param name The attribute name
  +     * @return The attribute value
  +     */
  +    public char getCharAttribute(String name) {
  +        return getCharAttribute(name, '\0');
  +    }
  +
  +    /**
  +     * listAttributes returns a list of the attribute names that exist for
  +     * this Configuration node.
  +     *
  +     * @return The Attribute names
  +     */
  +    public String[] listAttributes() {
  +        NamedNodeMap map = config.getAttributes();
  +        String[] result = new String[map.getLength()];
  +        int size = map.getLength();
  +        for (int i = 0; i < size; i++)
  +            result[i] = ((Attr) map.item(i)).getName();
  +        return result;
  +    }
  +
  +    /**
  +     * hasValue returns whether or not the Configuration node has a textual
  +     * value associated with it.
  +     *
  +     * @return Whether or not the node has a text value
  +     */
  +    public boolean hasValue() {
  +        NodeList list = config.getChildNodes();
  +        return (list.getLength() > 0 && list.item(0).getNodeType() == Node.TEXT_NODE);
  +    }
  +
  +    /**
  +     * getValue returns the value from the Configuration node.
  +     *
  +     * @param defValue The default value
  +     * @return The value
  +     */
  +    public String getValue(String defValue) {
  +        NodeList list = config.getChildNodes();
  +        if (list.getLength() == 1 && list.item(0).getNodeType() == Node.TEXT_NODE)
  +            return list.item(0).getNodeValue();
  +        else
  +            return defValue;
  +    }
  +
  +    /**
  +     * getValue returns the value from the Configuration node.
  +     *
  +     * @return The value
  +     */
  +    public String getValue() {
  +        return getValue("");
  +    }
  +
  +    /**
  +     * getBooleanValue returns the value from the Configuration node.
  +     *
  +     * @param defValue The default value
  +     * @return The value
  +     */
  +    public boolean getBooleanValue(boolean defValue) {
  +        try {
  +            return "[true][yes][1][y][on]".indexOf("[" + getValue().toLowerCase() + "]") != -1;
  +        }
  +        catch (Exception e) {
  +            return defValue;
  +        }
  +    }
  +
  +    /**
  +     * getBooleanValue returns the value from the Configuration node.
  +     *
  +     * @return The value
  +     */
  +    public boolean getBooleanValue() {
  +        return getBooleanValue(false);
  +    }
  +
  +    /**
  +     * getIntValue returns the value from the Configuration node.
  +     *
  +     * @param defValue The default value
  +     * @return The value
  +     */
  +    public int getIntValue(int defValue) {
  +        try {
  +            return Integer.parseInt(getValue());
  +        }
  +        catch (Exception e) {
  +            return defValue;
  +        }
  +    }
  +
  +    /**
  +     * getIntValue returns the value from the Configuration node.
  +     *
  +     * @return The value
  +     */
  +    public int getIntValue() {
  +        return getIntValue(0);
  +    }
  +
  +    /**
  +     * getShortValue returns the value from the Configuration node.
  +     *
  +     * @param defValue The default value
  +     * @return The value
  +     */
  +    public short getShortValue(short defValue) {
  +        try {
  +            return Short.parseShort(getValue());
  +        }
  +        catch (Exception e) {
  +            return defValue;
  +        }
  +    }
  +
  +    /**
  +     * getShortValue returns the value from the Configuration node.
  +     *
  +     * @return The value
  +     */
  +    public short getShortValue() {
  +        return getShortValue((short) 0);
  +    }
  +
  +    /**
  +     * getLongValue returns the value from the Configuration node.
  +     *
  +     * @param defValue The default value
  +     * @return The value
  +     */
  +    public long getLongValue(long defValue) {
  +        try {
  +            return Long.parseLong(getValue());
  +        }
  +        catch (Exception e) {
  +            return defValue;
  +        }
  +    }
  +
  +    /**
  +     * getLongValue returns the value from the Configuration node.
  +     *
  +     * @return The value
  +     */
  +    public long getLongValue() {
  +        return getLongValue(0);
  +    }
  +
  +    /**
  +     * getFloatValue returns the value from the Configuration node.
  +     *
  +     * @param defValue The default value
  +     * @return The value
  +     */
  +    public float getFloatValue(float defValue) {
  +        try {
  +            return Float.parseFloat(getValue());
  +        }
  +        catch (Exception e) {
  +            return defValue;
  +        }
  +    }
  +
  +    /**
  +     * getFloatValue returns the value from the Configuration node.
  +     *
  +     * @return The value
  +     */
  +    public float getFloatValue() {
  +        return getFloatValue((float) 0.0);
  +    }
  +
  +    /**
  +     * getDoubleValue returns the value from the Configuration node.
  +     *
  +     * @param defValue The default value
  +     * @return The value
  +     */
  +    public double getDoubleValue(double defValue) {
  +        try {
  +            return Double.parseDouble(getValue());
  +        }
  +        catch (Exception e) {
  +            return defValue;
  +        }
  +    }
  +
  +    /**
  +     * getDoubleValue returns the value from the Configuration node.
  +     *
  +     * @return The value
  +     */
  +    public double getDoubleValue() {
  +        return getDoubleValue((double) 0.0);
  +    }
  +
  +    /**
  +     * getByteValue returns the value from the Configuration node.
  +     *
  +     * @param defValue The default value
  +     * @return The value
  +     */
  +    public byte getByteValue(byte defValue) {
  +        try {
  +            return Byte.parseByte(getValue());
  +        }
  +        catch (Exception e) {
  +            return defValue;
  +        }
  +    }
  +
  +    /**
  +     * getByteValue returns the value from the Configuration node.
  +     *
  +     * @return The value
  +     */
  +    public byte getByteValue() {
  +        return getByteValue((byte) 0);
  +    }
  +
  +    /**
  +     * getCharValue returns the value from the Configuration node.
  +     *
  +     * @param defValue The default value
  +     * @return The value
  +     */
  +    public char getCharValue(char defValue) {
  +        try {
  +            return getValue().charAt(0);
  +        }
  +        catch (Exception e) {
  +            return defValue;
  +        }
  +    }
  +
  +    /**
  +     * getCharValue returns the value from the Configuration node.
  +     *
  +     * @return The value
  +     */
  +    public char getCharValue() {
  +        return getCharValue('\0');
  +    }
  +
  +    /**
  +     * hasChildren returns whether or not the Configuration node has child
  +     * Configuration elements.
  +     *
  +     * @return Whether or not children exist
  +     */
  +    public boolean hasChildren() {
  +        NodeList list = config.getChildNodes();
  +        int size = list.getLength();
  +        for (int i = 0; i < size; i++)
  +            if (list.item(i).getNodeType() == Node.ELEMENT_NODE)
  +                return true;
  +        return false;
  +    }
  +
  +    /**
  +     * getChildren returns the child Configuration nodes for this Configuration
  +     * node.
  +     *
  +     * @return The children
  +     */
  +    public Configuration[] getChildren() {
  +        NodeList list = config.getChildNodes();
  +        if (list == null)
  +            return EmptySet;
  +        List tmp = new ArrayList();
  +        int size = list.getLength();
  +        for (int i = 0; i < size; i++)
  +            if (list.item(i).getNodeType() == Node.ELEMENT_NODE)
  +                tmp.add(new Configuration((Element) list.item(i), readOnly));
  +        return (Configuration[]) tmp.toArray(EmptySet);
  +    }
  +
  +    /**
  +     * processChildren runs through the children of this Configuration and
  +     * performs prcessing callbacks to the ConfigurationCallback object.
  +     *
  +     * @param callback The callback object
  +     */
  +    public void processChildren(ConfigurationCallback callback) {
  +        NodeList list = config.getChildNodes();
  +        if (list == null)
  +            return;
  +        int size = list.getLength();
  +        try {
  +            for (int i = 0; i < size; i++)
  +                if (list.item(i).getNodeType() == Node.ELEMENT_NODE)
  +                    callback.process(new Configuration((Element) list.item(i), readOnly));
  +        }
  +        catch (Exception e) {
  +            log.warn(e);
  +        }
  +    }
  +
  +    /**
  +     * processChildren runs through the children of this Configuration and
  +     * performs prcessing callbacks to the ConfigurationCallback object.
  +     *
  +     * @param callback The callback object
  +     * @param name The Configuration name to process
  +     */
  +    public void processChildren(String name, ConfigurationCallback callback) {
  +        NodeList list = config.getChildNodes();
  +        if (list == null)
  +            return;
  +
  +        Node[] nl = new Node[list.getLength()];
  +        for (int i = 0; i < nl.length; i++)
  +            nl[i] = list.item(i);
  +
  +        int size = nl.length;
  +
  +        try {
  +            for (int i = 0; i < size; i++)
  +                if (nl[i].getNodeType() == Node.ELEMENT_NODE && nl[i].getNodeName().equals(name))
  +                    callback.process(new Configuration((Element) nl[i], readOnly));
  +        }
  +        catch (Exception e) {
  +            log.warn(e);
  +        }
  +    }
  +
  +    /**
  +     * getChild returns the first child Configuration node that matches the
  +     * specified name.
  +     *
  +     * @param name The Configuration node name
  +     * @param create Create Configuration if it doesn't exist
  +     * @return The child Configuration
  +     * @throws ReadOnlyException if the Configuration is read-only
  +     */
  +    public Configuration getChild(String name, boolean create) throws ReadOnlyException {
  +        NodeList list = config.getChildNodes();
  +        int size = list.getLength();
  +
  +        for (int i = 0; i < size; i++)
  +            if (list.item(i).getNodeType() == Node.ELEMENT_NODE && list.item(i).getNodeName().equals(name))
  +                return new Configuration((Element) list.item(i), readOnly);
  +        if (create)
  +            return add(name);
  +        else
  +            return null;
  +    }
  +
  +    /**
  +     * getChild returns the first child Configuration node that matches the
  +     * specified name.
  +     *
  +     * @param name The Configuration node name
  +     * @return The child Configuration
  +     */
  +    public Configuration getChild(String name) {
  +        try {
  +            return getChild(name, false);
  +        }
  +        catch (Exception e) {
  +            return null;
  +        }
  +    }
  +
  +    /**
  +     * isReadOnly returns whether or not this Configuration node is a
  +     * read-only node.
  +     *
  +     * @return The read-only status
  +     */
  +    public boolean isReadOnly() {
  +        return readOnly;
  +    }
  +
  +    /**
  +     * add adds a new Configuration node to this Configuration node.
  +     *
  +     * @param name The name of the Configuration node
  +     * @return The new Configuration node
  +     * @throws ReadOnlyException if the Configuration is read-only
  +     */
  +    public Configuration add(String name) throws ReadOnlyException {
  +        if (readOnly)
  +            throw new ReadOnlyException();
  +        Element elem = config.getOwnerDocument().createElement(name);
  +        config.appendChild(elem);
  +        //setDirty();
  +        return new Configuration(elem, readOnly);
  +    }
  +
  +    /**
  +     * add adds an existing Configuration node to this Configuration node.
  +     * Note!  This method does NOT perform a deep copy on the DOM Node that
  +     * newConfig manages.
  +     *
  +     * @param newConfig The Configuration node to add
  +     * @throws ReadOnlyException if the Configuration is read-only
  +     */
  +    public void add(Configuration newConfig) throws ReadOnlyException {
  +        if (readOnly)
  +            throw new ReadOnlyException();
  +        Node imported = config.getOwnerDocument().importNode(newConfig.config, true);
  +        config.appendChild(imported);
  +        newConfig.config = (Element) imported;
  +        //setDirty();
  +    }
  +
  +    /**
  +     * delete deletes this Configuration node from its parent Configuration.
  +     *
  +     * @throws ReadOnlyException if the Configuration is read-only
  +     */
  +    public void delete() throws ReadOnlyException {
  +        if (readOnly)
  +            throw new ReadOnlyException();
  +        if (config.getParentNode() != null)
  +            config.getParentNode().removeChild(config);
  +        //setDirty();
  +    }
  +
  +    /**
  +     * removeAttribute removes the named attribute from this Configuration.
  +     *
  +     * @param name The attribute name
  +     * @throws ReadOnlyException if the Configuration is read-only
  +     */
  +    public void removeAttribute(String name) throws ReadOnlyException {
  +        if (readOnly)
  +            throw new ReadOnlyException();
  +        config.removeAttribute(name);
  +        //setDirty();
  +    }
  +
  +    /**
  +     * setAttribute sets the attribute value for this Configuration.
  +     *
  +     * @param name The attribute name
  +     * @param value The attribute value
  +     * @throws ReadOnlyException if the Configuration is read-only
  +     */
  +    public void setAttribute(String name, String value) throws ReadOnlyException {
  +        if (readOnly)
  +            throw new ReadOnlyException();
  +        config.setAttribute(name, value);
  +        //setDirty();
  +    }
  +
  +    /**
  +     * setAttribute sets the attribute value for this Configuration.
  +     *
  +     * @param name The attribute name
  +     * @param value The attribute value
  +     * @throws ReadOnlyException if the Configuration is read-only
  +     */
  +    public void setAttribute(String name, boolean value) throws ReadOnlyException {
  +        setAttribute(name, String.valueOf(value));
  +    }
  +
  +    /**
  +     * setAttribute sets the attribute value for this Configuration.
  +     *
  +     * @param name The attribute name
  +     * @param value The attribute value
  +     * @throws ReadOnlyException if the Configuration is read-only
  +     */
  +    public void setAttribute(String name, int value) throws ReadOnlyException {
  +        setAttribute(name, String.valueOf(value));
  +    }
  +
  +    /**
  +     * setAttribute sets the attribute value for this Configuration.
  +     *
  +     * @param name The attribute name
  +     * @param value The attribute value
  +     * @throws ReadOnlyException if the Configuration is read-only
  +     */
  +    public void setAttribute(String name, short value) throws ReadOnlyException {
  +        setAttribute(name, String.valueOf(value));
  +    }
  +
  +    /**
  +     * setAttribute sets the attribute value for this Configuration.
  +     *
  +     * @param name The attribute name
  +     * @param value The attribute value
  +     * @throws ReadOnlyException if the Configuration is read-only
  +     */
  +    public void setAttribute(String name, long value) throws ReadOnlyException {
  +        setAttribute(name, String.valueOf(value));
  +    }
  +
  +    /**
  +     * setAttribute sets the attribute value for this Configuration.
  +     *
  +     * @param name The attribute name
  +     * @param value The attribute value
  +     * @throws ReadOnlyException if the Configuration is read-only
  +     */
  +    public void setAttribute(String name, float value) throws ReadOnlyException {
  +        setAttribute(name, String.valueOf(value));
  +    }
  +
  +    /**
  +     * setAttribute sets the attribute value for this Configuration.
  +     *
  +     * @param name The attribute name
  +     * @param value The attribute value
  +     * @throws ReadOnlyException if the Configuration is read-only
  +     */
  +    public void setAttribute(String name, double value) throws ReadOnlyException {
  +        setAttribute(name, String.valueOf(value));
  +    }
  +
  +    /**
  +     * setAttribute sets the attribute value for this Configuration.
  +     *
  +     * @param name The attribute name
  +     * @param value The attribute value
  +     * @throws ReadOnlyException if the Configuration is read-only
  +     */
  +    public void setAttribute(String name, byte value) throws ReadOnlyException {
  +        setAttribute(name, String.valueOf(value));
  +    }
  +
  +    /**
  +     * setAttribute sets the attribute value for this Configuration.
  +     *
  +     * @param name The attribute name
  +     * @param value The attribute value
  +     * @throws ReadOnlyException if the Configuration is read-only
  +     */
  +    public void setAttribute(String name, char value) throws ReadOnlyException {
  +        setAttribute(name, String.valueOf(value));
  +    }
  +
  +    /**
  +     * setValue sets the value of the Configuration node.
  +     *
  +     * @param value The New Value
  +     * @throws ReadOnlyException if the Configuration is read-only
  +     */
  +    public void setValue(String value) throws ReadOnlyException {
  +        if (readOnly)
  +            throw new ReadOnlyException();
  +        NodeList list = config.getChildNodes();
  +        if (list.getLength() == 1 && list.item(0).getNodeType() == Node.TEXT_NODE)
  +            list.item(0).setNodeValue(value);
  +        else {
  +            Text text = config.getOwnerDocument().createTextNode(value);
  +            config.appendChild(text);
  +        }
  +        //setDirty();
  +    }
  +
  +    /**
  +     * setValue sets the value of the Configuration node.
  +     *
  +     * @param value The New Value
  +     * @throws ReadOnlyException if the Configuration is read-only
  +     */
  +    public void setValue(boolean value) throws ReadOnlyException {
  +        setValue(String.valueOf(value));
  +    }
  +
  +    /**
  +     * setValue sets the value of the Configuration node.
  +     *
  +     * @param value The New Value
  +     * @throws ReadOnlyException if the Configuration is read-only
  +     */
  +    public void setValue(int value) throws ReadOnlyException {
  +        setValue(String.valueOf(value));
  +    }
  +
  +    /**
  +     * setValue sets the value of the Configuration node.
  +     *
  +     * @param value The New Value
  +     * @throws ReadOnlyException if the Configuration is read-only
  +     */
  +    public void setValue(short value) throws ReadOnlyException {
  +        setValue(String.valueOf(value));
  +    }
  +
  +    /**
  +     * setValue sets the value of the Configuration node.
  +     *
  +     * @param value The New Value
  +     * @throws ReadOnlyException if the Configuration is read-only
  +     */
  +    public void setValue(long value) throws ReadOnlyException {
  +        setValue(String.valueOf(value));
  +    }
  +
  +    /**
  +     * setValue sets the value of the Configuration node.
  +     *
  +     * @param value The New Value
  +     * @throws ReadOnlyException if the Configuration is read-only
  +     */
  +    public void setValue(float value) throws ReadOnlyException {
  +        setValue(String.valueOf(value));
  +    }
  +
  +    /**
  +     * setValue sets the value of the Configuration node.
  +     *
  +     * @param value The New Value
  +     * @throws ReadOnlyException if the Configuration is read-only
  +     */
  +    public void setValue(double value) throws ReadOnlyException {
  +        setValue(String.valueOf(value));
  +    }
  +
  +    /**
  +     * setValue sets the value of the Configuration node.
  +     *
  +     * @param value The New Value
  +     * @throws ReadOnlyException if the Configuration is read-only
  +     */
  +    public void setValue(byte value) throws ReadOnlyException {
  +        setValue(String.valueOf(value));
  +    }
  +
  +    /**
  +     * setValue sets the value of the Configuration node.
  +     *
  +     * @param value The New Value
  +     * @throws ReadOnlyException if the Configuration is read-only
  +     */
  +    public void setValue(char value) throws ReadOnlyException {
  +        setValue(String.valueOf(value));
  +    }
   }
  -
  
  
  
  1.10      +432 -443  xml-xindice/java/src/org/apache/xindice/core/request/URIMapper.java
  
  Index: URIMapper.java
  ===================================================================
  RCS file: /home/cvs/xml-xindice/java/src/org/apache/xindice/core/request/URIMapper.java,v
  retrieving revision 1.9
  retrieving revision 1.10
  diff -u -r1.9 -r1.10
  --- URIMapper.java	19 Nov 2002 05:16:58 -0000	1.9
  +++ URIMapper.java	15 Jul 2003 15:44:36 -0000	1.10
  @@ -59,6 +59,15 @@
    * $Id$
    */
   
  +import java.io.ByteArrayInputStream;
  +import java.io.IOException;
  +import java.io.InputStream;
  +import java.net.URL;
  +import java.net.URLConnection;
  +import java.util.Properties;
  +
  +import org.apache.commons.logging.Log;
  +import org.apache.commons.logging.LogFactory;
   import org.apache.xindice.core.Collection;
   import org.apache.xindice.core.Container;
   import org.apache.xindice.core.DBException;
  @@ -68,18 +77,7 @@
   import org.apache.xindice.util.Poolable;
   import org.apache.xindice.util.XindiceException;
   import org.apache.xindice.xml.TextWriter;
  -
  -import org.apache.commons.logging.Log;
  -import org.apache.commons.logging.LogFactory;
  -
  -import org.w3c.dom.*;
  -
  -import java.io.ByteArrayInputStream;
  -import java.io.IOException;
  -import java.io.InputStream;
  -import java.net.URL;
  -import java.net.URLConnection;
  -import java.util.Properties;
  +import org.w3c.dom.Document;
   
   /**
    * URIMapper maps a URI (from whence it came) to a Xindice object.  Xindice
  @@ -90,443 +88,434 @@
   
   public final class URIMapper extends URLConnection implements Poolable {
   
  -   public static final int UNKNOWN = -1;
  -   public static final int APPLICATION = 1;
  -   public static final int COLLECTION = 2;
  -   public static final int DOCUMENT = 3;
  +    public static final int UNKNOWN = -1;
  +    public static final int APPLICATION = 1;
  +    public static final int COLLECTION = 2;
  +    public static final int DOCUMENT = 3;
   
       public static final String DEFAULT_ENCODING = "UTF-8";
   
  -   private static Log log = LogFactory.getLog("org.apache.xindice.core");
  -
  -   private ObjectPool   pool = null;
  -   private String       uri = null;
  -   private int          type = 0;
  -
  -   private byte[]       buf = null;
  -   private int          pos = 0;
  -   private char         lastChar = 0;
  -
  -   private Database  db = null;
  -   private Collection   collection = null;
  -   private Document     document = null;
  -   private String       method = null;
  -   private Container    container = null;
  +    private static Log log = LogFactory.getLog("org.apache.xindice.core");
   
  -   private Properties   params = null;
  -   private String[]     args = null;
  -
  -   private String       urlresult = null;       // Holds the value of the URL resolution results (XML doc or XMLObject call results )
  -   private boolean      inputstreamset = false; // Flag to tell if the input stream has been initialized
  -
  -   /** Constructor for creating URIMapper instance using a standard URL
  -    */
  -   public URIMapper(URL u) {
  -      super(u);
  -      try {
  -         setURI(u.toString());
  -      }
  -      catch ( Exception e) {
  -         // Put error code here!
  -         if (log.isDebugEnabled()) {
  -            log.debug("No message", e);
  -         }
  -      }
  -   }
  -
  -   /** Constructor for older URIMapper instances
  -    */
  -   public URIMapper(String uri) throws XindiceException {
  -      super(null);
  -      setURI(uri);
  -   }
  -
  -   /** Constructor for older URIMapper instances
  -    */
  -   public URIMapper() {
  -      super(null);
  -   }
  -
  -   /**
  -      Opens a communications link to the resource referenced by this URL,
  -      if such a connection has not already been established.
  -   */
  -   public void connect() {
  -      this.connected=true;
  -   }
  -
  -   /**
  -      Returns an input stream that reads from this open connection.
  -   */
  -   public InputStream getInputStream() throws IOException {
  -
  -      String output = null ;
  -
  -      // Check if the inputstream has already been initialized, if not do now, else return the contents of urlresult
  -      if ( ! inputstreamset ) {
  -         try {
  -            switch ( type ) {
  -
  -               case URIMapper.DOCUMENT:
  -                  output = TextWriter.toString( getDocument() );
  -                  break;
  -
  -               default:
  -                  //  Document type not found, output error message
  -                  throw new Exception("Content type unsupported");
  +    private ObjectPool pool = null;
  +    private String uri = null;
  +    private int type = 0;
  +
  +    private byte[] buf = null;
  +    private int pos = 0;
  +    private char lastChar = 0;
  +
  +    private Database db = null;
  +    private Collection collection = null;
  +    private Document document = null;
  +    private String method = null;
  +    private Container container = null;
  +
  +    private Properties params = null;
  +    private String[] args = null;
  +
  +    private String urlresult = null; // Holds the value of the URL resolution results (XML doc or XMLObject call results )
  +    private boolean inputstreamset = false; // Flag to tell if the input stream has been initialized
  +
  +    /** Constructor for creating URIMapper instance using a standard URL
  +     */
  +    public URIMapper(URL u) {
  +        super(u);
  +        try {
  +            setURI(u.toString());
  +        }
  +        catch (Exception e) {
  +            // Put error code here!
  +            log.warn(e);
  +        }
  +    }
  +
  +    /** Constructor for older URIMapper instances
  +     */
  +    public URIMapper(String uri) throws XindiceException {
  +        super(null);
  +        setURI(uri);
  +    }
  +
  +    /** Constructor for older URIMapper instances
  +     */
  +    public URIMapper() {
  +        super(null);
  +    }
  +
  +    /**
  +       Opens a communications link to the resource referenced by this URL,
  +       if such a connection has not already been established.
  +    */
  +    public void connect() {
  +        this.connected = true;
  +    }
  +
  +    /**
  +       Returns an input stream that reads from this open connection.
  +    */
  +    public InputStream getInputStream() throws IOException {
  +
  +        String output = null;
  +
  +        // Check if the inputstream has already been initialized, if not do now, else return the contents of urlresult
  +        if (!inputstreamset) {
  +            try {
  +                switch (type) {
  +
  +                    case URIMapper.DOCUMENT :
  +                        output = TextWriter.toString(getDocument());
  +                        break;
  +
  +                    default :
  +                        //  Document type not found, output error message
  +                        throw new Exception("Content type unsupported");
  +                }
               }
  -         }
  -         catch ( Exception e ) {
  -            if (log.isDebugEnabled()) {
  -               log.debug("No message", e);
  +            catch (Exception e) {
  +                log.warn(e);
               }
  -         }
  -      }
  -      // Inputstream already initialized, set output to be value of urlresult
  -      else {
  -         output=urlresult ;
  -      }
  -
  -      // Save the value of output into local variable urlresult
  -      urlresult = output ;
  -      // Set inpustreamset flag to signal that url has already been resolved
  -      inputstreamset = true ;
  -
  -      // Send the result to the client, sending blank string if NULL
  -      if ( output == null) {
  -	  return new ByteArrayInputStream( new byte[0] );
  -      } else {
  -	  return new ByteArrayInputStream( output.getBytes( DEFAULT_ENCODING ) );
  -      }
  -   }
  -
  -   /**
  -    * Returns the value of the content-encoding header field.
  -    * Returns:
  -    *       the content encoding of the resource that the URL references, or null if not known.
  -    */
  -   public String getContentEncoding() {
  -       return DEFAULT_ENCODING;
  -   }
  -
  -   /**
  -    * Returns the value of the content-type header field.
  -    * Returns:
  -    *       the content type of the resource that the URL references, or null if not known.
  -    */
  -   public String getContentType() {
  -      // Return the docuement's content type, for now this can only be "text/xml"
  -      return new String("text/xml");
  -   }
  -
  -   /**
  -    * Returns the value of the content-length header field.
  -    * Returns:
  -    *       the content length of the resource that this connection's URL references, or -1 if the content length is not known.
  -    */
  -   public int getContentLength() {
  -      // Check to see if this document has already been resolved, if not call getInputStream
  -      if ( ! inputstreamset ) {
  -	  try {
  -	      this.getInputStream();
  -	  }
  -	  catch ( IOException e ) {
  -	      return 0;
  -	  }
  -      }
  -
  -      // Return the lenght of this document/XMLObject call
  -      return urlresult.length();
  -   }
  -
  -   /**
  -    * Returns the value of the last-modified header field. The result is the number of milliseconds since January 1, 1970 GMT.
  -    * Returns:
  -    *  the date the resource referenced by this URLConnection was last modified, or 0 if not known.
  -    */
  -   public long getLastModified() {
  -      // For now this functionality is not available, return 0
  -      return 0 ;
  -   }
  -
  -   public void setPool(ObjectPool pool) {
  -      this.pool = pool;
  -   }
  -
  -   public void reclaim() {
  -      reset();
  -      if ( pool != null )
  -         pool.putObject(this);
  -   }
  -
  -   /**
  -    * reset resets the state of the URIMapper.
  -    */
  -   private void reset() {
  -      type = UNKNOWN;
  -      lastChar = 0;
  -      method = "";
  -      db = null;
  -      collection = null;
  -      document = null;
  -      params = null;
  -      args = null;
  -      container = null;
  -
  -      // reset urlresult and inputstreamset
  -      urlresult = null ;
  -      inputstreamset = false ;
  -   }
  -
  -   /**
  -    * setURI sets the URI for the URIMapper and parses it.  The parsed
  -    * components of a URI can be retrieved using getObjectType and any
  -    * of the get<component> methods.
  -    *
  -    * @param uri The URI
  -    */
  -   public void setURI(String uri) throws XindiceException {
  -      this.uri = uri;
  -      reset();
  -      parse();
  -   }
  -
  -   /**
  -    * parseName parses an identifier up to any of the specified delimiters.
  -    *
  -    * @param delims The delimiters to use
  -    * @return The parsed name
  -    */
  -   private String parseName(String delims) {
  -      int start = pos;
  -      while ( pos < buf.length ) {
  -         lastChar = (char)buf[pos++];
  -         if ( delims.indexOf(lastChar) != -1 )
  -            break;
  -      }
  -      if ( pos == buf.length && delims.indexOf(lastChar) == -1 )
  -         pos++;
  -      return pos > start ? new String(buf, start, pos-start-1)
  -                         : "";
  -   }
  -
  -   /**
  -    * parseParams parses a parameter set and produces either a Properties or
  -    * String[] Object representing those parameters.
  -    */
  -   private void parseParams() {
  -      if ( lastChar == '?' ) {
  -         // Query String param list
  -         params = new Properties();
  -         String name;
  -         String value;
  -         String temp;
  -         while ( true ) {
  -            name = parseName("=");
  -            if ( name.length() == 0 )
  -               break;
  -            value = parseName("?&;");
  -            temp = params.getProperty(name);
  -            if( temp != null ) {
  -               StringBuffer sb = new StringBuffer(32);
  -               sb.append(temp);
  -               sb.append('\u0001');
  -               sb.append(value);
  -               value = sb.toString();
  +        }
  +        // Inputstream already initialized, set output to be value of urlresult
  +        else {
  +            output = urlresult;
  +        }
  +
  +        // Save the value of output into local variable urlresult
  +        urlresult = output;
  +        // Set inpustreamset flag to signal that url has already been resolved
  +        inputstreamset = true;
  +
  +        // Send the result to the client, sending blank string if NULL
  +        if (output == null) {
  +            return new ByteArrayInputStream(new byte[0]);
  +        }
  +        else {
  +            return new ByteArrayInputStream(output.getBytes(DEFAULT_ENCODING));
  +        }
  +    }
  +
  +    /**
  +     * Returns the value of the content-encoding header field.
  +     * Returns:
  +     *       the content encoding of the resource that the URL references, or null if not known.
  +     */
  +    public String getContentEncoding() {
  +        return DEFAULT_ENCODING;
  +    }
  +
  +    /**
  +     * Returns the value of the content-type header field.
  +     * Returns:
  +     *       the content type of the resource that the URL references, or null if not known.
  +     */
  +    public String getContentType() {
  +        // Return the docuement's content type, for now this can only be "text/xml"
  +        return new String("text/xml");
  +    }
  +
  +    /**
  +     * Returns the value of the content-length header field.
  +     * Returns:
  +     *       the content length of the resource that this connection's URL references, or -1 if the content length is not known.
  +     */
  +    public int getContentLength() {
  +        // Check to see if this document has already been resolved, if not call getInputStream
  +        if (!inputstreamset) {
  +            try {
  +                this.getInputStream();
               }
  -            params.setProperty(name, value);
  -         }
  -      }
  -      else
  -         params = new Properties();
  -   }
  -
  -   /**
  -    * parse parses the URI.
  -    */
  -   private void parse() throws XindiceException {
  -      buf = uri.getBytes();
  -      pos = 0;
  -      String tmp;
  -
  -      if ( buf.length == 0 ) {
  -         throw new DBException(FaultCodes.URI_EMPTY);
  -      }
  -
  -      // TODO: Be Able To Handle Remote URIs
  -      if ( (char)buf[0] != '/' ) {
  -         parseName(":"); // Ignore Protocol
  -         parseName("/"); // Ignore Slash
  -         parseName("/"); // Ignore Slash
  -         parseName("/:"); // Ignore Host (For Now)
  -         if ( lastChar == ':' )
  -            parseName("/"); // Ignore Port
  -      }
  -      else
  -         pos = 1;
  -
  -      // Database check
  -      tmp = parseName("/");
  -      if ( tmp == null )
  -         return;
  -
  -      db = Database.getDatabase(tmp);
  -      if ( db == null )
  -         return;
  -
  -      type = APPLICATION;
  -      tmp = parseName("/(?");
  -
  -
  -      int objType = getParsedObjectType(db, tmp);
  -      // If unknown then this URI just points to db and we're done.
  -      // Otherwise we need to keep walking down the URI.
  -      if (objType != UNKNOWN) {
  -         type = walkURI(db, tmp, objType);
  -      }
  -
  -      if ( lastChar == '?' ) {
  -         parseParams();
  -         return;
  -      }
  -   }
  -
  -   /**
  -    * Recursive method to handle the parse of the URI and setup the instance
  -    * objects.
  -    */
  -   protected int walkURI(Collection col, String name, int objType)
  -         throws XindiceException {
  -      switch (objType) {
  -         case DOCUMENT:
  -            container = col.getContainer(name);
  -            document = container.getDocument();
  -            return DOCUMENT;
  -
  -         case COLLECTION:
  -            Collection c = col.getCollection(name);
  -            if ( c != null ) {
  -               collection = c;
  -               String tmp = parseName("/(?");
  -               // If we have another name recurse to handle it.
  -               if (! tmp.equals("")) {
  -                  return walkURI(c, tmp, getParsedObjectType(c, tmp));
  -               }
  -
  -               return COLLECTION;
  +            catch (IOException e) {
  +                return 0;
               }
  -      }
  +        }
   
  -      return UNKNOWN;
  -   }
  -
  -   /**
  -    * Determine the type of object. If more then one object has the same name
  -    * the order of precedence is COLLECTION - XMLOBJECT - DOCUMENT
  -    */
  -   protected int getParsedObjectType(Collection col, String name)
  -         throws XindiceException {
  -
  -      if (col.getCollection(name) != null) {
  -         return COLLECTION;
  -      }
  -      else if ((col.getFiler() != null) && (col.getContainer(name) != null)) {
  -         return DOCUMENT;
  -      }
  -      else {
  -         return UNKNOWN;
  -      }
  -   }
  -
  -   /**
  -    * getObjectType returns the type of Object that was identified in the
  -    * parsing of the URI.  This method will return one of the following
  -    * values: UNKNOWN, APPLICATION, DATABASE, COLLECTION, DOCUMENT or
  -    * XMLOBJECT.
  -    *
  -    * @return The object type
  -    */
  -   public int getObjectType() {
  -      return type;
  -   }
  -
  -   /**
  -    * getDatabase returns the Database that was resolved in the
  -    * parsing of this URI.
  -    *
  -    * @return The Database
  -    */
  -   public Database getDatabase() {
  -      return db;
  -   }
  -
  -   /**
  -    * getCollection returns the Collection object that was resolved in the
  -    * parsing of the URI.  If no Collection was resolved, this method will
  -    * return null.
  -    *
  -    * @return The Collection
  -    */
  -   public Collection getCollection() {
  -      return collection;
  -   }
  -
  -   /**
  -    * getDocument returns the Document object that was resolved in the
  -    * parsing of the URI.  If no Document was resolved, this method will
  -    * return null.
  -    *
  -    * @return The Document
  -    */
  -   public Document getDocument() {
  -      return document;
  -   }
  -
  -   /**
  -    * getContainer returns the Document Container that was resolved in
  -    * the parsing of the URI.  If no Container was resolved, this method
  -    * will return null.
  -    *
  -    * @return The Container
  -    */
  -   public Container getContainer() {
  -      return container;
  -   }
  -
  -   /**
  -    * getMethod returns the method name that was resolved in the parsing
  -    * of the URI.  Method names are associated with XMLObjects.
  -    * If no method name was resolved, this method will return null.
  -    *
  -    * @return The method name
  -    */
  -   public String getMethod() {
  -      return method;
  -   }
  -
  -   /**
  -    * getProperties returns the Properties object that was produced in
  -    * parsing the URI's Query String.  Properties are passed into methods
  -    * that are associated with XMLObjects.  This method will return null if
  -    * no Properties were resolved.
  -    *
  -    * @return The Query String Properties
  -    */
  -   public Properties getProperties() {
  -      return params;
  -   }
  -
  -   /**
  -    * getArguments returns method arguments in the form of a String array.
  -    * Method arguments are passed to a method in the order that they are
  -    * specified in the URI.  If no arguments were parsed, this method will
  -    * return null.
  -    *
  -    * @return The method arguments
  -    */
  -   public String[] getArguments() {
  -      return args;
  -   }
  +        // Return the lenght of this document/XMLObject call
  +        return urlresult.length();
  +    }
  +
  +    /**
  +     * Returns the value of the last-modified header field. The result is the number of milliseconds since January 1, 1970 GMT.
  +     * Returns:
  +     *  the date the resource referenced by this URLConnection was last modified, or 0 if not known.
  +     */
  +    public long getLastModified() {
  +        // For now this functionality is not available, return 0
  +        return 0;
  +    }
  +
  +    public void setPool(ObjectPool pool) {
  +        this.pool = pool;
  +    }
  +
  +    public void reclaim() {
  +        reset();
  +        if (pool != null)
  +            pool.putObject(this);
  +    }
  +
  +    /**
  +     * reset resets the state of the URIMapper.
  +     */
  +    private void reset() {
  +        type = UNKNOWN;
  +        lastChar = 0;
  +        method = "";
  +        db = null;
  +        collection = null;
  +        document = null;
  +        params = null;
  +        args = null;
  +        container = null;
  +
  +        // reset urlresult and inputstreamset
  +        urlresult = null;
  +        inputstreamset = false;
  +    }
  +
  +    /**
  +     * setURI sets the URI for the URIMapper and parses it.  The parsed
  +     * components of a URI can be retrieved using getObjectType and any
  +     * of the get<component> methods.
  +     *
  +     * @param uri The URI
  +     */
  +    public void setURI(String uri) throws XindiceException {
  +        this.uri = uri;
  +        reset();
  +        parse();
  +    }
  +
  +    /**
  +     * parseName parses an identifier up to any of the specified delimiters.
  +     *
  +     * @param delims The delimiters to use
  +     * @return The parsed name
  +     */
  +    private String parseName(String delims) {
  +        int start = pos;
  +        while (pos < buf.length) {
  +            lastChar = (char) buf[pos++];
  +            if (delims.indexOf(lastChar) != -1)
  +                break;
  +        }
  +        if (pos == buf.length && delims.indexOf(lastChar) == -1)
  +            pos++;
  +        return pos > start ? new String(buf, start, pos - start - 1) : "";
  +    }
  +
  +    /**
  +     * parseParams parses a parameter set and produces either a Properties or
  +     * String[] Object representing those parameters.
  +     */
  +    private void parseParams() {
  +        if (lastChar == '?') {
  +            // Query String param list
  +            params = new Properties();
  +            String name;
  +            String value;
  +            String temp;
  +            while (true) {
  +                name = parseName("=");
  +                if (name.length() == 0)
  +                    break;
  +                value = parseName("?&;");
  +                temp = params.getProperty(name);
  +                if (temp != null) {
  +                    StringBuffer sb = new StringBuffer(32);
  +                    sb.append(temp);
  +                    sb.append('\u0001');
  +                    sb.append(value);
  +                    value = sb.toString();
  +                }
  +                params.setProperty(name, value);
  +            }
  +        }
  +        else
  +            params = new Properties();
  +    }
  +
  +    /**
  +     * parse parses the URI.
  +     */
  +    private void parse() throws XindiceException {
  +        buf = uri.getBytes();
  +        pos = 0;
  +        String tmp;
  +
  +        if (buf.length == 0) {
  +            throw new DBException(FaultCodes.URI_EMPTY);
  +        }
  +
  +        // TODO: Be Able To Handle Remote URIs
  +        if ((char) buf[0] != '/') {
  +            parseName(":"); // Ignore Protocol
  +            parseName("/"); // Ignore Slash
  +            parseName("/"); // Ignore Slash
  +            parseName("/:"); // Ignore Host (For Now)
  +            if (lastChar == ':')
  +                parseName("/"); // Ignore Port
  +        }
  +        else
  +            pos = 1;
  +
  +        // Database check
  +        tmp = parseName("/");
  +        if (tmp == null)
  +            return;
  +
  +        db = Database.getDatabase(tmp);
  +        if (db == null)
  +            return;
  +
  +        type = APPLICATION;
  +        tmp = parseName("/(?");
  +
  +        int objType = getParsedObjectType(db, tmp);
  +        // If unknown then this URI just points to db and we're done.
  +        // Otherwise we need to keep walking down the URI.
  +        if (objType != UNKNOWN) {
  +            type = walkURI(db, tmp, objType);
  +        }
  +
  +        if (lastChar == '?') {
  +            parseParams();
  +            return;
  +        }
  +    }
  +
  +    /**
  +     * Recursive method to handle the parse of the URI and setup the instance
  +     * objects.
  +     */
  +    protected int walkURI(Collection col, String name, int objType) throws XindiceException {
  +        switch (objType) {
  +            case DOCUMENT :
  +                container = col.getContainer(name);
  +                document = container.getDocument();
  +                return DOCUMENT;
  +
  +            case COLLECTION :
  +                Collection c = col.getCollection(name);
  +                if (c != null) {
  +                    collection = c;
  +                    String tmp = parseName("/(?");
  +                    // If we have another name recurse to handle it.
  +                    if (!tmp.equals("")) {
  +                        return walkURI(c, tmp, getParsedObjectType(c, tmp));
  +                    }
  +
  +                    return COLLECTION;
  +                }
  +        }
  +
  +        return UNKNOWN;
  +    }
  +
  +    /**
  +     * Determine the type of object. If more then one object has the same name
  +     * the order of precedence is COLLECTION - XMLOBJECT - DOCUMENT
  +     */
  +    protected int getParsedObjectType(Collection col, String name) throws XindiceException {
  +
  +        if (col.getCollection(name) != null) {
  +            return COLLECTION;
  +        }
  +        else if ((col.getFiler() != null) && (col.getContainer(name) != null)) {
  +            return DOCUMENT;
  +        }
  +        else {
  +            return UNKNOWN;
  +        }
  +    }
  +
  +    /**
  +     * getObjectType returns the type of Object that was identified in the
  +     * parsing of the URI.  This method will return one of the following
  +     * values: UNKNOWN, APPLICATION, DATABASE, COLLECTION, DOCUMENT or
  +     * XMLOBJECT.
  +     *
  +     * @return The object type
  +     */
  +    public int getObjectType() {
  +        return type;
  +    }
  +
  +    /**
  +     * getDatabase returns the Database that was resolved in the
  +     * parsing of this URI.
  +     *
  +     * @return The Database
  +     */
  +    public Database getDatabase() {
  +        return db;
  +    }
  +
  +    /**
  +     * getCollection returns the Collection object that was resolved in the
  +     * parsing of the URI.  If no Collection was resolved, this method will
  +     * return null.
  +     *
  +     * @return The Collection
  +     */
  +    public Collection getCollection() {
  +        return collection;
  +    }
  +
  +    /**
  +     * getDocument returns the Document object that was resolved in the
  +     * parsing of the URI.  If no Document was resolved, this method will
  +     * return null.
  +     *
  +     * @return The Document
  +     */
  +    public Document getDocument() {
  +        return document;
  +    }
  +
  +    /**
  +     * getContainer returns the Document Container that was resolved in
  +     * the parsing of the URI.  If no Container was resolved, this method
  +     * will return null.
  +     *
  +     * @return The Container
  +     */
  +    public Container getContainer() {
  +        return container;
  +    }
  +
  +    /**
  +     * getMethod returns the method name that was resolved in the parsing
  +     * of the URI.  Method names are associated with XMLObjects.
  +     * If no method name was resolved, this method will return null.
  +     *
  +     * @return The method name
  +     */
  +    public String getMethod() {
  +        return method;
  +    }
  +
  +    /**
  +     * getProperties returns the Properties object that was produced in
  +     * parsing the URI's Query String.  Properties are passed into methods
  +     * that are associated with XMLObjects.  This method will return null if
  +     * no Properties were resolved.
  +     *
  +     * @return The Query String Properties
  +     */
  +    public Properties getProperties() {
  +        return params;
  +    }
  +
  +    /**
  +     * getArguments returns method arguments in the form of a String array.
  +     * Method arguments are passed to a method in the order that they are
  +     * specified in the URI.  If no arguments were parsed, this method will
  +     * return null.
  +     *
  +     * @return The method arguments
  +     */
  +    public String[] getArguments() {
  +        return args;
  +    }
   }
  -
  -
  
  
  
  1.4       +281 -287  xml-xindice/java/src/org/apache/xindice/core/query/QueryEngine.java
  
  Index: QueryEngine.java
  ===================================================================
  RCS file: /home/cvs/xml-xindice/java/src/org/apache/xindice/core/query/QueryEngine.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- QueryEngine.java	31 Oct 2002 06:59:58 -0000	1.3
  +++ QueryEngine.java	15 Jul 2003 15:44:36 -0000	1.4
  @@ -59,6 +59,15 @@
    * $Id$
    */
   
  +import java.util.ArrayList;
  +import java.util.HashMap;
  +import java.util.List;
  +import java.util.Map;
  +import java.util.SortedSet;
  +import java.util.TreeSet;
  +
  +import org.apache.commons.logging.Log;
  +import org.apache.commons.logging.LogFactory;
   import org.apache.xindice.core.Collection;
   import org.apache.xindice.core.DBException;
   import org.apache.xindice.core.Database;
  @@ -71,16 +80,6 @@
   import org.apache.xindice.util.XindiceException;
   import org.apache.xindice.xml.NamespaceMap;
   
  -import org.apache.commons.logging.Log;
  -import org.apache.commons.logging.LogFactory;
  -
  -import java.util.ArrayList;
  -import java.util.HashMap;
  -import java.util.List;
  -import java.util.Map;
  -import java.util.SortedSet;
  -import java.util.TreeSet;
  -
   /**
    * QueryEngine is the Xindice Query Engine.  Its purpose is to orchestrate
    * query operations against the Xindice repository.  The QueryEngine
  @@ -89,293 +88,288 @@
    */
   
   public class QueryEngine extends SimpleConfigurable {
  -   private static final String[] EmptyStrings = new String[0];
  -   private static final Key[] EmptyKeys = new Key[0];
  +    private static final String[] EmptyStrings = new String[0];
  +    private static final Key[] EmptyKeys = new Key[0];
   
  -   private static final String RESOLVER = "resolver";
  -   private static final String CLASS = "class";
  +    private static final String RESOLVER = "resolver";
  +    private static final String CLASS = "class";
   
  -   private static Log log = LogFactory.getLog("org.apache.xindice.core");
  +    private static Log log = LogFactory.getLog("org.apache.xindice.core");
   
  -   private Database db;
  -   private Map resolvers = new HashMap();
  +    private Database db;
  +    private Map resolvers = new HashMap();
   
  -   public QueryEngine(Database db) {
  -      this.db = db;
  -   }
  +    public QueryEngine(Database db) {
  +        this.db = db;
  +    }
   
  -   public void setConfig(Configuration config) throws XindiceException {
  -      super.setConfig(config);
  -      config.processChildren(RESOLVER,
  -         new ConfigurationCallback() {
  +    public void setConfig(Configuration config) throws XindiceException {
  +        super.setConfig(config);
  +        config.processChildren(RESOLVER, new ConfigurationCallback() {
               public void process(Configuration cfg) {
  -               String className = cfg.getAttribute(CLASS);
  -               try {
  -                  QueryResolver res = (QueryResolver)Class.forName(className).newInstance();
  -                  res.setConfig(cfg);
  -                  res.setQueryEngine(QueryEngine.this);
  -                  resolvers.put(res.getQueryStyle(), res);
  -               }
  -               catch ( Exception e ) {
  -                  if (log.isDebugEnabled()) {
  -                     log.debug("No message", e);
  -                  }
  -               }
  +                String className = cfg.getAttribute(CLASS);
  +                try {
  +                    QueryResolver res = (QueryResolver) Class.forName(className).newInstance();
  +                    res.setConfig(cfg);
  +                    res.setQueryEngine(QueryEngine.this);
  +                    resolvers.put(res.getQueryStyle(), res);
  +                }
  +                catch (Exception e) {
  +                    log.warn(e);
  +                }
               }
  -      });
  -   }
  +        });
  +    }
   
  -   public Database getDatabase() {
  -      return db;
  -   }
  -
  -   /**
  -    * listStyles returns a list of styles supported by the
  -    * QueryEngine (ex: XPath, XUpdate)
  -    *
  -    * @return The supported styles
  -    */
  -   public String[] listStyles() {
  -      return (String[])resolvers.keySet().toArray(EmptyStrings);
  -   }
  -
  -   private QueryResolver getResolver(String style) throws QueryException {
  -      QueryResolver res = (QueryResolver)resolvers.get(style);
  -      if ( res == null )
  -         throw new StyleNotFoundException("No Resolver available for '"+style+"' queries");
  -      return res;
  -   }
  -   
  -   /**
  -    * query performs the specified query and returns a NodeSet with
  -    * any possible results from that query.  The query is performed
  -    * in the context of a Collection.
  -    *
  -    * @param col The Collection context
  -    * @param style The query style (XPath, Fulltext, etc...)
  -    * @param query The Query
  -    * @param nsMap The namespace Map (if any)
  -    * @param keys The initial Key set to use (if any)
  -    * @return A NodeSet with the query results
  -    */
  -   public NodeSet query(Collection col, String style, String query, NamespaceMap nsMap, Key[] keys) throws DBException, QueryException {
  -      QueryResolver res = getResolver(style);
  -      return res.query(col, query, nsMap, keys);
  -   }
  -
  -   /**
  -    * compileQuery compiles a Query against the specified Collection
  -    * context and returns the compiled Query.  This DOES NOT actually
  -    * run the query, merely just parses it and primes any possible
  -    * Indexers that the query might need.
  -    *
  -    * @param col The Collection context
  -    * @param style The query style (XPath, Fulltext, etc...)
  -    * @param query The Query
  -    * @param nsMap The namespace Map (if any)
  -    * @param keys The initial Key set to use (if any)
  -    * @return The compiled Query
  -    */
  -   public Query compileQuery(Collection col, String style, String query, NamespaceMap nsMap, Key[] keys) throws DBException, QueryException {
  -      QueryResolver res = getResolver(style);
  -      return res.compileQuery(col, query, nsMap, keys);
  -   }
  -   
  -
  -   // Utility methods
  -
  -   /**
  -    * getUniqueKeys takes a set of IndexMatch objects and extracts
  -    * all of its unique Keys in sorted order.
  -    *
  -    * @param matches The Match Set
  -    * @return The unique Keys in order
  -    */
  -   public static Key[] getUniqueKeys(IndexMatch[] matches) {
  -      SortedSet set = new TreeSet();
  -      for ( int i = 0; i < matches.length; i++ )
  -         set.add(matches[i].getKey());
  -      return (Key[])set.toArray(EmptyKeys);
  -   }
  -
  -   /**
  -    * andKeySets takes several sets of unique Keys and returns the
  -    * ANDed set (elements that exist in all sets).  The first dimension
  -    * of the array holds the individual sets, the second holds the
  -    * actual Keys.
  -    *
  -    * @param keySets 2-dimensional set of Keys
  -    * @return The ANDed set of Keys in order
  -    */
  -   public static Key[] andKeySets(Key[][] keySets) {
  -      int[] ptrs;
  -      
  -      if ( keySets.length == 0 )
  -         return EmptyKeys;
  -      else if ( keySets.length == 1 )
  -         return keySets[0];
  -      else {
  -         ptrs = new int[keySets.length];
  -         for ( int i = 0; i < keySets.length; i++ )
  -            if ( keySets[i].length == 0 )
  -               return EmptyKeys;
  -            else
  -               ptrs[i] = 0;
  -      }
  -
  -      SortedSet set = new TreeSet();
  -      boolean done = false;
  -      List highs = new ArrayList();
  -      Key highest = null;
  -      while ( !done ) {
  -         boolean eq = true;
  -
  -         for ( int i = 0; i < ptrs.length; i++ ) {
  -            Key comp = keySets[i][ptrs[i]];
  -            if ( highest == null ) {
  -               highest = comp;
  -               highs.add(new Integer(i));
  +    public Database getDatabase() {
  +        return db;
  +    }
  +
  +    /**
  +     * listStyles returns a list of styles supported by the
  +     * QueryEngine (ex: XPath, XUpdate)
  +     *
  +     * @return The supported styles
  +     */
  +    public String[] listStyles() {
  +        return (String[]) resolvers.keySet().toArray(EmptyStrings);
  +    }
  +
  +    private QueryResolver getResolver(String style) throws QueryException {
  +        QueryResolver res = (QueryResolver) resolvers.get(style);
  +        if (res == null)
  +            throw new StyleNotFoundException("No Resolver available for '" + style + "' queries");
  +        return res;
  +    }
  +
  +    /**
  +     * query performs the specified query and returns a NodeSet with
  +     * any possible results from that query.  The query is performed
  +     * in the context of a Collection.
  +     *
  +     * @param col The Collection context
  +     * @param style The query style (XPath, Fulltext, etc...)
  +     * @param query The Query
  +     * @param nsMap The namespace Map (if any)
  +     * @param keys The initial Key set to use (if any)
  +     * @return A NodeSet with the query results
  +     */
  +    public NodeSet query(Collection col, String style, String query, NamespaceMap nsMap, Key[] keys) throws DBException, QueryException {
  +        QueryResolver res = getResolver(style);
  +        return res.query(col, query, nsMap, keys);
  +    }
  +
  +    /**
  +     * compileQuery compiles a Query against the specified Collection
  +     * context and returns the compiled Query.  This DOES NOT actually
  +     * run the query, merely just parses it and primes any possible
  +     * Indexers that the query might need.
  +     *
  +     * @param col The Collection context
  +     * @param style The query style (XPath, Fulltext, etc...)
  +     * @param query The Query
  +     * @param nsMap The namespace Map (if any)
  +     * @param keys The initial Key set to use (if any)
  +     * @return The compiled Query
  +     */
  +    public Query compileQuery(Collection col, String style, String query, NamespaceMap nsMap, Key[] keys) throws DBException, QueryException {
  +        QueryResolver res = getResolver(style);
  +        return res.compileQuery(col, query, nsMap, keys);
  +    }
  +
  +    // Utility methods
  +
  +    /**
  +     * getUniqueKeys takes a set of IndexMatch objects and extracts
  +     * all of its unique Keys in sorted order.
  +     *
  +     * @param matches The Match Set
  +     * @return The unique Keys in order
  +     */
  +    public static Key[] getUniqueKeys(IndexMatch[] matches) {
  +        SortedSet set = new TreeSet();
  +        for (int i = 0; i < matches.length; i++)
  +            set.add(matches[i].getKey());
  +        return (Key[]) set.toArray(EmptyKeys);
  +    }
  +
  +    /**
  +     * andKeySets takes several sets of unique Keys and returns the
  +     * ANDed set (elements that exist in all sets).  The first dimension
  +     * of the array holds the individual sets, the second holds the
  +     * actual Keys.
  +     *
  +     * @param keySets 2-dimensional set of Keys
  +     * @return The ANDed set of Keys in order
  +     */
  +    public static Key[] andKeySets(Key[][] keySets) {
  +        int[] ptrs;
  +
  +        if (keySets.length == 0)
  +            return EmptyKeys;
  +        else if (keySets.length == 1)
  +            return keySets[0];
  +        else {
  +            ptrs = new int[keySets.length];
  +            for (int i = 0; i < keySets.length; i++)
  +                if (keySets[i].length == 0)
  +                    return EmptyKeys;
  +                else
  +                    ptrs[i] = 0;
  +        }
  +
  +        SortedSet set = new TreeSet();
  +        boolean done = false;
  +        List highs = new ArrayList();
  +        Key highest = null;
  +        while (!done) {
  +            boolean eq = true;
  +
  +            for (int i = 0; i < ptrs.length; i++) {
  +                Key comp = keySets[i][ptrs[i]];
  +                if (highest == null) {
  +                    highest = comp;
  +                    highs.add(new Integer(i));
  +                }
  +                else {
  +                    int c = highest.compareTo(comp);
  +                    if (c != 0)
  +                        eq = false;
  +                    if (c < 0) {
  +                        highest = comp;
  +                        highs.clear();
  +                        highs.add(new Integer(i));
  +                    }
  +                    else if (c == 0)
  +                        highs.add(new Integer(i));
  +                }
               }
  -            else {
  -               int c = highest.compareTo(comp);
  -               if ( c != 0 )
  -                  eq = false;
  -               if ( c < 0 ) {
  -                  highest = comp;
  -                  highs.clear();
  -                  highs.add(new Integer(i));
  -               }
  -               else if ( c == 0 )
  -                  highs.add(new Integer(i));
  +            if (eq) {
  +                set.add(highest);
  +                highs.clear();
  +                highest = null;
  +            }
  +            for (int i = 0; i < ptrs.length; i++) {
  +                if (!highs.contains(new Integer(i)))
  +                    ptrs[i]++;
  +                if (ptrs[i] >= keySets[i].length)
  +                    done = true;
               }
  -         }
  -         if ( eq ) {
  -            set.add(highest);
  -            highs.clear();
  -            highest = null;
  -         }
  -         for ( int i = 0; i < ptrs.length; i++ ) {
  -            if ( !highs.contains(new Integer(i)) )
  -               ptrs[i]++;
  -            if ( ptrs[i] >= keySets[i].length )
  -               done = true;
  -         }
  -         if ( !eq )
  -            highs.clear();
  -      }
  -
  -      return (Key[])set.toArray(EmptyKeys);
  -   }
  -
  -   /**
  -    * orKeySets takes several sets of unique Keys and returns the
  -    * ORed set (all unique elements).  The first dimension of the
  -    * array holds the individual sets, the second holds the actual
  -    * Keys.
  -    *
  -    * @param keySets 2-dimensional set of Keys
  -    * @return The ORed set of Keys in order
  -    */
  -   public static Key[] orKeySets(Key[][] keySets) {
  -      if ( keySets.length == 0 )
  -         return EmptyKeys;
  -      else if ( keySets.length == 1 )
  -         return keySets[0];
  -      else if ( keySets.length == 2 ) {
  -         // Optimization since most ORs will be 2 sets only
  -         if ( keySets[1].length == 0 )
  +            if (!eq)
  +                highs.clear();
  +        }
  +
  +        return (Key[]) set.toArray(EmptyKeys);
  +    }
  +
  +    /**
  +     * orKeySets takes several sets of unique Keys and returns the
  +     * ORed set (all unique elements).  The first dimension of the
  +     * array holds the individual sets, the second holds the actual
  +     * Keys.
  +     *
  +     * @param keySets 2-dimensional set of Keys
  +     * @return The ORed set of Keys in order
  +     */
  +    public static Key[] orKeySets(Key[][] keySets) {
  +        if (keySets.length == 0)
  +            return EmptyKeys;
  +        else if (keySets.length == 1)
               return keySets[0];
  -         else if ( keySets[0].length == 0 )
  -            return keySets[1];
  -      }
  -      
  -      SortedSet set = new TreeSet();
  -
  -      for ( int i = 0; i < keySets.length; i++ )
  -         for ( int j = 0; j < keySets[i].length; j++ )
  -            set.add(keySets[i][j]);
  -
  -      return (Key[])set.toArray(EmptyKeys);
  -   }
  -   
  -   /**
  -    * normalizeString normalizes the specific String by stripping
  -    * all leading, trailing, and continuous runs of white space.
  -    *
  -    * @param value The value to normalize
  -    * @return The result
  -    */
  -   public static String normalizeString(String value) {
  -      char[] c = value.toCharArray();
  -      char[] n = new char[c.length];
  -      boolean white = true;
  -      int pos = 0;
  -      for ( int i = 0; i < c.length; i++ ) {
  -         if ( " \t\n\r".indexOf(c[i]) != -1 ) {
  -            if ( !white ) {
  -               n[pos++] = ' ';
  -               white = true;
  +        else if (keySets.length == 2) {
  +            // Optimization since most ORs will be 2 sets only
  +            if (keySets[1].length == 0)
  +                return keySets[0];
  +            else if (keySets[0].length == 0)
  +                return keySets[1];
  +        }
  +
  +        SortedSet set = new TreeSet();
  +
  +        for (int i = 0; i < keySets.length; i++)
  +            for (int j = 0; j < keySets[i].length; j++)
  +                set.add(keySets[i][j]);
  +
  +        return (Key[]) set.toArray(EmptyKeys);
  +    }
  +
  +    /**
  +     * normalizeString normalizes the specific String by stripping
  +     * all leading, trailing, and continuous runs of white space.
  +     *
  +     * @param value The value to normalize
  +     * @return The result
  +     */
  +    public static String normalizeString(String value) {
  +        char[] c = value.toCharArray();
  +        char[] n = new char[c.length];
  +        boolean white = true;
  +        int pos = 0;
  +        for (int i = 0; i < c.length; i++) {
  +            if (" \t\n\r".indexOf(c[i]) != -1) {
  +                if (!white) {
  +                    n[pos++] = ' ';
  +                    white = true;
  +                }
               }
  -         }
  -         else {
  -            n[pos++] = c[i];
  -            white = false;
  -         }
  -      }
  -      if ( white && pos > 0 )
  -         pos--;
  -      return new String(n, 0, pos);
  -   }
  -
  -   /**
  -    * expandEntities expands the String's pre-defined XML entities
  -    * (&lt;, &gt;, etc...) into their actual character representations.
  -    *
  -    * @param value The value to expand entities for
  -    * @return The expanded String
  -    */
  -   public static String expandEntities(String value) {
  -      int idx = value.indexOf('&');
  -      if ( idx == -1 )
  -         return value;
  -
  -      StringBuffer sb = new StringBuffer(value.length());
  -      int pos = 0;
  -      while ( pos < value.length() ) {
  -         if ( idx != -1 ) {
  -            if ( idx > pos )
  -               sb.append(value.substring(pos, idx));
  -
  -            int end = value.indexOf(';', idx)+1;
  -            if ( end == 0 )
  -               // Some sort of error
  -               return value;
  -
  -            String token = value.substring(idx+1, end-1);
  -            if ( token.equals("apos") )
  -               sb.append("'");
  -            else if ( token.equals("quot") )
  -               sb.append("\"");
  -            else if ( token.equals("amp") )
  -               sb.append("&");
  -            else if ( token.equals("lt") )
  -               sb.append("<");
  -            else if ( token.equals("gt") )
  -               sb.append(">");
  -            else
  -               // Some sort of error
  -               return value;
  -
  -            pos = end;
  -            idx = value.indexOf('&', pos);
  -         }
  -         else {
  -            sb.append(value.substring(pos));
  -            break;
  -         }
  -      }
  -      return sb.toString();
  -   }
  +            else {
  +                n[pos++] = c[i];
  +                white = false;
  +            }
  +        }
  +        if (white && pos > 0)
  +            pos--;
  +        return new String(n, 0, pos);
  +    }
  +
  +    /**
  +     * expandEntities expands the String's pre-defined XML entities
  +     * (&lt;, &gt;, etc...) into their actual character representations.
  +     *
  +     * @param value The value to expand entities for
  +     * @return The expanded String
  +     */
  +    public static String expandEntities(String value) {
  +        int idx = value.indexOf('&');
  +        if (idx == -1)
  +            return value;
  +
  +        StringBuffer sb = new StringBuffer(value.length());
  +        int pos = 0;
  +        while (pos < value.length()) {
  +            if (idx != -1) {
  +                if (idx > pos)
  +                    sb.append(value.substring(pos, idx));
  +
  +                int end = value.indexOf(';', idx) + 1;
  +                if (end == 0)
  +                    // Some sort of error
  +                    return value;
  +
  +                String token = value.substring(idx + 1, end - 1);
  +                if (token.equals("apos"))
  +                    sb.append("'");
  +                else if (token.equals("quot"))
  +                    sb.append("\"");
  +                else if (token.equals("amp"))
  +                    sb.append("&");
  +                else if (token.equals("lt"))
  +                    sb.append("<");
  +                else if (token.equals("gt"))
  +                    sb.append(">");
  +                else
  +                    // Some sort of error
  +                    return value;
   
  -}
  +                pos = end;
  +                idx = value.indexOf('&', pos);
  +            }
  +            else {
  +                sb.append(value.substring(pos));
  +                break;
  +            }
  +        }
  +        return sb.toString();
  +    }
   
  +}
  
  
  
  1.13      +991 -989  xml-xindice/java/src/org/apache/xindice/core/query/XPathQueryResolver.java
  
  Index: XPathQueryResolver.java
  ===================================================================
  RCS file: /home/cvs/xml-xindice/java/src/org/apache/xindice/core/query/XPathQueryResolver.java,v
  retrieving revision 1.12
  retrieving revision 1.13
  diff -u -r1.12 -r1.13
  --- XPathQueryResolver.java	5 May 2003 16:18:22 -0000	1.12
  +++ XPathQueryResolver.java	15 Jul 2003 15:44:36 -0000	1.13
  @@ -117,1012 +117,1014 @@
    */
   
   public final class XPathQueryResolver extends SimpleConfigurable implements QueryResolver {
  -   private static final Key[] EmptyKeys = new Key[0];
  -   private static final Key[][] EmptyKeySet = new Key[0][0];
  -   private static final String WILDCARD = "*";
  -   // private static final String THISNODE = ".";
  -   // private static final String PARENTNODE = "..";
  -
  -   private static final String AUTOINDEX = "autoindex";
  -
  -   public static final String STYLE_XPATH = "XPath";
  -
  -   private static Log log = LogFactory.getLog("org.apache.xindice.core");
  -
  -   // Maps Xalan Comparisons To IndexQuery
  -   private static final int[] OpMap = { IndexQuery.NEQ,
  -                                        IndexQuery.EQ,
  -                                        IndexQuery.LEQ,
  -                                        IndexQuery.LT,
  -                                        IndexQuery.GEQ,
  -                                        IndexQuery.GT };
  -
  -   // Maps XPath Functions To Internal IDs (These are Xalan IDs)
  -   public static final int FUNC_NOT = 11;
  -   public static final int FUNC_TRUE = 12;
  -   public static final int FUNC_FALSE = 13;
  -   public static final int FUNC_BOOLEAN = 14;
  -   public static final int FUNC_NUMBER = 15;
  -   public static final int FUNC_FLOOR = 16;
  -   public static final int FUNC_CEILING = 17;
  -   public static final int FUNC_ROUND = 18;
  -   public static final int FUNC_STRING = 20;
  -   public static final int FUNC_STARTS_WITH = 21;
  -   public static final int FUNC_CONTAINS = 22;
  -   public static final int FUNC_SUBSTRING_BEFORE = 23;
  -   public static final int FUNC_SUBSTRING_AFTER = 24;
  -   public static final int FUNC_NORMALIZE_SPACE = 25;
  -   public static final int FUNC_TRANSLATE = 26;
  -   public static final int FUNC_CONCAT = 27;
  -   public static final int FUNC_SUBSTRING = 29;
  -   public static final int FUNC_STRING_LENGTH = 30;
  -
  -   private QueryEngine engine;
  -   private DefaultErrorHandler errorListener = new DefaultErrorHandler();
  -   private boolean autoIndex = false;
  -
  -   public void setConfig(Configuration config) throws XindiceException {
  -      super.setConfig(config);
  -      autoIndex = config.getBooleanAttribute(AUTOINDEX, autoIndex);
  -   }
  -
  -   public String getQueryStyle() {
  -      return STYLE_XPATH;
  -   }
  -
  -   public void setQueryEngine(QueryEngine engine) {
  -      this.engine = engine;
  -   }
  -
  -   public Query compileQuery(Collection context, String query, NamespaceMap nsMap, Key[] keys) throws QueryException {
  -      return new XPathQuery(context, query, nsMap, keys);
  -   }
  -
  -   public NodeSet query(Collection context, String query, NamespaceMap nsMap, Key[] keys) throws QueryException {
  -      XPathQuery xq = new XPathQuery(context, query, nsMap, keys);
  -      return xq.execute();
  -   }
  -
  -
  -   /**
  -    * XPathQuery
  -    */
  -
  -   private class XPathQuery implements Query {
  -      public Collection context;
  -      public IndexManager idxMgr;
  -      public NamespaceMap nsMap;
  -      public PrefixResolver pr;
  -      public SymbolTable symbols;
  -      public String query;
  -      public Compiler cmp;
  -      public XPath xp;
  -      public Key[] keys;
  -
  -      public XPathQuery(Collection context, String query, NamespaceMap nsMap, Key[] keys) throws QueryException {
  -         this.context = context;
  -         this.query = query;
  -         this.nsMap = nsMap;
  -         this.keys = keys;
  -
  -         Expression ex = null;
  -
  -         try {
  -            if ( nsMap != null ) {
  -               Node n = nsMap.getContextNode();
  -               pr = new PrefixResolverDefault(n);
  -            }
  -
  -            XPathParser parser = new XPathParser(errorListener, null);
  -            cmp = new Compiler(errorListener, null);
  -            parser.initXPath(cmp, query, pr);
  -            ex = cmp.compile(0);
  -
  -            symbols = context.getSymbols();
  -            idxMgr = context.getIndexManager();
  -         }
  -         catch ( Exception e ) {
  -            throw new CompilationException("Error Compiling XPath Expression", e);
  -         }
  -         if ( ex == null )
  -            throw new CompilationException("Error Compiling XPath Expression: XPath Compiler.compile returned null");
  -      }
  -
  -      public String getQueryStyle() {
  -         return STYLE_XPATH;
  -      }
  -
  -      public String getQueryString() {
  -         return query;
  -      }
  -
  -      public Collection getQueryContext() {
  -         return context;
  -      }
  -
  -      public NamespaceMap getNamespaceMap() {
  -         return nsMap;
  -      }
  -
  -      public Key[] getKeySet() {
  -         return keys;
  -      }
  -
  -      public NodeSet execute() throws QueryException {
  -         try {
  -            Key[] keySet = keys;
  -
  -            // TODO: Add logic to do an indexed check on provided
  -            //       keySets that are larger than a certain minimum
  -
  -            if ( keys == null && idxMgr != null ) {
  -               // Issue the query using Indexes
  -               try {
  -                  Object obj = evaluate(null, 0);
  -                  if ( obj instanceof NamedKeys )
  -                     keySet = ((NamedKeys)obj).keys;
  -               }
  -               catch ( Exception e ) {
  -                  if (log.isDebugEnabled()) {
  -                     log.debug("No message", e);
  -                  }
  -               }
  -            }
  -
  -            if ( keySet == null ) {
  -               // Fall back to a Collection scan
  -               SortedSet set = new TreeSet();
  -               RecordSet rs = context.getFiler().getRecordSet();
  -               while ( rs.hasMoreRecords() )
  -                  set.add(rs.getNextKey());
  -               keySet = (Key[])set.toArray(EmptyKeys);
  -            }
  -
  -            return new ResultSet(context, pr, keySet, query);
  -         }
  -         catch ( Exception e ) {
  -            if( e instanceof QueryException ) {
  -               throw (QueryException) e.fillInStackTrace();
  -            }
  -            throw new ProcessingException("Error executing XPath query");
  -         }
  -      }
  -
  -      private Key[] andKeys(List list) {
  -         if ( !list.isEmpty() ) {
  -            if ( list.size() > 1 ) {
  -               Key[][] keys = (Key[][])list.toArray(EmptyKeySet);
  -               return QueryEngine.andKeySets(keys);
  +    private static final Key[] EmptyKeys = new Key[0];
  +    private static final Key[][] EmptyKeySet = new Key[0][0];
  +    private static final String WILDCARD = "*";
  +    // private static final String THISNODE = ".";
  +    // private static final String PARENTNODE = "..";
  +
  +    private static final String AUTOINDEX = "autoindex";
  +
  +    public static final String STYLE_XPATH = "XPath";
  +
  +    private static Log log = LogFactory.getLog("org.apache.xindice.core");
  +
  +    // Maps Xalan Comparisons To IndexQuery
  +    private static final int[] OpMap = { IndexQuery.NEQ, IndexQuery.EQ, IndexQuery.LEQ, IndexQuery.LT, IndexQuery.GEQ, IndexQuery.GT };
  +
  +    // Maps XPath Functions To Internal IDs (These are Xalan IDs)
  +    public static final int FUNC_NOT = 11;
  +    public static final int FUNC_TRUE = 12;
  +    public static final int FUNC_FALSE = 13;
  +    public static final int FUNC_BOOLEAN = 14;
  +    public static final int FUNC_NUMBER = 15;
  +    public static final int FUNC_FLOOR = 16;
  +    public static final int FUNC_CEILING = 17;
  +    public static final int FUNC_ROUND = 18;
  +    public static final int FUNC_STRING = 20;
  +    public static final int FUNC_STARTS_WITH = 21;
  +    public static final int FUNC_CONTAINS = 22;
  +    public static final int FUNC_SUBSTRING_BEFORE = 23;
  +    public static final int FUNC_SUBSTRING_AFTER = 24;
  +    public static final int FUNC_NORMALIZE_SPACE = 25;
  +    public static final int FUNC_TRANSLATE = 26;
  +    public static final int FUNC_CONCAT = 27;
  +    public static final int FUNC_SUBSTRING = 29;
  +    public static final int FUNC_STRING_LENGTH = 30;
  +
  +    private QueryEngine engine;
  +    private DefaultErrorHandler errorListener = new DefaultErrorHandler();
  +    private boolean autoIndex = false;
  +
  +    public void setConfig(Configuration config) throws XindiceException {
  +        super.setConfig(config);
  +        autoIndex = config.getBooleanAttribute(AUTOINDEX, autoIndex);
  +    }
  +
  +    public String getQueryStyle() {
  +        return STYLE_XPATH;
  +    }
  +
  +    public void setQueryEngine(QueryEngine engine) {
  +        this.engine = engine;
  +    }
  +
  +    public Query compileQuery(Collection context, String query, NamespaceMap nsMap, Key[] keys) throws QueryException {
  +        return new XPathQuery(context, query, nsMap, keys);
  +    }
  +
  +    public NodeSet query(Collection context, String query, NamespaceMap nsMap, Key[] keys) throws QueryException {
  +        XPathQuery xq = new XPathQuery(context, query, nsMap, keys);
  +        return xq.execute();
  +    }
  +
  +    /**
  +     * XPathQuery
  +     */
  +
  +    private class XPathQuery implements Query {
  +        public Collection context;
  +        public IndexManager idxMgr;
  +        public NamespaceMap nsMap;
  +        public PrefixResolver pr;
  +        public SymbolTable symbols;
  +        public String query;
  +        public Compiler cmp;
  +        public XPath xp;
  +        public Key[] keys;
  +
  +        public XPathQuery(Collection context, String query, NamespaceMap nsMap, Key[] keys) throws QueryException {
  +            this.context = context;
  +            this.query = query;
  +            this.nsMap = nsMap;
  +            this.keys = keys;
  +
  +            Expression ex = null;
  +
  +            try {
  +                if (nsMap != null) {
  +                    Node n = nsMap.getContextNode();
  +                    pr = new PrefixResolverDefault(n);
  +                }
  +
  +                XPathParser parser = new XPathParser(errorListener, null);
  +                cmp = new Compiler(errorListener, null);
  +                parser.initXPath(cmp, query, pr);
  +                ex = cmp.compile(0);
  +
  +                symbols = context.getSymbols();
  +                idxMgr = context.getIndexManager();
  +            }
  +            catch (Exception e) {
  +                throw new CompilationException("Error Compiling XPath Expression", e);
  +            }
  +            if (ex == null)
  +                throw new CompilationException("Error Compiling XPath Expression: XPath Compiler.compile returned null");
  +        }
  +
  +        public String getQueryStyle() {
  +            return STYLE_XPATH;
  +        }
  +
  +        public String getQueryString() {
  +            return query;
  +        }
  +
  +        public Collection getQueryContext() {
  +            return context;
  +        }
  +
  +        public NamespaceMap getNamespaceMap() {
  +            return nsMap;
  +        }
  +
  +        public Key[] getKeySet() {
  +            return keys;
  +        }
  +
  +        public NodeSet execute() throws QueryException {
  +            try {
  +                Key[] keySet = keys;
  +
  +                // TODO: Add logic to do an indexed check on provided
  +                //       keySets that are larger than a certain minimum
  +
  +                if (keys == null && idxMgr != null) {
  +                    // Issue the query using Indexes
  +                    try {
  +                        Object obj = evaluate(null, 0);
  +                        if (obj instanceof NamedKeys)
  +                            keySet = ((NamedKeys) obj).keys;
  +                    }
  +                    catch (Exception e) {
  +                        log.warn(e);
  +                    }
  +                }
  +
  +                if (keySet == null) {
  +                    // Fall back to a Collection scan
  +                    SortedSet set = new TreeSet();
  +                    RecordSet rs = context.getFiler().getRecordSet();
  +                    while (rs.hasMoreRecords())
  +                        set.add(rs.getNextKey());
  +                    keySet = (Key[]) set.toArray(EmptyKeys);
  +                }
  +
  +                return new ResultSet(context, pr, keySet, query);
  +            }
  +            catch (Exception e) {
  +                if (e instanceof QueryException) {
  +                    throw (QueryException) e.fillInStackTrace();
  +                }
  +                throw new ProcessingException("Error executing XPath query");
  +            }
  +        }
  +
  +        private Key[] andKeys(List list) {
  +            if (!list.isEmpty()) {
  +                if (list.size() > 1) {
  +                    Key[][] keys = (Key[][]) list.toArray(EmptyKeySet);
  +                    return QueryEngine.andKeySets(keys);
  +                }
  +                else
  +                    return (Key[]) list.get(0);
               }
               else
  -               return (Key[])list.get(0);
  -         }
  -         else
  -            return null;
  -      }
  -
  -
  -      // Evaluation Methods
  -
  -      /**
  -       * evaluate does a partial evaluation of the XPath in
  -       * order to determine the optimal indexes to prepare for
  -       * the query and retrieve the Document subset that will be
  -       * used for the actual XPath query.
  -       * <br><br>
  -       * This will return an instance of one of the following classes:
  -       * <pre>
  -       *    String    If the sub-expression resolves to a Node Name
  -       *    XNumber   If the sub-expression resolves to a Number
  -       *    XString   If the sub-expression resolves to a String
  -       *    XBoolean  If the sub-expression resolves to a Boolean
  -       *    NamedKeys If the sub-expression resolves to a Key set
  -       * </pre>
  -       *
  -       * @param owner The parent node name for this context
  -       * @param pos The position to start at (recursively called)
  -       * @return Some Object result
  -       */
  -      private Object evaluate(String owner, int pos) throws Exception {
  -         int op = cmp.getOp(pos);
  -         if ( op == -1 )
  -            return null;
  -
  -         switch ( op ) {
  -
  -            case OpCodes.OP_LOCATIONPATH:
  -               return evalLocationPath(owner, pos);
  -
  -            case OpCodes.OP_ARGUMENT:
  -            case OpCodes.OP_XPATH:
  -            case OpCodes.OP_PREDICATE:
  -               return evaluate(owner, Compiler.getFirstChildPos(pos));
  -
  -            case OpCodes.OP_OR:
  -            case OpCodes.OP_AND:
  -               return evalSetComparison(op, owner, pos);
  -
  -            case OpCodes.OP_NOTEQUALS:
  -            case OpCodes.OP_EQUALS:
  -            case OpCodes.OP_LTE:
  -            case OpCodes.OP_LT:
  -            case OpCodes.OP_GTE:
  -            case OpCodes.OP_GT:
  -               return evalValComparison(op, owner, pos);
  -
  -            case OpCodes.OP_PLUS:
  -            case OpCodes.OP_MINUS:
  -            case OpCodes.OP_MULT:
  -            case OpCodes.OP_DIV:
  -            case OpCodes.OP_MOD:
  -            case OpCodes.OP_QUO:
  -               return evalMathOperation(op, owner, pos);
  -
  -            case OpCodes.OP_NEG:
  -            case OpCodes.OP_STRING:
  -            case OpCodes.OP_BOOL:
  -            case OpCodes.OP_NUMBER:
  -               return evalUnaryOperation(op, owner, pos);
  -
  -            case OpCodes.OP_UNION:
  -                return evalUnion(owner, pos);
  -
  -            case OpCodes.OP_VARIABLE:
  -               break;
  -
  -            case OpCodes.OP_GROUP:
  -               return evaluate(owner, Compiler.getFirstChildPos(pos));
  -
  -            case OpCodes.OP_EXTFUNCTION:
  -               break;
  -
  -            case OpCodes.OP_FUNCTION:
  -               return evalFunction(owner, pos);
  -
  -            case OpCodes.FROM_ANCESTORS:
  -            case OpCodes.FROM_ANCESTORS_OR_SELF:
  -            case OpCodes.FROM_ATTRIBUTES:
  -            case OpCodes.FROM_CHILDREN:
  -            case OpCodes.FROM_DESCENDANTS:
  -            case OpCodes.FROM_DESCENDANTS_OR_SELF:
  -            case OpCodes.FROM_FOLLOWING:
  -            case OpCodes.FROM_FOLLOWING_SIBLINGS:
  -            case OpCodes.FROM_PARENT:
  -            case OpCodes.FROM_PRECEDING:
  -            case OpCodes.FROM_PRECEDING_SIBLINGS:
  -            case OpCodes.FROM_NAMESPACE:
  -            case OpCodes.FROM_SELF:
  -            case OpCodes.FROM_ROOT:
  -               return evalAxis(op, owner, pos);
  -
  -            case OpCodes.NODENAME:
  -            case OpCodes.OP_LITERAL:
  -            case OpCodes.OP_NUMBERLIT:
  -               return evalLiteral(owner, pos);
  -
  -            case OpCodes.NODETYPE_TEXT:
  -            case OpCodes.NODETYPE_NODE:
  -               return owner;
  -
  -            case OpCodes.NODETYPE_ANYELEMENT:
  -            case OpCodes.ELEMWILDCARD:
  -               return WILDCARD;
  -
  -            case OpCodes.NODETYPE_ROOT:
  -            case OpCodes.NODETYPE_COMMENT:
  -            case OpCodes.NODETYPE_PI:
  -            case OpCodes.NODETYPE_FUNCTEST:
  -               break;
  -
  -            default:
  -               if (log.isWarnEnabled()) {
  -                  log.warn("Unknown: "+op);
  -               }
  -
  -         }
  -         return null;
  -      }
  -
  -      private Object evalLocationPath(String owner, int pos) throws Exception {
  -         int lp = Compiler.getFirstChildPos(pos);
  -         List ks = new ArrayList();
  -         String name = null;
  -         boolean attr = false;
  -         while ( cmp.getOp(lp) != -1 ) {
  -            Object obj = evaluate(owner, lp);
  -            if ( obj instanceof NamedKeys ) {
  -               NamedKeys nk = (NamedKeys)obj;
  -               if ( nk.name != null ) {
  -                  attr = nk.attribute;
  -                  if ( attr && name != null ) {
  -                     StringBuffer sb = new StringBuffer(32);
  -                     sb.append(name);
  -                     sb.append('@');
  -                     sb.append(nk.name);
  -                     name = sb.toString();
  -                  }
  -                  else
  -                     name = nk.name;
  -               }
  -               if ( nk.keys != null )
  -                  ks.add(nk.keys);
  -               else if ( name != null ) {
  -                  // Try to use a NameIndex to resolve the path component
  -                  IndexPattern pattern = new IndexPattern(symbols, name, nsMap);
  -                  Indexer idx = context.getIndexManager().getBestIndexer(Indexer.STYLE_NODENAME, pattern);
  -                  if ( idx != null ) {
  -                     IndexMatch[] matches = idx.queryMatches(new IndexQueryANY(pattern));
  -                     Key[] keys = QueryEngine.getUniqueKeys(matches);
  -                     ks.add(keys);
  -                  }
  -               }
  -            }
  -            lp = cmp.getNextOpPos(lp);
  -         }
  -         return new NamedKeys(name, attr, andKeys(ks));
  -      }
  -
  -      private Object evalUnion(String owner, int pos) throws Exception {
  -         int l = Compiler.getFirstChildPos(pos);
  -         int r = cmp.getNextOpPos(l);
  -         Object left = evaluate(owner, l);
  -         
  -         if ( left instanceof NamedKeys &&
  -            ((NamedKeys)left).keys != null)
  -         {
  -             Object right = evaluate(owner, r);
  -
  -
  -             
  -             if ( right instanceof NamedKeys &&
  -                ((NamedKeys)right).keys != null)
  -             {
  -                Key[][] keys = new Key[][] { ((NamedKeys)left).keys, ((NamedKeys)right).keys };
  -                return new NamedKeys(null, false, QueryEngine.orKeySets(keys));
  -             }
  -         }
  -         // no index query of left part of union
  -         // or no index query of right part of union => must do
  -         /// collection scan
  -         return null;
  -      }
  -
  -      private Object evalSetComparison(int op, String owner, int pos) throws Exception {
  -         int l = Compiler.getFirstChildPos(pos);
  -         int r = cmp.getNextOpPos(l);
  -         Object left = evaluate(owner, l);
  -         Object right = evaluate(owner, r);
  -
  -         NamedKeys nkl = left instanceof NamedKeys ? (NamedKeys)left : null;
  -         NamedKeys nkr = right instanceof NamedKeys ? (NamedKeys)right : null;
  -         if ( nkl != null && nkr != null && nkl.keys != null && nkr.keys != null ) {
  -            Key[][] keys = new Key[][] { nkl.keys, nkr.keys };
  -            if ( op == OpCodes.OP_OR )
  -               return new NamedKeys(null, false, QueryEngine.orKeySets(keys));
  -            else
  -               return new NamedKeys(null, false, QueryEngine.andKeySets(keys));
  -         }
  -         else if ( op == OpCodes.OP_AND ) {
  -            if ( nkl != null && nkl.keys != null )
  -               return new NamedKeys(null, false, nkl.keys);
  -            else if ( nkr != null && nkr.keys != null )
  -               return new NamedKeys(null, false, nkr.keys);
  -         }
  -         return null;
  -      }
  -
  -      private Object evalValComparison(int op, String owner, int pos) throws Exception {
  -         int l = Compiler.getFirstChildPos(pos);
  -         int r = cmp.getNextOpPos(l);
  -         Object left = evaluate(owner, l);
  -         Object right = evaluate(owner, r);
  -
  -         if ( ( left instanceof XObject ) && ( right instanceof XObject ) ) {
  -            switch ( op ) {
  -               case OpCodes.OP_NOTEQUALS: return new XBoolean(((XObject)left).notEquals((XObject)right));
  -               case OpCodes.OP_EQUALS:    return new XBoolean(((XObject)left).equals((XObject)right));
  -               case OpCodes.OP_LTE:       return new XBoolean(((XObject)left).lessThanOrEqual((XObject)right));
  -               case OpCodes.OP_LT:        return new XBoolean(((XObject)left).lessThan((XObject)right));
  -               case OpCodes.OP_GTE:       return new XBoolean(((XObject)left).greaterThanOrEqual((XObject)right));
  -               case OpCodes.OP_GT:        return new XBoolean(((XObject)left).greaterThan((XObject)right));
  -               default:                   return null; // Won't happen
  -            }
  -         }
  -         else
  -            return queryComparison(op, owner, left, right);
  -      }
  -
  -      private strictfp Object evalMathOperation(int op, String owner, int pos) throws Exception {
  -         int lc = Compiler.getFirstChildPos(pos);
  -         int rc = cmp.getNextOpPos(lc);
  -         XObject left = (XObject)evaluate(owner, lc);
  -         XObject right = (XObject)evaluate(owner, rc);
  -
  -         switch ( op ) {
  -            case OpCodes.OP_PLUS:  return new XNumber(left.num() + right.num());
  -            case OpCodes.OP_MINUS: return new XNumber(left.num() - right.num());
  -            case OpCodes.OP_MULT:  return new XNumber(left.num() * right.num());
  -            case OpCodes.OP_DIV:   return new XNumber(left.num() / right.num());
  -            case OpCodes.OP_MOD:   return new XNumber(left.num() % right.num());
  -            case OpCodes.OP_QUO:   return new XNumber(left.num() / right.num());
  -            default:               return null; // Won't happen
  -         }
  -      }
  -
  -      private Object evalUnaryOperation(int op, String owner, int pos) throws Exception {
  -         XObject val = (XObject)evaluate(owner, Compiler.getFirstChildPos(pos));
  -         switch ( op ) {
  -            case OpCodes.OP_NEG:    return new XNumber(-val.num());
  -            case OpCodes.OP_STRING: return new XString(val.str());
  -            case OpCodes.OP_BOOL:   return new XBoolean(val.bool());
  -            case OpCodes.OP_NUMBER: return new XNumber(val.num());
  -            default:                return null; // Won't happen
  -         }
  -      }
  -
  -      private Object evalFunction(String owner, int pos) throws Exception {
  -         int idx = Compiler.getFirstChildPos(pos);
  -         int id = cmp.getOp(idx);
  -         int endFunc = cmp.getOp(pos +1) - 1;
  -
  -         List args = new ArrayList();
  -         int lp = idx+1;
  -         while ( lp < endFunc ) {
  -            args.add(evaluate(owner, lp));
  -            lp = cmp.getNextOpPos(lp);
  -         }
  -
  -         switch ( id ) {
  -            case FUNC_BOOLEAN:
  -               return funcBoolean(args);
  -            case FUNC_CEILING:
  -               return funcCeiling(args);
  -            case FUNC_CONCAT:
  -               return funcConcat(args);
  -            case FUNC_CONTAINS:
  -               return funcContains(args);
  -            case FUNC_FALSE:
  -               return XBoolean.S_FALSE;
  -            case FUNC_FLOOR:
  -               return funcFloor(args);
  -            case FUNC_NORMALIZE_SPACE:
  -               return funcNormalizeSpace(args);
  -            case FUNC_NOT:
  -               return funcNot(args);
  -            case FUNC_NUMBER:
  -               return funcNumber(args);
  -            case FUNC_ROUND:
  -               return funcRound(args);
  -            case FUNC_STARTS_WITH:
  -               return funcStartsWith(owner, args);
  -            case FUNC_STRING:
  -               return funcString(args);
  -            case FUNC_STRING_LENGTH:
  -               return funcStringLength(args);
  -            case FUNC_SUBSTRING:
  -               return funcSubstring(args);
  -            case FUNC_SUBSTRING_AFTER:
  -               return funcSubstringAfter(args);
  -            case FUNC_SUBSTRING_BEFORE:
  -               return funcSubstringBefore(args);
  -            case FUNC_TRANSLATE:
  -               return funcTranslate(args);
  -            case FUNC_TRUE:
  -               return XBoolean.S_TRUE;
  -            default:
  -               return null;
  -         }
  -      }
  -
  -      private Object evalAxis(int op, String owner, int pos) throws Exception {
  -         String nsURI = cmp.getStepNS(pos);
  -         owner = (String)evaluate(owner, Compiler.getFirstChildPosOfStep(pos));
  -         //owner = cmp.getStepLocalName(pos);
  -
  -         if ( nsURI != null && nsMap != null ) {
  -            // We have to determine the prefix that was used
  -            // There has to be an easier way to do this with Xalan
  -            String pfx = null;
  -            Iterator i = nsMap.keySet().iterator();
  -            while ( i.hasNext() ) {
  -               String p = (String)i.next();
  -               if ( nsMap.getNamespaceURI(p).equals(nsURI) ) {
  -                  pfx = p;
  -                  break;
  -               }
  -            }
  -            if ( pfx != null ) {
  -               StringBuffer sb = new StringBuffer(32);
  -               sb.append(pfx);
  -               sb.append(':');
  -               sb.append(owner);
  -               owner = sb.toString();
  -            }
  -         }
  -
  -         int rp = cmp.getFirstPredicateOpPos(pos);
  -
  -         List ks = new ArrayList();
  -         while ( rp < pos+cmp.getOp(pos+1) ) {
  -            Object obj = evaluate(owner, rp);
  -            if ( obj instanceof NamedKeys ) {
  -               NamedKeys nk = (NamedKeys)obj;
  -               if ( nk.keys != null )
  -                  ks.add(nk.keys);
  -            }
  -            rp = cmp.getNextOpPos(rp);
  -         }
  -         return new NamedKeys(owner, (op == OpCodes.FROM_ATTRIBUTES), andKeys(ks));
  -      }
  -
  -      private Object evalLiteral(String owner, int pos) throws Exception {
  -         int idx = cmp.getOp(Compiler.getFirstChildPos(pos));
  -         switch ( idx ) {
  -            case OpCodes.EMPTY:
  -               return owner;
  -            case OpCodes.ELEMWILDCARD:
  -               return WILDCARD;
  -            default:
  -               return cmp.getToken(idx);
  -         }
  -      }
  -
  -
  -      // XPath Functions
  -
  -      private Object funcBoolean(List args) throws Exception {
  -         if ( args.size() == 1 ) {
  -            Object o = args.get(0);
  -            if ( o instanceof XObject ) {
  -               if ( ((XObject)o).bool() )
  -                  return XBoolean.S_TRUE;
  -               else
  -                  return XBoolean.S_FALSE;
  +                return null;
  +        }
  +
  +        // Evaluation Methods
  +
  +        /**
  +         * evaluate does a partial evaluation of the XPath in
  +         * order to determine the optimal indexes to prepare for
  +         * the query and retrieve the Document subset that will be
  +         * used for the actual XPath query.
  +         * <br><br>
  +         * This will return an instance of one of the following classes:
  +         * <pre>
  +         *    String    If the sub-expression resolves to a Node Name
  +         *    XNumber   If the sub-expression resolves to a Number
  +         *    XString   If the sub-expression resolves to a String
  +         *    XBoolean  If the sub-expression resolves to a Boolean
  +         *    NamedKeys If the sub-expression resolves to a Key set
  +         * </pre>
  +         *
  +         * @param owner The parent node name for this context
  +         * @param pos The position to start at (recursively called)
  +         * @return Some Object result
  +         */
  +        private Object evaluate(String owner, int pos) throws Exception {
  +            int op = cmp.getOp(pos);
  +            if (op == -1)
  +                return null;
  +
  +            switch (op) {
  +
  +                case OpCodes.OP_LOCATIONPATH :
  +                    return evalLocationPath(owner, pos);
  +
  +                case OpCodes.OP_ARGUMENT :
  +                case OpCodes.OP_XPATH :
  +                case OpCodes.OP_PREDICATE :
  +                    return evaluate(owner, Compiler.getFirstChildPos(pos));
  +
  +                case OpCodes.OP_OR :
  +                case OpCodes.OP_AND :
  +                    return evalSetComparison(op, owner, pos);
  +
  +                case OpCodes.OP_NOTEQUALS :
  +                case OpCodes.OP_EQUALS :
  +                case OpCodes.OP_LTE :
  +                case OpCodes.OP_LT :
  +                case OpCodes.OP_GTE :
  +                case OpCodes.OP_GT :
  +                    return evalValComparison(op, owner, pos);
  +
  +                case OpCodes.OP_PLUS :
  +                case OpCodes.OP_MINUS :
  +                case OpCodes.OP_MULT :
  +                case OpCodes.OP_DIV :
  +                case OpCodes.OP_MOD :
  +                case OpCodes.OP_QUO :
  +                    return evalMathOperation(op, owner, pos);
  +
  +                case OpCodes.OP_NEG :
  +                case OpCodes.OP_STRING :
  +                case OpCodes.OP_BOOL :
  +                case OpCodes.OP_NUMBER :
  +                    return evalUnaryOperation(op, owner, pos);
  +
  +                case OpCodes.OP_UNION :
  +                    return evalUnion(owner, pos);
  +
  +                case OpCodes.OP_VARIABLE :
  +                    break;
  +
  +                case OpCodes.OP_GROUP :
  +                    return evaluate(owner, Compiler.getFirstChildPos(pos));
  +
  +                case OpCodes.OP_EXTFUNCTION :
  +                    break;
  +
  +                case OpCodes.OP_FUNCTION :
  +                    return evalFunction(owner, pos);
  +
  +                case OpCodes.FROM_ANCESTORS :
  +                case OpCodes.FROM_ANCESTORS_OR_SELF :
  +                case OpCodes.FROM_ATTRIBUTES :
  +                case OpCodes.FROM_CHILDREN :
  +                case OpCodes.FROM_DESCENDANTS :
  +                case OpCodes.FROM_DESCENDANTS_OR_SELF :
  +                case OpCodes.FROM_FOLLOWING :
  +                case OpCodes.FROM_FOLLOWING_SIBLINGS :
  +                case OpCodes.FROM_PARENT :
  +                case OpCodes.FROM_PRECEDING :
  +                case OpCodes.FROM_PRECEDING_SIBLINGS :
  +                case OpCodes.FROM_NAMESPACE :
  +                case OpCodes.FROM_SELF :
  +                case OpCodes.FROM_ROOT :
  +                    return evalAxis(op, owner, pos);
  +
  +                case OpCodes.NODENAME :
  +                case OpCodes.OP_LITERAL :
  +                case OpCodes.OP_NUMBERLIT :
  +                    return evalLiteral(owner, pos);
  +
  +                case OpCodes.NODETYPE_TEXT :
  +                case OpCodes.NODETYPE_NODE :
  +                    return owner;
  +
  +                case OpCodes.NODETYPE_ANYELEMENT :
  +                case OpCodes.ELEMWILDCARD :
  +                    return WILDCARD;
  +
  +                case OpCodes.NODETYPE_ROOT :
  +                case OpCodes.NODETYPE_COMMENT :
  +                case OpCodes.NODETYPE_PI :
  +                case OpCodes.NODETYPE_FUNCTEST :
  +                    break;
  +
  +                default :
  +                    if (log.isWarnEnabled()) {
  +                        log.warn("Unknown: " + op);
  +                    }
  +
  +            }
  +            return null;
  +        }
  +
  +        private Object evalLocationPath(String owner, int pos) throws Exception {
  +            int lp = Compiler.getFirstChildPos(pos);
  +            List ks = new ArrayList();
  +            String name = null;
  +            boolean attr = false;
  +            while (cmp.getOp(lp) != -1) {
  +                Object obj = evaluate(owner, lp);
  +                if (obj instanceof NamedKeys) {
  +                    NamedKeys nk = (NamedKeys) obj;
  +                    if (nk.name != null) {
  +                        attr = nk.attribute;
  +                        if (attr && name != null) {
  +                            StringBuffer sb = new StringBuffer(32);
  +                            sb.append(name);
  +                            sb.append('@');
  +                            sb.append(nk.name);
  +                            name = sb.toString();
  +                        }
  +                        else
  +                            name = nk.name;
  +                    }
  +                    if (nk.keys != null)
  +                        ks.add(nk.keys);
  +                    else if (name != null) {
  +                        // Try to use a NameIndex to resolve the path component
  +                        IndexPattern pattern = new IndexPattern(symbols, name, nsMap);
  +                        Indexer idx = context.getIndexManager().getBestIndexer(Indexer.STYLE_NODENAME, pattern);
  +                        if (idx != null) {
  +                            IndexMatch[] matches = idx.queryMatches(new IndexQueryANY(pattern));
  +                            Key[] keys = QueryEngine.getUniqueKeys(matches);
  +                            ks.add(keys);
  +                        }
  +                    }
  +                }
  +                lp = cmp.getNextOpPos(lp);
  +            }
  +            return new NamedKeys(name, attr, andKeys(ks));
  +        }
  +
  +        private Object evalUnion(String owner, int pos) throws Exception {
  +            int l = Compiler.getFirstChildPos(pos);
  +            int r = cmp.getNextOpPos(l);
  +            Object left = evaluate(owner, l);
  +
  +            if (left instanceof NamedKeys && ((NamedKeys) left).keys != null) {
  +                Object right = evaluate(owner, r);
  +
  +                if (right instanceof NamedKeys && ((NamedKeys) right).keys != null) {
  +                    Key[][] keys = new Key[][] {((NamedKeys) left).keys, ((NamedKeys) right).keys };
  +                    return new NamedKeys(null, false, QueryEngine.orKeySets(keys));
  +                }
  +            }
  +            // no index query of left part of union
  +            // or no index query of right part of union => must do
  +            /// collection scan
  +            return null;
  +        }
  +
  +        private Object evalSetComparison(int op, String owner, int pos) throws Exception {
  +            int l = Compiler.getFirstChildPos(pos);
  +            int r = cmp.getNextOpPos(l);
  +            Object left = evaluate(owner, l);
  +            Object right = evaluate(owner, r);
  +
  +            NamedKeys nkl = left instanceof NamedKeys ? (NamedKeys) left : null;
  +            NamedKeys nkr = right instanceof NamedKeys ? (NamedKeys) right : null;
  +            if (nkl != null && nkr != null && nkl.keys != null && nkr.keys != null) {
  +                Key[][] keys = new Key[][] { nkl.keys, nkr.keys };
  +                if (op == OpCodes.OP_OR)
  +                    return new NamedKeys(null, false, QueryEngine.orKeySets(keys));
  +                else
  +                    return new NamedKeys(null, false, QueryEngine.andKeySets(keys));
  +            }
  +            else if (op == OpCodes.OP_AND) {
  +                if (nkl != null && nkl.keys != null)
  +                    return new NamedKeys(null, false, nkl.keys);
  +                else if (nkr != null && nkr.keys != null)
  +                    return new NamedKeys(null, false, nkr.keys);
  +            }
  +            return null;
  +        }
  +
  +        private Object evalValComparison(int op, String owner, int pos) throws Exception {
  +            int l = Compiler.getFirstChildPos(pos);
  +            int r = cmp.getNextOpPos(l);
  +            Object left = evaluate(owner, l);
  +            Object right = evaluate(owner, r);
  +
  +            if ((left instanceof XObject) && (right instanceof XObject)) {
  +                switch (op) {
  +                    case OpCodes.OP_NOTEQUALS :
  +                        return new XBoolean(((XObject) left).notEquals((XObject) right));
  +                    case OpCodes.OP_EQUALS :
  +                        return new XBoolean(((XObject) left).equals((XObject) right));
  +                    case OpCodes.OP_LTE :
  +                        return new XBoolean(((XObject) left).lessThanOrEqual((XObject) right));
  +                    case OpCodes.OP_LT :
  +                        return new XBoolean(((XObject) left).lessThan((XObject) right));
  +                    case OpCodes.OP_GTE :
  +                        return new XBoolean(((XObject) left).greaterThanOrEqual((XObject) right));
  +                    case OpCodes.OP_GT :
  +                        return new XBoolean(((XObject) left).greaterThan((XObject) right));
  +                    default :
  +                        return null; // Won't happen
  +                }
               }
               else
  -               return o;
  -         }
  -         return null;
  -      }
  -
  -      private Object funcCeiling(List args) throws Exception {
  -         if ( args.size() == 1 ) {
  -            Object o = args.get(0);
  -            if ( o instanceof XObject )
  -               return new XNumber(Math.ceil(((XObject)o).num()));
  -         }
  -         return null;
  -      }
  -
  -      private Object funcConcat(List args) {
  -         StringBuffer sb = new StringBuffer();
  -         for ( int i = 0; i < args.size(); i++ ) {
  -            Object o = args.get(i);
  -            if ( o instanceof XObject )
  -               sb.append(((XObject)o).str());
  -         }
  -         return new XString(sb.toString());
  -      }
  -
  -      private Object funcContains(List args) {
  -         if ( args.size() == 2 ) {
  -            Object o = args.get(0);
  -            Object s = args.get(1);
  -            if ( o instanceof XObject && s instanceof XObject ) {
  -               if ( ((XObject)o).str().indexOf(((XObject)s).str()) != -1 )
  -                  return XBoolean.S_TRUE;
  -               else
  -                  return XBoolean.S_FALSE;
  -            }
  -         }
  -         return null;
  -      }
  -
  -      private Object funcFloor(List args) throws Exception {
  -         if ( args.size() == 1 ) {
  -            Object o = args.get(0);
  -            if ( o instanceof XObject )
  -               return new XNumber(Math.floor(((XObject)o).num()));
  -         }
  -         return null;
  -      }
  -
  -      private Object funcNormalizeSpace(List args) {
  -         if ( args.size() == 1 ) {
  -            Object o = args.get(0);
  -            if ( o instanceof XObject )
  -               return new XString(QueryEngine.normalizeString(((XObject)o).str()));
  -            else
  -               return o;
  -         }
  -         return null;
  -      }
  -
  -      private Object funcNot(List args) throws Exception {
  -         if ( args.size() == 1 ) {
  -            Object o = args.get(0);
  -            if ( o instanceof XObject ) {
  -               if ( ((XObject)o).bool() )
  -                  return XBoolean.S_FALSE;
  -               else
  -                  return XBoolean.S_TRUE;
  -            }
  -         }
  -         return null;
  -      }
  -
  -      private Object funcNumber(List args) throws Exception {
  -         if ( args.size() == 1 ) {
  -            Object o = args.get(0);
  -            if ( o instanceof XObject )
  -               return new XNumber(((XObject)o).num());
  -            else
  -               return o;
  -         }
  -         return null;
  -      }
  -
  -      private Object funcRound(List args) throws Exception {
  -         if ( args.size() == 1 ) {
  -            Object o = args.get(0);
  -            if ( o instanceof XObject )
  -               return new XNumber(Math.round(((XObject)o).num()));
  -         }
  -         return null;
  -      }
  -
  -      private Object funcStartsWith(String owner, List args) {
  -         if ( args.size() == 2 ) {
  -            Object o = args.get(0);
  -            Object s = args.get(1);
  -
  -            if ( o instanceof XObject && s instanceof XObject ) {
  -               if ( ((XObject)o).str().startsWith(((XObject)s).str()) )
  -                  return XBoolean.S_TRUE;
  -               else
  -                  return XBoolean.S_FALSE;
  -            }
  -            else if ( o instanceof NamedKeys && s instanceof XObject ) {
  -               NamedKeys nk = (NamedKeys)o;
  -               String ps;
  -               if ( nk.attribute && nk.name.indexOf('@') == -1 )
  -                  ps = owner+"@"+nk.name;
  -               else
  -                  ps = nk.name;
  -
  -               IndexPattern pattern = new IndexPattern(symbols, ps, nsMap);
  -
  -               XObject obj = (XObject)s;
  -               Value val1 = new Value(obj.str());
  -
  -               IndexQuery iq = new IndexQuerySW(pattern, val1);
  -               return queryIndexes(nk, iq, ps, obj.getType());
  -            }
  -         }
  -         return null;
  -      }
  -
  -      private Object funcString(List args) {
  -         if ( args.size() == 1 ) {
  -            Object o = args.get(0);
  -            if ( o instanceof XObject )
  -               return new XString(((XObject)o).str());
  -            else
  -               return o;
  -         }
  -         return null;
  -      }
  -
  -      private Object funcStringLength(List args) {
  -         if ( args.size() == 1 ) {
  -            Object o = args.get(0);
  -            if ( o instanceof XObject )
  -               return new XNumber(((XObject)o).str().length());
  -         }
  -         return null;
  -      }
  -
  -      private Object funcSubstring(List args) throws Exception {
  -         if ( args.size() == 2 || args.size() == 3 ) {
  -            Object o = args.get(0);
  -            Object pos = args.get(1);
  -            Object len = args.get(2);
  -            if ( o instanceof XObject && pos instanceof XObject && (len == null || len instanceof XObject ) ) {
  -               int ipos = (int)((XObject)pos).num()-1;
  -               if ( len != null ) {
  -                  int ilen = (int)((XObject)len).num();
  -                  return new XString(((XObject)o).str().substring(ipos, ipos+ilen));
  -               }
  -               else
  -                  return new XString(((XObject)o).str().substring(ipos));
  -            }
  -         }
  -         return null;
  -      }
  -
  -      private Object funcSubstringAfter(List args) {
  -         if ( args.size() == 2 ) {
  -            Object o = args.get(0);
  -            Object s = args.get(1);
  -            if ( o instanceof XObject && s instanceof XObject ) {
  -               String val = ((XObject)o).str();
  -               String sub = ((XObject)s).str();
  -               int i = val.indexOf(sub);
  -               if ( i == -1 )
  -                  return new XString("");
  -               else
  -                  return new XString(val.substring(i+sub.length()));
  -            }
  -         }
  -         return null;
  -      }
  -
  -      private Object funcSubstringBefore(List args) {
  -         if ( args.size() == 2 ) {
  -            Object o = args.get(0);
  -            Object s = args.get(1);
  -            if ( o instanceof XObject && s instanceof XObject ) {
  -               String val = ((XObject)o).str();
  -               String sub = ((XObject)s).str();
  -               int i = val.indexOf(sub);
  -               if ( i == -1 )
  -                  return new XString("");
  -               else
  -                  return new XString(val.substring(0, i));
  -            }
  -         }
  -         return null;
  -      }
  -
  -      private Object funcTranslate(List args) {
  -         if ( args.size() == 3 ) {
  -            Object o = args.get(0);
  -            Object c1 = args.get(1);
  -            Object c2 = args.get(2);
  -            if ( o instanceof XObject && c1 instanceof XObject && c2 instanceof XObject) {
  -               char ch1 = ((XObject)c1).str().charAt(0);
  -               char ch2 = ((XObject)c2).str().charAt(0);
  -               return new XString(((XObject)o).str().replace(ch1, ch2));
  -            }
  -         }
  -         return null;
  -      }
  -
  -
  -      // The Actual Querying Methods
  -
  -      /**
  -       * queryIndexes actually performs index-based querying on behalf of
  -       * the evaluation methods.
  -       *
  -       * @param nk The NamedKeys instance to use for matches
  -       * @param iq The actual IndexQuery to use for resolution
  -       * @param ps The pattern String to possibly use for index gen
  -       * @param objType The object type to possibly use for index gen
  -       * @return The resulting Keys (if any)
  -       */
  -      private Object queryIndexes(NamedKeys nk, IndexQuery iq, String ps, int objType) {
  -         try {
  -            // TODO: Add logic to use an EmptyKeySet if a name doesn't already
  -            //       exist in the SymbolTable.  This will eliminate the need
  -            //       to do a collection scan in those cases where somebody
  -            //       typed an element or attribute name incorrectly.
  -
  -            IndexPattern pattern = iq.getPattern();
  -
  -            Indexer idx = context.getIndexManager().getBestIndexer(Indexer.STYLE_NODEVALUE, pattern);
  -            if ( idx != null )
  -               return new NamedKeys(nk.name, nk.attribute, QueryEngine.getUniqueKeys(idx.queryMatches(iq)));
  -            else if ( autoIndex ) {
  -               // TODO: This has to *not* be hardcoded
  -               Element e = new DocumentImpl().createElement("index");
  -               e.setAttribute("class", "org.apache.xindice.core.indexer.ValueIndexer");
  -               e.setAttribute("name", "xp_"+ps);
  -               e.setAttribute("pattern", ps);
  -
  -               // Set the type for the index
  -               String type = null;
  -               switch ( objType ) {
  -                  case XObject.CLASS_BOOLEAN: type = "boolean"; break;
  -                  case XObject.CLASS_NUMBER:  type = "double";  break;
  -                  case XObject.CLASS_STRING:
  -                     if ( ps.indexOf('@') != -1 )
  -                        type = "string";
  -                     else
  -                        type = "trimmed";
  -                     break;
  -               }
  -               if ( type != null )
  -                  e.setAttribute("type", type);
  -
  -               idxMgr.create(new Configuration(e));
  -            }
  -         }
  -         catch ( Exception e ) {
  -            if (log.isDebugEnabled()) {
  -               log.debug("No message", e);
  -            }
  -         }
  -         return null;
  -      }
  -
  -      /**
  -       * queryComparison performs a comparison query use the operands that
  -       * are passed to it, and returns the resulting Keys.
  -       *
  -       * @param op The Operator
  -       * @param owner The Owner Node
  -       * @param left The left Operand
  -       * @param right The right Operand
  -       * @return The resulting Keys (if any)
  -       */
  -      private Object queryComparison(int op, String owner, Object left, Object right) {
  -         if ( ! ( ( left instanceof NamedKeys ) && ( right instanceof XObject )
  -               || ( left instanceof XObject ) && ( right instanceof NamedKeys ) ) )
  -            return null; // How'd we get here?
  -
  -         op = OpMap[op-OpCodes.OP_NOTEQUALS];
  -
  -         if ( left instanceof XObject ) {
  -            // Check if we have to switch the operation
  -            if ( op == IndexQuery.GT
  -              || op == IndexQuery.LT
  -              || op == IndexQuery.GEQ
  -              || op == IndexQuery.LEQ )
  -               op = -op;
  -            // Swap the operands
  -            Object tmp = left;
  -            left = right;
  -            right = tmp;
  -         }
  -
  -         NamedKeys nk = (NamedKeys)left;
  -         XObject obj = (XObject)right;
  -
  -         String ps;
  -         if ( nk.attribute && nk.name.indexOf('@') == -1 )
  -            ps = owner+"@"+nk.name;
  -         else
  -            ps = nk.name;
  -
  -         IndexQuery iq;
  -         IndexPattern pattern = new IndexPattern(symbols, ps, nsMap);
  -         String value = obj.str();
  -
  -         switch ( op ) {
  -            case IndexQuery.NEQ: iq = new IndexQueryNEQ(pattern, value); break;
  -            case IndexQuery.EQ:  iq = new IndexQueryEQ(pattern, value);  break;
  -            case IndexQuery.LEQ: iq = new IndexQueryLEQ(pattern, value); break;
  -            case IndexQuery.LT:  iq = new IndexQueryLT(pattern, value);  break;
  -            case IndexQuery.GEQ: iq = new IndexQueryGEQ(pattern, value); break;
  -            case IndexQuery.GT:  iq = new IndexQueryGT(pattern, value);  break;
  -            default:             iq = null; // Won't happen
  -         }
  -
  -         return queryIndexes(nk, iq, ps, obj.getType());
  -      }
  -   }
  -
  -
  -   /**
  -    * NamedKeys
  -    */
  -
  -   private class NamedKeys {
  -      public boolean attribute = false;
  -      public String name;
  -      public Key[] keys;
  -
  -      public NamedKeys(String name, boolean attribute, Key[] keys) {
  -         this.name = name;
  -         this.attribute = attribute;
  -         this.keys = keys;
  -      }
  -   }
  -
  -
  -   /**
  -    * ResultSet
  -    */
  -
  -   private class ResultSet implements NodeSet {
  -      public Collection context;
  -      public String query;
  -      public ErrorListener errors;
  -      public PrefixResolver pr;
  -      public XPath xp;
  -
  -      public Key[] keySet;
  -      public int keyPos = 0;
  -      public NodeIterator ni;
  -      public Node node;
  -
  -      public ResultSet(Collection context, PrefixResolver pr, Key[] keySet, String query) {
  -//System.out.println("Query: "+query);
  -         this.context = context;
  -         this.pr = pr;
  -         this.keySet = keySet;
  -         this.query = query;
  -
  -         errors = new ErrorListener() {
  -            public void fatalError(TransformerException te) {
  -               if (log.isFatalEnabled()) {
  -                  log.fatal("No message", te);
  -               }
  -            }
  -
  -            public void error(TransformerException te) {
  -               if (log.isErrorEnabled()) {
  -                  log.error("No message", te);
  -               }
  -            }
  -
  -            public void warning(TransformerException te) {
  -               if (log.isWarnEnabled()) {
  -                  log.warn("No message", te);
  -               }
  -            }
  -         };
  -
  -         prepareNextNode();
  -      }
  -
  -      private void prepareNextNode() {
  -         node = null;
  -         while ( keyPos < keySet.length ) {
  -            try {
  -//System.out.println("  Key: "+keySet[keyPos]);
  -               DBDocument d = (DBDocument)context.getDocument(keySet[keyPos++]);
  -               if ( d == null )
  -                  continue;
  -
  -               Node n = d.getDocumentElement();
  -
  -               XPathContext xpc = new XPathContext();
  -               PrefixResolver pfx;
  -               if ( pr == null ) {
  -                  pfx = new PrefixResolverDefault(d.getDocumentElement());
  -                  xp = new XPath(query, null, pfx, XPath.SELECT, errors);
  -               }
  -               else {
  -                  pfx = pr;
  -                  if ( xp == null )
  -                     xp = new XPath(query, null, pfx, XPath.SELECT, errors);
  -               }
  -
  -               ni = xp.execute(xpc, n, pfx).nodeset();
  -
  -               node = ni.nextNode();
  -               if ( node != null )
  -                  break;
  -            }
  -            catch ( Exception e ) {
  -               if (log.isDebugEnabled()) {
  -                  log.debug("No message", e);
  -               }
  -            }
  -         }
  -      }
  -
  -      public boolean hasMoreNodes() {
  -         return node != null;
  -      }
  +                return queryComparison(op, owner, left, right);
  +        }
   
  -      public Node getNextNode() {
  -         Node n = node;
  +        private strictfp Object evalMathOperation(int op, String owner, int pos) throws Exception {
  +            int lc = Compiler.getFirstChildPos(pos);
  +            int rc = cmp.getNextOpPos(lc);
  +            XObject left = (XObject) evaluate(owner, lc);
  +            XObject right = (XObject) evaluate(owner, rc);
  +
  +            switch (op) {
  +                case OpCodes.OP_PLUS :
  +                    return new XNumber(left.num() + right.num());
  +                case OpCodes.OP_MINUS :
  +                    return new XNumber(left.num() - right.num());
  +                case OpCodes.OP_MULT :
  +                    return new XNumber(left.num() * right.num());
  +                case OpCodes.OP_DIV :
  +                    return new XNumber(left.num() / right.num());
  +                case OpCodes.OP_MOD :
  +                    return new XNumber(left.num() % right.num());
  +                case OpCodes.OP_QUO :
  +                    return new XNumber(left.num() / right.num());
  +                default :
  +                    return null; // Won't happen
  +            }
  +        }
  +
  +        private Object evalUnaryOperation(int op, String owner, int pos) throws Exception {
  +            XObject val = (XObject) evaluate(owner, Compiler.getFirstChildPos(pos));
  +            switch (op) {
  +                case OpCodes.OP_NEG :
  +                    return new XNumber(-val.num());
  +                case OpCodes.OP_STRING :
  +                    return new XString(val.str());
  +                case OpCodes.OP_BOOL :
  +                    return new XBoolean(val.bool());
  +                case OpCodes.OP_NUMBER :
  +                    return new XNumber(val.num());
  +                default :
  +                    return null; // Won't happen
  +            }
  +        }
  +
  +        private Object evalFunction(String owner, int pos) throws Exception {
  +            int idx = Compiler.getFirstChildPos(pos);
  +            int id = cmp.getOp(idx);
  +            int endFunc = cmp.getOp(pos + 1) - 1;
  +
  +            List args = new ArrayList();
  +            int lp = idx + 1;
  +            while (lp < endFunc) {
  +                args.add(evaluate(owner, lp));
  +                lp = cmp.getNextOpPos(lp);
  +            }
  +
  +            switch (id) {
  +                case FUNC_BOOLEAN :
  +                    return funcBoolean(args);
  +                case FUNC_CEILING :
  +                    return funcCeiling(args);
  +                case FUNC_CONCAT :
  +                    return funcConcat(args);
  +                case FUNC_CONTAINS :
  +                    return funcContains(args);
  +                case FUNC_FALSE :
  +                    return XBoolean.S_FALSE;
  +                case FUNC_FLOOR :
  +                    return funcFloor(args);
  +                case FUNC_NORMALIZE_SPACE :
  +                    return funcNormalizeSpace(args);
  +                case FUNC_NOT :
  +                    return funcNot(args);
  +                case FUNC_NUMBER :
  +                    return funcNumber(args);
  +                case FUNC_ROUND :
  +                    return funcRound(args);
  +                case FUNC_STARTS_WITH :
  +                    return funcStartsWith(owner, args);
  +                case FUNC_STRING :
  +                    return funcString(args);
  +                case FUNC_STRING_LENGTH :
  +                    return funcStringLength(args);
  +                case FUNC_SUBSTRING :
  +                    return funcSubstring(args);
  +                case FUNC_SUBSTRING_AFTER :
  +                    return funcSubstringAfter(args);
  +                case FUNC_SUBSTRING_BEFORE :
  +                    return funcSubstringBefore(args);
  +                case FUNC_TRANSLATE :
  +                    return funcTranslate(args);
  +                case FUNC_TRUE :
  +                    return XBoolean.S_TRUE;
  +                default :
  +                    return null;
  +            }
  +        }
  +
  +        private Object evalAxis(int op, String owner, int pos) throws Exception {
  +            String nsURI = cmp.getStepNS(pos);
  +            owner = (String) evaluate(owner, Compiler.getFirstChildPosOfStep(pos));
  +            //owner = cmp.getStepLocalName(pos);
  +
  +            if (nsURI != null && nsMap != null) {
  +                // We have to determine the prefix that was used
  +                // There has to be an easier way to do this with Xalan
  +                String pfx = null;
  +                Iterator i = nsMap.keySet().iterator();
  +                while (i.hasNext()) {
  +                    String p = (String) i.next();
  +                    if (nsMap.getNamespaceURI(p).equals(nsURI)) {
  +                        pfx = p;
  +                        break;
  +                    }
  +                }
  +                if (pfx != null) {
  +                    StringBuffer sb = new StringBuffer(32);
  +                    sb.append(pfx);
  +                    sb.append(':');
  +                    sb.append(owner);
  +                    owner = sb.toString();
  +                }
  +            }
  +
  +            int rp = cmp.getFirstPredicateOpPos(pos);
  +
  +            List ks = new ArrayList();
  +            while (rp < pos + cmp.getOp(pos + 1)) {
  +                Object obj = evaluate(owner, rp);
  +                if (obj instanceof NamedKeys) {
  +                    NamedKeys nk = (NamedKeys) obj;
  +                    if (nk.keys != null)
  +                        ks.add(nk.keys);
  +                }
  +                rp = cmp.getNextOpPos(rp);
  +            }
  +            return new NamedKeys(owner, (op == OpCodes.FROM_ATTRIBUTES), andKeys(ks));
  +        }
  +
  +        private Object evalLiteral(String owner, int pos) throws Exception {
  +            int idx = cmp.getOp(Compiler.getFirstChildPos(pos));
  +            switch (idx) {
  +                case OpCodes.EMPTY :
  +                    return owner;
  +                case OpCodes.ELEMWILDCARD :
  +                    return WILDCARD;
  +                default :
  +                    return cmp.getToken(idx);
  +            }
  +        }
  +
  +        // XPath Functions
  +
  +        private Object funcBoolean(List args) throws Exception {
  +            if (args.size() == 1) {
  +                Object o = args.get(0);
  +                if (o instanceof XObject) {
  +                    if (((XObject) o).bool())
  +                        return XBoolean.S_TRUE;
  +                    else
  +                        return XBoolean.S_FALSE;
  +                }
  +                else
  +                    return o;
  +            }
  +            return null;
  +        }
   
  -         node = ni.nextNode();
  -         if ( node == null )
  -            prepareNextNode();
  +        private Object funcCeiling(List args) throws Exception {
  +            if (args.size() == 1) {
  +                Object o = args.get(0);
  +                if (o instanceof XObject)
  +                    return new XNumber(Math.ceil(((XObject) o).num()));
  +            }
  +            return null;
  +        }
   
  -         return n;
  -      }
  -   }
  -}
  +        private Object funcConcat(List args) {
  +            StringBuffer sb = new StringBuffer();
  +            for (int i = 0; i < args.size(); i++) {
  +                Object o = args.get(i);
  +                if (o instanceof XObject)
  +                    sb.append(((XObject) o).str());
  +            }
  +            return new XString(sb.toString());
  +        }
  +
  +        private Object funcContains(List args) {
  +            if (args.size() == 2) {
  +                Object o = args.get(0);
  +                Object s = args.get(1);
  +                if (o instanceof XObject && s instanceof XObject) {
  +                    if (((XObject) o).str().indexOf(((XObject) s).str()) != -1)
  +                        return XBoolean.S_TRUE;
  +                    else
  +                        return XBoolean.S_FALSE;
  +                }
  +            }
  +            return null;
  +        }
  +
  +        private Object funcFloor(List args) throws Exception {
  +            if (args.size() == 1) {
  +                Object o = args.get(0);
  +                if (o instanceof XObject)
  +                    return new XNumber(Math.floor(((XObject) o).num()));
  +            }
  +            return null;
  +        }
  +
  +        private Object funcNormalizeSpace(List args) {
  +            if (args.size() == 1) {
  +                Object o = args.get(0);
  +                if (o instanceof XObject)
  +                    return new XString(QueryEngine.normalizeString(((XObject) o).str()));
  +                else
  +                    return o;
  +            }
  +            return null;
  +        }
   
  +        private Object funcNot(List args) throws Exception {
  +            if (args.size() == 1) {
  +                Object o = args.get(0);
  +                if (o instanceof XObject) {
  +                    if (((XObject) o).bool())
  +                        return XBoolean.S_FALSE;
  +                    else
  +                        return XBoolean.S_TRUE;
  +                }
  +            }
  +            return null;
  +        }
   
  +        private Object funcNumber(List args) throws Exception {
  +            if (args.size() == 1) {
  +                Object o = args.get(0);
  +                if (o instanceof XObject)
  +                    return new XNumber(((XObject) o).num());
  +                else
  +                    return o;
  +            }
  +            return null;
  +        }
   
  +        private Object funcRound(List args) throws Exception {
  +            if (args.size() == 1) {
  +                Object o = args.get(0);
  +                if (o instanceof XObject)
  +                    return new XNumber(Math.round(((XObject) o).num()));
  +            }
  +            return null;
  +        }
   
  +        private Object funcStartsWith(String owner, List args) {
  +            if (args.size() == 2) {
  +                Object o = args.get(0);
  +                Object s = args.get(1);
  +
  +                if (o instanceof XObject && s instanceof XObject) {
  +                    if (((XObject) o).str().startsWith(((XObject) s).str()))
  +                        return XBoolean.S_TRUE;
  +                    else
  +                        return XBoolean.S_FALSE;
  +                }
  +                else if (o instanceof NamedKeys && s instanceof XObject) {
  +                    NamedKeys nk = (NamedKeys) o;
  +                    String ps;
  +                    if (nk.attribute && nk.name.indexOf('@') == -1)
  +                        ps = owner + "@" + nk.name;
  +                    else
  +                        ps = nk.name;
  +
  +                    IndexPattern pattern = new IndexPattern(symbols, ps, nsMap);
  +
  +                    XObject obj = (XObject) s;
  +                    Value val1 = new Value(obj.str());
  +
  +                    IndexQuery iq = new IndexQuerySW(pattern, val1);
  +                    return queryIndexes(nk, iq, ps, obj.getType());
  +                }
  +            }
  +            return null;
  +        }
   
  +        private Object funcString(List args) {
  +            if (args.size() == 1) {
  +                Object o = args.get(0);
  +                if (o instanceof XObject)
  +                    return new XString(((XObject) o).str());
  +                else
  +                    return o;
  +            }
  +            return null;
  +        }
   
  +        private Object funcStringLength(List args) {
  +            if (args.size() == 1) {
  +                Object o = args.get(0);
  +                if (o instanceof XObject)
  +                    return new XNumber(((XObject) o).str().length());
  +            }
  +            return null;
  +        }
  +
  +        private Object funcSubstring(List args) throws Exception {
  +            if (args.size() == 2 || args.size() == 3) {
  +                Object o = args.get(0);
  +                Object pos = args.get(1);
  +                Object len = args.get(2);
  +                if (o instanceof XObject && pos instanceof XObject && (len == null || len instanceof XObject)) {
  +                    int ipos = (int) ((XObject) pos).num() - 1;
  +                    if (len != null) {
  +                        int ilen = (int) ((XObject) len).num();
  +                        return new XString(((XObject) o).str().substring(ipos, ipos + ilen));
  +                    }
  +                    else
  +                        return new XString(((XObject) o).str().substring(ipos));
  +                }
  +            }
  +            return null;
  +        }
   
  +        private Object funcSubstringAfter(List args) {
  +            if (args.size() == 2) {
  +                Object o = args.get(0);
  +                Object s = args.get(1);
  +                if (o instanceof XObject && s instanceof XObject) {
  +                    String val = ((XObject) o).str();
  +                    String sub = ((XObject) s).str();
  +                    int i = val.indexOf(sub);
  +                    if (i == -1)
  +                        return new XString("");
  +                    else
  +                        return new XString(val.substring(i + sub.length()));
  +                }
  +            }
  +            return null;
  +        }
  +
  +        private Object funcSubstringBefore(List args) {
  +            if (args.size() == 2) {
  +                Object o = args.get(0);
  +                Object s = args.get(1);
  +                if (o instanceof XObject && s instanceof XObject) {
  +                    String val = ((XObject) o).str();
  +                    String sub = ((XObject) s).str();
  +                    int i = val.indexOf(sub);
  +                    if (i == -1)
  +                        return new XString("");
  +                    else
  +                        return new XString(val.substring(0, i));
  +                }
  +            }
  +            return null;
  +        }
  +
  +        private Object funcTranslate(List args) {
  +            if (args.size() == 3) {
  +                Object o = args.get(0);
  +                Object c1 = args.get(1);
  +                Object c2 = args.get(2);
  +                if (o instanceof XObject && c1 instanceof XObject && c2 instanceof XObject) {
  +                    char ch1 = ((XObject) c1).str().charAt(0);
  +                    char ch2 = ((XObject) c2).str().charAt(0);
  +                    return new XString(((XObject) o).str().replace(ch1, ch2));
  +                }
  +            }
  +            return null;
  +        }
  +
  +        // The Actual Querying Methods
  +
  +        /**
  +         * queryIndexes actually performs index-based querying on behalf of
  +         * the evaluation methods.
  +         *
  +         * @param nk The NamedKeys instance to use for matches
  +         * @param iq The actual IndexQuery to use for resolution
  +         * @param ps The pattern String to possibly use for index gen
  +         * @param objType The object type to possibly use for index gen
  +         * @return The resulting Keys (if any)
  +         */
  +        private Object queryIndexes(NamedKeys nk, IndexQuery iq, String ps, int objType) {
  +            try {
  +                // TODO: Add logic to use an EmptyKeySet if a name doesn't already
  +                //       exist in the SymbolTable.  This will eliminate the need
  +                //       to do a collection scan in those cases where somebody
  +                //       typed an element or attribute name incorrectly.
  +
  +                IndexPattern pattern = iq.getPattern();
  +
  +                Indexer idx = context.getIndexManager().getBestIndexer(Indexer.STYLE_NODEVALUE, pattern);
  +                if (idx != null)
  +                    return new NamedKeys(nk.name, nk.attribute, QueryEngine.getUniqueKeys(idx.queryMatches(iq)));
  +                else if (autoIndex) {
  +                    // TODO: This has to *not* be hardcoded
  +                    Element e = new DocumentImpl().createElement("index");
  +                    e.setAttribute("class", "org.apache.xindice.core.indexer.ValueIndexer");
  +                    e.setAttribute("name", "xp_" + ps);
  +                    e.setAttribute("pattern", ps);
  +
  +                    // Set the type for the index
  +                    String type = null;
  +                    switch (objType) {
  +                        case XObject.CLASS_BOOLEAN :
  +                            type = "boolean";
  +                            break;
  +                        case XObject.CLASS_NUMBER :
  +                            type = "double";
  +                            break;
  +                        case XObject.CLASS_STRING :
  +                            if (ps.indexOf('@') != -1)
  +                                type = "string";
  +                            else
  +                                type = "trimmed";
  +                            break;
  +                    }
  +                    if (type != null)
  +                        e.setAttribute("type", type);
  +
  +                    idxMgr.create(new Configuration(e));
  +                }
  +            }
  +            catch (Exception e) {
  +                log.warn(e);
  +            }
  +            return null;
  +        }
  +
  +        /**
  +         * queryComparison performs a comparison query use the operands that
  +         * are passed to it, and returns the resulting Keys.
  +         *
  +         * @param op The Operator
  +         * @param owner The Owner Node
  +         * @param left The left Operand
  +         * @param right The right Operand
  +         * @return The resulting Keys (if any)
  +         */
  +        private Object queryComparison(int op, String owner, Object left, Object right) {
  +            if (!((left instanceof NamedKeys) && (right instanceof XObject) || (left instanceof XObject) && (right instanceof NamedKeys)))
  +                return null; // How'd we get here?
  +
  +            op = OpMap[op - OpCodes.OP_NOTEQUALS];
  +
  +            if (left instanceof XObject) {
  +                // Check if we have to switch the operation
  +                if (op == IndexQuery.GT || op == IndexQuery.LT || op == IndexQuery.GEQ || op == IndexQuery.LEQ)
  +                    op = -op;
  +                // Swap the operands
  +                Object tmp = left;
  +                left = right;
  +                right = tmp;
  +            }
  +
  +            NamedKeys nk = (NamedKeys) left;
  +            XObject obj = (XObject) right;
  +
  +            String ps;
  +            if (nk.attribute && nk.name.indexOf('@') == -1)
  +                ps = owner + "@" + nk.name;
  +            else
  +                ps = nk.name;
  +
  +            IndexQuery iq;
  +            IndexPattern pattern = new IndexPattern(symbols, ps, nsMap);
  +            String value = obj.str();
  +
  +            switch (op) {
  +                case IndexQuery.NEQ :
  +                    iq = new IndexQueryNEQ(pattern, value);
  +                    break;
  +                case IndexQuery.EQ :
  +                    iq = new IndexQueryEQ(pattern, value);
  +                    break;
  +                case IndexQuery.LEQ :
  +                    iq = new IndexQueryLEQ(pattern, value);
  +                    break;
  +                case IndexQuery.LT :
  +                    iq = new IndexQueryLT(pattern, value);
  +                    break;
  +                case IndexQuery.GEQ :
  +                    iq = new IndexQueryGEQ(pattern, value);
  +                    break;
  +                case IndexQuery.GT :
  +                    iq = new IndexQueryGT(pattern, value);
  +                    break;
  +                default :
  +                    iq = null; // Won't happen
  +            }
  +
  +            return queryIndexes(nk, iq, ps, obj.getType());
  +        }
  +    }
  +
  +    /**
  +     * NamedKeys
  +     */
  +
  +    private class NamedKeys {
  +        public boolean attribute = false;
  +        public String name;
  +        public Key[] keys;
  +
  +        public NamedKeys(String name, boolean attribute, Key[] keys) {
  +            this.name = name;
  +            this.attribute = attribute;
  +            this.keys = keys;
  +        }
  +    }
  +
  +    /**
  +     * ResultSet
  +     */
  +
  +    private class ResultSet implements NodeSet {
  +        public Collection context;
  +        public String query;
  +        public ErrorListener errors;
  +        public PrefixResolver pr;
  +        public XPath xp;
  +
  +        public Key[] keySet;
  +        public int keyPos = 0;
  +        public NodeIterator ni;
  +        public Node node;
  +
  +        public ResultSet(Collection context, PrefixResolver pr, Key[] keySet, String query) {
  +            //System.out.println("Query: "+query);
  +            this.context = context;
  +            this.pr = pr;
  +            this.keySet = keySet;
  +            this.query = query;
  +
  +            errors = new ErrorListener() {
  +                public void fatalError(TransformerException te) {
  +                    if (log.isFatalEnabled()) {
  +                        log.fatal("No message", te);
  +                    }
  +                }
  +
  +                public void error(TransformerException te) {
  +                    if (log.isErrorEnabled()) {
  +                        log.error("No message", te);
  +                    }
  +                }
  +
  +                public void warning(TransformerException te) {
  +                    if (log.isWarnEnabled()) {
  +                        log.warn("No message", te);
  +                    }
  +                }
  +            };
  +
  +            prepareNextNode();
  +        }
  +
  +        private void prepareNextNode() {
  +            node = null;
  +            while (keyPos < keySet.length) {
  +                try {
  +                    //System.out.println("  Key: "+keySet[keyPos]);
  +                    DBDocument d = (DBDocument) context.getDocument(keySet[keyPos++]);
  +                    if (d == null)
  +                        continue;
  +
  +                    Node n = d.getDocumentElement();
  +
  +                    XPathContext xpc = new XPathContext();
  +                    PrefixResolver pfx;
  +                    if (pr == null) {
  +                        pfx = new PrefixResolverDefault(d.getDocumentElement());
  +                        xp = new XPath(query, null, pfx, XPath.SELECT, errors);
  +                    }
  +                    else {
  +                        pfx = pr;
  +                        if (xp == null)
  +                            xp = new XPath(query, null, pfx, XPath.SELECT, errors);
  +                    }
  +
  +                    ni = xp.execute(xpc, n, pfx).nodeset();
  +
  +                    node = ni.nextNode();
  +                    if (node != null)
  +                        break;
  +                }
  +                catch (Exception e) {
  +                    log.warn(e);
  +                }
  +            }
  +        }
  +
  +        public boolean hasMoreNodes() {
  +            return node != null;
  +        }
  +
  +        public Node getNextNode() {
  +            Node n = node;
  +
  +            node = ni.nextNode();
  +            if (node == null)
  +                prepareNextNode();
  +
  +            return n;
  +        }
  +    }
  +}
  
  
  
  1.7       +246 -234  xml-xindice/java/src/org/apache/xindice/xml/TextWriter.java
  
  Index: TextWriter.java
  ===================================================================
  RCS file: /home/cvs/xml-xindice/java/src/org/apache/xindice/xml/TextWriter.java,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- TextWriter.java	31 Oct 2002 07:02:22 -0000	1.6
  +++ TextWriter.java	15 Jul 2003 15:44:36 -0000	1.7
  @@ -59,11 +59,6 @@
    * $Id$
    */
   
  -import org.apache.commons.logging.Log;
  -import org.apache.commons.logging.LogFactory;
  -
  -import org.w3c.dom.*;
  -
   import java.io.BufferedWriter;
   import java.io.IOException;
   import java.io.OutputStream;
  @@ -71,6 +66,16 @@
   import java.io.StringWriter;
   import java.io.Writer;
   
  +import org.apache.commons.logging.Log;
  +import org.apache.commons.logging.LogFactory;
  +import org.w3c.dom.Attr;
  +import org.w3c.dom.DOMException;
  +import org.w3c.dom.Element;
  +import org.w3c.dom.NamedNodeMap;
  +import org.w3c.dom.Node;
  +import org.w3c.dom.NodeList;
  +import org.w3c.dom.ProcessingInstruction;
  +
   /**
    * TextWriter takes a Document, DocumentFragment, or Element and
    * streams it as text to an output source (or a String)
  @@ -78,248 +83,255 @@
   
   public final class TextWriter {
   
  -   private static Log log = LogFactory.getLog("org.apache.xindice.xml");
  +    private static Log log = LogFactory.getLog("org.apache.xindice.xml");
   
  -   private Node node = null;
  +    private Node node = null;
   
  -   public TextWriter(Node node) throws DOMException {
  -      this.node = node;
  -   }
  -
  -   /**
  -    * write writes the node to the writer as text.
  -    *
  -    * @param writer The Writer to write to
  -    */
  -   public void write(Writer writer) throws IOException {
  -       write( node, writer );
  -   }
  -
  -   /**
  -    * write writes the node to the OutputStream as text.
  -    *
  -    * @param output The OutputStream to write to
  -    */
  -   public void write(OutputStream output) throws IOException {
  -       write( node, output );
  -   }
  -
  -   /**
  -    * toString returns the node as a String.
  -    *
  -    * @return The String value
  -    */
  -    public String toString() {
  -	return toString( node );
  +    public TextWriter(Node node) throws DOMException {
  +        this.node = node;
       }
   
  +    /**
  +     * write writes the node to the writer as text.
  +     *
  +     * @param writer The Writer to write to
  +     */
  +    public void write(Writer writer) throws IOException {
  +        write(node, writer);
  +    }
   
  +    /**
  +     * write writes the node to the OutputStream as text.
  +     *
  +     * @param output The OutputStream to write to
  +     */
  +    public void write(OutputStream output) throws IOException {
  +        write(node, output);
  +    }
   
  +    /**
  +     * toString returns the node as a String.
  +     *
  +     * @return The String value
  +     */
  +    public String toString() {
  +        return toString(node);
  +    }
   
  +    private static void writeNode(Writer writer, Node node) throws IOException {
  +        short type = node.getNodeType();
  +        switch (type) {
  +
  +            case Node.DOCUMENT_NODE :
  +                {
  +                    writer.write("<?xml version=\"1.0\"?>\n");
  +                    writeChildren(writer, node);
  +                    break;
  +                }
  +
  +            case Node.DOCUMENT_FRAGMENT_NODE :
  +                {
  +                    writeChildren(writer, node);
  +                    break;
  +                }
  +
  +            case Node.DOCUMENT_TYPE_NODE :
  +                {
  +                    if (log.isErrorEnabled()) {
  +                        log.error("can't serialize doctype yet");
  +                    }
  +                    /*
  +                    DocumentType d = (DocumentType)node;
  +                    writer.write("<!DOCTYPE ");
  +                    writer.write(node.getOwnerDocument().getDocumentElement().getNodeName());
  +                    writer.write('>');
  +                    */
  +                    break;
  +                }
  +
  +            case Node.ELEMENT_NODE :
  +                {
  +                    Element e = (Element) node;
  +                    String n = e.getTagName();
  +
  +                    writer.write('<');
  +                    writer.write(n);
  +
  +                    NamedNodeMap a = e.getAttributes();
  +                    int size = a.getLength();
  +                    for (int i = 0; i < size; i++) {
  +                        Attr att = (Attr) a.item(i);
  +                        writer.write(' ');
  +                        writeNode(writer, att);
  +                    }
  +
  +                    if (e.hasChildNodes()) {
  +                        writer.write('>');
  +                        writeChildren(writer, node);
  +                        writer.write("</");
  +                        writer.write(n);
  +                        writer.write('>');
  +                    }
  +                    else
  +                        writer.write(" />");
  +                    break;
  +                }
  +
  +            case Node.ATTRIBUTE_NODE :
  +                Attr a = (Attr) node;
  +                writer.write(a.getName());
  +                writer.write("=\"");
  +                writeEscapedText(writer, a.getValue());
  +                writer.write("\"");
  +                break;
  +
  +            case Node.ENTITY_REFERENCE_NODE :
  +                if (log.isErrorEnabled()) {
  +                    log.error("can't serialize reference ref yet");
  +                }
  +                break;
  +
  +            case Node.ENTITY_NODE :
  +                if (log.isErrorEnabled()) {
  +                    log.error("can't serialize entity yet");
  +                }
  +                break;
  +
  +            case Node.NOTATION_NODE :
  +                if (log.isErrorEnabled()) {
  +                    log.error("can't serialize notation yet");
  +                }
  +                break;
  +
  +            case Node.PROCESSING_INSTRUCTION_NODE :
  +                {
  +                    ProcessingInstruction pi = (ProcessingInstruction) node;
  +                    writer.write("<?");
  +                    writer.write(pi.getTarget());
  +                    writer.write(" ");
  +                    writer.write(pi.getData());
  +                    writer.write("?>\n");
  +                    break;
  +                }
  +
  +            case Node.TEXT_NODE :
  +                {
  +                    writeEscapedText(writer, node.getNodeValue());
  +                    break;
  +                }
  +
  +            case Node.CDATA_SECTION_NODE :
  +                {
  +                    writer.write("<![CDATA[");
  +                    writer.write(node.getNodeValue());
  +                    writer.write("]]>");
  +                    break;
  +                }
  +
  +            case Node.COMMENT_NODE :
  +                {
  +                    writer.write("<!--");
  +                    writer.write(node.getNodeValue());
  +                    writer.write("-->");
  +                    break;
  +                }
  +        }
  +    }
   
  +    private static void writeChildren(Writer writer, Node node) throws IOException {
  +        NodeList l = node.getChildNodes();
  +        int size = l.getLength();
  +        for (int i = 0; i < size; i++)
  +            writeNode(writer, l.item(i));
  +    }
   
  -   private static void writeNode(Writer writer, Node node) throws IOException {
  -      short type = node.getNodeType();
  -      switch ( type ) {
  -
  -         case Node.DOCUMENT_NODE: {
  -            writer.write("<?xml version=\"1.0\"?>\n");
  -            writeChildren(writer, node);
  -            break;
  -         }
  -
  -         case Node.DOCUMENT_FRAGMENT_NODE: {
  -            writeChildren(writer, node);
  -            break;
  -         }
  -
  -         case Node.DOCUMENT_TYPE_NODE: {
  -            if (log.isErrorEnabled()) {
  -               log.error("can't serialize doctype yet");
  -            }
  -            /*
  -            DocumentType d = (DocumentType)node;
  -            writer.write("<!DOCTYPE ");
  -            writer.write(node.getOwnerDocument().getDocumentElement().getNodeName());
  -            writer.write('>');
  -            */
  -            break;
  -         }
  -
  -         case Node.ELEMENT_NODE: {
  -            Element e = (Element)node;
  -            String n = e.getTagName();
  -
  -            writer.write('<');
  -            writer.write(n);
  -
  -            NamedNodeMap a = e.getAttributes();
  -            int size = a.getLength();
  -            for ( int i = 0; i < size; i++ ) {
  -               Attr att = (Attr)a.item(i);
  -               writer.write(' ');
  -               writeNode(writer, att);
  +    private static void writeEscapedText(Writer writer, String text) throws IOException {
  +        char[] value = text.toCharArray();
  +        String outval = null;
  +        int start = 0;
  +        int len = 0;
  +        for (int i = 0; i < value.length; i++) {
  +            switch (value[i]) {
  +                case '&' :
  +                    outval = "&amp;";
  +                    break;
  +                case '\'' :
  +                    outval = "&apos;";
  +                    break;
  +                case '\"' :
  +                    outval = "&quot;";
  +                    break;
  +                case '<' :
  +                    outval = "&lt;";
  +                    break;
  +                case '>' :
  +                    outval = "&gt;";
  +                    break;
  +                default :
  +                    len++;
  +                    break;
               }
   
  -            if ( e.hasChildNodes() ) {
  -               writer.write('>');
  -               writeChildren(writer, node);
  -               writer.write("</");
  -               writer.write(n);
  -               writer.write('>');
  -            }
  -            else
  -               writer.write(" />");
  -            break;
  -         }
  -
  -         case Node.ATTRIBUTE_NODE:
  -            Attr a = (Attr)node;
  -            writer.write(a.getName());
  -            writer.write("=\"");
  -            writeEscapedText(writer, a.getValue());
  -            writer.write("\"");
  -            break;
  -
  -         case Node.ENTITY_REFERENCE_NODE:
  -            if (log.isErrorEnabled()) {
  -               log.error("can't serialize reference ref yet");
  +            if (outval != null) {
  +                if (len > 0)
  +                    writer.write(value, start, len);
  +                writer.write(outval);
  +                start = i + 1;
  +                len = 0;
  +                outval = null;
               }
  -            break;
  +        }
  +        if (len > 0)
  +            writer.write(value, start, len);
  +    }
   
  -         case Node.ENTITY_NODE:
  -            if (log.isErrorEnabled()) {
  -               log.error("can't serialize entity yet");
  -            }
  -            break;
  +    /**
  +     * write writes the specified node to the writer as text.
  +     *
  +     * @param node The Node to write
  +     * @param writer The Writer to write to
  +     */
  +    public static void write(Node node, Writer writer) throws IOException {
  +        try {
  +            BufferedWriter buf = new BufferedWriter(writer, 4096);
  +            writeNode(buf, node);
  +            buf.flush();
  +        }
  +        catch (Exception e) {
  +            log.warn(e);
  +        }
  +    }
   
  -         case Node.NOTATION_NODE:
  -            if (log.isErrorEnabled()) {
  -               log.error("can't serialize notation yet");
  -            }
  -            break;
  +    /**
  +     * write writes the specified node to the OutputStream as text.
  +     *
  +     * @param node The Node to write
  +     * @param output The OutputStream to write to
  +     */
  +    public static void write(Node node, OutputStream output) throws IOException {
  +        try {
  +            OutputStreamWriter o = new OutputStreamWriter(output, "utf-8");
  +            write(node, o);
  +        }
  +        catch (Exception e) {
  +            log.warn(e);
  +        }
  +    }
   
  -         case Node.PROCESSING_INSTRUCTION_NODE: {
  -            ProcessingInstruction pi = (ProcessingInstruction)node;
  -            writer.write("<?");
  -            writer.write(pi.getTarget());
  -            writer.write(" ");
  -            writer.write(pi.getData());
  -            writer.write("?>\n");
  -            break;
  -         }
  -
  -         case Node.TEXT_NODE: {
  -            writeEscapedText(writer, node.getNodeValue());
  -            break;
  -         }
  -
  -         case Node.CDATA_SECTION_NODE: {
  -            writer.write("<![CDATA[");
  -            writer.write(node.getNodeValue());
  -            writer.write("]]>");
  -            break;
  -         }
  -
  -         case Node.COMMENT_NODE: {
  -            writer.write("<!--");
  -            writer.write(node.getNodeValue());
  -            writer.write("-->");
  -            break;
  -         }
  -      }
  -   }
  -
  -   private static void writeChildren(Writer writer, Node node) throws IOException {
  -      NodeList l = node.getChildNodes();
  -      int size = l.getLength();
  -      for ( int i = 0; i < size; i++ )
  -         writeNode(writer, l.item(i));
  -   }
  -
  -   private static void writeEscapedText(Writer writer, String text) throws IOException {
  -      char[] value = text.toCharArray();
  -      String outval = null;
  -      int start = 0;
  -      int len = 0;
  -      for ( int i = 0; i < value.length; i++ ) {
  -         switch ( value[i] ) {
  -            case '&'  : outval = "&amp;";  break;
  -            case '\'' : outval = "&apos;"; break;
  -            case '\"' : outval = "&quot;"; break;
  -            case '<'  : outval = "&lt;";   break;
  -            case '>'  : outval = "&gt;";   break;
  -            default   : len++;             break;
  -         }
  -
  -         if ( outval != null ) {
  -            if ( len > 0 )
  -               writer.write(value, start, len);
  -            writer.write(outval);
  -            start = i+1;
  -            len = 0;
  -            outval = null;
  -         }
  -      }
  -      if ( len > 0 )
  -         writer.write(value, start, len);
  -   }
  -   
  -   /**
  -    * write writes the specified node to the writer as text.
  -    *
  -    * @param node The Node to write
  -    * @param writer The Writer to write to
  -    */
  -   public static void write(Node node, Writer writer) throws IOException {
  -      try {
  -         BufferedWriter buf = new BufferedWriter(writer, 4096);
  -         writeNode(buf, node);
  -         buf.flush();
  -      }
  -      catch ( Exception e ) {
  -         if (log.isDebugEnabled()) {
  -            log.debug("No message", e);
  -         }
  -      }
  -   }
  -
  -   /**
  -    * write writes the specified node to the OutputStream as text.
  -    *
  -    * @param node The Node to write
  -    * @param output The OutputStream to write to
  -    */
  -   public static void write(Node node, OutputStream output) throws IOException {
  -      try {
  -         OutputStreamWriter o = new OutputStreamWriter(output, "utf-8");
  -         write( node, o);
  -      }
  -      catch ( Exception e ) {
  -         if (log.isDebugEnabled()) {
  -            log.debug("No message", e);
  -         }
  -      }
  -   }
  -
  -   /**
  -    * toString returns the node as a String.
  -    *
  -    * @param node The Node to convert
  -    * @return The String value
  -    **/
  -    public static String toString( Node node ) {
  -	StringWriter sw = new StringWriter();
  -	try {
  -	    write( node, sw );
  -	}
  -	catch ( IOException e ) {
  -       if (log.isDebugEnabled()) {
  -          log.debug("No message", e);
  -       }
  -	    //throw ex;
  -	}
  -	return sw.toString();
  +    /**
  +     * toString returns the node as a String.
  +     *
  +     * @param node The Node to convert
  +     * @return The String value
  +     **/
  +    public static String toString(Node node) {
  +        StringWriter sw = new StringWriter();
  +        try {
  +            write(node, sw);
  +        }
  +        catch (IOException e) {
  +            log.warn(e);
  +        }
  +        return sw.toString();
       }
   }
  -
  
  
  
  1.7       +50 -55    xml-xindice/java/src/org/apache/xindice/tools/command/XPathQuery.java
  
  Index: XPathQuery.java
  ===================================================================
  RCS file: /home/cvs/xml-xindice/java/src/org/apache/xindice/tools/command/XPathQuery.java,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- XPathQuery.java	31 Oct 2002 07:01:15 -0000	1.6
  +++ XPathQuery.java	15 Jul 2003 15:44:36 -0000	1.7
  @@ -59,8 +59,10 @@
    * $Id$
    */
   
  -import org.apache.xindice.tools.XMLTools;
  +import java.util.Hashtable;
  +import java.util.StringTokenizer;
   
  +import org.apache.xindice.tools.XMLTools;
   import org.xmldb.api.DatabaseManager;
   import org.xmldb.api.base.Collection;
   import org.xmldb.api.base.ResourceIterator;
  @@ -69,86 +71,79 @@
   import org.xmldb.api.modules.XMLResource;
   import org.xmldb.api.modules.XPathQueryService;
   
  -import java.util.Hashtable;
  -import java.util.StringTokenizer;
  -
   /**
    * SingleDocumentQuery is designed to enable the user/admin to XPathQuery a Collection for a Single Document.
    */
   
   public class XPathQuery extends Command {
   
  -    public boolean execute(Hashtable table ) throws Exception {
  +    public boolean execute(Hashtable table) throws Exception {
           Collection col = null;
  -        
  +
           try {
  -            
  -            if ( (String)table.get(XMLTools.COLLECTION) == null ) {
  +
  +            if ((String) table.get(XMLTools.COLLECTION) == null) {
                   System.out.println("ERROR : Collection name and switch required");
                   return false;
               }
   
  -            if ( (String)table.get(XMLTools.QUERY) == "" ) {
  +            if ((String) table.get(XMLTools.QUERY) == "") {
                   System.out.println("ERROR : Query and switch required");
                   return false;
               }
  -            
  -            
  -            String colstring = normalizeCollectionURI( (String)table.get(XMLTools.COLLECTION),
  -                                                       (String) table.get(XMLTools.LOCAL) );
  -            String querystring = (String)table.get(XMLTools.QUERY);
  +
  +            String colstring = normalizeCollectionURI((String) table.get(XMLTools.COLLECTION), (String) table.get(XMLTools.LOCAL));
  +            String querystring = (String) table.get(XMLTools.QUERY);
               XPathQueryService service = null;
               ResourceIterator results = null;
   
  -            col = DatabaseManager.getCollection( colstring );
  -            
  -            if ( col == null ) {
  -               System.out.println("ERROR : Collection not found!");
  -               return false;
  -            }
  -            
  -            service = (XPathQueryService)col.getService("XPathQueryService","1.0");
  -            addNamespaces(service, (String)table.get("namespaces"));
  -            
  +            col = DatabaseManager.getCollection(colstring);
  +
  +            if (col == null) {
  +                System.out.println("ERROR : Collection not found!");
  +                return false;
  +            }
  +
  +            service = (XPathQueryService) col.getService("XPathQueryService", "1.0");
  +            addNamespaces(service, (String) table.get("namespaces"));
  +
               ResourceSet resultSet = service.query(querystring);
               results = resultSet.getIterator();
  -            
  -            while (results.hasMoreResources() ) {
  -                XMLResource resource = (XMLResource)results.nextResource();
  -                String documentstr = (String)resource.getContent();
  +
  +            while (results.hasMoreResources()) {
  +                XMLResource resource = (XMLResource) results.nextResource();
  +                String documentstr = (String) resource.getContent();
                   System.out.println(documentstr);
               }
  -            
  -        } catch (Exception e) {
  -            System.out.println("ERROR : " + e.getMessage() );
  +
  +        }
  +        catch (Exception e) {
  +            System.out.println("ERROR : " + e.getMessage());
               if (table.get(XMLTools.VERBOSE).equals("true")) {
  -               if (log.isDebugEnabled()) {
  -                  log.debug("No message", e);
  -               }
  +                log.warn(e);
               }
               return false;
  -            
  -        } finally {
  -            if ( col != null ) {
  +
  +        }
  +        finally {
  +            if (col != null) {
                   col.close();
               }
           }
  -        
  -      return true;
  -   }
  -
  -	private void addNamespaces(XPathQueryService service, String namespacesString) throws XMLDBException {
  -		if ((namespacesString != "") && (namespacesString != null)) {
  -			StringTokenizer st = new StringTokenizer(namespacesString, "=;");
  -			if (st.countTokens() % 2 != 0) {
  -				System.out.println("ERROR : mismatched namespace prefixes and uris");
  -				return;
  -			}
  -			while (st.hasMoreTokens()) {
  -				service.setNamespace(st.nextToken(), st.nextToken());
  -			}
  -		}
  -	}
  -}
   
  +        return true;
  +    }
   
  +    private void addNamespaces(XPathQueryService service, String namespacesString) throws XMLDBException {
  +        if ((namespacesString != "") && (namespacesString != null)) {
  +            StringTokenizer st = new StringTokenizer(namespacesString, "=;");
  +            if (st.countTokens() % 2 != 0) {
  +                System.out.println("ERROR : mismatched namespace prefixes and uris");
  +                return;
  +            }
  +            while (st.hasMoreTokens()) {
  +                service.setNamespace(st.nextToken(), st.nextToken());
  +            }
  +        }
  +    }
  +}