Lax.java
001 package com.javaworld.apr2000.sax;
002 
003 /*
004  * Sample code by Mark Johnson, JavaWorld, April 2000.
005  * Code is may be used for any legal purpose, including commercial
006  * purposes, with no warranty expressed or implied.
007  * email: mark.johnson@javaworld.com
008  */
009 import org.xml.sax.*;
010 import java.lang.reflect.*;
011 import javax.xml.parsers.*;
012 import org.w3c.dom.*;
013 import org.xml.sax.SAXException;  
014 import org.xml.sax.SAXParseException;
015 import java.util.*;
016 import java.io.*;
017 
018 public class Lax extends org.xml.sax.HandlerBase {
019 
020 	// LAX translates XML content into method calls on this object
021 	private Vector _vecHandlers = null;
022 	private Vector _vecTags = null;
023 	private static Class[] _caNoArgs = null;
024 	private static Class[] _caAttrList = null;
025 	private static Class[] _caString = null;
026 	private SimpleErrorHandler _seh = new SimpleErrorHandler();
027 
028 	// Initialize class arrays used for reflection
029 	static {
030 		_caNoArgs = new Class[] {};
031 		_caAttrList = new Class[] {org.xml.sax.AttributeList.class};
032 		_caString = new Class[] {java.lang.String.class};
033 	}
034 /**
035  * Lax default constructor
036  */
037 public Lax() {
038 	super();
039 	_vecHandlers = new Vector();
040 	_vecTags = new Vector();
041 }
042 /**
043  * Lax ctor with a single handler
044  */
045 public Lax(Object handler_) {
046 	super();
047 	_vecHandlers = new Vector();
048 	_vecTags = new Vector();
049 	addHandler(handler_);
050 }
051 /**
052  * Add a handler to the list of handler objects.
053  * @param objHandler_ java.lang.Object
054  */
055 public void addHandler(Object objHandler_) {
056 	_vecHandlers.addElement(objHandler_);
057 }
058 /**
059  * Handle an incoming block of text by calling the textOf method for the
060  * current tag.
061  */
062 public void characters(char[] caChars, int iStart, int iEnd) throws SAXException {
063 	String sCurrentTag = sCurrentTag();
064 	
065 	if (sCurrentTag != null) {
066 		int i;
067 		String sTextMethodName = "textOf" + sCurrentTag;
068 		String sArg = null;
069 		
070 		// Call every text method for current tag found in the list of handlers.
071 		for (i = 0; i < _vecHandlers.size(); i++) {
072 			Object oThisHandler = _vecHandlers.elementAt(i);
073 			Method mTextMethod = mFindMethod(oThisHandler, sTextMethodName, _caString);
074 			if (mTextMethod != null) {
075 				try {
076 					if (sArg == null) {
077 						sArg = new String(caChars, iStart, iEnd);
078 					}
079 					mTextMethod.invoke(oThisHandler, new Object[] { sArg });
080 				} catch (InvocationTargetException ex) {
081 					System.err.println(ex);
082 				} catch (IllegalAccessException ex) {
083 					System.err.println(ex);
084 				}
085 			}
086 		}
087 	}
088 }
089 /**
090  * endDocument method comment.
091  */
092 public void endDocument() throws org.xml.sax.SAXException {
093 }
094 /**
095  * Call all end tag methods in the handler list
096  */
097 public void endElement(String sTag) throws SAXException {
098 	int i;
099 	String sEndMethodName = "end" + sTag;
100 
101 	// Call every tag start method for this tag found in the list of handlers.
102 	for (i = 0; i < _vecHandlers.size(); i++) {
103 		Object oThisHandler = _vecHandlers.elementAt(i);
104 		Method mEndMethod = mFindMethod(oThisHandler, sEndMethodName, _caNoArgs);
105 		if (mEndMethod != null) {
106 			try {
107 				mEndMethod.invoke(oThisHandler, new Object[] {});
108 			} catch (InvocationTargetException ex) {
109 				System.err.println(ex);
110 			} catch (IllegalAccessException ex) {
111 				System.err.println(ex);
112 			}
113 		}
114 	}
115 	popTag();
116 }
117 /**
118  * error method comment.
119  */
120 public void error(SAXParseException ex) throws SAXException {
121 	_seh.error(ex);
122 }
123 /**
124  * fatalError method comment.
125  */
126 public void fatalError(SAXParseException ex) throws SAXException {
127 	_seh.fatalError(ex);
128 }
129 /**
130  * Parse input XML with ShoppingListWriter
131  * @param args java.lang.String[]
132  */
133 public static void main(String args[]) {
134 	if (args.length < 1) {
135 		System.err.println("Usage: lax inputFile.xml [parserClass]");
136 		System.exit(1);
137 	}
138 
139 	String sInputFile = args[0];
140 	String sRecipeFile;
141 	String sShoppingListFile;
142 	String sBase = sInputFile;
143 	
144 	if (sBase.length() > 4 && sBase.toLowerCase().endsWith(".xml")) {
145 		sBase = sBase.substring(0, sBase.length() - 4);
146 	} else {
147 		sInputFile = sBase + ".xml";
148 	}
149 	sRecipeFile = sBase + "-recipe.html";
150 	sShoppingListFile = sBase + "-list.html";
151 
152 	Lax lax = new Lax();
153 
154 	ShoppingListWriter slw = new ShoppingListWriter(sShoppingListFile);
155 	lax.addHandler(slw);
156 	
157 	RecipeWriter rw = new RecipeWriter(sRecipeFile);
158 	lax.addHandler(rw);
159 
160 	lax.parseDocument(true, lax, sInputFile);
161 
162 
163 }
164 /**
165  * Return a method of object oHandler 
166  * with the given name and argument list, or null if not found
167  * @return java.lang.reflect.Method
168  * @param oHandler java.lang.Object - The handler object to search for a method.
169  * @param sTag java.lang.String - The tag to find.
170  */
171 private Method mFindMethod(Object oHandler, String sMethodName, Class[] caArgs) {
172 	Method m = null;
173 	Class classOfHandler = oHandler.getClass();
174 
175 	// Find a method with the given name and argument list
176 	try {
177 		m = classOfHandler.getMethod(sMethodName, caArgs);
178 	} catch (NoSuchMethodException ex) {
179 		// Ignore exception - no such method exists.
180 	}
181 	return m;
182 }
183 /**
184  * Reimplement this method to use a parser from a different vendor. See your
185  * parser package documentation for details.
186  * @param isValidating boolean
187  * @param documentHandler org.xml.sax.DocumentHandler
188  * @param errorHandler org.xml.sax.ErrorHandler
189  * @param sFilename java.lang.String
190  */
191 protected void parseDocument(boolean isValidating, HandlerBase handler, String sFilename) {
192 	try {
193 		// Get a "parser factory", an an object that creates parsers
194 		SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
195 
196 		// Set up the factory to create the appropriate type of parser
197 		saxParserFactory.setValidating(isValidating);
198 		saxParserFactory.setNamespaceAware(false); // Not this month...
199 
200 		SAXParser parser = saxParserFactory.newSAXParser();
201 
202 		parser.parse(new File(sFilename), handler);
203 	} catch (Exception ex) {
204 		System.err.println("Exception: " + ex);
205 		System.exit(2);
206 	}
207 }
208 /**
209  * Pop tag off of tag stack.
210  */
211 private void popTag() {
212 	_vecTags.removeElementAt(_vecTags.size() - 1);
213 }
214 /**
215  * Push tag onto tag stack.
216  * @param sTag java.lang.String
217  */
218 private void pushTag(String sTag) {
219 	_vecTags.addElement(sTag);
220 }
221 /**
222  * Return tag at top of tag stack. At any particular point in the parse,
223  * this string represents the tag being processed.
224  * @return java.lang.String
225  */
226 private String sCurrentTag() {
227 	int iIndex = _vecTags.size() - 1;
228 	if (iIndex >= 0) {
229 		return (String)(_vecTags.elementAt(_vecTags.size() - 1));
230 	} else {
231 		return null;
232 	}
233 }
234 /**
235  * startDocument method comment.
236  */
237 public void startDocument() throws org.xml.sax.SAXException {
238 }
239 /**
240  * Call all start methods for this tag.
241  */
242 public void startElement(String sTag, AttributeList alAttrs) {
243 	int i;
244 	String sStartMethodName = "start" + sTag;
245 
246 	pushTag(sTag);
247 
248 	// Call every tag start method for this tag found in the list of handlers.
249 	for (i = 0; i < _vecHandlers.size(); i++) {
250 		Object oThisHandler = _vecHandlers.elementAt(i);
251 		Method mStartMethod = mFindMethod(oThisHandler, sStartMethodName, _caAttrList);
252 		if (mStartMethod == null) {
253 			mStartMethod = mFindMethod(oThisHandler, sStartMethodName, _caNoArgs);
254 		}
255 		if (mStartMethod != null) {
256 			try {
257 				// Call start method with or without attribute list
258 				Class[] caMethodArgs = mStartMethod.getParameterTypes();
259 				if (caMethodArgs.length == 0) {
260 					mStartMethod.invoke(oThisHandler, new Object[] {});
261 				} else {
262 					mStartMethod.invoke(oThisHandler, new Object[] {alAttrs});
263 				}
264 			} catch (InvocationTargetException ex) {
265 				System.err.println(ex);
266 			} catch (IllegalAccessException ex) {
267 				System.err.println(ex);
268 			}
269 		}
270 	}
271 }
272 /**
273  * warning method comment.
274  */
275 public void warning(SAXParseException ex) throws SAXException {
276 	_seh.warning(ex);
277 }
278 }