com.puppycrawl.tools.checkstyle.XmlContentHandler.java Source code

Java tutorial

Introduction

Here is the source code for com.puppycrawl.tools.checkstyle.XmlContentHandler.java

Source

////////////////////////////////////////////////////////////////////////////////
// checkstyle: Checks Java source code for adherence to a set of rules.
// Copyright (C) 2001-2011  Oliver Burn
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
////////////////////////////////////////////////////////////////////////////////

package com.puppycrawl.tools.checkstyle;

import com.puppycrawl.tools.checkstyle.api.DetailAST;
import com.puppycrawl.tools.checkstyle.api.XmlTokenTypes;
import java.io.File;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.LocatorImpl;

/**
 * XML parser used to build an AST tree of a document.
 * 
 * @author Yoann Ciabaud<y.ciabaud@gmail.com>
 */
public class XmlContentHandler implements ContentHandler {

    /** Stores the location of the parser in the file. */
    private Locator locator;

    /** Root of the AST tree. */
    private DetailAST root;

    /** Pointer on the last parsed node. */
    private DetailAST currentNode;

    /** Document beeing parsed. */
    private File file;

    /** logger for debug purpose. */
    private static final Log LOG = LogFactory.getLog("com.puppycrawl.tools.checkstyle.XmlContentHandler");

    /**
     * Default constructor. 
     */
    public XmlContentHandler(File file) {
        super();

        locator = new LocatorImpl();
        root = null;
        this.file = file;
    }

    /** {@inheritDoc} */
    @Override
    public void setDocumentLocator(Locator value) {
        locator = value;
    }

    /** {@inheritDoc} */
    @Override
    public void startDocument() throws SAXException {
        LOG.debug("Starting XML parsing");

        // XmlToken
        XmlToken token = new XmlToken();
        token.setLine(locator.getLineNumber());
        token.setColumn(locator.getColumnNumber());
        token.setType(XmlTokenTypes.DOCUMENT);
        token.setText(file.getName());

        // Node
        root = new DetailAST();
        root.initialize(token);

        currentNode = root;

        // Path = package
        token = new XmlToken();
        token.setLine(locator.getLineNumber());
        token.setColumn(locator.getColumnNumber());
        token.setType(XmlTokenTypes.PATH);
        token.setText(file.getParent());
        DetailAST path = new DetailAST();
        path.initialize(token);
        root.addChild(path);
        DetailAST pathIdent = new DetailAST();
        token = new XmlToken();
        token.setLine(locator.getLineNumber());
        token.setColumn(locator.getColumnNumber());
        token.setType(XmlTokenTypes.IDENT);
        token.setText(file.getParent());
        pathIdent.initialize(token);
        path.addChild(pathIdent);

        // Fake child to match Java grammar structure
        pathIdent = new DetailAST();
        pathIdent.initialize(token);
        path.addChild(pathIdent);

        // Name = Type
        token = new XmlToken();
        token.setLine(locator.getLineNumber());
        token.setColumn(locator.getColumnNumber());
        token.setType(XmlTokenTypes.IDENT);
        token.setText(file.getName());
        DetailAST name = new DetailAST();
        name.initialize(token);
        root.addChild(name);
        DetailAST nameIdent = new DetailAST();
        token = new XmlToken();
        token.setLine(locator.getLineNumber());
        token.setColumn(locator.getColumnNumber());
        token.setType(XmlTokenTypes.IDENT);
        token.setText(file.getName());
        nameIdent.initialize(token);
        name.addChild(nameIdent);
    }

    /** {@inheritDoc} */
    public void endDocument() throws SAXException {
        LOG.debug("Ended parsing");
    }

    /** {@inheritDoc} */
    public void startPrefixMapping(String prefix, String URI) throws SAXException {
        LOG.debug("Prefix mapping : " + URI + ", chosen prefix : " + prefix);

        // XmlToken
        XmlToken token = new XmlToken();
        token.setLine(locator.getLineNumber());
        token.setColumn(locator.getColumnNumber());
        token.setText(prefix);
        token.setType(XmlTokenTypes.PREFIX_MAPPING);

        // Node
        DetailAST child = new DetailAST();
        child.initialize(token);

        // Prefix
        token = new XmlToken();
        token.setLine(locator.getLineNumber());
        token.setColumn(locator.getColumnNumber());
        token.setText(prefix);
        token.setType(XmlTokenTypes.IDENT);

        DetailAST prefixAST = new DetailAST();
        prefixAST.initialize(token);
        prefixAST.setText(token.getText());

        child.addChild(prefixAST);

        // URI
        token = new XmlToken();
        token.setLine(locator.getLineNumber());
        token.setColumn(locator.getColumnNumber());
        token.setText(URI);
        token.setType(XmlTokenTypes.STRING_LITERAL);

        DetailAST uri = new DetailAST();
        uri.initialize(token);

        child.addChild(uri);

        // Parent
        currentNode.addChild(child);

    }

    /** {@inheritDoc} */
    public void endPrefixMapping(String prefix) throws SAXException {
        LOG.debug("End of prefix mapping : " + prefix);
    }

