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