001: /*
002: * XMLHandler.java
003: */
004: package com.sun.portal.sra.config;
005:
006: import java.util.HashMap;
007: import java.util.Map;
008: import java.util.Stack;
009:
010: import org.xml.sax.Attributes;
011: import org.xml.sax.SAXException;
012: import org.xml.sax.helpers.DefaultHandler;
013:
014: public class XMLHandler extends DefaultHandler {
015: private final Map[] subHandlers = new HashMap[ARRAY_SIZE];
016: private Stack stack;
017: private StringBuffer sb = null;
018: private SubHandler result;
019:
020: public XMLHandler() {
021: this .stack = new Stack();
022: this .subHandlers[0] = new HashMap();
023: this .subHandlers[0].put("VIEW", new ViewHandler());
024: this .subHandlers[0].put("COMMANDCLASS",
025: new CommandclassHandler());
026: this .subHandlers[0].put("SRADESKTOP", new SradesktopHandler());
027: this .subHandlers[0].put("NAME", new NameHandler());
028: this .subHandlers[0].put("COMMAND", new CommandHandler());
029: }
030:
031: public void startDocument() throws SAXException {
032: this .stack = new Stack();
033: this .result = null;
034: }
035:
036: public void endDocument() throws SAXException {
037: if (!this .stack.isEmpty()) {
038: throw this .invalidState(new IllegalStateException(
039: "Stack is not empty at the end of document."));
040: }
041: }
042:
043: public void startElement(String uri, String localName,
044: String qName, Attributes attributes) throws SAXException {
045: this .processPCData();
046: this .getSubHandler(localName).startElement(uri, localName,
047: qName, attributes);
048: }
049:
050: public void endElement(String uri, String localName, String qName)
051: throws SAXException {
052: this .processPCData();
053: ((SubHandler) this .stack.peek()).endElement(uri, localName,
054: qName);
055: }
056:
057: public XMLElement getResult() {
058: if (this .result == null) {
059: return null;
060: }
061: return (XMLElement) this .result.getXMLContent();
062: }
063:
064: protected View createView() {
065: return new View();
066: }
067:
068: protected CommandClass createCommandclass() {
069: return new CommandClass();
070: }
071:
072: protected SraDesktop createSradesktop() {
073: return new SraDesktop();
074: }
075:
076: protected Name createName() {
077: return new Name();
078: }
079:
080: protected Command createCommand() {
081: return new Command();
082: }
083:
084: public void characters(char[] ch, int start, int length)
085: throws SAXException {
086: if (sb == null) {
087: sb = new StringBuffer();
088: }
089: sb.append(ch, start, length);
090: }
091:
092: private void processPCData() {
093: if (sb == null) {
094: return;
095: }
096: String pcdata = this .sb.toString();
097: XMLContent current = ((SubHandler) this .stack.peek())
098: .getXMLContent();
099: if (current instanceof XMLPCDataElement) {
100: ((XMLPCDataElement) current).add(pcdata);
101: sb = null;
102: return;
103: }
104: if (!pcdata.trim().equals("")) {
105: System.err.println("WARNING!: PCDATA lost ('"
106: + pcdata.trim() + "') target:" + current);
107: }
108: }
109:
110: private SubHandler getSubHandler(String localName)
111: throws SAXException {
112: SubHandler ret;
113: if (this .stack.isEmpty()) {
114: // the first time (when the stack is still empty. we have to
115: // search for a handler for the root element.
116: if (this .result != null) {
117: // something is terribly wrong!
118: throw this .invalidState(new IllegalStateException(
119: "Result is present, but stack is empty."));
120: }
121: ret = (SubHandler) this .subHandlers[0].get(localName);
122: // we don't need a new instance, by definition the subHandlers[0]
123: // only
124: // contains potential root elements
125: this .result = ret;
126: this .stack.push(ret);
127: if (ret == null) {
128: throw new SAXException(
129: "No Handler found for root element "
130: + localName + ".");
131: }
132: return ret;
133: }
134: // the SubHandler on top of the stack knows what to do!
135: return ((SubHandler) this .stack.peek())
136: .getSubHandler(localName);
137: }
138:
139: private SAXException invalidDocument(String encounteredElement)
140: throws SAXException {
141: return new SAXException(
142: "The parsed XML document is invalid. Unexpected element '"
143: + encounteredElement + "'.");
144: }
145:
146: private SAXException invalidMethod() throws SAXException {
147: return this .invalidState(new IllegalStateException(
148: "Method should never be called."));
149: }
150:
151: private SAXException invalidStack() throws SAXException {
152: return this .invalidState(new IllegalStateException(
153: "Stack misbehaviour."));
154: }
155:
156: private SAXException invalidState(Exception damn)
157: throws SAXException {
158: return new SAXException(
159: "Generated Code is not working properly!", damn);
160: }
161:
162: private abstract class SubHandler extends DefaultHandler {
163: protected SubHandler getSubHandler(String localName)
164: throws SAXException {
165: SubHandler ret = (SubHandler) XMLHandler.this .subHandlers[this
166: .index()].get(localName);
167: if (ret == null) {
168: return this .noHandlerFound(localName);
169: }
170: ret = ret.getInstance();
171: XMLHandler.this .stack.push(ret);
172: return ret;
173: }
174:
175: protected SubHandler noHandlerFound(String localName)
176: throws SAXException {
177: throw new SAXException("No Handler found for Element "
178: + localName + ".");
179: }
180:
181: protected int index() {
182: return 0;
183: }
184:
185: protected abstract SubHandler getInstance() throws SAXException;
186:
187: protected abstract XMLContent getXMLContent();
188: }
189:
190: interface XMLContentAddable
191:
192: {
193: //protected abstract
194: void add(XMLContent particle) throws SAXException;
195: }
196:
197: private abstract class SequenceContentSubHandler extends SubHandler
198: implements XMLContentAddable
199:
200: {
201: public void startElement(String uri, String localName,
202: String qName, Attributes attributes)
203: throws SAXException {
204: throw XMLHandler.this .invalidMethod();
205: }
206:
207: public void endElement(String uri, String localName,
208: String qName) throws SAXException {
209: if (XMLHandler.this .stack.pop() != this ) {
210: throw XMLHandler.this .invalidStack();
211: }
212: ((XMLContentAddable) XMLHandler.this .stack.peek()).add(this
213: .getXMLContent());
214: XMLHandler.this .endElement(uri, localName, qName);
215: }
216: }
217:
218: private abstract class ElementSubHandler extends SubHandler {
219: protected SubHandler getSubHandler(String localName)
220: throws SAXException {
221: // if startElement hasn't been called yet. this is the Handler
222: if (this .getXMLContent() == null) {
223: return this ;
224: }
225: return super .getSubHandler(localName);
226: }
227:
228: public void endElement(String uri, String localName,
229: String qName) throws SAXException {
230: if (XMLHandler.this .stack.pop() != this ) {
231: throw XMLHandler.this .invalidStack();
232: }
233: if (!XMLHandler.this .stack.isEmpty()) {
234: ((XMLContentAddable) XMLHandler.this .stack.peek())
235: .add(this .getXMLContent());
236: }
237: }
238:
239: public abstract void startElement(String uri, String localName,
240: String qName, Attributes attributes)
241: throws SAXException;
242: }
243:
244: private abstract class ChoiceElementSubHandler extends
245: ElementSubHandler implements XMLContentAddable
246:
247: {
248: protected SubHandler getSubHandler(String localName)
249: throws SAXException {
250: if (this .getXMLContent() == null) {
251: return this ;
252: }
253: // otherwise look for what is the right choice SubHandler,
254: // push it to the stack and see what it suggests
255: SubHandler sub = super .getSubHandler(localName);
256: return sub.getSubHandler(localName);
257: }
258:
259: protected abstract int index();
260: }
261:
262: private abstract class ChoiceContentSubHandler extends SubHandler
263: implements XMLContentAddable {
264: protected SubHandler getSubHandler(String localName)
265: throws SAXException {
266: // we are not interrested in startingElements
267: SubHandler sub = super .getSubHandler(localName);
268: return sub.getSubHandler(localName);
269: }
270:
271: public void endElement(String uri, String localName,
272: String qName) throws SAXException {
273: throw XMLHandler.this .invalidMethod();
274: }
275:
276: protected abstract int index();
277:
278: protected XMLContent getXMLContent() {
279: return null;
280: }
281:
282: public void add(XMLContent content) throws SAXException {
283: if (XMLHandler.this .stack.pop() != this ) {
284: throw XMLHandler.this .invalidStack();
285: }
286: ((XMLContentAddable) XMLHandler.this .stack.peek())
287: .add(content);
288: }
289: }
290:
291: class ViewHandler extends ElementSubHandler {
292: private View pcdataElement;
293:
294: public void startElement(String uri, String localName,
295: String qName, Attributes attributes)
296: throws SAXException {
297: final View element = XMLHandler.this .createView();
298: this .pcdataElement = element;
299: }
300:
301: protected XMLContent getXMLContent() {
302: return this .pcdataElement;
303: }
304:
305: protected SubHandler getInstance() {
306: return new ViewHandler();
307: }
308: }
309:
310: class CommandclassHandler extends ElementSubHandler {
311: private CommandClass pcdataElement;
312:
313: public void startElement(String uri, String localName,
314: String qName, Attributes attributes)
315: throws SAXException {
316: final CommandClass element = XMLHandler.this
317: .createCommandclass();
318: this .pcdataElement = element;
319: }
320:
321: protected XMLContent getXMLContent() {
322: return this .pcdataElement;
323: }
324:
325: protected SubHandler getInstance() {
326: return new CommandclassHandler();
327: }
328: }
329:
330: class SradesktopHandler extends ElementSubHandler implements
331: XMLContentAddable {
332: private SraDesktop myElement = null;
333:
334: public void startElement(String uri, String localName,
335: String qName, Attributes attributes)
336: throws SAXException {
337: final SraDesktop element = XMLHandler.this
338: .createSradesktop();
339: this .myElement = element;
340: }
341:
342: protected XMLContent getXMLContent() {
343: return this .myElement;
344: }
345:
346: public void add(XMLContent content) throws SAXException {
347: try {
348: if (content instanceof Command) {
349: this .myElement.add((Command) content);
350: return;
351: }
352: } catch (ClassCastException cce) {
353: throw new SAXException("Failed to add '"
354: + content.getClass().getName()
355: + "' to 'Sradesktop'."
356: + " XML document is not valid.", cce);
357: }
358: }
359:
360: protected SubHandler getInstance() {
361: return new SradesktopHandler();
362: }
363: }
364:
365: class NameHandler extends ElementSubHandler {
366: private Name pcdataElement;
367:
368: public void startElement(String uri, String localName,
369: String qName, Attributes attributes)
370: throws SAXException {
371: final Name element = XMLHandler.this .createName();
372: this .pcdataElement = element;
373: }
374:
375: protected XMLContent getXMLContent() {
376: return this .pcdataElement;
377: }
378:
379: protected SubHandler getInstance() {
380: return new NameHandler();
381: }
382: }
383:
384: class CommandHandler extends ElementSubHandler implements
385: XMLContentAddable {
386: private int slot = 0;
387: private Command sequenceElement = null;
388:
389: protected SubHandler getSubHandler(String localName)
390: throws SAXException {
391: if (this .getXMLContent() == null) {
392: return this ;
393: }
394: // required single
395: if (this .slot < 1) {
396: if ("NAME".equals(localName)) {
397: this .slot = 1;
398: XMLHandler.this .stack.push(new NameHandler());
399: return XMLHandler.this .getSubHandler(localName);
400: } else {
401: throw XMLHandler.this .invalidDocument(localName);
402: }
403: }
404: // required single
405: if (this .slot < 2) {
406: if ("COMMANDCLASS".equals(localName)) {
407: this .slot = 2;
408: XMLHandler.this .stack
409: .push(new CommandclassHandler());
410: return XMLHandler.this .getSubHandler(localName);
411: } else {
412: throw XMLHandler.this .invalidDocument(localName);
413: }
414: }
415: // required single
416: if (this .slot < 3) {
417: if ("VIEW".equals(localName)) {
418: this .slot = 3;
419: XMLHandler.this .stack.push(new ViewHandler());
420: return XMLHandler.this .getSubHandler(localName);
421: } else {
422: throw XMLHandler.this .invalidDocument(localName);
423: }
424: }
425: throw XMLHandler.this .invalidDocument(localName);
426: }
427:
428: public void startElement(String uri, String localName,
429: String qName, Attributes attributes)
430: throws SAXException {
431: final Command element = XMLHandler.this .createCommand();
432: this .sequenceElement = element;
433: }
434:
435: protected XMLContent getXMLContent() {
436: return this .sequenceElement;
437: }
438:
439: public void add(XMLContent content) throws SAXException {
440: //Exception e=null;
441: try {
442: switch (this .slot) {
443: case 1:
444: this .sequenceElement.setName((Name) content);
445: return;
446: case 2:
447: this .sequenceElement
448: .setCommandclass((CommandClass) content);
449: return;
450: case 3:
451: this .sequenceElement.setView((View) content);
452: return;
453: default:
454: throw new SAXException("Failed to add '"
455: + content.getClass().getName()
456: + "' to 'Command'.",
457: new IllegalStateException(
458: "Invalid state in '"
459: + this .getClass().getName()
460: + "'. Slot (" + this .slot
461: + ") does not exist."));
462: }
463: } catch (ClassCastException cce) {
464: throw new SAXException("Failed to add '"
465: + content.getClass().getName()
466: + "' to 'Command'."
467: + " XML document is not valid.", cce);
468: }
469: }
470:
471: protected SubHandler getInstance() {
472: return new CommandHandler();
473: }
474: }
475:
476: private static final int ARRAY_SIZE = 1;
477: }
|