Project

General

Profile

1 155 jones
/**
2 203 jones
 *  '$RCSfile$'
3
 *    Purpose: A Class that represents a structured query, and can be
4
 *             constructed from an XML serialization conforming to
5
 *             pathquery.dtd. The printSQL() method can be used to print
6
 *             a SQL serialization of the query.
7
 *  Copyright: 2000 Regents of the University of California and the
8
 *             National Center for Ecological Analysis and Synthesis
9
 *    Authors: Matt Jones
10 349 jones
 *    Release: @release@
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
package edu.ucsb.nceas.metacat;
32
33 899 berkley
import edu.ucsb.nceas.dbadapter.*;
34
35 155 jones
import java.io.*;
36 1354 tao
import java.util.Hashtable;
37 155 jones
import java.util.Stack;
38 158 jones
import java.util.Vector;
39 159 jones
import java.util.Enumeration;
40 155 jones
41 185 jones
import org.xml.sax.Attributes;
42 158 jones
import org.xml.sax.InputSource;
43
import org.xml.sax.SAXException;
44
import org.xml.sax.SAXParseException;
45 185 jones
import org.xml.sax.XMLReader;
46
import org.xml.sax.helpers.XMLReaderFactory;
47
import org.xml.sax.helpers.DefaultHandler;
48 155 jones
49 402 berkley
/**
50 172 jones
 * A Class that represents a structured query, and can be
51
 * constructed from an XML serialization conforming to @see pathquery.dtd.
52
 * The printSQL() method can be used to print a SQL serialization of the query.
53 155 jones
 */
