com.spoledge.audao.generator.GeneratorFlow.java Source code

Java tutorial

Introduction

Here is the source code for com.spoledge.audao.generator.GeneratorFlow.java

Source

/*
 * Copyright 2010 Spolecne s.r.o. (www.spoledge.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.spoledge.audao.generator;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Reader;

import java.util.ArrayList;
import java.util.Enumeration;
import java.util.LinkedHashSet;
import java.util.Properties;
import java.util.Set;

import javax.xml.transform.ErrorListener;
import javax.xml.transform.Result;
import javax.xml.transform.Templates;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

import com.spoledge.util.xslt.TemplatesCache;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * This is actualy the worker.
 */
public class GeneratorFlow implements ErrorListener {

    private Generator generator;
    private String pkgName;
    private String dirName;
    private Reader xmlReader;
    private Output output;

    private String xmlPreprocessed;
    private Properties listProps;
    private Set<String> tableNames;

    private byte[] buffer;

    private ArrayList<TransformerException> exceptions;
    private ArrayList<GeneratorException.Type> exceptionTypes;
    private boolean isFatalError = false;

    private Log log = LogFactory.getLog(getClass());

    ////////////////////////////////////////////////////////////////////////////
    // Constructors
    ////////////////////////////////////////////////////////////////////////////

    public GeneratorFlow(Generator generator, String pkgName, Reader xmlReader, Output output) {
        this.generator = generator;
        this.pkgName = pkgName;
        this.xmlReader = xmlReader;
        this.output = output;

        dirName = "dao/" + pkgName.replace('.', '/') + '/';
    }

    ////////////////////////////////////////////////////////////////////////////
    // Public
    ////////////////////////////////////////////////////////////////////////////

    public void generate(ResourceType type) throws IOException, TransformerException {
        switch (type) {
        case DTO:
            generateDtos();
            break;
        case DTO_IMPL:
            generateDtoImpls();
            break;
        case DTO_GWT_SERIALIZER:
            generateDtoGwtSerializers();
            break;
        case DAO:
            generateDaos();
            break;
        case DAO_IMPL:
            generateDaoImpls();
            break;
        case FACTORY:
            generateFactory();
            break;
        case FACTORY_IMPL:
            generateFactoryImpl();
            break;
        case SQL_CREATE:
            generateSqlCreate();
            break;
        case SQL_DROP:
            generateSqlDrop();
            break;
        case AUDAO_JAVA:
            generateAudaoJava();
            break;
        default:
            log.warn("generate(): unknown resource type " + type);
        }
    }

    public void generateDtos() throws IOException, TransformerException {
        Transformer transformer = getTransformer(ResourceType.DTO);
        String path = dirName + "dto/";

        for (String tableName : getTableNames()) {
            if (hasDto(tableName)) {
                transformer.setParameter("table_name", tableName);
                transformer.transform(getSource(), output.addResult(file(path, tableName, "")));
            }
        }
    }

    public void generateDtoGwtSerializers() throws IOException, TransformerException {
        Transformer transformer = getTransformer(ResourceType.DTO_GWT_SERIALIZER);
        String path = dirName + "dto/";

        for (String tableName : getTableNames()) {
            if (hasDto(tableName)) {
                transformer.setParameter("table_name", tableName);
                transformer.transform(getSource(),
                        output.addResult(file(path, tableName, "_CustomFieldSerializer")));
            }
        }
    }

    public void generateDtoImpls() throws IOException, TransformerException {
        Transformer transformer = getTransformer(ResourceType.DTO_IMPL);

        if (transformer == null)
            return;

        String path = dirName + "dto/" + generator.getTarget().getIdentifier() + '/';

        for (String tableName : getTableNames()) {
            if (hasDto(tableName)) {
                transformer.setParameter("table_name", tableName);
                transformer.transform(getSource(), output.addResult(file(path, tableName, "Impl")));
            }
        }
    }

    public void generateDaos() throws IOException, TransformerException {
        Transformer transformer = getTransformer(ResourceType.DAO);
        String path = dirName + "dao/";

        for (String tableName : getTableNames()) {
            transformer.setParameter("table_name", tableName);
            transformer.transform(getSource(), output.addResult(file(path, tableName, "Dao")));
        }
    }

