Project

General

Profile

1 155 jones
/**
2 203 jones
 *  '$RCSfile$'
3 2043 sgarg
 *    Purpose: A Class that searches a relational DB for elements and
4 203 jones
 *             attributes that have free text matches a query string,
5 2043 sgarg
 *             or structured query matches to a path specified node in the
6
 *             XML hierarchy.  It returns a result set consisting of the
7 203 jones
 *             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 155 jones
 *
12 203 jones
 *   '$Author$'
13
 *     '$Date$'
14
 * '$Revision$'
15 669 jones
 *
16
 * This program is free software; you can redistribute it and/or modify
17
 * it under the terms of the GNU General Public License as published by
18
 * the Free Software Foundation; either version 2 of the License, or
19
 * (at your option) any later version.
20
 *
21
 * This program is distributed in the hope that it will be useful,
22
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24
 * GNU General Public License for more details.
25
 *
26
 * You should have received a copy of the GNU General Public License
27
 * along with this program; if not, write to the Free Software
28
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
29 155 jones
 */
30
31 607 bojilova
package edu.ucsb.nceas.metacat;
32 155 jones
33 5752 leinfelder
import java.io.BufferedWriter;
34
import java.io.File;
35
import java.io.FileInputStream;
36
import java.io.FileOutputStream;
37
import java.io.IOException;
38
import java.io.InputStream;
39
import java.io.InputStreamReader;
40
import java.io.OutputStreamWriter;
41
import java.io.Reader;
42
import java.io.StringReader;
43
import java.io.StringWriter;
44
import java.io.Writer;
45 2074 jones
import java.sql.PreparedStatement;
46
import java.sql.ResultSet;
47
import java.sql.SQLException;
48 6602 leinfelder
import java.sql.Timestamp;
49
import java.util.ArrayList;
50
import java.util.Date;
51 5752 leinfelder
import java.util.Enumeration;
52
import java.util.Hashtable;
53
import java.util.Iterator;
54 6602 leinfelder
import java.util.List;
55 5752 leinfelder
import java.util.StringTokenizer;
56
import java.util.Vector;
57
import java.util.zip.ZipEntry;
58
import java.util.zip.ZipOutputStream;
59 2074 jones
60 940 tao
import javax.servlet.ServletOutputStream;
61 2087 tao
import javax.servlet.http.HttpServletResponse;
62 155 jones
63 8304 jones
import org.apache.commons.io.IOUtils;
64 7677 leinfelder
import org.apache.commons.lang.StringEscapeUtils;
65 2663 sgarg
import org.apache.log4j.Logger;
66 8163 tao
import org.dataone.service.exceptions.NotImplemented;
67 2087 tao
68 8163 tao
import edu.ucsb.nceas.metacat.common.query.EnabledQueryEngines;
69 5015 daigle
import edu.ucsb.nceas.metacat.database.DBConnection;
70
import edu.ucsb.nceas.metacat.database.DBConnectionPool;
71 5030 daigle
import edu.ucsb.nceas.metacat.properties.PropertyService;
72 8163 tao
import edu.ucsb.nceas.metacat.shared.HandlerException;
73 4589 daigle
import edu.ucsb.nceas.metacat.util.AuthUtil;
74 5025 daigle
import edu.ucsb.nceas.metacat.util.DocumentUtil;
75 4698 daigle
import edu.ucsb.nceas.metacat.util.MetacatUtil;
76 4080 daigle
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
77 2074 jones
78 7475 leinfelder
import edu.ucsb.nceas.utilities.access.AccessControlInterface;
79 7403 leinfelder
import edu.ucsb.nceas.utilities.triple.Triple;
80
import edu.ucsb.nceas.utilities.triple.TripleCollection;
81 2912 harris
82 7403 leinfelder
83 2043 sgarg
/**
84 2075 jones
 * A Class that searches a relational DB for elements and attributes that have
85
 * free text matches a query string, or structured query matches to a path
86
 * specified node in the XML hierarchy. It returns a result set consisting of
87
 * the document ID for each document that satisfies the query
88 155 jones
 */
