001: /**
002: *
003: * © Copyright International Business Machines Corporation 2005, 2006.
004: * All rights reserved.
005: *
006: * The 'DefaultEngine' class provides a default implementation of the
007: * 'TemplateEngine' interface.
008: *
009: * File : DefaultEngine.java
010: * Created : 2005/08/16
011: *
012: * @author Rene Pawlitzek (rpa@zurich.ibm.com)
013: * @version 2.00, 2005/08/16
014: * @since JDK 1.3
015: *
016: * History : 2005/08/16, rpa, new file
017: * 2005/08/16, rpa, introduced TemplateEngine interface
018: * 2005/08/16, rpa, removed tree dependency on Swing
019: * 2006/03/14, rpa, code review
020: *
021: */package com.ibm.hamlet;
022:
023: import java.io.*;
024: import java.util.*;
025: import org.apache.log4j.*;
026: import org.xml.sax.*;
027: import org.xml.sax.helpers.*;
028:
029: public class DefaultEngine extends DefaultHandler implements
030: TemplateEngine {
031:
032: // log4j
033: private static Category category = Category
034: .getInstance(DefaultEngine.class);
035:
036: private static ReaderPool readerPool = new ReaderPool();
037:
038: private static final String REPEAT_TAG = "REPEAT"; // repeat
039: private static final String INCLUDE_TAG = "INCLUDE"; // include
040: private static final String REPLACE_TAG = "REPLACE"; // replace
041: private static final String ID_ATTRIBUTE = "ID"; // id
042:
043: private boolean ignore, record;
044: private TreeNode root, curNode;
045: private PrintWriter out;
046: private ContentHandler handler;
047:
048: public void perform(InputStream in, ContentHandler handler,
049: PrintWriter out) throws Exception {
050:
051: XMLReader reader = null;
052: try {
053: this .out = out;
054: this .handler = handler;
055: reader = readerPool.getReader();
056: InputSource inputSource = new InputSource(in);
057: reader.setErrorHandler(this );
058: reader.setContentHandler(this );
059: reader.parse(inputSource);
060: } finally {
061: if (reader != null)
062: readerPool.returnReader(reader);
063: } // try
064:
065: } // perform
066:
067: private void playback(TreeNode node) throws Exception {
068: int childIndex = node.getChildCount() - 1;
069: for (int i = 0; i < node.getCount(); i++) {
070: Object obj = node.elementAt(i);
071: if (obj instanceof StartElement) {
072: StartElement elem = (StartElement) obj;
073: if (REPEAT_TAG.equals(elem.localName)) {
074: int count = 0;
075: String id = elem.atts.getValue(ID_ATTRIBUTE);
076: if (id != null)
077: count = handler.getElementRepeatCount(id,
078: elem.localName, elem.atts);
079: for (int j = 0; j < count; j++) {
080: playback((TreeNode) node.getChildAt(childIndex));
081: if (handler.getElementRepeatCount(id,
082: elem.localName, elem.atts) == 0)
083: break;
084: } // for
085: childIndex--;
086: } else
087: startElement(elem.namespaceURI, elem.localName,
088: elem.qName, elem.atts);
089: } else if (obj instanceof EndElement) {
090: EndElement elem = (EndElement) obj;
091: if (!REPEAT_TAG.equals(elem.localName))
092: endElement(elem.namespaceURI, elem.localName,
093: elem.qName);
094: } else if (obj instanceof CharElement) {
095: CharElement elem = (CharElement) obj;
096: characters(elem.str.toCharArray(), 0, elem.str.length());
097: } // if
098: } // for
099: } // playback
100:
101: /* ----- private classes ----- */
102:
103: private static class TreeNode {
104:
105: private TreeNode parent = null;
106: private ArrayList stack = new ArrayList();
107: private ArrayList children = new ArrayList();
108:
109: void add(Object obj) {
110: stack.add(obj);
111: } // add
112:
113: Object elementAt(int index) {
114: return stack.get(index);
115: } // elementAt
116:
117: Object getChildAt(int index) {
118: return children.get(index);
119: } // getChildAt
120:
121: int getCount() {
122: return stack.size();
123: } // getCount
124:
125: int getChildCount() {
126: return children.size();
127: } // getChildCount
128:
129: public void insert(TreeNode node, int position) {
130: node.parent = this ;
131: children.add(position, node);
132: } // insert
133:
134: public TreeNode getParent() {
135: return parent;
136: } // getParent
137:
138: } // TreeNode
139:
140: private static class StartElement {
141:
142: public String namespaceURI;
143: public String localName;
144: public String qName;
145: public Attributes atts;
146:
147: public StartElement(String namespaceURI, String localName,
148: String qName, Attributes atts) {
149: this .namespaceURI = namespaceURI;
150: this .localName = localName;
151: this .qName = qName;
152: this .atts = new AttributesImpl(atts);
153: } // StartElement
154:
155: } // StartElement
156:
157: private static class EndElement {
158:
159: public String namespaceURI;
160: public String localName;
161: public String qName;
162:
163: public EndElement(String namespaceURI, String localName,
164: String qName) {
165: this .namespaceURI = namespaceURI;
166: this .localName = localName;
167: this .qName = qName;
168: } // EndElement
169:
170: } // EndElement
171:
172: private static class CharElement {
173:
174: public String str;
175:
176: public CharElement(String str) {
177: this .str = str;
178: } // CharElement
179:
180: } // CharElement
181:
182: /* ----- implementation of ContentHandler ----- */
183:
184: public void startDocument() throws SAXException {
185: root = new TreeNode();
186: curNode = root;
187: } // startDocument
188:
189: public void endDocument() throws SAXException {
190: curNode = null;
191: root = null;
192: } // endDocument
193:
194: public void startElement(String namespaceURI, String localName,
195: String qName, Attributes atts) throws SAXException {
196:
197: try {
198: // category.debug ("local name: " + localName + ", qname: " + qName);
199: if (REPEAT_TAG.equals(localName)) {
200: record = true;
201: StartElement elem = new StartElement(namespaceURI,
202: localName, qName, atts);
203: curNode.add(elem);
204: TreeNode newNode = new TreeNode();
205: curNode.insert(newNode, 0);
206: curNode = newNode;
207: } else if (REPLACE_TAG.equals(localName)) {
208: if (record) {
209: StartElement elem = new StartElement(namespaceURI,
210: localName, qName, atts);
211: curNode.add(elem);
212: } else {
213: ignore = true;
214: String id = atts.getValue(ID_ATTRIBUTE);
215: if (id != null)
216: out.print(handler.getElementReplacement(id,
217: localName, atts));
218: } // if
219: } else if (INCLUDE_TAG.equals(localName)) {
220: if (record) {
221: StartElement elem = new StartElement(namespaceURI,
222: localName, qName, atts);
223: curNode.add(elem);
224: } else {
225: ignore = true;
226: String id = atts.getValue(ID_ATTRIBUTE);
227: if (id != null)
228: atts = handler.getElementAttributes(id,
229: localName, atts);
230: InputStream in = handler.getElementIncludeSource(
231: id, localName, atts);
232: RuntimeUtilities.printInclude(out, in);
233: } // if
234: } else {
235: if (record) {
236: StartElement elem = new StartElement(namespaceURI,
237: localName, qName, atts);
238: curNode.add(elem);
239: } else {
240: String id = atts.getValue(ID_ATTRIBUTE);
241: if (id != null)
242: atts = handler.getElementAttributes(id,
243: localName, atts);
244: RuntimeUtilities.printTag(out, localName, atts);
245: } // if
246: } // if
247: } catch (Exception e) {
248: category.debug(e.getMessage(), e);
249: throw new SAXException(e);
250: } // try
251:
252: } // startElement
253:
254: public void endElement(String namespaceURI, String localName,
255: String qName) throws SAXException {
256:
257: try {
258: if (REPEAT_TAG.equals(localName)) {
259: curNode = (TreeNode) curNode.getParent();
260: EndElement elem = new EndElement(namespaceURI,
261: localName, qName);
262: curNode.add(elem);
263: if (curNode.equals(root)) {
264: record = false;
265: playback(root);
266: root = new TreeNode();
267: curNode = root;
268: } // if
269: } else if (REPLACE_TAG.equals(localName)
270: || INCLUDE_TAG.equals(localName)) {
271: if (record) {
272: EndElement elem = new EndElement(namespaceURI,
273: localName, qName);
274: curNode.add(elem);
275: } else {
276: ignore = false;
277: } // if
278: } else {
279: if (record) {
280: EndElement elem = new EndElement(namespaceURI,
281: localName, qName);
282: curNode.add(elem);
283: } else {
284: out.print("</");
285: out.print(localName);
286: out.print(">");
287: } // if
288: } // if
289: } catch (Exception e) {
290: category.debug(e.getMessage(), e);
291: throw new SAXException(e);
292: } // try
293:
294: } // endElement
295:
296: public void characters(char[] ch, int start, int length)
297: throws SAXException {
298: String str = new String(ch, start, length);
299: if (record) {
300: CharElement elem = new CharElement(str);
301: curNode.add(elem);
302: } else {
303: if (!ignore)
304: out.print(str);
305: } // if
306: } // characters
307:
308: /* ----- implementation of ErrorHandler ----- */
309:
310: private void logError(String str, SAXParseException e) {
311: category.error(str + " (Line: " + e.getLineNumber()
312: + ", Column: " + e.getColumnNumber() + "): "
313: + e.getMessage());
314: } // logError
315:
316: public void warning(SAXParseException e) throws SAXException {
317: logError("Warning", e);
318: throw e;
319: } // warning
320:
321: public void error(SAXParseException e) throws SAXException {
322: logError("Error", e);
323: throw e;
324: } // error
325:
326: } // DefaultEngine
327:
328: /* ----- End of File ----- */
|