NXDSchema.java :  » Workflow-Engines » pegasus-2.1.0 » org » griphyn » vdl » dbschema » Java Open Source

Java Open Source » Workflow Engines » pegasus 2.1.0 
pegasus 2.1.0 » org » griphyn » vdl » dbschema » NXDSchema.java
/*
 * This file or a portion of this file is licensed under the terms of
 * the Globus Toolkit Public License, found in file ../GTPL, or at
 * http://www.globus.org/toolkit/download/license.html. This notice must
 * appear in redistributions of this file, with or without modification.
 *
 * Redistributions of this Software, with or without modification, must
 * reproduce the GTPL in: (1) the Software, or (2) the Documentation or
 * some other similar material which is provided with the Software (if
 * any).
 *
 * Copyright 1999-2004 University of Chicago and The University of
 * Southern California. All rights reserved.
 */
package org.griphyn.vdl.dbschema;

import java.sql.*;
import java.util.List;
import java.util.ArrayList;
import java.util.Properties;
import java.io.*;
import java.lang.reflect.*;

import org.xmldb.api.base.*;
import org.xmldb.api.modules.*;
import org.xmldb.api.*;
import javax.xml.transform.OutputKeys;
import javax.xml.parsers.DocumentBuilder; 
import javax.xml.parsers.DocumentBuilderFactory; 
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.DOMException; 
import org.xml.sax.SAXException; 
import org.xml.sax.SAXParseException; 
import org.xml.sax.InputSource;

import org.griphyn.vdl.util.ChimeraProperties;
import org.griphyn.vdl.classes.*;
import org.griphyn.vdl.util.Logging;
import org.griphyn.vdl.parser.*;
import org.griphyn.vdl.router.Cache;
import org.griphyn.vdl.annotation.*;
import org.griphyn.common.util.Separator;
import org.xml.sax.InputSource;

/**
 * This class provides basic functionalities to interact with the
 * backend database, such as insertion, deletion, and search of
 * entities in the VDC.
 *
 * @author Jens-S. Vckler
 * @author Yong Zhao
 * @version $Revision: 50 $ 
 */
public class NXDSchema extends DatabaseSchema implements XDC
{
  /**
   * An instance of the VDLx XML parser.
   */
  private org.griphyn.vdl.parser.VDLxParser m_parser;

  private DocumentBuilderFactory m_factory;

  private DocumentBuilder m_builder;

  /**
   * reference to collection '/db/vdc';
   */
  protected Collection m_db;

  protected Collection m_vdc;

  protected Collection m_meta;
  
  protected CollectionManagementService m_dbColService; 

  protected CollectionManagementService m_vdcColService; 

  protected XPathQueryService m_dbQrySvc;

  protected XPathQueryService m_vdcQrySvc;

  protected XPathQueryService m_metaQrySvc;

  protected XUpdateQueryService m_xupdQrySvc;

  /**
   * A cache for definitions to avoid reloading from the database.
   */
  protected Cache m_cache;  

  /**
   * Instantiates an XML parser for VDLx on demand. Since XML parsing
   * and parser instantiation is an expensive business, the reader will
   * only be generated on demand.
   *
   * @return a valid VDLx parser instance. 
   */
  private org.griphyn.vdl.parser.VDLxParser parserInstance()
  {
    if ( this.m_parser == null ) {
      // obtain the schema location URL from the schema properties: 
      // url is a list of strings representing schema locations. The
      // content exists in pairs, one of the namespace URI, one of the
      // location URL.
      String url = null;
      try {  
        ChimeraProperties props = ChimeraProperties.instance();
        url = 
    m_dbschemaprops.getProperty( "xml.url", props.getVDLSchemaLocation() );
      } catch (IOException e) {
  Logging.instance().log("nxd", 0, "ignored " + e);  
      }
      this.m_parser = new org.griphyn.vdl.parser.VDLxParser(url);
    }

    // done
    return this.m_parser;
  }

  /**
   * Default constructor for the NXD schema.
   */
  public NXDSchema(String dbDriver) 
    throws ClassNotFoundException, 
     NoSuchMethodException, InstantiationException, 
     IllegalAccessException, InvocationTargetException,
     SQLException, IOException,ParserConfigurationException
  {
    // load the driver from the properties
    super(); // call minimalistic c'tor, no driver loading!
    ChimeraProperties props = ChimeraProperties.instance();

    m_dbschemaprops =
        props.getDatabaseSchemaProperties( PROPERTY_PREFIX );

    m_cache = null;
    m_parser = null;

    // extract those properties specific to the database driver.
    // use default settings.
    String driverPrefix = null;
    String driverName = props.getDatabaseDriverName(driverPrefix);
    Properties driverprops = props.getDatabaseDriverProperties(driverPrefix);
    String url = props.getDatabaseURL(driverPrefix);
    String user = driverprops.getProperty("user", "guest");
    String passwd = driverprops.getProperty("password", "guest");

    try {
  m_factory = DocumentBuilderFactory.newInstance();
  m_builder = m_factory.newDocumentBuilder();


  Class cl = Class.forName(driverName);
  Database database = (Database) cl.newInstance();
  DatabaseManager.registerDatabase(database);

  // get the collection
  m_db = DatabaseManager.getCollection(url + "/db", user, passwd);
  m_dbColService = (CollectionManagementService)
      m_db.getService("CollectionManagementService", "1.0");
  
  m_vdc = m_db.getChildCollection("vdc");

  if(m_vdc == null) {
      // collection does not exist, create
      m_vdc = m_dbColService.createCollection("vdc");
  }
  m_vdc.setProperty(OutputKeys.INDENT, "no");
  
  m_meta = m_db.getChildCollection("metadata");

  if(m_meta == null) {
      // collection does not exist, create
      m_meta = m_dbColService.createCollection("metadata");
  }
  m_meta.setProperty(OutputKeys.INDENT, "no");
  
  m_vdcColService = (CollectionManagementService)
      m_vdc.getService("CollectionManagementService", "1.0");

        m_dbQrySvc = (XPathQueryService) m_db.getService("XPathQueryService", "1.0");

        m_vdcQrySvc = (XPathQueryService) m_vdc.getService("XPathQueryService", "1.0");

        m_metaQrySvc = (XPathQueryService) m_meta.getService("XPathQueryService", "1.0");

        m_dbQrySvc.setProperty("indent", "no");

        m_vdcQrySvc.setProperty("indent", "no");

        m_metaQrySvc.setProperty("indent", "no");

  XUpdateQueryService m_xupdQrySvc = (XUpdateQueryService) m_meta.getService("XUpdateQueryService", "1.0");
  
    } catch (XMLDBException e) {
  throw new SQLException (e.getMessage());
    } 
  }