    public void generateDaoImpls() throws IOException, TransformerException {
        Transformer transformer = getTransformer(ResourceType.DAO_IMPL);
        setDbType(transformer);

        String path = dirName + "dao/" + generator.getTarget().getIdentifier() + '/';

        for (String tableName : getTableNames()) {
            transformer.setParameter("table_name", tableName);
            transformer.transform(getSource(), output.addResult(file(path, tableName, "DaoImpl")));
        }
    }

    public void generateFactory() throws IOException, TransformerException {
        String path = dirName + "dao/DaoFactory.java";
        Transformer transformer = getTransformer(ResourceType.FACTORY);
        setDbType(transformer);
        transformer.transform(getSource(), output.addResult(path));
    }

    public void generateFactoryImpl() throws IOException, TransformerException {
        String path = dirName + "dao/" + generator.getTarget().getIdentifier() + "/DaoFactoryImpl.java";
        Transformer transformer = getTransformer(ResourceType.FACTORY_IMPL);
        setDbType(transformer);
        transformer.transform(getSource(), output.addResult(path));
    }

    public void generateSqlCreate() throws IOException, TransformerException {
        generateSql(ResourceType.SQL_CREATE, "sql/create-tables.sql");
    }

    public void generateSqlDrop() throws IOException, TransformerException {
        generateSql(ResourceType.SQL_DROP, "sql/drop-tables.sql");
    }

    public void generateAudaoJava() throws IOException {
        for (String resourceKey : generator.getJavaResourceKeys()) {
            copy(Generator.JAVA_RESOURCES + '/' + resourceKey, "dao/" + resourceKey);
        }
    }

    /**
     * Returns true if it caught at least error or warning.
     */
    public boolean hasExceptions() {
        return exceptions != null;
    }

    /**
     * Returns all caught exceptions.
     * @return the array or null
     */
    public ArrayList<TransformerException> getExceptions() {
        return exceptions;
    }

    /**
     * Returns all caught exception types.
     * @return the array or null
     */
    public ArrayList<GeneratorException.Type> getExceptionTypes() {
        return exceptionTypes;
    }

    ////////////////////////////////////////////////////////////////////////////
    // ErrorListener
    ////////////////////////////////////////////////////////////////////////////

    public void warning(TransformerException e) throws TransformerException {
        if (log.isDebugEnabled()) {
            log.debug("warning(): " + e.getMessage());
        }

        storeException(e, GeneratorException.Type.WARNING);
    }

    public void error(TransformerException e) throws TransformerException {
        if (log.isDebugEnabled()) {
            log.debug("error(): " + e.getMessage());
        }

        storeException(e, GeneratorException.Type.ERROR);
    }

    public void fatalError(TransformerException e) throws TransformerException {
        if (log.isDebugEnabled()) {
            log.debug("fatalError(): " + e.getMessage());
        }

        storeException(e, GeneratorException.Type.FATAL_ERROR);

        isFatalError = true;
    }

    ////////////////////////////////////////////////////////////////////////////
    // Private
    ////////////////////////////////////////////////////////////////////////////

    private void generateSql(ResourceType type, String name) throws IOException, TransformerException {
        Transformer transformer = getTransformer(type);

        if (transformer == null)
            return;

        setDbType(transformer);
        transformer.setParameter("db_user", "__USERNAME__");

        transformer.transform(getSource(), output.addResult(name));
    }

    private void generateOne(ResourceType type, String name) throws IOException, TransformerException {
        Transformer transformer = getTransformer(type);

        if (transformer == null)
            return;

        transformer.transform(getSource(), output.addResult(name));
    }

    private String file(String path, String tableName, String suffix) {
        String javaName = listProps.getProperty(tableName);
        int index = javaName.indexOf('|');

        if (index != -1)
            javaName = javaName.substring(0, index);

        String ret = path + javaName + suffix + ".java";

        if (log.isDebugEnabled()) {
            log.debug("file(): " + ret);
        }

        return ret;
    }

    private boolean hasDto(String tableName) {
        String javaName = listProps.getProperty(tableName);

        return javaName.indexOf("|NO-DTO") == -1;
    }

