001: /*
002: * <copyright>
003: *
004: * Copyright 2003-2004 BBNT Solutions, LLC
005: * under sponsorship of the Defense Advanced Research Projects
006: * Agency (DARPA).
007: *
008: * You can redistribute this software and/or modify it under the
009: * terms of the Cougaar Open Source License as published on the
010: * Cougaar Open Source Website (www.cougaar.org).
011: *
012: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
013: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
014: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
015: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
016: * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
017: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
018: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
019: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
020: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
021: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
022: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
023: *
024: * </copyright>
025: */
026: package org.cougaar.lib.aggagent.query;
027:
028: import java.io.Serializable;
029: import java.util.Enumeration;
030: import java.util.Timer;
031: import java.util.Vector;
032:
033: import org.cougaar.lib.aggagent.util.InverseSax;
034: import org.cougaar.lib.aggagent.util.XmlUtils;
035: import org.cougaar.lib.aggagent.util.Enum.Language;
036: import org.cougaar.lib.aggagent.util.Enum.QueryType;
037: import org.cougaar.lib.aggagent.util.Enum.ScriptType;
038: import org.cougaar.lib.aggagent.util.Enum.UpdateMethod;
039: import org.cougaar.lib.aggagent.util.Enum.XmlFormat;
040: import org.w3c.dom.Element;
041: import org.w3c.dom.NodeList;
042:
043: /**
044: * Instances of this class represent generalized "queries" in the sense of the
045: * Aggregation infrastructure. That is, a specification of a subset of data
046: * available within the society, with the presumption that the infrastructure
047: * will supply this data in some fashion. The way in which the specification
048: * is expressed will vary depending on the type of query.
049: * <br><br>
050: * Queries may be either transient ("find the answer now and then forget") or
051: * persistent ("maintain an updated view of the answer").
052: * <br><br>
053: * At this time, only one implementation (this one) is available. The query
054: * is specified by an unordered set of Cluster names and a pair of SILK
055: * scripts which define, respectively, the set of blackboard objects that
056: * should be examined and the encoding of the findings (including any
057: * intermediate calculations that may be necessary).
058: */
059: public class AggregationQuery implements Serializable {
060: public static String QUERY_TAG = "query";
061: private static String TYPE_ATT = "type";
062: private static String UPDATE_ATT = "update_method";
063: private static String PULL_RATE_ATT = "pull_rate";
064: private static String NAME_ATT = "name";
065: private static String CLUSTER_TAG = "source_cluster";
066: private static String TIMEOUT_TAG = "timeout";
067:
068: private QueryType queryType = QueryType.TRANSIENT;
069: private UpdateMethod updateMethod = UpdateMethod.PUSH;
070: private int pullRate = -1; // wait period in sec.(if neg., don't auto-pull)
071: private long timeout = 0; // period of tim to wait for transient queries. 0 means wait forever
072: private boolean timeoutSupplied = false; // True iff a timeout is set explicitly
073: private Vector sourceClusters = new Vector();
074:
075: private ScriptSpec predicateSpec = null;
076: private ScriptSpec formatSpec = null;
077: private ScriptSpec aggSpec = null;
078:
079: /**
080: * name assigned to this query by user or ui developer;
081: * not necessarily unique
082: * */
083: private String userDefinedName = "Query";
084:
085: /**
086: * Create a new AggregationQuery, initializing only the fundamental type
087: * as either TRANSIENT or PERSISTENT.
088: * @param queryType indicator of TRANSIENT or PERSISTENT status
089: */
090: public AggregationQuery(QueryType queryType) {
091: this .queryType = queryType;
092: }
093:
094: /**
095: * Create a new AggregationQuery, initializing it with data found in an XML
096: * document.
097: */
098: public AggregationQuery(Element root) {
099: queryType = QueryType.fromString(root.getAttribute(TYPE_ATT));
100: updateMethod = UpdateMethod.fromString(root
101: .getAttribute(UPDATE_ATT));
102: pullRate = Integer.parseInt(root.getAttribute(PULL_RATE_ATT));
103: userDefinedName = root.getAttribute(NAME_ATT);
104:
105: NodeList nl = root.getElementsByTagName(CLUSTER_TAG);
106: for (int i = 0; i < nl.getLength(); i++) {
107: addSourceCluster(nl.item(i).getFirstChild().getNodeValue()
108: .trim());
109: }
110:
111: nl = root.getElementsByTagName(TIMEOUT_TAG);
112: if (nl.getLength() > 0) {
113: String timeoutStr = nl.item(0).getFirstChild()
114: .getNodeValue().trim();
115: try {
116: timeout = Long.parseLong(timeoutStr);
117: timeoutSupplied = true;
118: } catch (NumberFormatException nfe) {
119: System.err
120: .println("WARNING: Expecting number for timeout, but received "
121: + timeoutStr);
122: System.err.println(" will use default value");
123: }
124: }
125:
126: nl = root.getElementsByTagName(ScriptType.UNARY_PREDICATE
127: .toString());
128: if (nl.getLength() > 0)
129: predicateSpec = new ScriptSpec((Element) nl.item(0));
130:
131: nl = root.getElementsByTagName(ScriptType.INCREMENT_FORMAT
132: .toString());
133: if (nl.getLength() > 0)
134: formatSpec = new ScriptSpec((Element) nl.item(0));
135:
136: nl = root
137: .getElementsByTagName(ScriptType.AGGREGATOR.toString());
138: if (nl.getLength() > 0)
139: aggSpec = new ScriptSpec((Element) nl.item(0));
140: }
141:
142: public void setName(String name) {
143: userDefinedName = name;
144: }
145:
146: public String getName() {
147: return userDefinedName;
148: }
149:
150: public QueryType getType() {
151: return queryType;
152: }
153:
154: public void setUpdateMethod(UpdateMethod updateMethod) {
155: this .updateMethod = updateMethod;
156: }
157:
158: public UpdateMethod getUpdateMethod() {
159: return updateMethod;
160: }
161:
162: public void setPullRate(int pullRate) {
163: this .pullRate = pullRate;
164: }
165:
166: public int getPullRate() {
167: return pullRate;
168: }
169:
170: public void setTimeout(long timeout) {
171: this .timeout = timeout;
172: timeoutSupplied = true;
173: }
174:
175: public long getTimeout() {
176: return timeout;
177: }
178:
179: public boolean timeoutSupplied() {
180: return timeoutSupplied;
181: }
182:
183: public void addSourceCluster(String clusterID) {
184: sourceClusters.add(clusterID);
185: }
186:
187: public void removeSourceCluster(String clusterID) {
188: sourceClusters.remove(clusterID);
189: }
190:
191: public Enumeration getSourceClusters() {
192: return sourceClusters.elements();
193: }
194:
195: public Vector getSourceClustersVector() {
196: return new Vector(sourceClusters);
197: }
198:
199: public ScriptSpec getPredicateSpec() {
200: return predicateSpec;
201: }
202:
203: public void setPredicateSpec(ScriptSpec ss) {
204: predicateSpec = ss;
205: }
206:
207: public ScriptSpec getFormatSpec() {
208: return formatSpec;
209: }
210:
211: public void setFormatSpec(ScriptSpec ss) {
212: formatSpec = ss;
213: }
214:
215: public ScriptSpec getAggSpec() {
216: return aggSpec;
217: }
218:
219: public void setAggSpec(ScriptSpec ss) {
220: aggSpec = ss;
221: }
222:
223: public String toXml() {
224: InverseSax doc = new InverseSax();
225: includeXml(doc);
226: return doc.toString();
227: }
228:
229: public void includeXml(InverseSax doc) {
230: doc.addElement(QUERY_TAG);
231: doc.addAttribute(TYPE_ATT, queryType.toString());
232: doc.addAttribute(UPDATE_ATT, updateMethod.toString());
233: doc.addAttribute(PULL_RATE_ATT, String.valueOf(pullRate));
234: doc.addAttribute(NAME_ATT, userDefinedName);
235:
236: for (int i = 0; i < sourceClusters.size(); i++)
237: doc.addTextElement(CLUSTER_TAG, sourceClusters.elementAt(i)
238: .toString());
239:
240: if (timeout != 0)
241: doc.addTextElement(TIMEOUT_TAG, String.valueOf(timeout));
242:
243: includeScriptXml(doc);
244: if (aggSpec != null)
245: aggSpec.includeXml(doc);
246: doc.endElement();
247: }
248:
249: public void includeScriptXml(InverseSax doc) {
250: predicateSpec.includeXml(doc);
251: formatSpec.includeXml(doc);
252: }
253:
254: public String toString() {
255: return userDefinedName;
256: }
257:
258: private Timer pullTimer;
259:
260: public void setPullTimer(Timer newPullTimer) {
261: pullTimer = newPullTimer;
262: }
263:
264: public java.util.Timer getPullTimer() {
265: return pullTimer;
266: }
267:
268: public static void main(String args[]) {
269: AggregationQuery aq = new AggregationQuery(QueryType.PERSISTENT);
270: aq.setName("Test Query");
271: aq.addSourceCluster("Cluster 1");
272: aq.addSourceCluster("Cluster 2");
273: aq.addSourceCluster("Cluster 3");
274: aq.setPredicateSpec(new ScriptSpec(ScriptType.UNARY_PREDICATE,
275: Language.SILK, "SOME SCRIPT"));
276: aq.setFormatSpec(new ScriptSpec(Language.SILK,
277: XmlFormat.XMLENCODER, "SOME OTHER SCRIPT"));
278:
279: String xmlQuery = aq.toXml();
280: System.out.println(xmlQuery);
281:
282: try {
283: Element qr = XmlUtils.parse(xmlQuery);
284: AggregationQuery aq2 = new AggregationQuery(qr);
285: System.out.println(aq2.toXml());
286: } catch (Exception e) {
287: e.printStackTrace();
288: }
289: }
290: }
|