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