All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eobjects.analyzer.cli.CliRunner Maven / Gradle / Ivy

There is a newer version: 1.0.6
Show newest version
/**
 * eobjects.org AnalyzerBeans
 * Copyright (C) 2010 eobjects.org
 *
 * This copyrighted material is made available to anyone wishing to use, modify,
 * copy, or redistribute it subject to the terms and conditions of the GNU
 * Lesser General Public License, as published by the Free Software Foundation.
 *
 * This program 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 distribution; if not, write to:
 * Free Software Foundation, Inc.
 * 51 Franklin Street, Fifth Floor
 * Boston, MA  02110-1301  USA
 */
package org.eobjects.analyzer.cli;

import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.vfs2.FileObject;
import org.apache.commons.vfs2.FileSystemException;
import org.apache.commons.vfs2.VFS;
import org.eobjects.analyzer.configuration.AnalyzerBeansConfiguration;
import org.eobjects.analyzer.configuration.JaxbConfigurationReader;
import org.eobjects.analyzer.connection.Datastore;
import org.eobjects.analyzer.connection.DatastoreConnection;
import org.eobjects.analyzer.descriptors.AnalyzerBeanDescriptor;
import org.eobjects.analyzer.descriptors.BeanDescriptor;
import org.eobjects.analyzer.descriptors.ConfiguredPropertyDescriptor;
import org.eobjects.analyzer.descriptors.FilterBeanDescriptor;
import org.eobjects.analyzer.descriptors.TransformerBeanDescriptor;
import org.eobjects.analyzer.job.JaxbJobReader;
import org.eobjects.analyzer.job.builder.AnalysisJobBuilder;
import org.eobjects.analyzer.job.runner.AnalysisResultFuture;
import org.eobjects.analyzer.job.runner.AnalysisRunner;
import org.eobjects.analyzer.job.runner.AnalysisRunnerImpl;
import org.eobjects.analyzer.result.AnalysisResultWriter;
import org.eobjects.analyzer.util.VFSUtils;
import org.eobjects.metamodel.DataContext;
import org.eobjects.metamodel.schema.Schema;
import org.eobjects.metamodel.schema.Table;
import org.eobjects.metamodel.util.FileHelper;
import org.eobjects.metamodel.util.ImmutableRef;
import org.eobjects.metamodel.util.LazyRef;
import org.eobjects.metamodel.util.Ref;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Contains the execution logic to run a job from the command line.
 * 
 * @author Kasper Sørensen
 */
public final class CliRunner implements Closeable {

    private final static Logger logger = LoggerFactory.getLogger(CliRunner.class);

    private final CliArguments _arguments;
    private final Ref _outputStreamRef;
    private final Ref _writerRef;
    private final boolean _closeOut;

    /**
     * Alternative constructor that will specifically specifies the output
     * writer. Should be used only for testing, since normally the CliArguments
     * should be used to decide which outputwriter to use
     * 
     * @param arguments
     * @param writer
     * @param outputStream
     */
    protected CliRunner(CliArguments arguments, Writer writer, OutputStream outputStream) {
        _arguments = arguments;
        if (outputStream == null) {
            final String outputFilePath = arguments.getOutputFile();
            if (outputFilePath == null) {
                _outputStreamRef = null;
                _writerRef = new LazyRef() {
                    @Override
                    protected Writer fetch() {
                        return new PrintWriter(System.out);
                    }
                };
            } else {

                final FileObject outputFile;
                try {
                    outputFile = VFSUtils.getFileSystemManager().resolveFile(outputFilePath);
                } catch (FileSystemException e) {
                    throw new IllegalStateException(e);
                }

                _writerRef = new LazyRef() {
                    @Override
                    protected Writer fetch() {
                        try {
                            OutputStream out = outputFile.getContent().getOutputStream();
                            return new OutputStreamWriter(out, FileHelper.DEFAULT_ENCODING);
                        } catch (Exception e) {
                            if (e instanceof RuntimeException) {
                                throw (RuntimeException) e;
                            }
                            throw new IllegalStateException(e);
                        }
                    }
                };
                _outputStreamRef = new LazyRef() {
                    @Override
                    protected OutputStream fetch() {
                        try {
                            return outputFile.getContent().getOutputStream();
                        } catch (FileSystemException e) {
                            throw new IllegalStateException(e);
                        }
                    }
                };
            }
            _closeOut = true;
        } else {
            _writerRef = new ImmutableRef(writer);
            _outputStreamRef = new ImmutableRef(outputStream);
            _closeOut = false;
        }
    }

