Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members  

BatchTool.java

Go to the documentation of this file.
00001 package net.threebit.utils.sosc;
00002 
00003 /*
00004         Copyright 2003 Shawn Deleurme
00005         Copyright 2003 Kevin O'Donnell
00006 
00007         This program is free software; you can redistribute it and/or modify
00008         it under the terms of the GNU General Public License as published by
00009         the Free Software Foundation; either version 2 of the License, or
00010         (at your option) any later version.
00011 
00012         This program is distributed in the hope that it will be useful,
00013         but WITHOUT ANY WARRANTY; without even the implied warranty of
00014         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015         GNU General Public License for more details.
00016 
00017         You should have received a copy of the GNU General Public License
00018         along with this program; if not, write to the Free Software
00019         Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00020 */
00021 
00022 import java.io.*;
00023 import java.sql.*;
00024 import java.util.*;
00025 
00029 public class BatchTool extends DbTool {
00030 
00031         public String CONTENTARGUMENTS = "_PREFIX__B_atchContentArguments";
00032         public String CONTENTS = "_PREFIX__B_atchContents";
00033         public String BATCHES = "_PREFIX__B_atches";
00034         public String PROFILES = "_PREFIX__B_atchProfiles";
00035 
00039         final static String MSSQL = 
00040                 " create table _PROFILES_ ( \n" +
00041                 "       id int primary key identity, \n" +
00042                 "       name varchar(100) \n" +
00043                 " ); \n" +
00044                 " create table _BATCHES_ ( \n" +
00045                 "       id int primary key identity, \n" +
00046                 "       profile int foreign key references _PROFILES_(id), \n" +
00047                 "       created datetime default getdate(), \n" +
00048                 "   status varchar(20) not null default 'review' \n" +
00049                 " ); \n" +
00050                 " create table _CONTENTS_ ( \n" +
00051                 "       id int primary key identity, \n" +
00052                 "       batch int foreign key references _BATCHES_(id), \n" +
00053                 "       i int, \n" +
00054                 "   v varchar(1000), \n" +
00055                 "               killed bit default 0 \n" +
00056                 " ); \n" +
00057                 " create table _CONTENTARGUMENTS_ ( \n" +
00058                 "       id int primary key identity, \n" +
00059                 "       content int foreign key references _CONTENTS_(id), \n" +
00060                 "   k varchar(100), \n" +
00061                 "   v varchar(1000) \n" +
00062                 " ); \n"
00063                 ;
00064 
00068         private String prefix = null;
00069 
00073         public BatchTool (String prefix, String className, String url, String userName, String password) throws Exception {
00074                 super(className, url, userName, password);
00075                 setPrefix(prefix);
00076         }
00077 
00081         public BatchTool (String prefix, Connection connection) throws Exception {
00082                 super(connection);
00083                 setPrefix(prefix);
00084         }
00085 
00089         private void setPrefix (String prefix) throws Exception {
00090                 if (prefix == null) { throw new Exception("Cannot specify a null prefix value; use an empty string instead"); }
00091                 this.prefix = prefix;
00092 
00093                 String b = "B";
00094                 if (prefix.equals("")) { b = "b"; }
00095                 CONTENTARGUMENTS = CONTENTARGUMENTS.replaceAll("_PREFIX_",prefix).replaceAll("_B_",b);
00096                 CONTENTS = CONTENTS.replaceAll("_PREFIX_",prefix).replaceAll("_B_",b);
00097                 BATCHES = BATCHES.replaceAll("_PREFIX_",prefix).replaceAll("_B_",b);
00098                 PROFILES = PROFILES.replaceAll("_PREFIX_",prefix).replaceAll("_B_",b);
00099         }
00100 
00104         public String getSchemaSQL (String dbType)  throws Exception {
00105                 String sql = null;
00106                 if (dbType.equals("pgsql")) { throw new Exception("Sorry, pgsql is not supported yet;"); }
00107                 else if (dbType.equals("mssql")) { sql = MSSQL; }
00108                 else { throw new Exception("Unsupported dbType: '" + dbType + "'"); }
00109                 sql = sql.replaceAll("_PROFILES_",PROFILES);
00110                 sql = sql.replaceAll("_CONTENTARGUMENTS_",CONTENTARGUMENTS);
00111                 sql = sql.replaceAll("_CONTENTS_",CONTENTS);
00112                 sql = sql.replaceAll("_BATCHES_",BATCHES);
00113                 return sql;
00114         }
00115 
00119         public void dropSchema (String dbType) throws Exception {
00120                 try {
00121                         update(
00122                                 " drop table " + CONTENTARGUMENTS + ";\n" +
00123                                 " drop table " + CONTENTS + ";\n" +
00124                                 " drop table " + BATCHES + ";\n" +
00125                                 " drop table " + PROFILES + ";\n" 
00126                         );
00127                 }
00128                 catch (Exception e) {
00129                         // just assume this is a "the tables did not exist error anyway";
00130                         e.printStackTrace(System.out);
00131                 }
00132         }
00133 
00137         public void createSchema (String dbType) throws Exception {
00138                 update( getSchemaSQL(dbType));
00139         }
00140 
00144         public int createProfile (String name) throws Exception {
00145 
00146                 boolean exists = false;
00147                 int id = 0;
00148                 try {
00149                         id = getProfileId(name);
00150                         exists = true;
00151                 }
00152                 catch (Exception e) {
00153                         // ok!  it means the profile does not exist
00154                 }
00155 
00156                 if (exists) { throw new Exception("A profile with id " + id + " already exists named '" + name + "'"); }
00157 
00158                 // Create it and return it's ID
00159                 update("insert into " + PROFILES + " (name) values (" + quote(name) + ")");
00160                 return getProfileId(name);
00161         };
00162         
00166         public int getProfileId (String name) throws Exception {
00167                 ResultSet r = query("select id from " + PROFILES + " where name = " + quote(name));
00168                 int rowCount = rowCount(r);
00169                 if (rowCount != 1) { throw new Exception("Too many or too few rows returned (" + rowCount + ")"); }
00170                 r.first();
00171                 return r.getInt("id");
00172         }
00173 
00177         public int createBatch (String profile) throws Exception {
00178                 int profileId = getProfileId(profile);
00179                 update("insert into " + BATCHES + " (profile) values ("+profileId+")");
00180                 return getInt("select max(id) from " + BATCHES + " where profile = " + profileId);
00181         }
00182 
00186         public void addIntContents (int batch, ResultSet r) throws Exception {
00187 
00188                 StringBuffer sql = new StringBuffer(); // insert into _CONTENTS_
00189                 Map args = new HashMap();
00190 
00191                 Map m = null;
00192                 int content = -1;
00193                 while (r.next()) {
00194                         content = r.getInt("content");
00195                         sql.append(" insert into " + CONTENTS + " (batch,i) values ("+batch+","+content+");\n");
00196                         m = toMap(r,false);
00197                         m.remove("content"); // this is not an 'argument'
00198                         args.put(new Integer(content),m);
00199                 }
00200                 // Actually add the contents
00201                 update(sql.toString());
00202                 r.close(); // release early, release often
00203 
00204                 // Now add the arguments for each content member
00205                 sql = new StringBuffer();
00206                 r = getBatchContents(batch);
00207                 int id = -1;
00208                 content = -1;
00209                 while (r.next()) {
00210                         id = r.getInt("id");
00211                         content = r.getInt("i");
00212                         m = (Map) args.get(new Integer(content));
00213                         for (Iterator i = m.keySet().iterator(); i.hasNext(); ) {
00214                                 String key = (String) i.next();
00215                                 String value = (String) m.get(key);
00216                                 sql.append(" insert into "+CONTENTARGUMENTS+" (content,k,v) values ("+id+","+quote(key)+","+quote(value)+"); \n");
00217                         }
00218                 }
00219                 update(sql.toString());
00220         }
00221 
00227         public void addIntContents (String query) throws Exception {
00228                 update( " insert into " + CONTENTS + " (batch,i) \n" + query);
00229         }
00230 
00236         public void addVarcharContents (String query) throws Exception {
00237                 update( " insert into " + CONTENTS + " (batch,v) \n" + query);
00238         }
00239 
00243         public void addContentArguments () throws Exception {
00244         }
00245 
00252         public ResultSet getContentArguments(int batchId) throws Exception {
00253                 // This will contain all of the necessary SQL for the "content arguments"
00254                 StringBuffer sb = new StringBuffer();
00255 
00256                 // Get the list of keys
00257                 ResultSet r = query(
00258                         "select distinct k from "+CONTENTARGUMENTS+" bca \n" +
00259                         "  join "+CONTENTS+" bc on bc.id = bca.content and bc.killed = 0 \n" +
00260                         "  where bc.batch = " + batchId
00261                 );
00262 
00263                 int rows = rowCount(r);
00264                 r.beforeFirst();
00265 
00266                 // Build an array of keys that must be VIEWED
00267                 String[] keys = new String[rows];
00268                 for (int x = 0; x < rows; x++) { r.next(); keys[x] = r.getString("k"); }
00269 
00270                 // First, the outer select
00271                 sb.append("select content,\n");
00272                 sb.append("  max(contentI) as contentI,\n");
00273                 sb.append("  max(contentV) as contentV,\n");
00274                 for (int x = 0; x < keys.length; x++) {
00275                         sb.append("  max("+keys[x]+") as "+keys[x]+",\n");
00276                 }
00277                 sb.deleteCharAt( sb.length()-2 ); // trailing ","
00278                 sb.append("from (\n");
00279 
00280                 // Now create a one-time view of all of the key/value pairs.  Performance
00281                 // sucks the big here, but this should not be on the critical path anyway.
00282                 for (int x = 0; x < keys.length; x++) {
00283                         sb.append("  select bca.id, content, bc.i as contentI, bc.v as contentv, ");
00284                         for (int y = 0; y < keys.length; y++) {
00285                                 sb.append((x==y) ? " bca.v" : " null");
00286                                 sb.append(" as " + keys[y]);
00287                                 sb.append(((y+1)==keys.length) ? "" : ",");
00288                         }
00289                         sb.append(" from "+CONTENTARGUMENTS+" bca \n");
00290                         sb.append("   join "+CONTENTS+" bc on bc.id = bca.content \n");
00291                         sb.append("   where \n");
00292                         sb.append("     bc.batch = " + batchId + "\n");
00293                         sb.append("     and k = '" + keys[x] + "'\n");
00294                         sb.append("     and bc.killed = 0 \n");
00295                         sb.append(((x+1)==keys.length) ? "" : "    union\n");
00296                 }
00297 
00298                 // Finish the outer select
00299                 sb.append(") as s group by content\n");
00300 
00301                 return query(sb.toString());
00302         }
00303 
00307         public ResultSet getBatchContents (int batch) throws Exception {
00308                 return query("select * from " + CONTENTS + " where batch = " + batch + " and killed = 0 ");
00309         };
00310 
00314         public ResultSet batchSummary (int profileId) throws Exception {
00315                 return query(
00316                         " select b.id, b.created, sum(case when bc.id is not null then 1 else 0 end) as size from " + BATCHES + " b " +
00317                         "   left join " + CONTENTS + " bc on bc.batch = b.id " +
00318                         "   where b.profile = " + profileId + " and bc.killed = 0 " +
00319                         "   group by b.id, b.created "
00320                 );
00321         }
00322 
00323 }

Generated on Mon Jul 14 17:19:19 2003 for SOSC by doxygen1.2.15