Project

General

Profile

1 155 jones
/**
2 203 jones
 *  '$RCSfile$'
3 2093 tao
 *    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 203 jones
 *             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 155 jones
 *
11 203 jones
 *   '$Author$'
12
 *     '$Date$'
13
 * '$Revision$'
14 669 jones
 *
15
 * This program is free software; you can redistribute it and/or modify
16
 * it under the terms of the GNU General Public License as published by
17
 * the Free Software Foundation; either version 2 of the License, or
18
 * (at your option) any later version.
19
 *
20
 * This program is distributed in the hope that it will be useful,
21
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23
 * GNU General Public License for more details.
24
 *
25
 * You should have received a copy of the GNU General Public License
26
 * along with this program; if not, write to the Free Software
27
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
28 155 jones
 */
29
30
package edu.ucsb.nceas.metacat;
31
32 2067 jones
import java.io.IOException;
33
import java.io.Reader;
34
import java.io.StringReader;
35
import java.util.Enumeration;
36 1354 tao
import java.util.Hashtable;
37 155 jones
import java.util.Stack;
38 158 jones
import java.util.Vector;
39 155 jones
40 2067 jones
import edu.ucsb.nceas.dbadapter.AbstractDatabase;
41
42 2663 sgarg
import org.apache.log4j.Logger;
43 185 jones
import org.xml.sax.Attributes;
44 158 jones
import org.xml.sax.InputSource;
45
import org.xml.sax.SAXException;
46 185 jones
import org.xml.sax.XMLReader;
47 2067 jones
import org.xml.sax.helpers.DefaultHandler;
48 185 jones
import org.xml.sax.helpers.XMLReaderFactory;
49 2419 sgarg
import java.util.Iterator;
50 155 jones
51 402 berkley
/**
52 2067 jones
 * A Class that represents a structured query, and can be constructed from an
53
 * XML serialization conforming to
54 2093 tao
 *
55 2067 jones
 * @see pathquery.dtd. The printSQL() method can be used to print a SQL
56
 *      serialization of the query.
57 155 jones
 */