    public CliRunner(CliArguments arguments) {
        this(arguments, null, null);
    }

    public void run() throws Throwable {
        final String configurationFilePath = _arguments.getConfigurationFile();
        final FileObject configurationFile = VFSUtils.getFileSystemManager().resolveFile(configurationFilePath);
        final InputStream inputStream = configurationFile.getContent().getInputStream();
        try {
            run(new JaxbConfigurationReader().create(inputStream));
        } finally {
            FileHelper.safeClose(inputStream);
        }
    }

    public void run(AnalyzerBeansConfiguration configuration) throws Throwable {
        final String jobFilePath = _arguments.getJobFile();
        final CliListType listType = _arguments.getListType();
        try {
            if (jobFilePath != null) {
                runJob(configuration);
            } else if (listType != null) {
                switch (listType) {
                case ANALYZERS:
                    printAnalyzers(configuration);
                    break;
                case TRANSFORMERS:
                    printTransformers(configuration);
                    break;
                case FILTERS:
                    printFilters(configuration);
                    break;
                case DATASTORES:
                    printDatastores(configuration);
                    break;
                case SCHEMAS:
                    printSchemas(configuration);
                    break;
                case TABLES:
                    printTables(configuration);
                    break;
                case COLUMNS:
                    printColumns(configuration);
                    break;
                default:
                    throw new IllegalArgumentException("Unknown list type: " + listType);
                }
            } else {
                throw new IllegalArgumentException(
                        "Neither --job-file nor --list-type is specified. Try running with -usage to see usage help.");
            }
        } catch (Exception e) {
            logger.error("Exception thrown in {}", e, this);
            System.err.println("Error:");
            e.printStackTrace(System.err);
        } finally {
            configuration.getTaskRunner().shutdown();
        }
    }

    private void printColumns(AnalyzerBeansConfiguration configuration) {
        String datastoreName = _arguments.getDatastoreName();
        String tableName = _arguments.getTableName();
        String schemaName = _arguments.getSchemaName();

        if (datastoreName == null) {
            System.err.println("You need to specify the datastore name!");
        } else if (tableName == null) {
            System.err.println("You need to specify a table name!");
        } else {
            Datastore ds = configuration.getDatastoreCatalog().getDatastore(datastoreName);
            if (ds == null) {
                System.err.println("No such datastore: " + datastoreName);
            } else {
                DatastoreConnection con = ds.openConnection();
                DataContext dc = con.getDataContext();
                Schema schema;
                if (schemaName == null) {
                    schema = dc.getDefaultSchema();
                } else {
                    schema = dc.getSchemaByName(schemaName);
                }
                if (schema == null) {
                    System.err.println("No such schema: " + schemaName);
                } else {
                    Table table = schema.getTableByName(tableName);
                    if (table == null) {
                        write("No such table: " + tableName);
                    } else {
                        String[] columnNames = table.getColumnNames();
                        write("Columns:");
                        write("--------");
                        for (String columnName : columnNames) {
                            write(columnName);
                        }
                    }
                }
                con.close();
            }
        }
    }

