Project

General

Profile

1
/**
2
 *  '$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
 *
11
 *   '$Author: tao $'
12
 *     '$Date: 2007-04-11 17:41:54 -0700 (Wed, 11 Apr 2007) $'
13
 * '$Revision: 3226 $'
14
 *
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
 */
29

    
30
package edu.ucsb.nceas.metacat;
31

    
32
import edu.ucsb.nceas.dbadapter.*;
33

    
34
import java.io.*;
35
import java.util.Hashtable;
36
import java.util.Stack;
37
import java.util.Vector;
38
import java.util.Enumeration;
39

    
40
import org.apache.log4j.Logger;
41

    
42
 /** a utility class that represents a group of terms in a query */
43
public  class QueryGroup {
44
    private String operator = null;  // indicates how query terms are combined
45
    private Vector children = null;  // the list of query terms and groups
46
    private int countPercentageSearchItem = 0;
47
    private Vector queryTermsWithSameValue = null;//this two dimension vectors.
48
                                                  //will hold query terms which has same search value.
49
    private Vector queryTerms = null;//this vector only holds query terms without same search value.
50
    private Vector queryGroupsChildren = null;
51
    private static Logger logMetacat = Logger.getLogger(QueryGroup.class);
52

    
53
    /**
54
     * construct a new QueryGroup
55
     *
56
     * @param operator the boolean conector used to connect query terms
57
     *                    in this query group
58
     */
59
    public QueryGroup(String operator) {
60
      this.operator = operator;
61
      children = new Vector();
62
      queryTermsWithSameValue = new Vector();
63
      queryTerms = new Vector();
64
      queryGroupsChildren = new Vector();
65
    }
66

    
67
    /**
68
     * Add a child QueryGroup to this QueryGroup
69
     *
70
     * @param qgroup the query group to be added to the list of terms
71
     */
72
    public void addChild(QueryGroup qgroup) {
73
      //children.add((Object)qgroup);
74
      queryGroupsChildren.add(qgroup);
75
    }
76

    
77
    /**
78
     * Add a child QueryTerm to this QueryGroup
79
     *
80
     * @param qterm the query term to be added to the list of terms
81
     */
82
    public void addChild(QueryTerm qterm) {
83
      // children.add((Object)qterm);
84
      handleNewQueryTerms(qterm);
85
      
86
    }
87

    
88
    /**
89
     * Retrieve an Enumeration of query terms for this QueryGroup
90
     */
91
    public Enumeration getChildren() {
92
      return children.elements();
93
    }
94

    
95
    public int getPercentageSymbolCount()
96
    {
97
      return countPercentageSearchItem;
98
    }
99

    
100
    /**
101
     * create a SQL serialization of the query that this instance represents
102
     */
103
    public String printSQL(boolean useXMLIndex) {
104
      StringBuffer self = new StringBuffer();
105
      StringBuffer queryString = new StringBuffer();
106

    
107
      boolean first = true;
108
      
109
      Enumeration en= getChildren();
110
      while (en.hasMoreElements()) {
111
        Object qobject = en.nextElement();
112
        if (qobject instanceof QueryGroup) {
113
            QueryGroup qg = (QueryGroup)qobject;
114
        	String queryGroupSQL = qg.printSQL(useXMLIndex);
115
        	logMetacat.info("In QueryGroup.printSQL.. found a QueryGroup: " 
116
        			+ queryGroupSQL);
117
        	
118
        	if (first) {
119
        		first = false;
120
        	} else {
121
        		if(!queryString.toString().equals("") && queryGroupSQL != null &&!queryGroupSQL.equals("")){
122
                    queryString.append(" " + operator + " ");
123
        		}
124
        	}
125
   		  	queryString.append(queryGroupSQL);
126
   		  	
127
   		  	// count percerntage number
128
   		  	int count = qg.getPercentageSymbolCount();
129
   		  	countPercentageSearchItem = countPercentageSearchItem + count;
130
        } else if (qobject instanceof QueryTerm) {
131
           QueryTerm qt = (QueryTerm)qobject;
132
           String termQueryString = qt.printSQL(useXMLIndex);
133
       	   logMetacat.info("In QueryGroup.printSQL.. found a QueryGroup: " 
134
        			+ termQueryString);
135
           if(!(qt.getSearchMode().equals("contains") && qt.getValue().equals("%"))){
136
        	   if (first) {
137
                   first = false;
138
               } else {
139
                   if(!queryString.toString().equals("")){
140
                       queryString.append(" " + operator + " ");
141
                   }
142
               }
143
               queryString.append(termQueryString);
144
           }
145
           // count percerntage number
146
           int count = qt.getPercentageSymbolCount();
147
           countPercentageSearchItem = countPercentageSearchItem + count;
148
        } else {
149
          System.err.println("qobject wrong type: fatal error");
150
        }
151
      }
152

    
153
      if(!queryString.toString().equals("")){
154
          self.append("(");
155
          self.append(queryString.toString());
156
          self.append(")");
157
      }
158
      
159
      logMetacat.info("In QueryGroup.printSQL.. final query returned is: " 
160
			+ self.toString());
161
      return self.toString();
162
    }
163
    
164
    
165
    /*
166
     * If every query term in a queryGroup share a search value, we should
167
     * use a new query to replace the original query term query in order to
168
     * improve performance
169
     */
170
    private String printSQLStringWithSameSearchValue()
171
    {
172
    	String sql ="";
173
    	String value ="";
174
    	StringBuffer sqlBuff = new StringBuffer();
175
    	Vector pathVector = new Vector();
176
    	int index =0;
177
    	
178
    	if (queryTermsWithSameValue != null)
179
    	{
180
    		QueryTerm term1 = (QueryTerm)queryTermsWithSameValue.elementAt(0);
181
        	value = term1.getValue();
182
        	boolean first = true;
183
			sqlBuff.append("SELECT DISTINCT docid FROM xml_path_index WHERE UPPER(nodedata) LIKE '%");
184
			sqlBuff.append(value);
185
			sqlBuff.append("%' AND path IN (");
186
    		//gets every path in query term object
187
    		for (int i=0; i<queryTermsWithSameValue.size(); i++)
188
    		{
189
    			QueryTerm term = (QueryTerm)queryTermsWithSameValue.elementAt(i);
190
    			value = term.getValue();
191
    			String path = term.getPathExpression();
192
    			if (path != null && !path.equals(""))
193
    			{
194
    				if (first)
195
    				{
196
    					first = false;
197
    					sqlBuff.append("'");
198
    					sqlBuff.append(path);
199
    					sqlBuff.append("'");
200
    					
201
    				}
202
    				else
203
    				{
204
    					sqlBuff.append(",'");
205
    					sqlBuff.append(path);
206
    					sqlBuff.append("'");
207
    				}
208
    				index++;
209
    			}
210
    		}
211
    		sqlBuff.append(")");
212
    	
213
    	}
214
    	if (index >0)
215
    	{
216
    		sql = sqlBuff.toString();
217
    	}
218
    	return sql;
219
    }
220

    
221
    /**
222
     * create a String description of the query that this instance represents.
223
     * This should become a way to get the XML serialization of the query.
224
     */
225
    public String toString() {
226
      StringBuffer self = new StringBuffer();
227

    
228
      self.append("  (Query group operator=" + operator + "\n");
229
      Enumeration en= getChildren();
230
      while (en.hasMoreElements()) {
231
        Object qobject = en.nextElement();
232
        self.append(qobject);
233
      }
234
      self.append("  )\n");
235
      return self.toString();
236
    }
237
    
238
    /*
239
     * When a new QueryTerm come, first we need to compare it to
240
     * the queryTerm vector, which contains queryTerm that doesn't
241
     * have same search value to any other queryTerm. Here is algorithm.
242
     * 1) If new QueryTerm find a QueryTerm in queryTerms which has same search value,
243
     *    them create a new vector which contain both QueryTerms and add the new vector
244
     *    to two-dimention vector queryTermsWithSameValue, and remove the QueryTerm which
245
     *    was in queryTerm.
246
     * 2) If new QueryTerm couldn't find a QueryTerm in queryTerms which has same search value,
247
     *    then search queryTermsWithSameValue, to see if this vector already has the search value.
248
     *    2.1) if has the search value, add the new QueryTerm to the queryTermsWithSameValue.
249
     *    2.2) if hasn't, add the new QueryTerm to queryTerms vector.
250
     */
251
    private void handleNewQueryTerms(QueryTerm newTerm)
252
    {
253
    	if (newTerm != null)
254
    	{
255
    		for (int i=0; i<queryTerms.size(); i++)
256
    		{
257
    			QueryTerm term = (QueryTerm)queryTerms.elementAt(i);
258
    			if (term != null && term.hasSameSearchValue(newTerm))
259
    			{
260
    				// find a target which has same search value
261
    				Vector newSameValueVector = new Vector();
262
    				newSameValueVector.add(term);
263
    				newSameValueVector.addElement(newTerm);
264
    				queryTermsWithSameValue.add(newSameValueVector);
265
    				queryTerms.remove(i);
266
    				return;
267
    			}
268
    		}
269
    		// no same search value was found in queryTerms.
270
    		// then we need search queryTermsWithSameValue
271
    		for (int i=0; i<queryTermsWithSameValue.size(); i++)
272
    		{
273
    			Vector sameValueVec = (Vector)queryTermsWithSameValue.elementAt(i);
274
    			// we only compare the first query term
275
    			QueryTerm term = (QueryTerm)sameValueVec.elementAt(0);
276
    			if (term != null && term.hasSameSearchValue(newTerm))
277
    			{
278
    				sameValueVec.add(newTerm);
279
    				return;
280
    			}
281
    		}
282
    		// both queryTerms and queryTermsWithSameValue don't have the search value,
283
    		// add this newTerm to queryTerms
284
    		queryTerms.add(newTerm);
285
    	}
286
    	
287
    }
288
  }
(54-54/66)