001    package hep.aida.ref.sql.Test;
002    
003    import hep.aida.ref.sql.SQLTuple;
004    import hep.aida.ref.sql.Util;
005    import hep.aida.ref.sql.AIDAURL;
006    import hep.aida.ref.sql.SQLTupleException;
007    
008    // AIDA
009    import hep.aida.IAnalysisFactory;
010    import hep.aida.ITree;
011    import hep.aida.ITuple;
012    import hep.aida.ITupleFactory;
013    import hep.aida.IFilter;
014    
015    // Log4J
016    import org.apache.log4j.Logger;
017    
018    // Java
019    import java.util.Collection;
020    import java.io.IOException;
021    
022    /** <code>Chain</code> reads two NTuple tables as one NTuple. It gets
023      * a <code>token_string</code> String from each row which
024      * satisfies a simple filter. {@link RowRepresentant}s are 
025      * created from those Strings and accumulated in
026      * an array. Database and NTuple (table) should exist.
027      * <br>
028      * <code>Chain</code> is an example to show chaining API and
029      * capabilities of SQLTuple.
030      * <p><font color="#880088">
031      * <pre>
032      * $Log: Chain.java,v $
033      * Revision 1.16  2007/05/23 16:38:45  hrivnac
034      * logical connections for Plotter; better UML
035      *
036      * Revision 1.15  2005/03/09 15:25:52  hrivnac
037      * ITuple.rows() improved
038      *
039      * Revision 1.14  2004/10/29 22:27:25  hrivnac
040      * imports corrected
041      *
042      * Revision 1.13  2004/06/16 21:56:43  hrivnac
043      * StringBuffer in SQLTuple.addRow() -> speed
044      *
045      * Revision 1.12  2004/05/22 15:12:59  hrivnac
046      * class id reformated
047      *
048      * Revision 1.11  2004/04/14 13:39:47  hrivnac
049      * 1.5 warnings fixed
050      *
051      * Revision 1.10  2004/04/13 15:45:54  hrivnac
052      * AIDA URL introduced
053      *
054      * Revision 1.9  2004/02/10 14:50:58  hrivnac
055      * JavaDoc tags completed
056      *
057      * Revision 1.8  2003/11/24 15:13:22  hrivnac
058      * Logging improved.
059      *
060      * Revision 1.7  2003/11/20 17:21:58  hrivnac
061      * Java 1.5 natively supported, Log4J reporting improved.
062      *
063      * Revision 1.6  2003/11/17 15:01:23  hrivnac
064      * More BM results.
065      *
066      * Revision 1.5  2003/11/17 10:18:29  hrivnac
067      * Cleaning.
068      *
069      * Revision 1.4  2003/11/06 16:54:16  hrivnac
070      * Merger works for SQL DBs
071      *
072      * Revision 1.3  2003/11/05 19:46:22  hrivnac
073      * - FreeHEP 1.2.1
074      * - JAIDA 3.2.1
075      *
076      * </pre>
077      * </font></p>
078      * @opt attributes
079      * @opt operations
080      * @opt types
081      * @opt visibility
082      * @version $Id: Chain.java,v 1.16 2007/05/23 16:38:45 hrivnac Exp $
083      * @author <a href="mailto:Julius.Hrivnac@cern.ch">J.Hrivnac</a> */
084    public class Chain {
085    
086      /** Initiate processing.
087        * @param args <ol>
088        *             <li>The URL of the first existing database,</li>
089        *             <li>the first user name to be used,</li>
090        *             <li>the first user password to be used,</li>
091        *             <li>the URL of the second existing database,</li>
092        *             <li>the second user name to be used,</li>
093        *             <li>the second user password to be used.</li>
094        *             </ol> */
095      public static void main(String[] args) {
096        if (args.length != 6) {
097          log.fatal(Util.urlHelp("hep.aida.ref.sql.Test.Chain <url1> <user1> <passwd1> <url2> <user2> <passwd2>"));
098          System.exit(1);
099          }
100        try {
101          (new Chain()).process(args[0], args[1], args[2], args[3], args[4], args[5]);
102          }
103        catch (Exception e) {
104          log.fatal(Util.report("*** Chain failed ***", e), e);
105          }
106        }
107    
108      /** Perform processing.
109        * @param url1    The URL of the first existing database.
110        * @param user1   The first user name to be used.
111        * @param passwd1 The first user password to be used.
112        * @param url2    The URL of the second existing database.
113        * @param user2   The second user name to be used.
114        * @param passwd2 The second user password to be used.
115        * @throws SQLTuple if the operation can't be performed. */
116      private void process(String url1,
117                           String user1,
118                           String passwd1,
119                           String url2,
120                           String user2,
121                           String passwd2) throws SQLTupleException {
122                                                                  
123        log.debug("Chaining SQLTuple " + url1 + " as " + user1);
124        log.debug("Chaining SQLTuple " + url2 + " as " + user2);
125    
126        // Parse URL
127        AIDAURL aidaurl1  = new AIDAURL(url1);
128        String dbName1    = aidaurl1.db();
129        String tableName1 = aidaurl1.table();
130        AIDAURL aidaurl2  = new AIDAURL(url2);
131        String dbName2    = aidaurl2.db();
132        String tableName2 = aidaurl2.table();
133           
134        // Create options
135        String options1 = "hep.aida.ref.sql.db="     + dbName1 + ";"
136                        + "hep.aida.ref.sql.user="   + user1   + ";"
137                        + "hep.aida.ref.sql.passwd=" + passwd1;
138        String options2 = "hep.aida.ref.sql.db="     + dbName2 + ";"
139                        + "hep.aida.ref.sql.user="   + user2   + ";"
140                        + "hep.aida.ref.sql.passwd=" + passwd2;
141    
142        // Create top-level factory (selection can be done 
143        // by -Dhep.aida.IAnalysisFactory command-line option)
144        IAnalysisFactory af = IAnalysisFactory.create();
145    
146        // Create Trees
147        ITree tree1 = null;
148        ITree tree2 = null;
149        try {
150          tree1 = af.createTreeFactory().create(dbName1, aidaurl1.storeType(), true, false, options1);
151          }
152        catch (IOException e) {
153          throw new SQLTupleException("Can't create Tree1 from following options: " + options1, e);
154          }
155        try {
156          tree2 = af.createTreeFactory().create(dbName2, aidaurl2.storeType(), true, false, options2);
157          }
158        catch (IOException e) {
159          throw new SQLTupleException("Can't create Tree2 from following options: " + options2, e);
160          }
161        ITree tree = af.createTreeFactory().create();
162    
163        // Get NTuples
164        ITuple tuple1 = (ITuple)tree1.find(tableName1);
165        ITuple tuple2 = (ITuple)tree2.find(tableName2);
166    
167        // Start time measure
168        long start = System.currentTimeMillis(); 
169    
170        // Create Chain
171        ITupleFactory tf = af.createTupleFactory(tree);
172        ITuple[] set = new ITuple[] {tuple1, tuple2};
173        ITuple tuple = tf.createChained("ChainedTuple", "Chained Tuple", set);
174    
175        // Quantify
176        int rows1 = tuple1.rows();
177        int rows2 = tuple2.rows();
178        int rows  = tuple.rows();
179    
180        // Close Tree
181        try {
182          tree1.close();
183          }
184        catch (IOException e) {
185          throw new SQLTupleException("Can't close Tree1", e);
186          }
187        try {
188          tree2.close();
189          }
190        catch (IOException e) {
191          throw new SQLTupleException("Can't close Tree2", e);
192          }
193    
194        // Report spent time and results
195        double delta = (System.currentTimeMillis() - start) / 1000.0;
196        log.info(rows1 + " + " + rows2 + " -> " + rows + " rows read in " + delta + " s");
197    
198        }
199    
200      /** Logging . */
201      private static Logger log = Logger.getLogger(Chain.class);
202    
203      }