    private String getDefinitionId(Definition def) {
  String prefix = (def.getType() == Definition.TRANSFORMATION)?"TR_":"DV_";
  String version = def.getVersion();
  String suffix = "";
  if (version != null)
      suffix = "_" + version;
  return prefix + def.getName() + suffix;
    }

    private String getDefinitionId(String name,
           String version,
           int type) {
  String prefix = (type == Definition.TRANSFORMATION)?"TR_":"DV_";
  String suffix = "";
  if (version != null)
      suffix = "_" + version;
  return prefix + name + suffix;
    }

  //
  // lower level methods, working directly on specific definitions
  //

  /**
   * Loads a single Definition from the backend database into an Java object.
   * This method does not allow wildcarding!
   *
   * @param namespace   namespace, null will be converted into empty string
   * @param name        name, null will be converted into empty string
   * @param version     version, null will be converted into empty string
   * @param type     type of the definition (TR or DV), must not be -1.
   * @return the Definition as specified, or null if not found.
   *
   * @see org.griphyn.vdl.classes.Definition#TRANSFORMATION
   * @see org.griphyn.vdl.classes.Definition#DERIVATION
   * @see #saveDefinition( Definition, boolean )
   */
  public Definition 
    loadDefinition( String namespace,
        String name,
        String version,
        int type )
    throws SQLException
  {
    Definition result = null;
    Logging.instance().log("xaction", 1, "START load definition" );

    try {
  Collection col;
  if (namespace != null) 
      col = m_vdc.getChildCollection(namespace);
  else 
      col = m_vdc;
  String id = getDefinitionId(name, version, type);
  //Logging.instance().log( "nxd", 0, "Definition id " + id );
  XMLResource res = (XMLResource)col.getResource(id);
  if(res != null) {
      MyCallbackHandler cb = new MyCallbackHandler();
      
      parserInstance().parse( new org.xml.sax.InputSource(new StringReader((String)res.getContent())), cb );
      result = cb.getDefinition();

  } else {
      Logging.instance().log( "nxd", 0, "Definition not found" );
  }
    } catch (Exception e) {
  throw new SQLException(e.getMessage());
    }
    Logging.instance().log("xaction", 1, "FINAL load definition" );
    return result;
  }

  /**
   * Saves a Definition, that is either a Transformation or Derivation,
   * into the backend database. This method, of course, does not allow
   * wildcarding. The definition has to be completely specified and
   * valid.
   *
   * @param definition is the new Definition to store.
   * @param overwrite true, if existing defitions will be overwritten by
   * new ones with the same primary (or secondary) key (-set), or false,
   * if a new definition will be rejected on key matches.
   *
   * @return true, if the backend database was changed, or
   *         false, if the definition was not accepted into the backend.
   *
   * @see org.griphyn.vdl.classes.Definition
   * @see org.griphyn.vdl.classes.Transformation
   * @see org.griphyn.vdl.classes.Derivation
   * @see #loadDefinition( String, String, String, int )
   */
  public boolean 
    saveDefinition( Definition definition, 
        boolean overwrite )
    throws SQLException
  {
      Logging.instance().log( "nxd", 2, "START save definition");

    try {
  String namespace = definition.getNamespace();
  Collection col;
  if (namespace != null)
      col = m_vdc.getChildCollection(namespace);
  else
      col = m_vdc;
  String id = getDefinitionId(definition);

  if (col == null) {
    // collection does not exist, create
    col = m_vdcColService.createCollection(namespace);
        } else if (!overwrite) {
    if (col.getResource(id) != null){
      Logging.instance().log( "app", 0, definition.shortID() +
            " already exists, ignoring" );
      return false;
    }
  }

        // create new XMLResource; an id will be assigned to the new resource
        XMLResource document = (XMLResource)col.createResource(id, "XMLResource");
        document.setContent(definition.toXML("", null));
        col.storeResource(document);

  // add to cache
  //if ( m_cache != null ) m_cache.set( new Long(id), definition );

    } catch (Exception e) {
  throw new SQLException(e.getMessage());
    }
    // done
    Logging.instance().log( "nxd", 2, "FINAL save definition");
    return true;
  }

  /**
   * Search the database for the existence of a definition.
   *
   * @param definition the definition object to search for
   * @return true, if the definition exists, false if not found
   */
  public boolean containsDefinition( Definition definition )
    throws SQLException 
  {
    boolean result = false;
    try {
  String namespace = definition.getNamespace();
  Collection col;
  if (namespace != null)
      col = m_vdc.getChildCollection(namespace);
  else
      col = m_vdc;
  String id = getDefinitionId(definition);

  if(col != null) {
      if (col.getResource(id) != null){
    result = true;
      }
  }
    } catch ( Exception e ) {
  throw new SQLException(e.getMessage());
    }
    return result;
  }

  /**
   * Delete a specific Definition objects from the database. No wildcard
   * matching will be done. "Fake" definitions are permissable, meaning
   * it just has the secondary key triple.
   *
   * @param definition is the definition specification to delete
   * @return true is something was deleted, false if non existent.
   *
   * @see org.griphyn.vdl.classes.Definition#TRANSFORMATION
   * @see org.griphyn.vdl.classes.Definition#DERIVATION 
   */
  public boolean deleteDefinition( Definition definition )
    throws SQLException 
  {
    boolean result = false;

    Logging.instance().log("xaction", 1, "START delete definition" );

    try {
  String namespace = definition.getNamespace();
  Collection col;
  if (namespace != null)
      col = m_vdc.getChildCollection(namespace);
  else
      col = m_vdc;
  String id = getDefinitionId(definition);

  if(col != null) {
      XMLResource res = (XMLResource)col.getResource(id);
      if (res != null){
    col.removeResource(res);
    result = true;
      }
  }
    } catch ( Exception e ) {
      // ignore
    }

    Logging.instance().log("xaction", 1, "FINAL delete definition" );
    return result;
  }

  /**
   * Delete Definition objects from the database. This method allows for
   * wildcards in the usual fashion. Use null for strings as wildcards,
   * and -1 for the type wildcard.
   *
   * @param namespace   namespace, null to match any namespace
   * @param name        name, null to match any name
   * @param version     version, null to match any version
   * @param type        definition type (TR or DV)
   * @return            a list containing all Definitions that were deleted
   *
   * @see org.griphyn.vdl.classes.Definition#TRANSFORMATION
   * @see org.griphyn.vdl.classes.Definition#DERIVATION 
   */
  public java.util.List deleteDefinition( String namespace,
            String name,
            String version,
            int type )
    throws SQLException 
  {
    Logging.instance().log("xaction", 1, "START delete definitions" );

    java.util.List result = searchDefinition(namespace, name, version, type);
    for (int i=0; i < result.size(); i++)
  deleteDefinition((Definition)result.get(i));

    Logging.instance().log("xaction", 1, "FINAL delete definitions" );
    return result;
  }

