Package org.jboss.aesh.cl

Source Code of org.jboss.aesh.cl.CommandLineParser

/*
* Copyright 2012 Red Hat, Inc. and/or its affiliates.
*
* Licensed under the Eclipse Public License version 1.0, available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.jboss.aesh.cl;

import org.jboss.aesh.cl.exception.ArgumentParserException;
import org.jboss.aesh.cl.exception.CommandLineParserException;
import org.jboss.aesh.cl.exception.OptionParserException;
import org.jboss.aesh.cl.exception.RequiredOptionException;
import org.jboss.aesh.cl.internal.OptionInt;
import org.jboss.aesh.cl.internal.ParameterInt;
import org.jboss.aesh.util.Parser;

import java.util.ArrayList;
import java.util.List;

/**
* A simple command line parser.
* It parses a given string based on the Parameter given and
* returns a {@link CommandLine}
*
* It can also print a formatted usage/help information.
*
* @author <a href="mailto:stale.pedersen@jboss.org">Ståle W. Pedersen</a>
*/
public class CommandLineParser {

    private List<ParameterInt> params;
    private static final String EQUALS = "=";

    public CommandLineParser(List<ParameterInt> parameters) {
        params = new ArrayList<ParameterInt>();
        params.addAll(parameters);
    }

    public CommandLineParser(ParameterInt parameterInt) {
        params = new ArrayList<ParameterInt>();
        params.add(parameterInt);
    }

    public CommandLineParser(String name, String usage) {
        params = new ArrayList<ParameterInt>();
        params.add(new ParameterInt(name, usage));
    }

    public void addParameter(ParameterInt param) {
        params.add(param);
    }

    public List<ParameterInt> getParameters() {
        return params;
    }

    /**
     * Returns a usage String based on the defined parameter and options.
     * Useful when printing "help" info etc.
     *
     */
    public String printHelp() {
        StringBuilder builder = new StringBuilder();
        for(ParameterInt param : params)
            builder.append(param.printHelp());

        return builder.toString();
    }

    /**
     * Parse a command line with the defined parameter as base of the rules.
     * If any options are found, but not defined in the parameter object an
     * CommandLineParserException will be thrown.
     * Also, if a required option is not found or options specified with value,
     * but is not given any value an OptionParserException will be thrown.
     *
     * The options found will be returned as a {@link CommandLine} object where
     * they can be queried after.
     *
     * @param line input
     * @return CommandLine
     * @throws CommandLineParserException
     */
    public CommandLine parse(String line) throws CommandLineParserException {
        return parse(line, false);
    }

    /**
     * Parse a command line with the defined parameter as base of the rules.
     * If any options are found, but not defined in the parameter object an
     * CommandLineParserException will be thrown.
     * Also, if a required option is not found or options specified with value,
     * but is not given any value an CommandLineParserException will be thrown.
     *
     * The options found will be returned as a {@link CommandLine} object where
     * they can be queried after.
     *
     * @param line input
     * @param ignoreMissingRequirements if we should ignore
     * @return CommandLine
     * @throws CommandLineParserException
     */
    public CommandLine parse(String line, boolean ignoreMissingRequirements) throws CommandLineParserException {
        List<String> lines = Parser.findAllWords(line);
        if(lines.size() > 0) {
            for(ParameterInt param : params) {
                if(param.getName().equals(lines.get(0)))
                    return doParse(param, lines, ignoreMissingRequirements);
            }
        }
        throw new CommandLineParserException("Param:"+ params+", not found in: "+line);
    }

