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