net.xy.jcms.controller.configurations.parser.TranslationParser.java Source code

Java tutorial

Introduction

Here is the source code for net.xy.jcms.controller.configurations.parser.TranslationParser.java

Source

/**
 * This file is part of XY.JCms, Copyright 2010 (C) Xyan Kruse, Xyan@gmx.net, Xyan.kilu.de
 * 
 * XY.JCms is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * XY.JCms 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 General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with XY.JCms. If not, see <http://www.gnu.org/licenses/>.
 */
package net.xy.jcms.controller.configurations.parser;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;

import net.xy.jcms.controller.configurations.pool.ConverterPool;
import net.xy.jcms.controller.translation.RuleParameter;
import net.xy.jcms.controller.translation.TranslationRule;
import net.xy.jcms.shared.InitializableController;

/**
 * parser for translation rules xml configuration files
 * 
 * @author Xyan
 * 
 */
public class TranslationParser {
    /**
     * logger
     */
    private final static Logger LOG = Logger.getLogger(TranslationParser.class);

    /**
     * parses an xml configuration from an input streams. throwes
     * IllegalArgumentExceptions in case of syntax error.
     * 
     * @param in
     * @return value
     * @throws XMLStreamException
     * @throws ClassNotFoundException
     *             in case there are problems with an params type converter
     */
    public static TranslationRule[] parse(final InputStream in, final ClassLoader loader)
            throws XMLStreamException, ClassNotFoundException {
        @SuppressWarnings("deprecation")
        final XMLInputFactory factory = XMLInputFactory.newInstance(
                "com.sun.xml.internal.stream.XMLInputFactoryImpl", TranslationParser.class.getClassLoader());
        LOG.info("XMLInputFactory loaded: " + factory.getClass().getName());
        factory.setProperty("javax.xml.stream.isCoalescing", true);
        // not supported be the reference implementation
        // factory.setProperty(XMLInputFactory.IS_VALIDATING, Boolean.TRUE);
        final XMLStreamReader parser = factory.createXMLStreamReader(in);
        while (parser.hasNext()) {
            final int event = parser.next();
            if (event == XMLStreamConstants.START_ELEMENT && parser.getName().getLocalPart().equals("rules")) {
                return parseRules(parser, loader);
            }
        }
        throw new IllegalArgumentException("No rules section found.");
    }

    /**
     * parses an single file translation
     * 
     * @param in
     * @param loader
     * @return value
     * @throws XMLStreamException
     * @throws ClassNotFoundException
     *             in case there are problems with an params type converter
     */
    public static TranslationRule parseSingle(final InputStream in, final ClassLoader loader)
            throws XMLStreamException, ClassNotFoundException {
        @SuppressWarnings("deprecation")
        final XMLInputFactory factory = XMLInputFactory.newInstance(
                "com.sun.xml.internal.stream.XMLInputFactoryImpl", TranslationParser.class.getClassLoader());
        LOG.info("XMLInputFactory loaded: " + factory.getClass().getName());
        factory.setProperty("javax.xml.stream.isCoalescing", true);
        final XMLStreamReader parser = factory.createXMLStreamReader(in);
        while (parser.hasNext()) {
            final int event = parser.next();
            if (event == XMLStreamConstants.START_ELEMENT && parser.getName().getLocalPart().equals("rule")) {
                return parseRule(parser, loader);
            }
        }
        throw new IllegalArgumentException("No rules section found.");
    }

    /**
     * goes over any <rule reactOn="^du" buildOff="du" usecase="contentgroup">
     * 
     * @param parser
     * @return value
     * @throws XMLStreamException
     * @throws ClassNotFoundException
     * @throws IllegalAccessException
     * @throws InstantiationException
     */
    private static TranslationRule[] parseRules(final XMLStreamReader parser, final ClassLoader loader)
            throws XMLStreamException, ClassNotFoundException {
        final List<TranslationRule> rules = new LinkedList<TranslationRule>();
        while (parser.nextTag() == XMLStreamConstants.START_ELEMENT) {
            if (parser.getLocalName().equals("rule")) {
                rules.add(parseRule(parser, loader));
            } else {
                throw new IllegalArgumentException("Syntax error nothing allowed between rule sections.");
            }
        }
        return rules.toArray(new TranslationRule[rules.size()]);
    }