  /**
   * Search the database for definitions by ns::name:version triple
   * and by type (either Transformation or Derivation). This version
   * of the search allows for jokers expressed as null value
   *
   * @param namespace   namespace, null to match any namespace
   * @param name        name, null to match any name
   * @param version     version, null to match any version
   * @param type        type of definition (TR/DV, or both)
   * @return            a list of definitions
   *
   * @see org.griphyn.vdl.classes.Definition#TRANSFORMATION
   * @see org.griphyn.vdl.classes.Definition#DERIVATION
   */
  public java.util.List searchDefinition( String namespace,
            String name,
            String version,
            int type )
    throws SQLException 
  {
    String xquery = ""; //"declare namespace vdl='http://www.griphyn.org/chimera/VDL';"

    String triple = "";
    if (namespace != null)
  triple += "[@namespace='" + namespace + "']";

    if (name != null)
  triple += "[@name='" + name + "']";

    if (version != null)
  triple += "[@version='" + version + "']";

    if (type != -1) {
  if (type == Definition.TRANSFORMATION)
      xquery = "//transformation" + triple;
  else
      xquery += "//derivation" + triple;
    } else
  xquery = "//derivation" + triple + "|//transformation" + triple;

    return searchDefinition(xquery);
  }

  /**
   * Searches the database for all derivations that satisfies a certain query.
   *
   * @param xquery    the query statement
   * @return  a list of definitions
   */
  public java.util.List searchDefinition( String xquery )
    throws SQLException 
  {
    if ( xquery == null )
      throw new NullPointerException("You must specify a query!");

    java.util.List result = new ArrayList();

    try {
  Logging.instance().log("xaction", 1, "query: " + xquery );

  ResourceSet rs = m_dbQrySvc.query(xquery);
  ResourceIterator i = rs.getIterator();
  while(i.hasMoreResources()) {
      Resource res = i.nextResource();
      
      MyCallbackHandler cb = new MyCallbackHandler();
      
      parserInstance().parse( new org.xml.sax.InputSource(new StringReader((String)res.getContent())), cb );
      result.add(cb.getDefinition());
  }

    } catch ( Exception e ) {
  throw new SQLException(e.getMessage());
    }

    return result;
  }

  /**
   * Searches the database for elements that satisfies a certain query.
   *
   * @param xquery    the query statement
   * @return  a list of string
   */
  public java.util.List searchElements( String xquery )
    throws SQLException 
  {
    if ( xquery == null )
      throw new NullPointerException("You must specify a query!");

    java.util.List result = new ArrayList();

    try {
  Logging.instance().log("nxd", 1, "query: " + xquery );

  ResourceSet rs = m_dbQrySvc.query(xquery);
  ResourceIterator i = rs.getIterator();
  while(i.hasMoreResources()) {
      Resource res = i.nextResource();
      result.add((String)res.getContent());
  }
    } catch ( Exception e ) {
  throw new SQLException(e.getMessage());
    }
    return result;
  }

  /**
   * Searches the database for annotations that satisfies a certain query.
   *
   * @param xquery    the query statement
   * @return true if found, false otherwise 
   */
  public XMLResource findAnnotation( String xquery )
    throws SQLException 
  {
    if ( xquery == null )
  return null;

    try {
  Logging.instance().log("nxd", 1, "query: " + xquery );

  ResourceSet rs = m_metaQrySvc.query(xquery);
  ResourceIterator i = rs.getIterator();
  if (i.hasMoreResources()) {
      XMLResource res = (XMLResource)i.nextResource();
      return res;
  } else 
      return null;
    } catch ( Exception e ) {
  throw new SQLException(e.getMessage());
    }
  }

  public java.util.List searchFilename( String lfn, int link )
    throws SQLException 
  {
    if ( lfn == null )
      throw new NullPointerException("You must query for a filename");

    String linkQuery = "";
    String type = LFN.toString(link);
    if (type != null)
  linkQuery = "[@link = '" + type + "']";

    String xquery = 
  "//derivation[.//lfn[@file = '" + lfn + "']" + linkQuery + "]";
    java.util.List result = searchDefinition(xquery);

    Logging.instance().log("xaction", 1, "FINAL select LFNs" );
    return result;
  }


  /**
   * Delete one or more definitions from the backend database. The key
   * triple parameters may be wildcards. Wildcards are expressed as
   * <code>null</code> value, or have regular expression.
   *
   * @param namespace   namespace
   * @param name        name
   * @param version     version
   * @param type        definition type (TR or DV)
   * @return            a list of definitions that were deleted.
   *
   * @see org.griphyn.vdl.classes.Definition#TRANSFORMATION
   * @see org.griphyn.vdl.classes.Definition#DERIVATION 
   */
  public java.util.List 
    deleteDefinitionEx( String namespace,
          String name,
          String version,
          int type )
    throws SQLException {
    Logging.instance().log("xaction", 1, "START delete definitions ex" );

    java.util.List result = searchDefinitionEx(namespace, name, version, type);
    for (int i=0; i < result.size(); i++)
  deleteDefinition((Definition)result.get(i));

    Logging.instance().log("xaction", 1, "FINAL delete definitions ex" );
    return result;
  }

  /**
   * Searches the database for definitions by ns::name:version triple
   * and by type (either Transformation or Derivation). This version of
   * the search allows for jokers expressed as null value
   *
   * @param namespace   namespace, null to match any namespace
   * @param name        name, null to match any name
   * @param version     version, null to match any version
   * @param type        type of definition, see below, or -1 as wildcard
   * @return            a list of Definition items, which may be empty
   *
   * @see org.griphyn.vdl.classes.Definition#TRANSFORMATION
   * @see org.griphyn.vdl.classes.Definition#DERIVATION
   * @see #loadDefinition( String, String, String, int )
   */
  public java.util.List 
    searchDefinitionEx( String namespace,
          String name,
          String version,
          int type )
    throws SQLException {
    String xquery = ""; 

    String triple = "";
    if (namespace != null)
  triple += "[matches(@namespace, '" + namespace + "')]";

    if (name != null)
  triple += "[matches(@name, '" + name + "')]";

    if (version != null)
  triple += "[matches(@version, '" + version + "')]";

    if (type != -1) {
  if (type == Definition.TRANSFORMATION)
      xquery = "//transformation" + triple;
  else
      xquery += "//derivation" + triple;
    } else
  xquery = "//derivation" + triple + "|//transformation" + triple;
    return searchDefinition(xquery);
  }