    private void printTables(AnalyzerBeansConfiguration configuration) {
        String datastoreName = _arguments.getDatastoreName();
        String schemaName = _arguments.getSchemaName();

        if (datastoreName == null) {
            System.err.println("You need to specify the datastore name!");
        } else {
            Datastore ds = configuration.getDatastoreCatalog().getDatastore(datastoreName);
            if (ds == null) {
                System.err.println("No such datastore: " + datastoreName);
            } else {
                DatastoreConnection con = ds.openConnection();
                DataContext dc = con.getDataContext();
                Schema schema;
                if (schemaName == null) {
                    schema = dc.getDefaultSchema();
                } else {
                    schema = dc.getSchemaByName(schemaName);
                }
                if (schema == null) {
                    System.err.println("No such schema: " + schemaName);
                } else {
                    String[] tableNames = schema.getTableNames();
                    if (tableNames == null || tableNames.length == 0) {
                        System.err.println("No tables in schema!");
                    } else {
                        write("Tables:");
                        write("-------");
                        for (String tableName : tableNames) {
                            write(tableName);
                        }
                    }
                }
                con.close();
            }
        }
    }

    private void printSchemas(AnalyzerBeansConfiguration configuration) {
        String datastoreName = _arguments.getDatastoreName();

        if (datastoreName == null) {
            System.err.println("You need to specify the datastore name!");
        } else {
            Datastore ds = configuration.getDatastoreCatalog().getDatastore(datastoreName);
            if (ds == null) {
                System.err.println("No such datastore: " + datastoreName);
            } else {
                DatastoreConnection con = ds.openConnection();
                String[] schemaNames = con.getDataContext().getSchemaNames();
                if (schemaNames == null || schemaNames.length == 0) {
                    write("No schemas in datastore!");
                } else {
                    write("Schemas:");
                    write("--------");
                    for (String schemaName : schemaNames) {
                        write(schemaName);
                    }
                }
                con.close();
            }
        }
    }

    private void printDatastores(AnalyzerBeansConfiguration configuration) {
        String[] datastoreNames = configuration.getDatastoreCatalog().getDatastoreNames();
        if (datastoreNames == null || datastoreNames.length == 0) {
            write("No datastores configured!");
        } else {
            write("Datastores:");
            write("-----------");
            for (String datastoreName : datastoreNames) {
                write(datastoreName);
            }
        }
    }

    protected void runJob(AnalyzerBeansConfiguration configuration) throws Throwable {
        final JaxbJobReader jobReader = new JaxbJobReader(configuration);

        final String jobFilePath = _arguments.getJobFile();
        final FileObject jobFile = VFS.getManager().resolveFile(jobFilePath);
        final Map variableOverrides = _arguments.getVariableOverrides();

        final InputStream inputStream = jobFile.getContent().getInputStream();

        final AnalysisJobBuilder analysisJobBuilder;
        try {
            analysisJobBuilder = jobReader.create(inputStream, variableOverrides);
        } finally {
            FileHelper.safeClose(inputStream);
        }

        final AnalysisRunner runner = new AnalysisRunnerImpl(configuration, new CliProgressAnalysisListener());
        final AnalysisResultFuture resultFuture = runner.run(analysisJobBuilder.toAnalysisJob());

        resultFuture.await();

        if (resultFuture.isSuccessful()) {
            final CliOutputType outputType = _arguments.getOutputType();
            AnalysisResultWriter writer = outputType.createWriter();
            writer.write(resultFuture, configuration, _writerRef, _outputStreamRef);
        } else {
            write("ERROR!");
            write("------");

            List errors = resultFuture.getErrors();
            write(errors.size() + " error(s) occurred while executing the job:");

            for (Throwable throwable : errors) {
                write("------");
                StringWriter stringWriter = new StringWriter();
                throwable.printStackTrace(new PrintWriter(stringWriter));
                write(stringWriter.toString());
            }

            throw errors.get(0);
        }
    }

