oodt-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mattm...@apache.org
Subject [3/6] oodt git commit: - add in xmlquery and product handler code necessary to build this app
Date Sun, 16 Jul 2017 18:33:32 GMT
http://git-wip-us.apache.org/repos/asf/oodt/blob/4066b63b/webapp/fmprod/src/main/java/org/apache/oodt/xmlquery/XMLQuery.java
----------------------------------------------------------------------
diff --git a/webapp/fmprod/src/main/java/org/apache/oodt/xmlquery/XMLQuery.java b/webapp/fmprod/src/main/java/org/apache/oodt/xmlquery/XMLQuery.java
new file mode 100755
index 0000000..eade767
--- /dev/null
+++ b/webapp/fmprod/src/main/java/org/apache/oodt/xmlquery/XMLQuery.java
@@ -0,0 +1,981 @@
+/*
+ * 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 org.apache.oodt.commons.util.EnterpriseEntityResolver;
+import org.apache.oodt.commons.util.XML;
+import org.apache.oodt.product.Retriever;
+
+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;
+
+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.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;
+
+/**
+ * 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 = "UNKNOWN";
+		}
+		if (title == null) {
+		  title = "UNKNOWN";
+		}
+		if (desc == null) {
+		  desc = "UNKNOWN";
+		}
+		if (ddId == null) {
+		  ddId = "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 = "ATTRIBUTE";
+		}
+		if (propType == null) {
+			propType = "BROADCAST";
+			propLevels = "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(':', ':');
+            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('\'');
+
+	  return kqOrParse();
+	}
+
+    /**
+     * 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)
+	{
+	  for (String FROM_TOKEN : FROM_TOKENS) {
+		if (s1.compareTo(FROM_TOKEN) == 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;
+
+	  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;
+    	StringBuilder s2;
+    	
+    	p1 = 0;
+	  s1l = s1.length();
+    	s2 = new StringBuilder();
+    	p2 = s1.indexOf(c, p1);
+    	while (p2 >= 0) {
+    	    s2.append(s1.substring(p1, p2)).append(rs);
+            p1 = p2 + 1;
+            p2 = s1.indexOf(c, p1);
+        }
+        if (p1 < s1l) {
+            s2.append(s1.substring(p1, s1l));
+        }
+        return s2.toString();
+	}       
+       
+    /**
+     * 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 (Object statistic : statistics) {
+		Statistic s = (Statistic) statistic;
+		elem.appendChild(s.toXML(doc));
+	  }
+
+	    // create and load querySelectSet
+	    elem = doc.createElement("querySelectSet");
+	    query.appendChild(elem);
+
+	  for (Object aSelectElementSet : selectElementSet) {
+		QueryElement queryElement = (QueryElement) aSelectElementSet;
+		elem.appendChild(queryElement.toXML(doc));
+	  }
+
+	    // create and load queryFromSet
+	    elem = doc.createElement("queryFromSet");
+	    query.appendChild(elem);
+
+	  for (Object aFromElementSet : fromElementSet) {
+		QueryElement queryElement = (QueryElement) aFromElementSet;
+		elem.appendChild(queryElement.toXML(doc));
+	  }
+
+	    // create and load queryWhereSet
+	    elem = doc.createElement("queryWhereSet");
+	    query.appendChild(elem);
+	  for (Object aWhereElementSet : whereElementSet) {
+		QueryElement queryElement = (QueryElement) aWhereElementSet;
+		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);
+				}
+			}
+                    }
+                }
+            }
+	}
+
+    /**
+     * 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");            
+        }
+	}
+
+    /**
+     * 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 ignored) {}
+		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")) {
+			StringBuilder expr = new StringBuilder();
+			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]));
+			StringBuilder str = new StringBuilder();
+			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;
+}

http://git-wip-us.apache.org/repos/asf/oodt/blob/4066b63b/webapp/fmprod/src/main/java/org/apache/oodt/xmlquery/activity/QueryConstructed.java
----------------------------------------------------------------------
diff --git a/webapp/fmprod/src/main/java/org/apache/oodt/xmlquery/activity/QueryConstructed.java b/webapp/fmprod/src/main/java/org/apache/oodt/xmlquery/activity/QueryConstructed.java
new file mode 100755
index 0000000..4598966
--- /dev/null
+++ b/webapp/fmprod/src/main/java/org/apache/oodt/xmlquery/activity/QueryConstructed.java
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.xmlquery.activity;
+
+import org.apache.oodt.commons.activity.Incident;
+
+public class QueryConstructed extends Incident {}

http://git-wip-us.apache.org/repos/asf/oodt/blob/4066b63b/webapp/fmprod/src/main/java/org/apache/oodt/xmlquery/activity/ResultsReceived.java
----------------------------------------------------------------------
diff --git a/webapp/fmprod/src/main/java/org/apache/oodt/xmlquery/activity/ResultsReceived.java b/webapp/fmprod/src/main/java/org/apache/oodt/xmlquery/activity/ResultsReceived.java
new file mode 100755
index 0000000..0c5616d
--- /dev/null
+++ b/webapp/fmprod/src/main/java/org/apache/oodt/xmlquery/activity/ResultsReceived.java
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+
+
+package org.apache.oodt.xmlquery.activity;
+
+import org.apache.oodt.commons.activity.Incident;
+
+public class ResultsReceived extends Incident {}

http://git-wip-us.apache.org/repos/asf/oodt/blob/4066b63b/webapp/fmprod/src/main/java/org/apache/oodt/xmlquery/package.html
----------------------------------------------------------------------
diff --git a/webapp/fmprod/src/main/java/org/apache/oodt/xmlquery/package.html b/webapp/fmprod/src/main/java/org/apache/oodt/xmlquery/package.html
new file mode 100755
index 0000000..5d3b494
--- /dev/null
+++ b/webapp/fmprod/src/main/java/org/apache/oodt/xmlquery/package.html
@@ -0,0 +1,26 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
+<!--
+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.
+-->
+<html>
+  <head>
+    <title>JPL OODT XML-based Query/Results
+    </title>
+  </head>
+  <body>
+    <p>Classes to support XML-based representation of queries and
+      their results.
+    </p>
+  </body>
+</html>

http://git-wip-us.apache.org/repos/asf/oodt/blob/4066b63b/webapp/fmprod/src/site/resources/images/delegation.png
----------------------------------------------------------------------
diff --git a/webapp/fmprod/src/site/resources/images/delegation.png b/webapp/fmprod/src/site/resources/images/delegation.png
new file mode 100644
index 0000000..aea86e3
Binary files /dev/null and b/webapp/fmprod/src/site/resources/images/delegation.png differ

http://git-wip-us.apache.org/repos/asf/oodt/blob/4066b63b/webapp/fmprod/src/site/resources/images/delegation.psd
----------------------------------------------------------------------
diff --git a/webapp/fmprod/src/site/resources/images/delegation.psd b/webapp/fmprod/src/site/resources/images/delegation.psd
new file mode 100644
index 0000000..9b74dca
Binary files /dev/null and b/webapp/fmprod/src/site/resources/images/delegation.psd differ

http://git-wip-us.apache.org/repos/asf/oodt/blob/4066b63b/webapp/fmprod/src/site/resources/images/edm-query.jpg
----------------------------------------------------------------------
diff --git a/webapp/fmprod/src/site/resources/images/edm-query.jpg b/webapp/fmprod/src/site/resources/images/edm-query.jpg
new file mode 100755
index 0000000..f6b5829
Binary files /dev/null and b/webapp/fmprod/src/site/resources/images/edm-query.jpg differ

http://git-wip-us.apache.org/repos/asf/oodt/blob/4066b63b/webapp/fmprod/src/site/resources/images/grid-product.jpg
----------------------------------------------------------------------
diff --git a/webapp/fmprod/src/site/resources/images/grid-product.jpg b/webapp/fmprod/src/site/resources/images/grid-product.jpg
new file mode 100644
index 0000000..7b1126e
Binary files /dev/null and b/webapp/fmprod/src/site/resources/images/grid-product.jpg differ

http://git-wip-us.apache.org/repos/asf/oodt/blob/4066b63b/webapp/fmprod/src/site/resources/images/large-stack.png
----------------------------------------------------------------------
diff --git a/webapp/fmprod/src/site/resources/images/large-stack.png b/webapp/fmprod/src/site/resources/images/large-stack.png
new file mode 100755
index 0000000..4bdcf53
Binary files /dev/null and b/webapp/fmprod/src/site/resources/images/large-stack.png differ

http://git-wip-us.apache.org/repos/asf/oodt/blob/4066b63b/webapp/fmprod/src/site/resources/images/large-stack.psd
----------------------------------------------------------------------
diff --git a/webapp/fmprod/src/site/resources/images/large-stack.psd b/webapp/fmprod/src/site/resources/images/large-stack.psd
new file mode 100755
index 0000000..caa6be9
Binary files /dev/null and b/webapp/fmprod/src/site/resources/images/large-stack.psd differ

http://git-wip-us.apache.org/repos/asf/oodt/blob/4066b63b/webapp/fmprod/src/site/resources/images/results.png
----------------------------------------------------------------------
diff --git a/webapp/fmprod/src/site/resources/images/results.png b/webapp/fmprod/src/site/resources/images/results.png
new file mode 100755
index 0000000..eef63e2
Binary files /dev/null and b/webapp/fmprod/src/site/resources/images/results.png differ

http://git-wip-us.apache.org/repos/asf/oodt/blob/4066b63b/webapp/fmprod/src/site/resources/images/results.psd
----------------------------------------------------------------------
diff --git a/webapp/fmprod/src/site/resources/images/results.psd b/webapp/fmprod/src/site/resources/images/results.psd
new file mode 100755
index 0000000..7e8476c
Binary files /dev/null and b/webapp/fmprod/src/site/resources/images/results.psd differ

http://git-wip-us.apache.org/repos/asf/oodt/blob/4066b63b/webapp/fmprod/src/site/resources/images/small-stack.png
----------------------------------------------------------------------
diff --git a/webapp/fmprod/src/site/resources/images/small-stack.png b/webapp/fmprod/src/site/resources/images/small-stack.png
new file mode 100755
index 0000000..d3604ef
Binary files /dev/null and b/webapp/fmprod/src/site/resources/images/small-stack.png differ

http://git-wip-us.apache.org/repos/asf/oodt/blob/4066b63b/webapp/fmprod/src/site/resources/images/small-stack.psd
----------------------------------------------------------------------
diff --git a/webapp/fmprod/src/site/resources/images/small-stack.psd b/webapp/fmprod/src/site/resources/images/small-stack.psd
new file mode 100755
index 0000000..d13ac6f
Binary files /dev/null and b/webapp/fmprod/src/site/resources/images/small-stack.psd differ

http://git-wip-us.apache.org/repos/asf/oodt/blob/4066b63b/webapp/fmprod/src/site/resources/images/xmlquery.png
----------------------------------------------------------------------
diff --git a/webapp/fmprod/src/site/resources/images/xmlquery.png b/webapp/fmprod/src/site/resources/images/xmlquery.png
new file mode 100755
index 0000000..189feb6
Binary files /dev/null and b/webapp/fmprod/src/site/resources/images/xmlquery.png differ

http://git-wip-us.apache.org/repos/asf/oodt/blob/4066b63b/webapp/fmprod/src/site/resources/images/xmlquery.psd
----------------------------------------------------------------------
diff --git a/webapp/fmprod/src/site/resources/images/xmlquery.psd b/webapp/fmprod/src/site/resources/images/xmlquery.psd
new file mode 100755
index 0000000..cce0220
Binary files /dev/null and b/webapp/fmprod/src/site/resources/images/xmlquery.psd differ

http://git-wip-us.apache.org/repos/asf/oodt/blob/4066b63b/webapp/fmprod/src/site/site.xml
----------------------------------------------------------------------
diff --git a/webapp/fmprod/src/site/site.xml b/webapp/fmprod/src/site/site.xml
new file mode 100644
index 0000000..2184b8d
--- /dev/null
+++ b/webapp/fmprod/src/site/site.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+
+<project name="Query Expression">
+
+  <body>
+    <links>
+      <item name="OODT" href="../oodt-site/"/>
+    </links>
+
+    <menu ref="reports" inherit="bottom"/>
+    <menu name="User's Guide">
+      <item name="Tutorial" href="tutorial/"/>
+      <item name="DIS-Style Query" href="disquery/"/>
+      <item name="Query Servlet" href="servlet/"/>
+    </menu>
+  </body>
+</project>

http://git-wip-us.apache.org/repos/asf/oodt/blob/4066b63b/webapp/fmprod/src/site/xdoc/disquery/index.xml
----------------------------------------------------------------------
diff --git a/webapp/fmprod/src/site/xdoc/disquery/index.xml b/webapp/fmprod/src/site/xdoc/disquery/index.xml
new file mode 100755
index 0000000..a9ddf49
--- /dev/null
+++ b/webapp/fmprod/src/site/xdoc/disquery/index.xml
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<document>
+
+  <properties>
+    <title>DIS-Style Query</title>
+    <author email="Sean.Hardman@jpl.nasa.gov">Sean Hardman</author>
+  </properties>
+
+  <body>
+    <section name="DIS-Style Query">
+      <p>A DIS-Style Query is a query using triples linked in a logical expression. Each triple is in the format of (element, relation, literal). The element portion of the triple may be any named data element recognized as a queryable attribute by the target of the query. The relation portion of the triple may contain any of the relational operators from the table below. The literal portion of the triple is the element value to be compared. Multiple sets of triples may be joined using any of the logical operators from the table below. Note that elements or literals containing spaces must be quoted. Also note that case sensitivity and support for the various operators is subject to the capabilities offered by the target of the query.
+      </p>
+
+      <p>The following table contains the supported relational operators:</p>
+
+      <table>
+      <tr>
+        <th colspan="2">Relational Operators</th>
+      </tr>
+      <tr>
+        <td>Equal</td> <td>=, EQ</td>
+      </tr>
+      <tr>
+        <td>Not Equal</td> <td>!=, NE</td>
+      </tr>
+      <tr>
+        <td>Less Than</td> <td>&lt;, LT</td>
+      </tr>
+      <tr>
+        <td>Less Than or Equal</td> <td>&lt;=, LE</td>
+      </tr>
+      <tr>
+        <td>Greater Than</td> <td>&gt;, GT</td>
+      </tr>
+      <tr>
+        <td>Greater Than or Equal</td> <td>&gt;=, GE</td>
+      </tr>
+      <tr>
+        <td>Contains</td> <td>LIKE</td>
+      </tr>
+      <tr>
+        <td>Does Not Contain</td> <td>NOTLIKE</td>
+      </tr>
+      <tr>
+        <td>Is Null</td> <td>IS</td>
+      </tr>
+      <tr>
+        <td>Is Not Null</td> <td>ISNOT</td>
+      </tr>
+      </table>
+
+      <p>The following table contains the supported logical operators:</p>
+
+      <table>
+      <tr>
+        <th colspan="2">Logical Operators</th>
+      </tr>
+      <tr>
+        <td>And</td> <td>AND, &amp;</td>
+      </tr>
+      <tr>
+        <td>Or</td> <td>OR, |</td>
+      </tr>
+      <tr>
+        <td>Not</td> <td>NOT, !</td>
+      </tr>
+      </table>
+
+      <p>The following are examples of DIS-Style queries:</p>
+
+      <ul>
+      <li>Title LIKE EDM AND Creator = "Sean Hardman"
+      <p>This query will return all objects where the <i>Title</i> element contains the text "EDM" and the <i>Creator</i> element is equal to "Sean Hardman".</p>
+      </li>
+
+      <li>Title LIKE EDM AND Creator = "Sean Hardman" OR Title LIKE OODT AND Creator = "Sean Kelly"
+      <p>This query will return all objects where either the first set of criteria matches or the second set of criteria matches.</p>
+      </li>
+
+      <li>Temperature &gt; 32 AND Temperature &lt; 212
+      <p>This query will return all objects where the <i>Temperature</i> element value is between the specified range.</p>
+      </li>
+
+      <li>Subject IS NULL
+      <p>This query will return all objects where the <i>Subject</i> element has no associated value. When using the IS and ISNOT relational operators, the literal must be "NULL" or "null".</p>
+      </li>
+      </ul>
+    </section>
+  </body>
+</document>

http://git-wip-us.apache.org/repos/asf/oodt/blob/4066b63b/webapp/fmprod/src/site/xdoc/servlet/index.xml
----------------------------------------------------------------------
diff --git a/webapp/fmprod/src/site/xdoc/servlet/index.xml b/webapp/fmprod/src/site/xdoc/servlet/index.xml
new file mode 100644
index 0000000..d266e1a
--- /dev/null
+++ b/webapp/fmprod/src/site/xdoc/servlet/index.xml
@@ -0,0 +1,640 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements.  See the NOTICE.txt 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.
+-->
+<document>
+
+  <properties>
+    <title>Query Servlet</title>
+    <author email="Sean.Kelly@jpl.nasa.gov">Sean Kelly</author>
+  </properties>
+
+  <body>
+    <section name="Query Servlet">
+
+      <p>The query servlet enables you to inject generic queries into
+	the OODT framework using HTTP.  This enables you to query for
+	profiles and products without requiring a Java, RMI, or CORBA
+   enabled application.
+      </p>
+    </section>
+
+    <section name="Requirements">
+
+      <p>The query servlet accepts various parameters for a query and
+	turns them into an <code>XMLQuery</code> object.  It uses this
+	object internally to send the query around the network and to
+	gather results.  It then returns a <code>text/xml</code>
+	representation of the <code>XMLQuery</code> object (for product
+	queries) or a <code>text/xml</code> representation of all matching
+	profiles (for profile queries).
+      </p>
+
+      <p><strong>That means you must be able to process XML</strong> in
+	order to use the query servlet.  Luckily, this isn't an onerous
+	restriction, as many languages are more than capable of doing so.
+      </p>
+
+      <p>For more details, view the Javadocs for the
+	<code>jpl.oodt.servlets.QueryServlet</code> class.</p>
+    </section>
+
+    <section name="Using the Query Servlet">
+
+      <p>In order to use the query servlet, you need to specify three parameters:
+      </p>
+
+      <ol>
+	<li>You need to know the <strong>type of the query</strong> you
+	  want to make.  You will use a string value of
+	  <code>profile</code> to make a profile query, and
+	  <code>product</code> to make a product query.  You specify
+	  your choice in a parameter named <code>type</code>.
+	</li>
+
+	<li>You need to know the <strong>name of the object</strong>
+	  that should receive the query.  This takes the form of
+	  <code>urn:eda:<var>protocol</var>:<var>name</var></code> such
+	  as <code>urn:eda:corba:PDS.Profile</code> or
+	  <code>urn:eda:rmi:NCI-ImageServer</code>.  You specify the
+	  object name in a parameter named <code>object</code>.
+	</li>
+
+	<li>You need <strong>the actual query</strong> you want to
+	  send.  You can express this in two ways:
+
+	  <ol>
+	    <li>As an <strong>keyword query expression</strong> like
+	      <code>TARGET_NAME = MARS</code>.  You specify the
+	      query expression in a parameter named
+	      <code>keywordQuery</code>.
+	    </li>
+
+	    <li>As a <strong>text serialized <code>XMLQuery</code>
+		object</strong>.  You specify the XML document in a
+	      parameter named <code>query</code>.
+	    </li>
+	  </ol>
+
+	  <p>Using the latter enables you to fully specify all sorts of
+	    parameters in the query.  The former, though, is far
+	    easier to use.
+	  </p>
+
+	</li>
+      </ol>
+
+      <p>You then URL encode parameters' values and make either an HTTP
+	<code>GET</code> or <code>POST</code> request to the query
+	servlet.  If all goes according to plan, the servlet will execute
+	the query and return to you a <code>text/xml</code> document
+	describing the results.  You can then manipulate that document as
+	you see fit.  For profile queries, the return value is a
+	<code>&lt;profiles&gt;</code> document with zero or more matching
+	profiles.  For product queries, it's a <code>&lt;query&gt;</code>
+
+	document with the original <code>XMLQuery</code> object with any
+	product results in the <code>&lt;queryResults&gt;</code> section.
+      </p>
+
+    </section>
+
+    <section name="Query Examples">
+
+      <p>Let's look at a couple of concrete examples.  In the first
+	example, we'll run a profile query against some planetary data
+	servers; the second example will run a product query for cancer
+	biomarkers.
+      </p>
+
+      <subsection name="Planetary Profile Query">
+
+	<p>Suppose you wanted to know what PDS product servers supported
+	  the query element <code>ONLINE_FILE_SPECIFICATION_NAME</code>.
+	  You could pass that element to the PDS system profile server named
+	  <code>urn:eda:rmi:PDS.System.Profile</code> using the query
+	  servlet at
+	  <code>http://starbrite.jpl.nasa.gov/servlet/jpl.oodt.servlets.QueryServlet</code>.
+	  You can formulate the HTTP <code>GET</code> request in a URL as
+	  follows:
+	</p>
+
+	<p><code><a href="http://starbrite.jpl.nasa.gov/servlet/jpl.oodt.servlets.QueryServlet?object=urn:eda:rmi:PDS.System.Profile&amp;type=profile&amp;keywordQuery=ONLINE_FILE_SPECIFICATION_NAME+%3D+ANY">http://starbrite.jpl.nasa.gov/servlet/jpl.oodt.servlets.QueryServlet?<br/>  object=urn:eda:rmi:PDS.System.Profile&amp;<br/>  type=profile&amp;<br/>  keywordQuery=ONLINE_FILE_SPECIFICATION_NAME+%3D+ANY</a></code></p>
+
+	<p>Note that we've broken this URL into multiple lines for
+	  readability.  There should be no linebreaks in a real URL.  Note
+	  the following about this URL:
+	</p>
+
+	<ul>
+	  <li>The question-mark separates the request URI from its
+	    parameters.
+	  </li>
+
+	  <li>The parameters may come in any order.</li>
+
+	  <li>The <code>object</code> parameter names the target of the
+	    query; in this case, the RMI product server named
+	    <code>urn:eda:rmi:PDS.System.Profile</code>.
+	  </li>
+
+	  <li>The <code>type</code> parameter specifies that we're doing a
+	    <em>profile search</em>.</li>
+
+	  <li>The <code>keywordQuery</code> parameter identifies the query
+	    expression.  Note the URL encoding: the spaces become
+	    <code>+</code> symbols, and the equals sign become
+	    <code>%3D</code>.
+	  </li>
+	</ul>
+
+	<p>The response from such a query is an XML document; this XML
+	  document describes matching profiles and may take a form such as
+	  the following:</p>
+
+<source>
+&lt;?xml version="1.0" encoding="UTF-8"?&gt;
+&lt;!DOCTYPE profiles PUBLIC "-//JPL//DTD OODT Profile 1.1//EN"
+"http://starshine.jpl.nasa.gov:80/dtd/prof.dtd"&gt;
+
+&lt;profiles&gt;
+  &lt;profile&gt;
+    &lt;profAttributes&gt;
+      &lt;profId&gt;1.3.6.1.4.1.1306.2.1.1.7&lt;/profId&gt;
+      &lt;profType&gt;profile&lt;/profType&gt;
+      &lt;profStatusId&gt;active&lt;/profStatusId&gt;
+    &lt;/profAttributes&gt;
+    &lt;resAttributes&gt;
+      &lt;Identifier&gt;PDS.ASU.Product&lt;/Identifier&gt;
+      &lt;Title&gt;
+      PDS Arizona State University Data Node Product Server
+      &lt;/Title&gt;
+      &lt;Format&gt;text/html&lt;/Format&gt;
+      &lt;resContext&gt;NASA.PDS.ASU&lt;/resContext&gt;
+      &lt;resClass&gt;system.productServer&lt;/resClass&gt;
+      &lt;resLocation&gt;
+      http://starbrite.jpl.nasa.gov/servlet/
+      jpl.oodt.servlets.ProductServlet?object=PDS.ASU.Product
+      &lt;/resLocation&gt;
+      &lt;resLocation&gt;urn:eda:rmi:PDS.ASU.Product&lt;/resLocation&gt;
+    &lt;/resAttributes&gt;
+    &lt;profElement&gt;
+      &lt;elemName&gt;ONLINE_FILE_SPECIFICATION_NAME&lt;/elemName&gt;
+      &lt;elemType&gt;CHARACTER&lt;/elemType&gt;
+      &lt;elemEnumFlag&gt;T&lt;/elemEnumFlag&gt;
+      &lt;elemMaxOccurrence&gt;0&lt;/elemMaxOccurrence&gt;
+    &lt;/profElement&gt;
+    &lt;profElement&gt;
+      &lt;elemName&gt;RETURN_TYPE&lt;/elemName&gt;
+      &lt;elemType&gt;CHARACTER&lt;/elemType&gt;
+      &lt;elemEnumFlag&gt;T&lt;/elemEnumFlag&gt;
+      &lt;elemValue&gt;PDS_ZIP&lt;/elemValue&gt;
+      &lt;elemValue&gt;PDS_LABEL&lt;/elemValue&gt;
+      &lt;elemValue&gt;RAW&lt;/elemValue&gt;
+      &lt;elemMaxOccurrence&gt;0&lt;/elemMaxOccurrence&gt;
+    &lt;/profElement&gt;
+  &lt;/profile&gt;
+
+  &lt;profile&gt;
+    &lt;profAttributes&gt;
+      &lt;profId&gt;1.3.6.1.4.1.1306.2.1.1.6&lt;/profId&gt;
+      &lt;profType&gt;profile&lt;/profType&gt;
+      &lt;profStatusId&gt;active&lt;/profStatusId&gt;
+    &lt;/profAttributes&gt;
+    &lt;resAttributes&gt;
+      &lt;Identifier&gt;PDS.RS.Product&lt;/Identifier&gt;
+      &lt;Title&gt;PDS Radio Science Product Server&lt;/Title&gt;
+      &lt;Format&gt;text/html&lt;/Format&gt;
+      &lt;resContext&gt;NASA.PDS.RS&lt;/resContext&gt;
+      &lt;resClass&gt;system.productServer&lt;/resClass&gt;
+      &lt;resLocation&gt;
+      http://starbrite.jpl.nasa.gov/servlet/
+      jpl.oodt.servlets.ProductServlet?object=PDS.RS.Product
+      &lt;/resLocation&gt;
+      &lt;resLocation&gt;urn:eda:rmi:PDS.RS.Product&lt;/resLocation&gt;
+    &lt;/resAttributes&gt;
+    &lt;profElement&gt;
+      &lt;elemName&gt;ONLINE_FILE_SPECIFICATION_NAME&lt;/elemName&gt;
+      &lt;elemType&gt;CHARACTER&lt;/elemType&gt;
+      &lt;elemEnumFlag&gt;T&lt;/elemEnumFlag&gt;
+      &lt;elemMaxOccurrence&gt;0&lt;/elemMaxOccurrence&gt;
+    &lt;/profElement&gt;
+    &lt;profElement&gt;
+      &lt;elemName&gt;RETURN_TYPE&lt;/elemName&gt;
+      &lt;elemType&gt;CHARACTER&lt;/elemType&gt;
+      &lt;elemEnumFlag&gt;T&lt;/elemEnumFlag&gt;
+      &lt;elemValue&gt;PDS_ZIP&lt;/elemValue&gt;
+      &lt;elemValue&gt;PDS_LABEL&lt;/elemValue&gt;
+      &lt;elemValue&gt;RAW&lt;/elemValue&gt;
+      &lt;elemMaxOccurrence&gt;0&lt;/elemMaxOccurrence&gt;
+    &lt;/profElement&gt;
+  &lt;/profile&gt;
+
+  &lt;profile&gt;
+    &lt;profAttributes&gt;
+      &lt;profId&gt;1.3.6.1.4.1.1306.2.1.1.4&lt;/profId&gt;
+      &lt;profType&gt;profile&lt;/profType&gt;
+      &lt;profStatusId&gt;active&lt;/profStatusId&gt;
+    &lt;/profAttributes&gt;
+    &lt;resAttributes&gt;
+      &lt;Identifier&gt;PDS.Atmos.Product&lt;/Identifier&gt;
+      &lt;Title&gt;PDS Atmospheres Product Server&lt;/Title&gt;
+      &lt;Format&gt;text/html&lt;/Format&gt;
+      &lt;resContext&gt;NASA.PDS.Atmos&lt;/resContext&gt;
+      &lt;resClass&gt;system.productServer&lt;/resClass&gt;
+      &lt;resLocation&gt;
+      http://starbrite.jpl.nasa.gov/servlet/
+      jpl.oodt.servlets.ProductServlet?object=PDS.Atmos.Product
+      &lt;/resLocation&gt;
+      &lt;resLocation&gt;urn:eda:rmi:PDS.Atmos.Product&lt;/resLocation&gt;
+    &lt;/resAttributes&gt;
+    &lt;profElement&gt;
+      &lt;elemName&gt;ONLINE_FILE_SPECIFICATION_NAME&lt;/elemName&gt;
+      &lt;elemType&gt;CHARACTER&lt;/elemType&gt;
+      &lt;elemEnumFlag&gt;T&lt;/elemEnumFlag&gt;
+      &lt;elemMaxOccurrence&gt;0&lt;/elemMaxOccurrence&gt;
+    &lt;/profElement&gt;
+    &lt;profElement&gt;
+      &lt;elemName&gt;RETURN_TYPE&lt;/elemName&gt;
+      &lt;elemType&gt;CHARACTER&lt;/elemType&gt;
+      &lt;elemEnumFlag&gt;T&lt;/elemEnumFlag&gt;
+      &lt;elemValue&gt;PDS_ZIP&lt;/elemValue&gt;
+      &lt;elemValue&gt;PDS_LABEL&lt;/elemValue&gt;
+      &lt;elemValue&gt;RAW&lt;/elemValue&gt;
+      &lt;elemMaxOccurrence&gt;0&lt;/elemMaxOccurrence&gt;
+    &lt;/profElement&gt;
+  &lt;/profile&gt;
+
+  &lt;profile&gt;
+    &lt;profAttributes&gt;
+      &lt;profId&gt;1.3.6.1.4.1.1306.2.1.1.3&lt;/profId&gt;
+      &lt;profType&gt;profile&lt;/profType&gt;
+      &lt;profStatusId&gt;active&lt;/profStatusId&gt;
+    &lt;/profAttributes&gt;
+    &lt;resAttributes&gt;
+      &lt;Identifier&gt;PDS.NAIF.Product&lt;/Identifier&gt;
+      &lt;Title&gt;PDS NAIF Product Server&lt;/Title&gt;
+      &lt;Format&gt;text/html&lt;/Format&gt;
+      &lt;resContext&gt;NASA.PDS.NAIF&lt;/resContext&gt;
+      &lt;resClass&gt;system.productServer&lt;/resClass&gt;
+      &lt;resLocation&gt;
+      http://starbrite.jpl.nasa.gov/servlet/
+      jpl.oodt.servlets.ProductServlet?object=PDS.NAIF.Product
+      &lt;/resLocation&gt;
+      &lt;resLocation&gt;urn:eda:rmi:PDS.NAIF.Product&lt;/resLocation&gt;
+    &lt;/resAttributes&gt;
+    &lt;profElement&gt;
+      &lt;elemName&gt;ONLINE_FILE_SPECIFICATION_NAME&lt;/elemName&gt;
+      &lt;elemType&gt;CHARACTER&lt;/elemType&gt;
+      &lt;elemEnumFlag&gt;T&lt;/elemEnumFlag&gt;
+      &lt;elemMaxOccurrence&gt;0&lt;/elemMaxOccurrence&gt;
+    &lt;/profElement&gt;
+    &lt;profElement&gt;
+      &lt;elemName&gt;RETURN_TYPE&lt;/elemName&gt;
+      &lt;elemType&gt;CHARACTER&lt;/elemType&gt;
+      &lt;elemEnumFlag&gt;T&lt;/elemEnumFlag&gt;
+      &lt;elemValue&gt;PDS_ZIP&lt;/elemValue&gt;
+      &lt;elemValue&gt;PDS_LABEL&lt;/elemValue&gt;
+      &lt;elemValue&gt;RAW&lt;/elemValue&gt;
+      &lt;elemMaxOccurrence&gt;0&lt;/elemMaxOccurrence&gt;
+    &lt;/profElement&gt;
+  &lt;/profile&gt;
+
+  &lt;profile&gt;
+    &lt;profAttributes&gt;
+      &lt;profId&gt;1.3.6.1.4.1.1306.2.1.1.2&lt;/profId&gt;
+      &lt;profType&gt;profile&lt;/profType&gt;
+      &lt;profStatusId&gt;active&lt;/profStatusId&gt;
+    &lt;/profAttributes&gt;
+    &lt;resAttributes&gt;
+      &lt;Identifier&gt;PDS.Geo.Product&lt;/Identifier&gt;
+      &lt;Title&gt;PDS Geosciences Product Server&lt;/Title&gt;
+      &lt;Format&gt;text/html&lt;/Format&gt;
+      &lt;resContext&gt;NASA.PDS.GEO&lt;/resContext&gt;
+      &lt;resClass&gt;system.productServer&lt;/resClass&gt;
+      &lt;resLocation&gt;
+      http://starbrite.jpl.nasa.gov/servlet/
+      jpl.oodt.servlets.ProductServlet?object=PDS.Geo.Product
+      &lt;/resLocation&gt;
+      &lt;resLocation&gt;urn:eda:rmi:PDS.Geo.Product&lt;/resLocation&gt;
+    &lt;/resAttributes&gt;
+    &lt;profElement&gt;
+      &lt;elemName&gt;ONLINE_FILE_SPECIFICATION_NAME&lt;/elemName&gt;
+      &lt;elemType&gt;CHARACTER&lt;/elemType&gt;
+      &lt;elemEnumFlag&gt;T&lt;/elemEnumFlag&gt;
+      &lt;elemMaxOccurrence&gt;0&lt;/elemMaxOccurrence&gt;
+    &lt;/profElement&gt;
+    &lt;profElement&gt;
+      &lt;elemName&gt;RETURN_TYPE&lt;/elemName&gt;
+      &lt;elemType&gt;CHARACTER&lt;/elemType&gt;
+      &lt;elemEnumFlag&gt;T&lt;/elemEnumFlag&gt;
+      &lt;elemValue&gt;PDS_ZIP&lt;/elemValue&gt;
+      &lt;elemValue&gt;PDS_LABEL&lt;/elemValue&gt;
+      &lt;elemValue&gt;RAW&lt;/elemValue&gt;
+      &lt;elemMaxOccurrence&gt;0&lt;/elemMaxOccurrence&gt;
+    &lt;/profElement&gt;
+  &lt;/profile&gt;
+
+  &lt;profile&gt;
+    &lt;profAttributes&gt;
+      &lt;profId&gt;1.3.6.1.4.1.1306.2.1.1.1&lt;/profId&gt;
+      &lt;profType&gt;profile&lt;/profType&gt;
+      &lt;profStatusId&gt;active&lt;/profStatusId&gt;
+    &lt;/profAttributes&gt;
+    &lt;resAttributes&gt;
+      &lt;Identifier&gt;PDS.CN.Product&lt;/Identifier&gt;
+      &lt;Title&gt;PDS Central Node Archive Product Server&lt;/Title&gt;
+      &lt;Format&gt;text/html&lt;/Format&gt;
+      &lt;resContext&gt;NASA.PDS.CN&lt;/resContext&gt;
+      &lt;resClass&gt;system.productServer&lt;/resClass&gt;
+      &lt;resLocation&gt;
+      http://starbrite.jpl.nasa.gov/servlet/
+      jpl.oodt.servlets.ProductServlet?object=PDS.CN.Product
+      &lt;/resLocation&gt;
+      &lt;resLocation&gt;urn:eda:rmi:PDS.CN.Product&lt;/resLocation&gt;
+    &lt;/resAttributes&gt;
+    &lt;profElement&gt;
+      &lt;elemName&gt;ONLINE_FILE_SPECIFICATION_NAME&lt;/elemName&gt;
+      &lt;elemType&gt;CHARACTER&lt;/elemType&gt;
+      &lt;elemEnumFlag&gt;T&lt;/elemEnumFlag&gt;
+      &lt;elemMaxOccurrence&gt;0&lt;/elemMaxOccurrence&gt;
+    &lt;/profElement&gt;
+    &lt;profElement&gt;
+      &lt;elemName&gt;RETURN_TYPE&lt;/elemName&gt;
+      &lt;elemType&gt;CHARACTER&lt;/elemType&gt;
+      &lt;elemEnumFlag&gt;T&lt;/elemEnumFlag&gt;
+      &lt;elemValue&gt;PDS_ZIP&lt;/elemValue&gt;
+      &lt;elemValue&gt;PDS_LABEL&lt;/elemValue&gt;
+      &lt;elemValue&gt;RAW&lt;/elemValue&gt;
+      &lt;elemMaxOccurrence&gt;0&lt;/elemMaxOccurrence&gt;
+    &lt;/profElement&gt;
+  &lt;/profile&gt;
+
+  &lt;profile&gt;
+    &lt;profAttributes&gt;
+      &lt;profId&gt;1.3.6.1.4.1.1306.2.1.1.10&lt;/profId&gt;
+      &lt;profType&gt;profile&lt;/profType&gt;
+      &lt;profStatusId&gt;active&lt;/profStatusId&gt;
+    &lt;/profAttributes&gt;
+    &lt;resAttributes&gt;
+      &lt;Identifier&gt;PDS.CN.Profile&lt;/Identifier&gt;
+      &lt;Title&gt;PDS.CN.Profile&lt;/Title&gt;
+      &lt;Format&gt;text/html&lt;/Format&gt;
+      &lt;resContext&gt;NASA.PDS.CN&lt;/resContext&gt;
+      &lt;resClass&gt;system.productServer&lt;/resClass&gt;
+      &lt;resLocation&gt;
+      http://starbrite.jpl.nasa.gov/servlet/
+      jpl.oodt.servlets.ProductServlet?object=PDS.CN.Profile
+      &lt;/resLocation&gt;
+      &lt;resLocation&gt;urn:eda:rmi:PDS.CN.Profile&lt;/resLocation&gt;
+    &lt;/resAttributes&gt;
+    &lt;profElement&gt;
+      &lt;elemName&gt;ONLINE_FILE_SPECIFICATION_NAME&lt;/elemName&gt;
+      &lt;elemType&gt;CHARACTER&lt;/elemType&gt;
+      &lt;elemEnumFlag&gt;T&lt;/elemEnumFlag&gt;
+      &lt;elemMaxOccurrence&gt;0&lt;/elemMaxOccurrence&gt;
+    &lt;/profElement&gt;
+    &lt;profElement&gt;
+      &lt;elemName&gt;RETURN_TYPE&lt;/elemName&gt;
+      &lt;elemType&gt;CHARACTER&lt;/elemType&gt;
+      &lt;elemEnumFlag&gt;T&lt;/elemEnumFlag&gt;
+      &lt;elemValue&gt;PDS_ZIP&lt;/elemValue&gt;
+      &lt;elemValue&gt;PDS_LABEL&lt;/elemValue&gt;
+      &lt;elemValue&gt;RAW&lt;/elemValue&gt;
+      &lt;elemMaxOccurrence&gt;0&lt;/elemMaxOccurrence&gt;
+    &lt;/profElement&gt;
+  &lt;/profile&gt;
+
+  &lt;profile&gt;
+    &lt;profAttributes&gt;
+      &lt;profId&gt;1.3.6.1.4.1.1306.2.1.1.9&lt;/profId&gt;
+      &lt;profType&gt;profile&lt;/profType&gt;
+      &lt;profStatusId&gt;active&lt;/profStatusId&gt;
+    &lt;/profAttributes&gt;
+    &lt;resAttributes&gt;
+      &lt;Identifier&gt;PDS.PPI.Product&lt;/Identifier&gt;
+      &lt;Title&gt;
+      PDS Planetary Plasma Interactions Product Server
+      &lt;/Title&gt;
+      &lt;Format&gt;text/html&lt;/Format&gt;
+      &lt;resContext&gt;NASA.PDS.PPI&lt;/resContext&gt;
+      &lt;resClass&gt;system.productServer&lt;/resClass&gt;
+      &lt;resLocation&gt;
+      http://starbrite.jpl.nasa.gov/servlet/
+      jpl.oodt.servlets.ProductServlet?object=PDS.PPI.Product
+      &lt;/resLocation&gt;
+      &lt;resLocation&gt;urn:eda:rmi:PDS.PPI.Product&lt;/resLocation&gt;
+    &lt;/resAttributes&gt;
+    &lt;profElement&gt;
+      &lt;elemName&gt;ONLINE_FILE_SPECIFICATION_NAME&lt;/elemName&gt;
+      &lt;elemType&gt;CHARACTER&lt;/elemType&gt;
+      &lt;elemEnumFlag&gt;T&lt;/elemEnumFlag&gt;
+      &lt;elemMaxOccurrence&gt;0&lt;/elemMaxOccurrence&gt;
+    &lt;/profElement&gt;
+    &lt;profElement&gt;
+      &lt;elemName&gt;RETURN_TYPE&lt;/elemName&gt;
+      &lt;elemType&gt;CHARACTER&lt;/elemType&gt;
+      &lt;elemEnumFlag&gt;T&lt;/elemEnumFlag&gt;
+      &lt;elemValue&gt;PDS_ZIP&lt;/elemValue&gt;
+      &lt;elemValue&gt;PDS_LABEL&lt;/elemValue&gt;
+      &lt;elemValue&gt;RAW&lt;/elemValue&gt;
+      &lt;elemMaxOccurrence&gt;0&lt;/elemMaxOccurrence&gt;
+    &lt;/profElement&gt;
+  &lt;/profile&gt;
+
+  &lt;profile&gt;
+    &lt;profAttributes&gt;
+      &lt;profId&gt;1.3.6.1.4.1.1306.2.1.1.8&lt;/profId&gt;
+      &lt;profType&gt;profile&lt;/profType&gt;
+      &lt;profStatusId&gt;active&lt;/profStatusId&gt;
+    &lt;/profAttributes&gt;
+    &lt;resAttributes&gt;
+      &lt;Identifier&gt;PDS.Img.Product&lt;/Identifier&gt;
+      &lt;Title&gt;PDS Imaging Product Server&lt;/Title&gt;
+      &lt;Format&gt;text/html&lt;/Format&gt;
+      &lt;resContext&gt;NASA.PDS.Img&lt;/resContext&gt;
+      &lt;resClass&gt;system.productServer&lt;/resClass&gt;
+      &lt;resLocation&gt;
+      http://starbrite.jpl.nasa.gov/servlet/
+      jpl.oodt.servlets.ProductServlet?object=PDS.Img.Product
+      &lt;/resLocation&gt;
+      &lt;resLocation&gt;urn:eda:rmi:PDS.Img.Product&lt;/resLocation&gt;
+    &lt;/resAttributes&gt;
+    &lt;profElement&gt;
+      &lt;elemName&gt;ONLINE_FILE_SPECIFICATION_NAME&lt;/elemName&gt;
+      &lt;elemType&gt;CHARACTER&lt;/elemType&gt;
+      &lt;elemEnumFlag&gt;T&lt;/elemEnumFlag&gt;
+      &lt;elemMaxOccurrence&gt;0&lt;/elemMaxOccurrence&gt;
+    &lt;/profElement&gt;
+    &lt;profElement&gt;
+      &lt;elemName&gt;RETURN_TYPE&lt;/elemName&gt;
+      &lt;elemType&gt;CHARACTER&lt;/elemType&gt;
+      &lt;elemEnumFlag&gt;T&lt;/elemEnumFlag&gt;
+      &lt;elemValue&gt;PDS_ZIP&lt;/elemValue&gt;
+      &lt;elemValue&gt;PDS_LABEL&lt;/elemValue&gt;
+      &lt;elemValue&gt;RAW&lt;/elemValue&gt;
+      &lt;elemMaxOccurrence&gt;0&lt;/elemMaxOccurrence&gt;
+    &lt;/profElement&gt;
+  &lt;/profile&gt;
+&lt;/profiles&gt;
+</source>
+
+      </subsection>
+
+      <subsection name="Biomarker Product Query">
+
+	<p>Suppose you had a query servlet available at
+	  <code>http://pancreas/qs</code>, and you want to query the CORBA
+	  product server <code>urn:eda:corba:TissueBank</code> with the
+	  query expression <code>SeverityLevel = 3</code>.  You can
+	  formulate the entire <code>GET</code> request as the following
+	  URL:
+	</p>
+
+	<source>
+  http://pancreas/qs?
+  type=product&amp;
+  object=urn:eda:corba:TissueBank&amp;
+  keywordQuery=SeverityLevel+%3D+3
+   </source>
+
+	<p>(Again, we've broken the URL for readability.)  The result to
+	  this query could be an XML document like the following:
+	</p>
+
+<source>
+&lt;?xml version="1.0" encoding="UTF-8"?&gt;
+&lt;!DOCTYPE query PUBLIC "-//JPL//DTD OODT Query 1.0//EN"
+                       "http://pancreas/dtd/query.dtd"&gt;
+
+&lt;query&gt;
+  &lt;queryAttributes&gt;
+    &lt;queryId&gt;UNKNOWN&lt;/queryId&gt;
+    &lt;queryTitle&gt;UNKNOWN&lt;/queryTitle&gt;
+    &lt;queryDesc&gt;UNKNOWN&lt;/queryDesc&gt;
+    &lt;queryType&gt;QUERY&lt;/queryType&gt;
+    &lt;queryStatusId&gt;ACTIVE&lt;/queryStatusId&gt;
+    &lt;querySecurityType&gt;UNKNOWN&lt;/querySecurityType&gt;
+    &lt;queryRevisionNote&gt;
+    1999-12-12 JSH V1.0 Under Development
+    &lt;/queryRevisionNote&gt;
+    &lt;queryDataDictId&gt;UNKNOWN&lt;/queryDataDictId&gt;
+  &lt;/queryAttributes&gt;
+  &lt;queryResultModeId&gt;ATTRIBUTE&lt;/queryResultModeId&gt;
+  &lt;queryPropogationType&gt;BROADCAST&lt;/queryPropogationType&gt;
+  &lt;queryPropogationLevels&gt;N/A&lt;/queryPropogationLevels&gt;
+  &lt;queryMimeAccept&gt;*/*&lt;/queryMimeAccept&gt;
+  &lt;queryMaxResults&gt;100&lt;/queryMaxResults&gt;
+  &lt;queryResults&gt;0&lt;/queryResults&gt;
+  &lt;queryKWQString&gt;SeverityLevel = 3&lt;/queryKWQString&gt;
+  &lt;querySelectSet&gt;
+    &lt;queryElement&gt;
+      &lt;tokenRole&gt;LITERAL&lt;/tokenRole&gt;
+      &lt;tokenValue&gt;3&lt;/tokenValue&gt;
+    &lt;/queryElement&gt;
+    &lt;queryElement&gt;
+      &lt;tokenRole&gt;elemName&lt;/tokenRole&gt;
+      &lt;tokenValue&gt;SeverityLevel&lt;/tokenValue&gt;
+    &lt;/queryElement&gt;
+    &lt;queryElement&gt;
+      &lt;tokenRole&gt;RELOP&lt;/tokenRole&gt;
+      &lt;tokenValue&gt;EQ&lt;/tokenValue&gt;
+    &lt;/queryElement&gt;
+  &lt;/querySelectSet&gt;
+  &lt;queryFromSet/&gt;
+  &lt;queryWhereSet/&gt;
+  &lt;queryResultSet&gt;
+    &lt;resultElement&gt;
+      &lt;resultId&gt;1&lt;/resultId&gt;
+      &lt;resultMimeType&gt;text/plain&lt;/resultMimeType&gt;
+      &lt;profId&gt;TissueBank&lt;/profId&gt;
+      &lt;identifier/&gt;
+      &lt;resultHeader&gt;
+        &lt;headerElement&gt;
+          &lt;elemName&gt;UNKNOWN&lt;/elemName&gt;
+          &lt;elemType&gt;TEXT&lt;/elemType&gt;
+        &lt;/headerElement&gt;
+      &lt;/resultHeader&gt;
+      &lt;Resultvalue xml:space="preserve"&gt;
+      PatientIDs=[1,2,4,7,11,19,22]&lt;/resultValue&gt;
+    &lt;/resultElement&gt;
+  &lt;/queryResultSet&gt;
+&lt;/query&gt;
+</source>
+
+	<p>Instead of using the <code>keywordQuery</code> parameter, you
+	  can create your own <code>XMLQuery</code> document and pass it in
+	  as the <code>query</code> parameter instead.  The query document
+	  would look like this:
+	</p>
+
+    <source>
+&lt;?xml version="1.0" encoding="UTF-8"?&gt;
+&lt;!DOCTYPE query PUBLIC "-//JPL//DTD OODT Query 1.0//EN"
+                       "http://pancreas:80/dtd/query.dtd"&gt;
+
+&lt;query&gt;
+  &lt;queryAttributes&gt;
+    &lt;queryId&gt;expr1&lt;/queryId&gt;
+    &lt;queryTitle&gt;Command-line Expression Query&lt;/queryTitle&gt;
+    &lt;queryDesc&gt;
+    The expression for this query came from the command-line.
+    &lt;/queryDesc&gt;
+    &lt;queryType&gt;QUERY&lt;/queryType&gt;
+    &lt;queryStatusId&gt;ACTIVE&lt;/queryStatusId&gt;
+    &lt;querySecurityType&gt;UNKNOWN&lt;/querySecurityType&gt;
+    &lt;queryRevisionNote&gt;
+    1999-12-12 JSH V1.0 Under Development
+    &lt;/queryRevisionNote&gt;
+    &lt;queryDataDictId&gt;UNKNOWN&lt;/queryDataDictId&gt;
+  &lt;/queryAttributes&gt;
+  &lt;queryResultModeId&gt;ATTRIBUTE&lt;/queryResultModeId&gt;
+  &lt;queryPropogationType&gt;BROADCAST&lt;/queryPropogationType&gt;
+  &lt;queryPropogationLevels&gt;N/A&lt;/queryPropogationLevels&gt;
+  &lt;queryMimeAccept&gt;*/*&lt;/queryMimeAccept&gt;
+  &lt;queryMaxResults&gt;100&lt;/queryMaxResults&gt;
+  &lt;queryResults&gt;0&lt;/queryResults&gt;
+  &lt;queryKWQString&gt;SeverityLevel = 3&lt;/queryKWQString&gt;
+  &lt;querySelectSet/&gt;
+  &lt;queryFromSet/&gt;
+  &lt;queryWhereSet&gt;
+    &lt;queryElement&gt;
+      &lt;tokenRole&gt;elemName&lt;/tokenRole&gt;
+      &lt;tokenValue&gt;SeverityLevel&lt;/tokenValue&gt;
+    &lt;/queryElement&gt;
+    &lt;queryElement&gt;
+      &lt;tokenRole&gt;LITERAL&lt;/tokenRole&gt;
+      &lt;tokenValue&gt;3&lt;/tokenValue&gt;
+    &lt;/queryElement&gt;
+    &lt;queryElement&gt;
+      &lt;tokenRole&gt;RELOP&lt;/tokenRole&gt;
+      &lt;tokenValue&gt;EQ&lt;/tokenValue&gt;
+    &lt;/queryElement&gt;
+  &lt;/queryWhereSet&gt;
+  &lt;queryResultSet/&gt;
+&lt;/query&gt;
+</source>
+
+	<p>Passing such a long string as a URL parameter in a
+	  <code>GET</code> request can be tricky, though.  For such long
+	  parameters, it's better to use a <code>POST</code> request
+	  instead.  See your HTTP API documentation for details on
+	  formulating <code>POST</code> requests.
+	</p>
+      </subsection>
+    </section>
+  </body>
+</document>


Mime
View raw message