Source Code Cross Referenced for AnnotationSchema.java in  » Workflow-Engines » pegasus-2.1.0 » org » griphyn » vdl » dbschema » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Workflow Engines » pegasus 2.1.0 » org.griphyn.vdl.dbschema 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


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:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.