Project

General

Profile

1
/**
2
 *  '$RCSfile$'
3
 *    Purpose: A Class that searches a relational DB for elements and 
4
 *             attributes that have free text matches a query string,
5
 *             or structured query matches to a path specified node in the 
6
 *             XML hierarchy.  It returns a result set consisting of the 
7
 *             document ID for each document that satisfies the query
8
 *  Copyright: 2000 Regents of the University of California and the
9
 *             National Center for Ecological Analysis and Synthesis
10
 *    Authors: Matt Jones
11
 *    Release: @release@
12
 *
13
 *   '$Author: berkley $'
14
 *     '$Date: 2001-02-26 16:42:41 -0800 (Mon, 26 Feb 2001) $'
15
 * '$Revision: 710 $'
16
 *
17
 * This program is free software; you can redistribute it and/or modify
18
 * it under the terms of the GNU General Public License as published by
19
 * the Free Software Foundation; either version 2 of the License, or
20
 * (at your option) any later version.
21
 *
22
 * This program is distributed in the hope that it will be useful,
23
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25
 * GNU General Public License for more details.
26
 *
27
 * You should have received a copy of the GNU General Public License
28
 * along with this program; if not, write to the Free Software
29
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
30
 */
31

    
32
package edu.ucsb.nceas.metacat;
33

    
34
import java.io.*;
35
import java.util.Vector;
36
import java.net.URL;
37
import java.net.MalformedURLException;
38
import java.sql.*;
39
import java.util.Stack;
40
import java.util.Hashtable;
41
import java.util.Enumeration;
42
import java.io.File;
43
import java.io.FileWriter;
44
import java.io.BufferedWriter;
45

    
46
/** 
47
 * A Class that searches a relational DB for elements and 
48
 * attributes that have free text matches a query string,
49
 * or structured query matches to a path specified node in the 
50
 * XML hierarchy.  It returns a result set consisting of the 
51
 * document ID for each document that satisfies the query
52
 */
