org.onebusaway.gtfs_merge.GtfsMergerMain.java Source code

Java tutorial

Introduction

Here is the source code for org.onebusaway.gtfs_merge.GtfsMergerMain.java

Source

/**
 * Copyright (C) 2012 Google, Inc.
 *
 * 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 org.onebusaway.gtfs_merge;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.cli.AlreadySelectedException;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.MissingArgumentException;
import org.apache.commons.cli.MissingOptionException;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.apache.commons.cli.PosixParser;
import org.apache.commons.cli.UnrecognizedOptionException;
import org.onebusaway.csv_entities.schema.annotations.CsvFields;
import org.onebusaway.gtfs.serialization.GtfsEntitySchemaFactory;
import org.onebusaway.gtfs_merge.strategies.AbstractEntityMergeStrategy;
import org.onebusaway.gtfs_merge.strategies.EntityMergeStrategy;

public class GtfsMergerMain {

    public static final String ARG_FILE = "file";

    public static final String ARG_DUPLICATE_DETECTION = "duplicateDetection";

    public static final String ARG_LOG_DROPPED_DUPLICATES = "logDroppedDuplicates";

    public static final String ARG_ERROR_ON_DROPPED_DUPLICATES = "errorOnDroppedDuplicates";

    /****
     * Generic Arguments
     ****/

    private static CommandLineParser _parser = new PosixParser();

    private Options _options = new Options();

    /**
     * Mapping from GTFS file name to the entity type handled by that class.
     */
    private Map<String, Class<?>> _entityClassesByFilename = new HashMap<String, Class<?>>();

    /**
     * If we ever need to register a custom option handler for a specific entity
     * type, we would do it here.
     */
    private Map<Class<?>, OptionHandler> _optionHandlersByEntityClass = new HashMap<Class<?>, OptionHandler>();

    public static void main(String[] args) throws IOException {
        GtfsMergerMain m = new GtfsMergerMain();
        m.run(args);
    }

    public GtfsMergerMain() {
        buildOptions(_options);
        mapEntityClassesToFilenames();
    }

    /*****************************************************************************
     * {@link Runnable} Interface
     ****************************************************************************/

    public void run(String[] args) throws IOException {

        if (needsHelp(args)) {
            printHelp();
            System.exit(0);
        }

        try {
            CommandLine cli = _parser.parse(_options, args, true);
            runApplication(cli, args);
        } catch (MissingOptionException ex) {
            System.err.println("Missing argument: " + ex.getMessage());
            printHelp();
        } catch (MissingArgumentException ex) {
            System.err.println("Missing argument: " + ex.getMessage());
            printHelp();
        } catch (UnrecognizedOptionException ex) {
            System.err.println("Unknown argument: " + ex.getMessage());
            printHelp();
        } catch (AlreadySelectedException ex) {
            System.err.println("Argument already selected: " + ex.getMessage());
            printHelp();
        } catch (ParseException ex) {
            System.err.println(ex.getMessage());
            printHelp();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    /*****************************************************************************
     * Abstract Methods
     ****************************************************************************/

    protected void buildOptions(Options options) {
        options.addOption(ARG_FILE, true, "GTFS file name");
        options.addOption(ARG_DUPLICATE_DETECTION, true, "duplicate detection strategy");
        options.addOption(ARG_LOG_DROPPED_DUPLICATES, false, "log dropped duplicates");
        options.addOption(ARG_ERROR_ON_DROPPED_DUPLICATES, false, "error on dropped duplicates");
    }

    protected void printHelp(PrintWriter out, Options options) throws IOException {

        InputStream is = getClass().getResourceAsStream("usage.txt");
        BufferedReader reader = new BufferedReader(new InputStreamReader(is));
        String line = null;

        while ((line = reader.readLine()) != null) {
            System.err.println(line);
        }

        reader.close();
    }

    protected void runApplication(CommandLine cli, String[] originalArgs) throws Exception {

        String[] args = cli.getArgs();

        if (args.length < 2) {
            printHelp();
            System.exit(-1);
        }

        GtfsMerger merger = new GtfsMerger();

        processOptions(cli, merger);

        List<File> inputPaths = new ArrayList<File>();
        for (int i = 0; i < args.length - 1; ++i) {
            inputPaths.add(new File(args[i]));
        }
        File outputPath = new File(args[args.length - 1]);

        merger.run(inputPaths, outputPath);
    }

    /*****************************************************************************
     * Protected Methods
     ****************************************************************************/

    protected void printHelp() throws IOException {
        printHelp(new PrintWriter(System.err, true), _options);
    }

    private boolean needsHelp(String[] args) {
        for (String arg : args) {
            if (arg.equals("-h") || arg.equals("--help") || arg.equals("-help"))
                return true;
        }
        return false;
    }

    private void mapEntityClassesToFilenames() {
        for (Class<?> entityClass : GtfsEntitySchemaFactory.getEntityClasses()) {
            CsvFields csvFields = entityClass.getAnnotation(CsvFields.class);
            if (csvFields == null) {
                continue;
            }
            String filename = csvFields.filename();
            _entityClassesByFilename.put(filename, entityClass);
        }
    }

    private void processOptions(CommandLine cli, GtfsMerger merger) {

        OptionHandler currentOptionHandler = null;
        AbstractEntityMergeStrategy mergeStrategy = null;

        for (Option option : cli.getOptions()) {
            if (option.getOpt().equals(ARG_FILE)) {
                String filename = option.getValue();
                Class<?> entityClass = _entityClassesByFilename.get(filename);
                if (entityClass == null) {
                    throw new IllegalStateException("unknown GTFS filename: " + filename);
                }
                mergeStrategy = getMergeStrategyForEntityClass(entityClass, merger);
                currentOptionHandler = getOptionHandlerForEntityClass(entityClass);
            } else {
                if (currentOptionHandler == null) {
                    throw new IllegalArgumentException(
                            "you must specify a --file argument first before specifying file-specific arguments");
                }
                currentOptionHandler.handleOption(option, mergeStrategy);
            }
        }
    }

    private AbstractEntityMergeStrategy getMergeStrategyForEntityClass(Class<?> entityClass, GtfsMerger merger) {
        EntityMergeStrategy strategy = merger.getEntityMergeStrategyForEntityType(entityClass);
        if (strategy == null) {
            throw new IllegalStateException("no merge strategy found for entityType=" + entityClass);
        }
        return (AbstractEntityMergeStrategy) strategy;
    }

    private OptionHandler getOptionHandlerForEntityClass(Class<?> entityClass) {
        OptionHandler handler = _optionHandlersByEntityClass.get(entityClass);
        if (handler == null) {
            handler = new OptionHandler();
        }
        return handler;
    }

}