package org.dbxml.core.xupdate;

/*
 * dbXML License, Version 1.0
 *
 *
 * Copyright (c) 1999-2001 The dbXML Group, L.L.C.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by
 *        The dbXML Group (http://www.dbxml.com/)."
 *    Alternately, this acknowledgment may appear in the software
 *    itself, if and wherever such third-party acknowledgments normally
 *    appear.
 *
 * 4. The names "dbXML" and "The dbXML Group" must not be used to
 *    endorse or promote products derived from this software without
 *    prior written permission. For written permission, please contact
 *    info@dbxml.com.
 *
 * 5. Products derived from this software may not be called "dbXML",
 *    nor may "dbXML" appear in their name, without prior written
 *    permission of The dbXML Group.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE DBXML GROUP OR ITS CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * $Id: XPathQueryImpl.java,v 1.2 2001/05/23 00:35:43 tom Exp $
 */
 
import org.w3c.dom.*;
import org.w3c.dom.traversal.NodeFilter;

import org.infozone.tools.xml.queries.*;

import org.apache.xpath.*;
import org.apache.xml.utils.*;

/**
 * XPath Query Impl to handle Xalan 2 XPath constructs.
 */
public final class XPathQueryImpl implements XPathQuery {
   
   private String qstring;
   private Node rootNode;
   private Node namespace;
   private NodeFilter filter;
   private XPath xpath;

   /**
    * Constructor for the XPathQueryImpl object
    */
   public XPathQueryImpl() {
   }

   /**
    * Sets the QString attribute of the XPathQueryImpl object
    *
    * @param qstring The new QString value
    * @exception Exception Description of Exception
    */
   public void setQString(String qstring) throws Exception {
      this.qstring = qstring;
   }

   /**
    * Sets the Namespace attribute of the XPathQueryImpl object
    *
    * @param namespace The new Namespace value
    * @exception Exception Description of Exception
    */
   public void setNamespace(Node namespace) throws Exception {
      this.namespace = namespace;
   }

   /**
    * Sets the NodeFilter attribute of the XPathQueryImpl object
    *
    * @param filter The new NodeFilter value
    * @exception Exception Description of Exception
    */
   public void setNodeFilter(NodeFilter filter) throws Exception {
      this.filter = filter;
   }

   /**
    * Execute the xpath.
    *
    * @param rootNode The node from which the query should start or null.
    * @return The XObject insulating the query result.
    * @exception Exception
    */
   public XObject execute(Node rootNode) throws Exception {
      if (rootNode.getNodeType() == Node.DOCUMENT_NODE) {
         rootNode = ((Document) rootNode).getDocumentElement();
      }

      this.rootNode = rootNode;

      // Since we don't have a XML Parser involved here, install some default
      // support for things like namespaces, etc.
      XPathContext xpathSupport = new XPathContext();
      
      PrefixResolver prefixResolver = null;
      // Create an object to resolve namespace prefixes.
      if (namespace != null) {
         if (namespace.getNodeType() == Node.DOCUMENT_NODE) {
            namespace = ((Document) namespace).getDocumentElement();
         }
         
         prefixResolver = new PrefixResolverDefault(namespace);
      }
      else {
         prefixResolver = new PrefixResolverDefault(rootNode);
      }
      
      // Create the XPath object.
      xpath = new XPath(qstring, null, prefixResolver, XPath.SELECT, null);
      
      // execute the XPath query on the specified root node
      return new XObjectImpl(xpath.execute(xpathSupport, rootNode, prefixResolver));
   }
}

