fulcrum.xml.Parser.java Source code

Java tutorial

Introduction

Here is the source code for fulcrum.xml.Parser.java

Source

/**
 * Copyright (c)2012, Rational Developers; Ryan McGuinness
 * All rights reserved
 * Site: http://www.rationaldevelopers.com/fulcrum-xml
 * License: http://www.rationaldevelopers.com/fulcrum-xml/license.txt
 * Read Me: http://www.rationaldevelopers.com/fulcrum-xml/readme.txt
 *.
 */
package fulcrum.xml;

import static fulcrum.xml.XMLConstants.AT;
import static fulcrum.xml.XMLConstants.FORWARD_SLASH;
import static fulcrum.xml.XMLConstants.REGEX_SPACE;
import static fulcrum.xml.XMLConstants.SPACE;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Stack;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.apache.commons.vfs2.FileContent;
import org.apache.commons.vfs2.FileObject;
import org.apache.commons.vfs2.FileSystemManager;
import org.apache.commons.vfs2.VFS;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

/**
 * 
 * @author Rational Developers
 * @author Ryan McGuinness
 * 
 *         This is the default parser for XML streams. Currently using SAX but
 *         may offer a pull parser later. Currently the parser is tightly
 *         coupled with the Document object that uses it.
 * 
 */
public class Parser extends DefaultHandler {
    private static final Logger LOGGER = LoggerFactory.getLogger(Parser.class);

    public static final String ERR_01 = "Invalid file name passed to document parser: ";

    private static final SAXParserFactory SAX_PARSE_FACTORY = SAXParserFactory.newInstance();

    private static FileSystemManager fsManager;

    static {
        SAX_PARSE_FACTORY.setValidating(true);
        SAX_PARSE_FACTORY.setNamespaceAware(true);
        SAX_PARSE_FACTORY.setXIncludeAware(true);

        try {
            fsManager = VFS.getManager();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private Set<Namespace> namespaces = new HashSet<Namespace>();
    private Stack<Element> elements = new Stack<Element>();
    private StringBuilder xPathBuilder = new StringBuilder();
    private StringBuilder textBuilder = new StringBuilder();
    private Document document = null;

    private void addXPath(String path, Node e) {
        Map<String, List<Node>> xPathMap = document.getxPathMap();
        if (xPathMap != null) {
            if (xPathMap.containsKey(path)) {
                xPathMap.get(path).add(e);
            } else {
                List<Node> lElements = new ArrayList<Node>();
                lElements.add(e);
                xPathMap.put(path, lElements);
            }
        }
    }

    private static SAXParser getParser() throws ParserConfigurationException, SAXException {
        return SAX_PARSE_FACTORY.newSAXParser();
    }

    /**
     * Only provides parsing functions to the "fulcrum.xml" package.
     * 
     * @see Document
     * 
     * @param fileLocation
     * @param document
     * @throws ParseException
     */
    protected void parse(String fileLocation, Document document) throws ParseException {
        FileObject fileObj = null;
        try {
            fileObj = fsManager.resolveFile(fileLocation);

            if (fileObj != null && fileObj.exists() && fileObj.isReadable()) {
                FileContent content = fileObj.getContent();
                InputStream is = content.getInputStream();
                int size = is.available();
                LOGGER.debug("Total File Size: " + size + " bytes");
                byte[] buffer = new byte[size];
                is.read(buffer, 0, size);
                LOGGER.debug("Start parsing");
                parse(buffer, document);
                LOGGER.debug("Finished paring");
                buffer = null;
                content.close();
                fileObj.close();
            }
        } catch (Exception e) {
            throw new ParseException(e);
        }
    }

    /**
     * * Only provides parsing functions to the "fulcrum.xml" package.
     * 
     * @see Document
     * 
     * @param xmlDocument
     * @param document
     * @throws ParseException
     */
    protected void parse(byte[] xmlDocument, Document document) throws ParseException {
        try {
            this.document = document;
            SAXParser sp = getParser();
            ByteArrayInputStream bais = new ByteArrayInputStream(xmlDocument);
            sp.parse(bais, this);
        } catch (Exception e) {
            throw new ParseException(e);
        }
    }

    /**
     * * Only provides parsing functions to the "fulcrum.xml" package.
     * 
     * @see Document
     * 
     * @param f
     * @param document
     * @throws ParseException
     */
    protected void parse(File f, Document document) throws ParseException {
        this.document = document;
        try {
            SAXParser sp = getParser();
            sp.parse(f, this);
        } catch (Exception e) {
            throw new ParseException(e);
        }
    }

    @Override
    public void startPrefixMapping(String prefix, String uri) throws SAXException {
        Namespace ns = new Namespace(prefix, uri);
        if (!namespaces.contains(ns)) {
            namespaces.add(ns);
        }
    }

    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes)
            throws SAXException {
        textBuilder.setLength(0);
        Element c = new Element(qName, uri);
        xPathBuilder.append(FORWARD_SLASH).append(localName);

        addXPath(xPathBuilder.toString(), c);
        for (int i = 0; i < attributes.getLength(); i++) {
            Attribute a = new Attribute(attributes.getQName(i), attributes.getURI(i), attributes.getValue(i));
            addXPath(xPathBuilder.toString() + AT + a.getLocalName(), a);
            c.addAttribute(a);
        }
        elements.push(c);
    }

    @Override
    public void characters(char[] c, int start, int end) throws SAXException {
        textBuilder.append(c, start, end);
    }

    @Override
    public void endElement(String uri, String localName, String qName) throws SAXException {
        if (elements.size() != 1) {
            Element c = elements.pop();
            if (textBuilder != null && textBuilder.length() > 0) {
                String v = textBuilder.toString();
                c.setText(v.replaceAll(REGEX_SPACE, SPACE).trim());
                textBuilder.setLength(0);
            }
            xPathBuilder.setLength(xPathBuilder.lastIndexOf(FORWARD_SLASH));
            elements.peek().addElement(c);
        }
    }

    @Override
    public void endDocument() throws SAXException {
        super.endDocument();
        Element root = elements.firstElement();
        document.setRoot(root);
        this.elements = null;
        this.namespaces = null;
        this.xPathBuilder = null;
        this.textBuilder = null;
    }
}