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

Java tutorial

Introduction

Here is the source code for net.xy.jcms.controller.configurations.parser.FragmentXMLParser.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.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang.StringUtils;

import net.xy.jcms.controller.configurations.pool.ComponentPool;
import net.xy.jcms.shared.IFragment;
import net.xy.jcms.shared.JCmsHelper;
import net.xy.jcms.shared.compiler.DynamicFragment;

/**
 * parses an dynamic fragment xml to an fragment instance
 * 
 * @author Xyan
 * 
 */
public class FragmentXMLParser {
    /**
     * mask instructions ass sgml/xml comments to not influence diverse dialects
     */
    private final static String BEGIN = "<!--";
    private final static String END = "-->";

    /**
     * pattern for an component instruction. masks are for back conversion
     */
    public final static Pattern COMPONENT = Pattern.compile(
            "^component name=\"([a-z0-9._\\-]{3,})\" class=\"([a-z0-9._\\-]{3,})\"", Pattern.CASE_INSENSITIVE);
    /**
     * back conversion use with printf and 2 parameters
     */
    public final static String COMPONENTMASK = BEGIN + "component name=\"%s\" class=\"%s\"" + END;

    /**
     * pattern for an template inclusion. masks are for back conversion
     */
    public final static Pattern TEMPLATE = Pattern.compile("^template name=\"([a-z0-9._\\-]{3,})\"",
            Pattern.CASE_INSENSITIVE);
    /**
     * back conversion use with printf and 1 parameter
     */
    public final static String TEMPLATEMASK = BEGIN + "template name=\"%s\"" + END;

    /**
     * reads an input stream as texdata and converts to an string object
     * 
     * @param stream
     * @return
     */
    private static String getStringFromStream(final InputStream stream) {
        final StringBuilder writer = new StringBuilder();
        final BufferedReader reader = new BufferedReader(new InputStreamReader(stream), 1024);
        final char[] buffer = new char[1024];
        try {
            int n;
            while ((n = reader.read(buffer)) != -1) {
                writer.append(buffer, 0, n);
            }
        } catch (final IOException e) {
        }
        return writer.toString();
    }

    /**
     * parse an dynamic fragment out from an string
     * 
     * @param classPath
     *            names resource origin of the stream
     * @param stream
     *            converted to an string
     * @param loader
     * @return fragment
     * @throws ClassNotFoundException
     * @throws IOException
     */
    public static IFragment parse(final String classPath, final String stream, final ClassLoader loader)
            throws ClassNotFoundException {
        final DynamicFragment ret = new DynamicFragment(classPath);
        int pointer = 0; // where every run begins
        do {

            final int beginPos = stream.indexOf(BEGIN, pointer);
            if (beginPos == -1) {
                // not more found
                ret.addStatic(stream.substring(pointer));
                break;
            }

            final int endPos = stream.indexOf(END, beginPos);
            if (endPos == -1) {
                // not end found
                ret.addStatic(stream.substring(pointer));
                break;
            }
            ret.addStatic(stream.substring(pointer, beginPos));
            pointer = endPos + END.length();

            final String comment = stream.substring(beginPos + BEGIN.length(), endPos).trim();
            Matcher match = COMPONENT.matcher(comment);
            if (match.matches()) {
                // found component
                ret.addChild(match.group(1).trim(), ComponentPool.get(match.group(2).trim(), loader));
            } else {
                match = TEMPLATE.matcher(comment);
                if (match.matches()) {
                    // found template
                    ret.addFragment(match.group(1).trim());
                }
            }
        } while (true);
        return ret;
    }

    /**
     * parses an dynamic fragment from an inputstream
     * 
     * @param classPath
     *            of resource to load
     * @param loader
     *            for loading component instances
     * @return value
     * @throws ClassNotFoundException
     * @throws IOException
     */
    public static IFragment parse(final String classPath, final ClassLoader loader)
            throws ClassNotFoundException, IOException {
        final InputStream st = JCmsHelper.loadResource(classPath, loader);
        String stream = null;
        if (st != null) {
            stream = getStringFromStream(st);
        }
        if (StringUtils.isBlank(stream)) {
            throw new IllegalArgumentException("Stream could not be read or is empty");
        }
        return parse(classPath, stream, loader);
    }
}