58 2067 jones
public class QuerySpecification extends DefaultHandler
59
{
60 1832 tao
61 2067 jones
    /** flag determining whether extended query terms are present */
62
    private boolean containsExtendedSQL = false;
63 158 jones
64 3235 sledge
    /** flag determining whether predicates are present */
65
    private boolean containsPredicates = false;
66
67 2067 jones
    /** Identifier for this query document */
68
    private String meta_file_id;
69 158 jones
70 2067 jones
    /** Title of this query */
71
    private String queryTitle;
72
73
    /** List of document types to be returned using package back tracing */
74
    private Vector returnDocList;
75
76
    /** List of document types to be searched */
77
    private Vector filterDocList;
78
79
    /** List of fields to be returned in result set */
80
    private Vector returnFieldList;
81
82
    /** List of users owning documents to be searched */
83
    private Vector ownerList;
84
85
    /** The root query group that contains the recursive query constraints */
86
    private QueryGroup query = null;
87
88
    // Query data structures used temporarily during XML parsing
89
    private Stack elementStack;
90
91
    private Stack queryStack;
92
93
    private String currentValue;
94
95
    private String currentPathexpr;
96
97
    private String parserName = null;
98
99
    private String accNumberSeparator = null;
100
101
    private static final AbstractDatabase dbAdapter = MetaCatUtil.dbAdapter;
102
103
    private boolean percentageSearch = false;
104
105
    private String userName = null;
106
107
    private static final String PUBLIC = "public";
108
109
    private String[] group = null;
110
111
    public static final String ATTRIBUTESYMBOL = "@";
112
113 3235 sledge
    public static final char PREDICATE_START = '[';
114
115
    public static final char PREDICATE_END = ']';
116
117 2067 jones
    private boolean hasAttributeReturnField = false;
118
119
    private Hashtable attributeReturnList = new Hashtable();
120
121
    private int countAttributeReturnField = 0;
122
123 2093 tao
    private StringBuffer textBuffer = new StringBuffer();
124 3223 tao
125
126 2663 sgarg
    private static Logger logMetacat = Logger.getLogger(QuerySpecification.class);
127
128 2067 jones
    /**
129
     * construct an instance of the QuerySpecification class
130 2093 tao
     *
131 2067 jones
     * @param queryspec
132
     *            the XML representation of the query (should conform to
133
     *            pathquery.dtd) as a Reader
134
     * @param parserName
135
     *            the fully qualified name of a Java Class implementing the
136
     *            org.xml.sax.XMLReader interface
137
     */
138
    public QuerySpecification(Reader queryspec, String parserName,
139
            String accNumberSeparator) throws IOException
140
    {
141
        super();
142
143
        // Initialize the class variables
144
        returnDocList = new Vector();
145
        filterDocList = new Vector();
146
        elementStack = new Stack();
147
        queryStack = new Stack();
148
        returnFieldList = new Vector();
149
        ownerList = new Vector();
150
        this.parserName = parserName;
151
        this.accNumberSeparator = accNumberSeparator;
152
153
        // Initialize the parser and read the queryspec
154
        XMLReader parser = initializeParser();
155
        if (parser == null) {
156
            System.err.println("SAX parser not instantiated properly.");
157
        }
158
        try {
159
            parser.parse(new InputSource(queryspec));
160
        } catch (SAXException e) {
161
            System.err.println("error parsing data in "
162
                    + "QuerySpecification.QuerySpecification");
163
            System.err.println(e.getMessage());
164
        }
165 181 jones
    }
166 2067 jones
167
    /**
168
     * construct an instance of the QuerySpecification class
169 2093 tao
     *
170 2067 jones
     * @param queryspec
171
     *            the XML representation of the query (should conform to
172
     *            pathquery.dtd) as a String
173
     * @param parserName
174
     *            the fully qualified name of a Java Class implementing the
175
     *            org.xml.sax.Parser interface
176
     */
177
    public QuerySpecification(String queryspec, String parserName,
178
            String accNumberSeparator) throws IOException
179
    {
180
        this(new StringReader(queryspec), parserName, accNumberSeparator);
181 155 jones
    }
182
183 2067 jones
    /**
184
     * construct an instance of the QuerySpecification class which don't need
185
     * to parser a xml document
186 2093 tao
     *
187 2067 jones
     * @param accNumberSeparator
188
     *            the separator between doc version
189
     */
190
    public QuerySpecification(String accNumberSeparator) throws IOException
191 2045 tao
    {
192 2067 jones
        // Initialize the class variables
193
        returnDocList = new Vector();
194
        filterDocList = new Vector();
195
        elementStack = new Stack();
196
        queryStack = new Stack();
197
        returnFieldList = new Vector();
198
        ownerList = new Vector();
199
        this.accNumberSeparator = accNumberSeparator;
200 2045 tao
    }
201 2067 jones
202
    /**
203
     * Method to set user name
204 2093 tao
     *
205 2067 jones
     * @param myName
206
     *            the user name
207
     */
208
    public void setUserName(String myName)
209 2045 tao
    {
210 2067 jones
        //to lower case
211
        if (myName != null) {
212
            this.userName = myName.toLowerCase();
213
        } else {
214
            this.userName = myName;
215
        }
216 2045 tao
    }
217 2067 jones
218
    /**
219
     * Method to set user group
220 2093 tao
     *
221 2067 jones
     * @param myGroup
222
     *            the user group
223
     */
224
    public void setGroup(String[] myGroup)
225 1301 tao
    {
226 2067 jones
        this.group = myGroup;
227 1301 tao
    }
228 2067 jones
229
    /**
230
     * Method to indicate this query is a percentage search
231
     */
232
    public boolean isPercentageSearch()
233 1301 tao
    {
234 2067 jones
        return percentageSearch;
235 1301 tao
    }
236 2067 jones
237
    /*
238
     * Method to get owner query. If it is owner it has all permission
239
     */
240
    private String createOwerQuery()
241 1301 tao
    {
242 2067 jones
        String ownerQuery = null;
243 3223 tao
        //if user is public, we don't need to run owner query
244
        if (userName != null && !userName.equalsIgnoreCase(PUBLIC))
245
        {
246
	        ownerQuery = "SELECT docid FROM xml_documents WHERE ";
247
	        if (userName != null && !userName.equals("")) {
248
	            ownerQuery = ownerQuery + "lower(user_owner) ='" + userName + "'";
249
	        }
250 2067 jones
        }
251 2663 sgarg
        logMetacat.info("OwnerQuery: " + ownerQuery);
252 2067 jones
        return ownerQuery;
253
    }
254
255
    /*
256
     * Method to create query for xml_access, this part is to get docid list
257
     * which have a allow rule for a given user
258
     */
259
    private String createAllowRuleQuery()
260 1301 tao
    {
261 2067 jones
        String allowQuery = null;
262
        String allowString = constructAllowString();
263
        allowQuery = "SELECT docid from xml_access WHERE( " + allowString;
264
        allowQuery = allowQuery + ") AND subtreeid IS NULL";
265 2663 sgarg
        logMetacat.info("allow query is: " + allowQuery);
266 2067 jones
        return allowQuery;
267
268 1301 tao
    }
269 2067 jones
270
    /* Method to construct a allow rule string */
271
    private String constructAllowString()
272 1301 tao
    {
273 2067 jones
        String allowQuery = "";
274
        // add allow rule for user name
275
        if (userName != null && !userName.equals("")) {
276
            allowQuery = allowQuery + "(lower(principal_name) = '" + userName
277
                    + "' AND perm_type = 'allow'"
278 2793 sgarg
                    + " AND (permission='4' OR permission='5' "
279
                    + "OR permission='6' OR permission='7'))";
280 2067 jones
        }
281
        // add allow rule for public
282
        allowQuery = allowQuery + "OR (lower(principal_name) = '" + PUBLIC
283
                + "' AND perm_type = 'allow'"
284 2793 sgarg
                + " AND (permission='4' OR permission='5' "
285
                + "OR permission='6' OR permission='7'))";
286 2067 jones
287
        // add allow rule for group
288
        if (group != null) {
289
            for (int i = 0; i < group.length; i++) {
290
                String groupUint = group[i];
291
                if (groupUint != null && !groupUint.equals("")) {
292
                    groupUint = groupUint.toLowerCase();
293
                    allowQuery = allowQuery + " OR (lower(principal_name) = '"
294
                            + groupUint + "' AND perm_type = 'allow'"
295 2793 sgarg
                	    + " AND (permission='4' OR permission='5' "
296
                            + "OR permission='6' OR permission='7'))";
297 2067 jones
                }//if
298
            }//for
299 1301 tao
        }//if
300 2663 sgarg
        logMetacat.info("allow string is: " + allowQuery);
301 2067 jones
        return allowQuery;
302
    }
303 155 jones
304 2067 jones
    /*
305
     * Method to create query for xml_access, this part is to get docid list
306
     * which have a deny rule and perm_order is allowFirst for a given user.
307
     * This means the user will be denied to read
308
     */
309
    private String createDenyRuleQuery()
310
    {
311
        String denyQuery = null;
312
        String denyString = constructDenyString();
313
        denyQuery = "SELECT docid from xml_access WHERE( " + denyString;
314
        denyQuery = denyQuery + ") AND subtreeid IS NULL ";
315 2663 sgarg
        logMetacat.info("denyquery is: " + denyQuery);
316 2067 jones
        return denyQuery;
317 711 jones
318 2067 jones
    }
319 181 jones
320 2067 jones
    /* Construct deny string */
321
    private String constructDenyString()
322 402 berkley
    {
323 2067 jones
        String denyQuery = "";
324
        // add deny rule for user name
325
        if (userName != null && !userName.equals("")) {
326
            denyQuery = denyQuery + "(lower(principal_name) = '" + userName
327
                    + "' AND perm_type = 'deny' "
328
                    + "AND perm_order ='allowFirst'"
329 2793 sgarg
                    + " AND (permission='4' OR permission='5' "
330
                    + "OR permission='6' OR permission='7'))";
331 2067 jones
        }
332
        // add deny rule for public
333
        denyQuery = denyQuery + "OR (lower(principal_name) = '" + PUBLIC
334
                + "' AND perm_type = 'deny' " + "AND perm_order ='allowFirst'"
335 2793 sgarg
                + " AND (permission='4' OR permission='5' "
336
                + "OR permission='6' OR permission='7'))";
337 2067 jones
338
        // add allow rule for group
339
        if (group != null) {
340
            for (int i = 0; i < group.length; i++) {
341
                String groupUint = group[i];
342
                if (groupUint != null && !groupUint.equals("")) {
343
                    groupUint = groupUint.toLowerCase();
344
                    denyQuery = denyQuery + " OR (lower(principal_name) = '"
345
                            + groupUint + "' AND perm_type = 'deny' "
346
                            + "AND perm_order ='allowFirst'"
347 2793 sgarg
                	    + " AND (permission='4' OR permission='5' "
348
                            + "OR permission='6' OR permission='7'))";
349 2067 jones
                }//if
350
            }//for
351
        }//if
352
        return denyQuery;
353 402 berkley
    }
354 2067 jones
355
    /**
356
     * Method to append a access control query to SQL. So in DBQuery class, we
357
     * can get docid from both user specified query and access control query.
358
     * We don't need to checking permission after we get the doclist. It will
359
     * be good to performance
360 2093 tao
     *
361 2067 jones
     */
362
    public String getAccessQuery()
363 402 berkley
    {
364 2067 jones
        String accessQuery = null;
365
        String onwer = createOwerQuery();
366
        String allow = createAllowRuleQuery();
367
        String deny = createDenyRuleQuery();
368 3223 tao
        if (onwer != null)
369
        {
370
          accessQuery = " AND (docid IN(" + onwer + ")";
371
          accessQuery = accessQuery + " OR (docid IN (" + allow + ")"
372 2067 jones
                + " AND docid NOT IN (" + deny + ")))";
373 3223 tao
        }
374
        else
375
        {
376
        	accessQuery = " AND (docid IN (" + allow + ")"
377
                + " AND docid NOT IN (" + deny + "))";
378
        }
379 2663 sgarg
        logMetacat.warn("accessquery is: " + accessQuery);
380 2067 jones
        return accessQuery;
381 402 berkley
    }
382 745 jones
383 2067 jones
    /**
384
     * Returns true if the parsed query contains and extended xml query (i.e.
385
     * there is at least one &lt;returnfield&gt; in the pathquery document)
386
     */
387
    public boolean containsExtendedSQL()
388
    {
389
        if (containsExtendedSQL) {
390
            return true;
391
        } else {
392
            return false;
393
        }
394
    }
395 745 jones
396 2067 jones
    /**
397
     * A method to get if the query has an attribute return field
398
     */
399 2472 cjones
    public boolean containsAttributeReturnField()
400 2067 jones
    {
401
        return hasAttributeReturnField;
402
    }
403 745 jones
404 2067 jones
    /**
405
     * Accessor method to return the identifier of this Query
406
     */
407
    public String getIdentifier()
408
    {
409
        return meta_file_id;
410
    }
411 155 jones
412 2067 jones
    /**
413
     * method to set the identifier of this query
414
     */
415
    public void setIdentifier(String id)
416
    {
417
        this.meta_file_id = id;
418
    }
419 745 jones
420 2067 jones
    /**
421
     * Accessor method to return the title of this Query
422
     */
423
    public String getQueryTitle()
424
    {
425
        return queryTitle;
426
    }
427 745 jones
428 2067 jones
    /**
429
     * method to set the title of this query
430
     */
431
    public void setQueryTitle(String title)
432
    {
433
        this.queryTitle = title;
434
    }
435 745 jones
436 2067 jones
    /**
437
     * Accessor method to return a vector of the return document types as
438
     * defined in the &lt;returndoctype&gt; tag in the pathquery dtd.
439
     */
440
    public Vector getReturnDocList()
441
    {
442
        return this.returnDocList;
443
    }
444 745 jones
445 2067 jones
    /**
446
     * method to set the list of return docs of this query
447
     */
448
    public void setReturnDocList(Vector returnDocList)
449
    {
450
        this.returnDocList = returnDocList;
451
    }
452 745 jones
453 2067 jones
    /**
454
     * Accessor method to return a vector of the filter doc types as defined in
455
     * the &lt;filterdoctype&gt; tag in the pathquery dtd.
456
     */
457
    public Vector getFilterDocList()
458
    {
459
        return this.filterDocList;
460
    }
461 172 jones
462 2067 jones
    /**
463
     * method to set the list of filter docs of this query
464
     */
465
    public void setFilterDocList(Vector filterDocList)
466
    {
467
        this.filterDocList = filterDocList;
468
    }
469 155 jones
470 2067 jones
    /**
471
     * Accessor method to return a vector of the extended return fields as
472
     * defined in the &lt;returnfield&gt; tag in the pathquery dtd.
473
     */
474
    public Vector getReturnFieldList()
475
    {
476
        return this.returnFieldList;
477
    }
478 155 jones
479 2067 jones
    /**
480
     * method to set the list of fields to be returned by this query
481
     */
482
    public void setReturnFieldList(Vector returnFieldList)
483
    {
484
        this.returnFieldList = returnFieldList;
485
    }
486 155 jones
487 2067 jones
    /**
488
     * Accessor method to return a vector of the owner fields as defined in the
489
     * &lt;owner&gt; tag in the pathquery dtd.
490
     */
491
    public Vector getOwnerList()
492
    {
493
        return this.ownerList;
494
    }
495 155 jones
496 2067 jones
    /**
497
     * method to set the list of owners used to constrain this query
498
     */
499
    public void setOwnerList(Vector ownerList)
500
    {
501
        this.ownerList = ownerList;
502 155 jones
    }
503
504 2067 jones
    /**
505
     * get the QueryGroup used to express query constraints
506
     */
507
    public QueryGroup getQueryGroup()
508
    {
509
        return query;
510 158 jones
    }
511 155 jones
512 2067 jones
    /**
513
     * set the querygroup
514
     */
515
    public void setQueryGroup(QueryGroup group)
516
    {
517
        query = group;
518 158 jones
    }
519
520 2067 jones
    /**
521
     * set if this query sepcification has extendQuery(has return doc type or
522
     * not)
523
     */
524
    public void setContainsExtenedSQL(boolean hasExtenedQuery)
525
    {
526
        containsExtendedSQL = hasExtenedQuery;
527
    }
528 158 jones
529 2067 jones
    /**
530
     * Set up the SAX parser for reading the XML serialized query
531
     */
532
    private XMLReader initializeParser()
533
    {
534
        XMLReader parser = null;
535
536
        // Set up the SAX document handlers for parsing
537
        try {
538
539
            // Get an instance of the parser
540
            parser = XMLReaderFactory.createXMLReader(parserName);
541
542
            // Set the ContentHandler to this instance
543
            parser.setContentHandler(this);
544
545
            // Set the error Handler to this instance
546
            parser.setErrorHandler(this);
547
548
        } catch (Exception e) {
549
            System.err.println("Error in QuerySpcecification.initializeParser "
550
                    + e.toString());
551
        }
552
553
        return parser;
554 1833 tao
    }
555 170 jones
556 2067 jones
    /**
557
     * callback method used by the SAX Parser when the start tag of an element
558
     * is detected. Used in this context to parse and store the query
559
     * information in class variables.
560
     */
561
    public void startElement(String uri, String localName, String qName,
562
            Attributes atts) throws SAXException
563
    {
564
        BasicNode currentNode = new BasicNode(localName);
565
        // add attributes to BasicNode here
566
        if (atts != null) {
567
            int len = atts.getLength();
568
            for (int i = 0; i < len; i++) {
569
                currentNode
570
                        .setAttribute(atts.getLocalName(i), atts.getValue(i));
571
            }
572
        }
573 170 jones
574 2067 jones
        elementStack.push(currentNode);
575
        if (currentNode.getTagName().equals("querygroup")) {
576
            QueryGroup currentGroup = new QueryGroup(currentNode
577
                    .getAttribute("operator"));
578
            if (query == null) {
579
                query = currentGroup;
580
            } else {
581
                QueryGroup parentGroup = (QueryGroup) queryStack.peek();
582
                parentGroup.addChild(currentGroup);
583
            }
584
            queryStack.push(currentGroup);
585
        }
586
    }
587 172 jones
588 2067 jones
    /**
589
     * callback method used by the SAX Parser when the end tag of an element is
590
     * detected. Used in this context to parse and store the query information
591
     * in class variables.
592
     */
593
    public void endElement(String uri, String localName, String qName)
594
            throws SAXException
595
    {
596
        BasicNode leaving = (BasicNode) elementStack.pop();
597
        if (leaving.getTagName().equals("queryterm")) {
598
            boolean isCaseSensitive = (new Boolean(leaving
599
                    .getAttribute("casesensitive"))).booleanValue();
600
            QueryTerm currentTerm = null;
601
            if (currentPathexpr == null) {
602
                currentTerm = new QueryTerm(isCaseSensitive, leaving
603
                        .getAttribute("searchmode"), currentValue);
604
            } else {
605
                currentTerm = new QueryTerm(isCaseSensitive, leaving
606
                        .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 2093 tao
        } else if (leaving.getTagName().equals("meta_file_id")) {
616
              meta_file_id = textBuffer.toString().trim();
617
        } else if (leaving.getTagName().equals("querytitle")) {
618
              queryTitle = textBuffer.toString().trim();
619
        } else if (leaving.getTagName().equals("value")) {
620
              currentValue = textBuffer.toString().trim();
621
        } else if (leaving.getTagName().equals("pathexpr")) {
622
              currentPathexpr = textBuffer.toString().trim();
623
        } else if (leaving.getTagName().equals("returndoctype")) {
624
              returnDocList.add(textBuffer.toString().trim());
625
        } else if (leaving.getTagName().equals("filterdoctype")) {
626
              filterDocList.add(textBuffer.toString().trim());
627
        } else if (leaving.getTagName().equals("returnfield")) {
628
              handleReturnField(textBuffer.toString().trim());
629
        } else if (leaving.getTagName().equals("filterdoctype")) {
630
              filterDocList.add(textBuffer.toString().trim());
631
        } else if (leaving.getTagName().equals("owner")) {
632
              ownerList.add(textBuffer.toString().trim());
633 172 jones
        }
634 2093 tao
635
        //rest textBuffer
636
        textBuffer = new StringBuffer();
637
638 172 jones
    }
639 743 jones
640 2067 jones
    /**
641
     * callback method used by the SAX Parser when the text sequences of an xml
642
     * stream are detected. Used in this context to parse and store the query
643
     * information in class variables.
644
     */
645
    public void characters(char ch[], int start, int length)
646
    {
647 2093 tao
      // buffer all text nodes for same element. This is for text was splited
648
      // into different nodes
649
      textBuffer.append(new String(ch, start, length));
650 2067 jones
651
    }
652
653
    /**
654
     * Method to transfer string to return field
655
     */
656 3235 sledge
    /* public void handleReturnField(String inputString)
657 2067 jones
    {
658
        // make sure if return fields has an attribute or not
659
        if (inputString.indexOf(ATTRIBUTESYMBOL) == -1) {
660
            // no attribute value will be returned
661 2663 sgarg
            logMetacat.info("QuerySpecification.handleReturnField(): " );
662
            logMetacat.info("  there are no attributes in the XPATH statement" );
663 2067 jones
            returnFieldList.add(inputString);
664
            containsExtendedSQL = true;
665 535 jones
        } else {
666 2474 sgarg
667 2467 cjones
          if ( inputString.startsWith(ATTRIBUTESYMBOL) ) {
668 2474 sgarg
669 2467 cjones
            // case where the return field is solely an attribute
670 2663 sgarg
            logMetacat.info("QuerySpecification.handleReturnField(): " );
671
            logMetacat.info("  there are *only* attributes in the XPATH statement" );
672 2472 cjones
            String returnPath = newPathExpressionWithOutAttribute(inputString);
673
            String attributeName = getAttributeName(inputString);
674
            Vector pathInfo = new Vector();
675
            // the vector has the information about return path and
676
            // attributename
677
            pathInfo.addElement(returnPath);
678
            pathInfo.addElement(attributeName);
679
            // put the vector into a hash table. The reseaon why don't put
680
            // return path or attributename as a key is because they are not
681
            // unique
682
            attributeReturnList.put(new Integer(countAttributeReturnField),
683
                    pathInfo);
684
            countAttributeReturnField++;
685
            hasAttributeReturnField = true;
686 2467 cjones
            containsExtendedSQL = true;
687
          } else {
688 2067 jones
            // has a attribute return field
689
            // divied the return filed into two parts, one is path and the
690
            // other is attribue name
691 2663 sgarg
            logMetacat.info("QuerySpecification.handleReturnField: " );
692
            logMetacat.info("  there are both attributes and elements" );
693
            logMetacat.info("  in the XPATH statement" );
694 2067 jones
            String returnPath = newPathExpressionWithOutAttribute(inputString);
695
            String attributeName = getAttributeName(inputString);
696
            Vector pathInfo = new Vector();
697
            // the vector has the information about return path and
698
            // attributename
699
            pathInfo.addElement(returnPath);
700
            pathInfo.addElement(attributeName);
701
            // put the vector into a hash table. The reseaon why don't put
702
            // return path or attributename as a key is because they are not
703
            // unique
704
            attributeReturnList.put(new Integer(countAttributeReturnField),
705
                    pathInfo);
706
            countAttributeReturnField++;
707
            hasAttributeReturnField = true;
708
            containsExtendedSQL = true;
709 2467 cjones
          }
710 535 jones
        }
711
    }
712 3235 sledge
     */
713
    public void handleReturnField(String inputString)
714
    {
715
        int attributePos = inputString.indexOf(ATTRIBUTESYMBOL);
716
        int predicateStart = -1;
717
        int predicateEnd;
718
        boolean hasPredicate = false;
719 535 jones
720 3235 sledge
        while (true)
721
        {
722
            predicateStart = inputString.indexOf(PREDICATE_START, predicateStart + 1);
723
724
            if (attributePos == -1)
725
                break;
726
727
            if (predicateStart == -1)
728
                break;
729
730
            hasPredicate = true;
731
732
            if (attributePos < predicateStart)
733
                break;
734
735
            predicateEnd = inputString.indexOf(PREDICATE_END, predicateStart);
736
737
            if (predicateEnd == -1)
738
            {
739
                logMetacat.warn("handleReturnField(): ");
740
                logMetacat.warn("    Invalid path: " + inputString);
741
                return;
742
            }
743
744
            while (attributePos < predicateEnd)
745
            {
746
                attributePos = inputString.indexOf(ATTRIBUTESYMBOL, attributePos + 1);
747
748
                if (attributePos == -1)
749
                    break;
750
            }
751
        }
752
753
        if (hasPredicate)
754
            containsPredicates = true;
755
756
        containsExtendedSQL = true;
757
758
        // make sure if return fields has an attribute or not
759
        if (attributePos == -1)
760
        {
761
            // no attribute value will be returned
762
            logMetacat.info("QuerySpecification.handleReturnField(): " );
763
            logMetacat.info("  there are no attributes in the XPATH statement" );
764
            returnFieldList.add(inputString);
765
            return;
766
        }
767
768
        // case where the return field is solely an attribute
769
        logMetacat.info("QuerySpecification.handleReturnField(): " );
770
        logMetacat.info("  Found an attribute in the XPATH statement." );
771
        String returnPath = inputString.substring(0,
772
                attributePos == 0 ? attributePos : attributePos - 1);
773
        String attributeName = inputString.substring(attributePos + 1).trim();
774
        Vector pathInfo = new Vector();
775
        // the vector has the information about return path and
776
        // attributename
777
        pathInfo.addElement(returnPath);
778
        pathInfo.addElement(attributeName);
779
        // put the vector into a hash table. The reseaon why don't put
780
        // return path or attributename as a key is because they are not
781
        // unique
782
        attributeReturnList.put(new Integer(countAttributeReturnField),
783
                pathInfo);
784
        countAttributeReturnField++;
785
        hasAttributeReturnField = true;
786
    }
787
788 2067 jones
    /**
789
     * create a SQL serialization of the query that this instance represents
790
     */
791
    public String printSQL(boolean useXMLIndex)
792
    {
793
794
        StringBuffer self = new StringBuffer();
795 2366 sgarg
        StringBuffer queryString = new StringBuffer();
796 2067 jones
797 2366 sgarg
        queryString.append("SELECT docid,docname,doctype,");
798
        queryString.append("date_created, date_updated, rev ");
799
        queryString.append("FROM xml_documents WHERE");
800 2067 jones
801 2366 sgarg
        // Get the query from the QueryGroup and check
802
        // if no query has been returned
803
        String queryFromQueryGroup = query.printSQL(useXMLIndex);
804 2677 sgarg
        logMetacat.info("Query from query in QuerySpec.printSQL: "
805
        		+ queryFromQueryGroup);
806
807 2373 sgarg
        if(!queryFromQueryGroup.trim().equals("")){
808 2366 sgarg
            self.append(" docid IN (");
809 2373 sgarg
            self.append(queryFromQueryGroup);
810 2366 sgarg
            self.append(") ");
811
        }
812 2067 jones
813
        // Add SQL to filter for doctypes requested in the query
814
        // This is an implicit OR for the list of doctypes. Only doctypes in
815
        // this
816
        // list will be searched if the tag is present
817
        if (!filterDocList.isEmpty()) {
818
            boolean firstdoctype = true;
819 2366 sgarg
            boolean emptyString = true;
820
821
            if(!self.toString().equals("")){
822
                self.append(" AND (");
823
                emptyString = false;
824
            }
825
826 2067 jones
            Enumeration en = filterDocList.elements();
827
            while (en.hasMoreElements()) {
828
                String currentDoctype = (String) en.nextElement();
829
                if (firstdoctype) {
830
                    firstdoctype = false;
831
                    self.append(" doctype = '" + currentDoctype + "'");
832
                } else {
833
                    self.append(" OR doctype = '" + currentDoctype + "'");
834
                }
835
            }
836 2366 sgarg
837
            if(!emptyString){
838
                self.append(") ");
839
            }
840 535 jones
        }
841 2067 jones
842
        // Add SQL to filter for owners requested in the query
843
        // This is an implicit OR for the list of owners
844
        if (!ownerList.isEmpty()) {
845
            boolean first = true;
846 2366 sgarg
            boolean emptyString = true;
847
848
            if(!self.toString().equals("")){
849
                self.append(" AND (");
850
                emptyString = false;
851
            }
852
853 2067 jones
            Enumeration en = ownerList.elements();
854
            while (en.hasMoreElements()) {
855
                String current = (String) en.nextElement();
856
                if (current != null) {
857
                    current = current.toLowerCase();
858
                }
859
                if (first) {
860
                    first = false;
861
                    self.append(" lower(user_owner) = '" + current + "'");
862
                } else {
863
                    self.append(" OR lower(user_owner) = '" + current + "'");
864
                }
865
            }
866 2366 sgarg
867
            if(!emptyString){
868
                self.append(") ");
869
            }
870 2067 jones
        }
871
872
        // if there is only one percentage search item, this query is a
873
        // percentage
874
        // search query
875 2663 sgarg
        logMetacat.info("percentage number: "
876
                + query.getPercentageSymbolCount());
877 2067 jones
        if (query.getPercentageSymbolCount() == 1) {
878 2663 sgarg
            logMetacat.info("It is a percentage search");
879 2067 jones
            percentageSearch = true;
880
        }
881
882 2366 sgarg
        queryString.append(self.toString());
883
        return queryString.toString();
884 535 jones
    }
885 2067 jones
886
    /**
887
     * This sql command will selecet startnodeid and endnodeid that user can
888
     * NOT access
889
     */
890
    public String printAccessControlSQLForReturnField(String doclist)
891 1350 tao
    {
892 2067 jones
        StringBuffer sql = new StringBuffer();
893
        String allowString = constructAllowString();
894
        String denyString = constructDenyString();
895
        sql.append("SELECT distinct startnodeid, endnodeid from xml_access ");
896
        sql.append("WHERE docid in (");
897
        sql.append(doclist);
898
        sql.append(") AND startnodeid IS NOT NULL AND ");
899
        sql.append("(");
900
        sql.append("(");
901 2068 jones
        sql
902
                .append("startnodeid NOT IN (SELECT startnodeid from xml_access, xml_documents ");
903 2067 jones
        sql.append(" WHERE xml_access.docid = xml_documents.docid");
904
        sql.append(" AND lower(xml_documents.user_owner) ='");
905
        sql.append(userName);
906
        sql.append("' AND xml_access.startnodeid IS NOT NULL)");
907
        sql.append(")");
908
        sql.append(" AND ");
909
        sql.append("(");
910 2068 jones
        sql
911
                .append("(startnodeid NOT IN (SELECT startnodeid from xml_access where( ");
912 2067 jones
        sql.append(allowString);
913
        sql.append(") AND (startnodeid IS NOT NULL))");
914
        sql.append(")");
915 2068 jones
        sql
916
                .append(" OR (startnodeid IN (SELECT startnodeid from xml_access where( ");
917 2067 jones
        sql.append(denyString);
918
        sql.append(") AND (startnodeid IS NOT NULL))");
919
        sql.append(")");
920
        sql.append(")");
921
        sql.append(")");
922 2663 sgarg
        logMetacat.info("accessControlSQLForReturnField: "
923
                + sql.toString());
924 2067 jones
        return sql.toString();
925 1350 tao
    }
926 2067 jones
927
    /**
928
     * This method prints sql based upon the &lt;returnfield&gt; tag in the
929 2069 jones
     * pathquery document. This allows for customization of the returned fields.
930 2093 tao
     * If the boolean useXMLIndex paramter is false, it uses a recursive query on
931
     * xml_nodes to find the fields to be included by their path expression, and
932 2069 jones
     * avoids the use of the xml_index table.
933 2093 tao
     *
934 2073 jones
     * @param doclist the list of document ids to search
935 2093 tao
     * @param unaccessableNodePair the node pairs (start id and end id) which
936 2073 jones
     *            this user should not access
937 2093 tao
     * @param useXMLIndex a boolean flag indicating whether to search using
938 2073 jones
     *            xml_index
939 2069 jones
     */
940
    public String printExtendedSQL(String doclist,
941
            Hashtable unaccessableNodePair, boolean useXMLIndex)
942
    {
943 3235 sledge
        if (useXMLIndex && !containsPredicates)
944
        {
945 2069 jones
            return printExtendedSQL(doclist, unaccessableNodePair);
946 3235 sledge
        }
947
        else
948
        {
949 2069 jones
            StringBuffer self = new StringBuffer();
950
951
            boolean firstfield = true;
952
            //put the returnfields into the query
953
            //the for loop allows for multiple fields
954 3235 sledge
            for (int i = 0; i < returnFieldList.size(); i++)
955
            {
956
                if (firstfield)
957
                {
958 2069 jones
                    firstfield = false;
959 3235 sledge
                }
960
                else
961
                {
962 2093 tao
                    self.append(" UNION ");
963 2069 jones
                }
964
                String path  = (String) returnFieldList.elementAt(i);
965
                self.append("select xml_nodes.docid, ");
966 3235 sledge
                self.append("'"+ path.replaceAll("'", "''") + "' as path, xml_nodes.nodedata, ");
967 2069 jones
                self.append("xml_nodes.parentnodeid ");
968
                self.append("from xml_nodes, xml_documents ");
969
                self.append("where parentnodeid IN ");
970
                self.append(QueryTerm.useNestedStatements(path));
971 2093 tao
972 2069 jones
                self.append(" AND xml_nodes.docid in (");
973
                self.append(doclist);
974 2073 jones
                self.append(") AND xml_nodes.nodetype = 'TEXT'");
975 2069 jones
                self.append(" AND xml_nodes.rootnodeid = xml_documents.rootnodeid");
976 2093 tao
977 2073 jones
                addAccessRestrictionSQL(unaccessableNodePair, self);
978 2069 jones
            }
979
980
            return self.toString();
981
        }
982
    }
983 2093 tao
984 2069 jones
    /**
985
     * This method prints sql based upon the &lt;returnfield&gt; tag in the
986
     * pathquery document. This allows for customization of the returned fields.
987
     * It uses the xml_index table and so assumes that this table has been
988
     * built.
989 2093 tao
     *
990 2073 jones
     * @param doclist the list of document ids to search
991 2093 tao
     * @param unaccessableNodePair the node pairs (start id and end id)
992 2073 jones
     *            which this user should not access
993 2067 jones
     */
994 2093 tao
    public String printExtendedSQL(String doclist,
995 2067 jones
            Hashtable unaccessableNodePair)
996 402 berkley
    {
997 2663 sgarg
        logMetacat.info("querySpecification.printExtendedSQL called\n");
998 2067 jones
        StringBuffer self = new StringBuffer();
999 2472 cjones
1000 2523 sgarg
        boolean usePathIndex = true;
1001 2434 sgarg
1002 2523 sgarg
        // test if the are elements in the return fields
1003
        if ( returnFieldList.size() == 0 ) {
1004
            return null;
1005
        }
1006 2067 jones
1007 2523 sgarg
        for (int i = 0; i < returnFieldList.size(); i++) {
1008
            if(!MetaCatUtil.pathsForIndexing.contains
1009
               (returnFieldList.elementAt(i))){
1010
                usePathIndex = false;
1011
                break;
1012
            }
1013
        }
1014 2073 jones
1015 2523 sgarg
        if(usePathIndex){
1016
            self.append("select docid, path, nodedata, parentnodeid ");
1017
            self.append("from xml_path_index where (path like '");
1018
1019
            boolean firstfield = true;
1020
            //put the returnfields into the query
1021
            //the for loop allows for multiple fields
1022
            for (int i = 0; i < returnFieldList.size(); i++) {
1023
                if (firstfield) {
1024
                    firstfield = false;
1025
                    self.append( (String) returnFieldList.elementAt(i));
1026
                    self.append("' ");
1027
                }
1028
                else {
1029
                    self.append("or path like '");
1030
                    self.append( (String) returnFieldList.elementAt(i));
1031
                    self.append("' ");
1032
                }
1033
            }
1034
            self.append(") AND docid in (");
1035
            self.append(doclist);
1036
            self.append(")");
1037
1038
        } else {
1039
            self.append("select xml_nodes.docid, xml_index.path, xml_nodes.nodedata,  ");
1040
            self.append("xml_nodes.parentnodeid ");
1041
            self.append("from xml_index, xml_nodes where xml_index.nodeid=");
1042
            self.append("xml_nodes.parentnodeid and (xml_index.path like '");
1043
1044
            boolean firstfield = true;
1045
            //put the returnfields into the query
1046
            //the for loop allows for multiple fields
1047
            for (int i = 0; i < returnFieldList.size(); i++) {
1048
                if (firstfield) {
1049
                    firstfield = false;
1050
                    self.append((String) returnFieldList.elementAt(i));
1051
                    self.append("' ");
1052
                } else {
1053
                    self.append("or xml_index.path like '");
1054
                    self.append((String) returnFieldList.elementAt(i));
1055
                    self.append("' ");
1056
                }
1057
            }
1058
            self.append(") AND xml_nodes.docid in (");
1059
            self.append(doclist);
1060
            self.append(") AND xml_nodes.nodetype = 'TEXT'");
1061
1062
        }
1063
1064
        addAccessRestrictionSQL(unaccessableNodePair, self);
1065
1066
        return self.toString();
1067 2073 jones
    }
1068
1069 2419 sgarg
1070 2073 jones
    /**
1071 2419 sgarg
     * Method to return a String generated after sorting the returnFieldList
1072
     * Vector
1073
     */
1074
    public String getSortedReturnFieldString(){
1075
        String returnFields = "";
1076
1077
        // Create a temporary vector and copy returnFieldList into it
1078
        Vector tempVector = new Vector();
1079 2464 sgarg
1080 2419 sgarg
        Iterator it = returnFieldList.iterator();
1081
        while(it.hasNext()){
1082
            tempVector.add(it.next());
1083
        }
1084
1085 2464 sgarg
        Enumeration attEnum = attributeReturnList.elements();
1086
        while(attEnum.hasMoreElements()){
1087
            Iterator tempIt = ((Vector)attEnum.nextElement()).iterator();
1088
	    String rfield = "";
1089
            if(tempIt.hasNext()){
1090
		String element = (String)tempIt.next();
1091 2474 sgarg
		if(element != null) {
1092
		    rfield +=element;
1093 2464 sgarg
		}
1094
	    }
1095
            if(tempIt.hasNext()){
1096
		String attribute = (String)tempIt.next();
1097 2474 sgarg
		if(attribute != null) {
1098
  		    rfield = rfield + "@" + attribute;
1099 2464 sgarg
                }
1100
	    }
1101
            tempVector.add(rfield);
1102
        }
1103
1104 2419 sgarg
        // Sort the temporary vector
1105
        java.util.Collections.sort(tempVector);
1106
1107
        // Generate the string and return it
1108
        it = tempVector.iterator();
1109
        while(it.hasNext()){
1110
            returnFields = returnFields + it.next() + "|";
1111
        }
1112
        return returnFields;
1113
    }
1114
1115
1116
    /**
1117 2073 jones
     * Create the SQl necessary to restrict access to allowed nodes.  This is
1118
     * accomplished by restricting the nodes that are returned to include
1119
     * only those whose IDs fall outside of a set of start/stop pairs of
1120
     * nodeid values.  These pairs are passed in as a hash, with the key
1121
     * containing the start nodeid and the value containing the end nodeid.
1122
     * Any nodes between these start and end nodeid values will be excluded
1123
     * from the results.
1124 2093 tao
     *
1125 2073 jones
     * @param unaccessableNodePair hash of start/end nodeid pairs to restrict
1126 2093 tao
     * @param self a stringbuffer to which the genrated SQL is appended
1127 2073 jones
     */
1128 2093 tao
    private void addAccessRestrictionSQL(Hashtable unaccessableNodePair,
1129 2073 jones
            StringBuffer self)
1130
    {
1131 2067 jones
        // add control part for extended query
1132
        Enumeration en = unaccessableNodePair.keys();
1133
1134
        while (en.hasMoreElements()) {
1135
            // Get control pairs in object
1136
            Long startNodeIdObject = (Long) en.nextElement();
1137
            Long endNodeIdObject = (Long) unaccessableNodePair
1138
                    .get(startNodeIdObject);
1139
            // change it to long
1140
            long startNodeId = startNodeIdObject.longValue();
1141
            long endNodeId = endNodeIdObject.longValue();
1142
            // add into query
1143 2073 jones
            self.append(" AND ( xml_nodes.nodeid < ");
1144 2067 jones
            self.append(startNodeId);
1145
            self.append(" OR xml_nodes.nodeid > ");
1146
            self.append(endNodeId);
1147
            self.append(")");
1148
        }
1149 402 berkley
    }
1150 2074 jones
1151 2067 jones
    /**
1152 2074 jones
     * This method prints sql that finds the values of attributes in the xml
1153
     * documents based upon the whether the returnfield tag in the pathquery
1154 2093 tao
     * document has an attribute symbol (@). This allows for customization of
1155 2074 jones
     * the returned fields.
1156 2093 tao
     *
1157 2074 jones
     * @param doclist the list of document ids to search
1158 2093 tao
     * @param useXMLIndex a boolean flag indicating whether to search using
1159 2074 jones
     *            xml_index
1160 2067 jones
     */
1161 2074 jones
    public String printAttributeQuery(String doclist, boolean useXMLIndex)
1162
    {
1163 3235 sledge
        if (useXMLIndex && !containsPredicates) {
1164 2074 jones
            return printAttributeQuery(doclist);
1165
        } else {
1166
            StringBuffer self = new StringBuffer();
1167
            boolean firstfield = true;
1168
            //put the returnfields attributes into the query
1169
            //the for loop allows for multiple fields and attributes
1170
            Enumeration returnAttributes = attributeReturnList.elements();
1171
            while (returnAttributes.hasMoreElements()) {
1172
                Vector currentVector = (Vector) returnAttributes.nextElement();
1173
                String returnPath = (String) currentVector.elementAt(0);
1174
                String attributeName = (String) currentVector.elementAt(1);
1175
                if (firstfield) {
1176
                    firstfield = false;
1177
                } else {
1178 2093 tao
                    self.append(" UNION ");
1179 2074 jones
                }
1180
                self.append("select xml_nodes.docid, '");
1181 3235 sledge
                self.append(returnPath.replaceAll("'", "''"));
1182 2074 jones
                self.append("' as path, xml_nodes.nodedata, xml_nodes.nodename ");
1183
                self.append("from xml_nodes, xml_documents ");
1184
                self.append("where parentnodeid IN ");
1185
                self.append(QueryTerm.useNestedStatements(returnPath));
1186
                self.append(" AND xml_nodes.nodename like '");
1187
                self.append(attributeName);
1188
                self.append("' AND xml_nodes.docid in (");
1189
                self.append(doclist);
1190
                self.append(") AND xml_nodes.nodetype = 'ATTRIBUTE'");
1191 2078 jones
                self.append(" AND xml_nodes.rootnodeid = xml_documents.rootnodeid");
1192 2074 jones
            }
1193 2093 tao
1194 2663 sgarg
            logMetacat.warn("Attribute query: " + self.toString());
1195 2074 jones
1196 2093 tao
            return self.toString();
1197 2074 jones
        }
1198
    }
1199
1200
    /**
1201
     * This method prints sql that finds the values of attributes in the xml
1202
     * documents based upon the whether the returnfield tag in the pathquery
1203 2093 tao
     * document has an attribute symbol (@). This allows for customization of
1204 2074 jones
     * the returned fields.
1205 2093 tao
     *
1206 2074 jones
     * @param doclist the list of document ids to search
1207
     */
1208 2067 jones
    public String printAttributeQuery(String doclist)
1209 1449 tao
    {
1210 2067 jones
        StringBuffer self = new StringBuffer();
1211
        self.append("select xml_nodes.docid, xml_index.path, ");
1212
        self.append("xml_nodes.nodedata, xml_nodes.nodename ");
1213
        self.append("from xml_index, xml_nodes where xml_index.nodeid=");
1214
        self.append("xml_nodes.parentnodeid and (");
1215
        boolean firstfield = true;
1216
        //put the returnfields attributes into the query
1217
        //the for loop allows for multiple fields and attributes
1218
        Enumeration returnAttributes = attributeReturnList.elements();
1219
        while (returnAttributes.hasMoreElements()) {
1220
            Vector currentVector = (Vector) returnAttributes.nextElement();
1221
            String returnPath = (String) currentVector.elementAt(0);
1222
            String attributeName = (String) currentVector.elementAt(1);
1223
            if (firstfield) {
1224
                firstfield = false;
1225 2466 sgarg
                self.append("( ");
1226
                if(returnPath != null){
1227
                    self.append("xml_index.path like '");
1228
                    self.append(returnPath);
1229
                    self.append("' AND ");
1230 2472 cjones
                }else {
1231 2663 sgarg
                  logMetacat.info("QuerySpecification.printAttributeQuery: "
1232
                   + "returnPath is: " + returnPath);
1233 2466 sgarg
                }
1234
                self.append("xml_nodes.nodename like '");
1235 2067 jones
                self.append(attributeName);
1236
                self.append("') ");
1237
            } else {
1238 2466 sgarg
                self.append(" or (");
1239
                if(returnPath != null){
1240
                    self.append("xml_index.path like '");
1241
                    self.append(returnPath);
1242
                    self.append("' AND ");
1243 2472 cjones
                }else {
1244 2663 sgarg
                  logMetacat.info("QuerySpecification.printAttributeQuery: "
1245
                   + "returnPath is null: " + returnPath);
1246 2466 sgarg
                }
1247
                self.append("xml_nodes.nodename like '");
1248 2067 jones
                self.append(attributeName);
1249
                self.append("') ");
1250
            }
1251
        }
1252
        self.append(") AND xml_nodes.docid in (");
1253
        self.append(doclist);
1254 2074 jones
        self.append(") AND xml_nodes.nodetype = 'ATTRIBUTE'");
1255 2663 sgarg
        logMetacat.warn("Attribute query: " + self.toString());
1256 2067 jones
1257
        return self.toString();
1258 1449 tao
    }
1259 405 berkley
1260 2067 jones
    public static String printRelationSQL(String docid)
1261 1354 tao
    {
1262 2067 jones
        StringBuffer self = new StringBuffer();
1263
        self.append("select subject, relationship, object, subdoctype, ");
1264
        self.append("objdoctype from xml_relation ");
1265
        self.append("where docid like '").append(docid).append("'");
1266
        return self.toString();
1267 1354 tao
    }
1268 2066 jones
1269 2067 jones
    public static String printGetDocByDoctypeSQL(String docid)
1270
    {
1271
        StringBuffer self = new StringBuffer();
1272 465 berkley
1273 2067 jones
        self.append("SELECT docid,docname,doctype,");
1274
        self.append("date_created, date_updated ");
1275
        self.append("FROM xml_documents WHERE docid IN (");
1276
        self.append(docid).append(")");
1277
        return self.toString();
1278
    }
1279 159 jones
1280 2067 jones
    /**
1281
     * create a String description of the query that this instance represents.
1282
     * This should become a way to get the XML serialization of the query.
1283
     */
1284
    public String toString()
1285
    {
1286
        return "meta_file_id=" + meta_file_id + "\n" + query;
1287
        //DOCTITLE attr cleared from the db
1288
        //return "meta_file_id=" + meta_file_id + "\n" +
1289
        //"querytitle=" + querytitle + "\n" + query;
1290
    }
1291
1292 2073 jones
    /** A method to get rid of attribute part in path expression */
1293 2067 jones
    public static String newPathExpressionWithOutAttribute(String pathExpression)
1294
    {
1295
        if (pathExpression == null) { return null; }
1296
        int index = pathExpression.lastIndexOf(ATTRIBUTESYMBOL);
1297
        String newExpression = null;
1298 2458 cjones
        if (index != 0) {
1299 2067 jones
            newExpression = pathExpression.substring(0, index - 1);
1300
        }
1301 2663 sgarg
        logMetacat.info("The path expression without attributes: "
1302
                + newExpression);
1303 2067 jones
        return newExpression;
1304
    }
1305
1306 2073 jones
    /** A method to get attribute name from path */
1307 2067 jones
    public static String getAttributeName(String path)
1308
    {
1309
        if (path == null) { return null; }
1310
        int index = path.lastIndexOf(ATTRIBUTESYMBOL);
1311
        int size = path.length();
1312
        String attributeName = null;
1313
        if (index != 1) {
1314
            attributeName = path.substring(index + 1, size);
1315
        }
1316 2663 sgarg
        logMetacat.info("The attirbute name from path: "
1317
                + attributeName);
1318 2067 jones
        return attributeName;
1319
    }
1320
1321 155 jones
}