    /** {@inheritDoc} */
    public void startElement(String nameSpaceURI, String localName, String rawName, Attributes attributs)
            throws SAXException {
        LOG.debug("Opening element : " + localName);

        int col = locator.getColumnNumber();

        // XmlToken
        XmlToken token = new XmlToken();
        token.setLine(locator.getLineNumber());
        token.setColumn(locator.getColumnNumber());
        token.setText(rawName);
        token.setType(XmlTokenTypes.ELEMENT);

        // Node
        DetailAST child = new DetailAST();
        child.initialize(token);

        // Parent
        currentNode.addChild(child);

        // Ident
        DetailAST ident = new DetailAST();
        token = new XmlToken();
        token.setLine(locator.getLineNumber());
        col++;
        token.setColumn(col);
        token.setText(localName);
        token.setType(XmlTokenTypes.IDENT);
        ident.initialize(token);
        child.addChild(ident);

        // Attributes
        LOG.debug("  Attributes : ");
        DetailAST attrs = new DetailAST();
        token = new XmlToken();
        token.setLine(locator.getLineNumber());
        col += rawName.length() + 1;
        token.setColumn(col);
        token.setText(rawName);
        token.setType(XmlTokenTypes.ATTRIBUTES);
        attrs.initialize(token);
        child.addChild(attrs);

        for (int index = 0; index < attributs.getLength(); index++) {

            // Attribut
            DetailAST attr = new DetailAST();
            token = new XmlToken();
            token.setLine(locator.getLineNumber());
            token.setColumn(index);
            token.setText(rawName);
            token.setType(XmlTokenTypes.ATTRIBUTE);
            attr.initialize(token);
            attrs.addChild(attr);
            LOG.debug("     - " + attributs.getLocalName(index) + " = " + attributs.getValue(index));

            // Ident
            ident = new DetailAST();
            token = new XmlToken();
            token.setLine(locator.getLineNumber());
            token.setColumn(index);
            token.setText(attributs.getLocalName(index));
            token.setType(XmlTokenTypes.IDENT);
            ident.initialize(token);
            attr.addChild(ident);

            // Value
            DetailAST value = new DetailAST();
            token = new XmlToken();
            token.setLine(locator.getLineNumber());
            token.setColumn(index + attributs.getLocalName(index).length() + 1);
            token.setText(attributs.getValue(index));
            token.setType(XmlTokenTypes.STRING_LITERAL);
            value.initialize(token);
            attr.addChild(value);

            // Go forward
            col += attributs.getLocalName(index).length() + attributs.getValue(index).length() + 2;
        }

        // This node is now he current node
        currentNode = child;
    }

    /** {@inheritDoc} */
    public void endElement(String nameSpaceURI, String localName, String rawName) throws SAXException {
        LOG.debug("End of the element : " + localName);

        // Go to the parent
        currentNode = currentNode.getParent();

    }

    /** {@inheritDoc} */
    public void characters(char[] ch, int start, int end) throws SAXException {

        String value = new String(ch, start, end);

        LOG.debug("#PCDATA : " + value);

        // XmlToken
        XmlToken token = new XmlToken();
        token.setLine(locator.getLineNumber());
        token.setColumn(locator.getColumnNumber() + start);
        token.setText(value);
        token.setType(XmlTokenTypes.PCDATA);

        // Node
        DetailAST child = new DetailAST();
        child.initialize(token);
        child.setText(token.getText());

        // Parent
        currentNode.addChild(child);

    }

    /** {@inheritDoc} */
    public void ignorableWhitespace(char[] ch, int start, int end) throws SAXException {

        String value = new String(ch, start, end);

        LOG.debug("ignorable whitespace : ..." + value + "...");

        // XmlToken
        XmlToken token = new XmlToken();
        token.setLine(locator.getLineNumber());
        token.setColumn(locator.getColumnNumber() + start);
        token.setText(value);
        token.setType(XmlTokenTypes.WHITE_SPACE);

        // Node
        DetailAST child = new DetailAST();
        child.initialize(token);
        child.setText(token.getText());

        // Parent
        currentNode.addChild(child);
    }

    /** {@inheritDoc} */
    public void processingInstruction(String target, String data) throws SAXException {
        LOG.debug("Processing instruction : " + target);
        LOG.debug("  Args : " + data);

        // XmlToken
        XmlToken token = new XmlToken();
        token.setLine(locator.getLineNumber());
        token.setColumn(locator.getColumnNumber());
        token.setText(target);
        token.setType(XmlTokenTypes.PROCESSING_INSTRUCTION);

        // Node
        DetailAST child = new DetailAST();
        child.initialize(token);
        child.setText(token.getText());

        // Target
        token = new XmlToken();
        token.setLine(locator.getLineNumber());
        token.setColumn(locator.getColumnNumber());
        token.setText(target);
        token.setType(XmlTokenTypes.PROCESSING_TARGET);

        DetailAST targetAST = new DetailAST();
        targetAST.initialize(token);
        targetAST.setText(token.getText());
        child.addChild(targetAST);

        // Data
        token = new XmlToken();
        token.setLine(locator.getLineNumber());
        token.setColumn(locator.getColumnNumber());
        token.setText(data);
        token.setType(XmlTokenTypes.PROCESSING_DATA);

        DetailAST dataAST = new DetailAST();
        dataAST.initialize(token);
        dataAST.setText(token.getText());
        child.addChild(dataAST);

        // Parent
        currentNode.addChild(child);
    }

    /** {@inheritDoc} */
    public void skippedEntity(String text) throws SAXException {

        // XmlToken
        XmlToken token = new XmlToken();
        token.setLine(locator.getLineNumber());
        token.setColumn(locator.getColumnNumber());
        token.setText(text);
        token.setType(XmlTokenTypes.SKIPPED_ENTITY);

        // Node
        DetailAST child = new DetailAST();
        child.initialize(token);
        child.setText(token.getText());

        // Parent
        currentNode.addChild(child);
    }

    /** {@inheritDoc} */
    public DetailAST getAST() {
        return root;
    }
}