1 |
155
|
jones
|
/**
|
2 |
|
|
* Name: QuerySpecification.java
|
3 |
|
|
* Purpose: A Class that represents a structured query, and can be
|
4 |
|
|
* constructed from an XML serialization
|
5 |
|
|
* Copyright: 2000 Regents of the University of California and the
|
6 |
|
|
* National Center for Ecological Analysis and Synthesis
|
7 |
|
|
* Authors: Matt Jones
|
8 |
|
|
*
|
9 |
|
|
* Version: '$Id$'
|
10 |
|
|
*/
|
11 |
|
|
|
12 |
|
|
package edu.ucsb.nceas.metacat;
|
13 |
|
|
|
14 |
|
|
import java.io.*;
|
15 |
|
|
import java.util.Stack;
|
16 |
158
|
jones
|
import java.util.Vector;
|
17 |
159
|
jones
|
import java.util.Enumeration;
|
18 |
155
|
jones
|
|
19 |
158
|
jones
|
import org.xml.sax.AttributeList;
|
20 |
|
|
import org.xml.sax.InputSource;
|
21 |
|
|
import org.xml.sax.HandlerBase;
|
22 |
|
|
import org.xml.sax.Parser;
|
23 |
|
|
import org.xml.sax.SAXException;
|
24 |
|
|
import org.xml.sax.SAXParseException;
|
25 |
|
|
import org.xml.sax.helpers.ParserFactory;
|
26 |
|
|
//import oracle.xml.parser.v2.SAXParser;
|
27 |
155
|
jones
|
|
28 |
158
|
jones
|
|
29 |
|
|
|
30 |
155
|
jones
|
/**
|
31 |
|
|
* A Class that represents a structuredd query,and can be constructed from an
|
32 |
|
|
* XML serialization
|
33 |
|
|
*/
|
34 |
|
|
public class QuerySpecification extends HandlerBase {
|
35 |
|
|
|
36 |
158
|
jones
|
/** Default parser name. */
|
37 |
|
|
private static final String
|
38 |
|
|
DEFAULT_PARSER = "org.apache.xerces.parsers.SAXParser";
|
39 |
|
|
//DEFAULT_PARSER = "oracle.xml.parser.v2.SAXParser";
|
40 |
|
|
|
41 |
|
|
// Query data structures
|
42 |
|
|
private String meta_file_id;
|
43 |
|
|
private String querytitle;
|
44 |
|
|
private QueryGroup query = null;
|
45 |
|
|
|
46 |
|
|
private Stack elementStack;
|
47 |
|
|
private Stack queryStack;
|
48 |
159
|
jones
|
private String currentValue;
|
49 |
|
|
private String currentPathexpr;
|
50 |
158
|
jones
|
|
51 |
155
|
jones
|
/**
|
52 |
|
|
* construct an instance of the QuerySpecification class
|
53 |
|
|
*
|
54 |
|
|
* @param queryspec the XML representation of the query as a Reader
|
55 |
|
|
*/
|
56 |
|
|
public QuerySpecification( Reader queryspec ) throws IOException {
|
57 |
|
|
super();
|
58 |
158
|
jones
|
|
59 |
|
|
// Initialize the stack
|
60 |
|
|
elementStack = new Stack();
|
61 |
|
|
queryStack = new Stack();
|
62 |
|
|
|
63 |
|
|
// Initialize the parser and read the queryspec
|
64 |
|
|
Parser parser = initializeParser();
|
65 |
155
|
jones
|
try {
|
66 |
|
|
parser.parse(new InputSource(queryspec));
|
67 |
|
|
} catch (SAXException e) {
|
68 |
|
|
System.out.println("error parsing data");
|
69 |
|
|
System.out.println(e.getMessage());
|
70 |
|
|
}
|
71 |
|
|
}
|
72 |
|
|
|
73 |
|
|
/**
|
74 |
|
|
* construct an instance of the QuerySpecification class
|
75 |
|
|
*
|
76 |
|
|
* @param queryspec the XML representation of the query as a String
|
77 |
|
|
*/
|
78 |
|
|
public QuerySpecification( String queryspec ) throws IOException {
|
79 |
|
|
|
80 |
|
|
this(new StringReader(queryspec));
|
81 |
|
|
}
|
82 |
|
|
|
83 |
|
|
/** Main routine for testing */
|
84 |
|
|
static public void main(String[] args) {
|
85 |
|
|
|
86 |
|
|
if (args.length < 1) {
|
87 |
|
|
System.err.println("Wrong number of arguments!!!");
|
88 |
|
|
System.err.println("USAGE: java QuerySpecification <xmlfile>");
|
89 |
|
|
return;
|
90 |
|
|
} else {
|
91 |
|
|
String xmlfile = args[0];
|
92 |
|
|
|
93 |
|
|
try {
|
94 |
|
|
FileReader xml = new FileReader(new File(xmlfile));
|
95 |
|
|
QuerySpecification qspec = new QuerySpecification(xml);
|
96 |
159
|
jones
|
System.out.println(qspec);
|
97 |
155
|
jones
|
} catch (IOException e) {
|
98 |
|
|
System.err.println(e.getMessage());
|
99 |
|
|
}
|
100 |
|
|
|
101 |
|
|
}
|
102 |
|
|
}
|
103 |
|
|
|
104 |
158
|
jones
|
private Parser initializeParser() {
|
105 |
|
|
Parser parser = null;
|
106 |
155
|
jones
|
//
|
107 |
|
|
// Set up the SAX document handlers for parsing
|
108 |
|
|
//
|
109 |
|
|
try {
|
110 |
|
|
|
111 |
|
|
// Get an instance of the parser
|
112 |
158
|
jones
|
parser = ParserFactory.makeParser(DEFAULT_PARSER);
|
113 |
155
|
jones
|
|
114 |
158
|
jones
|
// Set the DocumentHandler to this instance
|
115 |
155
|
jones
|
parser.setDocumentHandler(this);
|
116 |
|
|
|
117 |
|
|
// Set the other Handler to the defHandler
|
118 |
158
|
jones
|
parser.setErrorHandler(this);
|
119 |
155
|
jones
|
|
120 |
|
|
} catch (Exception e) {
|
121 |
|
|
System.err.println(e.toString());
|
122 |
|
|
}
|
123 |
|
|
|
124 |
|
|
return parser;
|
125 |
|
|
}
|
126 |
|
|
|
127 |
|
|
public void startElement (String name, AttributeList atts)
|
128 |
|
|
throws SAXException {
|
129 |
158
|
jones
|
|
130 |
|
|
BasicNode currentNode = new BasicNode(name);
|
131 |
159
|
jones
|
// add attributes to BasicNode here
|
132 |
|
|
if (atts != null) {
|
133 |
|
|
int len = atts.getLength();
|
134 |
|
|
for (int i = 0; i < len; i++) {
|
135 |
|
|
currentNode.setAttribute(atts.getName(i), atts.getValue(i));
|
136 |
|
|
}
|
137 |
|
|
}
|
138 |
|
|
|
139 |
158
|
jones
|
elementStack.push(currentNode);
|
140 |
159
|
jones
|
if (currentNode.getTagName().equals("querygroup")) {
|
141 |
158
|
jones
|
QueryGroup currentGroup = new QueryGroup(
|
142 |
|
|
currentNode.getAttribute("booleantype"));
|
143 |
|
|
if (query == null) {
|
144 |
|
|
query = currentGroup;
|
145 |
159
|
jones
|
} else {
|
146 |
|
|
QueryGroup parentGroup = (QueryGroup)queryStack.peek();
|
147 |
|
|
parentGroup.addChild(currentGroup);
|
148 |
158
|
jones
|
}
|
149 |
159
|
jones
|
queryStack.push(currentGroup);
|
150 |
158
|
jones
|
}
|
151 |
155
|
jones
|
}
|
152 |
|
|
|
153 |
|
|
public void endElement (String name) throws SAXException {
|
154 |
158
|
jones
|
BasicNode leaving = (BasicNode)elementStack.pop();
|
155 |
159
|
jones
|
if (leaving.getTagName().equals("queryterm")) {
|
156 |
|
|
boolean isCaseSensitive = (new Boolean(
|
157 |
|
|
leaving.getAttribute("casesensitive"))).booleanValue();
|
158 |
|
|
QueryTerm currentTerm = null;
|
159 |
|
|
if (currentPathexpr == null) {
|
160 |
|
|
currentTerm = new QueryTerm(isCaseSensitive,
|
161 |
|
|
leaving.getAttribute("searchmode"),currentValue);
|
162 |
|
|
} else {
|
163 |
|
|
currentTerm = new QueryTerm(isCaseSensitive,
|
164 |
|
|
leaving.getAttribute("searchmode"),currentValue,
|
165 |
|
|
currentPathexpr);
|
166 |
|
|
}
|
167 |
|
|
QueryGroup currentGroup = (QueryGroup)queryStack.peek();
|
168 |
|
|
currentGroup.addChild(currentTerm);
|
169 |
|
|
currentValue = null;
|
170 |
|
|
currentPathexpr = null;
|
171 |
|
|
} else if (leaving.getTagName().equals("querygroup")) {
|
172 |
|
|
QueryGroup leavingGroup = (QueryGroup)queryStack.pop();
|
173 |
158
|
jones
|
}
|
174 |
155
|
jones
|
}
|
175 |
158
|
jones
|
|
176 |
|
|
public void characters(char ch[], int start, int length) {
|
177 |
|
|
|
178 |
|
|
String inputString = new String(ch, start, length);
|
179 |
|
|
BasicNode currentNode = (BasicNode)elementStack.peek();
|
180 |
|
|
String currentTag = currentNode.getTagName();
|
181 |
|
|
if (currentTag.equals("meta_file_id")) {
|
182 |
|
|
meta_file_id = inputString;
|
183 |
|
|
} else if (currentTag.equals("querytitle")) {
|
184 |
|
|
querytitle = inputString;
|
185 |
159
|
jones
|
} else if (currentTag.equals("value")) {
|
186 |
|
|
currentValue = inputString;
|
187 |
|
|
} else if (currentTag.equals("pathexpr")) {
|
188 |
|
|
currentPathexpr = inputString;
|
189 |
158
|
jones
|
}
|
190 |
|
|
}
|
191 |
|
|
|
192 |
159
|
jones
|
public String toString() {
|
193 |
|
|
return "meta_file_id=" + meta_file_id + "\n" +
|
194 |
|
|
"querytitle=" + querytitle + "\n" + query;
|
195 |
|
|
}
|
196 |
|
|
|
197 |
158
|
jones
|
/** a utility class that represents a group of terms in a query */
|
198 |
|
|
private class QueryGroup {
|
199 |
|
|
private String booleantype = null; // indicates how query terms are combined
|
200 |
|
|
private Vector children = null; // the list of query terms and groups
|
201 |
|
|
|
202 |
|
|
public QueryGroup(String booleantype) {
|
203 |
|
|
this.booleantype = booleantype;
|
204 |
|
|
children = new Vector();
|
205 |
|
|
}
|
206 |
|
|
|
207 |
|
|
public void addChild(QueryGroup qgroup) {
|
208 |
|
|
children.add((Object)qgroup);
|
209 |
|
|
}
|
210 |
|
|
|
211 |
|
|
public void addChild(QueryTerm qterm) {
|
212 |
|
|
children.add((Object)qterm);
|
213 |
|
|
}
|
214 |
|
|
|
215 |
|
|
public Enumeration getChildren() {
|
216 |
|
|
return children.elements();
|
217 |
|
|
}
|
218 |
159
|
jones
|
|
219 |
|
|
public String toString() {
|
220 |
|
|
StringBuffer self = new StringBuffer();
|
221 |
|
|
|
222 |
|
|
self.append(" (Query group booleantype=" + booleantype + "\n");
|
223 |
|
|
Enumeration en= getChildren();
|
224 |
|
|
while (en.hasMoreElements()) {
|
225 |
|
|
Object qobject = en.nextElement();
|
226 |
|
|
self.append(qobject);
|
227 |
|
|
}
|
228 |
|
|
self.append(" )\n");
|
229 |
|
|
return self.toString();
|
230 |
|
|
}
|
231 |
158
|
jones
|
}
|
232 |
|
|
|
233 |
|
|
/** a utility class that represents a single term in a query */
|
234 |
|
|
private class QueryTerm {
|
235 |
|
|
private boolean casesensitive = false;
|
236 |
|
|
private String searchmode = null;
|
237 |
|
|
private String value = null;
|
238 |
|
|
private String pathexpr = null;
|
239 |
|
|
|
240 |
|
|
public QueryTerm(boolean casesensitive, String searchmode,
|
241 |
|
|
String value) {
|
242 |
|
|
this.casesensitive = casesensitive;
|
243 |
|
|
this.searchmode = searchmode;
|
244 |
|
|
this.value = value;
|
245 |
|
|
}
|
246 |
|
|
|
247 |
|
|
public QueryTerm(boolean casesensitive, String searchmode,
|
248 |
|
|
String value, String pathexpr) {
|
249 |
|
|
this(casesensitive, searchmode, value);
|
250 |
|
|
this.pathexpr = pathexpr;
|
251 |
|
|
}
|
252 |
|
|
|
253 |
|
|
public boolean isCaseSensitive() {
|
254 |
|
|
return casesensitive;
|
255 |
|
|
}
|
256 |
|
|
|
257 |
|
|
public String getSearchMode() {
|
258 |
|
|
return searchmode;
|
259 |
|
|
}
|
260 |
|
|
|
261 |
|
|
public String getValue() {
|
262 |
|
|
return value;
|
263 |
|
|
}
|
264 |
|
|
|
265 |
|
|
public String getPathExpression() {
|
266 |
|
|
return pathexpr;
|
267 |
|
|
}
|
268 |
159
|
jones
|
|
269 |
|
|
public String toString() {
|
270 |
|
|
StringBuffer self = new StringBuffer();
|
271 |
|
|
|
272 |
|
|
self.append(" Query Term iscasesensitive=" + casesensitive + "\n");
|
273 |
|
|
self.append(" searchmode=" + searchmode + "\n");
|
274 |
|
|
self.append(" value=" + value + "\n");
|
275 |
|
|
if (pathexpr != null) {
|
276 |
|
|
self.append(" pathexpr=" + pathexpr + "\n");
|
277 |
|
|
}
|
278 |
|
|
|
279 |
|
|
return self.toString();
|
280 |
|
|
}
|
281 |
158
|
jones
|
}
|
282 |
155
|
jones
|
}
|