    /**
     * parses the attributes <rule reactOn="^du" buildOff="du"
     * usecase="contentgroup">
     * 
     * @param parser
     * @return value
     * @throws XMLStreamException
     * @throws ClassNotFoundException
     * @throws IllegalAccessException
     * @throws InstantiationException
     */
    private static TranslationRule parseRule(final XMLStreamReader parser, final ClassLoader loader)
            throws XMLStreamException, ClassNotFoundException {
        String reactOn = null, buildOff = null, usecase = null;
        List<RuleParameter> parameters = null;
        if (parser.getAttributeCount() != 3) {
            throw new IllegalArgumentException("There are to much or few attributes specified for rule.");
        }
        for (int i = 0; i < 3; i++) {
            if (parser.getAttributeLocalName(i).equals("reactOn")) {
                reactOn = parser.getAttributeValue(i);
            } else if (parser.getAttributeLocalName(i).equals("buildOff")) {
                buildOff = parser.getAttributeValue(i);
            } else if (parser.getAttributeLocalName(i).equals("usecase")) {
                usecase = parser.getAttributeValue(i);
            }
        }
        parameters = parseParameter(parser, loader);

        if (StringUtils.isBlank(reactOn)) {
            throw new IllegalArgumentException("ReactOn has to be set");
        } else if (StringUtils.isBlank(buildOff)) {
            throw new IllegalArgumentException("BuildOff has to be set");
        } else if (StringUtils.isBlank(usecase)) {
            throw new IllegalArgumentException("UsecaseId has to be set");
        } else if (parameters == null) {
            throw new IllegalArgumentException("Error on parsing parameters");
        } else {
            return new TranslationRule(reactOn, buildOff, usecase, parameters);
        }
    }

    /**
     * checks for parameters <parameter name="contentgroup" group="1"
     * convert="de.jamba.ContentGroupConverter"/>
     * 
     * @param parser
     * @return value
     * @throws XMLStreamException
     * @throws ClassNotFoundException
     * @throws IllegalAccessException
     * @throws InstantiationException
     */
    private static List<RuleParameter> parseParameter(final XMLStreamReader parser, final ClassLoader loader)
            throws XMLStreamException, ClassNotFoundException {
        final List<RuleParameter> params = new ArrayList<RuleParameter>();
        while (parser.nextTag() == XMLStreamConstants.START_ELEMENT) {
            String parameterName = null, converter = null;
            Integer aplicatesToGroup = null;
            if (parser.getAttributeCount() != 3 && parser.getAttributeCount() != 2) {
                throw new IllegalArgumentException("There are to much or few attributes specified for parameter.");
            }
            for (int i = 0; i < parser.getAttributeCount(); i++) {
                if (parser.getAttributeLocalName(i).equals("name")) {
                    parameterName = parser.getAttributeValue(i);
                } else if (parser.getAttributeLocalName(i).equals("convert")) {
                    converter = parser.getAttributeValue(i);
                } else if (parser.getAttributeLocalName(i).equals("group")) {
                    aplicatesToGroup = new Integer(parser.getAttributeValue(i));
                }
            }

            boolean goEnd = true;
            Map<String, String> mappings = null;
            if (parser.next() == XMLStreamConstants.CHARACTERS) {
                final String mappingStr = parser.getText();
                // get integrated mapping body
                if (StringUtils.isNotBlank(mappingStr)) {
                    mappings = new HashMap<String, String>();
                    final String[] lines = mappingStr.split("\n");
                    for (String line : lines) {
                        line = line.trim();
                        if (StringUtils.isBlank(line) || line.startsWith("#")) {
                            continue;
                        }
                        final String[] pair = line.split("=", 2);
                        mappings.put(pair[0].trim(), pair[1].trim());
                    }
                }
            } else {
                goEnd = false; // allready on end
            }

            if (StringUtils.isBlank(parameterName)) {
                throw new IllegalArgumentException("Parameter name has to be set");
            } else if (StringUtils.isBlank(converter)) {
                throw new IllegalArgumentException("Parameter Converter has to be set");
            } else if (aplicatesToGroup == null) {
                throw new IllegalArgumentException("Applicates to regex group has to be set");
            } else {
                if (mappings != null) {
                    // get special mapping converter
                    params.add(new RuleParameter(parameterName, aplicatesToGroup,
                            ((InitializableController<?>) ConverterPool.get(converter, loader))
                                    .initialize(mappings)));
                } else {
                    // get normal converter
                    params.add(new RuleParameter(parameterName, aplicatesToGroup,
                            ConverterPool.get(converter, loader)));
                }
            }
            if (goEnd) {
                parser.nextTag(); // gets endtag
            }
        }
        return params;
    }
}