  /**
   * Searches the database for all LFNs that match a certain pattern.
   * The linkage is an additional constraint. This method allows
   * regular expression
   *
   * @param lfn    the LFN name
   * @param link   the linkage type of the LFN
   * @return       a list of filenames that match the criterion.
   *
   * @see org.griphyn.vdl.classes.LFN#NONE
   * @see org.griphyn.vdl.classes.LFN#INPUT
   * @see org.griphyn.vdl.classes.LFN#OUTPUT
   * @see org.griphyn.vdl.classes.LFN#INOUT
   */
  public java.util.List 
    searchLFN( String lfn, int link )
    throws SQLException {
    if ( lfn == null )
      throw new NullPointerException("You must query for a filename");

    String linkQuery = "";
    String type = LFN.toString(link);
    if (type != null)
  linkQuery = "[@link = '" + type + "')]";

    String xquery = 
  //  "//lfn[matches(@file, '" + lfn + "')]" + linkQuery + "/@file";
  "//lfn" + linkQuery + "/@file[matches(.,  '" + lfn + "')]";
    java.util.List result = searchElements(xquery);

    Logging.instance().log("xaction", 1, "FINAL select LFNs" );
    return result;
  }

  /**
   * Searches the database for a list of namespaces of the definitions
   * Sorted in ascending order.
   *
   * @param type   type of definition, see below, or -1 for both
   * @return       a list of namespaces 
   *
   * @see org.griphyn.vdl.classes.Definition#TRANSFORMATION
   * @see org.griphyn.vdl.classes.Definition#DERIVATION
   */
  public java.util.List 
    getNamespaceList( int type )
    throws SQLException {

    String xquery = "";
    if (type == Definition.TRANSFORMATION)
  xquery = "for $n in distinct-values(//transformation/@namespace) order by $n return $n"; 
    else if (type == Definition.DERIVATION)
  xquery = "for $n in distinct-values(//derivation/@namespace) order by $n return $n";
    else
       xquery = "for $n in distinct-values(//derivation/@namespace|//transformation/@namespace) order by $n return $n";

    java.util.List result = searchElements(xquery);

    Logging.instance().log("xaction", 1, "FINAL select LFNs" );
    return result;
  }

  /**
   * Searches the database for a list of fully-qualified names of 
   * the definitions sorted in ascending order.
   *
   * @param type   type of definition, see below, or -1 for both.
   * @return       a list of FQDNs 
   *
   * @see org.griphyn.vdl.classes.Definition#TRANSFORMATION
   * @see org.griphyn.vdl.classes.Definition#DERIVATION
   */
  public java.util.List 
    getFQDNList( int type )
    throws SQLException {
    String xquery = "";

    if (type == Definition.TRANSFORMATION)
  xquery = "for $d in //transformation order by $d/@namespace empty least, $d/@name, $d/@version return string-join((string-join(($d/@namespace, $d/@name), '::'), $d/@version), ':')";
    else if (type == Definition.DERIVATION)
  xquery = "for $d in //derivation order by $d/@namespace empty least, $d/@name, $d/@version return string-join((string-join(($d/@namespace, $d/@name), '::'), $d/@version), ':')";
    else
  xquery = "for $d in (//transformation|//derivation) order by $d/@namespace empty least, $d/@name, $d/@version return string-join((string-join(($d/@namespace, $d/@name), '::'), $d/@version), ':')";

    java.util.List result = searchElements(xquery);

    Logging.instance().log("xaction", 1, "FINAL select LFNs" );
    return result;
  }

  /**
   * Deletes an annotation with the specified key.
   *
   * @param primary is the primary object specifier for the class. 
   * According to the type, this is either the FQDI, or the filename.
   * @param secondary is a helper argument for annotations to calls
   * and formal arguments, and should be null for all other classes.
   * For calls, the argument must be packed into {@link java.lang.Integer}.
   * @param kind defines the kind/class of object to annotate.
   * @param key is the annotation key.
   * @return true, if the database was modified, false otherwise.
   * @exception SQLException, if something went wrong during database
   * access.
   */
  public boolean deleteAnnotation( String primary, Object secondary,
           int kind, String key )
    throws SQLException, IllegalArgumentException
  {
    String subject = "";
    String select = null;

    switch ( kind ) {
    case CLASS_TRANSFORMATION:
      subject = "tr";
      break;
    case CLASS_DERIVATION:
      subject = "dv";
      break;
    case CLASS_CALL:
      // may throw ClassCastException
      subject = "tr";  
      select = "call[" +  ((Integer) secondary).intValue() + "]";
      break;
    case CLASS_DECLARE:
      subject = "tr";
      // may throw ClassCastException
      //select = "declare[@name='" + (String)secondary + "']";
      select = (String)secondary;
      break;
    case CLASS_FILENAME:
      subject = "lfn";
      break;
    default:
      throw new IllegalArgumentException( "The class kind=" + kind + " cannot be annotated" );
    }

    try {
    XMLResource res = null;
    String xquery = "/annotation/metadata[@subject=\"" + subject + "\"][@name=\"" +
  primary + "\"]";
    if (select == null) {
  if (kind != CLASS_FILENAME) {
      xquery += "[empty(@select)]";
  }
    } else {
  xquery += "[@select=\"" + select + "\"]";
    }

    xquery +=  "/attribute[@name=\"" + key + "\"]";

    if ((res = findAnnotation(xquery)) != null) {
  String id = res.getDocumentId();

  // get the document
  XMLResource document = (XMLResource)m_meta.getResource(id);
  m_meta.removeResource(document);
  return true;
    }
    return false;
    } catch (XMLDBException e) {
      throw new SQLException(e.getMessage());
    }
  }

  /**
   * Deletes a specific key in an annotated transformation.
   *
   * @param fqdi is the FQDI of the transformation
   * @param key is the key to search for
   * @return true, if the database was modified, false otherwise.
   * @see org.griphyn.vdl.classes.Transformation
   */
  public boolean deleteAnnotationTransformation( String fqdi, String key )
    throws SQLException, IllegalArgumentException
  {
    return deleteAnnotation(fqdi, null, CLASS_TRANSFORMATION, key);
  }

