/******************************************************************************* * Copyright (c) 2008 Scott Stanchfield. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Based on the ANTLR parser generator by Terence Parr, http://antlr.org * Ric Klaren <klaren@cs.utwente.nl> * Scott Stanchfield - Modifications for XML Parsing *******************************************************************************/ package com.javadude.antxr.scanner; import java.io.Reader; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Map; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlPullParserFactory; import com.javadude.antxr.Parser; import com.javadude.antxr.Token; import com.javadude.antxr.TokenStream; import com.javadude.antxr.TokenStreamException; /** * A simple implementation of XMLPullTokenStream that uses kxml as its * implementation */ public class BasicKXml2XMLPullTokenStream implements TokenStream { private XMLPullTokenStream tokenStream; private static final Class<?>[] NO_PARAMETERS = new Class[] {}; private static final Object[] NO_ARGUMENTS = new Object[] {}; /** * Creates an instance of the KXml token stream * @param xmlToParse the xml stream to parse * @param parserClass the generated parser class * @param namespaceAware do we want a namespace aware parse * */ public BasicKXml2XMLPullTokenStream(Reader xmlToParse, Class<? extends Parser> parserClass, boolean namespaceAware) { // Create the XmlPull parser (really part of the scanner) try { XmlPullParserFactory factory = XmlPullParserFactory.newInstance("org.kxml2.io.KXmlParser", null); factory.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, namespaceAware); XmlPullParser parser = factory.newPullParser(); parser.setInput(xmlToParse); Field field = parserClass.getField("_tokenNames"); String[] tokenNames = (String[])field.get(null); Method getNameSpaceMapMethod = parserClass.getMethod("getNamespaceMap", BasicKXml2XMLPullTokenStream.NO_PARAMETERS); @SuppressWarnings("unchecked") Map<String, String> namespaceMap = (Map<String, String>)getNameSpaceMapMethod.invoke(null, BasicKXml2XMLPullTokenStream.NO_ARGUMENTS); // Create our scanner (using the xml pull parser) tokenStream = new XMLPullTokenStream(tokenNames, namespaceMap, parser); } catch (XmlPullParserException e) { throw new RuntimeException("Exception thrown setting up KXml parser. See nested exception.",e); } catch (NoSuchFieldException e) { throw new IllegalArgumentException("Cannot find _tokenNames in the parser class -- is it an XML parser?"); } catch (NoSuchMethodException e) { throw new IllegalArgumentException("Cannot find getNamespaceMap() in the parser class -- is it an XML parser?"); } catch (IllegalArgumentException e) { throw new IllegalArgumentException("Cannot access _tokenNames or getNamespaceMap() in the parser class (they should be static)"); } catch (IllegalAccessException e) { throw new IllegalArgumentException("Cannot access _tokenNames or getNamespaceMap() in the parser class (they should be public)"); } catch (InvocationTargetException e) { throw new RuntimeException("Exception thrown when running getNamespaceMap(). See nested exception.", e); } } /** {@inheritDoc} */ public Token nextToken() throws TokenStreamException { return tokenStream.nextToken(); } }