    private CommandLine doParse(ParameterInt param, List<String> lines,
                                boolean ignoreMissing) throws CommandLineParserException {
        param.clean();
        CommandLine commandLine = new CommandLine();
        OptionInt active = null;
        boolean addedArgument = false;
        //skip first entry since that's the name of the command
        for(int i=1; i < lines.size(); i++) {
            String parseLine = lines.get(i);
            //longName
            if(parseLine.startsWith("--")) {
                //make sure that we dont have any "active" options lying around
                if(active != null)
                    throw new OptionParserException("Option: "+active.getDisplayName()+" must be given a value");

                active = findLongOption(param, parseLine.substring(2));
                if(active != null && active.isProperty()) {
                    if(parseLine.length() <= (2+active.getLongName().length()) ||
                        !parseLine.contains(EQUALS))
                        throw new OptionParserException(
                                "Option "+active.getDisplayName()+", must be part of a property");

                    String name =
                            parseLine.substring(2+active.getLongName().length(),
                                    parseLine.indexOf(EQUALS));
                    String value = parseLine.substring( parseLine.indexOf(EQUALS)+1);

                    commandLine.addOption(new
                            ParsedOption(active.getName(), active.getLongName(),
                            new OptionProperty(name, value), active.getType()));
                    active = null;
                    if(addedArgument)
                        throw new ArgumentParserException("An argument was given to an option that do not support it.");
                }
                else if(active != null && (!active.hasValue() || active.getValue() != null)) {
                    commandLine.addOption(new ParsedOption(active.getName(), active.getLongName(),
                            active.getValue(), active.getType()));
                    active = null;
                    if(addedArgument)
                        throw new ArgumentParserException("An argument was given to an option that do not support it.");
                }
                else if(active == null)
                    throw new OptionParserException("Option: "+parseLine+" is not a valid option for this command");
            }
            //name
            else if(parseLine.startsWith("-")) {
                //make sure that we dont have any "active" options lying around
                if(active != null)
                    throw new OptionParserException("Option: "+active.getDisplayName()+" must be given a value");
                if(parseLine.length() != 2 && !parseLine.contains("="))
                    throw new OptionParserException("Option: - must be followed by a valid operator");

                active = findOption(param, parseLine.substring(1));

                if(active != null && active.isProperty()) {
                    if(parseLine.length() <= 2 ||
                            !parseLine.contains(EQUALS))
                    throw new OptionParserException(
                            "Option "+active.getDisplayName()+", must be part of a property");
                    String name =
                            parseLine.substring(2, // 2+char.length
                                    parseLine.indexOf(EQUALS));
                    String value = parseLine.substring( parseLine.indexOf(EQUALS)+1);

                    commandLine.addOption(new
                            ParsedOption(active.getName(), active.getLongName(),
                            new OptionProperty(name, value), active.getType()));
                    active = null;
                    if(addedArgument)
                        throw new OptionParserException("An argument was given to an option that do not support it.");
                }

                else if(active != null && (!active.hasValue() || active.getValue() != null)) {
                    commandLine.addOption(new ParsedOption(String.valueOf(active.getName()),
                            active.getLongName(), active.getValue(), active.getType()));
                    active = null;
                    if(addedArgument)
                        throw new OptionParserException("An argument was given to an option that do not support it.");
                }
                else if(active == null)
                    throw new OptionParserException("Option: "+parseLine+" is not a valid option for this command");
            }
            else if(active != null) {
                if(active.hasMultipleValues()) {
                    if(parseLine.contains(String.valueOf(active.getValueSeparator()))) {
                        for(String value : parseLine.split(String.valueOf(active.getValueSeparator()))) {
                            active.addValue(value.trim());
                        }
                    }
                }
                else
                    active.addValue(parseLine);

                commandLine.addOption(new ParsedOption(active.getName(),
                        active.getLongName(), active.getValues(), active.getType()));
                active = null;
                if(addedArgument)
                    throw new OptionParserException("An argument was given to an option that do not support it.");
            }
            //if no param is "active", we add it as an argument
            else {
                commandLine.addArgument(parseLine);
                addedArgument = true;
            }
        }
        if(active != null && ignoreMissing) {
            commandLine.addOption(new ParsedOption(active.getName(),
                    active.getLongName(), active.getValues(), active.getType()));
        }

        //this will throw and CommandLineParserException if needed
        if(!ignoreMissing)
            checkForMissingRequiredOptions(param, commandLine);

        return commandLine;
    }

    private void checkForMissingRequiredOptions(ParameterInt param, CommandLine commandLine) throws CommandLineParserException {
        for(OptionInt o : param.getOptions())
            if(o.isRequired()) {
                boolean found = false;
                for(ParsedOption po : commandLine.getOptions()) {
                    if(po.getName().equals(o.getName()) ||
                            po.getName().equals(o.getLongName()))
                        found = true;
                }
                if(!found)
                    throw new RequiredOptionException("Option: "+o.getDisplayName()+" is required for this command.");
            }
    }

    private OptionInt findOption(ParameterInt param, String line) {
        OptionInt option = param.findOption(line);
        //simplest case
        if(option != null)
            return option;

        option = param.startWithOption(line);
        //if its a property, we'll parse it later
        if(option != null && option.isProperty())
            return option;
        if(option != null) {
           String rest = line.substring(option.getName().length());
            if(rest != null && rest.length() > 1 && rest.startsWith("=")) {
                option.addValue(rest.substring(1));
                return option;
            }
        }

        return null;
    }

    private OptionInt findLongOption(ParameterInt param, String line) {
        OptionInt option = param.findLongOption(line);
        //simplest case
        if(option != null)
            return option;

        option = param.startWithLongOption(line);
        //if its a property, we'll parse it later
        if(option != null && option.isProperty())
            return option;
        if(option != null) {
            String rest = line.substring(option.getLongName().length());
            if(rest != null && rest.length() > 1 && rest.startsWith("=")) {
                option.addValue(rest.substring(1));
                return option;
            }
        }

        return null;
    }

    @Override
    public String toString() {
        return "CommandLineParser{" +
                "params=" + params +
                '}';
    }
}
TOP

Related Classes of org.jboss.aesh.cl.CommandLineParser

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.