89 2075 jones
public class DBQuery
90
{
91 155 jones
92 8164 tao
    public static final String XPATHQUERYOFFINFO = "The Metacat Path Query Engine is turned off. If you want to turn it on, please contact the administrator.";
93 2075 jones
    static final int ALL = 1;
94 2043 sgarg
95 2075 jones
    static final int WRITE = 2;
96 2043 sgarg
97 2075 jones
    static final int READ = 4;
98 5490 berkley
99
    private String qformat = "xml";
100 6035 leinfelder
101
    // are we combining the query with docid list and, if so, using INTERSECT or UNION?
102
    private String operator = null;
103 155 jones
104 2075 jones
    //private Connection conn = null;
105
    private String parserName = null;
106 706 bojilova
107 2663 sgarg
    private Logger logMetacat = Logger.getLogger(DBQuery.class);
108
109 2912 harris
    /** true if the metacat spatial option is installed **/
110
    private final boolean METACAT_SPATIAL = true;
111
112 3392 tao
    /** useful if you just want to grab a list of docids. Since the docids can be very long,
113
         it is a vector of vector  **/
114 3047 perry
    Vector docidOverride = new Vector();
115 3340 tao
116
    // a hash table serves as query reuslt cache. Key of hashtable
117 3342 tao
    // is a query string and value is result xml string
118 3340 tao
    private static Hashtable queryResultCache = new Hashtable();
119
120
    // Capacity of the query result cache
121 4080 daigle
    private static final int QUERYRESULTCACHESIZE;
122
    static {
123
    	int qryRsltCacheSize = 0;
124
    	try {
125 4212 daigle
    		qryRsltCacheSize = Integer.parseInt(PropertyService.getProperty("database.queryresultCacheSize"));
126 4080 daigle
    	} catch (PropertyNotFoundException pnfe) {
127
    		System.err.println("Could not get QUERYRESULTCACHESIZE property in static block: "
128
					+ pnfe.getMessage());
129
    	}
130
    	QUERYRESULTCACHESIZE = qryRsltCacheSize;
131
    }
132
133 3047 perry
134 3368 tao
    // Size of page for non paged query
135
    private static final int NONPAGESIZE = 99999999;
136 2075 jones
    /**
137
     * the main routine used to test the DBQuery utility.
138
     * <p>
139
     * Usage: java DBQuery <xmlfile>
140 5752 leinfelder
     * NOTE: encoding should be provided for best results
141 2075 jones
     * @param xmlfile the filename of the xml file containing the query
142
     */
143
    static public void main(String[] args)
144
    {
145 706 bojilova
146 2075 jones
        if (args.length < 1) {
147
            System.err.println("Wrong number of arguments!!!");
148
            System.err.println("USAGE: java DBQuery [-t] [-index] <xmlfile>");
149
            return;
150
        } else {
151
            try {
152 706 bojilova
153 2075 jones
                int i = 0;
154
                boolean showRuntime = false;
155
                boolean useXMLIndex = false;
156
                if (args[i].equals("-t")) {
157
                    showRuntime = true;
158
                    i++;
159
                }
160
                if (args[i].equals("-index")) {
161
                    useXMLIndex = true;
162
                    i++;
163
                }
164
                String xmlfile = args[i];
165 706 bojilova
166 2075 jones
                // Time the request if asked for
167
                double startTime = System.currentTimeMillis();
168 2043 sgarg
169 2075 jones
                // Open a connection to the database
170
                //Connection dbconn = util.openDBConnection();
171 2043 sgarg
172 2075 jones
                double connTime = System.currentTimeMillis();
173 2043 sgarg
174 2075 jones
                // Execute the query
175 2752 jones
                DBQuery queryobj = new DBQuery();
176 5752 leinfelder
                Reader xml = new InputStreamReader(new FileInputStream(new File(xmlfile)));
177 2075 jones
                Hashtable nodelist = null;
178 2087 tao
                //nodelist = queryobj.findDocuments(xml, null, null, useXMLIndex);
179 2043 sgarg
180 2075 jones
                // Print the reulting document listing
181
                StringBuffer result = new StringBuffer();
182
                String document = null;
183
                String docid = null;
184
                result.append("<?xml version=\"1.0\"?>\n");
185
                result.append("<resultset>\n");
186 2043 sgarg
187 2075 jones
                if (!showRuntime) {
188
                    Enumeration doclist = nodelist.keys();
189
                    while (doclist.hasMoreElements()) {
190
                        docid = (String) doclist.nextElement();
191
                        document = (String) nodelist.get(docid);
192
                        result.append("  <document>\n    " + document
193
                                + "\n  </document>\n");
194
                    }
195 706 bojilova
196 2075 jones
                    result.append("</resultset>\n");
197
                }
198
                // Time the request if asked for
199
                double stopTime = System.currentTimeMillis();
200
                double dbOpenTime = (connTime - startTime) / 1000;
201
                double readTime = (stopTime - connTime) / 1000;
202
                double executionTime = (stopTime - startTime) / 1000;
203
                if (showRuntime) {
204
                    System.out.print("  " + executionTime);
205
                    System.out.print("  " + dbOpenTime);
206
                    System.out.print("  " + readTime);
207
                    System.out.print("  " + nodelist.size());
208
                    System.out.println();
209
                }
210
                //System.out.println(result);
211
                //write into a file "result.txt"
212
                if (!showRuntime) {
213
                    File f = new File("./result.txt");
214 5752 leinfelder
                    Writer fw = new OutputStreamWriter(new FileOutputStream(f));
215 2075 jones
                    BufferedWriter out = new BufferedWriter(fw);
216
                    out.write(result.toString());
217
                    out.flush();
218
                    out.close();
219
                    fw.close();
220
                }
221 2043 sgarg
222 2075 jones
            } catch (Exception e) {
223
                System.err.println("Error in DBQuery.main");
224
                System.err.println(e.getMessage());
225
                e.printStackTrace(System.err);
226
            }
227
        }
228
    }
229 2043 sgarg
230 2075 jones
    /**
231
     * construct an instance of the DBQuery class
232 2087 tao
     *
233 2075 jones
     * <p>
234
     * Generally, one would call the findDocuments() routine after creating an
235
     * instance to specify the search query
236
     * </p>
237 2087 tao
     *
238
239 2075 jones
     * @param parserName the fully qualified name of a Java class implementing
240
     *            the org.xml.sax.XMLReader interface
241
     */
242 4080 daigle
    public DBQuery() throws PropertyNotFoundException
243 2075 jones
    {
244 4213 daigle
        String parserName = PropertyService.getProperty("xml.saxparser");
245 2752 jones
        this.parserName = parserName;
246 2075 jones
    }
247 2043 sgarg
248 3047 perry
    /**
249
     *
250
     * Construct an instance of DBQuery Class
251
     * BUT accept a docid Vector that will supersede
252
     * the query.printSQL() method
253
     *
254
     * If a docid Vector is passed in,
255
     * the docids will be used to create a simple IN query
256
     * without the multiple subselects of the printSQL() method
257
     *
258
     * Using this constructor, we just check for
259
     * a docidOverride Vector in the findResultDoclist() method
260
     *
261
     * @param docids List of docids to display in the resultset
262
     */
263 4080 daigle
    public DBQuery(Vector docids) throws PropertyNotFoundException
264 3047 perry
    {
265 3392 tao
    	// since the query will be too long to be handled, so we divided the
266
    	// docids vector into couple vectors.
267 4212 daigle
    	int size = (new Integer(PropertyService.getProperty("database.appResultsetSize"))).intValue();
268 5165 daigle
    	logMetacat.info("DBQuery.DBQuery - The size of select doicds is "+docids.size());
269
    	logMetacat.info("DBQuery.DBQuery - The application result size in metacat.properties is "+size);
270 3392 tao
    	Vector subset = new Vector();
271
    	if (docids != null && docids.size() > size)
272
    	{
273
    		int index = 0;
274
    		for (int i=0; i< docids.size(); i++)
275
    		{
276
277
    			if (index < size)
278
    			{
279
    				subset.add(docids.elementAt(i));
280
    				index ++;
281
    			}
282
    			else
283
    			{
284
    				docidOverride.add(subset);
285
    				subset = new Vector();
286
    				subset.add(docids.elementAt(i));
287
    			    index = 1;
288
    			}
289
    		}
290
    		if (!subset.isEmpty())
291
    		{
292
    			docidOverride.add(subset);
293
    		}
294
295
    	}
296
    	else
297
    	{
298
    		this.docidOverride.add(docids);
299
    	}
300
301 4213 daigle
        String parserName = PropertyService.getProperty("xml.saxparser");
302 3047 perry
        this.parserName = parserName;
303
    }
304 2087 tao
305
  /**
306
   * Method put the search result set into out printerwriter
307
   * @param resoponse the return response
308
   * @param out the output printer
309
   * @param params the paratermer hashtable
310
   * @param user the user name (it maybe different to the one in param)
311
   * @param groups the group array
312
   * @param sessionid  the sessionid
313 8163 tao
 * @throws NotImplemented
314 2087 tao
   */
315
  public void findDocuments(HttpServletResponse response,
316 5752 leinfelder
                                       Writer out, Hashtable params,
317 2087 tao
                                       String user, String[] groups,
318 4080 daigle
                                       String sessionid) throws PropertyNotFoundException
319 2087 tao
  {
320 4173 daigle
    boolean useXMLIndex = (new Boolean(PropertyService.getProperty("database.usexmlindex")))
321 2087 tao
               .booleanValue();
322
    findDocuments(response, out, params, user, groups, sessionid, useXMLIndex);
323
324
  }
325
326
327 2075 jones
    /**
328 2087 tao
     * Method put the search result set into out printerwriter
329
     * @param resoponse the return response
330
     * @param out the output printer
331
     * @param params the paratermer hashtable
332
     * @param user the user name (it maybe different to the one in param)
333
     * @param groups the group array
334
     * @param sessionid  the sessionid
335 2075 jones
     */
336 8163 tao
    private void findDocuments(HttpServletResponse response,
337 5752 leinfelder
                                         Writer out, Hashtable params,
338 2087 tao
                                         String user, String[] groups,
339 8163 tao
                                         String sessionid, boolean useXMLIndex) {
340
      if(!EnabledQueryEngines.getInstance().isEnabled(EnabledQueryEngines.PATHQUERYENGINE)) {
341
          try {
342
              String output = "";
343
              output += "<?xml version=\"1.0\"?>";
344
              output += "<error>";
345 8164 tao
              output += XPATHQUERYOFFINFO;
346 8163 tao
              output += "</error>";
347
              out.write(output);
348
              out.close();
349
          } catch (IOException e) {
350
              logMetacat.warn("DBQuery.findDocuments - metacat can't write the message that the pathquery is off to the client since :"+e.getMessage());
351
          }
352
          return;
353
      }
354 3211 berkley
      int pagesize = 0;
355
      int pagestart = 0;
356 5165 daigle
      long transferWarnLimit = 0;
357 3211 berkley
358
      if(params.containsKey("pagesize") && params.containsKey("pagestart"))
359
      {
360
        String pagesizeStr = ((String[])params.get("pagesize"))[0];
361
        String pagestartStr = ((String[])params.get("pagestart"))[0];
362
        if(pagesizeStr != null && pagestartStr != null)
363
        {
364
          pagesize = (new Integer(pagesizeStr)).intValue();
365
          pagestart = (new Integer(pagestartStr)).intValue();
366
        }
367
      }
368
369 3780 daigle
      String xmlquery = null;
370
      String qformat = null;
371 2087 tao
      // get query and qformat
372 3780 daigle
      try {
373
    	xmlquery = ((String[])params.get("query"))[0];
374 2168 tao
375 5165 daigle
        logMetacat.info("DBQuery.findDocuments - SESSIONID: " + sessionid);
376
        logMetacat.info("DBQuery.findDocuments - xmlquery: " + xmlquery);
377 3780 daigle
        qformat = ((String[])params.get("qformat"))[0];
378 5165 daigle
        logMetacat.info("DBQuery.findDocuments - qformat: " + qformat);
379 3780 daigle
      }
380
      catch (Exception ee)
381
      {
382 5165 daigle
        logMetacat.error("DBQuery.findDocuments - Couldn't retrieve xmlquery or qformat value from "
383 3780 daigle
                  +"params hashtable in DBQuery.findDocuments: "
384
                  + ee.getMessage());
385
      }
386 2168 tao
      // Get the XML query and covert it into a SQL statment
387
      QuerySpecification qspec = null;
388
      if ( xmlquery != null)
389
      {
390
         xmlquery = transformQuery(xmlquery);
391
         try
392
         {
393
           qspec = new QuerySpecification(xmlquery,
394
                                          parserName,
395 4212 daigle
                                          PropertyService.getProperty("document.accNumSeparator"));
396 2168 tao
         }
397
         catch (Exception ee)
398
         {
399 5165 daigle
           logMetacat.error("DBQuery.findDocuments - error generating QuerySpecification object: "
400 2663 sgarg
                                    + ee.getMessage());
401 2168 tao
         }
402
      }
403 2087 tao
404 2168 tao
405
406 5025 daigle
      if (qformat != null && qformat.equals(MetacatUtil.XMLFORMAT))
407 2087 tao
      {
408
        //xml format
409 5491 berkley
        if(response != null)
410
        {
411
            response.setContentType("text/xml");
412
        }
413 5490 berkley
        createResultDocument(xmlquery, qspec, out, user, groups, useXMLIndex,
414 7417 leinfelder
          pagesize, pagestart, sessionid, qformat, false);
415 2087 tao
      }//if
416
      else
417
      {
418 8265 leinfelder
        //skin format, in this case we will get whole result and sent it out
419 3257 berkley
        response.setContentType("text/html");
420 5752 leinfelder
        Writer nonout = null;
421 2168 tao
        StringBuffer xml = createResultDocument(xmlquery, qspec, nonout, user,
422 3211 berkley
                                                groups, useXMLIndex, pagesize,
423 7417 leinfelder
                                                pagestart, sessionid, qformat, false);
424 2658 sgarg
425 2087 tao
        //transfer the xml to html
426
        try
427
        {
428 5165 daigle
         long startHTMLTransform = System.currentTimeMillis();
429 2087 tao
         DBTransform trans = new DBTransform();
430
         response.setContentType("text/html");
431 2787 sgarg
432 3219 berkley
         // if the user is a moderator, then pass a param to the
433 2787 sgarg
         // xsl specifying the fact
434 4589 daigle
         if(AuthUtil.isModerator(user, groups)){
435 2787 sgarg
        	 params.put("isModerator", new String[] {"true"});
436
         }
437
438 2087 tao
         trans.transformXMLDocument(xml.toString(), "-//NCEAS//resultset//EN",
439
                                 "-//W3C//HTML//EN", qformat, out, params,
440
                                 sessionid);
441 5165 daigle
         long transformRunTime = System.currentTimeMillis() - startHTMLTransform;
442
443
         transferWarnLimit = Long.parseLong(PropertyService.getProperty("dbquery.transformTimeWarnLimit"));
444
445
         if (transformRunTime > transferWarnLimit) {
446
         	logMetacat.warn("DBQuery.findDocuments - The time to transfrom resultset from xml to html format is "
447
                  		                             + transformRunTime);
448
         }
449 4698 daigle
          MetacatUtil.writeDebugToFile("---------------------------------------------------------------------------------------------------------------Transfrom xml to html  "
450 5165 daigle
                             + transformRunTime);
451
          MetacatUtil.writeDebugToDelimiteredFile(" " + transformRunTime, false);
452 2087 tao
        }
453
        catch(Exception e)
454
        {
455 5165 daigle
         logMetacat.error("DBQuery.findDocuments - Error in MetaCatServlet.transformResultset:"
456 2663 sgarg
                                +e.getMessage());
457 2087 tao
         }
458
459
      }//else
460
461 3219 berkley
  }
462 5490 berkley
463 3220 tao
  /**
464
   * Transforms a hashtable of documents to an xml or html result and sent
465
   * the content to outputstream. Keep going untill hastable is empty. stop it.
466
   * add the QuerySpecification as parameter is for ecogrid. But it is duplicate
467
   * to xmlquery String
468
   * @param xmlquery
469
   * @param qspec
470
   * @param out
471
   * @param user
472
   * @param groups
473
   * @param useXMLIndex
474
   * @param sessionid
475
   * @return
476
   */
477
    public StringBuffer createResultDocument(String xmlquery,
478
                                              QuerySpecification qspec,
479 5752 leinfelder
                                              Writer out,
480 3220 tao
                                              String user, String[] groups,
481
                                              boolean useXMLIndex)
482
    {
483 7417 leinfelder
    	return createResultDocument(xmlquery,qspec,out, user,groups, useXMLIndex, 0, 0,"", qformat, false);
484 3220 tao
    }
485 7417 leinfelder
486
    /**
487
     *
488
     * @param xmlquery
489
     * @param user
490
     * @param groups
491
     * @param useXMLIndex
492
     * @return
493
     * @throws IOException
494
     * @throws PropertyNotFoundException
495
     */
496
	public String performPathquery(String xmlquery, String user,
497
			String[] groups) throws PropertyNotFoundException, IOException {
498
499
		// get the XML query and convert it to query specification
500
		xmlquery = transformQuery(xmlquery);
501
		QuerySpecification qspec = new QuerySpecification(xmlquery, parserName, PropertyService.getProperty("document.accNumSeparator"));
502
503
		// force it to output the results to the string buffer, not outputstream
504
		Writer nonout = null;
505
		boolean useXMLIndex = (new Boolean(PropertyService.getProperty("database.usexmlindex"))).booleanValue();
506
		StringBuffer xml = createResultDocument(xmlquery, qspec, nonout, user, groups, useXMLIndex, 0, 0, "", qformat, true);
507 2043 sgarg
508 7417 leinfelder
		return xml.toString();
509
510
	}
511
512 2087 tao
  /*
513
   * Transforms a hashtable of documents to an xml or html result and sent
514 2168 tao
   * the content to outputstream. Keep going untill hastable is empty. stop it.
515
   * add the QuerySpecification as parameter is for ecogrid. But it is duplicate
516
   * to xmlquery String
517 2087 tao
   */
518 2168 tao
  public StringBuffer createResultDocument(String xmlquery,
519
                                            QuerySpecification qspec,
520 5752 leinfelder
                                            Writer out,
521 2087 tao
                                            String user, String[] groups,
522 3211 berkley
                                            boolean useXMLIndex, int pagesize,
523 5490 berkley
                                            int pagestart, String sessionid,
524 7417 leinfelder
                                            String qformat, boolean includeGuid)
525 2087 tao
  {
526
    DBConnection dbconn = null;
527
    int serialNumber = -1;
528
    StringBuffer resultset = new StringBuffer();
529 3219 berkley
530
    //try to get the cached version first
531 4080 daigle
    // Hashtable sessionHash = MetaCatServlet.getSessionHash();
532
    // HttpSession sess = (HttpSession)sessionHash.get(sessionid);
533 3219 berkley
534 3220 tao
535 2087 tao
    resultset.append("<?xml version=\"1.0\"?>\n");
536
    resultset.append("<resultset>\n");
537 3257 berkley
    resultset.append("  <pagestart>" + pagestart + "</pagestart>\n");
538
    resultset.append("  <pagesize>" + pagesize + "</pagesize>\n");
539
    resultset.append("  <nextpage>" + (pagestart + 1) + "</nextpage>\n");
540
    resultset.append("  <previouspage>" + (pagestart - 1) + "</previouspage>\n");
541
542 7427 leinfelder
    resultset.append("  <query><![CDATA[" + xmlquery + "]]></query>");
543 3219 berkley
    //send out a new query
544 2087 tao
    if (out != null)
545 2075 jones
    {
546 5752 leinfelder
    	try {
547
    	  out.write(resultset.toString());
548
		} catch (IOException e) {
549
			logMetacat.error(e.getMessage(), e);
550
		}
551 2075 jones
    }
552 2168 tao
    if (qspec != null)
553 2087 tao
    {
554 2168 tao
      try
555
      {
556 2043 sgarg
557 2168 tao
        //checkout the dbconnection
558
        dbconn = DBConnectionPool.getDBConnection("DBQuery.findDocuments");
559
        serialNumber = dbconn.getCheckOutSerialNumber();
560 2087 tao
561 2168 tao
        //print out the search result
562
        // search the doc list
563 3392 tao
        Vector givenDocids = new Vector();
564
        StringBuffer resultContent = new StringBuffer();
565
        if (docidOverride == null || docidOverride.size() == 0)
566
        {
567 5165 daigle
        	logMetacat.debug("DBQuery.createResultDocument - Not in map query");
568 3392 tao
        	resultContent = findResultDoclist(qspec, out, user, groups,
569
                    dbconn, useXMLIndex, pagesize, pagestart,
570 7417 leinfelder
                    sessionid, givenDocids, qformat, includeGuid);
571 3392 tao
        }
572
        else
573
        {
574 5165 daigle
        	logMetacat.debug("DBQuery.createResultDocument - In map query");
575 3392 tao
        	// since docid can be too long to be handled. We divide it into several parts
576
        	for (int i= 0; i<docidOverride.size(); i++)
577
        	{
578 5165 daigle
        	   logMetacat.debug("DBQuery.createResultDocument - in loop===== "+i);
579 3392 tao
        		givenDocids = (Vector)docidOverride.elementAt(i);
580
        		StringBuffer subset = findResultDoclist(qspec, out, user, groups,
581
                        dbconn, useXMLIndex, pagesize, pagestart,
582 7417 leinfelder
                        sessionid, givenDocids, qformat, includeGuid);
583 3392 tao
        		resultContent.append(subset);
584
        	}
585
        }
586
587 3342 tao
        resultset.append(resultContent);
588 2168 tao
      } //try
589
      catch (IOException ioe)
590
      {
591 5165 daigle
        logMetacat.error("DBQuery.createResultDocument - IO error: " + ioe.getMessage());
592 2168 tao
      }
593
      catch (SQLException e)
594
      {
595 5165 daigle
        logMetacat.error("DBQuery.createResultDocument - SQL Error: " + e.getMessage());
596 2168 tao
      }
597
      catch (Exception ee)
598
      {
599 5165 daigle
        logMetacat.error("DBQuery.createResultDocument - General exception: "
600 2663 sgarg
                                 + ee.getMessage());
601 3219 berkley
        ee.printStackTrace();
602 2168 tao
      }
603
      finally
604
      {
605
        DBConnectionPool.returnDBConnection(dbconn, serialNumber);
606
      } //finally
607
    }//if
608 2087 tao
    String closeRestultset = "</resultset>";
609
    resultset.append(closeRestultset);
610
    if (out != null)
611
    {
612 5752 leinfelder
      try {
613
		out.write(closeRestultset);
614
		} catch (IOException e) {
615
			logMetacat.error(e.getMessage(), e);
616
		}
617 2087 tao
    }
618 2168 tao
619 3221 berkley
    //default to returning the whole resultset
620 2087 tao
    return resultset;
621
  }//createResultDocuments
622 2043 sgarg
623 2087 tao
    /*
624
     * Find the doc list which match the query
625
     */
626
    private StringBuffer findResultDoclist(QuerySpecification qspec,
627 5752 leinfelder
                                      Writer out,
628 2087 tao
                                      String user, String[]groups,
629 3211 berkley
                                      DBConnection dbconn, boolean useXMLIndex,
630 5490 berkley
                                      int pagesize, int pagestart, String sessionid,
631 7417 leinfelder
                                      Vector givenDocids, String qformat, boolean includeGuid)
632 2087 tao
                                      throws Exception
633
    {
634 6602 leinfelder
    	// keep track of the values we add as prepared statement question marks (?)
635
  	  List<Object> parameterValues = new ArrayList<Object>();
636
637 3342 tao
      StringBuffer resultsetBuffer = new StringBuffer();
638 3219 berkley
      String query = null;
639
      int count = 0;
640
      int index = 0;
641 3246 berkley
      ResultDocumentSet docListResult = new ResultDocumentSet();
642 3219 berkley
      PreparedStatement pstmt = null;
643
      String docid = null;
644 7417 leinfelder
      String guid = null;
645 3219 berkley
      String docname = null;
646
      String doctype = null;
647
      String createDate = null;
648
      String updateDate = null;
649
      StringBuffer document = null;
650 3262 berkley
      boolean lastpage = false;
651 3219 berkley
      int rev = 0;
652
      double startTime = 0;
653 3368 tao
      int offset = 1;
654 5165 daigle
      long startSelectionTime = System.currentTimeMillis();
655 3219 berkley
      ResultSet rs = null;
656 3368 tao
657
658
      // this is a hack for offset. in postgresql 7, if the returned docid list is too long,
659
      //the extend query which base on the docid will be too long to be run. So we
660
      // have to cut them into different parts. Page query don't need it somehow.
661
      if (out == null)
662 2091 tao
      {
663
        // for html page, we put everything into one page
664 2421 sgarg
        offset =
665 4212 daigle
            (new Integer(PropertyService.getProperty("database.webResultsetSize"))).intValue();
666 2091 tao
      }
667
      else
668
      {
669
          offset =
670 4212 daigle
              (new Integer(PropertyService.getProperty("database.appResultsetSize"))).intValue();
671 3368 tao
      }
672 2421 sgarg
673 3047 perry
      /*
674
       * Check the docidOverride Vector
675
       * if defined, we bypass the qspec.printSQL() method
676
       * and contruct a simpler query based on a
677
       * list of docids rather than a bunch of subselects
678
       */
679 6602 leinfelder
      // keep track of the values we add as prepared statement question marks (?)
680
	  List<Object> docidValues = new ArrayList<Object>();
681 3392 tao
      if ( givenDocids == null || givenDocids.size() == 0 ) {
682 6602 leinfelder
          query = qspec.printSQL(useXMLIndex, docidValues);
683
          parameterValues.addAll(docidValues);
684 3047 perry
      } else {
685 6035 leinfelder
    	  // condition for the docids
686 6629 leinfelder
    	  List<Object> docidConditionValues = new ArrayList<Object>();
687 6035 leinfelder
    	  StringBuffer docidCondition = new StringBuffer();
688 7407 leinfelder
    	  docidCondition.append( " xml_documents.docid IN (" );
689 3392 tao
          for (int i = 0; i < givenDocids.size(); i++) {
690 6629 leinfelder
        	  docidCondition.append("?");
691 6035 leinfelder
        	  if (i < givenDocids.size()-1) {
692
        		  docidCondition.append(",");
693
        	  }
694 6629 leinfelder
        	  docidConditionValues.add((String)givenDocids.elementAt(i));
695 3047 perry
          }
696 6035 leinfelder
          docidCondition.append( ") " );
697
698
    	  // include the docids, either exclusively, or in conjuction with the query
699
    	  if (operator == null) {
700 7417 leinfelder
    		  query = "SELECT xml_documents.docid, identifier.guid, docname, doctype, date_created, date_updated, xml_documents.rev " +
701 7407 leinfelder
    		  		"FROM xml_documents, identifier " +
702
    		  		"WHERE xml_documents.docid = identifier.docid AND xml_documents.rev = identifier.rev AND ";
703 6035 leinfelder
              query = query + docidCondition.toString();
704 6629 leinfelder
              parameterValues.addAll(docidConditionValues);
705 6035 leinfelder
    	  } else {
706
    		  // start with the keyword query, but add conditions
707 6602 leinfelder
              query = qspec.printSQL(useXMLIndex, docidValues);
708
              parameterValues.addAll(docidValues);
709 6035 leinfelder
              String myOperator = "";
710 7408 leinfelder
              if (!query.endsWith("WHERE") && !query.endsWith("OR") && !query.endsWith("AND")) {
711 6035 leinfelder
	              if (operator.equalsIgnoreCase(QueryGroup.UNION)) {
712
	            	  myOperator =  " OR ";
713
	              }
714
	              else {
715
	            	  myOperator =  " AND ";
716
	              }
717
              }
718
              query = query + myOperator + docidCondition.toString();
719 6629 leinfelder
              parameterValues.addAll(docidConditionValues);
720 6035 leinfelder
721
    	  }
722 3047 perry
      }
723 6629 leinfelder
      // we don't actually use this query for anything
724
      List<Object> ownerValues = new ArrayList<Object>();
725
      String ownerQuery = getOwnerQuery(user, ownerValues);
726 4574 daigle
      //logMetacat.debug("query: " + query);
727 5165 daigle
      logMetacat.debug("DBQuery.findResultDoclist - owner query: " + ownerQuery);
728 2087 tao
      // if query is not the owner query, we need to check the permission
729
      // otherwise we don't need (owner has all permission by default)
730
      if (!query.equals(ownerQuery))
731
      {
732
        // set user name and group
733
        qspec.setUserName(user);
734
        qspec.setGroup(groups);
735
        // Get access query
736
        String accessQuery = qspec.getAccessQuery();
737 7408 leinfelder
        if(!query.endsWith("AND")){
738 2366 sgarg
            query = query + accessQuery;
739
        } else {
740
            query = query + accessQuery.substring(4, accessQuery.length());
741
        }
742 3309 tao
743 2087 tao
      }
744 5165 daigle
      logMetacat.debug("DBQuery.findResultDoclist - final selection query: " + query);
745 6774 tao
746
747
      pstmt = dbconn.prepareStatement(query);
748
      // set all the values we have collected
749
      pstmt = setPreparedStatementValues(parameterValues, pstmt);
750
751
      String queryCacheKey = null;
752 3342 tao
      // we only get cache for public
753
      if (user != null && user.equalsIgnoreCase("public")
754 6774 tao
         && pagesize == 0 && PropertyService.getProperty("database.queryCacheOn").equals("true"))
755 3342 tao
      {
756 6774 tao
          queryCacheKey = pstmt.toString() +qspec.getReturnDocList()+qspec.getReturnFieldList();
757
          String cachedResult = getResultXMLFromCache(queryCacheKey);
758
          logMetacat.debug("=======DBQuery.findResultDoclist - The key of query cache is " + queryCacheKey);
759
          //System.out.println("==========the string from cache is "+cachedResult);
760
          if (cachedResult != null)
761
          {
762
          logMetacat.info("DBQuery.findResultDoclist - result from cache !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
763
           if (out != null)
764
             {
765
                 out.write(cachedResult);
766
             }
767
           resultsetBuffer.append(cachedResult);
768
           pstmt.close();
769
           return resultsetBuffer;
770
          }
771 3342 tao
      }
772
773 3219 berkley
      startTime = System.currentTimeMillis() / 1000;
774 6602 leinfelder
      logMetacat.debug("Prepared statement after setting parameter values: " + pstmt.toString());
775 3219 berkley
      rs = pstmt.executeQuery();
776 3246 berkley
777 2087 tao
      double queryExecuteTime = System.currentTimeMillis() / 1000;
778 5165 daigle
      logMetacat.debug("DBQuery.findResultDoclist - Time to execute select docid query is "
779 2663 sgarg
                    + (queryExecuteTime - startTime));
780 4698 daigle
      MetacatUtil.writeDebugToFile("\n\n\n\n\n\nExecute selection query  "
781 3271 tao
              + (queryExecuteTime - startTime));
782 4698 daigle
      MetacatUtil.writeDebugToDelimiteredFile(""+(queryExecuteTime - startTime), false);
783 3246 berkley
784 3247 berkley
      boolean tableHasRows = rs.next();
785 3246 berkley
786
      if(pagesize == 0)
787
      { //this makes sure we get all results if there is no paging
788 3368 tao
        pagesize = NONPAGESIZE;
789
        pagestart = NONPAGESIZE;
790 3246 berkley
      }
791
792
      int currentIndex = 0;
793 2087 tao
      while (tableHasRows)
794
      {
795 5165 daigle
        logMetacat.debug("DBQuery.findResultDoclist - getting result: " + currentIndex);
796 2087 tao
        docid = rs.getString(1).trim();
797 7417 leinfelder
        logMetacat.debug("DBQuery.findResultDoclist -  docid: " + docid);
798
        guid = rs.getString(2).trim();
799
        logMetacat.debug("DBQuery.findResultDoclist -  guid: " + guid);
800
        docname = rs.getString(3);
801
        doctype = rs.getString(4);
802
        logMetacat.debug("DBQuery.findResultDoclist - doctype: " + doctype);
803
        createDate = rs.getString(5);
804
        updateDate = rs.getString(6);
805
        rev = rs.getInt(7);
806 3246 berkley
807 3307 tao
         Vector returndocVec = qspec.getReturnDocList();
808
       if (returndocVec.size() == 0 || returndocVec.contains(doctype))
809 2087 tao
        {
810 5165 daigle
          logMetacat.debug("DBQuery.findResultDoclist - NOT Back tracing now...");
811 2087 tao
           document = new StringBuffer();
812 2043 sgarg
813 2087 tao
           String completeDocid = docid
814 4212 daigle
                            + PropertyService.getProperty("document.accNumSeparator");
815 2087 tao
           completeDocid += rev;
816
           document.append("<docid>").append(completeDocid).append("</docid>");
817 7417 leinfelder
           if (includeGuid) {
818
        	   document.append("<guid>").append(guid).append("</guid>");
819
           }
820 2087 tao
           if (docname != null)
821
           {
822
               document.append("<docname>" + docname + "</docname>");
823 3219 berkley
           }
824
           if (doctype != null)
825
           {
826
              document.append("<doctype>" + doctype + "</doctype>");
827
           }
828
           if (createDate != null)
829
           {
830
               document.append("<createdate>" + createDate + "</createdate>");
831
           }
832
           if (updateDate != null)
833
           {
834
             document.append("<updatedate>" + updateDate + "</updatedate>");
835
           }
836
           // Store the document id and the root node id
837 3246 berkley
838
           docListResult.addResultDocument(
839
             new ResultDocument(docid, (String) document.toString()));
840 5165 daigle
           logMetacat.info("DBQuery.findResultDoclist - real result: " + docid);
841 3246 berkley
           currentIndex++;
842 3219 berkley
           count++;
843 2087 tao
        }//else
844 3246 berkley
845 2087 tao
        // when doclist reached the offset number, send out doc list and empty
846
        // the hash table
847 3368 tao
        if (count == offset && pagesize == NONPAGESIZE)
848 3246 berkley
        { //if pagesize is not 0, do this later.
849 2087 tao
          //reset count
850 3262 berkley
          //logMetacat.warn("############doing subset cache");
851 2087 tao
          count = 0;
852 3246 berkley
          handleSubsetResult(qspec, resultsetBuffer, out, docListResult,
853 5490 berkley
                              user, groups,dbconn, useXMLIndex, qformat);
854 3246 berkley
          //reset docListResult
855
          docListResult = new ResultDocumentSet();
856 3368 tao
        }
857 3246 berkley
858 5165 daigle
       logMetacat.debug("DBQuery.findResultDoclist - currentIndex: " + currentIndex);
859
       logMetacat.debug("DBQuery.findResultDoclist - page comparator: " + (pagesize * pagestart) + pagesize);
860 3246 berkley
       if(currentIndex >= ((pagesize * pagestart) + pagesize))
861
       {
862
         ResultDocumentSet pagedResultsHash = new ResultDocumentSet();
863
         for(int i=pagesize*pagestart; i<docListResult.size(); i++)
864
         {
865
           pagedResultsHash.put(docListResult.get(i));
866
         }
867
868
         docListResult = pagedResultsHash;
869
         break;
870
       }
871 2087 tao
       // Advance to the next record in the cursor
872
       tableHasRows = rs.next();
873 3246 berkley
       if(!tableHasRows)
874
       {
875 3262 berkley
         ResultDocumentSet pagedResultsHash = new ResultDocumentSet();
876
         //get the last page of information then break
877 3368 tao
         if(pagesize != NONPAGESIZE)
878 3262 berkley
         {
879
           for(int i=pagesize*pagestart; i<docListResult.size(); i++)
880
           {
881
             pagedResultsHash.put(docListResult.get(i));
882
           }
883
           docListResult = pagedResultsHash;
884
         }
885
886
         lastpage = true;
887 3246 berkley
         break;
888
       }
889 2087 tao
     }//while
890 3246 berkley
891 2087 tao
     rs.close();
892
     pstmt.close();
893 5165 daigle
     long docListTime = System.currentTimeMillis() - startSelectionTime;
894
     long docListWarnLimit = Long.parseLong(PropertyService.getProperty("dbquery.findDocListTimeWarnLimit"));
895
     if (docListTime > docListWarnLimit) {
896
    	 logMetacat.warn("DBQuery.findResultDoclist - Total time to get docid list is: "
897
                          + docListTime);
898
     }
899 4698 daigle
     MetacatUtil.writeDebugToFile("---------------------------------------------------------------------------------------------------------------Total selection: "
900 5165 daigle
             + docListTime);
901
     MetacatUtil.writeDebugToDelimiteredFile(" "+ docListTime, false);
902 2087 tao
     //if docListResult is not empty, it need to be sent.
903 3246 berkley
     if (docListResult.size() != 0)
904 2087 tao
     {
905 3342 tao
906 2087 tao
       handleSubsetResult(qspec,resultsetBuffer, out, docListResult,
907 5490 berkley
                              user, groups,dbconn, useXMLIndex, qformat);
908 2087 tao
     }
909 2091 tao
910 3262 berkley
     resultsetBuffer.append("\n<lastpage>" + lastpage + "</lastpage>\n");
911
     if (out != null)
912
     {
913 5752 leinfelder
         out.write("\n<lastpage>" + lastpage + "</lastpage>\n");
914 3262 berkley
     }
915 3342 tao
916
     // now we only cached none-paged query and user is public
917
     if (user != null && user.equalsIgnoreCase("public")
918 4212 daigle
    		 && pagesize == NONPAGESIZE && PropertyService.getProperty("database.queryCacheOn").equals("true"))
919 3342 tao
     {
920
       //System.out.println("the string stored into cache is "+ resultsetBuffer.toString());
921 6774 tao
  	   storeQueryResultIntoCache(queryCacheKey, resultsetBuffer.toString());
922 3342 tao
     }
923 3262 berkley
924 2087 tao
     return resultsetBuffer;
925
    }//findReturnDoclist
926 2043 sgarg
927
928 2087 tao
    /*
929
     * Send completed search hashtable(part of reulst)to output stream
930
     * and buffer into a buffer stream
931
     */
932
    private StringBuffer handleSubsetResult(QuerySpecification qspec,
933
                                           StringBuffer resultset,
934 5752 leinfelder
                                           Writer out, ResultDocumentSet partOfDoclist,
935 2087 tao
                                           String user, String[]groups,
936 5490 berkley
                                       DBConnection dbconn, boolean useXMLIndex,
937
                                       String qformat)
938 2087 tao
                                       throws Exception
939
   {
940 5165 daigle
     double startReturnFieldTime = System.currentTimeMillis();
941 2424 sgarg
     // check if there is a record in xml_returnfield
942
     // and get the returnfield_id and usage count
943
     int usage_count = getXmlReturnfieldsTableId(qspec, dbconn);
944
     boolean enterRecords = false;
945
946 4212 daigle
     // get value of database.xmlReturnfieldCount
947 4080 daigle
     int count = (new Integer(PropertyService
948 4212 daigle
                            .getProperty("database.xmlReturnfieldCount")))
949 2424 sgarg
                            .intValue();
950 2430 sgarg
951 2446 sgarg
     // set enterRecords to true if usage_count is more than the offset
952 2430 sgarg
     // specified in metacat.properties
953 2424 sgarg
     if(usage_count > count){
954
         enterRecords = true;
955
     }
956 3257 berkley
957 2421 sgarg
     if(returnfield_id < 0){
958 5165 daigle
         logMetacat.warn("DBQuery.handleSubsetResult - Error in getting returnfield id from"
959 2663 sgarg
                                  + "xml_returnfield table");
960 3227 berkley
         enterRecords = false;
961 2421 sgarg
     }
962
963
     // get the hashtable containing the docids that already in the
964
     // xml_queryresult table
965 5165 daigle
     logMetacat.info("DBQuery.handleSubsetResult - size of partOfDoclist before"
966 2421 sgarg
                             + " docidsInQueryresultTable(): "
967 2663 sgarg
                             + partOfDoclist.size());
968 5165 daigle
     long startGetReturnValueFromQueryresultable = System.currentTimeMillis();
969 2421 sgarg
     Hashtable queryresultDocList = docidsInQueryresultTable(returnfield_id,
970
                                                        partOfDoclist, dbconn);
971
972
     // remove the keys in queryresultDocList from partOfDoclist
973
     Enumeration _keys = queryresultDocList.keys();
974
     while (_keys.hasMoreElements()){
975 3246 berkley
         partOfDoclist.remove((String)_keys.nextElement());
976 2421 sgarg
     }
977 5165 daigle
978
     long queryResultReturnValuetime = System.currentTimeMillis() - startGetReturnValueFromQueryresultable;
979
     long queryResultWarnLimit =
980
    	 Long.parseLong(PropertyService.getProperty("dbquery.findQueryResultsTimeWarnLimit"));
981
982
     if (queryResultReturnValuetime > queryResultWarnLimit) {
983
    	 logMetacat.warn("DBQuery.handleSubsetResult - Time to get return fields from xml_queryresult table is (Part1 in return fields) " +
984
    		 queryResultReturnValuetime);
985
     }
986 4698 daigle
     MetacatUtil.writeDebugToFile("-----------------------------------------Get fields from xml_queryresult(Part1 in return fields) " +
987 5165 daigle
    		 queryResultReturnValuetime);
988
     MetacatUtil.writeDebugToDelimiteredFile(" " + queryResultReturnValuetime,false);
989
990
     long startExtendedQuery = System.currentTimeMillis();
991 2425 sgarg
     // backup the keys-elements in partOfDoclist to check later
992
     // if the doc entry is indexed yet
993
     Hashtable partOfDoclistBackup = new Hashtable();
994 3246 berkley
     Iterator itt = partOfDoclist.getDocids();
995
     while (itt.hasNext()){
996
       Object key = itt.next();
997 2425 sgarg
         partOfDoclistBackup.put(key, partOfDoclist.get(key));
998
     }
999
1000 5165 daigle
     logMetacat.info("DBQuery.handleSubsetResult - size of partOfDoclist after"
1001 2421 sgarg
                             + " docidsInQueryresultTable(): "
1002 2663 sgarg
                             + partOfDoclist.size());
1003 2421 sgarg
1004
     //add return fields for the documents in partOfDoclist
1005
     partOfDoclist = addReturnfield(partOfDoclist, qspec, user, groups,
1006 5490 berkley
                                        dbconn, useXMLIndex, qformat);
1007 5165 daigle
     long extendedQueryRunTime = startExtendedQuery - System.currentTimeMillis();
1008
     long extendedQueryWarnLimit =
1009
    	 Long.parseLong(PropertyService.getProperty("dbquery.extendedQueryRunTimeWarnLimit"));
1010
1011
     if (extendedQueryRunTime > extendedQueryWarnLimit) {
1012
    	 logMetacat.warn("DBQuery.handleSubsetResult - Get fields from index and node table (Part2 in return fields) "
1013
        		                                          + extendedQueryRunTime);
1014
     }
1015 4698 daigle
     MetacatUtil.writeDebugToFile("-----------------------------------------Get fields from extened query(Part2 in return fields) "
1016 5165 daigle
             + extendedQueryRunTime);
1017 4698 daigle
     MetacatUtil.writeDebugToDelimiteredFile(" "
1018 5165 daigle
             + extendedQueryRunTime, false);
1019 2421 sgarg
     //add relationship part part docid list for the documents in partOfDocList
1020 3730 tao
     //partOfDoclist = addRelationship(partOfDoclist, qspec, dbconn, useXMLIndex);
1021 2421 sgarg
1022 5165 daigle
     long startStoreReturnField = System.currentTimeMillis();
1023 3246 berkley
     Iterator keys = partOfDoclist.getDocids();
1024 2087 tao
     String key = null;
1025
     String element = null;
1026 2421 sgarg
     String query = null;
1027 4080 daigle
     int offset = (new Integer(PropertyService
1028 4212 daigle
                               .getProperty("database.queryresultStringLength")))
1029 2421 sgarg
                               .intValue();
1030 3246 berkley
     while (keys.hasNext())
1031 2087 tao
     {
1032 3246 berkley
         key = (String) keys.next();
1033 2421 sgarg
         element = (String)partOfDoclist.get(key);
1034 3350 tao
1035 2446 sgarg
	 // check if the enterRecords is true, elements is not null, element's
1036
         // length is less than the limit of table column and if the document
1037 2425 sgarg
         // has been indexed already
1038 2446 sgarg
         if(enterRecords && element != null
1039 2425 sgarg
		&& element.length() < offset
1040
		&& element.compareTo((String) partOfDoclistBackup.get(key)) != 0){
1041 2421 sgarg
             query = "INSERT INTO xml_queryresult (returnfield_id, docid, "
1042 2446 sgarg
                 + "queryresult_string) VALUES (?, ?, ?)";
1043
1044 2421 sgarg
             PreparedStatement pstmt = null;
1045
             pstmt = dbconn.prepareStatement(query);
1046 2446 sgarg
             pstmt.setInt(1, returnfield_id);
1047
             pstmt.setString(2, key);
1048
             pstmt.setString(3, element);
1049 3350 tao
1050 2421 sgarg
             dbconn.increaseUsageCount(1);
1051 3350 tao
             try
1052
             {
1053
            	 pstmt.execute();
1054
             }
1055
             catch(Exception e)
1056
             {
1057 5165 daigle
            	 logMetacat.warn("DBQuery.handleSubsetResult - couldn't insert the element to xml_queryresult table "+e.getLocalizedMessage());
1058 3350 tao
             }
1059
             finally
1060
             {
1061
                pstmt.close();
1062
             }
1063 2421 sgarg
         }
1064 3263 tao
1065 2421 sgarg
         // A string with element
1066
         String xmlElement = "  <document>" + element + "</document>";
1067 3257 berkley
1068 2421 sgarg
         //send single element to output
1069
         if (out != null)
1070
         {
1071 5752 leinfelder
             out.write(xmlElement);
1072 2421 sgarg
         }
1073
         resultset.append(xmlElement);
1074
     }//while
1075 3263 tao
1076 5165 daigle
     double storeReturnFieldTime = System.currentTimeMillis() - startStoreReturnField;
1077
     long storeReturnFieldWarnLimit =
1078
    	 Long.parseLong(PropertyService.getProperty("dbquery.storeReturnFieldTimeWarnLimit"));
1079
1080
     if (storeReturnFieldTime > storeReturnFieldWarnLimit) {
1081
    	 logMetacat.warn("DBQuery.handleSubsetResult - Time to store new return fields into xml_queryresult table (Part4 in return fields) "
1082
                   + storeReturnFieldTime);
1083
     }
1084 4698 daigle
     MetacatUtil.writeDebugToFile("-----------------------------------------Insert new record to xml_queryresult(Part4 in return fields) "
1085 5165 daigle
             + storeReturnFieldTime);
1086
     MetacatUtil.writeDebugToDelimiteredFile(" " + storeReturnFieldTime, false);
1087 3263 tao
1088 3246 berkley
     Enumeration keysE = queryresultDocList.keys();
1089
     while (keysE.hasMoreElements())
1090 2421 sgarg
     {
1091 3246 berkley
         key = (String) keysE.nextElement();
1092 2421 sgarg
         element = (String)queryresultDocList.get(key);
1093
         // A string with element
1094
         String xmlElement = "  <document>" + element + "</document>";
1095
         //send single element to output
1096
         if (out != null)
1097
         {
1098 5752 leinfelder
             out.write(xmlElement);
1099 2421 sgarg
         }
1100
         resultset.append(xmlElement);
1101
     }//while
1102 5165 daigle
     double returnFieldTime = System.currentTimeMillis() - startReturnFieldTime;
1103
     long totalReturnFieldWarnLimit =
1104
    	 Long.parseLong(PropertyService.getProperty("dbquery.totalReturnFieldTimeWarnLimit"));
1105
1106
     if (returnFieldTime > totalReturnFieldWarnLimit) {
1107
    	 logMetacat.warn("DBQuery.handleSubsetResult - Total time to get return fields is: "
1108
                           + returnFieldTime);
1109
     }
1110
     MetacatUtil.writeDebugToFile("DBQuery.handleSubsetResult - ---------------------------------------------------------------------------------------------------------------"+
1111
    		 "Total to get return fields  " + returnFieldTime);
1112
     MetacatUtil.writeDebugToDelimiteredFile("DBQuery.handleSubsetResult - "+ returnFieldTime, false);
1113 2421 sgarg
     return resultset;
1114
 }
1115
1116
   /**
1117
    * Get the docids already in xml_queryresult table and corresponding
1118
    * queryresultstring as a hashtable
1119
    */
1120
   private Hashtable docidsInQueryresultTable(int returnfield_id,
1121 3246 berkley
                                              ResultDocumentSet partOfDoclist,
1122 2421 sgarg
                                              DBConnection dbconn){
1123
1124
         Hashtable returnValue = new Hashtable();
1125
         PreparedStatement pstmt = null;
1126
         ResultSet rs = null;
1127 6629 leinfelder
1128
         // keep track of parameter values
1129
         List<Object> parameterValues = new ArrayList<Object>();
1130 2421 sgarg
1131
         // get partOfDoclist as string for the query
1132 3246 berkley
         Iterator keylist = partOfDoclist.getDocids();
1133 2421 sgarg
         StringBuffer doclist = new StringBuffer();
1134 3246 berkley
         while (keylist.hasNext())
1135 2421 sgarg
         {
1136 6629 leinfelder
             doclist.append("?,");
1137
             parameterValues.add((String) keylist.next());
1138 2421 sgarg
         }//while
1139
1140
         if (doclist.length() > 0)
1141
         {
1142
             doclist.deleteCharAt(doclist.length() - 1); //remove the last comma
1143
1144
             // the query to find out docids from xml_queryresult
1145
             String query = "select docid, queryresult_string from "
1146
                          + "xml_queryresult where returnfield_id = " +
1147
                          returnfield_id +" and docid in ("+ doclist + ")";
1148 5165 daigle
             logMetacat.info("DBQuery.docidsInQueryresultTable - Query to get docids from xml_queryresult:"
1149 2663 sgarg
                                      + query);
1150 2421 sgarg
1151
             try {
1152
                 // prepare and execute the query
1153
                 pstmt = dbconn.prepareStatement(query);
1154 6629 leinfelder
                 // bind parameter values
1155
                 pstmt = setPreparedStatementValues(parameterValues, pstmt);
1156
1157 2421 sgarg
                 dbconn.increaseUsageCount(1);
1158
                 pstmt.execute();
1159
                 rs = pstmt.getResultSet();
1160
                 boolean tableHasRows = rs.next();
1161
                 while (tableHasRows) {
1162
                     // store the returned results in the returnValue hashtable
1163
                     String key = rs.getString(1);
1164
                     String element = rs.getString(2);
1165
1166
                     if(element != null){
1167
                         returnValue.put(key, element);
1168
                     } else {
1169 5165 daigle
                         logMetacat.info("DBQuery.docidsInQueryresultTable - Null elment found ("
1170 2663 sgarg
                         + "DBQuery.docidsInQueryresultTable)");
1171 2421 sgarg
                     }
1172
                     tableHasRows = rs.next();
1173
                 }
1174
                 rs.close();
1175
                 pstmt.close();
1176
             } catch (Exception e){
1177 5165 daigle
                 logMetacat.error("DBQuery.docidsInQueryresultTable - Error getting docids from "
1178
                                          + "queryresult: " + e.getMessage());
1179 2421 sgarg
              }
1180
         }
1181
         return returnValue;
1182
     }
1183
1184
1185
   /**
1186
    * Method to get id from xml_returnfield table
1187
    * for a given query specification
1188
    */
1189 2424 sgarg
   private int returnfield_id;
1190 2421 sgarg
   private int getXmlReturnfieldsTableId(QuerySpecification qspec,
1191
                                           DBConnection dbconn){
1192
       int id = -1;
1193 2424 sgarg
       int count = 1;
1194 2421 sgarg
       PreparedStatement pstmt = null;
1195
       ResultSet rs = null;
1196
       String returnfield = qspec.getSortedReturnFieldString();
1197
1198
       // query for finding the id from xml_returnfield
1199 2446 sgarg
       String query = "SELECT returnfield_id, usage_count FROM xml_returnfield "
1200
            + "WHERE returnfield_string LIKE ?";
1201 5165 daigle
       logMetacat.info("DBQuery.getXmlReturnfieldsTableId - ReturnField Query:" + query);
1202 2421 sgarg
1203
       try {
1204
           // prepare and run the query
1205
           pstmt = dbconn.prepareStatement(query);
1206 2446 sgarg
           pstmt.setString(1,returnfield);
1207 2421 sgarg
           dbconn.increaseUsageCount(1);
1208
           pstmt.execute();
1209
           rs = pstmt.getResultSet();
1210
           boolean tableHasRows = rs.next();
1211
1212
           // if record found then increase the usage count
1213
           // else insert a new record and get the id of the new record
1214
           if(tableHasRows){
1215
               // get the id
1216
               id = rs.getInt(1);
1217 2424 sgarg
               count = rs.getInt(2) + 1;
1218 2421 sgarg
               rs.close();
1219
               pstmt.close();
1220
1221
               // increase the usage count
1222 6629 leinfelder
               query = "UPDATE xml_returnfield SET usage_count = ?"
1223
                   + " WHERE returnfield_id = ?";
1224 5165 daigle
               logMetacat.info("DBQuery.getXmlReturnfieldsTableId - ReturnField Table Update:"+ query);
1225 2421 sgarg
1226
               pstmt = dbconn.prepareStatement(query);
1227 6629 leinfelder
               pstmt.setInt(1, count);
1228
               pstmt.setInt(2, id);
1229 2421 sgarg
               dbconn.increaseUsageCount(1);
1230
               pstmt.execute();
1231
               pstmt.close();
1232
1233
           } else {
1234
               rs.close();
1235
               pstmt.close();
1236
1237
               // insert a new record
1238
               query = "INSERT INTO xml_returnfield (returnfield_string, usage_count)"
1239 2446 sgarg
                   + "VALUES (?, '1')";
1240 5165 daigle
               logMetacat.info("DBQuery.getXmlReturnfieldsTableId - ReturnField Table Insert:"+ query);
1241 2421 sgarg
               pstmt = dbconn.prepareStatement(query);
1242 2446 sgarg
               pstmt.setString(1, returnfield);
1243 2421 sgarg
               dbconn.increaseUsageCount(1);
1244
               pstmt.execute();
1245
               pstmt.close();
1246
1247
               // get the id of the new record
1248 2446 sgarg
               query = "SELECT returnfield_id FROM xml_returnfield "
1249
                   + "WHERE returnfield_string LIKE ?";
1250 5165 daigle
               logMetacat.info("DBQuery.getXmlReturnfieldsTableId - ReturnField query after Insert:" + query);
1251 2421 sgarg
               pstmt = dbconn.prepareStatement(query);
1252 2446 sgarg
               pstmt.setString(1, returnfield);
1253
1254 2421 sgarg
               dbconn.increaseUsageCount(1);
1255
               pstmt.execute();
1256
               rs = pstmt.getResultSet();
1257
               if(rs.next()){
1258
                   id = rs.getInt(1);
1259
               } else {
1260
                   id = -1;
1261
               }
1262
               rs.close();
1263
               pstmt.close();
1264 2087 tao
           }
1265 2091 tao
1266 2421 sgarg
       } catch (Exception e){
1267 5165 daigle
           logMetacat.error("DBQuery.getXmlReturnfieldsTableId - Error getting id from xml_returnfield in "
1268 2421 sgarg
                                     + "DBQuery.getXmlReturnfieldsTableId: "
1269 2663 sgarg
                                     + e.getMessage());
1270 2421 sgarg
           id = -1;
1271
       }
1272 2424 sgarg
1273
       returnfield_id = id;
1274
       return count;
1275 2087 tao
   }
1276 2043 sgarg
1277
1278 2087 tao
    /*
1279
     * A method to add return field to return doclist hash table
1280
     */
1281 3246 berkley
    private ResultDocumentSet addReturnfield(ResultDocumentSet docListResult,
1282 2087 tao
                                      QuerySpecification qspec,
1283
                                      String user, String[]groups,
1284 5490 berkley
                                      DBConnection dbconn, boolean useXMLIndex,
1285
                                      String qformat)
1286 2087 tao
                                      throws Exception
1287
    {
1288
      PreparedStatement pstmt = null;
1289
      ResultSet rs = null;
1290
      String docid = null;
1291
      String fieldname = null;
1292 3635 leinfelder
      String fieldtype = null;
1293 2087 tao
      String fielddata = null;
1294
      String relation = null;
1295 6629 leinfelder
      // keep track of parameter values
1296
      List<Object> parameterValues = new ArrayList<Object>();
1297 2087 tao
1298
      if (qspec.containsExtendedSQL())
1299
      {
1300
        qspec.setUserName(user);
1301
        qspec.setGroup(groups);
1302
        Vector extendedFields = new Vector(qspec.getReturnFieldList());
1303
        Vector results = new Vector();
1304 3246 berkley
        Iterator keylist = docListResult.getDocids();
1305 2087 tao
        StringBuffer doclist = new StringBuffer();
1306 6629 leinfelder
        List<Object> doclistValues = new ArrayList<Object>();
1307 2087 tao
        Vector parentidList = new Vector();
1308
        Hashtable returnFieldValue = new Hashtable();
1309 3246 berkley
        while (keylist.hasNext())
1310 2087 tao
        {
1311 5490 berkley
          String key = (String)keylist.next();
1312 6629 leinfelder
          doclist.append("?,");
1313
          doclistValues.add(key);
1314 2087 tao
        }
1315
        if (doclist.length() > 0)
1316
        {
1317
          Hashtable controlPairs = new Hashtable();
1318
          doclist.deleteCharAt(doclist.length() - 1); //remove the last comma
1319 3248 tao
          boolean tableHasRows = false;
1320 3349 tao
1321 2087 tao
1322 6629 leinfelder
1323 2087 tao
           String extendedQuery =
1324 6734 leinfelder
               qspec.printExtendedSQL(doclist.toString(), useXMLIndex, parameterValues, doclistValues);
1325
           // DO not add doclist values -- they are included in the query
1326
           //parameterValues.addAll(doclistValues);
1327 5165 daigle
           logMetacat.info("DBQuery.addReturnfield - Extended query: " + extendedQuery);
1328 2376 sgarg
1329 2474 sgarg
           if(extendedQuery != null){
1330 5165 daigle
//        	   long extendedQueryStart = System.currentTimeMillis();
1331 2474 sgarg
               pstmt = dbconn.prepareStatement(extendedQuery);
1332 6602 leinfelder
               // set the parameter values
1333
               pstmt = DBQuery.setPreparedStatementValues(parameterValues, pstmt);
1334 2474 sgarg
               //increase dbconnection usage count
1335
               dbconn.increaseUsageCount(1);
1336
               pstmt.execute();
1337
               rs = pstmt.getResultSet();
1338
               tableHasRows = rs.next();
1339
               while (tableHasRows) {
1340
                   ReturnFieldValue returnValue = new ReturnFieldValue();
1341
                   docid = rs.getString(1).trim();
1342
                   fieldname = rs.getString(2);
1343 5490 berkley
1344
                   if(qformat.toLowerCase().trim().equals("xml"))
1345
                   {
1346
                       byte[] b = rs.getBytes(3);
1347 5756 leinfelder
                       fielddata = new String(b, 0, b.length, MetaCatServlet.DEFAULT_ENCODING);
1348 5490 berkley
                   }
1349
                   else
1350
                   {
1351
                       fielddata = rs.getString(3);
1352
                   }
1353
1354
                   //System.out.println("raw fielddata: " + fielddata);
1355 4698 daigle
                   fielddata = MetacatUtil.normalize(fielddata);
1356 5490 berkley
                   //System.out.println("normalized fielddata: " + fielddata);
1357 2474 sgarg
                   String parentId = rs.getString(4);
1358 3635 leinfelder
                   fieldtype = rs.getString(5);
1359 2474 sgarg
                   StringBuffer value = new StringBuffer();
1360 2043 sgarg
1361 3635 leinfelder
                   //handle case when usexmlindex is true differently
1362
                   //at one point merging the nodedata (for large text elements) was
1363
                   //deemed unnecessary - but now it is needed.  but not for attribute nodes
1364 2474 sgarg
                   if (useXMLIndex || !containsKey(parentidList, parentId)) {
1365 3635 leinfelder
                	   //merge node data only for non-ATTRIBUTEs
1366
                	   if (fieldtype != null && !fieldtype.equals("ATTRIBUTE")) {
1367
	                	   //try merging the data
1368
	                	   ReturnFieldValue existingRFV =
1369
	                		   getArrayValue(parentidList, parentId);
1370 5387 berkley
	                	   if (existingRFV != null && !existingRFV.getFieldType().equals("ATTRIBUTE")) {
1371 3635 leinfelder
	                		   fielddata = existingRFV.getFieldValue() + fielddata;
1372
	                	   }
1373
                	   }
1374 5387 berkley
                	   //System.out.println("fieldname: " + fieldname + " fielddata: " + fielddata);
1375 5490 berkley
1376 2474 sgarg
                       value.append("<param name=\"");
1377
                       value.append(fieldname);
1378
                       value.append("\">");
1379
                       value.append(fielddata);
1380
                       value.append("</param>");
1381
                       //set returnvalue
1382
                       returnValue.setDocid(docid);
1383
                       returnValue.setFieldValue(fielddata);
1384 3635 leinfelder
                       returnValue.setFieldType(fieldtype);
1385 2474 sgarg
                       returnValue.setXMLFieldValue(value.toString());
1386
                       // Store it in hastable
1387
                       putInArray(parentidList, parentId, returnValue);
1388
                   }
1389
                   else {
1390 5490 berkley
1391 2474 sgarg
                       // need to merge nodedata if they have same parent id and
1392
                       // node type is text
1393
                       fielddata = (String) ( (ReturnFieldValue)
1394
                                             getArrayValue(
1395
                           parentidList, parentId)).getFieldValue()
1396
                           + fielddata;
1397 5490 berkley
                       //System.out.println("fieldname: " + fieldname + " fielddata: " + fielddata);
1398 2474 sgarg
                       value.append("<param name=\"");
1399
                       value.append(fieldname);
1400
                       value.append("\">");
1401
                       value.append(fielddata);
1402
                       value.append("</param>");
1403
                       returnValue.setDocid(docid);
1404
                       returnValue.setFieldValue(fielddata);
1405 3635 leinfelder
                       returnValue.setFieldType(fieldtype);
1406 2474 sgarg
                       returnValue.setXMLFieldValue(value.toString());
1407
                       // remove the old return value from paretnidList
1408
                       parentidList.remove(parentId);
1409
                       // store the new return value in parentidlit
1410
                       putInArray(parentidList, parentId, returnValue);
1411
                   }
1412
                   tableHasRows = rs.next();
1413
               } //while
1414
               rs.close();
1415
               pstmt.close();
1416 2043 sgarg
1417 2474 sgarg
               // put the merger node data info into doclistReult
1418
               Enumeration xmlFieldValue = (getElements(parentidList)).
1419
                   elements();
1420
               while (xmlFieldValue.hasMoreElements()) {
1421
                   ReturnFieldValue object =
1422
                       (ReturnFieldValue) xmlFieldValue.nextElement();
1423
                   docid = object.getDocid();
1424 3246 berkley
                   if (docListResult.containsDocid(docid)) {
1425 2474 sgarg
                       String removedelement = (String) docListResult.
1426
                           remove(docid);
1427
                       docListResult.
1428 3246 berkley
                           addResultDocument(new ResultDocument(docid,
1429
                               removedelement + object.getXMLFieldValue()));
1430 2474 sgarg
                   }
1431
                   else {
1432 3246 berkley
                       docListResult.addResultDocument(
1433
                         new ResultDocument(docid, object.getXMLFieldValue()));
1434 2474 sgarg
                   }
1435
               } //while
1436 5165 daigle
//               double docListResultEnd = System.currentTimeMillis() / 1000;
1437
//               logMetacat.warn(
1438
//                   "Time to prepare ResultDocumentSet after"
1439
//                   + " execute extended query: "
1440
//                   + (docListResultEnd - extendedQueryEnd));
1441 2474 sgarg
           }
1442 2087 tao
       }//if doclist lenght is great than zero
1443
     }//if has extended query
1444 2043 sgarg
1445 2087 tao
      return docListResult;
1446
    }//addReturnfield
1447 2043 sgarg
1448 3730 tao
1449 2087 tao
  /**
1450
   * removes the <?xml version="1.0"?> tag from the beginning.  This takes a
1451
   * string as a param instead of a hashtable.
1452
   *
1453
   * @param xmlquery a string representing a query.
1454
   */
1455
   private  String transformQuery(String xmlquery)
1456
   {
1457
     xmlquery = xmlquery.trim();
1458
     int index = xmlquery.indexOf("?>");
1459
     if (index != -1)
1460
     {
1461
       return xmlquery.substring(index + 2, xmlquery.length());
1462
     }
1463
     else
1464
     {
1465
       return xmlquery;
1466
     }
1467
   }
1468 3340 tao
1469
   /*
1470 3342 tao
    * Method to store query string and result xml string into query result
1471 3340 tao
    * cache. If the size alreay reache the limitation, the cache will be
1472
    * cleared first, then store them.
1473
    */
1474 3342 tao
   private void storeQueryResultIntoCache(String query, String resultXML)
1475 3340 tao
   {
1476
	   synchronized (queryResultCache)
1477
	   {
1478
		   if (queryResultCache.size() >= QUERYRESULTCACHESIZE)
1479
		   {
1480
			   queryResultCache.clear();
1481
		   }
1482 3342 tao
		   queryResultCache.put(query, resultXML);
1483 3340 tao
1484
	   }
1485
   }
1486
1487
   /*
1488 3342 tao
    * Method to get result xml string from query result cache.
1489
    * Note: the returned string can be null.
1490 3340 tao
    */
1491 3342 tao
   private String getResultXMLFromCache(String query)
1492 3340 tao
   {
1493 3342 tao
	   String resultSet = null;
1494 3340 tao
	   synchronized (queryResultCache)
1495
	   {
1496
          try
1497
          {
1498 5165 daigle
        	 logMetacat.info("DBQuery.getResultXMLFromCache - Get query from cache");
1499 3342 tao
		     resultSet = (String)queryResultCache.get(query);
1500 3340 tao
1501
          }
1502
          catch (Exception e)
1503
          {
1504
        	  resultSet = null;
1505
          }
1506
1507
	   }
1508
	   return resultSet;
1509
   }
1510
1511
   /**
1512
    * Method to clear the query result cache.
1513
    */
1514
   public static void clearQueryResultCache()
1515
   {
1516
	   synchronized (queryResultCache)
1517
	   {
1518
		   queryResultCache.clear();
1519
	   }
1520
   }
1521 6602 leinfelder
1522
   /**
1523
    * Set the parameter values in the prepared statement using instrospection
1524
    * of the given value objects
1525
    * @param parameterValues
1526
    * @param pstmt
1527
    * @return
1528
    * @throws SQLException
1529
    */
1530
   public static PreparedStatement setPreparedStatementValues(List<Object> parameterValues, PreparedStatement pstmt) throws SQLException {
1531
	   // set all the values we have collected
1532
      int parameterIndex = 1;
1533
      for (Object parameterValue: parameterValues) {
1534
    	  if (parameterValue instanceof String) {
1535
    		  pstmt.setString(parameterIndex, (String) parameterValue);
1536
    	  }
1537
    	  else if (parameterValue instanceof Integer) {
1538
    		  pstmt.setInt(parameterIndex, (Integer) parameterValue);
1539
    	  }
1540
    	  else if (parameterValue instanceof Float) {
1541
    		  pstmt.setFloat(parameterIndex, (Float) parameterValue);
1542
    	  }
1543
    	  else if (parameterValue instanceof Double) {
1544
    		  pstmt.setDouble(parameterIndex, (Double) parameterValue);
1545
    	  }
1546
    	  else if (parameterValue instanceof Date) {
1547
    		  pstmt.setTimestamp(parameterIndex, new Timestamp(((Date) parameterValue).getTime()));
1548
    	  }
1549
    	  else {
1550
    		  pstmt.setObject(parameterIndex, parameterValue);
1551
    	  }
1552
    	  parameterIndex++;
1553
      }
1554
      return pstmt;
1555
   }
1556 2087 tao
1557
1558 2075 jones
    /*
1559
     * A method to search if Vector contains a particular key string
1560
     */
1561
    private boolean containsKey(Vector parentidList, String parentId)
1562
    {
1563 2043 sgarg
1564 2075 jones
        Vector tempVector = null;
1565 2043 sgarg
1566 2075 jones
        for (int count = 0; count < parentidList.size(); count++) {
1567
            tempVector = (Vector) parentidList.get(count);
1568 2360 sgarg
            if (parentId.compareTo((String) tempVector.get(0)) == 0) { return true; }
1569 2075 jones
        }
1570
        return false;
1571 2043 sgarg
    }
1572 3635 leinfelder
1573 2075 jones
    /*
1574
     * A method to put key and value in Vector
1575
     */
1576
    private void putInArray(Vector parentidList, String key,
1577
            ReturnFieldValue value)
1578
    {
1579 2043 sgarg
1580 2075 jones
        Vector tempVector = null;
1581 3635 leinfelder
        //only filter if the field type is NOT an attribute (say, for text)
1582
        String fieldType = value.getFieldType();
1583
        if (fieldType != null && !fieldType.equals("ATTRIBUTE")) {
1584
1585
	        for (int count = 0; count < parentidList.size(); count++) {
1586
	            tempVector = (Vector) parentidList.get(count);
1587
1588
	            if (key.compareTo((String) tempVector.get(0)) == 0) {
1589
	                tempVector.remove(1);
1590
	                tempVector.add(1, value);
1591
	                return;
1592
	            }
1593
	        }
1594 2075 jones
        }
1595 2043 sgarg
1596 2075 jones
        tempVector = new Vector();
1597
        tempVector.add(0, key);
1598
        tempVector.add(1, value);
1599
        parentidList.add(tempVector);
1600
        return;
1601 2043 sgarg
    }
1602
1603 2075 jones
    /*
1604
     * A method to get value in Vector given a key
1605
     */
1606
    private ReturnFieldValue getArrayValue(Vector parentidList, String key)
1607 1353 tao
    {
1608 2043 sgarg
1609 2075 jones
        Vector tempVector = null;
1610 2043 sgarg
1611 5490 berkley
        for (int count = 0; count < parentidList.size(); count++) {
1612 2075 jones
            tempVector = (Vector) parentidList.get(count);
1613 2043 sgarg
1614 5490 berkley
            if (key.compareTo((String) tempVector.get(0)) == 0) { return (ReturnFieldValue) tempVector
1615
                    .get(1); }
1616 2075 jones
        }
1617
        return null;
1618 2045 tao
    }
1619 436 berkley
1620 2075 jones
    /*
1621
     * A method to get enumeration of all values in Vector
1622
     */
1623
    private Vector getElements(Vector parentidList)
1624 342 berkley
    {
1625 2446 sgarg
        Vector enumVector = new Vector();
1626 2075 jones
        Vector tempVector = null;
1627 2043 sgarg
1628 2075 jones
        for (int count = 0; count < parentidList.size(); count++) {
1629
            tempVector = (Vector) parentidList.get(count);
1630 744 jones
1631 2446 sgarg
            enumVector.add(tempVector.get(1));
1632 744 jones
        }
1633 2446 sgarg
        return enumVector;
1634 372 berkley
    }
1635 2043 sgarg
1636 3308 tao
1637 2043 sgarg
1638 2075 jones
    /*
1639
     * A method to create a query to get owner's docid list
1640
     */
1641 6629 leinfelder
    private String getOwnerQuery(String owner, List<Object> parameterValues)
1642 372 berkley
    {
1643 2075 jones
        if (owner != null) {
1644
            owner = owner.toLowerCase();
1645
        }
1646
        StringBuffer self = new StringBuffer();
1647 2043 sgarg
1648 2075 jones
        self.append("SELECT docid,docname,doctype,");
1649
        self.append("date_created, date_updated, rev ");
1650
        self.append("FROM xml_documents WHERE docid IN (");
1651
        self.append("(");
1652
        self.append("SELECT DISTINCT docid FROM xml_nodes WHERE \n");
1653
        self.append("nodedata LIKE '%%%' ");
1654
        self.append(") \n");
1655
        self.append(") ");
1656
        self.append(" AND (");
1657 6629 leinfelder
        self.append(" lower(user_owner) = ?");
1658 2075 jones
        self.append(") ");
1659 6629 leinfelder
        parameterValues.add(owner);
1660 2075 jones
        return self.toString();
1661 342 berkley
    }
1662 2043 sgarg
1663 2075 jones
    /**
1664
     * format a structured query as an XML document that conforms to the
1665
     * pathquery.dtd and is appropriate for submission to the DBQuery
1666
     * structured query engine
1667 2087 tao
     *
1668 2075 jones
     * @param params The list of parameters that should be included in the
1669
     *            query
1670
     */
1671 4080 daigle
    public static String createSQuery(Hashtable params) throws PropertyNotFoundException
1672 342 berkley
    {
1673 2075 jones
        StringBuffer query = new StringBuffer();
1674
        Enumeration elements;
1675
        Enumeration keys;
1676
        String filterDoctype = null;
1677
        String casesensitive = null;
1678
        String searchmode = null;
1679
        Object nextkey;
1680
        Object nextelement;
1681
        //add the xml headers
1682
        query.append("<?xml version=\"1.0\"?>\n");
1683 2091 tao
        query.append("<pathquery version=\"1.2\">\n");
1684 372 berkley
1685 2091 tao
1686
1687 2075 jones
        if (params.containsKey("meta_file_id")) {
1688
            query.append("<meta_file_id>");
1689
            query.append(((String[]) params.get("meta_file_id"))[0]);
1690
            query.append("</meta_file_id>");
1691 372 berkley
        }
1692 2043 sgarg
1693 2075 jones
        if (params.containsKey("returndoctype")) {
1694
            String[] returnDoctypes = ((String[]) params.get("returndoctype"));
1695
            for (int i = 0; i < returnDoctypes.length; i++) {
1696
                String doctype = (String) returnDoctypes[i];
1697 181 jones
1698 2075 jones
                if (!doctype.equals("any") && !doctype.equals("ANY")
1699
                        && !doctype.equals("")) {
1700
                    query.append("<returndoctype>").append(doctype);
1701
                    query.append("</returndoctype>");
1702
                }
1703
            }
1704
        }
1705 181 jones
1706 2075 jones
        if (params.containsKey("filterdoctype")) {
1707
            String[] filterDoctypes = ((String[]) params.get("filterdoctype"));
1708
            for (int i = 0; i < filterDoctypes.length; i++) {
1709
                query.append("<filterdoctype>").append(filterDoctypes[i]);
1710
                query.append("</filterdoctype>");
1711
            }
1712
        }
1713 181 jones
1714 2075 jones
        if (params.containsKey("returnfield")) {
1715
            String[] returnfield = ((String[]) params.get("returnfield"));
1716
            for (int i = 0; i < returnfield.length; i++) {
1717
                query.append("<returnfield>").append(returnfield[i]);
1718
                query.append("</returnfield>");
1719
            }
1720
        }
1721 2043 sgarg
1722 2075 jones
        if (params.containsKey("owner")) {
1723
            String[] owner = ((String[]) params.get("owner"));
1724
            for (int i = 0; i < owner.length; i++) {
1725
                query.append("<owner>").append(owner[i]);
1726
                query.append("</owner>");
1727
            }
1728
        }
1729 181 jones
1730 2075 jones
        if (params.containsKey("site")) {
1731
            String[] site = ((String[]) params.get("site"));
1732
            for (int i = 0; i < site.length; i++) {
1733
                query.append("<site>").append(site[i]);
1734
                query.append("</site>");
1735
            }
1736
        }
1737 2043 sgarg
1738 2075 jones
        //allows the dynamic switching of boolean operators
1739
        if (params.containsKey("operator")) {
1740
            query.append("<querygroup operator=\""
1741
                    + ((String[]) params.get("operator"))[0] + "\">");
1742
        } else { //the default operator is UNION
1743
            query.append("<querygroup operator=\"UNION\">");
1744
        }
1745 940 tao
1746 2075 jones
        if (params.containsKey("casesensitive")) {
1747
            casesensitive = ((String[]) params.get("casesensitive"))[0];
1748
        } else {
1749
            casesensitive = "false";
1750
        }
1751 2043 sgarg
1752 2075 jones
        if (params.containsKey("searchmode")) {
1753
            searchmode = ((String[]) params.get("searchmode"))[0];
1754
        } else {
1755
            searchmode = "contains";
1756 940 tao
        }
1757
1758 2075 jones
        //anyfield is a special case because it does a
1759
        //free text search. It does not have a <pathexpr>
1760
        //tag. This allows for a free text search within the structured
1761
        //query. This is useful if the INTERSECT operator is used.
1762
        if (params.containsKey("anyfield")) {
1763
            String[] anyfield = ((String[]) params.get("anyfield"));
1764
            //allow for more than one value for anyfield
1765
            for (int i = 0; i < anyfield.length; i++) {
1766 4135 berkley
                if (anyfield[i] != null && !anyfield[i].equals("")) {
1767 2075 jones
                    query.append("<queryterm casesensitive=\"" + casesensitive
1768
                            + "\" " + "searchmode=\"" + searchmode
1769 7677 leinfelder
                            + "\"><value>"
1770
                            + StringEscapeUtils.escapeXml(anyfield[i])
1771 2075 jones
                            + "</value></queryterm>");
1772
                }
1773
            }
1774 940 tao
        }
1775 2043 sgarg
1776 2075 jones
        //this while loop finds the rest of the parameters
1777
        //and attempts to query for the field specified
1778
        //by the parameter.
1779
        elements = params.elements();
1780
        keys = params.keys();
1781
        while (keys.hasMoreElements() && elements.hasMoreElements()) {
1782
            nextkey = keys.nextElement();
1783
            nextelement = elements.nextElement();
1784 2043 sgarg
1785 2075 jones
            //make sure we aren't querying for any of these
1786
            //parameters since the are already in the query
1787
            //in one form or another.
1788
            Vector ignoredParams = new Vector();
1789
            ignoredParams.add("returndoctype");
1790
            ignoredParams.add("filterdoctype");
1791
            ignoredParams.add("action");
1792
            ignoredParams.add("qformat");
1793
            ignoredParams.add("anyfield");
1794
            ignoredParams.add("returnfield");
1795
            ignoredParams.add("owner");
1796
            ignoredParams.add("site");
1797
            ignoredParams.add("operator");
1798 2091 tao
            ignoredParams.add("sessionid");
1799 3211 berkley
            ignoredParams.add("pagesize");
1800
            ignoredParams.add("pagestart");
1801 4135 berkley
            ignoredParams.add("searchmode");
1802 2043 sgarg
1803 2075 jones
            // Also ignore parameters listed in the properties file
1804
            // so that they can be passed through to stylesheets
1805 4080 daigle
            String paramsToIgnore = PropertyService
1806 4173 daigle
                    .getProperty("database.queryignoredparams");
1807 2075 jones
            StringTokenizer st = new StringTokenizer(paramsToIgnore, ",");
1808
            while (st.hasMoreTokens()) {
1809
                ignoredParams.add(st.nextToken());
1810
            }
1811
            if (!ignoredParams.contains(nextkey.toString())) {
1812
                //allow for more than value per field name
1813
                for (int i = 0; i < ((String[]) nextelement).length; i++) {
1814
                    if (!((String[]) nextelement)[i].equals("")) {
1815
                        query.append("<queryterm casesensitive=\""
1816
                                + casesensitive + "\" " + "searchmode=\""
1817 2087 tao
                                + searchmode + "\">" + "<value>" +
1818 2075 jones
                                //add the query value
1819 7677 leinfelder
                                StringEscapeUtils.escapeXml(((String[]) nextelement)[i])
1820 2087 tao
                                + "</value><pathexpr>" +
1821 2075 jones
                                //add the path to query by
1822
                                nextkey.toString() + "</pathexpr></queryterm>");
1823
                    }
1824
                }
1825
            }
1826
        }
1827
        query.append("</querygroup></pathquery>");
1828
        //append on the end of the xml and return the result as a string
1829
        return query.toString();
1830
    }
1831 2043 sgarg
1832 2075 jones
    /**
1833
     * format a simple free-text value query as an XML document that conforms
1834
     * to the pathquery.dtd and is appropriate for submission to the DBQuery
1835
     * structured query engine
1836 2087 tao
     *
1837 2075 jones
     * @param value the text string to search for in the xml catalog
1838
     * @param doctype the type of documents to include in the result set -- use
1839
     *            "any" or "ANY" for unfiltered result sets
1840
     */
1841
    public static String createQuery(String value, String doctype)
1842 1292 tao
    {
1843 2075 jones
        StringBuffer xmlquery = new StringBuffer();
1844
        xmlquery.append("<?xml version=\"1.0\"?>\n");
1845
        xmlquery.append("<pathquery version=\"1.0\">");
1846 2043 sgarg
1847 2075 jones
        if (!doctype.equals("any") && !doctype.equals("ANY")) {
1848
            xmlquery.append("<returndoctype>");
1849
            xmlquery.append(doctype).append("</returndoctype>");
1850
        }
1851 2043 sgarg
1852 2075 jones
        xmlquery.append("<querygroup operator=\"UNION\">");
1853
        //chad added - 8/14
1854
        //the if statement allows a query to gracefully handle a null
1855
        //query. Without this if a nullpointerException is thrown.
1856
        if (!value.equals("")) {
1857
            xmlquery.append("<queryterm casesensitive=\"false\" ");
1858
            xmlquery.append("searchmode=\"contains\">");
1859
            xmlquery.append("<value>").append(value).append("</value>");
1860
            xmlquery.append("</queryterm>");
1861 1217 tao
        }
1862 2075 jones
        xmlquery.append("</querygroup>");
1863
        xmlquery.append("</pathquery>");
1864 2043 sgarg
1865 2075 jones
        return (xmlquery.toString());
1866
    }
1867 2043 sgarg
1868 2075 jones
    /**
1869
     * format a simple free-text value query as an XML document that conforms
1870
     * to the pathquery.dtd and is appropriate for submission to the DBQuery
1871
     * structured query engine
1872 2087 tao
     *
1873 2075 jones
     * @param value the text string to search for in the xml catalog
1874
     */
1875
    public static String createQuery(String value)
1876 940 tao
    {
1877 2075 jones
        return createQuery(value, "any");
1878 940 tao
    }
1879 2043 sgarg
1880 2075 jones
    /**
1881
     * Check for "READ" permission on @docid for @user and/or @group from DB
1882
     * connection
1883
     */
1884
    private boolean hasPermission(String user, String[] groups, String docid)
1885
            throws SQLException, Exception
1886 940 tao
    {
1887 2075 jones
        // Check for READ permission on @docid for @user and/or @groups
1888
        PermissionController controller = new PermissionController(docid);
1889
        return controller.hasPermission(user, groups,
1890
                AccessControlInterface.READSTRING);
1891
    }
1892 2043 sgarg
1893 2075 jones
    /**
1894
     * Get all docIds list for a data packadge
1895 2087 tao
     *
1896 2075 jones
     * @param dataPackageDocid, the string in docId field of xml_relation table
1897
     */
1898
    private Vector getCurrentDocidListForDataPackage(String dataPackageDocid)
1899 940 tao
    {
1900 2075 jones
        DBConnection dbConn = null;
1901
        int serialNumber = -1;
1902
        Vector docIdList = new Vector();//return value
1903
        PreparedStatement pStmt = null;
1904
        ResultSet rs = null;
1905
        String docIdInSubjectField = null;
1906
        String docIdInObjectField = null;
1907 2043 sgarg
1908 2075 jones
        // Check the parameter
1909
        if (dataPackageDocid == null || dataPackageDocid.equals("")) { return docIdList; }//if
1910 940 tao
1911 2075 jones
        //the query stirng
1912
        String query = "SELECT subject, object from xml_relation where docId = ?";
1913
        try {
1914
            dbConn = DBConnectionPool
1915
                    .getDBConnection("DBQuery.getCurrentDocidListForDataPackage");
1916
            serialNumber = dbConn.getCheckOutSerialNumber();
1917
            pStmt = dbConn.prepareStatement(query);
1918
            //bind the value to query
1919
            pStmt.setString(1, dataPackageDocid);
1920 2043 sgarg
1921 2075 jones
            //excute the query
1922
            pStmt.execute();
1923
            //get the result set
1924
            rs = pStmt.getResultSet();
1925
            //process the result
1926
            while (rs.next()) {
1927
                //In order to get the whole docIds in a data packadge,
1928
                //we need to put the docIds of subject and object field in
1929
                // xml_relation
1930
                //into the return vector
1931
                docIdInSubjectField = rs.getString(1);//the result docId in
1932
                                                      // subject field
1933
                docIdInObjectField = rs.getString(2);//the result docId in
1934
                                                     // object field
1935 940 tao
1936 2075 jones
                //don't put the duplicate docId into the vector
1937
                if (!docIdList.contains(docIdInSubjectField)) {
1938
                    docIdList.add(docIdInSubjectField);
1939
                }
1940 2043 sgarg
1941 2075 jones
                //don't put the duplicate docId into the vector
1942
                if (!docIdList.contains(docIdInObjectField)) {
1943
                    docIdList.add(docIdInObjectField);
1944
                }
1945
            }//while
1946
            //close the pStmt
1947
            pStmt.close();
1948
        }//try
1949
        catch (SQLException e) {
1950 5165 daigle
            logMetacat.error("DBQuery.getCurrentDocidListForDataPackage - Error in getDocidListForDataPackage: "
1951 2663 sgarg
                    + e.getMessage());
1952 2075 jones
        }//catch
1953
        finally {
1954
            try {
1955
                pStmt.close();
1956
            }//try
1957
            catch (SQLException ee) {
1958 5165 daigle
                logMetacat.error("DBQuery.getCurrentDocidListForDataPackage - SQL Error: "
1959 2663 sgarg
                                + ee.getMessage());
1960 2075 jones
            }//catch
1961
            finally {
1962
                DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1963
            }//fianlly
1964
        }//finally
1965
        return docIdList;
1966
    }//getCurrentDocidListForDataPackadge()
1967 2043 sgarg
1968 2075 jones
    /**
1969
     * Get all docIds list for a data packadge
1970 2087 tao
     *
1971 2075 jones
     * @param dataPackageDocid, the string in docId field of xml_relation table
1972
     */
1973 2641 tao
    private Vector getOldVersionDocidListForDataPackage(String dataPackageDocidWithRev)
1974 940 tao
    {
1975 2043 sgarg
1976 2075 jones
        Vector docIdList = new Vector();//return value
1977
        Vector tripleList = null;
1978
        String xml = null;
1979 2043 sgarg
1980 2075 jones
        // Check the parameter
1981 2641 tao
        if (dataPackageDocidWithRev == null || dataPackageDocidWithRev.equals("")) { return docIdList; }//if
1982 2043 sgarg
1983 2075 jones
        try {
1984
            //initial a documentImpl object
1985 2641 tao
            DocumentImpl packageDocument = new DocumentImpl(dataPackageDocidWithRev);
1986 2075 jones
            //transfer to documentImpl object to string
1987
            xml = packageDocument.toString();
1988 2043 sgarg
1989 2075 jones
            //create a tripcollection object
1990
            TripleCollection tripleForPackage = new TripleCollection(
1991
                    new StringReader(xml));
1992
            //get the vetor of triples
1993
            tripleList = tripleForPackage.getCollection();
1994 2043 sgarg
1995 2075 jones
            for (int i = 0; i < tripleList.size(); i++) {
1996
                //put subject docid into docIdlist without duplicate
1997
                if (!docIdList.contains(((Triple) tripleList.elementAt(i))
1998
                        .getSubject())) {
1999
                    //put subject docid into docIdlist
2000
                    docIdList.add(((Triple) tripleList.get(i)).getSubject());
2001
                }
2002
                //put object docid into docIdlist without duplicate
2003
                if (!docIdList.contains(((Triple) tripleList.elementAt(i))
2004
                        .getObject())) {
2005
                    docIdList.add(((Triple) (tripleList.get(i))).getObject());
2006
                }
2007
            }//for
2008
        }//try
2009
        catch (Exception e) {
2010 5165 daigle
            logMetacat.error("DBQuery.getCurrentDocidListForDataPackage - General error: "
2011 2663 sgarg
                    + e.getMessage());
2012 2075 jones
        }//catch
2013 2043 sgarg
2014 2075 jones
        // return result
2015
        return docIdList;
2016
    }//getDocidListForPackageInXMLRevisions()
2017 2043 sgarg
2018 2075 jones
    /**
2019
     * Check if the docId is a data packadge id. If the id is a data packadage
2020
     * id, it should be store in the docId fields in xml_relation table. So we
2021
     * can use a query to get the entries which the docId equals the given
2022
     * value. If the result is null. The docId is not a packadge id. Otherwise,
2023
     * it is.
2024 2087 tao
     *
2025 2075 jones
     * @param docId, the id need to be checked
2026
     */
2027
    private boolean isDataPackageId(String docId)
2028 940 tao
    {
2029 2075 jones
        boolean result = false;
2030
        PreparedStatement pStmt = null;
2031
        ResultSet rs = null;
2032
        String query = "SELECT docId from xml_relation where docId = ?";
2033
        DBConnection dbConn = null;
2034
        int serialNumber = -1;
2035
        try {
2036
            dbConn = DBConnectionPool
2037
                    .getDBConnection("DBQuery.isDataPackageId");
2038
            serialNumber = dbConn.getCheckOutSerialNumber();
2039
            pStmt = dbConn.prepareStatement(query);
2040
            //bind the value to query
2041
            pStmt.setString(1, docId);
2042
            //execute the query
2043
            pStmt.execute();
2044
            rs = pStmt.getResultSet();
2045
            //process the result
2046
            if (rs.next()) //There are some records for the id in docId fields
2047
            {
2048
                result = true;//It is a data packadge id
2049
            }
2050
            pStmt.close();
2051
        }//try
2052
        catch (SQLException e) {
2053 5165 daigle
            logMetacat.error("DBQuery.isDataPackageId - SQL Error: "
2054 2663 sgarg
                    + e.getMessage());
2055 2075 jones
        } finally {
2056
            try {
2057
                pStmt.close();
2058
            }//try
2059
            catch (SQLException ee) {
2060 5165 daigle
                logMetacat.error("DBQuery.isDataPackageId - SQL Error in isDataPackageId: "
2061 2663 sgarg
                        + ee.getMessage());
2062 2075 jones
            }//catch
2063
            finally {
2064
                DBConnectionPool.returnDBConnection(dbConn, serialNumber);
2065
            }//finally
2066
        }//finally
2067
        return result;
2068
    }//isDataPackageId()
2069 2043 sgarg
2070 6035 leinfelder
    public String getOperator() {
2071
		return operator;
2072
	}
2073
2074 2075 jones
    /**
2075 6035 leinfelder
     * Specifies if and how docid overrides should be included in the general query
2076
     * @param operator null, UNION, or INTERSECT (see QueryGroup)
2077
     */
2078
	public void setOperator(String operator) {
2079
		this.operator = operator;
2080
	}
2081
2082 7671 leinfelder
	public String getQformat() {
2083
		return qformat;
2084
	}
2085
2086
	public void setQformat(String qformat) {
2087
		this.qformat = qformat;
2088
	}
2089
2090 6035 leinfelder
	/**
2091 2075 jones
     * Check if the user has the permission to export data package
2092 2087 tao
     *
2093 2075 jones
     * @param conn, the connection
2094
     * @param docId, the id need to be checked
2095
     * @param user, the name of user
2096
     * @param groups, the user's group
2097
     */
2098
    private boolean hasPermissionToExportPackage(String docId, String user,
2099
            String[] groups) throws Exception
2100 940 tao
    {
2101 2075 jones
        //DocumentImpl doc=new DocumentImpl(conn,docId);
2102
        return DocumentImpl.hasReadPermission(user, groups, docId);
2103
    }
2104 2043 sgarg
2105 2075 jones
    /**
2106
     * Get the current Rev for a docid in xml_documents table
2107 2087 tao
     *
2108 2075 jones
     * @param docId, the id need to get version numb If the return value is -5,
2109
     *            means no value in rev field for this docid
2110
     */
2111
    private int getCurrentRevFromXMLDoumentsTable(String docId)
2112
            throws SQLException
2113
    {
2114
        int rev = -5;
2115
        PreparedStatement pStmt = null;
2116
        ResultSet rs = null;
2117
        String query = "SELECT rev from xml_documents where docId = ?";
2118
        DBConnection dbConn = null;
2119
        int serialNumber = -1;
2120
        try {
2121
            dbConn = DBConnectionPool
2122
                    .getDBConnection("DBQuery.getCurrentRevFromXMLDocumentsTable");
2123
            serialNumber = dbConn.getCheckOutSerialNumber();
2124
            pStmt = dbConn.prepareStatement(query);
2125
            //bind the value to query
2126
            pStmt.setString(1, docId);
2127
            //execute the query
2128
            pStmt.execute();
2129
            rs = pStmt.getResultSet();
2130
            //process the result
2131
            if (rs.next()) //There are some records for rev
2132
            {
2133
                rev = rs.getInt(1);
2134
                ;//It is the version for given docid
2135
            } else {
2136
                rev = -5;
2137
            }
2138 2043 sgarg
2139 1292 tao
        }//try
2140 2075 jones
        catch (SQLException e) {
2141 5165 daigle
            logMetacat.error("DBQuery.getCurrentRevFromXMLDoumentsTable - SQL Error: "
2142 2663 sgarg
                            + e.getMessage());
2143 2075 jones
            throw e;
2144 1292 tao
        }//catch
2145 2075 jones
        finally {
2146
            try {
2147
                pStmt.close();
2148
            }//try
2149
            catch (SQLException ee) {
2150 2663 sgarg
                logMetacat.error(
2151 5165 daigle
                        "DBQuery.getCurrentRevFromXMLDoumentsTable - SQL Error: "
2152 2663 sgarg
                                + ee.getMessage());
2153 2075 jones
            }//catch
2154
            finally {
2155
                DBConnectionPool.returnDBConnection(dbConn, serialNumber);
2156
            }//finally
2157
        }//finally
2158
        return rev;
2159
    }//getCurrentRevFromXMLDoumentsTable
2160 2043 sgarg
2161 2075 jones
    /**
2162
     * put a doc into a zip output stream
2163 2087 tao
     *
2164 2075 jones
     * @param docImpl, docmentImpl object which will be sent to zip output
2165
     *            stream
2166
     * @param zipOut, zip output stream which the docImpl will be put
2167
     * @param packageZipEntry, the zip entry name for whole package
2168
     */
2169
    private void addDocToZipOutputStream(DocumentImpl docImpl,
2170
            ZipOutputStream zipOut, String packageZipEntry)
2171
            throws ClassNotFoundException, IOException, SQLException,
2172
            McdbException, Exception
2173
    {
2174
        byte[] byteString = null;
2175
        ZipEntry zEntry = null;
2176 2043 sgarg
2177 5760 leinfelder
        byteString = docImpl.getBytes();
2178 2075 jones
        //use docId as the zip entry's name
2179 7671 leinfelder
        String fullDocId = docImpl.getDocID() + PropertyService.getProperty("document.accNumSeparator") + docImpl.getRev();
2180
		zEntry = new ZipEntry(packageZipEntry + "/metadata/" + fullDocId );
2181 2075 jones
        zEntry.setSize(byteString.length);
2182
        zipOut.putNextEntry(zEntry);
2183
        zipOut.write(byteString, 0, byteString.length);
2184
        zipOut.closeEntry();
2185 2043 sgarg
2186 2075 jones
    }//addDocToZipOutputStream()
2187 940 tao
2188 2075 jones
    /**
2189
     * Transfer a docid vetor to a documentImpl vector. The documentImpl vetor
2190
     * only inlcudes current version. If a DocumentImple object couldn't find
2191
     * for a docid, then the String of this docid was added to vetor rather
2192
     * than DocumentImple object.
2193 2087 tao
     *
2194 2075 jones
     * @param docIdList, a vetor hold a docid list for a data package. In
2195
     *            docid, there is not version number in it.
2196
     */
2197 2043 sgarg
2198 2075 jones
    private Vector getCurrentAllDocumentImpl(Vector docIdList)
2199
            throws McdbException, Exception
2200 940 tao
    {
2201 2075 jones
        //Connection dbConn=null;
2202
        Vector documentImplList = new Vector();
2203
        int rev = 0;
2204 2043 sgarg
2205 2075 jones
        // Check the parameter
2206
        if (docIdList.isEmpty()) { return documentImplList; }//if
2207 2043 sgarg
2208 2075 jones
        //for every docid in vector
2209
        for (int i = 0; i < docIdList.size(); i++) {
2210
            try {
2211 7665 leinfelder
				//get newest version for this docId
2212
                String smartDocid = DocumentUtil.getSmartDocId((String) docIdList.elementAt(i));
2213
                rev = getCurrentRevFromXMLDoumentsTable(smartDocid);
2214 940 tao
2215 2075 jones
                // There is no record for this docId in xml_documents table
2216
                if (rev == -5) {
2217
                    // Rather than put DocumentImple object, put a String
2218
                    // Object(docid)
2219
                    // into the documentImplList
2220
                    documentImplList.add((String) docIdList.elementAt(i));
2221
                    // Skip other code
2222
                    continue;
2223
                }
2224 2043 sgarg
2225 7665 leinfelder
                String docidPlusVersion = smartDocid
2226 4212 daigle
                        + PropertyService.getProperty("document.accNumSeparator") + rev;
2227 2043 sgarg
2228 2075 jones
                //create new documentImpl object
2229
                DocumentImpl documentImplObject = new DocumentImpl(
2230
                        docidPlusVersion);
2231
                //add them to vector
2232
                documentImplList.add(documentImplObject);
2233
            }//try
2234
            catch (Exception e) {
2235 5165 daigle
                logMetacat.error("DBQuery.getCurrentAllDocumentImpl - General error: "
2236 2663 sgarg
                        + e.getMessage());
2237 2075 jones
                // continue the for loop
2238
                continue;
2239
            }
2240
        }//for
2241
        return documentImplList;
2242
    }
2243 2043 sgarg
2244 2075 jones
    /**
2245
     * Transfer a docid vetor to a documentImpl vector. If a DocumentImple
2246
     * object couldn't find for a docid, then the String of this docid was
2247
     * added to vetor rather than DocumentImple object.
2248 2087 tao
     *
2249 2075 jones
     * @param docIdList, a vetor hold a docid list for a data package. In
2250
     *            docid, t here is version number in it.
2251
     */
2252
    private Vector getOldVersionAllDocumentImpl(Vector docIdList)
2253
    {
2254
        //Connection dbConn=null;
2255
        Vector documentImplList = new Vector();
2256
        String siteCode = null;
2257
        String uniqueId = null;
2258
        int rev = 0;
2259 2043 sgarg
2260 2075 jones
        // Check the parameter
2261
        if (docIdList.isEmpty()) { return documentImplList; }//if
2262 2043 sgarg
2263 2075 jones
        //for every docid in vector
2264
        for (int i = 0; i < docIdList.size(); i++) {
2265 2043 sgarg
2266 2075 jones
            String docidPlusVersion = (String) (docIdList.elementAt(i));
2267
2268
            try {
2269
                //create new documentImpl object
2270
                DocumentImpl documentImplObject = new DocumentImpl(
2271
                        docidPlusVersion);
2272
                //add them to vector
2273
                documentImplList.add(documentImplObject);
2274
            }//try
2275
            catch (McdbDocNotFoundException notFoundE) {
2276 5165 daigle
                logMetacat.error("DBQuery.getOldVersionAllDocument - Error finding doc "
2277
                		+ docidPlusVersion + " : " + notFoundE.getMessage());
2278 2075 jones
                // Rather than add a DocumentImple object into vetor, a String
2279
                // object
2280
                // - the doicd was added to the vector
2281
                documentImplList.add(docidPlusVersion);
2282
                // Continue the for loop
2283
                continue;
2284
            }//catch
2285
            catch (Exception e) {
2286 2663 sgarg
                logMetacat.error(
2287 5165 daigle
                        "DBQuery.getOldVersionAllDocument - General error: "
2288 2663 sgarg
                                + e.getMessage());
2289 2075 jones
                // Continue the for loop
2290
                continue;
2291
            }//catch
2292
2293
        }//for
2294
        return documentImplList;
2295
    }//getOldVersionAllDocumentImple
2296
2297
    /**
2298
     * put a data file into a zip output stream
2299 2087 tao
     *
2300 2075 jones
     * @param docImpl, docmentImpl object which will be sent to zip output
2301
     *            stream
2302
     * @param zipOut, the zip output stream which the docImpl will be put
2303
     * @param packageZipEntry, the zip entry name for whole package
2304
     */
2305
    private void addDataFileToZipOutputStream(DocumentImpl docImpl,
2306
            ZipOutputStream zipOut, String packageZipEntry)
2307
            throws ClassNotFoundException, IOException, SQLException,
2308
            McdbException, Exception
2309 940 tao
    {
2310 2075 jones
        byte[] byteString = null;
2311
        ZipEntry zEntry = null;
2312
        // this is data file; add file to zip
2313 4080 daigle
        String filePath = PropertyService.getProperty("application.datafilepath");
2314 2075 jones
        if (!filePath.endsWith("/")) {
2315
            filePath += "/";
2316
        }
2317 7671 leinfelder
        String fileName = docImpl.getDocID() + PropertyService.getProperty("document.accNumSeparator") + docImpl.getRev();
2318
        String entityName = docImpl.getDocname();
2319
        filePath = filePath + fileName;
2320
        zEntry = new ZipEntry(packageZipEntry + "/data/" + fileName + "-" + entityName);
2321 2075 jones
        zipOut.putNextEntry(zEntry);
2322
        FileInputStream fin = null;
2323
        try {
2324 7671 leinfelder
            fin = new FileInputStream(filePath);
2325 2075 jones
            byte[] buf = new byte[4 * 1024]; // 4K buffer
2326
            int b = fin.read(buf);
2327
            while (b != -1) {
2328
                zipOut.write(buf, 0, b);
2329
                b = fin.read(buf);
2330 8304 jones
            }
2331
            fin.close();
2332 2075 jones
            zipOut.closeEntry();
2333
        }//try
2334
        catch (IOException ioe) {
2335 5165 daigle
            logMetacat.error("DBQuery.addDataFileToZipOutputStream - I/O error: "
2336 2663 sgarg
                    + ioe.getMessage());
2337 8304 jones
        } finally {
2338
            IOUtils.closeQuietly(fin);
2339
        }
2340 2075 jones
    }//addDataFileToZipOutputStream()
2341 2043 sgarg
2342 2075 jones
    /**
2343
     * create a html summary for data package and put it into zip output stream
2344 2087 tao
     *
2345 2075 jones
     * @param docImplList, the documentImpl ojbects in data package
2346
     * @param zipOut, the zip output stream which the html should be put
2347
     * @param packageZipEntry, the zip entry name for whole package
2348
     */
2349
    private void addHtmlSummaryToZipOutputStream(Vector docImplList,
2350
            ZipOutputStream zipOut, String packageZipEntry) throws Exception
2351
    {
2352
        StringBuffer htmlDoc = new StringBuffer();
2353
        ZipEntry zEntry = null;
2354
        byte[] byteString = null;
2355
        InputStream source;
2356
        DBTransform xmlToHtml;
2357 2043 sgarg
2358 2075 jones
        //create a DBTransform ojbect
2359
        xmlToHtml = new DBTransform();
2360
        //head of html
2361
        htmlDoc.append("<html><head></head><body>");
2362
        for (int i = 0; i < docImplList.size(); i++) {
2363
            // If this String object, this means it is missed data file
2364
            if ((((docImplList.elementAt(i)).getClass()).toString())
2365
                    .equals("class java.lang.String")) {
2366 2043 sgarg
2367 2075 jones
                htmlDoc.append("<a href=\"");
2368
                String dataFileid = (String) docImplList.elementAt(i);
2369
                htmlDoc.append("./data/").append(dataFileid).append("\">");
2370
                htmlDoc.append("Data File: ");
2371
                htmlDoc.append(dataFileid).append("</a><br>");
2372
                htmlDoc.append("<br><hr><br>");
2373 1356 tao
2374 2075 jones
            }//if
2375
            else if ((((DocumentImpl) docImplList.elementAt(i)).getDoctype())
2376
                    .compareTo("BIN") != 0) { //this is an xml file so we can
2377
                                              // transform it.
2378
                //transform each file individually then concatenate all of the
2379
                //transformations together.
2380 1356 tao
2381 2075 jones
                //for metadata xml title
2382
                htmlDoc.append("<h2>");
2383
                htmlDoc.append(((DocumentImpl) docImplList.elementAt(i))
2384
                        .getDocID());
2385
                //htmlDoc.append(".");
2386
                //htmlDoc.append(((DocumentImpl)docImplList.elementAt(i)).getRev());
2387
                htmlDoc.append("</h2>");
2388
                //do the actual transform
2389 7859 leinfelder
                Writer docString = new StringWriter();
2390 7671 leinfelder
                xmlToHtml.transformXMLDocument(
2391
                		((DocumentImpl) docImplList.elementAt(i)).toString(),
2392
                		((DocumentImpl) docImplList.elementAt(i)).getDoctype(), //"-//NCEAS//eml-generic//EN",
2393
                        "-//W3C//HTML//EN",
2394
                        qformat,
2395
                        docString,
2396
                        null,
2397
                        null);
2398 2075 jones
                htmlDoc.append(docString.toString());
2399
                htmlDoc.append("<br><br><hr><br><br>");
2400
            }//if
2401
            else { //this is a data file so we should link to it in the html
2402
                htmlDoc.append("<a href=\"");
2403
                String dataFileid = ((DocumentImpl) docImplList.elementAt(i))
2404
                        .getDocID();
2405
                htmlDoc.append("./data/").append(dataFileid).append("\">");
2406
                htmlDoc.append("Data File: ");
2407
                htmlDoc.append(dataFileid).append("</a><br>");
2408
                htmlDoc.append("<br><hr><br>");
2409
            }//else
2410
        }//for
2411
        htmlDoc.append("</body></html>");
2412 5760 leinfelder
        // use standard encoding even though the different docs might have use different encodings,
2413
        // the String objects in java should be correct and able to be encoded as the same Metacat default
2414
        byteString = htmlDoc.toString().getBytes(MetaCatServlet.DEFAULT_ENCODING);
2415 2075 jones
        zEntry = new ZipEntry(packageZipEntry + "/metadata.html");
2416
        zEntry.setSize(byteString.length);
2417
        zipOut.putNextEntry(zEntry);
2418
        zipOut.write(byteString, 0, byteString.length);
2419
        zipOut.closeEntry();
2420
        //dbConn.close();
2421 1356 tao
2422 2075 jones
    }//addHtmlSummaryToZipOutputStream
2423 1356 tao
2424 2075 jones
    /**
2425
     * put a data packadge into a zip output stream
2426 2087 tao
     *
2427 2641 tao
     * @param docId, which the user want to put into zip output stream,it has version
2428 2075 jones
     * @param out, a servletoutput stream which the zip output stream will be
2429
     *            put
2430
     * @param user, the username of the user
2431
     * @param groups, the group of the user
2432
     */
2433
    public ZipOutputStream getZippedPackage(String docIdString,
2434
            ServletOutputStream out, String user, String[] groups,
2435
            String passWord) throws ClassNotFoundException, IOException,
2436
            SQLException, McdbException, NumberFormatException, Exception
2437 945 tao
    {
2438 2075 jones
        ZipOutputStream zOut = null;
2439
        String elementDocid = null;
2440
        DocumentImpl docImpls = null;
2441
        //Connection dbConn = null;
2442
        Vector docIdList = new Vector();
2443
        Vector documentImplList = new Vector();
2444
        Vector htmlDocumentImplList = new Vector();
2445
        String packageId = null;
2446
        String rootName = "package";//the package zip entry name
2447 2043 sgarg
2448 2075 jones
        String docId = null;
2449
        int version = -5;
2450
        // Docid without revision
2451 5025 daigle
        docId = DocumentUtil.getDocIdFromString(docIdString);
2452 2075 jones
        // revision number
2453 5025 daigle
        version = DocumentUtil.getVersionFromString(docIdString);
2454 2043 sgarg
2455 2075 jones
        //check if the reqused docId is a data package id
2456
        if (!isDataPackageId(docId)) {
2457 2043 sgarg
2458 2075 jones
            /*
2459
             * Exception e = new Exception("The request the doc id "
2460
             * +docIdString+ " is not a data package id");
2461
             */
2462 940 tao
2463 2075 jones
            //CB 1/6/03: if the requested docid is not a datapackage, we just
2464
            // zip
2465
            //up the single document and return the zip file.
2466
            if (!hasPermissionToExportPackage(docId, user, groups)) {
2467 2043 sgarg
2468 2075 jones
                Exception e = new Exception("User " + user
2469
                        + " does not have permission"
2470
                        + " to export the data package " + docIdString);
2471
                throw e;
2472
            }
2473 2043 sgarg
2474 2641 tao
            docImpls = new DocumentImpl(docIdString);
2475 2075 jones
            //checking if the user has the permission to read the documents
2476
            if (DocumentImpl.hasReadPermission(user, groups, docImpls
2477
                    .getDocID())) {
2478
                zOut = new ZipOutputStream(out);
2479
                //if the docImpls is metadata
2480
                if ((docImpls.getDoctype()).compareTo("BIN") != 0) {
2481
                    //add metadata into zip output stream
2482
                    addDocToZipOutputStream(docImpls, zOut, rootName);
2483
                }//if
2484
                else {
2485
                    //it is data file
2486
                    addDataFileToZipOutputStream(docImpls, zOut, rootName);
2487
                    htmlDocumentImplList.add(docImpls);
2488
                }//else
2489 1292 tao
            }//if
2490 2043 sgarg
2491 2075 jones
            zOut.finish(); //terminate the zip file
2492
            return zOut;
2493
        }
2494
        // Check the permission of user
2495 7665 leinfelder
        else if (!hasPermissionToExportPackage(docIdString, user, groups)) {
2496 2075 jones
2497
            Exception e = new Exception("User " + user
2498
                    + " does not have permission"
2499
                    + " to export the data package " + docIdString);
2500
            throw e;
2501
        } else //it is a packadge id
2502 1292 tao
        {
2503 2075 jones
            //store the package id
2504
            packageId = docId;
2505
            //get current version in database
2506
            int currentVersion = getCurrentRevFromXMLDoumentsTable(packageId);
2507
            //If it is for current version (-1 means user didn't specify
2508
            // revision)
2509
            if ((version == -1) || version == currentVersion) {
2510
                //get current version number
2511
                version = currentVersion;
2512
                //get package zip entry name
2513
                //it should be docId.revsion.package
2514 4212 daigle
                rootName = packageId + PropertyService.getProperty("document.accNumSeparator")
2515
                        + version + PropertyService.getProperty("document.accNumSeparator")
2516 2075 jones
                        + "package";
2517
                //get the whole id list for data packadge
2518
                docIdList = getCurrentDocidListForDataPackage(packageId);
2519
                //get the whole documentImple object
2520
                documentImplList = getCurrentAllDocumentImpl(docIdList);
2521 2043 sgarg
2522 1292 tao
            }//if
2523 2075 jones
            else if (version > currentVersion || version < -1) {
2524
                throw new Exception("The user specified docid: " + docId + "."
2525
                        + version + " doesn't exist");
2526
            }//else if
2527
            else //for an old version
2528 1292 tao
            {
2529 2075 jones
2530
                rootName = docIdString
2531 4212 daigle
                        + PropertyService.getProperty("document.accNumSeparator") + "package";
2532 2075 jones
                //get the whole id list for data packadge
2533
                docIdList = getOldVersionDocidListForDataPackage(docIdString);
2534
2535
                //get the whole documentImple object
2536
                documentImplList = getOldVersionAllDocumentImpl(docIdList);
2537 1292 tao
            }//else
2538 940 tao
2539 2075 jones
            // Make sure documentImplist is not empty
2540
            if (documentImplList.isEmpty()) { throw new Exception(
2541
                    "Couldn't find component for data package: " + packageId); }//if
2542 2043 sgarg
2543 2075 jones
            zOut = new ZipOutputStream(out);
2544
            //put every element into zip output stream
2545
            for (int i = 0; i < documentImplList.size(); i++) {
2546
                // if the object in the vetor is String, this means we couldn't
2547
                // find
2548
                // the document locally, we need find it remote
2549
                if ((((documentImplList.elementAt(i)).getClass()).toString())
2550
                        .equals("class java.lang.String")) {
2551
                    // Get String object from vetor
2552
                    String documentId = (String) documentImplList.elementAt(i);
2553 5165 daigle
                    logMetacat.info("DBQuery.getZippedPackage - docid: " + documentId);
2554 2075 jones
                    // Get doicd without revision
2555 5025 daigle
                    String docidWithoutRevision =
2556
                    	DocumentUtil.getDocIdFromString(documentId);
2557 5165 daigle
                    logMetacat.info("DBQuery.getZippedPackage - docidWithoutRevsion: "
2558 2663 sgarg
                            + docidWithoutRevision);
2559 2075 jones
                    // Get revision
2560 5025 daigle
                    String revision =
2561
                    	DocumentUtil.getRevisionStringFromString(documentId);
2562 5165 daigle
                    logMetacat.info("DBQuery.getZippedPackage - revision from docIdentifier: "
2563 2663 sgarg
                            + revision);
2564 2075 jones
                    // Zip entry string
2565
                    String zipEntryPath = rootName + "/data/";
2566
                    // Create a RemoteDocument object
2567
                    RemoteDocument remoteDoc = new RemoteDocument(
2568
                            docidWithoutRevision, revision, user, passWord,
2569
                            zipEntryPath);
2570
                    // Here we only read data file from remote metacat
2571
                    String docType = remoteDoc.getDocType();
2572
                    if (docType != null) {
2573
                        if (docType.equals("BIN")) {
2574
                            // Put remote document to zip output
2575
                            remoteDoc.readDocumentFromRemoteServerByZip(zOut);
2576
                            // Add String object to htmlDocumentImplList
2577
                            String elementInHtmlList = remoteDoc
2578
                                    .getDocIdWithoutRevsion()
2579 4212 daigle
                                    + PropertyService.getProperty("document.accNumSeparator")
2580 2075 jones
                                    + remoteDoc.getRevision();
2581
                            htmlDocumentImplList.add(elementInHtmlList);
2582
                        }//if
2583
                    }//if
2584 1361 tao
2585 2075 jones
                }//if
2586
                else {
2587
                    //create a docmentImpls object (represent xml doc) base on
2588
                    // the docId
2589
                    docImpls = (DocumentImpl) documentImplList.elementAt(i);
2590
                    //checking if the user has the permission to read the
2591
                    // documents
2592 7665 leinfelder
2593
                    String fullDocId = docImpls.getDocID() + PropertyService.getProperty("document.accNumSeparator") + docImpls.getRev();
2594
					if (DocumentImpl.hasReadPermission(user, groups, fullDocId )) {
2595 2075 jones
                        //if the docImpls is metadata
2596
                        if ((docImpls.getDoctype()).compareTo("BIN") != 0) {
2597
                            //add metadata into zip output stream
2598
                            addDocToZipOutputStream(docImpls, zOut, rootName);
2599
                            //add the documentImpl into the vetor which will
2600
                            // be used in html
2601
                            htmlDocumentImplList.add(docImpls);
2602 2043 sgarg
2603 2075 jones
                        }//if
2604
                        else {
2605
                            //it is data file
2606
                            addDataFileToZipOutputStream(docImpls, zOut,
2607
                                    rootName);
2608
                            htmlDocumentImplList.add(docImpls);
2609
                        }//else
2610
                    }//if
2611
                }//else
2612
            }//for
2613 2043 sgarg
2614 2075 jones
            //add html summary file
2615
            addHtmlSummaryToZipOutputStream(htmlDocumentImplList, zOut,
2616
                    rootName);
2617
            zOut.finish(); //terminate the zip file
2618
            //dbConn.close();
2619
            return zOut;
2620
        }//else
2621
    }//getZippedPackage()
2622 2043 sgarg
2623 2075 jones
    private class ReturnFieldValue
2624 1361 tao
    {
2625 2043 sgarg
2626 2075 jones
        private String docid = null; //return field value for this docid
2627 2043 sgarg
2628 2075 jones
        private String fieldValue = null;
2629 2043 sgarg
2630 2075 jones
        private String xmlFieldValue = null; //return field value in xml
2631
                                             // format
2632 3635 leinfelder
        private String fieldType = null; //ATTRIBUTE, TEXT...
2633 2075 jones
2634
        public void setDocid(String myDocid)
2635
        {
2636
            docid = myDocid;
2637
        }
2638
2639
        public String getDocid()
2640
        {
2641
            return docid;
2642
        }
2643
2644
        public void setFieldValue(String myValue)
2645
        {
2646
            fieldValue = myValue;
2647
        }
2648
2649
        public String getFieldValue()
2650
        {
2651
            return fieldValue;
2652
        }
2653
2654
        public void setXMLFieldValue(String xml)
2655
        {
2656
            xmlFieldValue = xml;
2657
        }
2658
2659
        public String getXMLFieldValue()
2660
        {
2661
            return xmlFieldValue;
2662
        }
2663 3635 leinfelder
2664
        public void setFieldType(String myType)
2665
        {
2666
            fieldType = myType;
2667
        }
2668 2075 jones
2669 3635 leinfelder
        public String getFieldType()
2670
        {
2671
            return fieldType;
2672
        }
2673
2674 1361 tao
    }
2675 3246 berkley
2676
    /**
2677
     * a class to store one result document consisting of a docid and a document
2678
     */
2679
    private class ResultDocument
2680
    {
2681
      public String docid;
2682
      public String document;
2683
2684
      public ResultDocument(String docid, String document)
2685
      {
2686
        this.docid = docid;
2687
        this.document = document;
2688
      }
2689
    }
2690
2691
    /**
2692
     * a private class to handle a set of resultDocuments
2693
     */
2694
    private class ResultDocumentSet
2695
    {
2696
      private Vector docids;
2697
      private Vector documents;
2698
2699
      public ResultDocumentSet()
2700
      {
2701
        docids = new Vector();
2702
        documents = new Vector();
2703
      }
2704
2705
      /**
2706
       * adds a result document to the set
2707
       */
2708
      public void addResultDocument(ResultDocument rd)
2709
      {
2710
        if(rd.docid == null)
2711 3263 tao
          return;
2712 3246 berkley
        if(rd.document == null)
2713
          rd.document = "";
2714 3349 tao
2715 3263 tao
           docids.addElement(rd.docid);
2716
           documents.addElement(rd.document);
2717 3349 tao
2718 3246 berkley
      }
2719
2720
      /**
2721
       * gets an iterator of docids
2722
       */
2723
      public Iterator getDocids()
2724
      {
2725
        return docids.iterator();
2726
      }
2727
2728
      /**
2729
       * gets an iterator of documents
2730
       */
2731
      public Iterator getDocuments()
2732
      {
2733
        return documents.iterator();
2734
      }
2735
2736
      /**
2737
       * returns the size of the set
2738
       */
2739
      public int size()
2740
      {
2741
        return docids.size();
2742
      }
2743
2744
      /**
2745
       * tests to see if this set contains the given docid
2746
       */
2747 3337 tao
      private boolean containsDocid(String docid)
2748 3246 berkley
      {
2749
        for(int i=0; i<docids.size(); i++)
2750
        {
2751
          String docid0 = (String)docids.elementAt(i);
2752
          if(docid0.trim().equals(docid.trim()))
2753
          {
2754
            return true;
2755
          }
2756
        }
2757
        return false;
2758
      }
2759
2760
      /**
2761
       * removes the element with the given docid
2762
       */
2763
      public String remove(String docid)
2764
      {
2765
        for(int i=0; i<docids.size(); i++)
2766
        {
2767
          String docid0 = (String)docids.elementAt(i);
2768
          if(docid0.trim().equals(docid.trim()))
2769
          {
2770
            String returnDoc = (String)documents.elementAt(i);
2771
            documents.remove(i);
2772
            docids.remove(i);
2773
            return returnDoc;
2774
          }
2775
        }
2776
        return null;
2777
      }
2778
2779
      /**
2780
       * add a result document
2781
       */
2782
      public void put(ResultDocument rd)
2783
      {
2784
        addResultDocument(rd);
2785
      }
2786
2787
      /**
2788
       * add a result document by components
2789
       */
2790
      public void put(String docid, String document)
2791
      {
2792
        addResultDocument(new ResultDocument(docid, document));
2793
      }
2794
2795
      /**
2796
       * get the document part of the result document by docid
2797
       */
2798
      public Object get(String docid)
2799
      {
2800
        for(int i=0; i<docids.size(); i++)
2801
        {
2802
          String docid0 = (String)docids.elementAt(i);
2803
          if(docid0.trim().equals(docid.trim()))
2804
          {
2805
            return documents.elementAt(i);
2806
          }
2807
        }
2808
        return null;
2809
      }
2810
2811
      /**
2812
       * get the document part of the result document by an object
2813
       */
2814
      public Object get(Object o)
2815
      {
2816
        return get((String)o);
2817
      }
2818
2819
      /**
2820
       * get an entire result document by index number
2821
       */
2822
      public ResultDocument get(int index)
2823
      {
2824
        return new ResultDocument((String)docids.elementAt(index),
2825
          (String)documents.elementAt(index));
2826
      }
2827
2828
      /**
2829
       * return a string representation of this object
2830
       */
2831
      public String toString()
2832
      {
2833
        String s = "";
2834
        for(int i=0; i<docids.size(); i++)
2835
        {
2836
          s += (String)docids.elementAt(i) + "\n";
2837
        }
2838
        return s;
2839
      }
2840 3263 tao
      /*
2841
       * Set a new document value for a given docid
2842
       */
2843
      public void set(String docid, String document)
2844
      {
2845
    	   for(int i=0; i<docids.size(); i++)
2846
           {
2847
             String docid0 = (String)docids.elementAt(i);
2848
             if(docid0.trim().equals(docid.trim()))
2849
             {
2850
                 documents.set(i, document);
2851
             }
2852
           }
2853
2854
      }
2855 3246 berkley
    }
2856 155 jones
}