54 185 jones
public class QuerySpecification extends DefaultHandler {
55 155 jones
56 745 jones
  /** flag determining whether extended query terms are present */
57 402 berkley
  private boolean containsExtendedSQL=false;
58 745 jones
  /** Identifier for this query document */
59 158 jones
  private String meta_file_id;
60 745 jones
  /** Title of this query */
61
  private String queryTitle;
62
  /** List of document types to be returned using package back tracing */
63 743 jones
  private Vector returnDocList;
64 745 jones
  /** List of document types to be searched */
65 743 jones
  private Vector filterDocList;
66 745 jones
  /** List of fields to be returned in result set */
67 402 berkley
  private Vector returnFieldList;
68 745 jones
  /** List of users owning documents to be searched */
69 535 jones
  private Vector ownerList;
70 745 jones
  /** List of sites/scopes used to constrain search */
71 535 jones
  private Vector siteList;
72 745 jones
  /** The root query group that contains the recursive query constraints */
73 158 jones
  private QueryGroup query = null;
74 1348 tao
75 745 jones
  // Query data structures used temporarily during XML parsing
76 158 jones
  private Stack elementStack;
77
  private Stack queryStack;
78 159 jones
  private String currentValue;
79
  private String currentPathexpr;
80 172 jones
  private String parserName = null;
81 535 jones
  private String accNumberSeparator = null;
82 899 berkley
  private static final AbstractDatabase dbAdapter = MetaCatUtil.dbAdapter;
83 1301 tao
84 1832 tao
85 1350 tao
  private boolean percentageSearch = false;
86
87 1301 tao
  private String userName = null;
88
  private static final String PUBLIC = "public";
89
  private String [] group = null;
90 158 jones
91 1348 tao
  public static final String ATTRIBUTESYMBOL = "@";
92 1354 tao
  private boolean hasAttributeReturnField = false;
93
  private Hashtable attributeReturnList = new Hashtable();
94
  private int countAttributeReturnField = 0;
95 155 jones
  /**
96
   * construct an instance of the QuerySpecification class
97
   *
98 172 jones
   * @param queryspec the XML representation of the query (should conform
99
   *                  to pathquery.dtd) as a Reader
100
   * @param parserName the fully qualified name of a Java Class implementing
101 185 jones
   *                  the org.xml.sax.XMLReader interface
102 155 jones
   */
103 535 jones
  public QuerySpecification( Reader queryspec, String parserName,
104
         String accNumberSeparator ) throws IOException {
105 155 jones
    super();
106 402 berkley
107 172 jones
    // Initialize the class variables
108 743 jones
    returnDocList = new Vector();
109
    filterDocList = new Vector();
110 158 jones
    elementStack = new Stack();
111
    queryStack   = new Stack();
112 402 berkley
    returnFieldList = new Vector();
113 535 jones
    ownerList = new Vector();
114
    siteList = new Vector();
115 172 jones
    this.parserName = parserName;
116 535 jones
    this.accNumberSeparator = accNumberSeparator;
117 158 jones
118
    // Initialize the parser and read the queryspec
119 185 jones
    XMLReader parser = initializeParser();
120 181 jones
    if (parser == null) {
121
      System.err.println("SAX parser not instantiated properly.");
122
    }
123 155 jones
    try {
124
      parser.parse(new InputSource(queryspec));
125
    } catch (SAXException e) {
126 675 berkley
      System.err.println("error parsing data in " +
127
                         "QuerySpecification.QuerySpecification");
128 180 jones
      System.err.println(e.getMessage());
129 155 jones
    }
130
  }
131
132
  /**
133
   * construct an instance of the QuerySpecification class
134
   *
135 172 jones
   * @param queryspec the XML representation of the query (should conform
136
   *                  to pathquery.dtd) as a String
137
   * @param parserName the fully qualified name of a Java Class implementing
138
   *                  the org.xml.sax.Parser interface
139 155 jones
   */
140 535 jones
  public QuerySpecification( String queryspec, String parserName,
141
         String accNumberSeparator) throws IOException {
142
    this(new StringReader(queryspec), parserName, accNumberSeparator);
143 155 jones
  }
144 1301 tao
145
  /**
146 1833 tao
   * construct an instance of the QuerySpecification class which don't need
147
   * to parser a xml document
148
   * @param accNumberSeparator  the separator between doc version
149
   */
150
  public QuerySpecification(String accNumberSeparator ) throws IOException
151
  {
152
    // Initialize the class variables
153
    returnDocList = new Vector();
154
    filterDocList = new Vector();
155
    elementStack = new Stack();
156
    queryStack   = new Stack();
157
    returnFieldList = new Vector();
158
    ownerList = new Vector();
159
    siteList = new Vector();
160
    this.accNumberSeparator = accNumberSeparator;
161
   }
162
163
164
  /**
165 1301 tao
   * Method to set user name
166
   *
167
   * @param myName  the user name
168
   */
169
  public void setUserName(String myName)
170 2045 tao
  {
171
    //to lower case
172
    if (myName != null)
173
    {
174
      this.userName = myName.toLowerCase();
175
    }
176
    else
177
    {
178
      this.userName = myName;
179
    }
180 1301 tao
  }
181
182
  /**
183
   * Method to set user group
184
   *
185
   * @param myGroup  the user group
186
   */
187
  public void setGroup(String [] myGroup)
188
  {
189
    this.group = myGroup;
190
  }
191 1350 tao
  /**
192
   * Method to indicate this query is a percentage search
193
   */
194
  public boolean isPercentageSearch()
195
  {
196
    return percentageSearch;
197
  }
198 1301 tao
  /*
199
   * Method to get owner query. If it is owner it has all permission
200
   */
201
  private String createOwerQuery()
202
  {
203
    String ownerQuery = null;
204 1452 tao
    ownerQuery = "SELECT docid FROM xml_documents WHERE ";
205 1301 tao
    if (userName != null && !userName.equals(""))
206
    {
207 2045 tao
      ownerQuery = ownerQuery + "lower(user_owner) ='"+ userName +"'";
208 1301 tao
    }
209
210
    MetaCatUtil.debugMessage("OwnerQuery: "+ownerQuery, 30);
211
    return ownerQuery;
212
  }
213
214
  /*
215
   * Method to create query for xml_access, this part is to get docid list which
216
   * have a allow rule for a given user
217
   */
218
  private String createAllowRuleQuery()
219
  {
220
    String allowQuery = null;
221 1446 tao
    String allowString = constructAllowString();
222 1447 tao
    allowQuery ="SELECT docid from xml_access WHERE( "+allowString;
223
    allowQuery = allowQuery +") AND subtreeid IS NULL";
224 1446 tao
    MetaCatUtil.debugMessage("allow query is: "+ allowQuery, 30);
225
    return allowQuery;
226
227
228
  }
229
230
  /* Method to construct a allow rule string */
231
  private String constructAllowString()
232
  {
233
    String allowQuery ="";
234
     // add allow rule for user name
235
     if (userName != null && !userName.equals(""))
236 1301 tao
    {
237 2045 tao
      allowQuery = allowQuery +"(lower(principal_name) = '" + userName
238 1304 tao
                              +"' AND perm_type = 'allow'"
239
                              +" AND (permission='4' OR permission='7'))";
240 1301 tao
    }
241
    // add allow rule for public
242 2045 tao
    allowQuery = allowQuery +"OR (lower(principal_name) = '" + PUBLIC
243 1304 tao
                              +"' AND perm_type = 'allow'"
244
                              +" AND (permission='4' OR permission='7'))";
245 1301 tao
246
    // add allow rule for group
247
    if (group != null)
248
    {
249
      for (int i = 0; i< group.length; i++)
250
      {
251
        String groupUint = group[i];
252
        if (groupUint != null && !groupUint.equals(""))
253
        {
254 2045 tao
          groupUint = groupUint.toLowerCase();
255
          allowQuery = allowQuery +" OR (lower(principal_name) = '" + groupUint
256 1304 tao
                              +"' AND perm_type = 'allow'"
257
                              +" AND (permission='4' OR permission='7'))";
258 1301 tao
        }//if
259
      }//for
260
    }//if
261 1446 tao
    MetaCatUtil.debugMessage("allow string is: "+ allowQuery, 40);
262 1301 tao
    return allowQuery;
263
  }
264 155 jones
265 1301 tao
   /*
266
   * Method to create query for xml_access, this part is to get docid list which
267
   * have a deny rule and perm_order is allowFirst for a given user. This means
268
   * the user will be denied to read
269
   */
270
  private String createDenyRuleQuery()
271
  {
272
    String denyQuery = null;
273 1446 tao
    String denyString = constructDenyString();
274 1447 tao
    denyQuery ="SELECT docid from xml_access WHERE( " + denyString;
275
    denyQuery = denyQuery + ") AND subtreeid IS NULL ";
276 1446 tao
    MetaCatUtil.debugMessage("denyquery is: "+ denyQuery, 30);
277
    return denyQuery;
278
279
  }
280
  /* Construct deny string */
281
  private String constructDenyString()
282
  {
283
    String denyQuery ="";
284 1301 tao
    // add deny rule for user name
285
    if (userName != null && !userName.equals(""))
286
    {
287 2045 tao
      denyQuery = denyQuery +"(lower(principal_name) = '" + userName
288 1301 tao
                              +"' AND perm_type = 'deny' "
289 1304 tao
                              +"AND perm_order ='allowFirst'"
290
                              +" AND (permission='4' OR permission='7'))";
291 1301 tao
    }
292
    // add deny rule for public
293 2045 tao
    denyQuery = denyQuery +"OR (lower(principal_name) = '" + PUBLIC
294 1301 tao
                               +"' AND perm_type = 'deny' "
295 1304 tao
                               +"AND perm_order ='allowFirst'"
296
                               +" AND (permission='4' OR permission='7'))";
297 1301 tao
298
    // add allow rule for group
299
    if (group != null)
300
    {
301
      for (int i = 0; i< group.length; i++)
302
      {
303
        String groupUint = group[i];
304
        if (groupUint != null && !groupUint.equals(""))
305
        {
306 2045 tao
          groupUint = groupUint.toLowerCase();
307
          denyQuery = denyQuery +" OR (lower(principal_name) = '" + groupUint
308 1301 tao
                                +"' AND perm_type = 'deny' "
309 1304 tao
                                +"AND perm_order ='allowFirst'"
310
                                +" AND (permission='4' OR permission='7'))";
311 1301 tao
        }//if
312
      }//for
313
    }//if
314
    return denyQuery;
315
  }
316
317
  /**
318
   * Method to append a access control query to SQL. So in DBQuery class, we can
319
   * get docid from both user specified query and access control query. We don't
320
   * need to checking permission after we get the doclist. It will be good to
321
   * performance
322
   *
323
   */
324
  public String getAccessQuery()
325
  {
326
    String accessQuery = null;
327
    String onwer = createOwerQuery();
328
    String allow = createAllowRuleQuery();
329
    String deny = createDenyRuleQuery();
330
    accessQuery = " AND (docid IN("+ onwer + ")";
331
    accessQuery = accessQuery + " OR (docid IN (" + allow + ")"
332
                 + " AND docid NOT IN ("+ deny + ")))";
333
    MetaCatUtil.debugMessage("accessquery is: "+ accessQuery, 30);
334
    return accessQuery;
335
  }
336
337 155 jones
  /** Main routine for testing */
338
  static public void main(String[] args) {
339
340
     if (args.length < 1) {
341
       System.err.println("Wrong number of arguments!!!");
342
       System.err.println("USAGE: java QuerySpecification <xmlfile>");
343
       return;
344
     } else {
345 711 jones
       int i = 0;
346
       boolean useXMLIndex = true;
347
       if ( args[i].equals( "-noindex" ) ) {
348
         useXMLIndex = false;
349
         i++;
350
       }
351
       String xmlfile  = args[i];
352
353 155 jones
       try {
354 203 jones
         MetaCatUtil util = new MetaCatUtil();
355 155 jones
         FileReader xml = new FileReader(new File(xmlfile));
356 203 jones
         QuerySpecification qspec =
357 535 jones
                 new QuerySpecification(xml, util.getOption("saxparser"),
358
                                        util.getOption("accNumberSeparator"));
359 706 bojilova
         System.out.println(qspec.printSQL(useXMLIndex));
360 181 jones
361 155 jones
       } catch (IOException e) {
362
         System.err.println(e.getMessage());
363
       }
364
365
     }
366
  }
367 402 berkley
368
  /**
369
   * Returns true if the parsed query contains and extended xml query
370
   * (i.e. there is at least one &lt;returnfield&gt; in the pathquery document)
371
   */
372
  public boolean containsExtendedSQL()
373
  {
374
    if(containsExtendedSQL)
375
    {
376
      return true;
377
    }
378
    else
379
    {
380
      return false;
381
    }
382
  }
383
384
  /**
385 1354 tao
   * A method to get if the query has an attribute return field
386
   */
387
  public boolean containAttributeReturnField()
388
  {
389
    return hasAttributeReturnField;
390
  }
391
392
  /**
393 745 jones
   * Accessor method to return the identifier of this Query
394
   */
395
  public String getIdentifier()
396
  {
397
    return meta_file_id;
398
  }
399
400
  /**
401
   * method to set the identifier of this query
402
   */
403
  public void setIdentifier(String id) {
404
    this.meta_file_id = id;
405
  }
406
407
  /**
408
   * Accessor method to return the title of this Query
409
   */
410
  public String getQueryTitle()
411
  {
412
    return queryTitle;
413
  }
414
415
  /**
416
   * method to set the title of this query
417
   */
418
  public void setQueryTitle(String title)
419
  {
420
    this.queryTitle = title;
421
  }
422
423
  /**
424
   * Accessor method to return a vector of the return document types as
425
   * defined in the &lt;returndoctype&gt; tag in the pathquery dtd.
426
   */
427
  public Vector getReturnDocList()
428
  {
429
    return this.returnDocList;
430
  }
431
432
  /**
433
   * method to set the list of return docs of this query
434
   */
435
  public void setReturnDocList(Vector returnDocList)
436
  {
437
    this.returnDocList = returnDocList;
438
  }
439
440
  /**
441
   * Accessor method to return a vector of the filter doc types as
442
   * defined in the &lt;filterdoctype&gt; tag in the pathquery dtd.
443
   */
444
  public Vector getFilterDocList()
445
  {
446
    return this.filterDocList;
447
  }
448
449
  /**
450
   * method to set the list of filter docs of this query
451
   */
452
  public void setFilterDocList(Vector filterDocList)
453
  {
454
    this.filterDocList = filterDocList;
455
  }
456
457
  /**
458 402 berkley
   * Accessor method to return a vector of the extended return fields as
459
   * defined in the &lt;returnfield&gt; tag in the pathquery dtd.
460
   */
461
  public Vector getReturnFieldList()
462
  {
463
    return this.returnFieldList;
464
  }
465 155 jones
466 172 jones
  /**
467 745 jones
   * method to set the list of fields to be returned by this query
468
   */
469
  public void setReturnFieldList(Vector returnFieldList)
470
  {
471
    this.returnFieldList = returnFieldList;
472
  }
473
474
  /**
475
   * Accessor method to return a vector of the owner fields as
476
   * defined in the &lt;owner&gt; tag in the pathquery dtd.
477
   */
478
  public Vector getOwnerList()
479
  {
480
    return this.ownerList;
481
  }
482
483
  /**
484
   * method to set the list of owners used to constrain this query
485
   */
486
  public void setOwnerList(Vector ownerList)
487
  {
488
    this.ownerList = ownerList;
489
  }
490
491
  /**
492
   * Accessor method to return a vector of the site fields as
493
   * defined in the &lt;site&gt; tag in the pathquery dtd.
494
   */
495
  public Vector getSiteList()
496
  {
497
    return this.siteList;
498
  }
499
500
  /**
501
   * method to set the list of sites used to constrain this query
502
   */
503
  public void setSiteList(Vector siteList)
504
  {
505
    this.siteList = siteList;
506
  }
507
508
  /**
509
   * get the QueryGroup used to express query constraints
510
   */
511
  public QueryGroup getQueryGroup()
512
  {
513
    return query;
514
  }
515 1832 tao
516
  /**
517
   * set the querygroup
518
   */
519
  public void setQueryGroup(QueryGroup group)
520
  {
521
    query = group;
522
  }
523 1833 tao
524 745 jones
  /**
525 1833 tao
   * set if this query sepcification has extendQuery(has return doc type or not)
526
   */
527
  public void setContainsExtenedSQL(boolean hasExtenedQuery)
528
  {
529
     containsExtendedSQL = hasExtenedQuery;
530
  }
531
532
  /**
533 172 jones
   * Set up the SAX parser for reading the XML serialized query
534
   */
535 185 jones
  private XMLReader initializeParser() {
536
    XMLReader parser = null;
537 172 jones
538 155 jones
    // Set up the SAX document handlers for parsing
539
    try {
540
541
      // Get an instance of the parser
542 185 jones
      parser = XMLReaderFactory.createXMLReader(parserName);
543 155 jones
544 185 jones
      // Set the ContentHandler to this instance
545
      parser.setContentHandler(this);
546 155 jones
547 185 jones
      // Set the error Handler to this instance
548 158 jones
      parser.setErrorHandler(this);
549 155 jones
550
    } catch (Exception e) {
551 675 berkley
       System.err.println("Error in QuerySpcecification.initializeParser " +
552
                           e.toString());
553 155 jones
    }
554
555
    return parser;
556
  }
557
558 172 jones
  /**
559
   * callback method used by the SAX Parser when the start tag of an
560
   * element is detected. Used in this context to parse and store
561
   * the query information in class variables.
562
   */
563 185 jones
  public void startElement (String uri, String localName,
564
                            String qName, Attributes atts)
565 155 jones
         throws SAXException {
566 185 jones
    BasicNode currentNode = new BasicNode(localName);
567 159 jones
    // add attributes to BasicNode here
568
    if (atts != null) {
569
      int len = atts.getLength();
570
      for (int i = 0; i < len; i++) {
571 185 jones
        currentNode.setAttribute(atts.getLocalName(i), atts.getValue(i));
572 159 jones
      }
573
    }
574
575 158 jones
    elementStack.push(currentNode);
576 159 jones
    if (currentNode.getTagName().equals("querygroup")) {
577 158 jones
      QueryGroup currentGroup = new QueryGroup(
578 178 jones
                                currentNode.getAttribute("operator"));
579 158 jones
      if (query == null) {
580
        query = currentGroup;
581 159 jones
      } else {
582
        QueryGroup parentGroup = (QueryGroup)queryStack.peek();
583
        parentGroup.addChild(currentGroup);
584 158 jones
      }
585 159 jones
      queryStack.push(currentGroup);
586 158 jones
    }
587 155 jones
  }
588
589 172 jones
  /**
590
   * callback method used by the SAX Parser when the end tag of an
591
   * element is detected. Used in this context to parse and store
592
   * the query information in class variables.
593
   */
594 185 jones
  public void endElement (String uri, String localName,
595
                          String qName) throws SAXException {
596 158 jones
    BasicNode leaving = (BasicNode)elementStack.pop();
597 159 jones
    if (leaving.getTagName().equals("queryterm")) {
598
      boolean isCaseSensitive = (new Boolean(
599
              leaving.getAttribute("casesensitive"))).booleanValue();
600
      QueryTerm currentTerm = null;
601
      if (currentPathexpr == null) {
602
        currentTerm = new QueryTerm(isCaseSensitive,
603
                      leaving.getAttribute("searchmode"),currentValue);
604
      } else {
605
        currentTerm = new QueryTerm(isCaseSensitive,
606
                      leaving.getAttribute("searchmode"),currentValue,
607
                      currentPathexpr);
608
      }
609
      QueryGroup currentGroup = (QueryGroup)queryStack.peek();
610
      currentGroup.addChild(currentTerm);
611
      currentValue = null;
612
      currentPathexpr = null;
613
    } else if (leaving.getTagName().equals("querygroup")) {
614
      QueryGroup leavingGroup = (QueryGroup)queryStack.pop();
615 158 jones
    }
616 155 jones
  }
617 158 jones
618 172 jones
  /**
619
   * callback method used by the SAX Parser when the text sequences of an
620
   * xml stream are detected. Used in this context to parse and store
621
   * the query information in class variables.
622
   */
623 158 jones
  public void characters(char ch[], int start, int length) {
624
625
    String inputString = new String(ch, start, length);
626
    BasicNode currentNode = (BasicNode)elementStack.peek();
627
    String currentTag = currentNode.getTagName();
628
    if (currentTag.equals("meta_file_id")) {
629
      meta_file_id = inputString;
630 745 jones
    } else if (currentTag.equals("querytitle")) {
631
      queryTitle = inputString;
632 159 jones
    } else if (currentTag.equals("value")) {
633
      currentValue = inputString;
634
    } else if (currentTag.equals("pathexpr")) {
635
      currentPathexpr = inputString;
636 172 jones
    } else if (currentTag.equals("returndoctype")) {
637 743 jones
      returnDocList.add(inputString);
638 745 jones
    } else if (currentTag.equals("filterdoctype")) {
639
      filterDocList.add(inputString);
640 402 berkley
    } else if (currentTag.equals("returnfield")) {
641 1833 tao
       handleReturnField(inputString);
642
    } else if (currentTag.equals("filterdoctype")) {
643
      filterDocList.add(inputString);
644
    } else if (currentTag.equals("owner")) {
645
      ownerList.add(inputString);
646
    } else if (currentTag.equals("site")) {
647
      siteList.add(inputString);
648
    }
649
  }
650
651
  /**
652
   * Method to transfer string to return field
653
   */
654
  public void handleReturnField(String inputString)
655
  {
656
     // make sure if return fields has an attribute or not
657 1354 tao
      if (inputString.indexOf(ATTRIBUTESYMBOL) ==-1)
658
      {
659
        // no attribute value will be returned
660
        returnFieldList.add(inputString);
661
        containsExtendedSQL = true;
662
      }
663
      else
664
      {
665
        // has a attribute return field
666
        // divied the return filed into two parts, one is path and the
667
        // other is attribue name
668
        String returnPath = newPathExpressionWithOutAttribute(inputString);
669
        String attributeName = getAttributeName(inputString);
670
        Vector pathInfo = new Vector();
671
        // the vector has the information about return path and attributename
672
        pathInfo.addElement(returnPath);
673
        pathInfo.addElement(attributeName);
674
        // put the vector into a hash table. The reseaon why don't put
675
        // return path or attributename as a key is because they are not unique
676
        attributeReturnList.put
677
                            (new Integer(countAttributeReturnField), pathInfo);
678
        countAttributeReturnField++;
679
        hasAttributeReturnField = true;
680
        containsExtendedSQL = true;
681
682
      }
683 158 jones
  }
684 172 jones
  /**
685
   * create a SQL serialization of the query that this instance represents
686
   */
687 706 bojilova
  public String printSQL(boolean useXMLIndex) {
688 1350 tao
689
690 170 jones
    StringBuffer self = new StringBuffer();
691
692 692 bojilova
    self.append("SELECT docid,docname,doctype,");
693 626 berkley
    self.append("date_created, date_updated, rev ");
694 172 jones
    self.append("FROM xml_documents WHERE docid IN (");
695 170 jones
696 178 jones
    // This determines the documents that meet the query conditions
697 706 bojilova
    self.append(query.printSQL(useXMLIndex));
698 172 jones
699
    self.append(") ");
700 402 berkley
701 172 jones
    // Add SQL to filter for doctypes requested in the query
702 743 jones
    // This is an implicit OR for the list of doctypes. Only doctypes in this
703
    // list will be searched if the tag is present
704
    if (!filterDocList.isEmpty()) {
705 172 jones
      boolean firstdoctype = true;
706
      self.append(" AND (");
707 743 jones
      Enumeration en = filterDocList.elements();
708 172 jones
      while (en.hasMoreElements()) {
709
        String currentDoctype = (String)en.nextElement();
710
        if (firstdoctype) {
711 402 berkley
           firstdoctype = false;
712
           self.append(" doctype = '" + currentDoctype + "'");
713 172 jones
        } else {
714
          self.append(" OR doctype = '" + currentDoctype + "'");
715
        }
716
      }
717
      self.append(") ");
718
    }
719 743 jones
720 535 jones
    // Add SQL to filter for owners requested in the query
721
    // This is an implicit OR for the list of owners
722
    if (!ownerList.isEmpty()) {
723
      boolean first = true;
724
      self.append(" AND (");
725
      Enumeration en = ownerList.elements();
726
      while (en.hasMoreElements()) {
727
        String current = (String)en.nextElement();
728 2045 tao
        if (current != null)
729
        {
730
          current = current.toLowerCase();
731
        }
732 535 jones
        if (first) {
733
           first = false;
734 2045 tao
           self.append(" lower(user_owner) = '" + current + "'");
735 535 jones
        } else {
736 2045 tao
          self.append(" OR lower(user_owner) = '" + current + "'");
737 535 jones
        }
738
      }
739
      self.append(") ");
740
    }
741
742
    // Add SQL to filter for sites requested in the query
743
    // This is an implicit OR for the list of sites
744
    if (!siteList.isEmpty()) {
745
      boolean first = true;
746
      self.append(" AND (");
747
      Enumeration en = siteList.elements();
748
      while (en.hasMoreElements()) {
749
        String current = (String)en.nextElement();
750
        if (first) {
751
           first = false;
752
           self.append(" SUBSTR(docid, 1, INSTR(docid, '" +
753
               accNumberSeparator + "')-1) = '" + current + "'");
754
        } else {
755
          self.append(" OR SUBSTR(docid, 1, INSTR(docid, '" +
756
               accNumberSeparator + "')-1) = '" + current + "'");
757
        }
758
      }
759
      self.append(") ");
760
    }
761 1350 tao
762
    // if there is only one percentage search item, this query is a percentage
763
    // search query
764 1832 tao
    MetaCatUtil.debugMessage("percentage number: " +
765
                                         query.getPercentageSymbolCount(), 35);
766
    if (query.getPercentageSymbolCount() ==1 )
767 1350 tao
    {
768 1832 tao
      MetaCatUtil.debugMessage("it is a percentage search", 30);
769 1350 tao
      percentageSearch =true;
770
    }
771
772 170 jones
    return self.toString();
773
  }
774 402 berkley
775 1446 tao
  /** This sql command will selecet startnodeid and endnodeid that user can NOT
776
    * access
777 1453 tao
    */
778 1446 tao
  public String printAccessControlSQLForReturnField(String doclist)
779
  {
780
    StringBuffer sql = new StringBuffer();
781
    String allowString = constructAllowString();
782
    String denyString = constructDenyString();
783 1451 tao
    sql.append("SELECT distinct startnodeid, endnodeid from xml_access ");
784 1446 tao
    sql.append("WHERE docid in (");
785
    sql.append(doclist);
786 1452 tao
    sql.append(") AND startnodeid IS NOT NULL AND ");
787 1446 tao
    sql.append("(");
788 1453 tao
    sql.append("(");
789
    sql.append("startnodeid NOT IN (SELECT startnodeid from xml_access, xml_documents ");
790
    sql.append(" WHERE xml_access.docid = xml_documents.docid");
791 2045 tao
    sql.append(" AND lower(xml_documents.user_owner) ='");
792 1453 tao
    sql.append(userName);
793 1454 tao
    sql.append("' AND xml_access.startnodeid IS NOT NULL)");
794 1453 tao
    sql.append(")");
795
    sql.append(" AND ");
796
    sql.append("(");
797 1454 tao
    sql.append("(startnodeid NOT IN (SELECT startnodeid from xml_access where( ");
798 1446 tao
    sql.append(allowString);
799 1454 tao
    sql.append(") AND (startnodeid IS NOT NULL))");
800 1446 tao
    sql.append(")");
801 1454 tao
    sql.append(" OR (startnodeid IN (SELECT startnodeid from xml_access where( ");
802 1446 tao
    sql.append(denyString);
803 1454 tao
    sql.append(") AND (startnodeid IS NOT NULL))");
804 1446 tao
    sql.append(")");
805
    sql.append(")");
806
    sql.append(")");
807
    MetaCatUtil.debugMessage("accessControlSQLForReturnField: " +
808
                             sql.toString(), 30);
809
    return sql.toString();
810
  }
811
812 402 berkley
  /**
813
   * This method prints sql based upon the &lt;returnfield&gt; tag in the
814
   * pathquery document.  This allows for customization of the
815
   * returned fields
816 465 berkley
   * @param doclist the list of document ids to search by
817 1449 tao
   * @param unaccessableNodePair  the node pair(start id and end id) which this
818
   *                               user could not access it
819 402 berkley
   */
820 1449 tao
  public String printExtendedSQL(String doclist, Hashtable unaccessableNodePair)
821 402 berkley
  {
822
    StringBuffer self = new StringBuffer();
823 1362 tao
    self.append("select xml_nodes.docid, xml_index.path, xml_nodes.nodedata, ");
824
    self.append("xml_nodes.parentnodeid ");
825 423 berkley
    self.append("from xml_index, xml_nodes where xml_index.nodeid=");
826
    self.append("xml_nodes.parentnodeid and (xml_index.path like '");
827 402 berkley
    boolean firstfield = true;
828
    //put the returnfields into the query
829
    //the for loop allows for multiple fields
830
    for(int i=0; i<returnFieldList.size(); i++)
831
    {
832
      if(firstfield)
833
      {
834
        firstfield = false;
835 405 berkley
        self.append((String)returnFieldList.elementAt(i));
836 402 berkley
        self.append("' ");
837
      }
838
      else
839
      {
840 423 berkley
        self.append("or xml_index.path like '");
841 405 berkley
        self.append((String)returnFieldList.elementAt(i));
842 402 berkley
        self.append("' ");
843
      }
844
    }
845 423 berkley
    self.append(") AND xml_nodes.docid in (");
846 465 berkley
    //self.append(query.printSQL());
847
    self.append(doclist);
848 402 berkley
    self.append(")");
849 423 berkley
    self.append(" AND xml_nodes.nodetype = 'TEXT'");
850 1449 tao
851
    // add control part for extended query
852
    Enumeration en = unaccessableNodePair.keys();
853
854
    while (en.hasMoreElements())
855
    {
856
      // Get control pairs in object
857
      Long startNodeIdObject = (Long)en.nextElement();
858
      Long endNodeIdObject = (Long)unaccessableNodePair.get(startNodeIdObject);
859
      // change it to long
860
      long startNodeId = startNodeIdObject.longValue();
861
      long endNodeId   = endNodeIdObject.longValue();
862
      // add into query
863 1451 tao
      self.append(" AND( xml_nodes.nodeid < ");
864 1449 tao
      self.append(startNodeId);
865 1451 tao
      self.append(" OR xml_nodes.nodeid > ");
866 1449 tao
      self.append(endNodeId);
867
      self.append(")");
868
    }
869 405 berkley
870 1350 tao
871 402 berkley
    return self.toString();
872
  }
873 465 berkley
874 1354 tao
  /**
875
   * This method prints sql based upon the returnfield tag in the
876
   * pathquery document has an attribute.  This allows for customization of the
877
   * returned fields
878
   * @param doclist the list of document ids to search by
879
   */
880
  public String printAttributeQuery(String doclist)
881
  {
882
    StringBuffer self = new StringBuffer();
883
    self.append("select xml_nodes.docid, xml_index.path, ");
884
    self.append("xml_nodes.nodedata, xml_nodes.nodename ");
885
    self.append("from xml_index, xml_nodes where xml_index.nodeid=");
886
    self.append("xml_nodes.parentnodeid and (");
887
    boolean firstfield = true;
888
    //put the returnfields attributes into the query
889
    //the for loop allows for multiple fields and attributes
890
    Enumeration returnAttributes = attributeReturnList.elements();
891
    while (returnAttributes.hasMoreElements())
892
    {
893
      Vector currentVector = (Vector)returnAttributes.nextElement();
894
      String returnPath = (String)currentVector.elementAt(0);
895
      String attributeName = (String)currentVector.elementAt(1);
896
      if(firstfield)
897
      {
898
        firstfield = false;
899
        self.append("( xml_index.path like '");
900
        self.append(returnPath);
901
        self.append("' AND xml_nodes.nodename like '");
902
        self.append(attributeName);
903
        self.append("') ");
904
      }
905
      else
906
      {
907
        self.append(" or ( xml_index.path like '");
908
        self.append(returnPath);
909
        self.append("' AND xml_nodes.nodename like '");
910
        self.append(attributeName);
911
        self.append("') ");
912
      }
913
    }
914
    self.append(") AND xml_nodes.docid in (");
915
    //self.append(query.printSQL());
916
    self.append(doclist);
917
    self.append(")");
918
    self.append(" AND xml_nodes.nodetype = 'ATTRIBUTE'");
919
    MetaCatUtil.debugMessage("Attribute query: "+self.toString(), 30);
920
921
    return self.toString();
922
  }
923
924 465 berkley
  public static String printRelationSQL(String docid)
925
  {
926
    StringBuffer self = new StringBuffer();
927 489 berkley
    self.append("select subject, relationship, object, subdoctype, ");
928
    self.append("objdoctype from xml_relation ");
929 743 jones
    self.append("where docid like '").append(docid).append("'");
930 465 berkley
    return self.toString();
931
  }
932 453 berkley
933 172 jones
  /**
934 465 berkley
   * Prints sql that returns all relations in the database.
935 453 berkley
   */
936
  public static String printPackageSQL()
937
  {
938
    StringBuffer self = new StringBuffer();
939
    self.append("select z.nodedata, x.nodedata, y.nodedata from ");
940
    self.append("(select nodeid, parentnodeid from xml_index where path like ");
941 743 jones
    self.append("'triple/subject') s, (select nodeid, parentnodeid ");
942 453 berkley
    self.append("from xml_index where path like ");
943 743 jones
    self.append("'triple/relationship') rel, ");
944 453 berkley
    self.append("(select nodeid, parentnodeid from xml_index where path like ");
945 743 jones
    self.append("'triple/object') o, ");
946 453 berkley
    self.append("xml_nodes x, xml_nodes y, xml_nodes z ");
947
    self.append("where s.parentnodeid = rel.parentnodeid ");
948
    self.append("and rel.parentnodeid = o.parentnodeid ");
949 899 berkley
    self.append("and x.parentnodeid in (rel.nodeid) ");
950
    self.append("and y.parentnodeid in (o.nodeid) ");
951
    self.append("and z.parentnodeid in (s.nodeid) ");
952 453 berkley
    //self.append("and z.nodedata like '%");
953
    //self.append(docid);
954
    //self.append("%'");
955
    return self.toString();
956
  }
957
958
  /**
959 465 berkley
   * Prints sql that returns all relations in the database that were input
960
   * under a specific docid
961
   * @param docid the docid to search for.
962
   */
963
  public static String printPackageSQL(String docid)
964
  {
965
    StringBuffer self = new StringBuffer();
966 1386 tao
    self.append("select z.nodedata, z.parentnodeid, ");
967
    self.append("x.nodedata, x.parentnodeid, y.nodedata, y.parentnodeid from ");
968 465 berkley
    self.append("(select nodeid, parentnodeid from xml_index where path like ");
969 743 jones
    self.append("'triple/subject') s, (select nodeid, parentnodeid ");
970 465 berkley
    self.append("from xml_index where path like ");
971 743 jones
    self.append("'triple/relationship') rel, ");
972 465 berkley
    self.append("(select nodeid, parentnodeid from xml_index where path like ");
973 743 jones
    self.append("'triple/object') o, ");
974 465 berkley
    self.append("xml_nodes x, xml_nodes y, xml_nodes z ");
975
    self.append("where s.parentnodeid = rel.parentnodeid ");
976
    self.append("and rel.parentnodeid = o.parentnodeid ");
977 899 berkley
    self.append("and x.parentnodeid in (rel.nodeid) ");
978
    self.append("and y.parentnodeid in (o.nodeid) ");
979
    self.append("and z.parentnodeid in (s.nodeid) ");
980 465 berkley
    self.append("and z.docid like '").append(docid).append("'");
981
982
    return self.toString();
983
  }
984
985
  /**
986
   * Returns all of the relations that has a certain docid in the subject
987
   * or the object.
988
   *
989
   * @param docid the docid to search for
990
   */
991
  public static String printPackageSQL(String subDocidURL, String objDocidURL)
992
  {
993
    StringBuffer self = new StringBuffer();
994
    self.append("select z.nodedata, x.nodedata, y.nodedata from ");
995
    self.append("(select nodeid, parentnodeid from xml_index where path like ");
996 743 jones
    self.append("'triple/subject') s, (select nodeid, parentnodeid ");
997 465 berkley
    self.append("from xml_index where path like ");
998 743 jones
    self.append("'triple/relationship') rel, ");
999 465 berkley
    self.append("(select nodeid, parentnodeid from xml_index where path like ");
1000 743 jones
    self.append("'triple/object') o, ");
1001 465 berkley
    self.append("xml_nodes x, xml_nodes y, xml_nodes z ");
1002
    self.append("where s.parentnodeid = rel.parentnodeid ");
1003
    self.append("and rel.parentnodeid = o.parentnodeid ");
1004 899 berkley
    self.append("and x.parentnodeid in (rel.nodeid) ");
1005
    self.append("and y.parentnodeid in (o.nodeid) ");
1006
    self.append("and z.parentnodeid in (s.nodeid) ");
1007 465 berkley
    self.append("and (z.nodedata like '");
1008
    self.append(subDocidURL);
1009
    self.append("' or y.nodedata like '");
1010
    self.append(objDocidURL);
1011
    self.append("')");
1012
    return self.toString();
1013
  }
1014
1015
  public static String printGetDocByDoctypeSQL(String docid)
1016
  {
1017
    StringBuffer self = new StringBuffer();
1018
1019 692 bojilova
    self.append("SELECT docid,docname,doctype,");
1020 465 berkley
    self.append("date_created, date_updated ");
1021
    self.append("FROM xml_documents WHERE docid IN (");
1022
    self.append(docid).append(")");
1023
    return self.toString();
1024
  }
1025
1026
  /**
1027 172 jones
   * create a String description of the query that this instance represents.
1028
   * This should become a way to get the XML serialization of the query.
1029
   */
1030 159 jones
  public String toString() {
1031 692 bojilova
    return "meta_file_id=" + meta_file_id + "\n" + query;
1032
//DOCTITLE attr cleared from the db
1033
//    return "meta_file_id=" + meta_file_id + "\n" +
1034
//           "querytitle=" + querytitle + "\n" + query;
1035 159 jones
  }
1036 1354 tao
1037
  /* A method to get rid of attribute part in path expression*/
1038
  public static String newPathExpressionWithOutAttribute(String pathExpression)
1039
  {
1040
      if (pathExpression == null)
1041
      {
1042
        return null;
1043
      }
1044
      int index = pathExpression.lastIndexOf(ATTRIBUTESYMBOL);
1045
      String newExpression = null;
1046
      if (index != 1)
1047
      {
1048
        newExpression=pathExpression.substring(0, index-1);
1049
      }
1050 1837 tao
      MetaCatUtil.debugMessage("The path expression without attributes: " +
1051 1354 tao
                               newExpression, 30);
1052
      return newExpression;
1053
  }
1054
1055
  /* A method to get attribute name from path */
1056
  public static String getAttributeName(String path)
1057
  {
1058
      if (path == null)
1059
      {
1060
        return null;
1061
      }
1062
      int index = path.lastIndexOf(ATTRIBUTESYMBOL);
1063
      int size = path.length();
1064
      String attributeName = null;
1065
       if (index != 1)
1066
      {
1067
        attributeName = path.substring(index+1, size);
1068
      }
1069 1837 tao
      MetaCatUtil.debugMessage("The attirbute name from path: " +
1070 1354 tao
                               attributeName, 30);
1071
      return attributeName;
1072
  }
1073 159 jones
1074 158 jones
1075 155 jones
}