Project

General

Profile

1 155 jones
/**
2 203 jones
 *  '$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 349 jones
 *    Release: @release@
12 155 jones
 *
13 203 jones
 *   '$Author$'
14
 *     '$Date$'
15
 * '$Revision$'
16 669 jones
 *
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 155 jones
 */
31
32 607 bojilova
package edu.ucsb.nceas.metacat;
33 155 jones
34
import java.io.*;
35 401 berkley
import java.util.Vector;
36 155 jones
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 706 bojilova
import java.io.File;
43
import java.io.FileWriter;
44
import java.io.BufferedWriter;
45 155 jones
46
/**
47 172 jones
 * 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 155 jones
 */
53
public class DBQuery {
54
55 441 bojilova
  static final int ALL = 1;
56
  static final int WRITE = 2;
57
  static final int READ = 4;
58
59 535 jones
  private Connection  conn = null;
60
  private String  parserName = null;
61 465 berkley
  private MetaCatUtil util = new MetaCatUtil();
62 155 jones
  /**
63
   * the main routine used to test the DBQuery utility.
64 184 jones
   * <p>
65
   * Usage: java DBQuery <xmlfile>
66 155 jones
   *
67 170 jones
   * @param xmlfile the filename of the xml file containing the query
68 155 jones
   */
69
  static public void main(String[] args) {
70
71 184 jones
     if (args.length < 1)
72 155 jones
     {
73
        System.err.println("Wrong number of arguments!!!");
74 706 bojilova
        System.err.println("USAGE: java DBQuery [-t] [-index] <xmlfile>");
75 155 jones
        return;
76
     } else {
77
        try {
78
79 706 bojilova
          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 155 jones
          // Open a connection to the database
96 184 jones
          MetaCatUtil   util = new MetaCatUtil();
97
          Connection dbconn = util.openDBConnection();
98 706 bojilova
99 705 berkley
          double connTime = System.currentTimeMillis();
100 706 bojilova
101 170 jones
          // Execute the query
102 184 jones
          DBQuery queryobj = new DBQuery(dbconn, util.getOption("saxparser"));
103 170 jones
          FileReader xml = new FileReader(new File(xmlfile));
104 155 jones
          Hashtable nodelist = null;
105 706 bojilova
          nodelist = queryobj.findDocuments(xml, null, null, useXMLIndex);
106
107 172 jones
          // Print the reulting document listing
108 155 jones
          StringBuffer result = new StringBuffer();
109
          String document = null;
110 170 jones
          String docid = null;
111 155 jones
          result.append("<?xml version=\"1.0\"?>\n");
112 296 higgins
          result.append("<resultset>\n");
113 706 bojilova
  // following line removed by Dan Higgins to avoid insertion of query XML inside returned XML doc
114 710 berkley
  //        result.append("  <query>" + xmlfile + "</query>\n");
115 743 jones
          if (!showRuntime)
116 710 berkley
          {
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 155 jones
          }
127 706 bojilova
          // Time the request if asked for
128
          double stopTime = System.currentTimeMillis();
129 705 berkley
          double dbOpenTime = (connTime - startTime)/1000;
130 706 bojilova
          double readTime = (stopTime - connTime)/1000;
131 705 berkley
          double executionTime = (stopTime - startTime)/1000;
132 706 bojilova
          if (showRuntime) {
133 710 berkley
            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 706 bojilova
          }
139
          //System.out.println(result);
140
          //write into a file "result.txt"
141 743 jones
          if (!showRuntime)
142 710 berkley
          {
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 675 berkley
          System.err.println("Error in DBQuery.main");
155 155 jones
          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 172 jones
   * @param parserName the fully qualified name of a Java class implementing
169 185 jones
   *                   the org.xml.sax.XMLReader interface
170 155 jones
   */
171 172 jones
  public DBQuery( Connection conn, String parserName )
172 155 jones
                  throws IOException,
173
                         SQLException,
174 172 jones
                         ClassNotFoundException {
175 155 jones
    this.conn = conn;
176 172 jones
    this.parserName = parserName;
177 155 jones
  }
178
179 745 jones
  /**
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 802 bojilova
  public Hashtable findDocuments(Reader xmlquery, String user, String[] groups)
187 465 berkley
  {
188 802 bojilova
    return findDocuments(xmlquery, user, groups, true);
189 465 berkley
  }
190 706 bojilova
191 155 jones
  /**
192
   * routine to search the elements and attributes looking to match query
193
   *
194 178 jones
   * @param xmlquery the xml serialization of the query (@see pathquery.dtd)
195 465 berkley
   * @param user the username of the user
196
   * @param group the group of the user
197 745 jones
   * @param useXMLIndex flag whether to search using the path index
198 155 jones
   */
199 802 bojilova
  public Hashtable findDocuments(Reader xmlquery, String user, String[] groups,
200 745 jones
                                 boolean useXMLIndex)
201 453 berkley
  {
202 535 jones
      Hashtable   docListResult = new Hashtable();
203 667 berkley
      PreparedStatement pstmt = null;
204 170 jones
      String docid = null;
205 155 jones
      String docname = null;
206
      String doctype = null;
207 401 berkley
      String createDate = null;
208
      String updateDate = null;
209
      String fieldname = null;
210
      String fielddata = null;
211 453 berkley
      String relation = null;
212 667 berkley
      Connection dbconn = null;
213 766 bojilova
      Connection dbconn2 = null;
214 624 berkley
      int rev = 0;
215 155 jones
      StringBuffer document = null;
216 465 berkley
217 155 jones
      try {
218 743 jones
        if (conn == null || conn.isClosed()) {
219 710 berkley
          dbconn = util.openDBConnection();
220 743 jones
        } else {
221 710 berkley
          dbconn = conn;
222
        }
223 766 bojilova
        // problem with ODBC driver multi-threading
224 790 bojilova
     //   dbconn2 = util.openDBConnection(); // for use by AccessControlList
225 766 bojilova
226 172 jones
        // Get the XML query and covert it into a SQL statment
227 178 jones
        QuerySpecification qspec = new QuerySpecification(xmlquery,
228 535 jones
                                   parserName,
229 624 berkley
                                   util.getOption("accNumSeparator"));
230 790 bojilova
  //System.out.println(qspec.printSQL(useXMLIndex));
231 706 bojilova
        pstmt = dbconn.prepareStatement( qspec.printSQL(useXMLIndex) );
232 790 bojilova
233 172 jones
        // Execute the SQL query using the JDBC connection
234 155 jones
        pstmt.execute();
235
        ResultSet rs = pstmt.getResultSet();
236
        boolean tableHasRows = rs.next();
237 667 berkley
        while (tableHasRows)
238
        {
239 768 bojilova
          docid = rs.getString(1).trim();
240 802 bojilova
          if ( !hasPermission(dbconn, user, groups, docid) ) {
241 612 bojilova
            // Advance to the next record in the cursor
242
            tableHasRows = rs.next();
243
            continue;
244
          }
245 155 jones
          docname = rs.getString(2);
246
          doctype = rs.getString(3);
247 692 bojilova
          createDate = rs.getString(4);
248
          updateDate = rs.getString(5);
249
          rev = rs.getInt(6);
250 743 jones
251 745 jones
          // 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 743 jones
          if (returndocVec.size() != 0 && !returndocVec.contains(doctype))
255
          {
256 745 jones
            MetaCatUtil.debugMessage("Back tracing now...");
257 743 jones
            String sep = util.getOption("accNumSeparator");
258 465 berkley
            StringBuffer btBuf = new StringBuffer();
259 743 jones
            btBuf.append("select docid from xml_relation where ");
260
261 465 berkley
            //build the doctype list for the backtracking sql statement
262 743 jones
            btBuf.append("packagetype in (");
263 465 berkley
            for(int i=0; i<returndocVec.size(); i++)
264
            {
265
              btBuf.append("'").append((String)returndocVec.get(i)).append("'");
266 743 jones
              if (i != (returndocVec.size() - 1))
267 465 berkley
              {
268
                btBuf.append(", ");
269 475 berkley
              }
270 465 berkley
            }
271
            btBuf.append(") ");
272 743 jones
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 667 berkley
278 743 jones
            PreparedStatement npstmt = dbconn.
279
                                       prepareStatement(btBuf.toString());
280 671 berkley
            npstmt.execute();
281
            ResultSet btrs = npstmt.getResultSet();
282 465 berkley
            boolean hasBtRows = btrs.next();
283 743 jones
            while (hasBtRows)
284 465 berkley
            { //there was a backtrackable document found
285
              DocumentImpl xmldoc = null;
286 743 jones
              String packageDocid = btrs.getString(1);
287 800 jones
              util.debugMessage("Getting document for docid: " + packageDocid);
288 465 berkley
              try
289
              {
290 800 jones
                //  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 465 berkley
              }
299
              catch(Exception e)
300
              {
301 675 berkley
                System.out.println("Error getting document in " +
302
                                   "DBQuery.findDocuments: " + e.getMessage());
303 465 berkley
              }
304
305 800 jones
              String docid_org = xmldoc.getDocID();
306
              if (docid_org == null) {
307
                util.debugMessage("Docid_org was null.");
308
              }
309
              docid   = docid_org.trim();
310 465 berkley
              docname = xmldoc.getDocname();
311
              doctype = xmldoc.getDoctype();
312
              createDate = xmldoc.getCreateDate();
313
              updateDate = xmldoc.getUpdateDate();
314 743 jones
              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 465 berkley
            }
340 671 berkley
            npstmt.close();
341 465 berkley
            btrs.close();
342 743 jones
          } else {
343 465 berkley
344 743 jones
            document = new StringBuffer();
345
346 624 berkley
            String completeDocid = docid + util.getOption("accNumSeparator");
347
            completeDocid += rev;
348
            document.append("<docid>").append(completeDocid).append("</docid>");
349 465 berkley
            if (docname != null) {
350
              document.append("<docname>" + docname + "</docname>");
351
            }
352
            if (doctype != null) {
353
              document.append("<doctype>" + doctype + "</doctype>");
354
            }
355 743 jones
            if (createDate != null) {
356 465 berkley
              document.append("<createdate>" + createDate + "</createdate>");
357
            }
358 743 jones
            if (updateDate != null) {
359 465 berkley
              document.append("<updatedate>" + updateDate + "</updatedate>");
360
            }
361
            // Store the document id and the root node id
362
            docListResult.put(docid,(String)document.toString());
363 743 jones
364 155 jones
          }
365
366
          // Advance to the next record in the cursor
367
          tableHasRows = rs.next();
368
        }
369 667 berkley
        rs.close();
370 818 berkley
        pstmt.close();
371 401 berkley
372 743 jones
        if (qspec.containsExtendedSQL())
373 401 berkley
        {
374
          Vector extendedFields = new Vector(qspec.getReturnFieldList());
375
          Vector results = new Vector();
376 465 berkley
          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 834 jones
          if (doclist.length() > 0) {
385
            doclist.deleteCharAt(doclist.length()-1); //remove the last comma
386
            //pstmt.close();
387
            pstmt = dbconn.prepareStatement(qspec.printExtendedSQL(
388 465 berkley
                                        doclist.toString()));
389 834 jones
            pstmt.execute();
390
            rs = pstmt.getResultSet();
391 401 berkley
            tableHasRows = rs.next();
392 834 jones
            while(tableHasRows)
393 401 berkley
            {
394 834 jones
              docid = rs.getString(1).trim();
395
              if ( !hasPermission(dbconn, user, groups, docid) ) {
396
                // Advance to the next record in the cursor
397
                tableHasRows = rs.next();
398
                continue;
399
              }
400
              fieldname = rs.getString(2);
401
              fielddata = rs.getString(3);
402
403
              document = new StringBuffer();
404
405
              document.append("<param name=\"");
406
              document.append(fieldname);
407
              document.append("\">");
408
              document.append(fielddata);
409
              document.append("</param>");
410
411
              tableHasRows = rs.next();
412
              if (docListResult.containsKey(docid))
413
              {
414
                String removedelement = (String)docListResult.remove(docid);
415
                docListResult.put(docid, removedelement + document.toString());
416
              }
417
              else
418
              {
419
                docListResult.put(docid, document.toString());
420
              }
421 401 berkley
            }
422
          }
423 667 berkley
          rs.close();
424 401 berkley
        }
425 818 berkley
        pstmt.close();
426
427 465 berkley
        //this loop adds the relation data to the resultdoc
428
        //this code might be able to be added to the backtracking code above
429
        Enumeration docidkeys = docListResult.keys();
430
        while(docidkeys.hasMoreElements())
431 453 berkley
        {
432 602 berkley
          //String connstring = "metacat://"+util.getOption("server")+"?docid=";
433
          String connstring = "%docid=";
434 465 berkley
          String docidkey = (String)docidkeys.nextElement();
435 743 jones
          pstmt = dbconn.prepareStatement(qspec.printRelationSQL(docidkey));
436 465 berkley
          pstmt.execute();
437
          rs = pstmt.getResultSet();
438
          tableHasRows = rs.next();
439
          while(tableHasRows)
440
          {
441
            String sub = rs.getString(1);
442
            String rel = rs.getString(2);
443
            String obj = rs.getString(3);
444 489 berkley
            String subDT = rs.getString(4);
445
            String objDT = rs.getString(5);
446
447 743 jones
            //MetacatURL murl = new MetacatURL(sub);
448
            //we only want to process metacat urls here.
449
            //if (murl.getProtocol().equals("metacat")) {
450
              //String[] tempparam = murl.getParam(0);
451
              //if (tempparam[0].equals("docid") && tempparam[1].equals(docidkey))
452
              //{
453 465 berkley
                document = new StringBuffer();
454 743 jones
                document.append("<triple>");
455
                document.append("<subject>").append(sub);
456
                document.append("</subject>");
457 820 bojilova
                //if (!subDT.equals("null")) {
458
                if ( subDT != null ) {
459 743 jones
                  document.append("<subjectdoctype>").append(subDT);
460
                  document.append("</subjectdoctype>");
461
                }
462
                document.append("<relationship>").append(rel);
463
                document.append("</relationship>");
464
                document.append("<object>").append(obj);
465
                document.append("</object>");
466 820 bojilova
                //if (!objDT.equals("null")) {
467
                if ( objDT != null ) {
468 743 jones
                  document.append("<objectdoctype>").append(objDT);
469
                  document.append("</objectdoctype>");
470
                }
471
                document.append("</triple>");
472 465 berkley
473
                String removedelement = (String)docListResult.remove(docidkey);
474 743 jones
                docListResult.put(docidkey, removedelement +
475
                                  document.toString());
476 465 berkley
477 743 jones
              //}
478
            //}
479 465 berkley
            tableHasRows = rs.next();
480 453 berkley
          }
481 667 berkley
          rs.close();
482
          pstmt.close();
483 453 berkley
        }
484 667 berkley
485 155 jones
      } catch (SQLException e) {
486 667 berkley
        System.err.println("SQL Error in DBQuery.findDocuments: " +
487
                           e.getMessage());
488 170 jones
      } catch (IOException ioe) {
489 675 berkley
        System.err.println("IO error in DBQuery.findDocuments:");
490 170 jones
        System.err.println(ioe.getMessage());
491 667 berkley
      } catch (Exception ee) {
492 800 jones
        System.err.println("Exception in DBQuery.findDocuments: " +
493 667 berkley
                           ee.getMessage());
494 800 jones
        ee.printStackTrace(System.err);
495 155 jones
      }
496 667 berkley
      finally {
497
        try
498
        {
499
          dbconn.close();
500 790 bojilova
        //  dbconn2.close();
501 667 berkley
        }
502
        catch(SQLException sqle)
503
        {
504
          System.out.println("error closing conn in DBQuery.findDocuments");
505
        }
506
      }
507 423 berkley
    //System.out.println("docListResult: ");
508
    //System.out.println(docListResult.toString());
509 155 jones
    return docListResult;
510
  }
511 342 berkley
512
  /**
513 436 berkley
   * returns a string array of the contents of a particular node.
514
   * If the node appears more than once, the contents are returned
515
   * in the order in which they appearred in the document.
516
   * @param nodename the name or path of the particular node.
517
   * @param docid the docid of the document you want the node from.
518
   * @param conn a database connection-this allows this method to be static
519
   */
520
  public static Object[] getNodeContent(String nodename, String docid,
521
                                        Connection conn)
522
  {
523
    StringBuffer query = new StringBuffer();
524
    Vector result = new Vector();
525 667 berkley
    PreparedStatement pstmt = null;
526 436 berkley
    query.append("select nodedata from xml_nodes where parentnodeid in ");
527
    query.append("(select nodeid from xml_index where path like '");
528
    query.append(nodename);
529
    query.append("' and docid like '").append(docid).append("')");
530
    try
531
    {
532
      pstmt = conn.prepareStatement(query.toString());
533
534
      // Execute the SQL query using the JDBC connection
535
      pstmt.execute();
536
      ResultSet rs = pstmt.getResultSet();
537
      boolean tableHasRows = rs.next();
538
      while (tableHasRows)
539
      {
540
        result.add(rs.getString(1));
541
        System.out.println(rs.getString(1));
542
        tableHasRows = rs.next();
543
      }
544
    }
545
    catch (SQLException e)
546
    {
547 675 berkley
      System.err.println("Error in DBQuery.getNodeContent: " + e.getMessage());
548 667 berkley
    } finally {
549
      try
550
      {
551
        pstmt.close();
552
      }
553
      catch(SQLException sqle) {}
554
    }
555 436 berkley
    return result.toArray();
556
  }
557
558
  /**
559 342 berkley
   * format a structured query as an XML document that conforms
560
   * to the pathquery.dtd and is appropriate for submission to the DBQuery
561
   * structured query engine
562
   *
563 743 jones
   * @param params The list of parameters that should be included in the query
564 342 berkley
   */
565 372 berkley
  public static String createSQuery(Hashtable params)
566 350 berkley
  {
567
    StringBuffer query = new StringBuffer();
568 342 berkley
    Enumeration elements;
569
    Enumeration keys;
570 743 jones
    String filterDoctype = null;
571 372 berkley
    String casesensitive = null;
572
    String searchmode = null;
573 342 berkley
    Object nextkey;
574
    Object nextelement;
575 350 berkley
    //add the xml headers
576
    query.append("<?xml version=\"1.0\"?>\n");
577 743 jones
    query.append("<pathquery version=\"1.0\">\n");
578
579
    if (params.containsKey("meta_file_id"))
580 342 berkley
    {
581 743 jones
      query.append("<meta_file_id>");
582 342 berkley
      query.append( ((String[])params.get("meta_file_id"))[0]);
583 535 jones
      query.append("</meta_file_id>");
584 342 berkley
    }
585 350 berkley
586 743 jones
    if (params.containsKey("returndoctype"))
587 372 berkley
    {
588 744 jones
      String[] returnDoctypes = ((String[])params.get("returndoctype"));
589
      for(int i=0; i<returnDoctypes.length; i++)
590
      {
591
        String doctype = (String)returnDoctypes[i];
592
593
        if (!doctype.equals("any") &&
594
            !doctype.equals("ANY") &&
595
            !doctype.equals("") )
596
        {
597
          query.append("<returndoctype>").append(doctype);
598
          query.append("</returndoctype>");
599
        }
600
      }
601 372 berkley
    }
602 744 jones
603 743 jones
    if (params.containsKey("filterdoctype"))
604
    {
605
      String[] filterDoctypes = ((String[])params.get("filterdoctype"));
606
      for(int i=0; i<filterDoctypes.length; i++)
607
      {
608
        query.append("<filterdoctype>").append(filterDoctypes[i]);
609
        query.append("</filterdoctype>");
610
      }
611
    }
612 372 berkley
613 743 jones
    if (params.containsKey("returnfield"))
614 401 berkley
    {
615
      String[] returnfield = ((String[])params.get("returnfield"));
616
      for(int i=0; i<returnfield.length; i++)
617
      {
618
        query.append("<returnfield>").append(returnfield[i]);
619
        query.append("</returnfield>");
620
      }
621
    }
622
623 743 jones
    if (params.containsKey("owner"))
624 535 jones
    {
625
      String[] owner = ((String[])params.get("owner"));
626
      for(int i=0; i<owner.length; i++)
627
      {
628
        query.append("<owner>").append(owner[i]);
629
        query.append("</owner>");
630
      }
631
    }
632
633 743 jones
    if (params.containsKey("site"))
634 535 jones
    {
635
      String[] site = ((String[])params.get("site"));
636
      for(int i=0; i<site.length; i++)
637
      {
638
        query.append("<site>").append(site[i]);
639
        query.append("</site>");
640
      }
641
    }
642
643 350 berkley
    //allows the dynamic switching of boolean operators
644 743 jones
    if (params.containsKey("operator"))
645 350 berkley
    {
646
      query.append("<querygroup operator=\"" +
647 535 jones
                ((String[])params.get("operator"))[0] + "\">");
648 350 berkley
    }
649
    else
650
    { //the default operator is UNION
651
      query.append("<querygroup operator=\"UNION\">");
652
    }
653 535 jones
654 743 jones
    if (params.containsKey("casesensitive"))
655 372 berkley
    {
656
      casesensitive = ((String[])params.get("casesensitive"))[0];
657
    }
658
    else
659
    {
660
      casesensitive = "false";
661
    }
662
663 743 jones
    if (params.containsKey("searchmode"))
664 372 berkley
    {
665
      searchmode = ((String[])params.get("searchmode"))[0];
666
    }
667
    else
668
    {
669
      searchmode = "contains";
670
    }
671 535 jones
672 342 berkley
    //anyfield is a special case because it does a
673
    //free text search.  It does not have a <pathexpr>
674 350 berkley
    //tag.  This allows for a free text search within the structured
675
    //query.  This is useful if the INTERSECT operator is used.
676 743 jones
    if (params.containsKey("anyfield"))
677 342 berkley
    {
678 372 berkley
       String[] anyfield = ((String[])params.get("anyfield"));
679
       //allow for more than one value for anyfield
680
       for(int i=0; i<anyfield.length; i++)
681 350 berkley
       {
682 743 jones
         if (!anyfield[i].equals(""))
683 372 berkley
         {
684
           query.append("<queryterm casesensitive=\"" + casesensitive +
685
                        "\" " + "searchmode=\"" + searchmode + "\"><value>" +
686 535 jones
                        anyfield[i] +
687
                        "</value></queryterm>");
688 372 berkley
         }
689 350 berkley
       }
690 342 berkley
    }
691 535 jones
692 342 berkley
    //this while loop finds the rest of the parameters
693
    //and attempts to query for the field specified
694
    //by the parameter.
695
    elements = params.elements();
696
    keys = params.keys();
697
    while(keys.hasMoreElements() && elements.hasMoreElements())
698
    {
699
      nextkey = keys.nextElement();
700 535 jones
      nextelement = elements.nextElement();
701 372 berkley
702 535 jones
      //make sure we aren't querying for any of these
703
      //parameters since the are already in the query
704 342 berkley
      //in one form or another.
705 743 jones
      if (!nextkey.toString().equals("returndoctype") &&
706
         !nextkey.toString().equals("filterdoctype")  &&
707 535 jones
         !nextkey.toString().equals("action")  &&
708
         !nextkey.toString().equals("qformat") &&
709
         !nextkey.toString().equals("anyfield") &&
710 401 berkley
         !nextkey.toString().equals("returnfield") &&
711 535 jones
         !nextkey.toString().equals("owner") &&
712
         !nextkey.toString().equals("site") &&
713
         !nextkey.toString().equals("operator") )
714
      {
715 372 berkley
        //allow for more than value per field name
716
        for(int i=0; i<((String[])nextelement).length; i++)
717
        {
718 743 jones
          if (!((String[])nextelement)[i].equals(""))
719 372 berkley
          {
720
            query.append("<queryterm casesensitive=\"" + casesensitive +"\" " +
721 535 jones
                         "searchmode=\"" + searchmode + "\">" +
722
                         "<value>" +
723 372 berkley
                         //add the query value
724 535 jones
                         ((String[])nextelement)[i] +
725
                         "</value><pathexpr>" +
726
                         //add the path to query by
727 372 berkley
                         nextkey.toString() +
728
                         "</pathexpr></queryterm>");
729
          }
730
        }
731 535 jones
      }
732 342 berkley
    }
733
    query.append("</querygroup></pathquery>");
734 350 berkley
    //append on the end of the xml and return the result as a string
735 342 berkley
    return query.toString();
736
  }
737
738 181 jones
  /**
739
   * format a simple free-text value query as an XML document that conforms
740
   * to the pathquery.dtd and is appropriate for submission to the DBQuery
741
   * structured query engine
742
   *
743
   * @param value the text string to search for in the xml catalog
744
   * @param doctype the type of documents to include in the result set -- use
745
   *        "any" or "ANY" for unfiltered result sets
746
   */
747
   public static String createQuery(String value, String doctype) {
748
     StringBuffer xmlquery = new StringBuffer();
749
     xmlquery.append("<?xml version=\"1.0\"?>\n");
750
     xmlquery.append("<pathquery version=\"1.0\">");
751
752
     if (!doctype.equals("any") && !doctype.equals("ANY")) {
753
       xmlquery.append("<returndoctype>");
754
       xmlquery.append(doctype).append("</returndoctype>");
755
     }
756
757
     xmlquery.append("<querygroup operator=\"UNION\">");
758 350 berkley
     //chad added - 8/14
759
     //the if statement allows a query to gracefully handle a null
760
     //query.  Without this if a nullpointerException is thrown.
761 743 jones
     if (!value.equals(""))
762 350 berkley
     {
763
       xmlquery.append("<queryterm casesensitive=\"false\" ");
764
       xmlquery.append("searchmode=\"contains\">");
765
       xmlquery.append("<value>").append(value).append("</value>");
766
       xmlquery.append("</queryterm>");
767
     }
768 181 jones
     xmlquery.append("</querygroup>");
769
     xmlquery.append("</pathquery>");
770
771
772
     return (xmlquery.toString());
773
   }
774
775
  /**
776
   * format a simple free-text value query as an XML document that conforms
777
   * to the pathquery.dtd and is appropriate for submission to the DBQuery
778
   * structured query engine
779
   *
780
   * @param value the text string to search for in the xml catalog
781
   */
782
   public static String createQuery(String value) {
783
     return createQuery(value, "any");
784
   }
785 441 bojilova
786 570 bojilova
  /**
787
    * Check for "READ" permission on @docid for @user and/or @group
788
    * from DB connection
789
    */
790
  private boolean hasPermission ( Connection conn, String user,
791 802 bojilova
                                  String[] groups, String docid )
792 605 bojilova
                  throws SQLException
793 570 bojilova
  {
794 802 bojilova
    // Check for READ permission on @docid for @user and/or @groups
795 607 bojilova
    AccessControlList aclobj = new AccessControlList(conn);
796 802 bojilova
    return aclobj.hasPermission("READ", user, groups, docid);
797 441 bojilova
  }
798
799 155 jones
}