0001: /*
0002: * This file or a portion of this file is licensed under the terms of
0003: * the Globus Toolkit Public License, found in file ../GTPL, or at
0004: * http://www.globus.org/toolkit/download/license.html. This notice must
0005: * appear in redistributions of this file, with or without modification.
0006: *
0007: * Redistributions of this Software, with or without modification, must
0008: * reproduce the GTPL in: (1) the Software, or (2) the Documentation or
0009: * some other similar material which is provided with the Software (if
0010: * any).
0011: *
0012: * Copyright 1999-2004 University of Chicago and The University of
0013: * Southern California. All rights reserved.
0014: */
0015:
0016: package org.griphyn.vdl.dbschema;
0017:
0018: import java.sql.*;
0019: import java.util.*;
0020: import java.io.*;
0021: import java.lang.reflect.*;
0022: import java.net.InetAddress;
0023: import org.griphyn.common.util.Separator;
0024: import org.griphyn.vdl.util.ChimeraProperties;
0025: import org.griphyn.vdl.annotation.*;
0026: import org.griphyn.vdl.classes.*;
0027: import org.griphyn.vdl.util.Logging;
0028: import org.griphyn.vdl.parser.*;
0029: import org.griphyn.vdl.router.Cache;
0030: import org.xml.sax.InputSource;
0031:
0032: /**
0033: * This class provides basic functionalities to interact with the
0034: * backend database, such as insertion, deletion, and search.
0035: * While the main database layout for storing definitions is derived
0036: * from the "chunk" schema with minor improvements, the database
0037: * layout of the annotations is shown in the following figure:<p>
0038: *
0039: * <img src="doc-files/AnnotationSchema-1.png" alt="annotation schema"><p>
0040: *
0041: * The central five elements that can receive annotations, all depend
0042: * on the same sequence generator for their primary key. Their secondary
0043: * key references the definition in question, or otherwise qualifies the
0044: * element to annotate. Note that logical filenames can be annotated
0045: * outside of any definitions.<p>
0046: *
0047: * Grouped along the outer edges, five primary data type tables store
0048: * annotations efficiently. The distinction into separate data types is
0049: * necessary to enable efficient searches and appropriate operations.
0050: * Their primary key is also a foreign key referencing the five central
0051: * elements.
0052: *
0053: * @author Jens-S. Vöckler
0054: * @author Yong Zhao
0055: * @version $Revision: 50 $
0056: */
0057: public class AnnotationSchema extends DatabaseSchema implements
0058: Advanced, Annotation {
0059: /**
0060: * Name of the four parameter tables in human readable format.
0061: */
0062: protected static final String[] c_lfn_names = { "ANNO_LFN_I",
0063: "ANNO_LFN_O", "ANNO_LFN_B" };
0064:
0065: /**
0066: * Communication between saveDefinition and deleteDefinition in
0067: * update mode.
0068: */
0069: protected boolean m_deferDeleteCommit;
0070:
0071: /**
0072: * An instance of the VDLx XML parser.
0073: */
0074: private org.griphyn.vdl.parser.VDLxParser m_parser;
0075:
0076: /**
0077: * A cache for definitions to avoid reloading from the database.
0078: */
0079: protected Cache m_cache;
0080:
0081: /**
0082: * Instantiates an XML parser for VDLx on demand. Since XML parsing
0083: * and parser instantiation is an expensive business, the reader will
0084: * only be generated on demand, and only once.
0085: *
0086: * @return a valid VDLx parser instance.
0087: */
0088: private org.griphyn.vdl.parser.VDLxParser parserInstance() {
0089: if (this .m_parser == null) {
0090: // obtain the schema location URL from the schema properties:
0091: // url is a list of strings representing schema locations. The
0092: // content exists in pairs, one of the namespace URI, one of the
0093: // location URL.
0094: String url = null;
0095: try {
0096: ChimeraProperties props = ChimeraProperties.instance();
0097: url = m_dbschemaprops.getProperty("xml.url", props
0098: .getVDLSchemaLocation());
0099: } catch (IOException e) {
0100: Logging.instance().log("chunk", 0, "ignored " + e);
0101: }
0102: this .m_parser = new org.griphyn.vdl.parser.VDLxParser(url);
0103: }
0104:
0105: // done
0106: return this .m_parser;
0107: }
0108:
0109: /**
0110: * Default constructor for the "chunk" schema.
0111: *
0112: * @param dbDriverName is the database driver name
0113: */
0114: public AnnotationSchema(String dbDriverName)
0115: throws ClassNotFoundException, NoSuchMethodException,
0116: InstantiationException, IllegalAccessException,
0117: InvocationTargetException, SQLException, IOException {
0118: // load the driver from the properties
0119: super (dbDriverName, VDC.PROPERTY_PREFIX);
0120: Logging.instance().log("dbschema", 3,
0121: "done with default schema c'tor");
0122:
0123: this .m_cache = this .m_dbdriver.cachingMakesSense() ? new Cache(
0124: 600) : null;
0125: this .m_deferDeleteCommit = false;
0126: this .m_parser = null;
0127:
0128: this .m_dbdriver.insertPreparedStatement("stmt.save.definition",
0129: "INSERT INTO anno_definition(id,type,name,namespace,version,xml) "
0130: + "VALUES (?,?,?,?,?,?)");
0131: this .m_dbdriver.insertPreparedStatement("stmt.save.lfn_i",
0132: "INSERT INTO anno_lfn_i(did,name) VALUES (?,?)");
0133: this .m_dbdriver.insertPreparedStatement("stmt.save.lfn_o",
0134: "INSERT INTO anno_lfn_o(did,name) VALUES (?,?)");
0135: this .m_dbdriver.insertPreparedStatement("stmt.save.lfn_b",
0136: "INSERT INTO anno_lfn_b(did,name) VALUES (?,?)");
0137:
0138: this .m_dbdriver.insertPreparedStatement("stmt.updt.definition",
0139: "UPDATE anno_definition SET xml=? WHERE id=?");
0140:
0141: this .m_dbdriver.insertPreparedStatement("stmt.save.anno_tr",
0142: "INSERT INTO anno_tr(id,did,mkey) VALUES (?,?,?)");
0143: this .m_dbdriver.insertPreparedStatement("stmt.save.anno_dv",
0144: "INSERT INTO anno_dv(id,did,mkey) VALUES (?,?,?)");
0145: this .m_dbdriver.insertPreparedStatement("stmt.save.anno_lfn",
0146: "INSERT INTO anno_lfn(id,name,mkey) VALUES (?,?,?)");
0147: this .m_dbdriver
0148: .insertPreparedStatement("stmt.save.anno_targ",
0149: "INSERT INTO anno_targ(id,did,name,mkey) VALUES (?,?,?,?)");
0150: this .m_dbdriver
0151: .insertPreparedStatement("stmt.save.anno_call",
0152: "INSERT INTO anno_call(id,did,pos,mkey) VALUES (?,?,?,?)");
0153:
0154: this .m_dbdriver.insertPreparedStatement("stmt.save.anno_bool",
0155: "INSERT INTO anno_bool(id,value) VALUES (?,?)");
0156: this .m_dbdriver.insertPreparedStatement("stmt.save.anno_int",
0157: "INSERT INTO anno_int(id,value) VALUES (?,?)");
0158: this .m_dbdriver.insertPreparedStatement("stmt.save.anno_float",
0159: "INSERT INTO anno_float(id,value) VALUES (?,?)");
0160: this .m_dbdriver.insertPreparedStatement("stmt.save.anno_date",
0161: "INSERT INTO anno_date(id,value) VALUES (?,?)");
0162: this .m_dbdriver.insertPreparedStatement("stmt.save.anno_text",
0163: "INSERT INTO anno_text(id,value) VALUES (?,?)");
0164:
0165: this .m_dbdriver.insertPreparedStatement("stmt.select.lfn_i",
0166: "SELECT distinct did FROM anno_lfn_i WHERE name=?");
0167: this .m_dbdriver.insertPreparedStatement("stmt.select.lfn_o",
0168: "SELECT distinct did FROM anno_lfn_o WHERE name=?");
0169: this .m_dbdriver.insertPreparedStatement("stmt.select.lfn_b",
0170: "SELECT distinct did FROM anno_lfn_b WHERE name=?");
0171: this .m_dbdriver
0172: .insertPreparedStatement(
0173: "stmt.select.lfn_*",
0174: "SELECT distinct did FROM anno_lfn_i WHERE name=? UNION "
0175: + "SELECT distinct did FROM anno_lfn_o WHERE name=? UNION "
0176: + "SELECT distinct did FROM anno_lfn_b WHERE name=?");
0177: this .m_dbdriver
0178: .insertPreparedStatement(
0179: "stmt.select.lfn_*.name",
0180: "SELECT distinct name FROM anno_lfn_i WHERE did=? UNION "
0181: + "SELECT distinct name FROM anno_lfn_o WHERE did=? UNION "
0182: + "SELECT distinct name FROM anno_lfn_b WHERE did=?");
0183:
0184: this .m_dbdriver
0185: .insertPreparedStatement("stmt.select.lfn_i.name.ex",
0186: "SELECT distinct name FROM anno_lfn_i WHERE name LIKE ?");
0187: this .m_dbdriver
0188: .insertPreparedStatement("stmt.select.lfn_o.name.ex",
0189: "SELECT distinct name FROM anno_lfn_o WHERE name LIKE ?");
0190: this .m_dbdriver
0191: .insertPreparedStatement("stmt.select.lfn_b.name.ex",
0192: "SELECT distinct name FROM anno_lfn_b WHERE name LIKE ?");
0193: this .m_dbdriver
0194: .insertPreparedStatement(
0195: "stmt.select.lfn_*.name.ex",
0196: "SELECT distinct name FROM anno_lfn_i WHERE name LIKE ? UNION "
0197: + "SELECT distinct name FROM anno_lfn_o WHERE name LIKE ? UNION "
0198: + "SELECT distinct name FROM anno_lfn_b WHERE name LIKE ?");
0199:
0200: this .m_dbdriver
0201: .insertPreparedStatement(
0202: "stmt.select.big",
0203: "SELECT id FROM anno_tr WHERE did=? UNION "
0204: + "SELECT id FROM anno_dv WHERE did=? UNION "
0205: + "SELECT id FROM anno_call WHERE did=? UNION "
0206: + "SELECT id FROM anno_targ WHERE did=? UNION "
0207: +
0208: // "SELECT id FROM anno_lfn WHERE name IN (" +
0209: // " SELECT distinct name FROM lfn_i WHERE did=? UNION " +
0210: // " SELECT distinct name FROM lfn_o WHERE did=? UNION " +
0211: // " SELECT distinct name FROM lfn_b WHERE did=? )" );
0212: "SELECT a.id FROM anno_lfn a, anno_lfn_i i WHERE i.name=a.name AND a.id=? UNION "
0213: + "SELECT a.id FROM anno_lfn a, anno_lfn_o o WHERE o.name=a.name AND a.id=? UNION "
0214: + "SELECT a.id FROM anno_lfn a, anno_lfn_b b WHERE b.name=a.name AND a.id=?");
0215:
0216: this .m_dbdriver.insertPreparedStatement("stmt.select.xml.id",
0217: "SELECT xml FROM anno_definition WHERE id=?");
0218: this .m_dbdriver
0219: .insertPreparedStatement(
0220: "stmt.select.xml",
0221: "SELECT id,xml FROM anno_definition WHERE type=? AND name=? AND namespace=? AND version=?");
0222: this .m_dbdriver
0223: .insertPreparedStatement(
0224: "stmt.select.id",
0225: "SELECT id FROM anno_definition WHERE type=? AND name=? AND namespace=? AND version=?");
0226:
0227: this .m_dbdriver.insertPreparedStatement("stmt.delete.xml",
0228: "DELETE FROM anno_definition WHERE id=?");
0229: this .m_dbdriver.insertPreparedStatement("stmt.delete.lfn_i",
0230: "DELETE FROM anno_lfn_i WHERE did=?");
0231: this .m_dbdriver.insertPreparedStatement("stmt.delete.lfn_o",
0232: "DELETE FROM anno_lfn_o WHERE did=?");
0233: this .m_dbdriver.insertPreparedStatement("stmt.delete.lfn_b",
0234: "DELETE FROM anno_lfn_b WHERE did=?");
0235:
0236: this .m_dbdriver.insertPreparedStatement(
0237: "stmt.delete.anno_bool",
0238: "DELETE FROM anno_bool WHERE id=?");
0239: this .m_dbdriver.insertPreparedStatement("stmt.delete.anno_int",
0240: "DELETE FROM anno_int WHERE id=?");
0241: this .m_dbdriver.insertPreparedStatement(
0242: "stmt.delete.anno_float",
0243: "DELETE FROM anno_float WHERE id=?");
0244: this .m_dbdriver.insertPreparedStatement(
0245: "stmt.delete.anno_date",
0246: "DELETE FROM anno_date WHERE id=?");
0247: this .m_dbdriver.insertPreparedStatement(
0248: "stmt.delete.anno_text",
0249: "DELETE FROM anno_text WHERE id=?");
0250:
0251: this .m_dbdriver.insertPreparedStatement("stmt.delete.anno_tr",
0252: "DELETE FROM anno_tr WHERE id=?");
0253: this .m_dbdriver.insertPreparedStatement("stmt.delete.anno_dv",
0254: "DELETE FROM anno_dv WHERE id=?");
0255: this .m_dbdriver.insertPreparedStatement("stmt.delete.anno_lfn",
0256: "DELETE FROM anno_lfn WHERE id=?");
0257: this .m_dbdriver.insertPreparedStatement(
0258: "stmt.delete.anno_targ",
0259: "DELETE FROM anno_targ WHERE id=?");
0260: this .m_dbdriver.insertPreparedStatement(
0261: "stmt.delete.anno_call",
0262: "DELETE FROM anno_call WHERE id=?");
0263:
0264: this .m_dbdriver.insertPreparedStatement("stmt.select.anno_tr",
0265: "SELECT id FROM anno_tr WHERE did=? AND mkey=?");
0266: this .m_dbdriver.insertPreparedStatement("stmt.select.anno_dv",
0267: "SELECT id FROM anno_dv WHERE did=? AND mkey=?");
0268: this .m_dbdriver.insertPreparedStatement("stmt.select.anno_lfn",
0269: "SELECT id FROM anno_lfn WHERE name=? AND mkey=?");
0270: this .m_dbdriver
0271: .insertPreparedStatement("stmt.select.anno_targ",
0272: "SELECT id FROM anno_targ WHERE did=? AND name=? AND mkey=?");
0273: this .m_dbdriver
0274: .insertPreparedStatement("stmt.select.anno_call",
0275: "SELECT id FROM anno_call WHERE did=? AND pos=? AND mkey=?");
0276:
0277: this .m_dbdriver.insertPreparedStatement(
0278: "stmt.select.anno_bool",
0279: "SELECT value FROM anno_bool WHERE id=?");
0280: this .m_dbdriver.insertPreparedStatement("stmt.select.anno_int",
0281: "SELECT value FROM anno_int WHERE id=?");
0282: this .m_dbdriver.insertPreparedStatement(
0283: "stmt.select.anno_float",
0284: "SELECT value FROM anno_float WHERE id=?");
0285: this .m_dbdriver.insertPreparedStatement(
0286: "stmt.select.anno_date",
0287: "SELECT value FROM anno_date WHERE id=?");
0288: this .m_dbdriver.insertPreparedStatement(
0289: "stmt.select.anno_text",
0290: "SELECT value FROM anno_text WHERE id=?");
0291:
0292: this .m_dbdriver.insertPreparedStatement("stmt.select.anno_tr2",
0293: "SELECT id,mkey FROM anno_tr WHERE did=?");
0294: this .m_dbdriver.insertPreparedStatement("stmt.select.anno_dv2",
0295: "SELECT id,mkey FROM anno_dv WHERE did=?");
0296: this .m_dbdriver.insertPreparedStatement(
0297: "stmt.select.anno_lfn2",
0298: "SELECT id,mkey FROM anno_lfn WHERE name=?");
0299: this .m_dbdriver.insertPreparedStatement(
0300: "stmt.select.anno_targ2",
0301: "SELECT id,mkey FROM anno_targ WHERE did=? and name=?");
0302: this .m_dbdriver.insertPreparedStatement(
0303: "stmt.select.anno_call2",
0304: "SELECT id,mkey FROM anno_call WHERE did=? and pos=?");
0305:
0306: // udpates, take one
0307: this .m_dbdriver.insertPreparedStatement("stmt.update.anno_tr",
0308: "UPDATE anno_tr SET did=? WHERE did=?");
0309: this .m_dbdriver.insertPreparedStatement("stmt.udpate.anno_dv",
0310: "UPDATE anno_dv SET did=? WHERE did=?");
0311: this .m_dbdriver.insertPreparedStatement(
0312: "stmt.update.anno_targ",
0313: "UPDATE anno_targ SET did=? WHERE did=?");
0314: this .m_dbdriver.insertPreparedStatement(
0315: "stmt.update.anno_call",
0316: "UPDATE anno_call SET did=? WHERE did=?");
0317: }
0318:
0319: //
0320: // lower level methods, working directly on specific definitions
0321: //
0322:
0323: /**
0324: * Loads a single Definition from the backend database into an Java object.
0325: * This method does not allow wildcarding!
0326: *
0327: * @param namespace namespace, null will be converted into empty string
0328: * @param name name, null will be converted into empty string
0329: * @param version version, null will be converted into empty string
0330: * @param type type of the definition (TR or DV), must not be -1.
0331: * @return the Definition as specified, or null if not found.
0332: *
0333: * @see org.griphyn.vdl.classes.Definition#TRANSFORMATION
0334: * @see org.griphyn.vdl.classes.Definition#DERIVATION
0335: * @see #saveDefinition( Definition, boolean )
0336: */
0337: public Definition loadDefinition(String namespace, String name,
0338: String version, int type) throws SQLException {
0339: Definition result = null;
0340: Logging.instance().log("xaction", 1, "START load definition");
0341:
0342: int i = 1;
0343: PreparedStatement ps = m_dbdriver
0344: .getPreparedStatement("stmt.select.xml");
0345: ps.setInt(i++, type);
0346: ps.setString(i++, makeNotNull(name));
0347: ps.setString(i++, makeNotNull(namespace));
0348: ps.setString(i++, makeNotNull(version));
0349: Logging.instance().log("chunk", 2,
0350: "SELECT xml FROM anno_definition");
0351:
0352: ResultSet rs = ps.executeQuery();
0353: Logging.instance().log("xaction", 1, "INTER load definition");
0354:
0355: if (rs.next()) {
0356: MyCallbackHandler cb = new MyCallbackHandler();
0357: Long lid = new Long(rs.getLong("id"));
0358: // FIXME: multiple null handlings missing
0359: parserInstance().parse(
0360: new org.xml.sax.InputSource(rs
0361: .getCharacterStream("xml")), cb);
0362: result = cb.getDefinition();
0363:
0364: // add to cache
0365: if (m_cache != null)
0366: m_cache.set(lid, result);
0367: } else {
0368: Logging.instance().log("chunk", 0, "Definition not found");
0369: }
0370:
0371: rs.close();
0372: Logging.instance().log("xaction", 1, "FINAL load definition");
0373: return result;
0374: }
0375:
0376: /**
0377: * Load a single Definition from the backend database into a Java
0378: * object by its primary key id. This is an internal helper function.
0379: *
0380: * @param id is a long which represent the primary id.
0381: * @return the Definitions that was matched by the id.
0382: *
0383: * @see #loadDefinition( String, String, String, int )
0384: * @see #saveDefinition( Definition, boolean )
0385: */
0386: private Definition loadDefinition(long id) throws SQLException {
0387: Definition result = null;
0388: Long lid = new Long(id);
0389: Logging.instance().log("xaction", 1,
0390: "START load definition " + lid);
0391:
0392: // try grabbing from cache
0393: if (m_cache != null)
0394: result = (Definition) m_cache.get(lid);
0395:
0396: if (result == null) {
0397: // no cache, or not in cache
0398: PreparedStatement ps = m_dbdriver
0399: .getPreparedStatement("stmt.select.xml.id");
0400: if (m_dbdriver.preferString())
0401: ps.setString(1, Long.toString(id));
0402: else
0403: ps.setLong(1, id);
0404: ResultSet rs = ps.executeQuery();
0405: Logging.instance().log("xaction", 1,
0406: "INTER load definitions");
0407:
0408: if (rs.next()) {
0409: MyCallbackHandler cb = new MyCallbackHandler();
0410:
0411: // FIXME: multiple null handlings missing
0412: parserInstance().parse(
0413: new org.xml.sax.InputSource(rs
0414: .getCharacterStream("xml")), cb);
0415: result = cb.getDefinition();
0416:
0417: // add to cache
0418: if (m_cache != null)
0419: m_cache.set(lid, result);
0420: } else {
0421: Logging.instance().log("chunk", 0,
0422: "Definition not found");
0423: }
0424: rs.close();
0425: }
0426:
0427: Logging.instance().log("xaction", 1, "FINAL load definitions");
0428: return result;
0429: }
0430:
0431: /**
0432: * Compiles the name of a DV/TR for log messages.
0433: *
0434: * @param d is a definition
0435: * @return the type plus FQDN of the definition
0436: */
0437: private String what(Definition d) {
0438: StringBuffer result = new StringBuffer();
0439: switch (d.getType()) {
0440: case Definition.DERIVATION:
0441: result.append("DV");
0442: break;
0443: case Definition.TRANSFORMATION:
0444: result.append("TR");
0445: break;
0446: default:
0447: result.append("??");
0448: break;
0449: }
0450:
0451: result.append(' ').append(d.shortID());
0452: return result.toString();
0453: }
0454:
0455: /**
0456: * Saves a Definition, that is either a Transformation or Derivation,
0457: * into the backend database. This method, of course, does not allow
0458: * wildcarding. The definition has to be completely specified and
0459: * valid.<p>
0460: * Please note that updating a definition will remove all the meta-
0461: * data that was defined for the definition.
0462: *
0463: * @param definition is the new Definition to store.
0464: * @param overwrite true, if existing defitions will be overwritten by
0465: * new ones with the same primary (or secondary) key (-set), or false,
0466: * if a new definition will be rejected on key matches.
0467: *
0468: * @return true, if the backend database was changed, or
0469: * false, if the definition was not accepted into the backend.
0470: *
0471: * @see org.griphyn.vdl.classes.Definition
0472: * @see org.griphyn.vdl.classes.Transformation
0473: * @see org.griphyn.vdl.classes.Derivation
0474: * @see #loadDefinition( String, String, String, int )
0475: */
0476: public boolean saveDefinition(Definition definition,
0477: boolean overwrite) throws SQLException {
0478: Logging.instance().log("chunk", 2, "SAVE DEFINITION started");
0479:
0480: // figure out, if it already exists
0481: long id = -1;
0482: try {
0483: Long temp = getDefinitionId(definition);
0484: if (temp != null)
0485: id = temp.longValue();
0486: } catch (SQLException e) {
0487: String cause = e.getMessage();
0488: Logging.instance().log(
0489: "app",
0490: 1,
0491: "Ignoring SQL exception"
0492: + (cause == null ? "" : ": "
0493: + e.getMessage()));
0494: m_dbdriver.clearWarnings();
0495: }
0496: boolean useInsert = (id == -1);
0497:
0498: // if in insertion mode, complain and exit
0499: if (!useInsert && !overwrite) {
0500: Logging
0501: .instance()
0502: .log(
0503: "app",
0504: 0,
0505: definition.shortID()
0506: + " already exists (SQL anno_definition.id="
0507: + id + "), ignoring");
0508: return false;
0509: }
0510:
0511: Logging.instance().log("app", 1,
0512: "Trying to add " + what(definition));
0513: PreparedStatement ps = m_dbdriver
0514: .getPreparedStatement(useInsert ? "stmt.save.definition"
0515: : "stmt.updt.definition");
0516:
0517: if (useInsert) {
0518: // INSERT
0519: try {
0520: id = m_dbdriver.sequence1("def_id_seq");
0521: } catch (SQLException e) {
0522: Logging.instance().log(
0523: "app",
0524: 0,
0525: "In " + definition.shortID() + ": "
0526: + e.toString().trim());
0527: Logging.instance().log("xaction", 1, "START rollback");
0528: m_dbdriver
0529: .cancelPreparedStatement("stmt.save.definition");
0530: m_dbdriver.rollback();
0531: Logging.instance().log("xaction", 1, "FINAL rollback");
0532: return false;
0533: }
0534:
0535: // add ID explicitely from sequence to insertion
0536: Logging.instance().log("xaction", 1,
0537: "START save definition");
0538: int i = 1;
0539: longOrNull(ps, i++, id);
0540:
0541: ps.setInt(i++, definition.getType());
0542: if (definition.getName() == null)
0543: throw new SQLException("VDS inconsistency: "
0544: + "The name of a definition is null");
0545: else
0546: ps.setString(i++, definition.getName());
0547: ps.setString(i++, makeNotNull(definition.getNamespace()));
0548: ps.setString(i++, makeNotNull(definition.getVersion()));
0549: String xml = definition.toXML((String) null, (String) null);
0550: ps.setCharacterStream(i++, new StringReader(xml), xml
0551: .length());
0552:
0553: // save prepared values
0554: Logging.instance()
0555: .log("chunk", 2, "INSERT INTO Definition");
0556: try {
0557: ps.executeUpdate();
0558: if (id == -1)
0559: id = m_dbdriver.sequence2(ps, "def_id_seq", 1);
0560: } catch (SQLException e) {
0561: Logging.instance().log(
0562: "app",
0563: 0,
0564: "In " + definition.shortID() + ": "
0565: + e.toString().trim());
0566: Logging.instance().log("xaction", 1, "START rollback");
0567: m_dbdriver
0568: .cancelPreparedStatement("stmt.save.definition");
0569: m_dbdriver.rollback();
0570: Logging.instance().log("xaction", 1, "FINAL rollback");
0571: return false;
0572: }
0573: Logging.instance().log("xaction", 1,
0574: "FINAL save definition: ID=" + id);
0575:
0576: } else {
0577: // UPDATE
0578: Logging.instance().log("xaction", 1,
0579: "START udpate definition");
0580: int i = 1;
0581: String xml = definition.toXML((String) null, (String) null);
0582: ps.setCharacterStream(i++, new StringReader(xml), xml
0583: .length());
0584: longOrNull(ps, i++, id);
0585:
0586: // update prepared values
0587: Logging.instance().log("chunk", 2, "UPDATE Definition");
0588: try {
0589: ps.executeUpdate();
0590: } catch (SQLException e) {
0591: Logging.instance().log(
0592: "app",
0593: 0,
0594: "In " + definition.shortID() + ": "
0595: + e.toString().trim());
0596: Logging.instance().log("xaction", 1, "START rollback");
0597: m_dbdriver
0598: .cancelPreparedStatement("stmt.updt.definition");
0599: m_dbdriver.rollback();
0600: Logging.instance().log("xaction", 1, "FINAL rollback");
0601: return false;
0602: }
0603: Logging.instance().log("xaction", 1,
0604: "FINAL update definition: ID=" + id);
0605:
0606: // TODO: Drop all old LFNs
0607: deleteLFNsForDefinitionId(id);
0608: }
0609:
0610: // batch save LFNs from Derivations
0611: if (definition instanceof Derivation) {
0612: Derivation derivation = (Derivation) definition;
0613: Set alreadyKnown = new HashSet();
0614: // ordering MUST MATCH classes.LFN constants!
0615: PreparedStatement stmt[] = {
0616: m_dbdriver.getPreparedStatement("stmt.save.lfn_i"),
0617: m_dbdriver.getPreparedStatement("stmt.save.lfn_o"),
0618: m_dbdriver.getPreparedStatement("stmt.save.lfn_b") };
0619: int[] count = new int[stmt.length];
0620: for (int ii = 0; ii < count.length; ++ii)
0621: count[ii] = 0;
0622:
0623: for (Iterator j = derivation.iteratePass(); j.hasNext();) {
0624: Value value = ((Pass) j.next()).getValue();
0625: if (value != null) {
0626: switch (value.getContainerType()) {
0627: case Value.SCALAR:
0628: // check Scalar contents for LFN
0629: saveScalar(id, (Scalar) value, alreadyKnown,
0630: stmt, count);
0631: break;
0632: case Value.LIST:
0633: // check List for Scalars for LFN
0634: for (Iterator k = ((org.griphyn.vdl.classes.List) value)
0635: .iterateScalar(); k.hasNext();) {
0636: saveScalar(id, (Scalar) k.next(),
0637: alreadyKnown, stmt, count);
0638: }
0639: break;
0640: default:
0641: throw new RuntimeException(
0642: "unknown container type");
0643: }
0644: }
0645: }
0646:
0647: for (int ii = 0; ii < stmt.length; ++ii) {
0648: // anything to do?
0649: if (count[ii] > 0) {
0650: // batch insert
0651: Logging.instance().log(
0652: "chunk",
0653: 2,
0654: "BATCH INSERT for " + count[ii] + ' '
0655: + c_lfn_names[ii]);
0656:
0657: Logging.instance().log(
0658: "xaction",
0659: 1,
0660: "START batch-add " + count[ii] + ' '
0661: + c_lfn_names[ii]);
0662: int[] update = stmt[ii].executeBatch();
0663: Logging.instance().log(
0664: "xaction",
0665: 1,
0666: "FINAL batch-add " + count[ii] + ' '
0667: + c_lfn_names[ii]);
0668: }
0669: }
0670: }
0671:
0672: // commit the changes
0673: Logging.instance().log("xaction", 1, "START commit");
0674: this .m_dbdriver.commit();
0675: Logging.instance().log("xaction", 1, "FINAL commit");
0676:
0677: // done
0678: return true;
0679: }
0680:
0681: /**
0682: * Saves all logical filenames from a Scalar object. This is a helper
0683: * function to save a single definition.
0684: *
0685: * @param id is the definition id in the DEFINITION table
0686: * @param scalar is a Scalar instance of which the LFNs are to be saved.
0687: * @param already is a set of filenames that were already added during
0688: * this session
0689: * @param stmt is an array of the ids of the prepared statements for
0690: * the different tables.
0691: * @param count count the number of entries in a prepared statement.
0692: *
0693: * @see #saveDefinition( Definition, boolean )
0694: */
0695: private void saveScalar(long id, Scalar scalar, Set already,
0696: PreparedStatement[] stmt, int[] count) throws SQLException {
0697: int result = 0;
0698: for (Iterator i = scalar.iterateLeaf(); i.hasNext();) {
0699: Leaf leaf = (Leaf) i.next();
0700: // only interested in logical filenames, nothing else
0701: if (leaf instanceof LFN) {
0702: LFN lfn = (LFN) leaf;
0703: String name = lfn.getFilename();
0704:
0705: // already inserted previously?
0706: if (already.contains(name))
0707: continue;
0708: else
0709: already.add(name);
0710:
0711: // adjust!
0712: int index = -1;
0713: int link = lfn.getLink();
0714: switch (link) {
0715: case LFN.INPUT:
0716: index = 0;
0717: break;
0718: case LFN.OUTPUT:
0719: index = 1;
0720: break;
0721: case LFN.INOUT:
0722: index = 2;
0723: break;
0724: default:
0725: throw new RuntimeException("Illegal linkage "
0726: + link + " for " + name);
0727: }
0728:
0729: int n = 1;
0730: if (m_dbdriver.preferString())
0731: stmt[index].setString(n++, Long.toString(id));
0732: else
0733: stmt[index].setLong(n++, id);
0734: stmt[index].setString(n++, name);
0735: Logging.instance()
0736: .log(
0737: "chunk",
0738: 3,
0739: "adding LFN " + LFN.toString(link)
0740: + ':' + name);
0741: stmt[index].addBatch();
0742:
0743: count[index]++;
0744: }
0745: }
0746: }
0747:
0748: //
0749: // higher level methods, allowing for wildcarding unless working on
0750: // a single Definition.
0751: //
0752:
0753: /**
0754: * Obtains the primary key id for a given definition. "Fake" definitions
0755: * are NOT permissable. This is an internal helper function.
0756: *
0757: * @param namespace is the specific namespace, null will be mapped to ""
0758: * @param name is the specific name, null will be mapped to ""
0759: * @param version is the specific version, null will be mapped to ""
0760: * @param type is the type identifier, -1 is not allowed.
0761: * @return the id of the definition, or null if not found.
0762: *
0763: * @see #getDefinitionId( String, String, String, int )
0764: */
0765: protected Long getSpecificDefinitionId(String namespace,
0766: String name, String version, int type) throws SQLException {
0767: Logging.instance().log("xaction", 1,
0768: "START select ID from DEFINITION");
0769: Long result = null;
0770:
0771: // ps.resetPreparedStatement( "stmt.select.id" );
0772: int i = 1;
0773: PreparedStatement ps = m_dbdriver
0774: .getPreparedStatement("stmt.select.id");
0775: ps.setInt(i++, type);
0776: ps.setString(i++, makeNotNull(name));
0777: ps.setString(i++, makeNotNull(namespace));
0778: ps.setString(i++, makeNotNull(version));
0779: Logging.instance().log("chunk", 2, "SELECT id FROM definition");
0780:
0781: ResultSet rs = ps.executeQuery();
0782: Logging.instance().log("xaction", 1,
0783: "INTER select ID from DEFINITION");
0784: if (rs.next())
0785: result = new Long(rs.getLong(1));
0786: else
0787: Logging.instance().log("chunk", 0, "Definition not found");
0788:
0789: rs.close();
0790: Logging.instance().log("xaction", 1,
0791: "FINAL select ID from DEFINITION");
0792: return result;
0793: }
0794:
0795: /**
0796: * Obtains the primary key id for a given definition. "Fake" definitions
0797: * are permissable. This is an internal helper function.
0798: *
0799: * @param d is a definition specification.
0800: * @return the id of the definition, or null if not found.
0801: *
0802: * @see #getSpecificDefinitionId( String, String, String, int )
0803: * @see #getDefinitionId( String, String, String, int )
0804: */
0805: protected Long getDefinitionId(Definition d) throws SQLException {
0806: return getSpecificDefinitionId(d.getNamespace(), d.getName(), d
0807: .getVersion(), d.getType());
0808: }
0809:
0810: /**
0811: * Obtains the list of primary key ids for a matching definitions.
0812: * This method allows for wildcards in the usual fashion. Use null for
0813: * strings as wildcards, and -1 for the type wildcard. This method may
0814: * return an empty list, but it will not return null. This is an
0815: * internal helper function.
0816: *
0817: * @param namespace namespace, null to match any namespace
0818: * @param name name, null to match any name
0819: * @param version version, null to match any version
0820: * @param type definition type (TR or DV)
0821: * @return a possibly empty list containing all matching
0822: * definition ids as Longs.
0823: *
0824: * @see org.griphyn.vdl.classes.Definition#TRANSFORMATION
0825: * @see org.griphyn.vdl.classes.Definition#DERIVATION
0826: * @see #getDefinitionId( Definition )
0827: */
0828: protected java.util.List getDefinitionId(String namespace,
0829: String name, String version, int type) throws SQLException {
0830: java.util.List result = new ArrayList();
0831: Logging.instance().log("xaction", 1,
0832: "START select IDs from DEFINITION");
0833:
0834: java.util.List select = new ArrayList(1);
0835: select.add(new String("distinct id"));
0836:
0837: java.util.Map where = new TreeMap();
0838: if (type != -1)
0839: where.put("type", Integer.toString(type));
0840: if (namespace != null)
0841: where.put("namespace", namespace);
0842: if (name != null)
0843: where.put("name", name);
0844: if (version != null)
0845: where.put("version", version);
0846:
0847: ResultSet rs = m_dbdriver.select(select, "anno_definition",
0848: where, null);
0849: while (rs.next())
0850: result.add(new Long(rs.getLong("id")));
0851:
0852: rs.close();
0853: Logging.instance().log("xaction", 1,
0854: "FINAL select IDs from DEFINITION");
0855: return result;
0856: }
0857:
0858: /**
0859: * Obtains the list of primary key ids for a matching definitions.
0860: * This method allows for wildcards in the usual fashion. Use null for
0861: * strings as wildcards, and -1 for the type wildcard. It also allows
0862: * special characters '%' and '_' in strings. This method may
0863: * return an empty list, but it will not return null. This is an
0864: * internal helper function.
0865: *
0866: * @param namespace namespace, null to match any namespace
0867: * @param name name, null to match any name
0868: * @param version version, null to match any version
0869: * @param type definition type (TR or DV)
0870: * @return a possibly empty list containing all matching
0871: * definition ids as Longs.
0872: *
0873: * @see org.griphyn.vdl.classes.Definition#TRANSFORMATION
0874: * @see org.griphyn.vdl.classes.Definition#DERIVATION
0875: * @see #getDefinitionId( Definition )
0876: */
0877: protected java.util.List getDefinitionIdEx(String namespace,
0878: String name, String version, int type) throws SQLException {
0879: java.util.List result = new ArrayList();
0880: Logging.instance().log("xaction", 1,
0881: "START select IDs from DEFINITION");
0882:
0883: java.util.List select = new ArrayList(1);
0884: select.add(new String("distinct id"));
0885:
0886: java.util.Map where = new TreeMap();
0887: java.util.Map operator = new TreeMap();
0888:
0889: if (type != -1)
0890: where.put("type", Integer.toString(type));
0891:
0892: if (namespace != null) {
0893: where.put("namespace", namespace);
0894: operator.put("namespace", "LIKE");
0895: }
0896: if (name != null) {
0897: where.put("name", name);
0898: operator.put("name", "LIKE");
0899: }
0900: if (version != null) {
0901: where.put("version", version);
0902: operator.put("version", "LIKE");
0903: }
0904:
0905: ResultSet rs = m_dbdriver.select(select, "anno_definition",
0906: where, operator, null);
0907: while (rs.next())
0908: result.add(new Long(rs.getLong("id")));
0909:
0910: rs.close();
0911: Logging.instance().log("xaction", 1,
0912: "FINAL select IDs from DEFINITION");
0913: return result;
0914: }
0915:
0916: /**
0917: * Search the database for the existence of a definition.
0918: *
0919: * @param definition the definition object to search for
0920: * @return true, if the definition exists, false if not found
0921: */
0922: public boolean containsDefinition(Definition definition)
0923: throws SQLException {
0924: boolean result = false;
0925: try {
0926: result = (getDefinitionId(definition) != null);
0927: } catch (SQLException sql) {
0928: // ignore
0929: this .m_dbdriver.clearWarnings();
0930: }
0931: return result;
0932: }
0933:
0934: /**
0935: * Deletes the joined annotations when a definition is being deleted.
0936: *
0937: * @param id is the definition id to remove
0938: * @return list of all annotation ids that were removed
0939: */
0940: private java.util.List deleteAnnotationFromDefinition(long id)
0941: throws SQLException {
0942: PreparedStatement ps = null;
0943: ResultSet rs = null;
0944: ArrayList idlist = new ArrayList();
0945: boolean preferString = m_dbdriver.preferString();
0946:
0947: //
0948: // part 1: assemble all affected annotation ids
0949: //
0950: // fnlist := collect list of filenames WHERE id=$id
0951: // annolist := SELECT distinct id FROM anno_$rest WHERE did=$id
0952: // annolist += SELECT distinct id FROM anno_lfn WHERE name IN $fnlist
0953:
0954: Logging.instance().log("xaction", 1, "START *huge* union");
0955: ps = this .m_dbdriver.getPreparedStatement("stmt.select.big");
0956: for (int i = 1; i <= 7; ++i) {
0957: if (preferString)
0958: ps.setString(i, Long.toString(id));
0959: else
0960: ps.setLong(i, id);
0961: }
0962:
0963: rs = ps.executeQuery();
0964: while (rs.next()) {
0965: idlist.add(new Long(rs.getLong(1)));
0966: }
0967: rs.close();
0968: Logging.instance().log("xaction", 1, "FINAL *huge* union");
0969:
0970: //
0971: // part 2: remove all affected annotations
0972: //
0973: // DELETE anno_$type WHERE id IN $annolist
0974: // DELETE anno_$rest WHERE id IN $annolist
0975:
0976: Logging.instance()
0977: .log("xaction", 1, "START delete annotations");
0978:
0979: // list of all statements we need to access
0980: PreparedStatement list[] = {
0981: this .m_dbdriver
0982: .getPreparedStatement("stmt.delete.anno_bool"),
0983: this .m_dbdriver
0984: .getPreparedStatement("stmt.delete.anno_int"),
0985: this .m_dbdriver
0986: .getPreparedStatement("stmt.delete.anno_float"),
0987: this .m_dbdriver
0988: .getPreparedStatement("stmt.delete.anno_date"),
0989: this .m_dbdriver
0990: .getPreparedStatement("stmt.delete.anno_text"),
0991: this .m_dbdriver
0992: .getPreparedStatement("stmt.delete.anno_tr"),
0993: this .m_dbdriver
0994: .getPreparedStatement("stmt.delete.anno_dv"),
0995: this .m_dbdriver
0996: .getPreparedStatement("stmt.delete.anno_lfn"),
0997: this .m_dbdriver
0998: .getPreparedStatement("stmt.delete.anno_targ"),
0999: this .m_dbdriver
1000: .getPreparedStatement("stmt.delete.anno_call") };
1001:
1002: // prepare and batch all statements
1003: for (Iterator i = idlist.iterator(); i.hasNext();) {
1004: id = ((Long) i.next()).longValue();
1005: for (int j = 0; j < list.length; ++j) {
1006: if (preferString)
1007: list[j].setString(1, Long.toString(id));
1008: else
1009: list[j].setLong(1, id);
1010: list[j].addBatch();
1011: }
1012: }
1013:
1014: // run all batches
1015: Logging.instance()
1016: .log("xaction", 1, "INTER delete annotations");
1017: for (int j = 0; j < list.length; ++j) {
1018: int[] status = new int[idlist.size()];
1019: try {
1020: status = list[j].executeBatch();
1021: } catch (NullPointerException npe) {
1022: Logging.instance().log("app", 1,
1023: "tripped over NPE, ignoring!");
1024: }
1025: }
1026:
1027: Logging.instance().log("xaction", 1, "FINAL delete annotation");
1028: if (!m_deferDeleteCommit)
1029: m_dbdriver.commit();
1030: return idlist;
1031: }
1032:
1033: /**
1034: * Deletes all logical filenames that are associated with a
1035: * particular definition. Note that this method does not commit
1036: * the changes, as it is supposed to be called from other methods.
1037: *
1038: * @param did is the definition id to remove LFNs for
1039: * @return number of rows affected, may be zero.
1040: */
1041: private int deleteLFNsForDefinitionId(long did) throws SQLException {
1042: int status, result = 0;
1043: PreparedStatement ps = null;
1044: boolean preferString = m_dbdriver.preferString();
1045:
1046: Logging.instance().log("xaction", 1, "START DELETE FROM lfn_i");
1047: ps = m_dbdriver.getPreparedStatement("stmt.delete.lfn_i");
1048: if (preferString)
1049: ps.setString(1, Long.toString(did));
1050: else
1051: ps.setLong(1, did);
1052: result = ps.executeUpdate();
1053: Logging.instance().log("xaction", 1,
1054: "FINAL DELETE FROM lfn_i: " + result);
1055:
1056: Logging.instance().log("xaction", 1, "START DELETE FROM lfn_o");
1057: ps = m_dbdriver.getPreparedStatement("stmt.delete.lfn_o");
1058: if (preferString)
1059: ps.setString(1, Long.toString(did));
1060: else
1061: ps.setLong(1, did);
1062: status = ps.executeUpdate();
1063: result += status;
1064: Logging.instance().log("xaction", 1,
1065: "FINAL DELETE FROM lfn_o: " + status);
1066:
1067: Logging.instance().log("xaction", 1, "START DELETE FROM lfn_b");
1068: ps = m_dbdriver.getPreparedStatement("stmt.delete.lfn_b");
1069: if (preferString)
1070: ps.setString(1, Long.toString(did));
1071: else
1072: ps.setLong(1, did);
1073: status = ps.executeUpdate();
1074: result += status;
1075: Logging.instance().log("xaction", 1,
1076: "FINAL DELETE FROM lfn_b: " + status);
1077:
1078: return result;
1079: }
1080:
1081: /**
1082: * Delete a specific Definition objects from the database. No wildcard
1083: * matching will be done. "Fake" definitions are permissable, meaning
1084: * it just has the secondary key triple.
1085: *
1086: * @param definition is the definition specification to delete
1087: * @return true is something was deleted, false if non existent.
1088: *
1089: * @see org.griphyn.vdl.classes.Definition#TRANSFORMATION
1090: * @see org.griphyn.vdl.classes.Definition#DERIVATION
1091: */
1092: public boolean deleteDefinition(Definition definition)
1093: throws SQLException {
1094: int result = 0;
1095: PreparedStatement ps = null;
1096:
1097: //
1098: // TODO: turn into a stored procedure call
1099: //
1100: Logging.instance().log("xaction", 1, "START delete definition");
1101: Long defId = getDefinitionId(definition);
1102: boolean preferString = m_dbdriver.preferString();
1103: if (defId != null) {
1104: long id = defId.longValue();
1105: deleteAnnotationFromDefinition(id);
1106: deleteLFNsForDefinitionId(id);
1107:
1108: Logging.instance().log("xaction", 1,
1109: "START DELETE FROM definition");
1110: ps = m_dbdriver.getPreparedStatement("stmt.delete.xml");
1111: if (preferString)
1112: ps.setString(1, Long.toString(id));
1113: else
1114: ps.setLong(1, id);
1115: result = ps.executeUpdate();
1116: Logging.instance().log("xaction", 1,
1117: "FINAL DELETE FROM definition: " + result);
1118:
1119: if (!m_deferDeleteCommit)
1120: m_dbdriver.commit();
1121: }
1122:
1123: Logging.instance().log("xaction", 1, "FINAL delete definition");
1124: return (result != 0);
1125: }
1126:
1127: /**
1128: * Delete Definition objects from the database. This method allows for
1129: * wildcards in the usual fashion. Use null for strings as wildcards,
1130: * and -1 for the type wildcard. For efficiency reasons, this method
1131: * will return an empty list.
1132: *
1133: * @param namespace namespace, null to match any namespace
1134: * @param name name, null to match any name
1135: * @param version version, null to match any version
1136: * @param type definition type (TR or DV)
1137: * @return a list containing all Definitions that were deleted
1138: *
1139: * @see org.griphyn.vdl.classes.Definition#TRANSFORMATION
1140: * @see org.griphyn.vdl.classes.Definition#DERIVATION
1141: */
1142: public java.util.List deleteDefinition(String namespace,
1143: String name, String version, int type) throws SQLException {
1144: java.util.List result = new ArrayList();
1145: Logging.instance()
1146: .log("xaction", 1, "START delete definitions");
1147:
1148: java.util.List idlist = getDefinitionId(namespace, name,
1149: version, type);
1150: if (idlist.size() == 0)
1151: return result;
1152: // postcondition: contains all IDs, count(id)>0, to be deleted
1153:
1154: // save old values
1155: if (!m_deferDeleteCommit) {
1156: // we come from saveDefinition, thus we won't need saved values
1157: for (Iterator i = idlist.iterator(); i.hasNext();) {
1158: Definition d = loadDefinition(((Long) i.next())
1159: .longValue());
1160: if (d != null)
1161: result.add(d);
1162: }
1163: }
1164:
1165: // remove all affected annoations by walking through them
1166: // yuk, this is probably extremely expensive
1167: for (Iterator i = idlist.iterator(); i.hasNext();) {
1168: long id = ((Long) i.next()).longValue();
1169: deleteAnnotationFromDefinition(id);
1170: }
1171:
1172: // list of all statements we need to access
1173: PreparedStatement ps[] = {
1174: this .m_dbdriver
1175: .getPreparedStatement("stmt.delete.lfn_i"),
1176: this .m_dbdriver
1177: .getPreparedStatement("stmt.delete.lfn_o"),
1178: this .m_dbdriver
1179: .getPreparedStatement("stmt.delete.lfn_b"),
1180: this .m_dbdriver.getPreparedStatement("stmt.delete.xml") };
1181:
1182: // prepare and batch all statements
1183: boolean preferString = m_dbdriver.preferString();
1184: for (Iterator i = idlist.iterator(); i.hasNext();) {
1185: long id = ((Long) i.next()).longValue();
1186: for (int j = 0; j < ps.length; ++j) {
1187: if (preferString)
1188: ps[j].setString(1, Long.toString(id));
1189: else
1190: ps[j].setLong(1, id);
1191: ps[j].addBatch();
1192: }
1193: }
1194:
1195: // run all batches
1196: Logging.instance()
1197: .log("xaction", 1, "INTER delete definitions");
1198: for (int j = 0; j < ps.length; ++j) {
1199: int[] status = new int[idlist.size()];
1200: try {
1201: status = ps[j].executeBatch();
1202: } catch (NullPointerException npe) {
1203: Logging.instance().log("app", 1,
1204: "tripped over NPE, ignoring!");
1205: }
1206: }
1207:
1208: Logging.instance()
1209: .log("xaction", 1, "FINAL delete definitions");
1210: if (!m_deferDeleteCommit)
1211: m_dbdriver.commit();
1212: return result;
1213: }
1214:
1215: /**
1216: * Search the database for definitions by ns::name:version triple
1217: * and by type (either Transformation or Derivation). This version
1218: * of the search allows for jokers expressed as null value
1219: *
1220: * @param namespace namespace, null to match any namespace
1221: * @param name name, null to match any name
1222: * @param version version, null to match any version
1223: * @param type type of definition (TR/DV, or both)
1224: * @return a list of definitions
1225: *
1226: * @see org.griphyn.vdl.classes.Definition#TRANSFORMATION
1227: * @see org.griphyn.vdl.classes.Definition#DERIVATION
1228: */
1229: public java.util.List searchDefinition(String namespace,
1230: String name, String version, int type) throws SQLException {
1231: java.util.List idlist = getDefinitionId(namespace, name,
1232: version, type);
1233:
1234: // TODO: make this a batch or sproc
1235: java.util.List result = new ArrayList();
1236: for (Iterator i = idlist.iterator(); i.hasNext();) {
1237: Definition d = loadDefinition(((Long) i.next()).longValue());
1238: if (d != null)
1239: result.add(d);
1240: }
1241: return result;
1242: }
1243:
1244: /**
1245: * Searches the database for all derivations that contain a certain LFN.
1246: * The linkage is an additional constraint. This method does not allow
1247: * jokers.
1248: *
1249: * @param lfn the LFN name
1250: * @param link the linkage type of the LFN
1251: * @return a list of Definition items that match the criterion.
1252: *
1253: * @see org.griphyn.vdl.classes.LFN#NONE
1254: * @see org.griphyn.vdl.classes.LFN#INPUT
1255: * @see org.griphyn.vdl.classes.LFN#OUTPUT
1256: * @see org.griphyn.vdl.classes.LFN#INOUT
1257: */
1258: public java.util.List searchFilename(String lfn, int link)
1259: throws SQLException {
1260: if (lfn == null)
1261: throw new NullPointerException(
1262: "You must query for a filename");
1263: Logging.instance().log("xaction", 1, "START select LFNs");
1264: PreparedStatement ps = null;
1265:
1266: if (link == -1) {
1267: // wildcard match
1268: ps = this .m_dbdriver
1269: .getPreparedStatement("stmt.select.lfn_*");
1270: for (int ii = 0; ii < c_lfn_names.length; ++ii)
1271: ps.setString(ii + 1, lfn);
1272: Logging.instance().log(
1273: "chunk",
1274: 2,
1275: "SELECT distinct id FROM anno_lfn_*"
1276: + " WHERE name='" + lfn + "'");
1277: } else if (LFN.isInRange(link)) {
1278: // known linkage, one table only
1279:
1280: // ordering MUST MATCH classes.LFN constants!
1281: switch (link) {
1282: case LFN.NONE:
1283: throw new RuntimeException(
1284: "The linkage \"none\" is not permitted");
1285: // break;
1286: case LFN.INPUT:
1287: ps = this .m_dbdriver
1288: .getPreparedStatement("stmt.select.lfn_i");
1289: break;
1290: case LFN.OUTPUT:
1291: ps = this .m_dbdriver
1292: .getPreparedStatement("stmt.select.lfn_o");
1293: break;
1294: case LFN.INOUT:
1295: ps = this .m_dbdriver
1296: .getPreparedStatement("stmt.select.lfn_b");
1297: break;
1298: }
1299: ;
1300:
1301: ps.setString(1, lfn);
1302: Logging.instance().log(
1303: "chunk",
1304: 2,
1305: "SELECT distinct id FROM " + c_lfn_names[link - 1]
1306: + " WHERE name='" + lfn + "'");
1307: } else {
1308: throw new RuntimeException("The linkage " + link
1309: + " is not permitted");
1310: }
1311:
1312: ResultSet rs = ps.executeQuery();
1313:
1314: // TODO: make this a batch or sproc
1315: java.util.List result = new ArrayList();
1316: while (rs.next()) {
1317: Definition d = loadDefinition(rs.getLong(1));
1318: if (d != null)
1319: result.add(d);
1320: }
1321:
1322: rs.close();
1323: Logging.instance().log("xaction", 1, "FINAL select LFNs");
1324: return result;
1325: }
1326:
1327: //
1328: //
1329: // annotations
1330: //
1331: //
1332:
1333: /**
1334: * Retrieves the annotation id of a given transformation.
1335: *
1336: * @param did is the definition id of the transformation
1337: * @param key is the key to search for.
1338: * @return -1 if not found, or the correction annotation id.
1339: * @exception SQLException if some database operation fails.
1340: */
1341: private long getAnnotationIdTransformation(long did, String key)
1342: throws SQLException {
1343: long result = -1;
1344:
1345: Logging.instance().log("xaction", 1, "START select anno_tr");
1346: int i = 1;
1347: PreparedStatement ps = m_dbdriver
1348: .getPreparedStatement("stmt.select.anno_tr");
1349: if (m_dbdriver.preferString())
1350: ps.setString(i++, Long.toString(did));
1351: else
1352: ps.setLong(i++, did);
1353: ps.setString(i++, makeNotNull(key));
1354:
1355: Logging.instance().log("chunk", 2, "SELECT id FROM anno_tr");
1356: ResultSet rs = ps.executeQuery();
1357: if (rs.next())
1358: result = rs.getLong(1);
1359: rs.close();
1360:
1361: Logging.instance().log("xaction", 1,
1362: "FINAL select anno_tr.id = " + result);
1363: return result;
1364: }
1365:
1366: /**
1367: * Retrieves the annotation id of a given derivation id.
1368: *
1369: * @param did is the definition id of the derivation
1370: * @param key is the key to search for.
1371: * @return -1 if not found, or the correction annotation id.
1372: * @exception SQLException if some database operation fails.
1373: */
1374: private long getAnnotationIdDerivation(long did, String key)
1375: throws SQLException {
1376: long result = -1;
1377:
1378: Logging.instance().log("xaction", 1, "START select anno_dv");
1379: int i = 1;
1380: PreparedStatement ps = m_dbdriver
1381: .getPreparedStatement("stmt.select.anno_dv");
1382: if (m_dbdriver.preferString())
1383: ps.setString(i++, Long.toString(did));
1384: else
1385: ps.setLong(i++, did);
1386: ps.setString(i++, makeNotNull(key));
1387:
1388: Logging.instance().log("chunk", 2, "SELECT id FROM anno_dv");
1389: ResultSet rs = ps.executeQuery();
1390: if (rs.next())
1391: result = rs.getLong(1);
1392: rs.close();
1393:
1394: Logging.instance().log("xaction", 1,
1395: "FINAL select anno_dv.id = " + result);
1396: return result;
1397: }
1398:
1399: /**
1400: * Retrieves the annotation id of a given transformation formal argument.
1401: *
1402: * @param did is the definition id of the transformation
1403: * @param farg is the formal argument name
1404: * @param key is the key to search for.
1405: * @return -1 if not found, or the correction annotation id.
1406: * @exception SQLException if some database operation fails.
1407: */
1408: private long getAnnotationIdDeclare(long did, String farg,
1409: String key) throws SQLException {
1410: long result = -1;
1411:
1412: Logging.instance().log("xaction", 1, "START select anno_targ");
1413: int i = 1;
1414: PreparedStatement ps = m_dbdriver
1415: .getPreparedStatement("stmt.select.anno_targ");
1416: if (m_dbdriver.preferString())
1417: ps.setString(i++, Long.toString(did));
1418: else
1419: ps.setLong(i++, did);
1420: ps.setString(i++, makeNotNull(farg));
1421: ps.setString(i++, makeNotNull(key));
1422:
1423: Logging.instance().log("chunk", 2, "SELECT id FROM anno_targ");
1424: ResultSet rs = ps.executeQuery();
1425: if (rs.next())
1426: result = rs.getLong(1);
1427: rs.close();
1428:
1429: Logging.instance().log("xaction", 1,
1430: "FINAL select anno_targ.id = " + result);
1431: return result;
1432: }
1433:
1434: /**
1435: * Retrieves the annotation id of a given call within a transformation.
1436: *
1437: * @param did is the definition id of the transformation
1438: * @param pos is the position of the call statement
1439: * @param key is the key to search for.
1440: * @return -1 if not found, or the correction annotation id.
1441: * @exception SQLException if some database operation fails.
1442: */
1443: private long getAnnotationIdCall(long did, int pos, String key)
1444: throws SQLException {
1445: long result = -1;
1446:
1447: Logging.instance().log("xaction", 1, "START select anno_call");
1448: int i = 1;
1449: PreparedStatement ps = m_dbdriver
1450: .getPreparedStatement("stmt.select.anno_call");
1451: if (m_dbdriver.preferString()) {
1452: ps.setString(i++, Long.toString(did));
1453: ps.setString(i++, Integer.toString(pos));
1454: } else {
1455: ps.setLong(i++, did);
1456: ps.setInt(i++, pos);
1457: }
1458: ps.setString(i++, makeNotNull(key));
1459:
1460: Logging.instance().log("chunk", 2, "SELECT id FROM anno_call");
1461: ResultSet rs = ps.executeQuery();
1462: if (rs.next())
1463: result = rs.getLong(1);
1464: rs.close();
1465:
1466: Logging.instance().log("xaction", 1,
1467: "FINAL select anno_call.id = " + result);
1468: return result;
1469: }
1470:
1471: /**
1472: * Retrieves the annotation id of a given logical filename.
1473: *
1474: * @param lfn is the logical filename.
1475: * @param key is the key to search for.
1476: * @return -1 if not found, or the correction annotation id.
1477: * @exception SQLException if some database operation fails.
1478: */
1479: private long getAnnotationIdFilename(String lfn, String key)
1480: throws SQLException {
1481: long result = -1;
1482:
1483: Logging.instance().log("xaction", 1, "START select anno_lfn");
1484: int i = 1;
1485: PreparedStatement ps = m_dbdriver
1486: .getPreparedStatement("stmt.select.anno_lfn");
1487: ps.setString(i++, makeNotNull(lfn));
1488: ps.setString(i++, makeNotNull(key));
1489:
1490: Logging.instance().log("chunk", 2, "SELECT id FROM anno_lfn");
1491: ResultSet rs = ps.executeQuery();
1492: if (rs.next())
1493: result = rs.getLong(1);
1494: rs.close();
1495:
1496: Logging.instance().log("xaction", 1,
1497: "FINAL select anno_lfn.id = " + result);
1498: return result;
1499: }
1500:
1501: /**
1502: * Deletes an annotation with the specified key.
1503: *
1504: * @param primary is the primary object specifier for the class.
1505: * According to the type, this is either the FQDI, or the filename.
1506: * @param secondary is a helper argument for annotations to calls
1507: * and formal arguments, and should be null for all other classes.
1508: * For calls, the argument must be packed into {@link java.lang.Integer}.
1509: * @param kind defines the kind/class of object to annotate.
1510: * @param key is the annotation key.
1511: * @return true, if the database was modified, false otherwise.
1512: * @exception SQLException, if something went wrong during database
1513: * access.
1514: */
1515: public boolean deleteAnnotation(String primary, Object secondary,
1516: int kind, String key) throws SQLException,
1517: IllegalArgumentException {
1518: boolean result = true;
1519: switch (kind) {
1520: case CLASS_TRANSFORMATION:
1521: result = deleteAnnotationTransformation(primary, key);
1522: break;
1523: case CLASS_DERIVATION:
1524: result = deleteAnnotationDerivation(primary, key);
1525: break;
1526: case CLASS_CALL:
1527: // may throw ClassCastException
1528: result = deleteAnnotationCall(primary,
1529: ((Integer) secondary).intValue(), key);
1530: break;
1531: case CLASS_DECLARE:
1532: // may throw ClassCastException
1533: result = deleteAnnotationDeclare(primary,
1534: ((String) secondary), key);
1535: break;
1536: case CLASS_FILENAME:
1537: result = deleteAnnotationFilename(primary, key);
1538: break;
1539: default:
1540: throw new IllegalArgumentException("The class kind=" + kind
1541: + " cannot be annotated");
1542: }
1543:
1544: return result;
1545: }
1546:
1547: /**
1548: * Deletes an annotation value with the specified annotation id.
1549: *
1550: * @param id is the annotation id for which to delete
1551: *
1552: * @return true, if the database was modified, false otherwise.
1553: * @exception SQLException, if something went wrong during database
1554: * access.
1555: */
1556: private boolean deleteAnnotationValue(long id) throws SQLException {
1557: PreparedStatement list[] = {
1558: this .m_dbdriver
1559: .getPreparedStatement("stmt.delete.anno_bool"),
1560: this .m_dbdriver
1561: .getPreparedStatement("stmt.delete.anno_int"),
1562: this .m_dbdriver
1563: .getPreparedStatement("stmt.delete.anno_float"),
1564: this .m_dbdriver
1565: .getPreparedStatement("stmt.delete.anno_date"),
1566: this .m_dbdriver
1567: .getPreparedStatement("stmt.delete.anno_text") };
1568:
1569: boolean result = true;
1570:
1571: // prepare and batch all statements
1572: for (int j = 0; j < list.length; ++j) {
1573: if (m_dbdriver.preferString())
1574: list[j].setString(1, Long.toString(id));
1575: else
1576: list[j].setLong(1, id);
1577: list[j].addBatch();
1578: }
1579:
1580: // run all batches
1581: Logging.instance()
1582: .log("xaction", 1, "INTER delete annotations");
1583: for (int j = 0; j < list.length; ++j) {
1584: int[] status = new int[1];
1585: try {
1586: status = list[j].executeBatch();
1587: result = (result && (status[0] != 0));
1588: } catch (NullPointerException npe) {
1589: Logging.instance().log("app", 1,
1590: "tripped over NPE, ignoring!");
1591: }
1592: }
1593:
1594: Logging.instance().log("xaction", 1, "FINAL delete annotation");
1595: if (!m_deferDeleteCommit)
1596: m_dbdriver.commit();
1597: return result;
1598: }
1599:
1600: /**
1601: * Deletes an annotation in a type table with the specified
1602: * annotation id. The table is determined from the type of the
1603: * annotational tuple.
1604: *
1605: * @param id is the annotation id for which to delete
1606: * @param kind is the class of object.
1607: * @return true, if the database was modified, false otherwise.
1608: * @exception SQLException, if something went wrong during database
1609: * access.
1610: */
1611: private boolean deleteAnnotationKey(long id, int kind)
1612: throws SQLException {
1613: Logging.instance().log("xaction", 1, "START delete anno_<key>");
1614:
1615: PreparedStatement ps = null;
1616: switch (kind) {
1617: case CLASS_FILENAME:
1618: ps = m_dbdriver
1619: .getPreparedStatement("stmt.delete.anno_lfn");
1620: break;
1621: case CLASS_TRANSFORMATION:
1622: ps = m_dbdriver.getPreparedStatement("stmt.delete.anno_tr");
1623: break;
1624: case CLASS_DERIVATION:
1625: ps = m_dbdriver.getPreparedStatement("stmt.delete.anno_dv");
1626: break;
1627: case CLASS_DECLARE:
1628: ps = m_dbdriver
1629: .getPreparedStatement("stmt.delete.anno_targ");
1630: break;
1631: case CLASS_CALL:
1632: ps = m_dbdriver
1633: .getPreparedStatement("stmt.delete.anno_call");
1634: break;
1635: default:
1636: throw new SQLException("Don't know the class of object");
1637: }
1638:
1639: if (m_dbdriver.preferString())
1640: ps.setString(1, Long.toString(id));
1641: else
1642: ps.setLong(1, id);
1643:
1644: Logging.instance().log("chunk", 2, "DELETE FROM anno_<key>");
1645: int rc = ps.executeUpdate();
1646: Logging.instance().log("xaction", 1, "FINAL delete anno_<key>");
1647: boolean ret = deleteAnnotationValue(id);
1648: return (rc != 0 && ret);
1649: }
1650:
1651: /**
1652: * Deletes an annotation in a type table with the specified
1653: * annotation id. The table is determined from the type of the
1654: * annotational tuple.
1655: *
1656: * @param id is the annotation id for which to delete
1657: * @param annotation is the annotation which determines the type
1658: * @return true, if the database was modified, false otherwise.
1659: * @exception SQLException, if something went wrong during database
1660: * access.
1661: */
1662: private boolean deleteAnnotationValue(long id, Tuple annotation)
1663: throws SQLException {
1664: Logging.instance().log("xaction", 1,
1665: "START delete anno_<value>");
1666:
1667: PreparedStatement ps = null;
1668: if (annotation instanceof TupleBoolean)
1669: ps = m_dbdriver
1670: .getPreparedStatement("stmt.delete.anno_bool");
1671: else if (annotation instanceof TupleDate)
1672: ps = m_dbdriver
1673: .getPreparedStatement("stmt.delete.anno_date");
1674: else if (annotation instanceof TupleFloat)
1675: ps = m_dbdriver
1676: .getPreparedStatement("stmt.delete.anno_float");
1677: else if (annotation instanceof TupleInteger)
1678: ps = m_dbdriver
1679: .getPreparedStatement("stmt.delete.anno_int");
1680: else if (annotation instanceof TupleString)
1681: ps = m_dbdriver
1682: .getPreparedStatement("stmt.delete.anno_text");
1683: else
1684: throw new SQLException("Don't know the tuple type");
1685:
1686: if (m_dbdriver.preferString())
1687: ps.setString(1, Long.toString(id));
1688: else
1689: ps.setLong(1, id);
1690:
1691: Logging.instance().log("chunk", 2, "DELETE FROM anno_<value>");
1692: int rc = ps.executeUpdate();
1693: Logging.instance().log("xaction", 1,
1694: "FINAL delete anno_<value>");
1695: return (rc != 0);
1696: }
1697:
1698: /**
1699: * Deletes a specific key in an annotated transformation.
1700: *
1701: * @param fqdi is the FQDI of the transformation
1702: * @param key is the key to search for
1703: * @return true, if the database was modified, false otherwise.
1704: * @see org.griphyn.vdl.classes.Transformation
1705: */
1706: public boolean deleteAnnotationTransformation(String fqdi,
1707: String key) throws SQLException, IllegalArgumentException {
1708: int kind = CLASS_TRANSFORMATION;
1709:
1710: // split FQDI
1711: String[] names = Separator.split(fqdi); // may throw IAE
1712:
1713: // obtain DID for FQDI
1714: Long did = getSpecificDefinitionId(names[0], names[1],
1715: names[2], Definition.TRANSFORMATION);
1716: if (did == null)
1717: throw new SQLException("Unknown TR " + fqdi);
1718:
1719: // obtain possible existing anno_tr id
1720: long id = getAnnotationIdTransformation(did.longValue(), key);
1721:
1722: // no such key, if the id is -1, handled by finalizer
1723: return deleteAnnotationKey(id, kind);
1724: }
1725:
1726: /**
1727: * Deletes a specific key in an annotated derivation.
1728: *
1729: * @param fqdi is the FQDI of the derivation
1730: * @param key is the key to search for
1731: * @return true, if the database was modified, false otherwise.
1732: * @see org.griphyn.vdl.classes.Derivation
1733: */
1734: public boolean deleteAnnotationDerivation(String fqdi, String key)
1735: throws SQLException, IllegalArgumentException {
1736: int kind = CLASS_DERIVATION;
1737:
1738: // split FQDI
1739: String[] names = Separator.split(fqdi); // may throw IAE
1740:
1741: // obtain DID for FQDI
1742: Long did = getSpecificDefinitionId(names[0], names[1],
1743: names[2], Definition.DERIVATION);
1744: if (did == null)
1745: throw new SQLException("Unknown DV " + fqdi);
1746:
1747: // obtain possible existing anno_dv id
1748: long id = getAnnotationIdDerivation(did.longValue(), key);
1749:
1750: // no such key, if the id does not exist
1751: return deleteAnnotationKey(id, kind);
1752: }
1753:
1754: /**
1755: * Deletes a specific key in an annotated formal argument.
1756: *
1757: * @param fqdi is the FQDI of the transformation
1758: * @param farg is the name of the formal argument
1759: * @param key is the key to search for
1760: * @return true, if the database was modified, false otherwise.
1761: * @see org.griphyn.vdl.classes.Declare
1762: */
1763: public boolean deleteAnnotationDeclare(String fqdi, String farg,
1764: String key) throws SQLException, IllegalArgumentException {
1765: int kind = CLASS_DECLARE;
1766:
1767: // split FQDI
1768: String[] names = Separator.split(fqdi); // may throw IAE
1769:
1770: // obtain DID for FQDI
1771: Long did = getSpecificDefinitionId(names[0], names[1],
1772: names[2], Definition.TRANSFORMATION);
1773: if (did == null)
1774: throw new SQLException("Unknown TR " + fqdi);
1775:
1776: // obtain possible existing anno_call id
1777: long id = getAnnotationIdDeclare(did.longValue(), farg, key);
1778:
1779: // no such key, if the id does not exist
1780: return deleteAnnotationKey(id, kind);
1781: }
1782:
1783: /**
1784: * Deletes a specific key for a call statement.
1785: *
1786: * @param fqdi is the FQDI of the transformation
1787: * @param index is the number of the call to annotate.
1788: * @param key is the key to search for
1789: * @return true, if the database was modified, false otherwise.
1790: * @see org.griphyn.vdl.classes.Call
1791: */
1792: public boolean deleteAnnotationCall(String fqdi, int index,
1793: String key) throws SQLException, IllegalArgumentException {
1794: int kind = CLASS_CALL;
1795:
1796: // split FQDI
1797: String[] names = Separator.split(fqdi); // may throw IAE
1798:
1799: // obtain DID for FQDI
1800: Long did = getSpecificDefinitionId(names[0], names[1],
1801: names[2], Definition.TRANSFORMATION);
1802: if (did == null)
1803: throw new SQLException("Unknown TR " + fqdi);
1804:
1805: // obtain possible existing anno_call id
1806: long id = getAnnotationIdCall(did.longValue(), index, key);
1807:
1808: // no such key, if the id does not exist
1809: return deleteAnnotationKey(id, kind);
1810: }
1811:
1812: /**
1813: * Deletes a specific key in an annotated filename.
1814: *
1815: * @param filename is the name of the file that was annotated.
1816: * @param key is the key to search for
1817: * @return true, if the database was modified, false otherwise.
1818: * @see org.griphyn.vdl.classes.LFN
1819: */
1820: public boolean deleteAnnotationFilename(String filename, String key)
1821: throws SQLException, IllegalArgumentException {
1822: int kind = CLASS_FILENAME;
1823:
1824: // obtain possible existing anno_lfn id
1825: long id = getAnnotationIdFilename(filename, key);
1826:
1827: // no such key, if the id does not exist
1828: return deleteAnnotationKey(id, kind);
1829: }
1830:
1831: /**
1832: * Inserts a tuple into the correct type-table for annotations.
1833: *
1834: * @param id is the annotation id for which to insert.
1835: * @param annotation is the annotation to insert. Only the type
1836: * and value will be taken, as the key was inserted elsewhere.
1837: * @return true, if the database was modified, false otherwise.
1838: * @exception SQLException if something during the database access
1839: * went awry.
1840: */
1841: private boolean saveAnnotationValue(long id, Tuple annotation)
1842: throws SQLException {
1843: Logging.instance().log("xaction", 1, "START save anno_<value>");
1844:
1845: PreparedStatement ps = null;
1846: if (annotation instanceof TupleBoolean) {
1847: ps = m_dbdriver.getPreparedStatement("stmt.save.anno_bool");
1848: ps.setBoolean(2, ((Boolean) annotation.getValue())
1849: .booleanValue());
1850: } else if (annotation instanceof TupleDate) {
1851: ps = m_dbdriver.getPreparedStatement("stmt.save.anno_date");
1852: ps.setTimestamp(2, ((Timestamp) annotation.getValue()));
1853: } else if (annotation instanceof TupleFloat) {
1854: ps = m_dbdriver
1855: .getPreparedStatement("stmt.save.anno_float");
1856: ps.setDouble(2, ((Double) annotation.getValue())
1857: .doubleValue());
1858: } else if (annotation instanceof TupleInteger) {
1859: ps = m_dbdriver.getPreparedStatement("stmt.save.anno_int");
1860: ps.setLong(2, ((Long) annotation.getValue()).longValue());
1861: } else if (annotation instanceof TupleString) {
1862: ps = m_dbdriver.getPreparedStatement("stmt.save.anno_text");
1863: // ps.setString( 2, ((String) annotation.getValue()) );
1864: String value = (String) annotation.getValue();
1865: ps.setCharacterStream(2, new StringReader(value), value
1866: .length());
1867: } else
1868: throw new SQLException("Don't know the tuple type");
1869:
1870: if (m_dbdriver.preferString())
1871: ps.setString(1, Long.toString(id));
1872: else
1873: ps.setLong(1, id);
1874:
1875: Logging.instance().log("chunk", 2, "INSERT INTO anno_<value>");
1876: int rc = ps.executeUpdate();
1877: Logging.instance().log("xaction", 1, "FINAL save anno_<value>");
1878: return (rc != 0);
1879: }
1880:
1881: /**
1882: * Annotates a transformation with a tuple.
1883: *
1884: * @param fqdi is the FQDI to annotate
1885: * @param annotation is the value to place
1886: * @param overwrite is a predicate on replace or maintain.
1887: * @return the insertion id, or -1, if the database was untouched
1888: * @see org.griphyn.vdl.classes.Transformation
1889: */
1890: public long saveAnnotationTransformation(String fqdi,
1891: Tuple annotation, boolean overwrite) throws SQLException,
1892: IllegalArgumentException {
1893: // split FQDI
1894: String[] names = Separator.split(fqdi); // may throw IAE
1895:
1896: // obtain DID for FQDI
1897: Long did = getSpecificDefinitionId(names[0], names[1],
1898: names[2], Definition.TRANSFORMATION);
1899: if (did == null)
1900: throw new SQLException("Unknown TR " + fqdi);
1901:
1902: // obtain possible existing anno_tr id
1903: long id = getAnnotationIdTransformation(did.longValue(),
1904: annotation.getKey());
1905:
1906: // insert into anno_tr with new id, if id does not exist
1907: if (id == -1) {
1908: // obtain new id
1909: id = m_dbdriver.sequence1("anno_id_seq");
1910:
1911: Logging.instance().log("xaction", 1, "START save anno_tr");
1912: PreparedStatement ps = m_dbdriver
1913: .getPreparedStatement("stmt.save.anno_tr");
1914:
1915: int i = 1;
1916: longOrNull(ps, i++, id);
1917:
1918: if (m_dbdriver.preferString())
1919: ps.setString(i++, did.toString());
1920: else
1921: ps.setLong(i++, did.longValue());
1922: ps.setString(i++, makeNotNull(annotation.getKey()));
1923:
1924: // save prepared values
1925: Logging.instance().log("chunk", 2, "INSERT INTO anno_tr");
1926: try {
1927: int rc = ps.executeUpdate();
1928: if (id == -1)
1929: id = m_dbdriver.sequence2(ps, "anno_id_seq", 1);
1930: } catch (SQLException e) {
1931: Logging.instance().log(
1932: "app",
1933: 0,
1934: "While inserting into anno_tr: "
1935: + e.toString().trim());
1936: // rollback in saveInvocation()
1937: m_dbdriver.cancelPreparedStatement("stmt.save.anno_tr");
1938: throw e; // re-throw
1939: }
1940: Logging.instance().log("xaction", 1,
1941: "FINAL save anno_tr: ID=" + id);
1942: } else {
1943: // id does exist, nothing to do in anno_tr
1944: }
1945:
1946: // delete before insert if overwrite mode
1947: if (overwrite)
1948: deleteAnnotationValue(id, annotation);
1949: return (saveAnnotationValue(id, annotation) ? id : -1);
1950: }
1951:
1952: /**
1953: * Annotates a derivation with a tuple.
1954: *
1955: * @param fqdi is the FQDI to annotate
1956: * @param annotation is the value to place
1957: * @param overwrite is a predicate on replace or maintain.
1958: * @return the insertion id, or -1, if the database was untouched
1959: * @see org.griphyn.vdl.classes.Derivation
1960: */
1961: public long saveAnnotationDerivation(String fqdi, Tuple annotation,
1962: boolean overwrite) throws SQLException,
1963: IllegalArgumentException {
1964: // split FQDI
1965: String[] names = Separator.split(fqdi); // may throw IAE
1966:
1967: // obtain DID for FQDI
1968: Long did = getSpecificDefinitionId(names[0], names[1],
1969: names[2], Definition.DERIVATION);
1970: if (did == null)
1971: throw new SQLException("Unknown DV " + fqdi);
1972:
1973: // obtain possible existing anno_dv id
1974: long id = getAnnotationIdDerivation(did.longValue(), annotation
1975: .getKey());
1976:
1977: // insert into anno_dv with new id, if id does not exist
1978: if (id == -1) {
1979: // obtain new id
1980: id = m_dbdriver.sequence1("anno_id_seq");
1981:
1982: Logging.instance().log("xaction", 1, "START save anno_dv");
1983: PreparedStatement ps = m_dbdriver
1984: .getPreparedStatement("stmt.save.anno_dv");
1985: int i = 1;
1986: longOrNull(ps, i++, id);
1987: if (m_dbdriver.preferString())
1988: ps.setString(i++, did.toString());
1989: else
1990: ps.setLong(i++, did.longValue());
1991: ps.setString(i++, makeNotNull(annotation.getKey()));
1992:
1993: // save prepared values
1994: Logging.instance().log("chunk", 2, "INSERT INTO anno_dv");
1995: try {
1996: int rc = ps.executeUpdate();
1997: if (id == -1)
1998: id = m_dbdriver.sequence2(ps, "anno_id_seq", 1);
1999: } catch (SQLException e) {
2000: Logging.instance().log(
2001: "app",
2002: 0,
2003: "While inserting into anno_tr: "
2004: + e.toString().trim());
2005: // rollback in saveInvocation()
2006: m_dbdriver.cancelPreparedStatement("stmt.save.anno_tr");
2007: throw e; // re-throw
2008: }
2009: Logging.instance().log("xaction", 1,
2010: "FINAL save anno_dv: ID=" + id);
2011: } else {
2012: // id does exist, nothing to do in anno_tr
2013: }
2014:
2015: // delete before insert if overwrite mode
2016: if (overwrite)
2017: deleteAnnotationValue(id, annotation);
2018: return (saveAnnotationValue(id, annotation) ? id : -1);
2019: }
2020:
2021: /**
2022: * Annotates a transformation argument with a tuple.
2023: *
2024: * @param fqdi is the FQDI to annotate
2025: * @param formalname is the name of the formal argument to annotoate.
2026: * @param annotation is the value to place
2027: * @param overwrite is a predicate on replace or maintain.
2028: * @return the insertion id, or -1, if the database was untouched
2029: * @see org.griphyn.vdl.classes.Declare
2030: */
2031: public long saveAnnotationDeclare(String fqdi, String formalname,
2032: Tuple annotation, boolean overwrite) throws SQLException,
2033: IllegalArgumentException {
2034: // split FQDI
2035: String[] names = Separator.split(fqdi); // may throw IAE
2036:
2037: // obtain DID for FQDI
2038: Long did = getSpecificDefinitionId(names[0], names[1],
2039: names[2], Definition.TRANSFORMATION);
2040: if (did == null)
2041: throw new SQLException("Unknown TR " + fqdi);
2042:
2043: Transformation tr = (Transformation) loadDefinition(did
2044: .longValue());
2045: boolean found = false;
2046: for (Iterator i = tr.iterateDeclare(); i.hasNext();) {
2047: String arg = ((Declare) i.next()).getName();
2048: if (arg.equals(formalname)) {
2049: found = true;
2050: break;
2051: }
2052: }
2053:
2054: if (!found)
2055: throw new SQLException("Invalid argument " + formalname
2056: + " for TR " + fqdi);
2057:
2058: // obtain possible existing anno_farg id
2059: long id = getAnnotationIdDeclare(did.longValue(), formalname,
2060: annotation.getKey());
2061:
2062: // insert into anno_dv with new id, if id does not exist
2063: if (id == -1) {
2064: // obtain new id
2065: id = m_dbdriver.sequence1("anno_id_seq");
2066:
2067: Logging.instance()
2068: .log("xaction", 1, "START save anno_targ");
2069: PreparedStatement ps = m_dbdriver
2070: .getPreparedStatement("stmt.save.anno_targ");
2071: int i = 1;
2072: longOrNull(ps, i++, id);
2073: if (m_dbdriver.preferString())
2074: ps.setString(i++, did.toString());
2075: else
2076: ps.setLong(i++, did.longValue());
2077: ps.setString(i++, makeNotNull(formalname));
2078: ps.setString(i++, makeNotNull(annotation.getKey()));
2079:
2080: // save prepared values
2081: Logging.instance().log("chunk", 2, "INSERT INTO anno_targ");
2082: try {
2083: int rc = ps.executeUpdate();
2084: if (id == -1)
2085: id = m_dbdriver.sequence2(ps, "anno_id_seq", 1);
2086: } catch (SQLException e) {
2087: Logging.instance().log(
2088: "app",
2089: 0,
2090: "While inserting into anno_targ: "
2091: + e.toString().trim());
2092: // rollback in saveInvocation()
2093: m_dbdriver
2094: .cancelPreparedStatement("stmt.save.anno_targ");
2095: throw e; // re-throw
2096: }
2097: Logging.instance().log("xaction", 1,
2098: "FINAL save anno_targ: ID=" + id);
2099: } else {
2100: // id does exist, nothing to do in anno_targ
2101: }
2102:
2103: // delete before insert if overwrite mode
2104: if (overwrite)
2105: deleteAnnotationValue(id, annotation);
2106: return (saveAnnotationValue(id, annotation) ? id : -1);
2107: }
2108:
2109: /**
2110: * Annotates a transformation call with a tuple.
2111: *
2112: * @param fqdi is the FQDI to annotate
2113: * @param index is the number of the call to annotate.
2114: * @param annotation is the value to place
2115: * @param overwrite is a predicate on replace or maintain.
2116: * @return the insertion id, or -1, if the database was untouched
2117: * @see org.griphyn.vdl.classes.Call
2118: */
2119: public long saveAnnotationCall(String fqdi, int index,
2120: Tuple annotation, boolean overwrite) throws SQLException,
2121: IllegalArgumentException {
2122: // split FQDI
2123: String[] names = Separator.split(fqdi); // may throw IAE
2124:
2125: // obtain DID for FQDI
2126: Long did = getSpecificDefinitionId(names[0], names[1],
2127: names[2], Definition.TRANSFORMATION);
2128: if (did == null)
2129: throw new SQLException("Unknown TR " + fqdi);
2130:
2131: Transformation tr = (Transformation) loadDefinition(did
2132: .longValue());
2133: if (index <= 0 || tr.getCallCount() < index)
2134: throw new SQLException("Invalid position " + index
2135: + " for TR " + fqdi);
2136:
2137: // obtain possible existing anno_call id
2138: long id = getAnnotationIdCall(did.longValue(), index,
2139: annotation.getKey());
2140:
2141: // insert into anno_dv with new id, if id does not exist
2142: if (id == -1) {
2143: // obtain new id
2144: id = m_dbdriver.sequence1("anno_id_seq");
2145:
2146: Logging.instance()
2147: .log("xaction", 1, "START save anno_call");
2148: PreparedStatement ps = m_dbdriver
2149: .getPreparedStatement("stmt.save.anno_call");
2150: int i = 1;
2151: longOrNull(ps, i++, id);
2152:
2153: if (m_dbdriver.preferString()) {
2154: ps.setString(i++, did.toString());
2155: ps.setString(i++, Integer.toString(index));
2156: } else {
2157: ps.setLong(i++, did.longValue());
2158: ps.setInt(i++, index);
2159: }
2160: ps.setString(i++, makeNotNull(annotation.getKey()));
2161:
2162: // save prepared values
2163: Logging.instance().log("chunk", 2, "INSERT INTO anno_call");
2164: try {
2165: int rc = ps.executeUpdate();
2166: if (id == -1)
2167: id = m_dbdriver.sequence2(ps, "anno_id_seq", 1);
2168: } catch (SQLException e) {
2169: Logging.instance().log(
2170: "app",
2171: 0,
2172: "While inserting into anno_call: "
2173: + e.toString().trim());
2174: // rollback in saveInvocation()
2175: m_dbdriver
2176: .cancelPreparedStatement("stmt.save.anno_call");
2177: throw e; // re-throw
2178: }
2179: Logging.instance().log("xaction", 1,
2180: "FINAL save anno_targ: ID=" + id);
2181: } else {
2182: // id does exist, nothing to do in anno_targ
2183: }
2184:
2185: // delete before insert if overwrite mode
2186: if (overwrite)
2187: deleteAnnotationValue(id, annotation);
2188: return (saveAnnotationValue(id, annotation) ? id : -1);
2189: }
2190:
2191: /**
2192: * Annotates a logical filename with a tuple.
2193: *
2194: * @param filename is the FQDI to annotate
2195: * @param annotation is the value to place
2196: * @param overwrite is a predicate on replace or maintain.
2197: * @return the insertion id, or -1, if the database was untouched
2198: * @see org.griphyn.vdl.classes.LFN
2199: */
2200: public long saveAnnotationFilename(String filename,
2201: Tuple annotation, boolean overwrite) throws SQLException,
2202: IllegalArgumentException {
2203: // obtain possible existing anno_lfn id
2204: long id = getAnnotationIdFilename(filename, annotation.getKey());
2205:
2206: // insert into anno_dv with new id, if id does not exist
2207: if (id == -1) {
2208: // obtain new id
2209: id = m_dbdriver.sequence1("anno_id_seq");
2210:
2211: Logging.instance().log("xaction", 1, "START save anno_lfn");
2212: PreparedStatement ps = m_dbdriver
2213: .getPreparedStatement("stmt.save.anno_lfn");
2214: int i = 1;
2215: longOrNull(ps, i++, id);
2216: ps.setString(i++, makeNotNull(filename));
2217: ps.setString(i++, makeNotNull(annotation.getKey()));
2218:
2219: // save prepared values
2220: Logging.instance().log("chunk", 2, "INSERT INTO anno_lfn");
2221: try {
2222: int rc = ps.executeUpdate();
2223: if (id == -1)
2224: id = m_dbdriver.sequence2(ps, "anno_id_seq", 1);
2225: } catch (SQLException e) {
2226: Logging.instance().log(
2227: "app",
2228: 0,
2229: "While inserting into anno_lfn: "
2230: + e.toString().trim());
2231: // rollback in saveInvocation()
2232: m_dbdriver
2233: .cancelPreparedStatement("stmt.save.anno_lfn");
2234: throw e; // re-throw
2235: }
2236: Logging.instance().log("xaction", 1,
2237: "FINAL save anno_lfn: ID=" + id);
2238: } else {
2239: // id does exist, nothing to do in anno_targ
2240: }
2241:
2242: // delete before insert if overwrite mode
2243: if (overwrite)
2244: deleteAnnotationValue(id, annotation);
2245: return (saveAnnotationValue(id, annotation) ? id : -1);
2246: }
2247:
2248: /**
2249: * Annotates any of the annotatable classes with the specified tuple.
2250: * This is an interface method to the various class-specific methods.
2251: *
2252: * @param primary is the primary object specifier for the class.
2253: * According to the type, this is either the FQDI, or the filename.
2254: * @param secondary is a helper argument for annotations to calls
2255: * and formal arguments, and should be null for all other classes.
2256: * For calls, the argument must be packed into {@link java.lang.Integer}.
2257: * @param kind defines the kind/class of object to annotate.
2258: * @param annotation is the value to place into the class.
2259: * @param overwrite is a predicate on replace or maintain.
2260: * @return the insertion id, or -1, if the database was untouched
2261: * @see #saveAnnotationTransformation( String, Tuple, boolean )
2262: * @see #saveAnnotationDerivation( String, Tuple, boolean )
2263: * @see #saveAnnotationCall( String, int, Tuple, boolean )
2264: * @see #saveAnnotationDeclare( String, String, Tuple, boolean )
2265: * @see #saveAnnotationFilename( String, Tuple, boolean )
2266: */
2267: public long saveAnnotation(String primary, Object secondary,
2268: int kind, Tuple annotation, boolean overwrite)
2269: throws SQLException, IllegalArgumentException {
2270: long result = -1;
2271: switch (kind) {
2272: case CLASS_TRANSFORMATION:
2273: result = saveAnnotationTransformation(primary, annotation,
2274: overwrite);
2275: break;
2276: case CLASS_DERIVATION:
2277: result = saveAnnotationDerivation(primary, annotation,
2278: overwrite);
2279: break;
2280: case CLASS_CALL:
2281: // may throw ClassCastException
2282: result = saveAnnotationCall(primary, ((Integer) secondary)
2283: .intValue(), annotation, overwrite);
2284: break;
2285: case CLASS_DECLARE:
2286: // may throw ClassCastException
2287: result = saveAnnotationDeclare(primary,
2288: ((String) secondary), annotation, overwrite);
2289: break;
2290: case CLASS_FILENAME:
2291: result = saveAnnotationFilename(primary, annotation,
2292: overwrite);
2293: break;
2294: default:
2295: throw new IllegalArgumentException("The class kind=" + kind
2296: + " cannot be annotated");
2297: }
2298: if (result != -1)
2299: if (!m_deferDeleteCommit)
2300: m_dbdriver.commit();
2301:
2302: return result;
2303: }
2304:
2305: /**
2306: * Obtains the value at a specific id from the boolean annotations.
2307: *
2308: * @param id is the annotation id
2309: * @param key is used to create the tuple
2310: * @return null if not found, or a valid tuple otherwise.
2311: */
2312: private TupleBoolean loadAnnotationBoolean(long id, String key)
2313: throws SQLException {
2314: TupleBoolean result = null;
2315:
2316: Logging.instance().log("xaction", 1, "START select anno_bool");
2317: PreparedStatement ps = m_dbdriver
2318: .getPreparedStatement("stmt.select.anno_bool");
2319: if (m_dbdriver.preferString())
2320: ps.setString(1, Long.toString(id));
2321: else
2322: ps.setLong(1, id);
2323:
2324: Logging.instance().log("chunk", 2,
2325: "SELECT value FROM anno_bool");
2326: ResultSet rs = ps.executeQuery();
2327: if (rs.next()) {
2328: boolean value = rs.getBoolean(1);
2329: result = new TupleBoolean(key, value);
2330: }
2331: rs.close();
2332:
2333: Logging.instance().log("xaction", 1, "FINAL select anno_bool");
2334: return result;
2335: }
2336:
2337: /**
2338: * Obtains the value at a specific id from the integer annotations.
2339: *
2340: * @param id is the annotation id
2341: * @param key is used to create the tuple
2342: * @return null if not found, or a valid tuple otherwise.
2343: */
2344: private TupleInteger loadAnnotationInteger(long id, String key)
2345: throws SQLException {
2346: TupleInteger result = null;
2347:
2348: Logging.instance().log("xaction", 1, "START select anno_int");
2349: PreparedStatement ps = m_dbdriver
2350: .getPreparedStatement("stmt.select.anno_int");
2351: if (m_dbdriver.preferString())
2352: ps.setString(1, Long.toString(id));
2353: else
2354: ps.setLong(1, id);
2355:
2356: Logging.instance()
2357: .log("chunk", 2, "SELECT value FROM anno_int");
2358: ResultSet rs = ps.executeQuery();
2359: if (rs.next()) {
2360: long value = rs.getLong(1);
2361: result = new TupleInteger(key, value);
2362: }
2363: rs.close();
2364:
2365: Logging.instance().log("xaction", 1, "FINAL select anno_int");
2366: return result;
2367: }
2368:
2369: /**
2370: * Obtains the value at a specific id from the float annotations.
2371: *
2372: * @param id is the annotation id
2373: * @param key is used to create the tuple
2374: * @return null if not found, or a valid tuple otherwise.
2375: */
2376: private TupleFloat loadAnnotationFloat(long id, String key)
2377: throws SQLException {
2378: TupleFloat result = null;
2379:
2380: Logging.instance().log("xaction", 1, "START select anno_float");
2381: PreparedStatement ps = m_dbdriver
2382: .getPreparedStatement("stmt.select.anno_float");
2383: if (m_dbdriver.preferString())
2384: ps.setString(1, Long.toString(id));
2385: else
2386: ps.setLong(1, id);
2387:
2388: Logging.instance().log("chunk", 2,
2389: "SELECT value FROM anno_float");
2390: ResultSet rs = ps.executeQuery();
2391: if (rs.next()) {
2392: double value = rs.getDouble(1);
2393: result = new TupleFloat(key, value);
2394: }
2395: rs.close();
2396:
2397: Logging.instance().log("xaction", 1, "FINAL select anno_float");
2398: return result;
2399: }
2400:
2401: /**
2402: * Obtains the value at a specific id from the date annotations.
2403: *
2404: * @param id is the annotation id
2405: * @param key is used to create the tuple
2406: * @return null if not found, or a valid tuple otherwise.
2407: */
2408: private TupleDate loadAnnotationDate(long id, String key)
2409: throws SQLException {
2410: TupleDate result = null;
2411:
2412: Logging.instance().log("xaction", 1, "START select anno_date");
2413: PreparedStatement ps = m_dbdriver
2414: .getPreparedStatement("stmt.select.anno_date");
2415: if (m_dbdriver.preferString())
2416: ps.setString(1, Long.toString(id));
2417: else
2418: ps.setLong(1, id);
2419:
2420: Logging.instance().log("chunk", 2,
2421: "SELECT value FROM anno_date");
2422: ResultSet rs = ps.executeQuery();
2423: if (rs.next()) {
2424: java.sql.Timestamp value = rs.getTimestamp(1);
2425: result = new TupleDate(key, value);
2426: }
2427: rs.close();
2428:
2429: Logging.instance().log("xaction", 1, "FINAL select anno_date");
2430: return result;
2431: }
2432:
2433: /**
2434: * Obtains the value at a specific id from the string annotations.
2435: *
2436: * @param id is the annotation id
2437: * @param key is used to create the tuple
2438: * @return null if not found, or a valid tuple otherwise.
2439: */
2440: private TupleString loadAnnotationString(long id, String key)
2441: throws SQLException {
2442: TupleString result = null;
2443:
2444: Logging.instance().log("xaction", 1, "START select anno_text");
2445: PreparedStatement ps = m_dbdriver
2446: .getPreparedStatement("stmt.select.anno_text");
2447: if (m_dbdriver.preferString())
2448: ps.setString(1, Long.toString(id));
2449: else
2450: ps.setLong(1, id);
2451:
2452: Logging.instance().log("chunk", 2,
2453: "SELECT value FROM anno_text");
2454: ResultSet rs = ps.executeQuery();
2455: if (rs.next()) {
2456: Reader r = rs.getCharacterStream(1);
2457: StringBuffer temp = new StringBuffer(128);
2458: try {
2459: int ch;
2460: while ((ch = r.read()) >= 0)
2461: temp.append((char) ch);
2462: } catch (IOException ioe) {
2463: throw new SQLException(ioe.getMessage());
2464: }
2465: result = new TupleString(key, temp.toString());
2466: }
2467: rs.close();
2468:
2469: Logging.instance().log("xaction", 1, "FINAL select anno_text");
2470: return result;
2471: }
2472:
2473: /**
2474: * Tries to retrieve a tuple value from its annotation id by
2475: * walking over all tables, most likely one first. This is an
2476: * internal function helping to keep common code common.
2477: *
2478: * @param id is the annotation id to search for
2479: * @param key is the key for tuple creation.
2480: * @return null, if the id was -1 (no such id), or if nothing
2481: * was found.
2482: */
2483: private Tuple loadAnnotationFinal(long id, String key)
2484: throws SQLException {
2485: Tuple result = null;
2486: if (id != -1) {
2487: // order by likelyhood
2488: result = loadAnnotationString(id, key);
2489: if (result == null)
2490: result = loadAnnotationInteger(id, key);
2491: if (result == null)
2492: result = loadAnnotationFloat(id, key);
2493: if (result == null)
2494: result = loadAnnotationDate(id, key);
2495: if (result == null)
2496: result = loadAnnotationBoolean(id, key);
2497: }
2498: return result;
2499: }
2500:
2501: /**
2502: * Obtains the value to a specific key in an annotated transformation.
2503: *
2504: * @param fqdi is the FQDI of the transformation
2505: * @param key is the key to search for
2506: * @return the annotated value, or null if not found.
2507: * @see org.griphyn.vdl.classes.Transformation
2508: */
2509: public Tuple loadAnnotationTransformation(String fqdi, String key)
2510: throws SQLException, IllegalArgumentException {
2511: // split FQDI
2512: String[] names = Separator.split(fqdi); // may throw IAE
2513:
2514: // obtain DID for FQDI
2515: Long did = getSpecificDefinitionId(names[0], names[1],
2516: names[2], Definition.TRANSFORMATION);
2517: if (did == null)
2518: throw new SQLException("Unknown TR " + fqdi);
2519:
2520: // obtain possible existing anno_tr id
2521: long id = getAnnotationIdTransformation(did.longValue(), key);
2522:
2523: // no such key, if the id is -1, handled by finalizer
2524: return loadAnnotationFinal(id, key);
2525: }
2526:
2527: /**
2528: * Obtains the value to a specific key in an annotated derivation.
2529: *
2530: * @param fqdi is the FQDI of the derivation
2531: * @param key is the key to search for
2532: * @return the annotated value, or null if not found.
2533: * @see org.griphyn.vdl.classes.Derivation
2534: */
2535: public Tuple loadAnnotationDerivation(String fqdi, String key)
2536: throws SQLException, IllegalArgumentException {
2537: // split FQDI
2538: String[] names = Separator.split(fqdi); // may throw IAE
2539:
2540: // obtain DID for FQDI
2541: Long did = getSpecificDefinitionId(names[0], names[1],
2542: names[2], Definition.DERIVATION);
2543: if (did == null)
2544: throw new SQLException("Unknown DV " + fqdi);
2545:
2546: // obtain possible existing anno_dv id
2547: long id = getAnnotationIdDerivation(did.longValue(), key);
2548:
2549: // no such key, if the id does not exist
2550: return loadAnnotationFinal(id, key);
2551: }
2552:
2553: /**
2554: * Obtains the value to a specific key in an annotated formal argument.
2555: *
2556: * @param fqdi is the FQDI of the transformation
2557: * @param farg is the name of the formal argument
2558: * @param key is the key to search for
2559: * @return the annotated value, or null if not found
2560: * @see org.griphyn.vdl.classes.Declare
2561: */
2562: public Tuple loadAnnotationDeclare(String fqdi, String farg,
2563: String key) throws SQLException, IllegalArgumentException {
2564: // split FQDI
2565: String[] names = Separator.split(fqdi); // may throw IAE
2566:
2567: // obtain DID for FQDI
2568: Long did = getSpecificDefinitionId(names[0], names[1],
2569: names[2], Definition.TRANSFORMATION);
2570: if (did == null)
2571: throw new SQLException("Unknown TR " + fqdi);
2572:
2573: // obtain possible existing anno_call id
2574: long id = getAnnotationIdDeclare(did.longValue(), farg, key);
2575:
2576: // no such key, if the id does not exist
2577: return loadAnnotationFinal(id, key);
2578: }
2579:
2580: /**
2581: * Obtains the value to a specific key for a call statement.
2582: *
2583: * @param fqdi is the FQDI of the transformation
2584: * @param index is the number of the call to annotate.
2585: * @param key is the key to search for
2586: * @return the annotated value, or null if not found
2587: * @see org.griphyn.vdl.classes.Call
2588: */
2589: public Tuple loadAnnotationCall(String fqdi, int index, String key)
2590: throws SQLException, IllegalArgumentException {
2591: // split FQDI
2592: String[] names = Separator.split(fqdi); // may throw IAE
2593:
2594: // obtain DID for FQDI
2595: Long did = getSpecificDefinitionId(names[0], names[1],
2596: names[2], Definition.TRANSFORMATION);
2597: if (did == null)
2598: throw new SQLException("Unknown TR " + fqdi);
2599:
2600: // obtain possible existing anno_call id
2601: long id = getAnnotationIdCall(did.longValue(), index, key);
2602:
2603: // no such key, if the id does not exist
2604: return loadAnnotationFinal(id, key);
2605: }
2606:
2607: /**
2608: * Obtains the value to a specific key in an annotated filename.
2609: *
2610: * @param filename is the name of the file that was annotated.
2611: * @param key is the key to search for
2612: * @return the annotated value, or null if not found.
2613: * @see org.griphyn.vdl.classes.LFN
2614: */
2615: public Tuple loadAnnotationFilename(String filename, String key)
2616: throws SQLException, IllegalArgumentException {
2617: // obtain possible existing anno_lfn id
2618: long id = getAnnotationIdFilename(filename, key);
2619:
2620: // no such key, if the id does not exist
2621: return loadAnnotationFinal(id, key);
2622: }
2623:
2624: /**
2625: * Retrieves a specific annotation from an annotatable classes with
2626: * the specified tuple. This is an interface method to the various
2627: * class-specific methods.
2628: *
2629: * @param primary is the primary object specifier for the class.
2630: * According to the type, this is either the FQDI, or the filename.
2631: * @param secondary is a helper argument for annotations to calls
2632: * and formal arguments, and should be null for all other classes.
2633: * For calls, the argument must be packed into {@link java.lang.Integer}.
2634: * @param kind defines the kind/class of object to annotate.
2635: * @param key is the key to look for.
2636: * @return null if not found, otherwise the annotation tuple.
2637: * @see #loadAnnotationTransformation( String, String )
2638: * @see #loadAnnotationDerivation( String, String )
2639: * @see #loadAnnotationCall( String, int, String )
2640: * @see #loadAnnotationDeclare( String, String, String )
2641: * @see #loadAnnotationFilename( String, String )
2642: */
2643: public Tuple loadAnnotation(String primary, Object secondary,
2644: int kind, String key) throws SQLException,
2645: IllegalArgumentException {
2646: Tuple result = null;
2647: switch (kind) {
2648: case CLASS_TRANSFORMATION:
2649: result = loadAnnotationTransformation(primary, key);
2650: break;
2651: case CLASS_DERIVATION:
2652: result = loadAnnotationDerivation(primary, key);
2653: break;
2654: case CLASS_CALL:
2655: // may throw ClassCastException
2656: result = loadAnnotationCall(primary, ((Integer) secondary)
2657: .intValue(), key);
2658: break;
2659: case CLASS_DECLARE:
2660: // may throw ClassCastException
2661: result = loadAnnotationDeclare(primary,
2662: ((String) secondary), key);
2663: break;
2664: case CLASS_FILENAME:
2665: result = loadAnnotationFilename(primary, key);
2666: break;
2667: default:
2668: throw new IllegalArgumentException("The class kind=" + kind
2669: + " cannot be annotated");
2670: }
2671:
2672: return result;
2673: }
2674:
2675: /**
2676: * Lists all annotations for a transformation.
2677: *
2678: * @param fqdi is the FQDI of the transformation
2679: * @return a list of tuples, which may be empty.
2680: * @see org.griphyn.vdl.classes.Transformation
2681: */
2682: public java.util.List loadAnnotationTransformation(String fqdi)
2683: throws SQLException, IllegalArgumentException {
2684: java.util.List result = new java.util.ArrayList();
2685:
2686: // split FQDI
2687: String[] names = Separator.split(fqdi); // may throw IAE
2688:
2689: // obtain DID for FQDI
2690: Long did = getSpecificDefinitionId(names[0], names[1],
2691: names[2], Definition.TRANSFORMATION);
2692: if (did == null)
2693: throw new SQLException("Unknown TR " + fqdi);
2694:
2695: // obtain all anno_tr ids
2696: Logging.instance().log("xaction", 1, "START select anno_tr2");
2697: int i = 1;
2698: PreparedStatement ps = m_dbdriver
2699: .getPreparedStatement("stmt.select.anno_tr2");
2700: if (m_dbdriver.preferString())
2701: ps.setString(i++, did.toString());
2702: else
2703: ps.setLong(i++, did.longValue());
2704:
2705: Logging.instance().log("chunk", 2, "SELECT id FROM anno_tr");
2706: ResultSet rs = ps.executeQuery();
2707: while (rs.next()) {
2708: Tuple temp = loadAnnotationFinal(rs.getLong(1), rs
2709: .getString(2));
2710: if (temp != null)
2711: result.add(temp);
2712: }
2713: rs.close();
2714:
2715: Logging.instance().log("xaction", 1, "FINAL select anno_tr2");
2716: return result;
2717: }
2718:
2719: /**
2720: * Lists all annotations for a derivation.
2721: *
2722: * @param fqdi is the FQDI of the derivation
2723: * @return a list of tuples, which may be empty.
2724: * @see org.griphyn.vdl.classes.Derivation
2725: */
2726: public java.util.List loadAnnotationDerivation(String fqdi)
2727: throws SQLException, IllegalArgumentException {
2728: java.util.List result = new java.util.ArrayList();
2729:
2730: // split FQDI
2731: String[] names = Separator.split(fqdi); // may throw IAE
2732:
2733: // obtain DID for FQDI
2734: Long did = getSpecificDefinitionId(names[0], names[1],
2735: names[2], Definition.DERIVATION);
2736: if (did == null)
2737: throw new SQLException("Unknown DV " + fqdi);
2738:
2739: // obtain all anno_tr ids
2740: Logging.instance().log("xaction", 1, "START select anno_dv2");
2741: int i = 1;
2742: PreparedStatement ps = m_dbdriver
2743: .getPreparedStatement("stmt.select.anno_dv2");
2744: if (m_dbdriver.preferString())
2745: ps.setString(i++, did.toString());
2746: else
2747: ps.setLong(i++, did.longValue());
2748:
2749: Logging.instance().log("chunk", 2, "SELECT id FROM anno_dv");
2750: ResultSet rs = ps.executeQuery();
2751: while (rs.next()) {
2752: Tuple temp = loadAnnotationFinal(rs.getLong(1), rs
2753: .getString(2));
2754: if (temp != null)
2755: result.add(temp);
2756: }
2757: rs.close();
2758:
2759: Logging.instance().log("xaction", 1, "FINAL select anno_dv2");
2760: return result;
2761: }
2762:
2763: /**
2764: * Lists all annotations for a formal argument.
2765: *
2766: * @param fqdi is the FQDI of the transformation
2767: * @param farg is the name of the formal argument
2768: * @return a list of tuples, which may be empty.
2769: * @see org.griphyn.vdl.classes.Declare
2770: */
2771: public java.util.List loadAnnotationDeclare(String fqdi, String farg)
2772: throws SQLException, IllegalArgumentException {
2773: java.util.List result = new java.util.ArrayList();
2774:
2775: // split FQDI
2776: String[] names = Separator.split(fqdi); // may throw IAE
2777:
2778: // obtain DID for FQDI
2779: Long did = getSpecificDefinitionId(names[0], names[1],
2780: names[2], Definition.TRANSFORMATION);
2781: if (did == null)
2782: throw new SQLException("Unknown TR " + fqdi);
2783:
2784: // obtain all anno_tr ids
2785: Logging.instance().log("xaction", 1, "START select anno_targ2");
2786: int i = 1;
2787: PreparedStatement ps = m_dbdriver
2788: .getPreparedStatement("stmt.select.anno_targ2");
2789: if (m_dbdriver.preferString())
2790: ps.setString(i++, did.toString());
2791: else
2792: ps.setLong(i++, did.longValue());
2793: ps.setString(i++, farg);
2794:
2795: Logging.instance().log("chunk", 2, "SELECT id FROM anno_targ");
2796: ResultSet rs = ps.executeQuery();
2797: while (rs.next()) {
2798: Tuple temp = loadAnnotationFinal(rs.getLong(1), rs
2799: .getString(2));
2800: if (temp != null)
2801: result.add(temp);
2802: }
2803: rs.close();
2804:
2805: Logging.instance().log("xaction", 1, "FINAL select anno_targ2");
2806: return result;
2807: }
2808:
2809: /**
2810: * Lists all annotations for a call statement.
2811: *
2812: * @param fqdi is the FQDI of the transformation
2813: * @param index is the number of the call to annotate.
2814: * @return a list of tuples, which may be empty.
2815: * @see org.griphyn.vdl.classes.Call
2816: */
2817: public java.util.List loadAnnotationCall(String fqdi, int index)
2818: throws SQLException, IllegalArgumentException {
2819: java.util.List result = new java.util.ArrayList();
2820:
2821: // split FQDI
2822: String[] names = Separator.split(fqdi); // may throw IAE
2823:
2824: // obtain DID for FQDI
2825: Long did = getSpecificDefinitionId(names[0], names[1],
2826: names[2], Definition.TRANSFORMATION);
2827: if (did == null)
2828: throw new SQLException("Unknown TR " + fqdi);
2829:
2830: // obtain all anno_tr ids
2831: Logging.instance().log("xaction", 1, "START select anno_call2");
2832: int i = 1;
2833: PreparedStatement ps = m_dbdriver
2834: .getPreparedStatement("stmt.select.anno_call2");
2835: if (m_dbdriver.preferString()) {
2836: ps.setString(i++, did.toString());
2837: ps.setString(i++, Integer.toString(index));
2838: } else {
2839: ps.setLong(i++, did.longValue());
2840: ps.setInt(i++, index);
2841: }
2842:
2843: Logging.instance().log("chunk", 2, "SELECT id FROM anno_call");
2844: ResultSet rs = ps.executeQuery();
2845: while (rs.next()) {
2846: Tuple temp = loadAnnotationFinal(rs.getLong(1), rs
2847: .getString(2));
2848: if (temp != null)
2849: result.add(temp);
2850: }
2851: rs.close();
2852:
2853: Logging.instance().log("xaction", 1, "FINAL select anno_call2");
2854: return result;
2855: }
2856:
2857: /**
2858: * Lists all annotations for a logical filename.
2859: *
2860: * @param filename is the logical filename.
2861: * @return a list of tuples, which may be empty.
2862: * @see org.griphyn.vdl.classes.LFN
2863: */
2864: public java.util.List loadAnnotationFilename(String filename)
2865: throws SQLException, IllegalArgumentException {
2866: java.util.List result = new java.util.ArrayList();
2867:
2868: // obtain all anno_tr ids
2869: Logging.instance().log("xaction", 1, "START select anno_lfn2");
2870: int i = 1;
2871: PreparedStatement ps = m_dbdriver
2872: .getPreparedStatement("stmt.select.anno_lfn2");
2873: ps.setString(i++, filename);
2874:
2875: Logging.instance().log("chunk", 2, "SELECT id FROM anno_lfn");
2876: ResultSet rs = ps.executeQuery();
2877: while (rs.next()) {
2878: Tuple temp = loadAnnotationFinal(rs.getLong(1), rs
2879: .getString(2));
2880: if (temp != null)
2881: result.add(temp);
2882: }
2883: rs.close();
2884:
2885: Logging.instance().log("xaction", 1, "FINAL select anno_lfn2");
2886: return result;
2887: }
2888:
2889: /**
2890: * Retrieves all annotations from an annotatable classes with
2891: * the specified tuple. This is an interface method to the various
2892: * class-specific methods.
2893: *
2894: * @param primary is the primary object specifier for the class.
2895: * According to the type, this is either the FQDI, or the filename.
2896: * @param secondary is a helper argument for annotations to calls
2897: * and formal arguments, and should be null for all other classes.
2898: * For calls, the argument must be packed into {@link java.lang.Integer}.
2899: * @param kind defines the kind/class of object to annotate.
2900: *
2901: * @return null if not found, otherwise the annotation tuple.
2902: * @see #loadAnnotationTransformation( String )
2903: * @see #loadAnnotationDerivation( String )
2904: * @see #loadAnnotationCall( String, int )
2905: * @see #loadAnnotationDeclare( String, String )
2906: * @see #loadAnnotationFilename( String )
2907: */
2908: public java.util.List loadAnnotation(String primary,
2909: Object secondary, int kind) throws SQLException,
2910: IllegalArgumentException {
2911:
2912: switch (kind) {
2913: case CLASS_TRANSFORMATION:
2914: return loadAnnotationTransformation(primary);
2915: case CLASS_DERIVATION:
2916: return loadAnnotationDerivation(primary);
2917: case CLASS_CALL:
2918: // may throw ClassCastException
2919: return loadAnnotationCall(primary, ((Integer) secondary)
2920: .intValue());
2921: case CLASS_DECLARE:
2922: // may throw ClassCastException
2923: return loadAnnotationDeclare(primary, ((String) secondary));
2924: case CLASS_FILENAME:
2925: return loadAnnotationFilename(primary);
2926: default:
2927: throw new IllegalArgumentException("The class kind=" + kind
2928: + " cannot be annotated");
2929: }
2930: }
2931:
2932: /**
2933: * Search for LFNs or Definitions that has certain annotations
2934: *
2935: * @param kind defines the kind/class of object annotated.
2936: * @param arg is used only for TR ARG and TR CALL. For the former
2937: * it is the name of the argument (String), for the latter the position of
2938: * the call (Integer).
2939: * @param tree stores the query tree to query the annotation
2940: * @return a list of LFNs if search for filenames, otherwise a list of
2941: * definitions.
2942: * @exception SQLException if something goes wrong with the database.
2943: * @see org.griphyn.vdl.annotation.QueryTree
2944: */
2945: public java.util.List searchAnnotation(int kind, Object arg,
2946: QueryTree tree) throws SQLException {
2947: java.util.List result = new java.util.ArrayList();
2948:
2949: if (tree == null)
2950: return result;
2951:
2952: String sql = tree.toSQL(kind, arg);
2953: if (sql == null || sql.equals(""))
2954: return result;
2955:
2956: // obtain all anno_tr ids
2957: Logging.instance().log("xaction", 1, "START search annotation");
2958:
2959: // use backdoor, why don't we change this into some nicer name???
2960: ResultSet rs = backdoor(sql);
2961: while (rs.next()) {
2962: if (kind == Annotation.CLASS_FILENAME) {
2963: String fn = rs.getString(1);
2964: result.add(fn);
2965: } else {
2966: Definition d = loadDefinition(rs.getLong(1));
2967: if (d != null)
2968: result.add(d);
2969: }
2970: }
2971: rs.close();
2972:
2973: Logging.instance().log("xaction", 1, "FINAL search annotation");
2974: return result;
2975: }
2976:
2977: /**
2978: * A not very generic method to search annotation (and anything) in
2979: * the database. Selects any rows in one or more colums from one or
2980: * more tables restricted by some condition, possibly ordered.<p>
2981: *
2982: * WARNING: This is a method for internal use only.
2983: *
2984: * @param select is the ordered set of column names to select, or
2985: * simply a one-value list with an asterisk.
2986: * @param table is the name of the table to select from.
2987: * @param where is a collection of column names and values they must equal.
2988: * @param order is an optional ordering string.
2989: * @return something to search for results in.
2990: * @exception SQLException if something goes wrong with the database.
2991: * @see org.griphyn.vdl.dbdriver.DatabaseDriver#select( java.util.List, String, java.util.Map, String )
2992: */
2993: public ResultSet searchAnnotation(java.util.List select,
2994: String table, java.util.Map where, String order)
2995: throws SQLException {
2996: return m_dbdriver.select(select, table, where, order);
2997: }
2998:
2999: /**
3000: * Delete one or more definitions from the backend database. The key
3001: * triple parameters may be wildcards. Wildcards are expressed as
3002: * <code>null</code> value, or have special characters '%' and '_'.
3003: *
3004: * @param namespace namespace
3005: * @param name name
3006: * @param version version
3007: * @param type definition type (TR or DV)
3008: * @return a list of definitions that were deleted.
3009: *
3010: * @see org.griphyn.vdl.classes.Definition#TRANSFORMATION
3011: * @see org.griphyn.vdl.classes.Definition#DERIVATION
3012: */
3013: public java.util.List deleteDefinitionEx(String namespace,
3014: String name, String version, int type) throws SQLException {
3015: java.util.List result = new ArrayList();
3016: Logging.instance()
3017: .log("xaction", 1, "START delete definitions");
3018:
3019: java.util.List idlist = getDefinitionIdEx(namespace, name,
3020: version, type);
3021: if (idlist.size() == 0)
3022: return result;
3023: // postcondition: contains all IDs, count(id)>0, to be deleted
3024:
3025: // save old values
3026: if (!m_deferDeleteCommit) {
3027: // we come from saveDefinition, thus we won't need saved values
3028: for (Iterator i = idlist.iterator(); i.hasNext();) {
3029: Definition d = loadDefinition(((Long) i.next())
3030: .longValue());
3031: if (d != null)
3032: result.add(d);
3033: }
3034: }
3035:
3036: // remove all affected annoations by walking through them
3037: // yuk, this is probably extremely expensive
3038: for (Iterator i = idlist.iterator(); i.hasNext();) {
3039: long id = ((Long) i.next()).longValue();
3040: deleteAnnotationFromDefinition(id);
3041: }
3042:
3043: // list of all statements we need to access
3044: PreparedStatement ps[] = {
3045: this .m_dbdriver
3046: .getPreparedStatement("stmt.delete.lfn_i"),
3047: this .m_dbdriver
3048: .getPreparedStatement("stmt.delete.lfn_o"),
3049: this .m_dbdriver
3050: .getPreparedStatement("stmt.delete.lfn_b"),
3051: this .m_dbdriver.getPreparedStatement("stmt.delete.xml") };
3052:
3053: // prepare and batch all statements
3054: boolean preferString = m_dbdriver.preferString();
3055: for (Iterator i = idlist.iterator(); i.hasNext();) {
3056: long id = ((Long) i.next()).longValue();
3057: for (int j = 0; j < ps.length; ++j) {
3058: if (preferString)
3059: ps[j].setString(1, Long.toString(id));
3060: else
3061: ps[j].setLong(1, id);
3062: ps[j].addBatch();
3063: }
3064: }
3065:
3066: // run all batches
3067: Logging.instance()
3068: .log("xaction", 1, "INTER delete definitions");
3069: for (int j = 0; j < ps.length; ++j) {
3070: int[] status = new int[idlist.size()];
3071: try {
3072: status = ps[j].executeBatch();
3073: } catch (NullPointerException npe) {
3074: Logging.instance().log("app", 1,
3075: "tripped over NPE, ignoring!");
3076: }
3077: }
3078:
3079: Logging.instance()
3080: .log("xaction", 1, "FINAL delete definitions");
3081: if (!m_deferDeleteCommit)
3082: m_dbdriver.commit();
3083: return result;
3084: }
3085:
3086: /**
3087: * Search the database for definitions by ns::name:version triple
3088: * and by type (either Transformation or Derivation). This version
3089: * of the search allows for jokers expressed as null value
3090: *
3091: * @param namespace namespace, null to match any namespace
3092: * @param name name, null to match any name
3093: * @param version version, null to match any version
3094: * @param type type of definition, see below, or -1 as wildcard
3095: * @return a list of Definition items, which may be empty
3096: *
3097: * @see org.griphyn.vdl.classes.Definition#TRANSFORMATION
3098: * @see org.griphyn.vdl.classes.Definition#DERIVATION
3099: * @see #loadDefinition( String, String, String, int )
3100: */
3101: public java.util.List searchDefinitionEx(String namespace,
3102: String name, String version, int type) throws SQLException {
3103: java.util.List idlist = getDefinitionIdEx(namespace, name,
3104: version, type);
3105:
3106: // TODO: make this a batch or sproc
3107: java.util.List result = new ArrayList();
3108: for (Iterator i = idlist.iterator(); i.hasNext();) {
3109: Definition d = loadDefinition(((Long) i.next()).longValue());
3110: if (d != null)
3111: result.add(d);
3112: }
3113: return result;
3114: }
3115:
3116: /**
3117: * Searches the database for all LFNs that match a certain pattern.
3118: * The linkage is an additional constraint. This method allows
3119: * joker characters such as '%' and '_'.
3120: *
3121: * @param lfn the LFN name
3122: * @param link the linkage type of the LFN
3123: * @return a list of filenames that match the criterion.
3124: *
3125: * @see org.griphyn.vdl.classes.LFN#NONE
3126: * @see org.griphyn.vdl.classes.LFN#INPUT
3127: * @see org.griphyn.vdl.classes.LFN#OUTPUT
3128: * @see org.griphyn.vdl.classes.LFN#INOUT
3129: */
3130: public java.util.List searchLFN(String lfn, int link)
3131: throws SQLException {
3132: if (lfn == null)
3133: throw new NullPointerException(
3134: "You must query for a filename");
3135: Logging.instance().log("xaction", 1, "START select LFNs");
3136: PreparedStatement ps = null;
3137:
3138: if (link == -1) {
3139: // wildcard match
3140: ps = this .m_dbdriver
3141: .getPreparedStatement("stmt.select.lfn_*.name.ex");
3142: for (int ii = 0; ii < c_lfn_names.length; ++ii)
3143: ps.setString(ii + 1, lfn);
3144: Logging.instance().log(
3145: "chunk",
3146: 2,
3147: "SELECT distinct name FROM lfn_*"
3148: + " WHERE name LIKE '" + lfn + "'");
3149: } else if (LFN.isInRange(link)) {
3150: // known linkage, one table only
3151:
3152: // ordering MUST MATCH classes.LFN constants!
3153: switch (link) {
3154: case LFN.NONE:
3155: throw new RuntimeException(
3156: "The linkage \"none\" is not permitted");
3157: // break;
3158: case LFN.INPUT:
3159: ps = this .m_dbdriver
3160: .getPreparedStatement("stmt.select.lfn_i.name.ex");
3161: break;
3162: case LFN.OUTPUT:
3163: ps = this .m_dbdriver
3164: .getPreparedStatement("stmt.select.lfn_o.name.ex");
3165: break;
3166: case LFN.INOUT:
3167: ps = this .m_dbdriver
3168: .getPreparedStatement("stmt.select.lfn_b.name.ex");
3169: break;
3170: }
3171: ;
3172:
3173: ps.setString(1, lfn);
3174: Logging.instance().log(
3175: "chunk",
3176: 2,
3177: "SELECT distinct name FROM "
3178: + c_lfn_names[link - 1]
3179: + " WHERE name LIKE '" + lfn + "'");
3180: } else {
3181: throw new RuntimeException("The linkage " + link
3182: + " is not permitted");
3183: }
3184:
3185: ResultSet rs = ps.executeQuery();
3186:
3187: // TODO: make this a batch or sproc
3188: java.util.List result = new ArrayList();
3189: while (rs.next()) {
3190: result.add(rs.getString("name"));
3191: }
3192:
3193: rs.close();
3194: Logging.instance().log("xaction", 1, "FINAL select LFNs");
3195: return result;
3196: }
3197:
3198: /**
3199: * Searches the database for a list of namespaces of the definitions
3200: * Sorted in ascending order.
3201: *
3202: * @param type type of definition, see below, or -1 for both
3203: * @return a list of namespaces
3204: *
3205: * @see org.griphyn.vdl.classes.Definition#TRANSFORMATION
3206: * @see org.griphyn.vdl.classes.Definition#DERIVATION
3207: */
3208: public java.util.List getNamespaceList(int type)
3209: throws SQLException {
3210: java.util.List result = new ArrayList();
3211: Logging.instance().log("xaction", 1,
3212: "START select namespaces from DEFINITION");
3213:
3214: java.util.List select = new ArrayList(1);
3215: select.add(new String("distinct namespace"));
3216:
3217: java.util.Map where = new TreeMap();
3218:
3219: if (type != -1)
3220: where.put("type", Integer.toString(type));
3221:
3222: String order = " ORDER BY namespace";
3223: Logging.instance().log("xaction", 1, "START select namespaces");
3224: ResultSet rs = m_dbdriver.select(select, "anno_definition",
3225: where, order);
3226:
3227: while (rs.next())
3228: result.add(new String(rs.getString("namespace")));
3229:
3230: rs.close();
3231: Logging.instance().log("xaction", 1,
3232: "FINAL select namespaces from DEFINITION");
3233: return result;
3234: }
3235:
3236: /**
3237: * Searches the database for a list of fully-qualified names of
3238: * the definitions sorted in ascending order.
3239: *
3240: * @param type type of definition, see below, or -1 for both
3241: * @return a list of FQDNs
3242: *
3243: * @see org.griphyn.vdl.classes.Definition#TRANSFORMATION
3244: * @see org.griphyn.vdl.classes.Definition#DERIVATION
3245: */
3246: public java.util.List getFQDNList(int type) throws SQLException {
3247: java.util.List result = new ArrayList();
3248: Logging.instance().log("xaction", 1,
3249: "START select triplets from DEFINITION");
3250:
3251: java.util.List select = new ArrayList(1);
3252: select.add(new String("namespace, name, version"));
3253:
3254: java.util.Map where = new TreeMap();
3255:
3256: if (type != -1)
3257: where.put("type", Integer.toString(type));
3258:
3259: String order = " ORDER BY namespace, name, version";
3260: Logging.instance().log("xaction", 1, "START select triplets");
3261: ResultSet rs = m_dbdriver.select(select, "anno_definition",
3262: where, order);
3263:
3264: while (rs.next())
3265: result.add(new String(Separator.combine(rs
3266: .getString("namespace"), rs.getString("name"), rs
3267: .getString("version"))));
3268:
3269: rs.close();
3270: Logging.instance().log("xaction", 1,
3271: "FINAL select triplets from DEFINITION");
3272: return result;
3273: }
3274:
3275: /**
3276: * A too generic method to search annotation (and anything) in
3277: * the database. This method is also responsible for breaking
3278: * any no-database-based backends.<p>
3279: *
3280: * WARNING: This is a method for internal use only.
3281: *
3282: * @param query is an SQL query statement.
3283: * @return something to search for results in.
3284: * @exception SQLException if something goes wrong with the database.
3285: */
3286: public ResultSet backdoor(String query) throws SQLException {
3287: return m_dbdriver.backdoor(query);
3288: }
3289: }
|