com.obidea.semantika.cli.Main.java Source code

Java tutorial

Introduction

Here is the source code for com.obidea.semantika.cli.Main.java

Source

/*
 * Copyright (c) 2013-2014 Obidea
 * 
 * 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.obidea.semantika.cli;

import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.Map;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.GnuParser;
import org.apache.commons.cli.OptionBuilder;
import org.apache.commons.cli.Options;
import org.apache.log4j.Level;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;

import com.obidea.semantika.app.ApplicationFactory;
import com.obidea.semantika.app.ApplicationManager;
import com.obidea.semantika.materializer.IMaterializerEngine;
import com.obidea.semantika.materializer.MaterializationException;
import com.obidea.semantika.materializer.MaterializerEngineException;
import com.obidea.semantika.queryanswer.IQueryEngine;
import com.obidea.semantika.queryanswer.SparqlQueryEngine;
import com.obidea.semantika.queryanswer.exception.QueryAnswerException;
import com.obidea.semantika.queryanswer.result.IQueryResult;
import com.obidea.semantika.util.StringUtils;

@SuppressWarnings("static-access")
public class Main {
    private static final String VERSION_NUMBER = "1.3"; //$NON-NLS-1$
    private static final String SEMANTIKA_CORE_VERSION_NUMBER = "1.7.1"; //$NON-NLS-1$

    private static Options sOptions = new Options();
    static {
        sOptions.addOption(Environment.HELP, false, "print this message"); //$NON-NLS-1$
        sOptions.addOption(Environment.VERSION, false, "print the version information and exit"); //$NON-NLS-1$
        sOptions.addOption(Environment.SHOW_SQL, false, "show the generated SQL (for 'queryanswer' only)"); //$NON-NLS-1$
        sOptions.addOption(Environment.VERBOSE_SHORTCUT, Environment.VERBOSE, false, "be extra verbose"); //$NON-NLS-1$
        sOptions.addOption(Environment.QUIET_SHORTCUT, Environment.QUIET, false, "be extra quiet"); //$NON-NLS-1$
        sOptions.addOption(Environment.QUERY, true, "input SPARQL query"); //$NON-NLS-1$
        sOptions.addOption(OptionBuilder.withLongOpt(Environment.CONFIG)
                .withDescription("path to Semantika configuration file (default=./application.cfg.xml)") //$NON-NLS-1$
                .hasArg().withArgName("path") //$NON-NLS-1$
                .create(Environment.CONFIG_SHORTCUT));
        sOptions.addOption(OptionBuilder.withLongOpt(Environment.OUTPUT)
                .withDescription("path to output file to flush the result") //$NON-NLS-1$
                .hasArg().withArgName("path") //$NON-NLS-1$
                .create(Environment.OUTPUT_SHORTCUT));
        sOptions.addOption(OptionBuilder.withLongOpt(Environment.FORMAT)
                .withDescription("flush result in selected format (options: N3,TTL,XML,JSON)") //$NON-NLS-1$
                .hasArg().withArgName("format") //$NON-NLS-1$
                .create(Environment.FORMAT_SHORTCUT));
        sOptions.addOption(OptionBuilder.withLongOpt(Environment.LIMIT)
                .withDescription("limit the number of returned query result") //$NON-NLS-1$
                .hasArg().withArgName("size") //$NON-NLS-1$
                .create(Environment.LIMIT_SHORTCUT));
    }

    private static CustomHelpFormatter mFormatter = new CustomHelpFormatter();

    public static void main(String[] args) {
        @SuppressWarnings("unchecked")
        List<Logger> loggers = Collections.list(LogManager.getCurrentLoggers());
        loggers.add(LogManager.getRootLogger());
        normal(loggers);

        try {
            CommandLineParser parser = new GnuParser();
            CommandLine optionLine = parser.parse(sOptions, args);

            if (optionLine.hasOption(Environment.VERSION)) {
                printVersion();
                System.exit(0);
            }
            if (optionLine.hasOption(Environment.HELP)) {
                printUsage();
                System.exit(0);
            }

            String operation = determineOperation(args);
            if (StringUtils.isEmpty(operation)) {
                printUsage();
            } else {
                setupLoggers(optionLine, loggers);
                executeOperation(operation, optionLine);
            }
        } catch (Exception e) {
            System.err.println("Unexpected exception:" + e.getMessage()); //$NON-NLS-1$
            System.exit(1);
        }
    }

    private static void setupLoggers(CommandLine optionLine, List<Logger> loggers) {
        if (optionLine.hasOption(Environment.VERBOSE)) {
            verbose(loggers);
        } else if (optionLine.hasOption(Environment.QUIET)) {
            quiet(loggers);
        }
    }

    private static void executeOperation(String operation, CommandLine optionLine) throws Exception {
        if (operation.equals(Environment.QUERYANSWER_OP)) {
            File config = determineConfigurationFile(optionLine);
            ApplicationManager manager = new ApplicationFactory().configure(config).createApplicationManager();

            String sparql = determineInputSparql(optionLine, manager.getPrefixManager().getPrefixMapper());
            int limit = determineResultLimit(optionLine);
            IQueryEngine engine = createQueryEngine(manager);

            boolean showSql = determineShowSql(optionLine);
            queryanswer(engine, sparql, limit, showSql);
        } else if (operation.equals(Environment.MATERIALIZE_OP)) {
            File config = determineConfigurationFile(optionLine);
            ApplicationManager manager = new ApplicationFactory().configure(config).createApplicationManager();

            String format = determineOutputFormat(optionLine);
            File fout = determineOutputFile(optionLine);
            IMaterializerEngine engine = createMaterializerEngine(manager, format);
            materialize(engine, fout);
        } else {
            System.err.println("Invalid command"); //$NON-NLS-1$
            printUsage();
        }
    }

    private static void queryanswer(IQueryEngine engine, String sparql, int limit, boolean showSql)
            throws QueryAnswerException, IOException {
        engine.start();
        if (showSql) {
            printSql(sparql, engine);
        } else {
            flushResult(evaluateQuery(sparql, engine, limit));
        }
        engine.stop();
    }

    private static void printSql(String sparql, IQueryEngine engine) throws QueryAnswerException {
        String sql = engine.translate(sparql);
        System.out.println(sql);
    }

    private static IQueryResult evaluateQuery(String sparql, IQueryEngine engine, int limit)
            throws QueryAnswerException {
        if (engine instanceof SparqlQueryEngine) {
            return ((SparqlQueryEngine) engine).createQuery(sparql).setMaxResults(limit).evaluate();
        }
        return engine.evaluate(sparql);
    }

    private static void materialize(IMaterializerEngine engine, File fout)
            throws MaterializerEngineException, MaterializationException {
        engine.start();
        engine.materialize(fout, new ConsoleProgressBar());
        engine.stop();
    }

    private static IQueryEngine createQueryEngine(ApplicationManager manager) {
        return manager.createQueryEngine();
    }

    private static IMaterializerEngine createMaterializerEngine(ApplicationManager manager, String format) {
        if (format.equals("N3")) { //$NON-NLS-1$
            return manager.createMaterializerEngine().useNTriples();
        } else if (format.equals("TTL")) { //$NON-NLS-1$
            return manager.createMaterializerEngine().useTurtle();
        } else if (format.equals("XML")) { //$NON-NLS-1$
            return manager.createMaterializerEngine().useRdfXml();
        } else if (format.equals("JSON")) { //$NON-NLS-1$
            return manager.createMaterializerEngine().useRdfJson();
        }
        return null; // should never goes here
    }

    /**
     * Flush the query result to stdout.
     */
    private static void flushResult(IQueryResult result) throws IOException {
        while (result.next()) {
            System.out.println(result.getValueArray().toString());
        }
    }

    /**
     * Determines the input SPARQL string.
     * 
     * @param optionLine
     *           The command-line arguments passed in.
     * @param iPrefixManager 
     * @return The query string.
     */
    private static String determineInputSparql(CommandLine optionLine, Map<String, String> prefixes) {
        String query = optionLine.getOptionValue(Environment.QUERY).trim(); //$NON-NLS-1$
        if (StringUtils.isEmpty(query)) {
            System.err.println("Input query is missing"); //$NON-NLS-1$
            System.exit(1);
        }
        return appendPrefixes(query, prefixes);
    }

    private static String appendPrefixes(String query, Map<String, String> prefixes) {
        StringBuilder toReturn = new StringBuilder();
        for (String prefix : prefixes.keySet()) {
            toReturn.append("PREFIX ").append(prefix).append(":"); //$NON-NLS-1$ //$NON-NLS-2$
            toReturn.append("\t"); //$NON-NLS-1$
            toReturn.append("<").append(prefixes.get(prefix)).append(">"); //$NON-NLS-1$ //$NON-NLS-2$
            toReturn.append("\n"); //$NON-NLS-1$
        }
        toReturn.append(query);
        return toReturn.toString();
    }

    /**
     * Determines the file to use for loading the configuration.
     * 
     * @param optionLine
     *           The command-line arguments passed in.
     * @return The path of the configuration file on disk.
     */
    private static File determineConfigurationFile(CommandLine optionLine) {
        String config = optionLine.getOptionValue(Environment.CONFIG); //$NON-NLS-1$
        if (StringUtils.isEmpty(config)) {
            return new File(ApplicationFactory.DEFAULT_CONFIGURATION_FILENAME); //$NON-NLS-1$
        }
        return new File(config);
    }

    /**
     * Determines the writer format for flushing the output.
     * 
     * @param args
     *           The command-line arguments passed in.
     * @return The selected writer format.
     */
    private static String determineOutputFormat(CommandLine optionLine) {
        String format = optionLine.getOptionValue(Environment.FORMAT);
        if (StringUtils.isEmpty(format)) {
            format = "TTL"; //$NON-NLS-1$ - by default
        }
        return format;
    }

    /**
     * Determines the limit of the query result to be fetched.
     * 
     * @param optionLine
     *           The command-line arguments passed in.
     * @return The limit amount.
     */
    private static int determineResultLimit(CommandLine optionLine) {
        String limit = optionLine.getOptionValue(Environment.LIMIT);
        if (StringUtils.isEmpty(limit)) {
            return -1;
        }
        return Integer.parseInt(limit);
    }

    /**
     * Determines if the generated SQL should be printed instead of executing it.
     * 
     * @param optionLine
     *           The command-line arguments passed in.
     */
    private static boolean determineShowSql(CommandLine optionLine) {
        return optionLine.hasOption(Environment.SHOW_SQL);
    }

    /**
     * Determines the command operation Semantika CLI should execute.
     * 
     * @param args
     *           The command-line arguments passed in.
     * @return The operation string or <code>null</code> if it could not be
     *         determined.
     */
    private static String determineOperation(String[] args) {
        for (String arg : args) {
            if (!arg.startsWith("-")) { //$NON-NLS-1$
                return arg;
            }
        }
        return null;
    }

    /**
     * Determines the file to use to flush out the result.
     * 
     * @param args
     *           The command-line arguments passed in.
     * @return The path of the output file on disk.
     */
    private static File determineOutputFile(CommandLine optionLine) {
        String output = optionLine.getOptionValue(Environment.OUTPUT);
        if (!StringUtils.isEmpty(output)) {
            return new File(output);
        }
        System.err.println("Output file is missing"); //$NON-NLS-1$
        System.exit(1);
        return null;
    }

    /**
     * Print tool version.
     */
    private static void printVersion() {
        StringBuilder sb = new StringBuilder();
        sb.append("semantika version "); //$NON-NLS-1$
        sb.append("\"").append(VERSION_NUMBER).append("\""); //$NON-NLS-1$ //$NON-NLS-2$
        sb.append("\n"); //$NON-NLS-1$
        sb.append("Semantika Core Runtime "); //$NON-NLS-1$
        sb.append("(build ").append(SEMANTIKA_CORE_VERSION_NUMBER).append(")"); //$NON-NLS-1$ //$NON-NLS-2$
        System.out.println(sb.toString());
    }

    /**
     * Set all loggers in INFO level.
     */
    private static void normal(List<Logger> loggers) {
        for (Logger logger : loggers) {
            logger.setLevel(Level.INFO);
        }
    }

    /**
     * Set all loggers in DEBUG level.
     */
    private static void verbose(List<Logger> loggers) {
        for (Logger logger : loggers) {
            logger.setLevel(Level.DEBUG);
        }
    }

    /**
     * Disable all loggers.
     */
    private static void quiet(List<Logger> loggers) {
        for (Logger logger : loggers) {
            logger.setLevel(Level.OFF);
        }
    }

    /**
     * Prints the usage instructions on the console.
     */
    private static void printUsage() {
        StringBuilder usage = new StringBuilder();
        usage.append(String.format("semantika %s [OPTIONS...]\n", Environment.QUERYANSWER_OP));
        usage.append("           (to execute query answer)\n");
        usage.append(String.format("       semantika %s [OPTIONS...]\n", Environment.MATERIALIZE_OP));
        usage.append("           (to execute RDB2RDF export)");
        String header = "where OPTIONS include:"; //$NON-NLS-1$
        String footer = "\nExample:\n" + //$NON-NLS-1$
                "  ./semantika queryanswer -c application.cfg.xml -l 100 -sparql 'SELECT ?x WHERE { ?x a :Person }'\n" //$NON-NLS-1$
                + "  ./semantika rdb2rdf -c application.cfg.xml -o output.n3 -f N3";
        mFormatter.setOptionComparator(null);
        mFormatter.printHelp(400, usage.toString(), header, sOptions, footer);
    }
}