  /**
   * Deletes a specific key in an annotated derivation.
   *
   * @param fqdi is the FQDI of the derivation
   * @param key is the key to search for
   * @return true, if the database was modified, false otherwise.
   * @see org.griphyn.vdl.classes.Derivation
   */
  public boolean deleteAnnotationDerivation( String fqdi, String key )
    throws SQLException, IllegalArgumentException
  {
    return deleteAnnotation(fqdi, null, CLASS_DERIVATION, key);
  }   

  /**
   * Deletes a specific key in an annotated formal argument.
   *
   * @param fqdi is the FQDI of the transformation
   * @param farg is the name of the formal argument
   * @param key is the key to search for
   * @return true, if the database was modified, false otherwise.
   * @see org.griphyn.vdl.classes.Declare
   */
  public boolean deleteAnnotationDeclare( String fqdi, String farg,
              String key )
    throws SQLException, IllegalArgumentException
  {
    return deleteAnnotation(fqdi, farg, CLASS_DECLARE, key);
  }

  /**
   * Deletes a specific key for a call statement.
   *
   * @param fqdi is the FQDI of the transformation
   * @param index is the number of the call to annotate.
   * @param key is the key to search for
   * @return true, if the database was modified, false otherwise.
   * @see org.griphyn.vdl.classes.Call
   */
  public boolean deleteAnnotationCall( String fqdi, int index, 
           String key )
    throws SQLException, IllegalArgumentException
  {
    return deleteAnnotation(fqdi, new Integer(index), CLASS_CALL, key);
  }

  /**
   * Deletes a specific key in an annotated filename.
   *
   * @param filename is the name of the file that was annotated.
   * @param key is the key to search for
   * @return true, if the database was modified, false otherwise.
   * @see org.griphyn.vdl.classes.LFN
   */
  public boolean deleteAnnotationFilename( String filename, String key )
    throws SQLException, IllegalArgumentException
  {
    return deleteAnnotation(filename, null, CLASS_FILENAME, key);
  }

  /**
   * Annotates a transformation with a tuple.
   *
   * @param fqdi is the FQDI to annotate
   * @param annotation is the value to place
   * @param overwrite is a predicate on replace or maintain.
   * @return the insertion id, or -1, if the database was untouched
   * @see org.griphyn.vdl.classes.Transformation
   */
  public long saveAnnotationTransformation( String fqdi, 
              Tuple annotation, 
              boolean overwrite )
    throws SQLException, IllegalArgumentException
  {
    /* 
    try {
     String key = annotation.getKey();
     String type = annotation.getTypeString();
     Object value = annotation.getValue();

     Logging.instance().log( "nxd", 2, "INSERT INTO anno_tr" );

     String id = null;
     XMLResource res = null;

     String xupdate = 
   "<xu:modifications version=\"1.0\" " +
   "xmlns:xu=\"http://www.xmldb.org/xupdate\">";
     String xquery = "//annotation/metadata[@subject='tr'][@name='" +
    fqdi + "']";
     if ((res = findAnnotation(xquery)) != null) {
   //annotation for tr exists
   id = res.getDocumentId();
   String xquery_attr = xquery + "/attribute[@name='" + key + "']/text()";
   if (findAnnotation(xquery_attr)!=null) {
       //attribute already exists
       Logging.instance().log( "nxd", 2, "Attribute already exists." );

       if (!overwrite) 
     return -1;
       xupdate += "<xu:update select=\"" + xquery + "\">" +
     value + "</xu:update>";
       //xupdate += "<xu:update select=\"" + xquery_attr + "/@type\">" + 
       //type + "</xu:update>";
   } else {
       //attribute does not exist
       Logging.instance().log( "nxd", 2, "Attribute does not exist." );

       xupdate += "<xu:append select=\"" + xquery + "\">" +
     "<xu:element name=\"attribute\">" +
     "<xu:attribute name=\"name\">" + key + "</xu:attribute>" +
     "<xu:attribute name=\"type\">" + type + "</xu:attribute>" +
     value + "</xu:element>" +
     "</xu:append>";
   }
   xupdate += "</xu:modifications>";
   System.out.println(xupdate);
   long l = m_xupdQrySvc.update(xupdate);
     } else {
   //create the annotation
   String anno = "<annotation><metadata subject=\"tr\" name=\"" + fqdi + "\">" +
       "<attribute name=\"" + key + "\" type=\"" + type + "\">" + value + "</attribute>" +
       "</metadata></annotation>";

   // create new XMLResource; an id will be assigned to the new resource
   XMLResource document = (XMLResource)m_meta.createResource(null, "XMLResource");
   document.setContent(anno);
   m_meta.storeResource(document);
     }
     return 0; 
    } catch (XMLDBException e) {
  throw new SQLException(e.getMessage());
    }
    */
    return saveAnnotation(fqdi, null, CLASS_TRANSFORMATION, annotation, overwrite);
  }

  /**
   * Annotates a derivation with a tuple.
   *
   * @param fqdi is the FQDI to annotate
   * @param annotation is the value to place
   * @param overwrite is a predicate on replace or maintain.
   * @return the insertion id, or -1, if the database was untouched
   * @see org.griphyn.vdl.classes.Derivation
   */
  public long saveAnnotationDerivation( String fqdi, 
          Tuple annotation, 
          boolean overwrite )
    throws SQLException, IllegalArgumentException
  {
    return saveAnnotation(fqdi, null, CLASS_DERIVATION, annotation, overwrite);
  }

  /**
   * Annotates a transformation argument with a tuple.
   *
   * @param fqdi is the FQDI to annotate
   * @param formalname is the name of the formal argument to annotoate.
   * @param annotation is the value to place
   * @param overwrite is a predicate on replace or maintain.
   * @return the insertion id, or -1, if the database was untouched
   * @see org.griphyn.vdl.classes.Declare
   */
  public long saveAnnotationDeclare( String fqdi, 
             String formalname,
             Tuple annotation, 
             boolean overwrite )
    throws SQLException, IllegalArgumentException
  {
    return saveAnnotation(fqdi, formalname, CLASS_DECLARE, annotation, overwrite);
  }

  /**
   * Annotates a transformation call with a tuple.
   *
   * @param fqdi is the FQDI to annotate
   * @param index is the number of the call to annotate.
   * @param annotation is the value to place
   * @param overwrite is a predicate on replace or maintain.
   * @return the insertion id, or -1, if the database was untouched
   * @see org.griphyn.vdl.classes.Call
   */
  public long saveAnnotationCall( String fqdi, 
          int index,
          Tuple annotation, 
          boolean overwrite )
    throws SQLException, IllegalArgumentException
  {
    return saveAnnotation(fqdi, new Integer(index), CLASS_CALL, annotation, overwrite);
  }

  /**
   * Annotates a logical filename with a tuple.
   *
   * @param filename is the FQDI to annotate
   * @param annotation is the value to place
   * @param overwrite is a predicate on replace or maintain.
   * @return the insertion id, or -1, if the database was untouched
   * @see org.griphyn.vdl.classes.LFN
   */
  public long saveAnnotationFilename( String filename, 
              Tuple annotation, 
              boolean overwrite )
    throws SQLException, IllegalArgumentException
  {
    return saveAnnotation(filename, null, CLASS_FILENAME, annotation, overwrite);
  }

  /**
   * Annotates any of the annotatable classes with the specified tuple.
   * This is an interface method to the various class-specific methods.
   *
   * @param primary is the primary object specifier for the class. 
   * According to the type, this is either the FQDI, or the filename.
   * @param secondary is a helper argument for annotations to calls
   * and formal arguments, and should be null for all other classes.
   * For calls, the argument must be packed into {@link java.lang.Integer}.
   * @param kind defines the kind/class of object to annotate.
   * @param annotation is the value to place into the class.
   * @param overwrite is a predicate on replace or maintain.
   * @return the insertion id, or -1, if the database was untouched
   * @see #saveAnnotationTransformation( String, Tuple, boolean )
   * @see #saveAnnotationDerivation( String, Tuple, boolean )
   * @see #saveAnnotationCall( String, int, Tuple, boolean )
   * @see #saveAnnotationDeclare( String, String, Tuple, boolean )
   * @see #saveAnnotationFilename( String, Tuple, boolean )
   */
  public long saveAnnotation( String primary, Object secondary,
            int kind, Tuple annotation, boolean overwrite )
    throws SQLException, IllegalArgumentException
  {
    long result = -1;
    String subject = "";
    String select = null;
    String q_sec = null;
    String defn = "transformation";

    switch ( kind ) {
    case CLASS_TRANSFORMATION:
      subject = "tr";
      break;
    case CLASS_DERIVATION:
      subject = "dv";
      defn = "derivation";
      break;
    case CLASS_CALL:
      // may throw ClassCastException
      subject = "tr";  
      select = "call[" +  ((Integer) secondary).intValue() + "]";
      q_sec = select;
      break;
    case CLASS_DECLARE:
      subject = "tr";
      // may throw ClassCastException
      q_sec = "declare[@name='" + (String)secondary + "']";
      select = (String)secondary;
      break;
    case CLASS_FILENAME:
      subject = "lfn";
      break;
    default:
      throw new IllegalArgumentException( "The class kind=" + kind + " cannot be annotated" );
    }

    try {

      if (kind != CLASS_FILENAME) {
  String[] names = Separator.split(primary);
  String q_ns, q_name, q_ver;

  if (names[0] == null)
    q_ns = "[empty(@namespace)]";
  else
    q_ns = "[@namespace='" + names[0] + "']";

  if (names[1] == null)
    q_name = "[empty(@name)]";
  else
    q_name = "[@name='" + names[1] + "']";

  if (names[2] == null)
    q_ver = "[empty(@version)]";
  else
    q_ver = "[@version='" + names[2] + "']";

  //check if tr/dv is valid
  String xquery = "//" + defn + q_ns + q_name + q_ver;
  if (q_sec != null )
    xquery += "/" + q_sec;
  Logging.instance().log("nxd", 0, "query: " + xquery);
  ResourceSet rs = m_vdcQrySvc.query(xquery);
  ResourceIterator i = rs.getIterator();
  if (!i.hasMoreResources()) {
    Logging.instance().log("app", 0, "definition not found!");
    return -1;
  }
      }

      String key = annotation.getKey();
      String type = annotation.getTypeString();
      Object value = annotation.getValue();
    
      String id = null;
      XMLResource res = null;
      String xquery = "/annotation/metadata[@subject=\"" + subject + "\"][@name=\"" +
  primary + "\"]";
      if (select == null) {
  if (kind != CLASS_FILENAME) {
    xquery += "[empty(@select)]";
  }
      } else {
  xquery += "[@select=\"" + select + "\"]";
      }

      xquery +=  "/attribute[@name=\"" + key + "\"]";
      
      if ((res = findAnnotation(xquery)) != null) {
  if (!overwrite) {
    System.err.println("key " + key + " already defined!");
    return -1;
  }
  id = res.getDocumentId();
      }
      
      //create the annotation
      String anno = "<annotation xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\"><metadata subject=\"" + subject + "\" name=\"" + primary + "\"";
      if (select !=null)
  anno += " select=\"" + select + "\"";
      anno += ">" + "<attribute name=\"" + key + "\" xsi:type=\"xs:" + type + "\">" + value + "</attribute>" +
  "</metadata></annotation>";
  
      // create new XMLResource; an id will be assigned to the new resource
      XMLResource document = (XMLResource)m_meta.createResource(id, "XMLResource");
  
      document.setContent(anno);
      m_meta.storeResource(document);
      
      return 0;
    } catch (XMLDBException e) {
      throw new SQLException(e.getMessage());
    }
  }

  /**
   * Obtains the value to a specific key in an annotated transformation.
   *
   * @param fqdi is the FQDI of the transformation
   * @param key is the key to search for
   * @return the annotated value, or null if not found.
   * @see org.griphyn.vdl.classes.Transformation
   */
  public Tuple loadAnnotationTransformation( String fqdi, String key )
    throws SQLException, IllegalArgumentException
  {
      return loadAnnotation(fqdi, null, CLASS_TRANSFORMATION, key);
  }

  /**
   * Obtains the value to a specific key in an annotated derivation.
   *
   * @param fqdi is the FQDI of the derivation
   * @param key is the key to search for
   * @return the annotated value, or null if not found.
   * @see org.griphyn.vdl.classes.Derivation
   */
  public Tuple loadAnnotationDerivation( String fqdi, String key )
    throws SQLException, IllegalArgumentException
  {
      return loadAnnotation(fqdi, null, CLASS_DERIVATION, key);
  }

  /**
   * Obtains the value to a specific key in an annotated formal argument.
   *
   * @param fqdi is the FQDI of the transformation
   * @param farg is the name of the formal argument
   * @param key is the key to search for
   * @return the annotated value, or null if not found
   * @see org.griphyn.vdl.classes.Declare
   */
  public Tuple loadAnnotationDeclare( String fqdi, String farg,
              String key )
    throws SQLException, IllegalArgumentException
  {
      return loadAnnotation(fqdi, farg, CLASS_DECLARE, key);
  }