    protected void printAnalyzers(AnalyzerBeansConfiguration configuration) {
        Collection> descriptors = configuration.getDescriptorProvider()
                .getAnalyzerBeanDescriptors();
        if (descriptors == null || descriptors.isEmpty()) {
            write("No analyzers configured!");
        } else {
            write("Analyzers:");
            write("----------");
            printBeanDescriptors(descriptors);
        }
    }

    private void printTransformers(AnalyzerBeansConfiguration configuration) {
        Collection> descriptors = configuration.getDescriptorProvider()
                .getTransformerBeanDescriptors();
        if (descriptors == null || descriptors.isEmpty()) {
            write("No transformers configured!");
        } else {
            write("Transformers:");
            write("-------------");
            printBeanDescriptors(descriptors);
        }
    }

    private void printFilters(AnalyzerBeansConfiguration configuration) {
        Collection> descriptors = configuration.getDescriptorProvider()
                .getFilterBeanDescriptors();
        if (descriptors == null || descriptors.isEmpty()) {
            write("No filters configured!");
        } else {
            write("Filters:");
            write("--------");
            printBeanDescriptors(descriptors);
        }
    }

    protected void printBeanDescriptors(Collection> descriptors) {
        logger.debug("Printing {} descriptors", descriptors.size());
        for (BeanDescriptor descriptor : descriptors) {
            write("name: " + descriptor.getDisplayName());

            Set propertiesForInput = descriptor.getConfiguredPropertiesForInput();
            if (propertiesForInput.size() == 1) {
                ConfiguredPropertyDescriptor propertyForInput = propertiesForInput.iterator().next();
                if (propertyForInput != null) {
                    if (propertyForInput.isArray()) {
                        write(" - Consumes multiple input columns (type: "
                                + propertyForInput.getTypeArgument(0).getSimpleName() + ")");
                    } else {
                        write(" - Consumes a single input column (type: "
                                + propertyForInput.getTypeArgument(0).getSimpleName() + ")");
                    }
                }
            } else {
                write(" - Consumes " + propertiesForInput.size() + " named inputs");
                for (ConfiguredPropertyDescriptor propertyForInput : propertiesForInput) {
                    if (propertyForInput.isArray()) {
                        write("   Input columns: " + propertyForInput.getName() + " (type: "
                                + propertyForInput.getTypeArgument(0).getSimpleName() + ")");
                    } else {
                        write("   Input column: " + propertyForInput.getName() + " (type: "
                                + propertyForInput.getTypeArgument(0).getSimpleName() + ")");
                    }
                }
            }

            Set properties = descriptor.getConfiguredProperties();
            for (ConfiguredPropertyDescriptor property : properties) {
                if (!property.isInputColumn()) {
                    write(" - Property: name=" + property.getName() + ", type="
                            + property.getBaseType().getSimpleName() + ", required=" + property.isRequired());
                }
            }

            if (descriptor instanceof TransformerBeanDescriptor) {
                Class dataType = ((TransformerBeanDescriptor) descriptor).getOutputDataType();
                write(" - Output type is: " + dataType.getSimpleName());
            }

            if (descriptor instanceof FilterBeanDescriptor) {
                Set categoryNames = ((FilterBeanDescriptor) descriptor).getOutcomeCategoryNames();
                for (String categoryName : categoryNames) {
                    write(" - Outcome category: " + categoryName);
                }
            }
        }
    }

    private void write(String str) {
        try {
            _writerRef.get().write(str + "\n");
        } catch (IOException e) {
            throw new IllegalStateException(e);
        }
    }

    @Override
    public void close() {
        if (_closeOut) {
            close(_writerRef);
            close(_outputStreamRef);
        }
    }

    private void close(Ref ref) {
        if (ref != null) {
            if (ref instanceof LazyRef) {
                LazyRef lazyRef = (LazyRef) ref;
                if (lazyRef.isFetched()) {
                    FileHelper.safeClose(ref.get());
                }
            } else {
                FileHelper.safeClose(ref.get());
            }
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy