001: /*
002: * <copyright>
003: *
004: * Copyright 1997-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:
027: package org.cougaar.core.qos.frame;
028:
029: import java.io.File;
030: import java.net.MalformedURLException;
031: import java.net.URL;
032: import java.util.ArrayList;
033: import java.util.HashMap;
034: import java.util.Map;
035: import java.util.Properties;
036:
037: import org.cougaar.bootstrap.XMLReaderUtils;
038: import org.cougaar.core.component.ServiceBroker;
039: import org.cougaar.core.service.BlackboardService;
040: import org.cougaar.util.log.Logger;
041: import org.cougaar.util.log.Logging;
042: import org.xml.sax.Attributes;
043: import org.xml.sax.XMLReader;
044: import org.xml.sax.helpers.AttributesImpl;
045: import org.xml.sax.helpers.DefaultHandler;
046:
047: /**
048: * This class parses frame and protocol xml files and creates the
049: * corresponding {@link PrototypeFrame}s and {@link DataFrame}s . The
050: * parsing is SAX.
051: */
052: public class FrameSetParser extends DefaultHandler {
053:
054: private String frame_set_name;
055: private FrameSet frame_set;
056: private PrototypeSpec proto_spec;
057: private PathSpec path_spec;
058: private String slot_def; // slot being defined when we're parsing prototypes xml
059: private ServiceBroker sb;
060: private BlackboardService bbs;
061: private Logger log;
062:
063: public FrameSetParser() {
064: this .log = Logging.getLogger(getClass().getName());
065: }
066:
067: public FrameSetParser(ServiceBroker sb, BlackboardService bbs) {
068: this ();
069: this .sb = sb;
070: this .bbs = bbs;
071: }
072:
073: public FrameSet parseFrameSetFiles(String name,
074: String[] xml_filenames) {
075: if (xml_filenames == null || xml_filenames.length == 0)
076: return null;
077:
078: FrameSet fset = parseFrameSetFile(name, xml_filenames[0], null);
079: for (int i = 1; i < xml_filenames.length; i++)
080: parseFrameSetFile(name, xml_filenames[i], fset);
081: return fset;
082: }
083:
084: public FrameSet parseFrameSetFile(String name, String xml_filename) {
085: return parseFrameSetFile(name, xml_filename, null);
086: }
087:
088: public FrameSet parseFrameSetFile(String name, String xml_filename,
089: FrameSet frameSet) {
090: ClassLoader loader = FrameSetParser.class.getClassLoader();
091: URL url = loader.getResource(xml_filename);
092: if (url == null) {
093: // Try it as a file
094: File file = new File(xml_filename);
095: try {
096: url = file.toURL();
097: } catch (MalformedURLException e) {
098: log.error("Bogus FrameSet data location "
099: + xml_filename, e);
100: return frameSet;
101: }
102: }
103: return parseFrameSetData(name, url, frameSet);
104: }
105:
106: public FrameSet parseFrameSetData(String name, final URL url,
107: FrameSet frameSet) {
108: if (log.isInfoEnabled())
109: log.info("Loading FrameSet" + name + " from " + url);
110:
111: this .frame_set = frameSet;
112: this .frame_set_name = name;
113: try {
114: final XMLReader producer = XMLReaderUtils.createXMLReader();
115: String producerClassName = producer.getClass().getName();
116: if (log.isInfoEnabled())
117: log.info("Made SAX reader class=" + producerClassName);
118: if (producerClassName
119: .equals("com.sun.org.apache.xerces.internal.parsers.SAXParser")) {
120: producer
121: .setFeature(
122: "http://apache.org/xml/features/nonvalidating/load-external-dtd",
123: false);
124: }
125: if (producerClassName
126: .equals("org.apache.crimson.parser.XMLReaderImpl")) {
127: // TODO Add Feature to disable validation, so that node does not make Web call to get .dtd
128: }
129:
130: DefaultHandler consumer = this ;
131: producer.setContentHandler(consumer);
132: producer.setErrorHandler(consumer);
133: if (frame_set == null) {
134: producer.parse(url.toString());
135: } else {
136: // run in a transaction
137: Runnable r = new Runnable() {
138: public void run() {
139: try {
140: producer.parse(url.toString());
141: } catch (Throwable ex) {
142: log.error("Error parsing FrameSet file "
143: + url, ex);
144: }
145: }
146: };
147: frame_set.runInTransaction(r);
148: }
149: } catch (Throwable ex) {
150: log.error("Error parsing FrameSet file " + url, ex);
151: }
152: return frame_set;
153: }
154:
155: public void startElement(String uri, String local, String name,
156: Attributes attrs) {
157: try {
158: if (name.equals("frameset")) {
159: startFrameset(attrs);
160: } else if (name.equals("prototypes")) {
161: // no-op
162: } else if (name.equals("prototype")) {
163: startPrototype(attrs);
164: } else if (name.equals("relation-prototype")) {
165: startPrototype(attrs);
166: } else if (name.equals("slot")) {
167: startSlot(attrs);
168: } else if (name.equals("slot-reference")) {
169: slot_reference(attrs);
170: } else if (name.equals("aggregate-by")) {
171: String relatedSlot = attrs.getValue("related-slot");
172: String relation = attrs.getValue("relation");
173: String cname = attrs.getValue("aggregator");
174: String role = attrs.getValue("role");
175: frame_set.addAggregator(slot_def, relatedSlot,
176: relation, role, cname);
177: } else if (name.equals("fork")) {
178: fork(attrs);
179: } else if (name.equals("path")) {
180: startPath(attrs);
181: } else if (name.equals("copyright")) {
182: // no-op
183: } else {
184: // implicit data frame
185: makeFrame(name, attrs);
186: }
187: } catch (Exception ex) {
188: log.error("startElement " + name, ex);
189: }
190: }
191:
192: public void endElement(String uri, String local, String name) {
193: try {
194: if (name.equals("frameset")) {
195: endFrameset();
196: } else if (name.equals("prototypes")) {
197: // no-op
198: } else if (name.equals("prototype")) {
199: endPrototype();
200: } else if (name.equals("relation-prototype")) {
201: endPrototype();
202: } else if (name.equals("path")) {
203: endPath();
204: } else if (name.equals("fork")) {
205: // no-op
206: } else if (name.equals("slot")) {
207: endSlot();
208: } else if (name.equals("slot-reference")) {
209: // no-op
210: } else if (name.equals("aggregate-by")) {
211: // no-op
212: } else if (name.equals("copyright")) {
213: // no-op
214: } else {
215: // implicit data frame
216: }
217: } catch (Exception ex) {
218: log.error("endElement " + name, ex);
219: }
220: }
221:
222: public void characters(char buf[], int offset, int length) {
223: // no-op
224: }
225:
226: private void startFrameset(Attributes attrs) {
227: if (log.isDebugEnabled())
228: log.debug("startFrameset");
229:
230: if (frame_set != null)
231: return;
232:
233: String pkg = attrs.getValue("package");
234: String container_relation = attrs
235: .getValue("container-relation");
236: String inheritance = attrs.getValue("frame-inheritance");
237: String indexSlot = attrs.getValue("index-slot");
238: if (!inheritance.equals("single")) {
239: throw new RuntimeException(
240: "Only single-inheritance FrameSets are supported!");
241: }
242: String domain = attrs.getValue("domain");
243:
244: frame_set = new SingleInheritanceFrameSet(pkg, sb, bbs, domain,
245: frame_set_name, container_relation, indexSlot);
246: }
247:
248: private void startPrototype(Attributes attrs) {
249: if (log.isDebugEnabled())
250: log.debug("startPrototype");
251:
252: proto_spec = new PrototypeSpec(attrs);
253: }
254:
255: private void endPrototype() {
256: if (log.isDebugEnabled())
257: log.debug("endPrototype");
258:
259: proto_spec.makePrototype(frame_set);
260: proto_spec = null;
261: }
262:
263: private void makeFrame(String name, Attributes attrs) {
264: if (log.isDebugEnabled())
265: log.debug("startFrame");
266:
267: DataFrameSpec frame_spec = new DataFrameSpec(name, attrs);
268: frame_spec.makeFrame(frame_set);
269: }
270:
271: private void startPath(Attributes attrs) {
272: if (log.isDebugEnabled())
273: log.debug("startPath");
274:
275: String name = attrs.getValue("name");
276: path_spec = new PathSpec(name);
277: }
278:
279: private void fork(Attributes attrs) {
280: String role = attrs.getValue("role");
281: String relation = attrs.getValue("relation");
282: path_spec.addToPath(role, relation);
283: }
284:
285: private void endPath() {
286: if (log.isDebugEnabled())
287: log.debug("endPath");
288: path_spec.makePath(frame_set);
289: path_spec = null;
290: }
291:
292: private void startSlot(Attributes attrs) {
293: if (log.isDebugEnabled())
294: log.debug("slot");
295:
296: if (proto_spec != null) {
297: slot_def = attrs.getValue("name");
298: proto_spec.put(slot_def, new AttributesImpl(attrs));
299: } else {
300: // log
301: }
302: }
303:
304: private void endSlot() {
305: slot_def = null;
306: }
307:
308: private void slot_reference(Attributes attrs) {
309: if (log.isDebugEnabled())
310: log.debug("slot-reference");
311:
312: if (path_spec != null) {
313: String slot = attrs.getValue("name");
314: path_spec.setSlot(slot);
315: } else {
316: // log
317: }
318: }
319:
320: private void endFrameset() {
321: // no-op
322: }
323:
324: // Helper structs
325: private class DataFrameSpec {
326: String prototype;
327: Properties slotValues;
328:
329: DataFrameSpec(String name, Attributes attrs) {
330: slotValues = new Properties();
331: prototype = name;
332: for (int i = 0; i < attrs.getLength(); i++) {
333: String pname = attrs.getLocalName(i);
334: String value = attrs.getValue(i);
335: slotValues.put(pname, value);
336: }
337: }
338:
339: Frame makeFrame(FrameSet frameSet) {
340: PrototypeFrame pframe = frameSet
341: .findPrototypeFrame(prototype);
342: if (pframe == null)
343: return null;
344:
345: Frame frame = frameSet.makeFrame(prototype, slotValues);
346: return frame;
347: }
348: }
349:
350: private class PrototypeSpec {
351: String name;
352: Attributes attrs;
353: Map<String, Attributes> slots;
354: String prototype;
355:
356: PrototypeSpec(Attributes attrs) {
357: slots = new HashMap<String, Attributes>();
358: name = attrs.getValue("name");
359: prototype = attrs.getValue("prototype");
360: this .attrs = new AttributesImpl(attrs);
361: }
362:
363: void put(String slot, Attributes attrs) {
364: slots.put(slot, attrs);
365: }
366:
367: Frame makePrototype(FrameSet frameSet) {
368: PrototypeFrame frame = frameSet.makePrototype(name,
369: prototype, attrs, slots);
370: return frame;
371: }
372:
373: }
374:
375: private class PathSpec {
376: String name;
377: ArrayList path;
378: String slot;
379:
380: PathSpec(String name) {
381: this .name = name;
382: path = new ArrayList();
383: }
384:
385: void addToPath(String role, String relation) {
386: path.add(new Path.Fork(role, relation));
387: }
388:
389: void setSlot(String slot) {
390: this .slot = slot;
391: }
392:
393: Path makePath(FrameSet frameSet) {
394: Path.Fork[] array = new Path.Fork[path.size()];
395: for (int i = 0; i < path.size(); i++)
396: array[i] = (Path.Fork) path.get(i);
397: return frameSet.makePath(name, array, slot);
398: }
399:
400: }
401:
402: }
|