  /**
   * Obtains the value to a specific key for a call statement.
   *
   * @param fqdi is the FQDI of the transformation
   * @param index is the number of the call to annotate.
   * @param key is the key to search for
   * @return the annotated value, or null if not found
   * @see org.griphyn.vdl.classes.Call
   */
  public Tuple loadAnnotationCall( String fqdi, int index, 
           String key )
    throws SQLException, IllegalArgumentException
  {
      return loadAnnotation(fqdi, new Integer(index), CLASS_CALL, key);
  }

  /**
   * Obtains the value to a specific key in an annotated filename.
   *
   * @param filename is the name of the file that was annotated.
   * @param key is the key to search for
   * @return the annotated value, or null if not found.
   * @see org.griphyn.vdl.classes.LFN
   */
  public Tuple loadAnnotationFilename( String filename, String key )
    throws SQLException, IllegalArgumentException
  {
      return loadAnnotation(filename, null, CLASS_FILENAME, key);
  }

  /**
   * Retrieves a specific annotation from an annotatable classes with
   * the specified tuple. This is an interface method to the various
   * class-specific methods.
   *
   * @param primary is the primary object specifier for the class. 
   * According to the type, this is either the FQDI, or the filename.
   * @param secondary is a helper argument for annotations to calls
   * and formal arguments, and should be null for all other classes.
   * For calls, the argument must be packed into {@link java.lang.Integer}.
   * @param kind defines the kind/class of object to annotate.
   * @param key is the key to look for.
   * @return null if not found, otherwise the annotation tuple.
   * @see #loadAnnotationTransformation( String, String )
   * @see #loadAnnotationDerivation( String, String )
   * @see #loadAnnotationCall( String, int, String )
   * @see #loadAnnotationDeclare( String, String, String )
   * @see #loadAnnotationFilename( String, String )
   */
  public Tuple loadAnnotation( String primary, Object secondary,
             int kind, String key )
    throws SQLException, IllegalArgumentException
  {
    Tuple result = null;
    String subject = "";
    String select = null;

    switch ( kind ) {
    case CLASS_TRANSFORMATION:
      subject = "tr";
      break;
    case CLASS_DERIVATION:
      subject = "dv";
      break;
    case CLASS_CALL:
      // may throw ClassCastException
      subject = "tr";  
      select = "call[" +  ((Integer) secondary).intValue() + "]";
      break;
    case CLASS_DECLARE:
      subject = "tr";
      // may throw ClassCastException
      //select = "declare[@name='" + (String)secondary + "']";
      select = (String)secondary;
      break;
    case CLASS_FILENAME:
      subject = "lfn";
      break;
    default:
      throw new IllegalArgumentException( "The class kind=" + kind + " cannot be annotated" );
    }

    try {
    String id = null;
    String xquery = "/annotation/metadata[@subject=\"" + subject + "\"][@name=\"" +
  primary + "\"]";
    if (select == null) {
  if (kind != CLASS_FILENAME) {
      xquery += "[empty(@select)]";
  }
    } else {
  xquery += "[@select=\"" + select + "\"]";
    }

    xquery +=  "/attribute[@name=\"" + key + "\"]";

    XMLResource res = null;
    if ((res = findAnnotation(xquery)) != null) {
  result = loadAnnotationResource(res);
    }
    return result;
    } catch (Exception e) {
  throw new SQLException(e.getMessage());
    }
  }

  /**
   * get the annotation from a XML resource
   */
  protected Tuple loadAnnotationResource(XMLResource res)  
    throws SQLException
  {
      Tuple result = null;

      if (res == null) 
    return result;

      Element elem;
      try {
    elem = (Element)res.getContentAsDOM();
      } catch (Exception e) {
    throw new SQLException( e.getMessage());
      }
      if (elem != null) {
    String key = elem.getAttribute("name");
    String type = elem.getAttributeNS("http://www.w3.org/2001/XMLSchema-instance","type");
    String value = elem.getFirstChild().getNodeValue();
    if (key == null || type == null || value == null)
        return result;
    if (type.equals("xs:string")) {
        result = new TupleString(key, null);
        result.setValue(value);
        return result;
    }
    if (type.equals("xs:float")){
        result = new TupleFloat(key, 0);
        result.setValue(value);
        return result;
    }
    if (type.equals("xs:int")){
        result = new TupleInteger(key, 0);
        result.setValue(value);
        return result;
    }
    if (type.equals("xs:boolean")) {
        result = new TupleBoolean(key, false);
        result.setValue(value);
        return result;
    }
    if (type.equals("xs:date")) {
        result = new TupleDate(key, null);
        result.setValue(value);
        return result;
    }
      }
      return result;
  }

  /**
   * Lists all annotations for a transformation.
   *
   * @param fqdi is the FQDI of the transformation
   * @return a list of tuples, which may be empty.
   * @see org.griphyn.vdl.classes.Transformation
   */
  public java.util.List loadAnnotationTransformation( String fqdi )
    throws SQLException, IllegalArgumentException
  {
      return loadAnnotation(fqdi, null, CLASS_TRANSFORMATION);
  }

  /**
   * Lists all annotations for a derivation.
   *
   * @param fqdi is the FQDI of the derivation
   * @return a list of tuples, which may be empty.
   * @see org.griphyn.vdl.classes.Derivation
   */
  public java.util.List loadAnnotationDerivation( String fqdi )
    throws SQLException, IllegalArgumentException
  {
      return loadAnnotation(fqdi, null, CLASS_DERIVATION);
  }


  /**
   * Lists all annotations for a formal argument.
   *
   * @param fqdi is the FQDI of the transformation
   * @param farg is the name of the formal argument
   * @return a list of tuples, which may be empty.
   * @see org.griphyn.vdl.classes.Declare
   */
  public java.util.List loadAnnotationDeclare( String fqdi, String farg )
    throws SQLException, IllegalArgumentException
  {
      return loadAnnotation(fqdi, farg, CLASS_DECLARE);
  }

  /**
   * Lists all annotations for a call statement.
   *
   * @param fqdi is the FQDI of the transformation
   * @param index is the number of the call to annotate.
   * @return a list of tuples, which may be empty.
   * @see org.griphyn.vdl.classes.Call
   */
  public java.util.List loadAnnotationCall( String fqdi, int index )
    throws SQLException, IllegalArgumentException
  {
      return loadAnnotation(fqdi, new Integer(index), CLASS_CALL);
  }

