Package com.bungleton.yarrgs.parser

Source Code of com.bungleton.yarrgs.parser.ParseRunner

//
// Yarrgs - Java command line argument parsing with a hint of a sea breeze
// http://github.com/groves/yarrgs

package com.bungleton.yarrgs.parser;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import com.bungleton.yarrgs.YarrgConfigurationException;
import com.bungleton.yarrgs.YarrgHelpException;
import com.bungleton.yarrgs.YarrgParseException;
import com.bungleton.yarrgs.argument.Argument;
import com.bungleton.yarrgs.argument.HelpArgument;
import com.bungleton.yarrgs.argument.OptionArgument;
import com.bungleton.yarrgs.argument.PositionalArgument;
import com.bungleton.yarrgs.argument.ValueOptionArgument;

/**
* Holds the state for parsing a particular set of args for a Command, runs that parse, and fills
* in the values on an instance.
*/
public class ParseRunner<T>
{
    public ParseRunner (String[] args, T instance, Command<T> cmd)
        throws YarrgParseException
    {
        _usage = cmd.getUsage();
        _detail = cmd.getDetail();
        _cmd = cmd;
        List<String> nonFlagged = new ArrayList<String>();
        ARGS: for (int ii = 0; ii < args.length; ii++) {
            String next = ii + 1 == args.length ? null : args[ii + 1];
            if (args[ii].startsWith("--") && args[ii].length() > 2) {
                if (handleOption(args[ii], next, _cmd._longOptions.get(args[ii]))) {
                    ii++;
                }
            } else if (args[ii].startsWith("-") && args[ii].length() > 1) {
                // Short options can be chained together off of a single -, but any with another
                // short option following it doesn't have access to the next arg and must be flag
                char[] shorts = args[ii].substring(1, args[ii].length() - 1).toCharArray();
                for (int jj = 0; jj < shorts.length; jj++) {
                    if (handleOption("-" + shorts[jj], args[ii].substring(2 + jj),
                        _cmd._shortOptions.get(shorts[jj]))) {
                        continue ARGS;
                    }
                }
                // Let the final short option look at the next arg
                char finalShort = args[ii].charAt(args[ii].length() - 1);
                if (handleOption("-" + finalShort, next, _cmd._shortOptions.get(finalShort))) {
                    ii++;
                }
            } else {
                nonFlagged.add(args[ii]);
            }
        }

        int positionalsIdx = 0;
        for (PositionalArgument arg : _cmd._posiPositionals) {
            checkState(nonFlagged.size() > positionalsIdx,
                "Required argument '" + arg.getShortArgumentDescriptor() + "' missing");
            parse(nonFlagged.get(positionalsIdx++), arg);
        }
        if (nonFlagged.size() - positionalsIdx > _cmd._negaPositionals.size()) {
            checkState(_cmd._unmatched != null, "Too many arguments given");
            for (; positionalsIdx < nonFlagged.size() - _cmd._negaPositionals.size(); positionalsIdx++) {
                parse(nonFlagged.get(positionalsIdx), _cmd._unmatched);
            }
        }
        for (PositionalArgument arg : _cmd._negaPositionals) {
            checkState(nonFlagged.size() > positionalsIdx,
                "Required argument '" + arg.getShortArgumentDescriptor() + "' missing");
            parse(nonFlagged.get(positionalsIdx++), arg);
        }
        for (Entry<Field, Parser<?>> entry : parsers.entrySet()) {
            Object value = entry.getValue().getResult();
            try {
                entry.getKey().set(instance, value);
            } catch (Exception e) {
                throw new YarrgConfigurationException("Expected to be able to set '"
                    + entry.getKey() + "' to " + value, e);
            }
        }
    }

    /**
     * Adds the value of arg and possibly nextArg to the parser for handler.
     *
     * @param nextArg - The argument following this one, or null if there isn't one.
     * @return if nextArg was consumed by handling this option.
     */
    protected boolean handleOption (String arg, String nextArg, OptionArgument handler)
        throws YarrgParseException
    {
        checkState(handler != null, "No such option '" + arg + "'");
        if (handler instanceof ValueOptionArgument) {
            checkState(nextArg != null, "'" + arg + "' requires a value following it");
            parse(nextArg, handler);
            return true;
        } else if (handler instanceof HelpArgument) {
            throw new YarrgHelpException(_usage, _detail);
        } else {
            parse("true", handler);
            return false;
        }
    }

    /**
     * Adds the value from arg to the parser for argDesc.
     */
    protected void parse (String arg, Argument argDesc)
        throws YarrgParseException
    {
        Parser<?> parser = parsers.get(argDesc.field);
        if (parser == null) {
            parser = _cmd._factory.createParser(argDesc.field);
            parsers.put(argDesc.field, parser);
        }
        try {
            parser.add(arg);
        } catch (RuntimeException e) {
            throw new YarrgParseException(_usage, e.getMessage(), e);
        }
    }

    protected void checkState (boolean condition, String message)
        throws YarrgParseException
    {
        if (!condition) {
            throw new YarrgParseException(_usage, message);
        }
    }

    protected final String _usage, _detail;
    protected final Command<T> _cmd;
    protected final Map<Field, Parser<?>> parsers = new HashMap<Field, Parser<?>>();
}
TOP

Related Classes of com.bungleton.yarrgs.parser.ParseRunner

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.