    private Set<String> getTableNames() throws IOException, TransformerException {
        if (tableNames != null)
            return tableNames;

        Transformer transformer = getTransformer(resourceKey("dao/gen-list.xsl"));

        StringWriter sw = new StringWriter();
        StreamSource source = new StreamSource(new StringReader(getXmlPreprocessed()));
        StreamResult result = new StreamResult(sw);

        transformer.transform(source, result);

        listProps = new Properties();

        // NOTE: JDK 1.5 compatibility - we cannot use load(Reader):
        // listProps.load( new StringReader( sw.toString()));
        listProps.load(new ByteArrayInputStream(sw.toString().getBytes("UTF-8")));

        // NOTE: JDK 1.5 compatibility - we cannot use stringPropertyNames():
        // tableNames = listProps.stringPropertyNames();
        tableNames = new LinkedHashSet<String>();

        for (Enumeration en = listProps.propertyNames(); en.hasMoreElements();) {
            tableNames.add((String) en.nextElement());
        }

        return tableNames;
    }

    private StreamSource getSource() throws TransformerException {
        return new StreamSource(new StringReader(getXmlPreprocessed()));
    }

    private String getXmlPreprocessed() throws TransformerException {
        if (xmlPreprocessed != null)
            return xmlPreprocessed;

        Transformer transformer = getTransformer(resourceKey("preprocess.xsl"));

        StringWriter sw = new StringWriter();
        StreamSource source = new StreamSource(xmlReader);
        StreamResult result = new StreamResult(sw);

        transformer.transform(source, result);

        xmlPreprocessed = sw.toString();

        if (log.isDebugEnabled()) {
            log.debug("getXmlPreprocessed():\n" + xmlPreprocessed);
        }

        if (generator.getIsDebugEnabled()) {
            OutputStream os = null;

            try {
                os = output.addStream("preprocessed.xml");
                os.write(xmlPreprocessed.getBytes("UTF-8"));
                os.flush();
            } catch (Exception e) {
                log.error("getXmlPreprocessed():", e);
            } finally {
                if (os != null)
                    try {
                        os.close();
                    } catch (Exception ee) {
                    }
            }
        }

        return xmlPreprocessed;
    }

    private Transformer getTransformer(ResourceType type) {
        String resourceKey = generator.getResourceKey(type);

        return resourceKey != null ? getTransformer(resourceKey) : null;
    }

    private Transformer getTransformer(String resourceKey) {
        try {
            TemplatesCache tc = generator.getTemplatesCache();
            Templates templates = tc.getTemplates(resourceKey);

            if (templates == null) {
                InputStream is = getClass().getResourceAsStream(resourceKey);
                templates = tc.getTemplates(resourceKey, new StreamSource(is, resourceKey));
            }

            Transformer ret = templates.newTransformer();
            ret.setURIResolver(generator.getResourceURIResolver()); // not auto copied from TrFactory
            ret.setErrorListener(this);
            ret.setParameter("pkg_db", pkgName);

            return ret;
        } catch (TransformerConfigurationException e) {
            throw new RuntimeException(e);
        }
    }

    private String resourceKey(String name) {
        return Generator.XSL_RESOURCES + '/' + name;
    }

    private void copy(String resourceKey, String path) throws IOException {
        InputStream is = getClass().getResourceAsStream(resourceKey);

        if (is == null)
            throw new IOException("Cannot find resource: " + path);

        OutputStream os = output.addStream(path);

        if (buffer == null)
            buffer = new byte[2048];

        int n;

        while ((n = is.read(buffer, 0, buffer.length)) != -1) {
            os.write(buffer, 0, n);
        }

        os.flush();
    }

    private void setDbType(Transformer transformer) {
        transformer.setParameter("db_type", generator.getTarget().getIdentifier());
    }

    private void storeException(TransformerException e, GeneratorException.Type type) throws TransformerException {

        // Xalan sends the error messages twice:
        if (isFatalError)
            return;

        if (exceptions == null) {
            exceptions = new ArrayList<TransformerException>();
            exceptionTypes = new ArrayList<GeneratorException.Type>();
        }

        exceptions.add(e);
        exceptionTypes.add(type);
    }
}