  /**
   * Lists all annotations for a logical filename.
   *
   * @param filename is the logical filename.
   * @return a list of tuples, which may be empty.
   * @see org.griphyn.vdl.classes.LFN
   */
  public java.util.List loadAnnotationFilename( String filename )
    throws SQLException, IllegalArgumentException
  {
      return loadAnnotation(filename, null, CLASS_FILENAME);
  }

  /**
   * Retrieves all annotations from an annotatable classes with
   * the specified tuple. This is an interface method to the various
   * class-specific methods.
   *
   * @param primary is the primary object specifier for the class. 
   * According to the type, this is either the FQDI, or the filename.
   * @param secondary is a helper argument for annotations to calls
   * and formal arguments, and should be null for all other classes.
   * For calls, the argument must be packed into {@link java.lang.Integer}.
   * @param kind defines the kind/class of object to annotate.
   *
   * @return null if not found, otherwise the annotation tuple.
   * @see #loadAnnotationTransformation( String )
   * @see #loadAnnotationDerivation( String )
   * @see #loadAnnotationCall( String, int )
   * @see #loadAnnotationDeclare( String, String )
   * @see #loadAnnotationFilename( String )
   */
  public java.util.List loadAnnotation( String primary, 
          Object secondary,
          int kind )
    throws SQLException, IllegalArgumentException
  {
    java.util.List result = new java.util.ArrayList();
    String subject = "";
    String select = null;

    switch ( kind ) {
    case CLASS_TRANSFORMATION:
      subject = "tr";
      break;
    case CLASS_DERIVATION:
      subject = "dv";
      break;
    case CLASS_CALL:
      // may throw ClassCastException
      subject = "tr";  
      select = "call[" +  ((Integer) secondary).intValue() + "]";
      break;
    case CLASS_DECLARE:
      subject = "tr";
      // may throw ClassCastException
      //select = "declare[@name='" + (String)secondary + "']";
      select = (String)secondary;
      break;
    case CLASS_FILENAME:
      subject = "lfn";
      break;
    default:
      throw new IllegalArgumentException( "The class kind=" + kind + " cannot be annotated" );
    }

    try {
    String id = null;
    String xquery = "/annotation/metadata[@subject=\"" + subject + "\"][@name=\"" +
  primary + "\"]";
    if (select == null) {
  if (kind != CLASS_FILENAME) {
      xquery += "[empty(@select)]";
  }
    } else {
  xquery += "[@select=\"" + select + "\"]";
    }

    xquery +=  "/attribute";
    Logging.instance().log("nxd", 1, "query: " + xquery );

    ResourceSet rs = m_metaQrySvc.query(xquery);
    ResourceIterator i = rs.getIterator();
    while (i.hasMoreResources()) {
  XMLResource res = (XMLResource)i.nextResource();
  Tuple tuple = loadAnnotationResource(res);
  if (tuple != null) {
      result.add(tuple);
  }
    }
    return result;
    } catch (Exception e) {
  throw new SQLException(e.getMessage());
    }
  }


  /**
   * Search for LFNs or Definitions that has certain annotations
   *
   * @param kind defines the kind/class of object annotated.
   * @param arg is used only for TR ARG and TR CALL. For the former
   * it is the name of the argument (String), for the latter the position of 
   * the call (Integer).
   * @param tree stores the query tree to query the annotation
   * @return a list of LFNs if search for filenames, otherwise a list of
   * definitions.
   * @exception SQLException if something goes wrong with the database.
   * @see org.griphyn.vdl.annotation.QueryTree
   */
  public java.util.List searchAnnotation( int kind,
            Object arg,
            QueryTree tree)
    throws SQLException
  {
    java.util.List result = new java.util.ArrayList();

    if ( tree == null)
  return result;

    String subject = "";
    String defn = "transformation";
    String select = null;

    switch ( kind ) {
    case CLASS_TRANSFORMATION:
      subject = "tr";
      break;
    case CLASS_DERIVATION:
      subject = "dv";
      defn = "derivation";
      break;
    case CLASS_CALL:
      // may throw ClassCastException
      subject = "tr";  
      select = "call[" +  ((Integer) arg).intValue() + "]";
      break;
    case CLASS_DECLARE:
      subject = "tr";
      // may throw ClassCastException
      //select = "declare[@name='" + (String)arg + "']";
      select = (String)arg;
      break;
    case CLASS_FILENAME:
      subject = "lfn";
      break;
    default:
      throw new IllegalArgumentException( "The class kind=" + kind + " cannot be annotated" );
    }

    try {
    String id = null;
    String cond = "[@subject=\"" + subject + "\"]";
    if (select == null) {
  if (kind != CLASS_FILENAME) {
      cond += "[empty(@select)]";
  }
    } else {
  cond += "[@select=\"" + select + "\"]";
    }
    String xquery = "for $mn in distinct-values(//annotation/metadata" + cond + "/@name) " +
  "let $m := //annotation/metadata[@name=$mn]" + cond; 

    String where = " where ";
    where += tree.toXQuery("$m/attribute");

    if (kind == CLASS_FILENAME) {
  xquery += ", $r := $m";
  xquery += where;
  xquery += " return $mn";

  return searchElements(xquery);
    } else {
  xquery += ", $n := substring-before($mn, '::'), $na := substring-after($mn, '::'), $iv := if ($na) then $na else $mn, $v := substring-after($iv, ':'), $ib := substring-before($iv, ':'), $i := if ($ib) then $ib else $iv,";
  xquery += " $t := if ($n) then if ($v) then //" + defn + "[@namespace=$n][@name=$i][@version=$v] else //" + defn + "[@namespace=$n][@name=$i][empty(@version)] else if ($v) then //" + defn + "[empty(@namespace)][@name=$i][@version=$v] else //" + defn + "[empty(@namespace)][@name=$i][empty(@version)]";
  
  xquery += where;
  if (kind == CLASS_DECLARE)
      xquery += " return $t[" + "declare[@name='" + select + "']" + "]";
  else
      xquery += " return $t";
  return searchDefinition(xquery);
    }

    } catch (Exception e) {
  throw new SQLException(e.getMessage());
    }
  }


  /**
   * pass-thru to driver.
   * @return true, if it is feasible to cache results from the driver
   * false, if requerying the driver is sufficiently fast (e.g. driver
   * is in main memory, or driver does caching itself).
   */
  public boolean cachingMakesSense()
  {
      return true;
  }

  public void close()
    throws SQLException
  {
      try {
    //m_vdc.close();
    //m_db.close();
      } catch (Exception e){
    throw new SQLException(e.getMessage());
      }
  }
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.