53
public class DBQuery {
54

    
55
  static final int ALL = 1;
56
  static final int WRITE = 2;
57
  static final int READ = 4;
58

    
59
  private Connection  conn = null;
60
  private String  parserName = null;
61
  private MetaCatUtil util = new MetaCatUtil();
62
  /**
63
   * the main routine used to test the DBQuery utility.
64
   * <p>
65
   * Usage: java DBQuery <xmlfile>
66
   *
67
   * @param xmlfile the filename of the xml file containing the query
68
   */
69
  static public void main(String[] args) {
70
     
71
     if (args.length < 1)
72
     {
73
        System.err.println("Wrong number of arguments!!!");
74
        System.err.println("USAGE: java DBQuery [-t] [-index] <xmlfile>");
75
        return;
76
     } else {
77
        try {
78

    
79
          int i = 0;
80
          boolean showRuntime = false;
81
          boolean useXMLIndex = false;
82
          if ( args[i].equals( "-t" ) ) {
83
            showRuntime = true;
84
            i++;
85
          }
86
          if ( args[i].equals( "-index" ) ) {
87
            useXMLIndex = true;
88
            i++;
89
          } 
90
          String xmlfile  = args[i];
91

    
92
          // Time the request if asked for
93
          double startTime = System.currentTimeMillis();
94

    
95
          // Open a connection to the database
96
          MetaCatUtil   util = new MetaCatUtil();
97
          Connection dbconn = util.openDBConnection();
98

    
99
          double connTime = System.currentTimeMillis();
100

    
101
          // Execute the query
102
          DBQuery queryobj = new DBQuery(dbconn, util.getOption("saxparser"));
103
          FileReader xml = new FileReader(new File(xmlfile));
104
          Hashtable nodelist = null;
105
          nodelist = queryobj.findDocuments(xml, null, null, useXMLIndex);
106

    
107
          // Print the reulting document listing
108
          StringBuffer result = new StringBuffer();
109
          String document = null;
110
          String docid = null;
111
          result.append("<?xml version=\"1.0\"?>\n");
112
          result.append("<resultset>\n"); 
113
  // following line removed by Dan Higgins to avoid insertion of query XML inside returned XML doc
114
  //        result.append("  <query>" + xmlfile + "</query>\n"); 
115
          if(!showRuntime)
116
          {
117
            Enumeration doclist = nodelist.keys();
118
            while (doclist.hasMoreElements()) {
119
              docid = (String)doclist.nextElement();
120
              document = (String)nodelist.get(docid);
121
              result.append("  <document>\n    " + document + 
122
                            "\n  </document>\n");
123
            }
124
            
125
            result.append("</resultset>\n");
126
          }
127
          // Time the request if asked for
128
          double stopTime = System.currentTimeMillis();
129
          double dbOpenTime = (connTime - startTime)/1000;
130
          double readTime = (stopTime - connTime)/1000;
131
          double executionTime = (stopTime - startTime)/1000;
132
          if (showRuntime) {
133
            System.out.print("  " + executionTime);
134
            System.out.print("  " + dbOpenTime);
135
            System.out.print("  " + readTime);
136
            System.out.print("  " + nodelist.size());
137
            System.out.println();
138
          }
139
          //System.out.println(result);
140
          //write into a file "result.txt"
141
          if(!showRuntime)
142
          {
143
            File f = new File("./result.txt");
144
            FileWriter fw = new FileWriter(f);
145
            BufferedWriter out = new BufferedWriter(fw);
146
            out.write(result.toString());          
147
            out.flush();
148
            out.close();
149
            fw.close();
150
          }
151
          
152
        } 
153
        catch (Exception e) {
154
          System.err.println("Error in DBQuery.main");
155
          System.err.println(e.getMessage());
156
          e.printStackTrace(System.err);
157
        }
158
     }
159
  }
160
  
161
  /**
162
   * construct an instance of the DBQuery class 
163
   *
164
   * <p>Generally, one would call the findDocuments() routine after creating 
165
   * an instance to specify the search query</p>
166
   *
167
   * @param conn the JDBC connection that we use for the query
168
   * @param parserName the fully qualified name of a Java class implementing
169
   *                   the org.xml.sax.XMLReader interface
170
   */
171
  public DBQuery( Connection conn, String parserName ) 
172
                  throws IOException, 
173
                         SQLException, 
174
                         ClassNotFoundException {
175
    this.conn = conn;
176
    this.parserName = parserName;
177
  }
178
  
179
  public Hashtable findDocuments(Reader xmlquery, String user, String group,
180
                                 boolean useXMLIndex)
181
  {
182
    return findDocuments(xmlquery, user, group, null, useXMLIndex);
183
  }
184
  
185
  public Hashtable findDocuments(Reader xmlquery, String user, String group,
186
                                 String[] returndoc)
187
  {
188
    return findDocuments(xmlquery, user, group, returndoc, true);
189
  }
190

    
191
  /** 
192
   * routine to search the elements and attributes looking to match query
193
   *
194
   * @param xmlquery the xml serialization of the query (@see pathquery.dtd)
195
   * @param user the username of the user
196
   * @param group the group of the user
197
   * @param returndoc an array of document types to backtrack against.
198
   */
199
  public Hashtable findDocuments(Reader xmlquery, String user, String group,
200
                                 String[] returndoc, boolean useXMLIndex)
201
  {
202
    //System.out.println("in finddocuments");
203
      Hashtable   docListResult = new Hashtable();
204
      PreparedStatement pstmt = null;
205
      String docid = null;
206
      String docname = null;
207
      String doctype = null;
208
// DOCTITLE attr cleared from the db
209
//      String doctitle = null;
210
      String createDate = null;
211
      String updateDate = null;
212
      String fieldname = null;
213
      String fielddata = null;
214
      String relation = null;
215
      Connection dbconn = null;
216
      int rev = 0;
217
      StringBuffer document = null; 
218
      Vector returndocVec = new Vector();
219
      
220
      if(returndoc != null)
221
      {//add the returndoc elements to a vector for easier manipulation
222
        for(int i=0; i<returndoc.length; i++)
223
        {
224
          returndocVec.add(new String((String)returndoc[i]));
225
        }
226
      }
227
      
228
      try {
229
        if(conn == null)
230
        {
231
          dbconn = util.openDBConnection();
232
        }
233
        else
234
        {
235
          dbconn = conn;
236
        }
237
        // Get the XML query and covert it into a SQL statment
238
        QuerySpecification qspec = new QuerySpecification(xmlquery, 
239
                                   parserName, 
240
                                   util.getOption("accNumSeparator"));
241
       // System.out.println(qspec.printSQL());
242
        pstmt = dbconn.prepareStatement( qspec.printSQL(useXMLIndex) );
243

    
244
        // Execute the SQL query using the JDBC connection
245
        pstmt.execute();
246
        ResultSet rs = pstmt.getResultSet();
247
        boolean tableHasRows = rs.next();
248
        while (tableHasRows) 
249
        {
250
          docid = rs.getString(1);
251
          if ( !hasPermission(dbconn, user, group, docid) ) {
252
            // Advance to the next record in the cursor
253
            tableHasRows = rs.next();
254
            continue;
255
          }
256
          docname = rs.getString(2);
257
          doctype = rs.getString(3);
258
// DOCTITLE attr cleared from the db
259
//          doctitle = rs.getString(4);
260
          createDate = rs.getString(4);
261
          updateDate = rs.getString(5);
262
          rev = rs.getInt(6);
263
          
264
          //System.out.println("vec.size = " + returndocVec.size());
265
          if(returndocVec.size() != 0 && !returndocVec.contains(doctype))
266
          { //there are returndocs to match (backtracking can now be performed). 
267
            //System.out.println("olddoctype: " + doctype);
268
            StringBuffer btBuf = new StringBuffer();
269
            btBuf.append("select object from xml_relation where ");
270
            btBuf.append("objdoctype in (");
271
            //build the doctype list for the backtracking sql statement
272
            for(int i=0; i<returndocVec.size(); i++)
273
            {
274
              btBuf.append("'").append((String)returndocVec.get(i)).append("'");
275
              if(i != (returndocVec.size() - 1))
276
              {
277
                btBuf.append(", ");
278
              } 
279
            }
280
            btBuf.append(") ");
281
            btBuf.append("and subject like '");
282
            //btBuf.append("metacat://").append(util.getOption("server"));
283
            //btBuf.append("?docid=").append(docid).append("'");
284
            btBuf.append("%docid=").append(docid).append("'");
285
            //System.out.println("sql: " + btBuf.toString());
286
            
287
            PreparedStatement npstmt = dbconn.prepareStatement(btBuf.toString());
288
            npstmt.execute();
289
            ResultSet btrs = npstmt.getResultSet();
290
            boolean hasBtRows = btrs.next();
291
            if(hasBtRows)
292
            { //there was a backtrackable document found
293
              DocumentImpl xmldoc = null;
294
              //System.out.println("document found is: " + btrs.getString(1));
295
              MetacatURL objURL = new MetacatURL(btrs.getString(1));
296
              try
297
              {
298
                xmldoc = new DocumentImpl(dbconn, objURL.getParam(0)[1]);
299
              }
300
              catch(Exception e)
301
              {
302
                System.out.println("Error getting document in " + 
303
                                   "DBQuery.findDocuments: " + e.getMessage());
304
              }
305
              
306
              docid   = xmldoc.getDocID();
307
              docname = xmldoc.getDocname();
308
              doctype = xmldoc.getDoctype();
309
// DOCTITLE attr cleared from the db
310
//              doctitle = xmldoc.getDocTitle();
311
              createDate = xmldoc.getCreateDate();
312
              updateDate = xmldoc.getUpdateDate();
313
              //System.out.println("docname: " + docname + " doctype: " + doctype + 
314
              //                   " doctitle: " + doctitle + " createdate: " +
315
              //                   createDate + " updatedate: " + updateDate);
316
            }
317
            npstmt.close();
318
            btrs.close();
319
          }
320
          
321
          document = new StringBuffer();
322
          //System.out.println("packagdoctype: " + util.getOption("packagedoctype"));
323
          //if(!doctype.equals(util.getOption("packagedoctype")))
324
          {
325
            String completeDocid = docid + util.getOption("accNumSeparator");
326
            completeDocid += rev;
327
            document.append("<docid>").append(completeDocid).append("</docid>");
328
            if (docname != null) {
329
              document.append("<docname>" + docname + "</docname>");
330
            }
331
            if (doctype != null) {
332
              document.append("<doctype>" + doctype + "</doctype>");
333
            }
334
// DOCTITLE attr cleared from the db
335
//            if (doctitle != null) {
336
//              document.append("<doctitle>" + doctitle + "</doctitle>");
337
//            }
338
            if(createDate != null) {
339
              document.append("<createdate>" + createDate + "</createdate>");
340
            }
341
            if(updateDate != null) {
342
              document.append("<updatedate>" + updateDate + "</updatedate>");
343
            }
344
            // Store the document id and the root node id
345
            docListResult.put(docid,(String)document.toString());
346
          }
347

    
348
          // Advance to the next record in the cursor
349
          tableHasRows = rs.next();
350
        }
351
        rs.close();
352
        //pstmt.close();
353
        
354
        if(qspec.containsExtendedSQL())
355
        {
356
          Vector extendedFields = new Vector(qspec.getReturnFieldList());
357
          Vector results = new Vector();
358
          Enumeration keylist = docListResult.keys();
359
          StringBuffer doclist = new StringBuffer();
360
          while(keylist.hasMoreElements())
361
          {
362
            doclist.append("'");
363
            doclist.append((String)keylist.nextElement());
364
            doclist.append("',");
365
          }
366
          doclist.deleteCharAt(doclist.length()-1); //remove the last comma
367
          pstmt.close();
368
          pstmt = dbconn.prepareStatement(qspec.printExtendedSQL(
369
                                        doclist.toString()));
370
          pstmt.execute();
371
          rs = pstmt.getResultSet();
372
          tableHasRows = rs.next();
373
          while(tableHasRows) 
374
          {
375
            docid = rs.getString(1);
376
            if ( !hasPermission(dbconn, user, group, docid) ) {
377
              // Advance to the next record in the cursor
378
              tableHasRows = rs.next();
379
              continue;
380
            }
381
            fieldname = rs.getString(2);
382
            fielddata = rs.getString(3);
383
            
384
            document = new StringBuffer();
385

    
386
            document.append("<param name=\"");
387
            document.append(fieldname);
388
            document.append("\">");
389
            document.append(fielddata);
390
            document.append("</param>");
391

    
392
            tableHasRows = rs.next();
393
            if(docListResult.containsKey(docid))
394
            {
395
              String removedelement = (String)docListResult.remove(docid);
396
              docListResult.put(docid, removedelement + document.toString());
397
            }
398
            else
399
            {
400
              docListResult.put(docid, document.toString()); 
401
            }
402
          }
403
          rs.close();
404
        }
405

    
406
        //this loop adds the relation data to the resultdoc
407
        //this code might be able to be added to the backtracking code above
408
        Enumeration docidkeys = docListResult.keys();
409
        while(docidkeys.hasMoreElements())
410
        {
411
          //String connstring = "metacat://"+util.getOption("server")+"?docid=";
412
          String connstring = "%docid=";
413
          String docidkey = (String)docidkeys.nextElement();
414
          //System.out.println("relationsql: " + qspec.printRelationSQL(
415
          //                                           connstring + docidkey));
416
          pstmt.close();
417
          pstmt = dbconn.prepareStatement(
418
                  qspec.printRelationSQL(connstring + docidkey));
419
          pstmt.execute();
420
          rs = pstmt.getResultSet();
421
          tableHasRows = rs.next();
422
          while(tableHasRows)
423
          {
424
            String sub = rs.getString(1);
425
            String rel = rs.getString(2);
426
            String obj = rs.getString(3);
427
            String subDT = rs.getString(4);
428
            String objDT = rs.getString(5);
429
            
430
            MetacatURL murl = new MetacatURL(sub);
431
            if(murl.getProtocol().equals("metacat"))
432
            {//we only want to process metacat urls here.
433
              String[] tempparam = murl.getParam(0);
434
              if(tempparam[0].equals("docid") && tempparam[1].equals(docidkey))
435
              {
436
                document = new StringBuffer();
437
                document.append("<relation>");
438
                document.append("<relationtype>").append(rel);
439
                document.append("</relationtype>");
440
                document.append("<relationdoc>").append(obj);
441
                document.append("</relationdoc>");
442
                document.append("<relationdoctype>").append(objDT);
443
                document.append("</relationdoctype>");
444
                document.append("</relation>");
445
                
446
                String removedelement = (String)docListResult.remove(docidkey);
447
                docListResult.put(docidkey, removedelement + document.toString());
448
                
449
              }
450
            }
451
            tableHasRows = rs.next();
452
          }
453
          rs.close();
454
          pstmt.close();
455
        }
456
        
457
      } catch (SQLException e) {
458
        System.err.println("SQL Error in DBQuery.findDocuments: " + 
459
                           e.getMessage());
460
      } catch (IOException ioe) {
461
        System.err.println("IO error in DBQuery.findDocuments:");
462
        System.err.println(ioe.getMessage());
463
      } catch (Exception ee) {
464
        System.out.println("Exception in DBQuery.findDocuments: " + 
465
                           ee.getMessage());
466
      }
467
      finally {
468
        try
469
        {
470
          dbconn.close();
471
        }
472
        catch(SQLException sqle)
473
        {
474
          System.out.println("error closing conn in DBQuery.findDocuments");
475
        }
476
      }
477
    //System.out.println("docListResult: ");
478
    //System.out.println(docListResult.toString());
479
    return docListResult;
480
  }
481
  
482
  /**
483
   * returns a string array of the contents of a particular node. 
484
   * If the node appears more than once, the contents are returned 
485
   * in the order in which they appearred in the document.
486
   * @param nodename the name or path of the particular node.
487
   * @param docid the docid of the document you want the node from.
488
   * @param conn a database connection-this allows this method to be static
489
   */
490
  public static Object[] getNodeContent(String nodename, String docid, 
491
                                        Connection conn)
492
  {
493
    StringBuffer query = new StringBuffer();
494
    Vector result = new Vector();
495
    PreparedStatement pstmt = null;
496
    query.append("select nodedata from xml_nodes where parentnodeid in ");
497
    query.append("(select nodeid from xml_index where path like '");
498
    query.append(nodename);
499
    query.append("' and docid like '").append(docid).append("')");
500
    try
501
    {
502
      pstmt = conn.prepareStatement(query.toString());
503

    
504
      // Execute the SQL query using the JDBC connection
505
      pstmt.execute();
506
      ResultSet rs = pstmt.getResultSet();
507
      boolean tableHasRows = rs.next();
508
      while (tableHasRows) 
509
      {
510
        result.add(rs.getString(1));
511
        System.out.println(rs.getString(1));
512
        tableHasRows = rs.next();
513
      }
514
    } 
515
    catch (SQLException e) 
516
    {
517
      System.err.println("Error in DBQuery.getNodeContent: " + e.getMessage());
518
    } finally {
519
      try
520
      {
521
        pstmt.close();
522
      }
523
      catch(SQLException sqle) {}
524
    }
525
    return result.toArray();
526
  }
527
  
528
  /**
529
   * format a structured query as an XML document that conforms
530
   * to the pathquery.dtd and is appropriate for submission to the DBQuery
531
   * structured query engine
532
   *
533
   * @param params The list of parameters that  should be included in the query
534
   */
535
  public static String createSQuery(Hashtable params)
536
  { 
537
    StringBuffer query = new StringBuffer();
538
    Enumeration elements;
539
    Enumeration keys;
540
    String doctype = null;
541
    String casesensitive = null;
542
    String searchmode = null;
543
    Object nextkey;
544
    Object nextelement;
545
    //add the xml headers
546
    query.append("<?xml version=\"1.0\"?>\n");
547
    query.append("<pathquery version=\"1.0\"><meta_file_id>");
548
    
549
    if(params.containsKey("meta_file_id"))
550
    {
551
      query.append( ((String[])params.get("meta_file_id"))[0]);
552
      query.append("</meta_file_id>");
553
    }
554
    else
555
    {
556
      query.append("unspecified</meta_file_id>");
557
    }
558
    
559
// DOCTITLE attr cleared from the db
560
//    query.append("<querytitle>");
561
//    if(params.containsKey("querytitle"))
562
//    {
563
//      query.append(((String[])params.get("querytitle"))[0]);
564
//      query.append("</querytitle>");
565
//    }
566
//    else
567
//    {
568
//      query.append("unspecified</querytitle>");
569
//    }
570
    
571
    if(params.containsKey("doctype"))
572
    {
573
      doctype = ((String[])params.get("doctype"))[0]; 
574
    }
575
    else
576
    {
577
      doctype = "ANY";  
578
    }
579
    
580
    if(params.containsKey("returnfield"))
581
    {
582
      String[] returnfield = ((String[])params.get("returnfield"));
583
      for(int i=0; i<returnfield.length; i++)
584
      {
585
        query.append("<returnfield>").append(returnfield[i]);
586
        query.append("</returnfield>");
587
      }
588
    }
589
    
590
    if(params.containsKey("owner"))
591
    {
592
      String[] owner = ((String[])params.get("owner"));
593
      for(int i=0; i<owner.length; i++)
594
      {
595
        query.append("<owner>").append(owner[i]);
596
        query.append("</owner>");
597
      }
598
    }
599
    
600
    if(params.containsKey("site"))
601
    {
602
      String[] site = ((String[])params.get("site"));
603
      for(int i=0; i<site.length; i++)
604
      {
605
        query.append("<site>").append(site[i]);
606
        query.append("</site>");
607
      }
608
    }
609
    
610
    //if you don't limit the query by doctype, then it just creates
611
    //an empty returndoctype tag.
612
    if (!doctype.equals("any") && 
613
        !doctype.equals("ANY") &&
614
        !doctype.equals("") ) 
615
    {
616
       query.append("<returndoctype>");
617
       query.append(doctype).append("</returndoctype>");
618
    }
619
    else
620
    { 
621
      query.append("<returndoctype></returndoctype>");
622
    }
623
    
624
    //allows the dynamic switching of boolean operators
625
    if(params.containsKey("operator"))
626
    {
627
      query.append("<querygroup operator=\"" + 
628
                ((String[])params.get("operator"))[0] + "\">");
629
    }
630
    else
631
    { //the default operator is UNION
632
      query.append("<querygroup operator=\"UNION\">"); 
633
    }
634
        
635
    if(params.containsKey("casesensitive"))
636
    {
637
      casesensitive = ((String[])params.get("casesensitive"))[0]; 
638
    }
639
    else
640
    {
641
      casesensitive = "false"; 
642
    }
643
    
644
    if(params.containsKey("searchmode"))
645
    {
646
      searchmode = ((String[])params.get("searchmode"))[0]; 
647
    }
648
    else
649
    {
650
      searchmode = "contains"; 
651
    }
652
        
653
    //anyfield is a special case because it does a 
654
    //free text search.  It does not have a <pathexpr>
655
    //tag.  This allows for a free text search within the structured
656
    //query.  This is useful if the INTERSECT operator is used.
657
    if(params.containsKey("anyfield"))
658
    {
659
       String[] anyfield = ((String[])params.get("anyfield"));
660
       //allow for more than one value for anyfield
661
       for(int i=0; i<anyfield.length; i++)
662
       {
663
         if(!anyfield[i].equals(""))
664
         {
665
           query.append("<queryterm casesensitive=\"" + casesensitive + 
666
                        "\" " + "searchmode=\"" + searchmode + "\"><value>" +
667
                        anyfield[i] +
668
                        "</value></queryterm>"); 
669
         }
670
       }
671
    }
672
        
673
    //this while loop finds the rest of the parameters
674
    //and attempts to query for the field specified
675
    //by the parameter.
676
    elements = params.elements();
677
    keys = params.keys();
678
    while(keys.hasMoreElements() && elements.hasMoreElements())
679
    {
680
      nextkey = keys.nextElement();
681
      nextelement = elements.nextElement();
682

    
683
      //make sure we aren't querying for any of these
684
      //parameters since the are already in the query
685
      //in one form or another.
686
      if(!nextkey.toString().equals("doctype") && 
687
         !nextkey.toString().equals("action")  &&
688
         !nextkey.toString().equals("qformat") && 
689
         !nextkey.toString().equals("anyfield") &&
690
         !nextkey.toString().equals("returnfield") &&
691
         !nextkey.toString().equals("owner") &&
692
         !nextkey.toString().equals("site") &&
693
         !nextkey.toString().equals("operator") )
694
      {
695
        //allow for more than value per field name
696
        for(int i=0; i<((String[])nextelement).length; i++)
697
        {
698
          if(!((String[])nextelement)[i].equals(""))
699
          {
700
            query.append("<queryterm casesensitive=\"" + casesensitive +"\" " + 
701
                         "searchmode=\"" + searchmode + "\">" +
702
                         "<value>" +
703
                         //add the query value
704
                         ((String[])nextelement)[i] +
705
                         "</value><pathexpr>" +
706
                         //add the path to query by 
707
                         nextkey.toString() + 
708
                         "</pathexpr></queryterm>");
709
          }
710
        }
711
      }
712
    }
713
    query.append("</querygroup></pathquery>");
714
    //append on the end of the xml and return the result as a string
715
    return query.toString();
716
  }
717
  
718
  /**
719
   * format a simple free-text value query as an XML document that conforms
720
   * to the pathquery.dtd and is appropriate for submission to the DBQuery
721
   * structured query engine
722
   *
723
   * @param value the text string to search for in the xml catalog
724
   * @param doctype the type of documents to include in the result set -- use
725
   *        "any" or "ANY" for unfiltered result sets
726
   */
727
   public static String createQuery(String value, String doctype) {
728
     StringBuffer xmlquery = new StringBuffer();
729
     xmlquery.append("<?xml version=\"1.0\"?>\n");
730
     xmlquery.append("<pathquery version=\"1.0\">");
731
     xmlquery.append("<meta_file_id>Unspecified</meta_file_id>");
732
// DOCTITLE attr cleared from the db
733
//     xmlquery.append("<querytitle>Unspecified</querytitle>");
734

    
735
     if (!doctype.equals("any") && !doctype.equals("ANY")) {
736
       xmlquery.append("<returndoctype>");
737
       xmlquery.append(doctype).append("</returndoctype>");
738
     }
739

    
740
     xmlquery.append("<querygroup operator=\"UNION\">");
741
     //chad added - 8/14
742
     //the if statement allows a query to gracefully handle a null 
743
     //query.  Without this if a nullpointerException is thrown.
744
     if(!value.equals(""))
745
     {
746
       xmlquery.append("<queryterm casesensitive=\"false\" ");
747
       xmlquery.append("searchmode=\"contains\">");
748
       xmlquery.append("<value>").append(value).append("</value>");
749
       xmlquery.append("</queryterm>");
750
     }
751
     xmlquery.append("</querygroup>");
752
     xmlquery.append("</pathquery>");
753

    
754
     
755
     return (xmlquery.toString());
756
   }
757

    
758
  /**
759
   * format a simple free-text value query as an XML document that conforms
760
   * to the pathquery.dtd and is appropriate for submission to the DBQuery
761
   * structured query engine
762
   *
763
   * @param value the text string to search for in the xml catalog
764
   */
765
   public static String createQuery(String value) {
766
     return createQuery(value, "any");
767
   }
768
   
769
  /** 
770
    * Check for "READ" permission on @docid for @user and/or @group 
771
    * from DB connection 
772
    */
773
  private boolean hasPermission ( Connection conn, String user,
774
                                  String group, String docid ) 
775
                  throws SQLException
776
  {
777
    // b' of the command line invocation
778
    if ( (user == null) && (group == null) ) {
779
      return true;
780
    }
781
    
782
    // Check for READ permission on @docid for @user and/or @group
783
    AccessControlList aclobj = new AccessControlList(conn);
784
    boolean hasPermission = aclobj.hasPermission("READ",user,docid);
785
    if ( !hasPermission && group != null ) {
786
      hasPermission = aclobj.hasPermission("READ",group,docid);
787
    }
788
    
789
    return hasPermission;
790
  }
791
   
792
}
(14-14/43)