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: jones $'
14
 *     '$Date: 2001-07-20 11:23:06 -0700 (Fri, 20 Jul 2001) $'
15
 * '$Revision: 800 $'
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
  /** 
180
   * routine to search the elements and attributes looking to match query
181
   *
182
   * @param xmlquery the xml serialization of the query (@see pathquery.dtd)
183
   * @param user the username of the user
184
   * @param group the group of the user
185
   */
186
  public Hashtable findDocuments(Reader xmlquery, String user, String group)
187
  {
188
    return findDocuments(xmlquery, user, group, 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 useXMLIndex flag whether to search using the path index
198
   */
199
  public Hashtable findDocuments(Reader xmlquery, String user, String group,
200
                                 boolean useXMLIndex)
201
  {
202
      Hashtable   docListResult = new Hashtable();
203
      PreparedStatement pstmt = null;
204
      String docid = null;
205
      String docname = null;
206
      String doctype = null;
207
      String createDate = null;
208
      String updateDate = null;
209
      String fieldname = null;
210
      String fielddata = null;
211
      String relation = null;
212
      Connection dbconn = null;
213
      Connection dbconn2 = null;
214
      int rev = 0;
215
      StringBuffer document = null; 
216
      
217
      try {
218
        if (conn == null || conn.isClosed()) {
219
          dbconn = util.openDBConnection();
220
        } else {
221
          dbconn = conn;
222
        }
223
        // problem with ODBC driver multi-threading
224
     //   dbconn2 = util.openDBConnection(); // for use by AccessControlList
225
        
226
        // Get the XML query and covert it into a SQL statment
227
        QuerySpecification qspec = new QuerySpecification(xmlquery, 
228
                                   parserName, 
229
                                   util.getOption("accNumSeparator"));
230
  //System.out.println(qspec.printSQL(useXMLIndex)); 
231
        pstmt = dbconn.prepareStatement( qspec.printSQL(useXMLIndex) );
232
  
233
        // Execute the SQL query using the JDBC connection
234
        pstmt.execute();
235
        ResultSet rs = pstmt.getResultSet();
236
        boolean tableHasRows = rs.next();
237
        while (tableHasRows) 
238
        {
239
          docid = rs.getString(1).trim();
240
          if ( !hasPermission(dbconn, user, group, docid) ) {
241
            // Advance to the next record in the cursor
242
            tableHasRows = rs.next();
243
            continue;
244
          }
245
          docname = rs.getString(2);
246
          doctype = rs.getString(3);
247
          createDate = rs.getString(4);
248
          updateDate = rs.getString(5);
249
          rev = rs.getInt(6);
250

    
251
          // if there are returndocs to match, backtracking can be performed
252
          // otherwise, just return the document that was hit
253
          Vector returndocVec = qspec.getReturnDocList();
254
          if (returndocVec.size() != 0 && !returndocVec.contains(doctype))
255
          { 
256
            MetaCatUtil.debugMessage("Back tracing now...");
257
            String sep = util.getOption("accNumSeparator");
258
            StringBuffer btBuf = new StringBuffer();
259
            btBuf.append("select docid from xml_relation where ");
260

    
261
            //build the doctype list for the backtracking sql statement
262
            btBuf.append("packagetype in (");
263
            for(int i=0; i<returndocVec.size(); i++)
264
            {
265
              btBuf.append("'").append((String)returndocVec.get(i)).append("'");
266
              if (i != (returndocVec.size() - 1))
267
              {
268
                btBuf.append(", ");
269
              } 
270
            }
271
            btBuf.append(") ");
272

    
273
            btBuf.append("and (subject like '");
274
            btBuf.append(docid).append(sep).append(rev).append("'");
275
            btBuf.append("or object like '");
276
            btBuf.append(docid).append(sep).append(rev).append("')");
277
            
278
            PreparedStatement npstmt = dbconn.
279
                                       prepareStatement(btBuf.toString());
280
            npstmt.execute();
281
            ResultSet btrs = npstmt.getResultSet();
282
            boolean hasBtRows = btrs.next();
283
            while (hasBtRows)
284
            { //there was a backtrackable document found
285
              DocumentImpl xmldoc = null;
286
              String packageDocid = btrs.getString(1);
287
              util.debugMessage("Getting document for docid: " + packageDocid);
288
              try
289
              {
290
                //  THIS CONSTRUCTOR BUILDS THE WHOLE XML doc not needed here
291
                // xmldoc = new DocumentImpl(dbconn, packageDocid);
292
                //  thus use the following to get the doc info only
293
                //  xmldoc = new DocumentImpl(dbconn);
294
                xmldoc = new DocumentImpl(dbconn, packageDocid, false);
295
                if (xmldoc == null) {
296
                  util.debugMessage("Document was null for: " + packageDocid);
297
                }
298
              }
299
              catch(Exception e)
300
              {
301
                System.out.println("Error getting document in " + 
302
                                   "DBQuery.findDocuments: " + e.getMessage());
303
              }
304
              
305
              String docid_org = xmldoc.getDocID();
306
              if (docid_org == null) {
307
                util.debugMessage("Docid_org was null.");
308
              }
309
              docid   = docid_org.trim();
310
              docname = xmldoc.getDocname();
311
              doctype = xmldoc.getDoctype();
312
              createDate = xmldoc.getCreateDate();
313
              updateDate = xmldoc.getUpdateDate();
314
              rev = xmldoc.getRev();
315

    
316
              document = new StringBuffer();
317

    
318
              String completeDocid = docid + util.getOption("accNumSeparator");
319
              completeDocid += rev;
320
              document.append("<docid>").append(completeDocid);
321
              document.append("</docid>");
322
              if (docname != null) {
323
                document.append("<docname>" + docname + "</docname>");
324
              }
325
              if (doctype != null) {
326
                document.append("<doctype>" + doctype + "</doctype>");
327
              }
328
              if (createDate != null) {
329
                document.append("<createdate>" + createDate + "</createdate>");
330
              }
331
              if (updateDate != null) {
332
                document.append("<updatedate>" + updateDate + "</updatedate>");
333
              }
334
              // Store the document id and the root node id
335
              docListResult.put(docid,(String)document.toString());
336
         
337
              // Get the next package document linked to our hit
338
              hasBtRows = btrs.next();
339
            }
340
            npstmt.close();
341
            btrs.close();
342
          } else {
343
          
344
            document = new StringBuffer();
345

    
346
            String completeDocid = docid + util.getOption("accNumSeparator");
347
            completeDocid += rev;
348
            document.append("<docid>").append(completeDocid).append("</docid>");
349
            if (docname != null) {
350
              document.append("<docname>" + docname + "</docname>");
351
            }
352
            if (doctype != null) {
353
              document.append("<doctype>" + doctype + "</doctype>");
354
            }
355
            if (createDate != null) {
356
              document.append("<createdate>" + createDate + "</createdate>");
357
            }
358
            if (updateDate != null) {
359
              document.append("<updatedate>" + updateDate + "</updatedate>");
360
            }
361
            // Store the document id and the root node id
362
            docListResult.put(docid,(String)document.toString());
363
  
364
          }
365

    
366
          // Advance to the next record in the cursor
367
          tableHasRows = rs.next();
368
        }
369
        rs.close();
370
        //pstmt.close();
371
        
372
        if (qspec.containsExtendedSQL())
373
        {
374
          Vector extendedFields = new Vector(qspec.getReturnFieldList());
375
          Vector results = new Vector();
376
          Enumeration keylist = docListResult.keys();
377
          StringBuffer doclist = new StringBuffer();
378
          while(keylist.hasMoreElements())
379
          {
380
            doclist.append("'");
381
            doclist.append((String)keylist.nextElement());
382
            doclist.append("',");
383
          }
384
          doclist.deleteCharAt(doclist.length()-1); //remove the last comma
385
          pstmt.close();
386
          pstmt = dbconn.prepareStatement(qspec.printExtendedSQL(
387
                                        doclist.toString()));
388
          pstmt.execute();
389
          rs = pstmt.getResultSet();
390
          tableHasRows = rs.next();
391
          while(tableHasRows) 
392
          {
393
            docid = rs.getString(1).trim();
394
            if ( !hasPermission(dbconn, user, group, docid) ) {
395
              // Advance to the next record in the cursor
396
              tableHasRows = rs.next();
397
              continue;
398
            }
399
            fieldname = rs.getString(2);
400
            fielddata = rs.getString(3);
401
            
402
            document = new StringBuffer();
403

    
404
            document.append("<param name=\"");
405
            document.append(fieldname);
406
            document.append("\">");
407
            document.append(fielddata);
408
            document.append("</param>");
409

    
410
            tableHasRows = rs.next();
411
            if (docListResult.containsKey(docid))
412
            {
413
              String removedelement = (String)docListResult.remove(docid);
414
              docListResult.put(docid, removedelement + document.toString());
415
            }
416
            else
417
            {
418
              docListResult.put(docid, document.toString()); 
419
            }
420
          }
421
          rs.close();
422
        }
423

    
424
        //this loop adds the relation data to the resultdoc
425
        //this code might be able to be added to the backtracking code above
426
        Enumeration docidkeys = docListResult.keys();
427
        while(docidkeys.hasMoreElements())
428
        {
429
          //String connstring = "metacat://"+util.getOption("server")+"?docid=";
430
          String connstring = "%docid=";
431
          String docidkey = (String)docidkeys.nextElement();
432

    
433
          pstmt.close();
434
          pstmt = dbconn.prepareStatement(qspec.printRelationSQL(docidkey));
435
          pstmt.execute();
436
          rs = pstmt.getResultSet();
437
          tableHasRows = rs.next();
438
          while(tableHasRows)
439
          {
440
            String sub = rs.getString(1);
441
            String rel = rs.getString(2);
442
            String obj = rs.getString(3);
443
            String subDT = rs.getString(4);
444
            String objDT = rs.getString(5);
445
            
446
            //MetacatURL murl = new MetacatURL(sub);
447
            //we only want to process metacat urls here.
448
            //if (murl.getProtocol().equals("metacat")) {
449
              //String[] tempparam = murl.getParam(0);
450
              //if (tempparam[0].equals("docid") && tempparam[1].equals(docidkey))
451
              //{
452
                document = new StringBuffer();
453
                document.append("<triple>");
454
                document.append("<subject>").append(sub);
455
                document.append("</subject>");
456
                if (!subDT.equals("null")) {
457
                  document.append("<subjectdoctype>").append(subDT);
458
                  document.append("</subjectdoctype>");
459
                }
460
                document.append("<relationship>").append(rel);
461
                document.append("</relationship>");
462
                document.append("<object>").append(obj);
463
                document.append("</object>");
464
                if (!objDT.equals("null")) {
465
                  document.append("<objectdoctype>").append(objDT);
466
                  document.append("</objectdoctype>");
467
                }
468
                document.append("</triple>");
469
                
470
                String removedelement = (String)docListResult.remove(docidkey);
471
                docListResult.put(docidkey, removedelement + 
472
                                  document.toString());
473
                
474
              //}
475
            //}
476
            tableHasRows = rs.next();
477
          }
478
          rs.close();
479
          pstmt.close();
480
        }
481
        
482
      } catch (SQLException e) {
483
        System.err.println("SQL Error in DBQuery.findDocuments: " + 
484
                           e.getMessage());
485
      } catch (IOException ioe) {
486
        System.err.println("IO error in DBQuery.findDocuments:");
487
        System.err.println(ioe.getMessage());
488
      } catch (Exception ee) {
489
        System.err.println("Exception in DBQuery.findDocuments: " + 
490
                           ee.getMessage());
491
        ee.printStackTrace(System.err);
492
      }
493
      finally {
494
        try
495
        {
496
          dbconn.close();
497
        //  dbconn2.close();
498
        }
499
        catch(SQLException sqle)
500
        {
501
          System.out.println("error closing conn in DBQuery.findDocuments");
502
        }
503
      }
504
    //System.out.println("docListResult: ");
505
    //System.out.println(docListResult.toString());
506
    return docListResult;
507
  }
508
  
509
  /**
510
   * returns a string array of the contents of a particular node. 
511
   * If the node appears more than once, the contents are returned 
512
   * in the order in which they appearred in the document.
513
   * @param nodename the name or path of the particular node.
514
   * @param docid the docid of the document you want the node from.
515
   * @param conn a database connection-this allows this method to be static
516
   */
517
  public static Object[] getNodeContent(String nodename, String docid, 
518
                                        Connection conn)
519
  {
520
    StringBuffer query = new StringBuffer();
521
    Vector result = new Vector();
522
    PreparedStatement pstmt = null;
523
    query.append("select nodedata from xml_nodes where parentnodeid in ");
524
    query.append("(select nodeid from xml_index where path like '");
525
    query.append(nodename);
526
    query.append("' and docid like '").append(docid).append("')");
527
    try
528
    {
529
      pstmt = conn.prepareStatement(query.toString());
530

    
531
      // Execute the SQL query using the JDBC connection
532
      pstmt.execute();
533
      ResultSet rs = pstmt.getResultSet();
534
      boolean tableHasRows = rs.next();
535
      while (tableHasRows) 
536
      {
537
        result.add(rs.getString(1));
538
        System.out.println(rs.getString(1));
539
        tableHasRows = rs.next();
540
      }
541
    } 
542
    catch (SQLException e) 
543
    {
544
      System.err.println("Error in DBQuery.getNodeContent: " + e.getMessage());
545
    } finally {
546
      try
547
      {
548
        pstmt.close();
549
      }
550
      catch(SQLException sqle) {}
551
    }
552
    return result.toArray();
553
  }
554
  
555
  /**
556
   * format a structured query as an XML document that conforms
557
   * to the pathquery.dtd and is appropriate for submission to the DBQuery
558
   * structured query engine
559
   *
560
   * @param params The list of parameters that should be included in the query
561
   */
562
  public static String createSQuery(Hashtable params)
563
  { 
564
    StringBuffer query = new StringBuffer();
565
    Enumeration elements;
566
    Enumeration keys;
567
    String filterDoctype = null;
568
    String casesensitive = null;
569
    String searchmode = null;
570
    Object nextkey;
571
    Object nextelement;
572
    //add the xml headers
573
    query.append("<?xml version=\"1.0\"?>\n");
574
    query.append("<pathquery version=\"1.0\">\n");
575

    
576
    if (params.containsKey("meta_file_id"))
577
    {
578
      query.append("<meta_file_id>");
579
      query.append( ((String[])params.get("meta_file_id"))[0]);
580
      query.append("</meta_file_id>");
581
    }
582
    
583
    if (params.containsKey("returndoctype"))
584
    {
585
      String[] returnDoctypes = ((String[])params.get("returndoctype"));
586
      for(int i=0; i<returnDoctypes.length; i++)
587
      {
588
        String doctype = (String)returnDoctypes[i];
589

    
590
        if (!doctype.equals("any") && 
591
            !doctype.equals("ANY") &&
592
            !doctype.equals("") ) 
593
        {
594
          query.append("<returndoctype>").append(doctype);
595
          query.append("</returndoctype>");
596
        }
597
      }
598
    }
599
    
600
    if (params.containsKey("filterdoctype"))
601
    {
602
      String[] filterDoctypes = ((String[])params.get("filterdoctype"));
603
      for(int i=0; i<filterDoctypes.length; i++)
604
      {
605
        query.append("<filterdoctype>").append(filterDoctypes[i]);
606
        query.append("</filterdoctype>");
607
      }
608
    }
609
    
610
    if (params.containsKey("returnfield"))
611
    {
612
      String[] returnfield = ((String[])params.get("returnfield"));
613
      for(int i=0; i<returnfield.length; i++)
614
      {
615
        query.append("<returnfield>").append(returnfield[i]);
616
        query.append("</returnfield>");
617
      }
618
    }
619
    
620
    if (params.containsKey("owner"))
621
    {
622
      String[] owner = ((String[])params.get("owner"));
623
      for(int i=0; i<owner.length; i++)
624
      {
625
        query.append("<owner>").append(owner[i]);
626
        query.append("</owner>");
627
      }
628
    }
629
    
630
    if (params.containsKey("site"))
631
    {
632
      String[] site = ((String[])params.get("site"));
633
      for(int i=0; i<site.length; i++)
634
      {
635
        query.append("<site>").append(site[i]);
636
        query.append("</site>");
637
      }
638
    }
639
    
640
    //allows the dynamic switching of boolean operators
641
    if (params.containsKey("operator"))
642
    {
643
      query.append("<querygroup operator=\"" + 
644
                ((String[])params.get("operator"))[0] + "\">");
645
    }
646
    else
647
    { //the default operator is UNION
648
      query.append("<querygroup operator=\"UNION\">"); 
649
    }
650
        
651
    if (params.containsKey("casesensitive"))
652
    {
653
      casesensitive = ((String[])params.get("casesensitive"))[0]; 
654
    }
655
    else
656
    {
657
      casesensitive = "false"; 
658
    }
659
    
660
    if (params.containsKey("searchmode"))
661
    {
662
      searchmode = ((String[])params.get("searchmode"))[0]; 
663
    }
664
    else
665
    {
666
      searchmode = "contains"; 
667
    }
668
        
669
    //anyfield is a special case because it does a 
670
    //free text search.  It does not have a <pathexpr>
671
    //tag.  This allows for a free text search within the structured
672
    //query.  This is useful if the INTERSECT operator is used.
673
    if (params.containsKey("anyfield"))
674
    {
675
       String[] anyfield = ((String[])params.get("anyfield"));
676
       //allow for more than one value for anyfield
677
       for(int i=0; i<anyfield.length; i++)
678
       {
679
         if (!anyfield[i].equals(""))
680
         {
681
           query.append("<queryterm casesensitive=\"" + casesensitive + 
682
                        "\" " + "searchmode=\"" + searchmode + "\"><value>" +
683
                        anyfield[i] +
684
                        "</value></queryterm>"); 
685
         }
686
       }
687
    }
688
        
689
    //this while loop finds the rest of the parameters
690
    //and attempts to query for the field specified
691
    //by the parameter.
692
    elements = params.elements();
693
    keys = params.keys();
694
    while(keys.hasMoreElements() && elements.hasMoreElements())
695
    {
696
      nextkey = keys.nextElement();
697
      nextelement = elements.nextElement();
698

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

    
749
     if (!doctype.equals("any") && !doctype.equals("ANY")) {
750
       xmlquery.append("<returndoctype>");
751
       xmlquery.append(doctype).append("</returndoctype>");
752
     }
753

    
754
     xmlquery.append("<querygroup operator=\"UNION\">");
755
     //chad added - 8/14
756
     //the if statement allows a query to gracefully handle a null 
757
     //query.  Without this if a nullpointerException is thrown.
758
     if (!value.equals(""))
759
     {
760
       xmlquery.append("<queryterm casesensitive=\"false\" ");
761
       xmlquery.append("searchmode=\"contains\">");
762
       xmlquery.append("<value>").append(value).append("</value>");
763
       xmlquery.append("</queryterm>");
764
     }
765
     xmlquery.append("</querygroup>");
766
     xmlquery.append("</pathquery>");
767

    
768
     
769
     return (xmlquery.toString());
770
   }
771

    
772
  /**
773
   * format a simple free-text value query as an XML document that conforms
774
   * to the pathquery.dtd and is appropriate for submission to the DBQuery
775
   * structured query engine
776
   *
777
   * @param value the text string to search for in the xml catalog
778
   */
779
   public static String createQuery(String value) {
780
     return createQuery(value, "any");
781
   }
782
   
783
  /** 
784
    * Check for "READ" permission on @docid for @user and/or @group 
785
    * from DB connection 
786
    */
787
  private boolean hasPermission ( Connection conn, String user,
788
                                  String group, String docid ) 
789
                  throws SQLException
790
  {
791
    // b' of the command line invocation
792
    if ( (user == null) && (group == null) ) {
793
      return true;
794
    }
795
    
796
    // Check for READ permission on @docid for @user and/or @group
797
    AccessControlList aclobj = new AccessControlList(conn);
798
    boolean hasPermission = aclobj.hasPermission("READ",user,docid);
799
    if ( !hasPermission && group != null ) {
800
      hasPermission = aclobj.hasPermission("READ",group,docid);
801
    }
802
    
803
    return hasPermission;
804
  }
805
   
806
}
(14-14/40)