blob: 255e487b4d6d70369e0c9d54a8411823408c81c3 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
EDA XML Query Class
*/
package org.apache.oodt.xmlquery;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.StreamTokenizer;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.apache.oodt.product.Retriever;
import org.apache.oodt.commons.util.EnterpriseEntityResolver;
import org.apache.oodt.commons.util.XML;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
import org.xml.sax.EntityResolver;
import org.xml.sax.SAXException;
/**
* EDA XML query class. Parses a DIS style keyword query and creates query
* SELECT, FROM, and WHERE clauses. An XML DOM structure and an XML document
* representing the query can also be created. A RESULT set can be added to
* and retrieve.
*
*/
public class XMLQuery implements java.io.Serializable, Cloneable {
/** Result mode. */
private String resultModeId;
/** Propogation type. */
private String propogationType;
/** # of levels to propogate, depending on propogation type. */
private String propogationLevels;
/** Max results allowed. */
private int maxResults = DEFAULT_MAX_RESULTS;
/** KWQ, as a string. */
private String kwqString;
/** List of acceptable MIME types. */
private List mimeAccept;
/** List of statistics. */
private List statistics = new ArrayList();
/** Number of results so far.
*
* This could be greater than <code>results.size()</code> because that's limited by maxResults.
*
* Meh, this isn't even updated by anyone as far as I can tell.
*/
protected int numResults;
private QueryHeader queryHeader;
private List selectElementSet = new ArrayList();
private List fromElementSet = new ArrayList();
private List whereElementSet = new ArrayList();
private QueryResult result = new QueryResult();
private transient StreamTokenizer tokens; // Used for parse
private transient String lpart; // parser left part
private transient String opart; // parser operator
private transient String rpart; // parser right part
private transient String previous_token; // parser - allows backout
private transient int qfsc = 0; // query from set item count
private transient int qwsc = 0; // query where set item count
private transient int lit = 0; // last query item type ("from" or "where" clause)
public static final String[] FROM_TOKENS = {};
/** Constructor.
*
* @param keywordQuery The DIS style keyword query string.
* @param id A query identifier.
* @param title A terse description of the query for display.
* @param desc A description of the query.
* @param ddId The data dictionary identifier.
* @param resultModeId Indicates the return of INSTANCE, PROFILE, or CLASS.
* @param propType Indicates query BROADCAST or PROPOGATE.
* @param propLevels Number of propogation levels.
* @param maxResults Maximum number of results to be returned.
*/
public XMLQuery(String keywordQuery, String id, String title, String desc, String ddId, String resultModeId,
String propType, String propLevels, int maxResults) {
this(keywordQuery, id, title, desc, ddId, resultModeId, propType, propLevels, maxResults, null, true);
}
/** Constructor.
*
* @param keywordQuery The DIS style keyword query string.
* @param id A query identifier.
* @param title A terse description of the query for display.
* @param desc A description of the query.
* @param ddId The data dictionary identifier.
* @param resultModeId Indicates the return of INSTANCE, PROFILE, or CLASS.
* @param propType Indicates query BROADCAST or PROPOGATE.
* @param propLevels Number of propogation levels.
* @param maxResults Maximum number of results to be returned.
* @param parseQuery Indicates whether query should be parsed
*/
public XMLQuery(String keywordQuery, String id, String title, String desc, String ddId, String resultModeId,
String propType, String propLevels, int maxResults, boolean parseQuery) {
this(keywordQuery, id, title, desc, ddId, resultModeId, propType, propLevels, maxResults, null, parseQuery);
}
/** Constructor.
*
* @param keywordQuery The DIS style keyword query string.
* @param id A query identifier.
* @param title A terse description of the query for display.
* @param desc A description of the query.
* @param ddId The data dictionary identifier.
* @param resultModeId Indicates the return of INSTANCE, PROFILE, or CLASS.
* @param propType Indicates query BROADCAST or PROPOGATE.
* @param propLevels Number of propogation levels.
* @param maxResults Maximum number of results to be returned.
* @param mimeAccept List of acceptable MIME types.
*/
public XMLQuery(String keywordQuery, String id, String title, String desc, String ddId, String resultModeId,
String propType, String propLevels, int maxResults, List mimeAccept) {
this(keywordQuery, id, title, desc, ddId, resultModeId, propType, propLevels, maxResults, mimeAccept, true);
}
/** Constructor.
*
* @param keywordQuery The DIS style keyword query string.
* @param id A query identifier.
* @param title A terse description of the query for display.
* @param desc A description of the query.
* @param ddId The data dictionary identifier.
* @param resultModeId Indicates the return of INSTANCE, PROFILE, or CLASS.
* @param propType Indicates query BROADCAST or PROPOGATE.
* @param propLevels Number of propogation levels.
* @param maxResults Maximum number of results to be returned.
* @param mimeAccept List of acceptable MIME types.
* @param parseQuery Indicates whether query should be parsed
*/
public XMLQuery(String keywordQuery, String id, String title, String desc, String ddId, String resultModeId,
String propType, String propLevels, int maxResults,
List mimeAccept, boolean parseQuery) {
if (mimeAccept == null) {
mimeAccept = new ArrayList();
mimeAccept.add("*/*");
}
if (keywordQuery == null) keywordQuery = "UNKNOWN";
// init query header (object attributes)
if (id == null) id = new String("UNKNOWN");
if (title == null) title = new String("UNKNOWN");
if (desc == null) desc = new String("UNKNOWN");
if (ddId == null) ddId = new String("UNKNOWN");
queryHeader = new QueryHeader(id, title, desc, /*type*/"QUERY", /*status*/"ACTIVE", /*security*/"UNKNOWN",
/*revision*/"1999-12-12 JSH V1.0 Under Development", ddId);
// init query attributes
if (resultModeId == null) resultModeId = new String("ATTRIBUTE");
if (propType == null) {
propType = new String("BROADCAST");
propLevels = new String("N/A");
}
this.resultModeId = resultModeId;
this.propogationType = propType;
this.propogationLevels = propLevels;
this.maxResults = maxResults;
this.kwqString = keywordQuery;
this.mimeAccept = mimeAccept;
// parse the keyword query string
if (! parseQuery) {
queryHeader.setStatusID("NOTPARSED");
} else if (!parseKeywordString(keywordQuery)) {
queryHeader.setStatusID("ERROR");
}
}
/** Get the list of acceptable MIME types.
*
* @return The list of acceptable MIME types; you may modify the list.
*/
public List getMimeAccept() {
return mimeAccept;
}
/**
* Instantiates an XMLQuery instance from an XML query structure in string format.
*
* @param xmlQueryString The XML query structure in string format.
*/
public XMLQuery (String xmlQueryString) throws SAXException {
if (xmlQueryString == null) xmlQueryString = BLANK;
try {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setCoalescing(false);
factory.setNamespaceAware(false);
factory.setValidating(false);
DocumentBuilder builder = factory.newDocumentBuilder();
builder.setEntityResolver(ENTITY_RESOLVER);
Document doc = builder.parse(new ByteArrayInputStream(xmlQueryString.getBytes()));
loadXMLQueryStruct(doc.getDocumentElement());
} catch (IOException ex) {
System.err.println("Unexpected no good bloody IOException while parsing doc: " + xmlQueryString);
throw new IllegalStateException("Unexpected no good bloody IOException: " + ex.getMessage() + ", during"
+ " parse of " + xmlQueryString);
} catch (ParserConfigurationException ex) {
throw new IllegalStateException("Unexpected ParserConfigurationException: " + ex.getMessage());
}
}
/**
* Instantiates an XMLQuery instance from an XML query structure in DOM node format.
*
* @param node The XML &lt;query&gt; node.
*/
public XMLQuery (Node node) {
loadXMLQueryStruct(node);
}
/**
* Gets the original DIS style keyword query string.
*
* @return The DIS style keyword query string.
*/
public String getKwdQueryString () {
return kwqString;
}
/**
* Gets the max # of results
*
* @return the results
*/
public int getMaxResults() {
return maxResults;
}
/**
* @return Gets the select elements
*
*/
public List getSelectElementSet() {
return(selectElementSet);
}
/**
* @return Gets the from element set from the query
*
*/
public List getFromElementSet()
{
return(fromElementSet);
}
/**
* @return Gets the resultModeID
*
*/
public String getResultModeID()
{
return(resultModeId);
}
/**
* @return Gets the where set
*
*/
public List getWhereElementSet() {
return(whereElementSet);
}
/**
* Set query where element set.
* @param whereElementSet Thw where element set of XMLQuery.
*/
public void setWhereElementSet(List whereElementSet) {
this.whereElementSet = whereElementSet;
}
/**
* @return Gets the result list
*
*/
public QueryResult getResult() {
return result;
}
public List getResults() {
return result.getList();
}
public void setRetriever(Retriever retriever) {
result.setRetriever(retriever);
}
/**
* @return The query as an XML DOM structure.
*/
public Document getXMLDoc () {
Document doc = createDocument();
doc.appendChild(doc.createElement("query"));
createXMLDoc(doc);
return doc;
}
/** Get the list of stasitics of this query.
*
* @return A list of {@link Statistic} objects.
*/
public List getStatistics() {
return statistics;
}
/**
* Gets query as an XML document in string format.
*
* @return The query as an XML document in string format.
*/
public String getXMLDocString () {
StringWriter writer = new StringWriter();
try {
TransformerFactory factory = TransformerFactory.newInstance();
Transformer transformer = factory.newTransformer();
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
transformer.setOutputProperty(OutputKeys.MEDIA_TYPE, "text/xml");
transformer.setOutputProperty(OutputKeys.METHOD, "xml");
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
transformer.setOutputProperty(OutputKeys.STANDALONE, "no");
transformer.setOutputProperty(OutputKeys.VERSION, "1.0");
transformer.transform(new DOMSource(getXMLDoc()), new StreamResult(writer));
} catch (TransformerException ex) {
throw new IllegalStateException("Unexpected TransformerException: " + ex.getMessage());
} finally {
try {
writer.close();
} catch (IOException ignore) {}
}
return writer.toString();
}
/**
* Get the propagation type.
*
* @return a {@link String} value.
*/
public String getPropagationType() {
return propogationType;
}
/**
* Get the propagation levels.
*
* @return a {@link String} value.
*/
public String getPropagationLevels() {
return propogationLevels;
}
/**
* Parse keyword query string (simple top down recursion).
*/
private boolean parseKeywordString (String kwdQueryString) {
previous_token = "";
lpart = "";
rpart = "";
tokens = new java.io.StreamTokenizer(new StringReader(kwdQueryString));
tokens.resetSyntax();
tokens.ordinaryChar('/');
tokens.wordChars(':', ':');
tokens.wordChars('0', '9');
tokens.wordChars('.', '.');
tokens.wordChars('-', '-');
tokens.wordChars('[', '[');
tokens.wordChars(']', ']');
tokens.wordChars('a', 'z');
tokens.wordChars('A', 'Z');
tokens.wordChars('_', '_');
tokens.wordChars('/', '/');
tokens.eolIsSignificant(true);
tokens.whitespaceChars(0, ' ');
tokens.quoteChar('"');
tokens.quoteChar('\'');
if (kqOrParse ()){
return true;
} else {
return false;
}
}
/**
* Parse OR logical operator.
*/
private boolean kqOrParse ()
{
boolean lflag, rflag;
lflag = kqAndParse();
while (isTokenEqual("OR") | isTokenEqual("or") | isTokenEqual("|")) {
rflag = kqAndParse();
lflag &= rflag;
appendLogOperator("LOGOP", "OR");
}
return lflag;
}
/**
* Parse AND logical operator.
*/
private boolean kqAndParse ()
{
boolean lflag, rflag;
lflag = kqNotParse();
while (isTokenEqual("AND") | isTokenEqual("and") | isTokenEqual("&")) {
rflag = kqNotParse();
lflag &= rflag;
appendLogOperator("LOGOP", "AND");
}
return lflag;
}
/**
* Parse NOT logical operator.
*/
private boolean kqNotParse ()
{
boolean lflag, rflag;
if (isTokenEqual("NOT") | isTokenEqual("not") | isTokenEqual("!")) {
lflag = kqFactorParse();
appendLogOperator("LOGOP", "NOT");
} else {
lflag = kqFactorParse ();
}
return lflag;
}
/**
* Parse logical operator operand and handle nesting (parens)
* also logic for differentiating SELECT, WHERE, and FROM
*/
private boolean kqFactorParse ()
{
String ropn, enm;
if (isTokenEqual("(")) {
return (kqOrParse () & isTokenEqual(")"));
} else {
lpart = getNextToken ();
if (lpart.compareTo("") != 0) {
ropn = getNextToken ();
if (ropn.compareTo("EQ") == 0 || ropn.compareTo("LT") == 0 || ropn.compareTo("LE") == 0 || ropn.compareTo("GT") == 0 || ropn.compareTo("GE")== 0 || ropn.compareTo("NE") == 0 || ropn.compareToIgnoreCase("LIKE") == 0 || ropn.compareToIgnoreCase("NOTLIKE") == 0 || ropn.compareTo("IS") == 0 || ropn.compareTo("ISNOT") == 0) {
rpart = getNextToken ();
if (rpart.compareTo("") != 0) {
lit = 0;
enm = lpart;
if (enm.compareTo("RETURN") == 0) {
selectElementSet.add(new QueryElement("elemName", rpart));
} else if (isFromToken(lpart)) {
qfsc++;
lit = 1;
fromElementSet.add(new QueryElement("elemName", lpart));
fromElementSet.add(new QueryElement("LITERAL", rpart));
fromElementSet.add(new QueryElement("RELOP", ropn));
} else {
lit = 2;
qwsc++;
whereElementSet.add(new QueryElement("elemName", lpart));
whereElementSet.add(new QueryElement("LITERAL", rpart));
whereElementSet.add(new QueryElement("RELOP", ropn));
}
return true;
}
}
}
}
return false;
}
/**
* Create Logical Operator DOM node for WHERE clause.
*/
private boolean appendLogOperator (String tt, String ts)
{
if (lit == 1 & qfsc > 1) {
fromElementSet.add(new QueryElement(tt, ts));
} else if (lit == 2 & qwsc > 1) {
whereElementSet.add(new QueryElement(tt, ts));
}
return true;
}
/**
* Lexical analyzer - find a FROM token.
*/
private static boolean isFromToken (String s1)
{
String tmpStr = s1;
for (int i = 0; i < FROM_TOKENS.length; i++)
{
if (tmpStr.compareTo(FROM_TOKENS[i]) == 0) {
return true;
}
}
return false;
}
/**
* Lexical analyzer - return next token - allows lookahead.
*/
private String getNextToken ()
{
String ts;
ts = previous_token;
if (previous_token.compareTo("") == 0) {
ts = getNextTokenFromStream();
return ts;
} else {
previous_token = "";
return ts;
}
}
/**
* Lexical analyzer - check if next token equal to argument.
*/
private boolean isTokenEqual (String s1) {
String ts;
boolean rc = false;
ts = previous_token;
if (previous_token.compareTo("") == 0) {
ts = getNextTokenFromStream ();
if (ts.compareTo("") == 0) {
rc = false;
} else {
if (ts.compareTo(s1) == 0) {
previous_token = "";
rc = true;
} else {
previous_token = ts;
rc = false;
}
}
} else {
if (previous_token.compareTo(s1) == 0) {
previous_token = "";
rc = true;
} else {
rc = false;
}
}
return rc;
}
/**
* Lexical analyzer - return next token from instance of StreamTokenizer.
*/
private String getNextTokenFromStream () {
int c, c2;
String rc = "";
try {
switch (c=tokens.nextToken()) {
case StreamTokenizer.TT_EOF:
rc = "";
break;
case StreamTokenizer.TT_EOL:
rc = "";
break;
case StreamTokenizer.TT_NUMBER: // not currently set
rc = "";
break;
case StreamTokenizer.TT_WORD:
rc = tokens.sval;
break;
case '(':
case ')':
rc = String.valueOf((char)c);
break;
case '"':
case '\'':
rc = tokens.sval;
break;
case '=':
rc = "EQ";
break;
case '&':
rc = "AND";
break;
case '|':
rc = "OR";
break;
case '<':
c2 = tokens.nextToken();
if (c2 == '=') {
rc = "LE";
} else {
tokens.pushBack();
rc = "LT";
}
break;
case '>':
c2 = tokens.nextToken();
if (c2 == '=') {
rc = "GE";
} else {
tokens.pushBack();
rc = "GT";
}
break;
case '!':
c2 = tokens.nextToken();
if (c2 == '=') {
rc = "NE";
} else {
tokens.pushBack();
rc = "NOT";
}
break;
default:
rc = "";
}
} catch (IOException e1) {
rc = "";
}
return rc;
}
/**
* Replace character with string
*/
private String replaceCharWithString (String s1, char c, String rs)
{
int p1, p2, s1l;
String s2;
p1 = 0; p2 = 0;
s1l = s1.length();
s2 = "";
p2 = s1.indexOf(c, p1);
while (p2 >= 0) {
s2 += s1.substring (p1, p2) + rs;
p1 = p2 + 1;
p2 = s1.indexOf(c, p1);
}
if (p1 < s1l) {
s2 += s1.substring(p1, s1l);
}
return s2;
}
/**
* Creates a XML DOM structure from a keyword query string.
* Set up the basic structure then calls the query parser.
*/
private void createXMLDoc (Document doc) {
int loc;
String kwd;
String type;
String val;
Element item;
Element elem;
Element query = doc.getDocumentElement();
// create query header (object attributes)
query.appendChild(queryHeader.toXML(doc));
// create query attributes
XML.add(query, "queryResultModeId", resultModeId);
XML.add(query, "queryPropogationType", propogationType);
XML.add(query, "queryPropogationLevels", propogationLevels);
XML.add(query, "queryMimeAccept", mimeAccept);
XML.add(query, "queryMaxResults", String.valueOf(maxResults));
XML.add(query, "queryResults", String.valueOf(numResults));
XML.add(query, "queryKWQString", kwqString);
// create and load queryStatistics
elem = doc.createElement("queryStatistics");
query.appendChild(elem);
for (Iterator i = statistics.iterator(); i.hasNext();) {
Statistic s = (Statistic) i.next();
elem.appendChild(s.toXML(doc));
}
// create and load querySelectSet
elem = doc.createElement("querySelectSet");
query.appendChild(elem);
for (Iterator i = selectElementSet.iterator(); i.hasNext();) {
QueryElement queryElement = (QueryElement) i.next();
elem.appendChild(queryElement.toXML(doc));
}
// create and load queryFromSet
elem = doc.createElement("queryFromSet");
query.appendChild(elem);
for (Iterator i = fromElementSet.iterator(); i.hasNext();) {
QueryElement queryElement = (QueryElement) i.next();
elem.appendChild(queryElement.toXML(doc));
}
// create and load queryWhereSet
elem = doc.createElement("queryWhereSet");
query.appendChild(elem);
for (Iterator i = whereElementSet.iterator(); i.hasNext();) {
QueryElement queryElement = (QueryElement) i.next();
elem.appendChild(queryElement.toXML(doc));
}
query.appendChild(result.toXML(doc));
}
/**
* Creates a leaf (end node - TEXT) in the DOM structure.
*/
private Element createLeaf (Element child, String value) {
child.appendChild(child.getOwnerDocument().createTextNode(value));
return child;
}
/**
* Load the internal query structure (dictionary) from an XML DOM structure
*/
private void loadXMLQueryStruct (Node root) {
Node node;
String nodeName;
initNodes();
for (node = root.getFirstChild();
node != null;
node = node.getNextSibling()) {
if (node instanceof Element) {
nodeName = node.getNodeName();
if (nodeName.compareTo("queryAttributes") == 0) {
queryHeader = new QueryHeader(node);
} else if (nodeName.compareTo("queryResultModeId") == 0) {
resultModeId = XML.unwrappedText(node);
} else if (nodeName.compareTo("queryPropogationType") == 0) {
propogationType = XML.unwrappedText(node);
} else if (nodeName.compareTo("queryPropogationLevels") == 0) {
propogationLevels = XML.unwrappedText(node);
} else if (nodeName.equals("queryMimeAccept")) {
mimeAccept.add(XML.unwrappedText(node));
} else if (nodeName.compareTo("queryMaxResults") == 0) {
maxResults = Integer.parseInt(XML.unwrappedText(node));
} else if (nodeName.compareTo("queryResults") == 0) {
numResults = Integer.parseInt(XML.unwrappedText(node));
} else if (nodeName.compareTo("queryKWQString") == 0) {
kwqString = XML.unwrappedText(node);
} else if (nodeName.compareTo("querySelectSet") == 0) {
scanQueryElements(selectElementSet, node);
} else if (nodeName.compareTo("queryFromSet") == 0) {
scanQueryElements(fromElementSet, node);
} else if (nodeName.compareTo("queryWhereSet") == 0) {
scanQueryElements(whereElementSet, node);
} else if (nodeName.compareTo("queryResultSet") == 0) {
result = new QueryResult(node);
} else if (nodeName.equals("queryStatistics")) {
NodeList children = node.getChildNodes();
for (int i = 0; i < children.getLength(); ++i) {
Node statisticNode = children.item(i);
if (statisticNode.getNodeType() == Node.ELEMENT_NODE) {
Statistic s = new Statistic(statisticNode);
statistics.add(s);
}
}
}
}
}
return;
}
/**
* Replace the dictionary keyword value with the DOM text node value.
*/
private void replaceKwdVal (Map map, Node node, String nodeName) {
Node childNode;
childNode = node.getFirstChild();
if (childNode instanceof Text) {
map.put(nodeName, childNode.getNodeValue());
} else {
map.put(nodeName, "UNKNOWN");
}
return;
}
/**
* Scan the DOM structure for the SELECT, FROM, or WHERE set.
*
* @param list To what list to add the query elements.
* @param node Where to find the query elements.
*/
private static void scanQueryElements(List list, Node node) {
NodeList children = node.getChildNodes();
for (int i = 0; i < children.getLength(); ++i) {
Node n = children.item(i);
if (n.getNodeType() == Node.ELEMENT_NODE)
list.add(new QueryElement(n));
}
}
/**
* Initialize the Query and Resource attributes in the dictionary.
*/
private void initNodes () {
queryHeader = new QueryHeader();
resultModeId = "ATTRIBUTE";
propogationType = "BROADCAST";
propogationLevels = "N/A";
maxResults = DEFAULT_MAX_RESULTS;
kwqString = "UNKNOWN";
mimeAccept = new ArrayList();
}
public int hashCode() {
return resultModeId.hashCode() ^ propogationType.hashCode() ^ propogationLevels.hashCode()
^ (maxResults << 8) ^ kwqString.hashCode() ^ numResults ^ queryHeader.hashCode()
^ selectElementSet.hashCode() ^ fromElementSet.hashCode() ^ whereElementSet.hashCode()
^ result.hashCode();
}
public boolean equals(Object rhs) {
if (rhs == this) return true;
if (rhs == null || !(rhs instanceof XMLQuery)) return false;
XMLQuery obj = (XMLQuery) rhs;
return resultModeId.equals(obj.resultModeId) && propogationType.equals(obj.propogationType)
&& propogationLevels.equals(obj.propogationLevels) && maxResults == obj.maxResults
&& kwqString.equals(obj.kwqString) && numResults == obj.numResults
&& queryHeader.equals(obj.queryHeader) && selectElementSet.equals(obj.selectElementSet)
&& fromElementSet.equals(obj.fromElementSet) && whereElementSet.equals(obj.whereElementSet)
&& result.equals(obj.result);
}
public Object clone() {
Object rc = null;
try {
rc = super.clone();
} catch (CloneNotSupportedException cantHappen) {}
return rc;
}
public String toString() {
return getClass().getName() + "[kwqString=" + kwqString + "]";
}
/** Create an XML DOM document using the query DTD.
*
* @return An XML DOM document, with a query root element, using the query DTD.
*/
public static Document createDocument() {
try {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setCoalescing(true);
factory.setNamespaceAware(false);
factory.setValidating(false);
DocumentBuilder builder = factory.newDocumentBuilder();
return builder.newDocument();
} catch (ParserConfigurationException ex) {
throw new IllegalStateException("Unexpected ParserConfigurationException: " + ex.getMessage());
}
}
public static void main(String[] argv) throws Exception {
if (argv.length < 2 || (!argv[0].equals("-expr") && !argv[0].equals("-file"))
|| (argv[0].equals("-file") && argv.length > 2)) {
System.err.println("Usage: -expr <expr>...");
System.err.println(" or: -file <file>");
System.exit(1);
}
XMLQuery q;
if (argv[0].equals("-expr")) {
StringBuffer expr = new StringBuffer();
for (int i = 1; i < argv.length; ++i)
expr.append(argv[i]).append(' ');
q = new XMLQuery(expr.toString().trim(), "expr1", "Command-line Expression Query",
"The expression for this query came from the command-line", /*ddId*/ null,
/*resultModeId*/ null, /*propType*/ null, /*propLevels*/ null, XMLQuery.DEFAULT_MAX_RESULTS);
} else if (argv[0].equals("-file")) {
BufferedReader reader = new BufferedReader(new FileReader(argv[1]));
StringBuffer str = new StringBuffer();
String line;
while ((line = reader.readLine()) != null)
str.append(line).append('\n');
reader.close();
q = new XMLQuery(str.toString());
} else throw new IllegalStateException("Can't get here; only -expr or -file allowed, but got \"" + argv[0] + "\"");
System.out.println("kwdQueryString: " + q.getKwdQueryString());
System.out.println("fromElementSet: " + q.getFromElementSet());
System.out.println("results: " + q.getResult());
System.out.println("whereElementSet: " + q.getWhereElementSet());
System.out.println("selectElementSet: " + q.getSelectElementSet());
System.out.println("======doc string=======");
System.out.println(q.getXMLDocString());
}
public QueryHeader getQueryHeader() {
return queryHeader;
}
/** Maximum number results to get (default). */
public static final int DEFAULT_MAX_RESULTS = 100;
/** The Formal Public Identifier of the query DTD. */
public static final String QUERY_FPI = "-//JPL//DTD OODT Query 1.0//EN";
/** The System Identifier of the query DTD. */
public static final String QUERY_URL = "http://oodt.jpl.nasa.gov/edm-query/query.dtd"; // FIXME: Move to apache.org
/** A blank query document, as a string. */
private static String BLANK = "<?xml version='1.0' encoding='UTF-8'?>\n<!DOCTYPE query PUBLIC '" + QUERY_FPI
+ "' '" + QUERY_URL + "'>\n<query/>";
/** Resolver for the query DTD. */
private static final EntityResolver ENTITY_RESOLVER = new EnterpriseEntityResolver();
/** Serial version unique ID. */
static final long serialVersionUID = -7638068782048963710L;
}