org.apache.oodt.cas.cli.construct.StdCmdLineConstructor.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.oodt.cas.cli.construct.StdCmdLineConstructor.java

Source

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.apache.oodt.cas.cli.construct;

//OODT static imports
import static org.apache.oodt.cas.cli.util.CmdLineUtils.getOptionByName;
import static org.apache.oodt.cas.cli.util.CmdLineUtils.isHelpOption;
import static org.apache.oodt.cas.cli.util.CmdLineUtils.isSubOption;
import static org.apache.oodt.cas.cli.util.CmdLineUtils.sortOptionsByRequiredStatus;

//JDK imports
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.Stack;

//Apache imports
import org.apache.commons.lang.Validate;

//OODT imports
import org.apache.oodt.cas.cli.exception.CmdLineConstructionException;
import org.apache.oodt.cas.cli.option.CmdLineOption;
import org.apache.oodt.cas.cli.option.CmdLineOptionInstance;
import org.apache.oodt.cas.cli.option.GroupCmdLineOption;
import org.apache.oodt.cas.cli.option.GroupSubOption;
import org.apache.oodt.cas.cli.util.CmdLineIterable;
import org.apache.oodt.cas.cli.util.ParsedArg;

//Google imports
import com.google.common.annotations.VisibleForTesting;

/**
 * Standard {@link CmdLineConstructor} which support options and option
 * groups.
 *
 * @author bfoster (Brian Foster)
 */
public class StdCmdLineConstructor implements CmdLineConstructor {

    public Set<CmdLineOptionInstance> construct(CmdLineIterable<ParsedArg> parsedArgs,
            Set<CmdLineOption> validOptions) throws CmdLineConstructionException {
        HashSet<CmdLineOptionInstance> optionInstances = new HashSet<CmdLineOptionInstance>();

        Stack<CmdLineOptionInstance> groupOptions = new Stack<CmdLineOptionInstance>();
        for (ParsedArg arg : parsedArgs) {

            if (arg.getType().equals(ParsedArg.Type.OPTION)) {

                // check if option is a valid one
                CmdLineOption option = getOptionByName(arg.getName(), validOptions);
                if (option == null) {
                    throw new CmdLineConstructionException("Invalid option: '" + arg.getName() + "'");
                }

                // read found option
                CmdLineOptionInstance specifiedOption = getOption(parsedArgs, option);

                // Check if we are currently loading subOptions.
                if (!groupOptions.isEmpty()) {

                    CmdLineOptionInstance currentGroup = groupOptions.peek();

                    // Check if option is NOT a subOption for current group.
                    if (!isSubOption(currentGroup.getOption(), option)) {

                        // Check if current group was expecting more subOptions.
                        Set<CmdLineOption> requiredSubOptions = verifyGroupHasRequiredSubOptions(currentGroup);
                        if (!requiredSubOptions.isEmpty()) {
                            throw new CmdLineConstructionException(
                                    "Missing the following required subOptions for '" + currentGroup.getOption()
                                            + "': " + sortOptionsByRequiredStatus(requiredSubOptions));

                        } else if (currentGroup.getSubOptions().isEmpty()) {
                            throw new CmdLineConstructionException(
                                    "Must specify a subOption for group option '" + currentGroup.getOption() + "'");

                        } else {

                            // pop group and add to list of specified options.
                            optionInstances.add(groupOptions.pop());
                        }
                        // It is a sub-option...
                    } else {

                        // Add option to current group subOptions.
                        currentGroup.addSubOption(specifiedOption);
                        continue;

                    }
                }

                if (option instanceof GroupCmdLineOption) {

                    // Push group as current group.
                    groupOptions.push(specifiedOption);

                    if (!parsedArgs.hasNext()) {
                        throw new CmdLineConstructionException(
                                "Must specify a subOption for group option '" + specifiedOption.getOption() + "'");
                    }
                } else if (option.isSubOption()) {
                    throw new CmdLineConstructionException(
                            "Option '" + option + "' is a subOption, but was used at top level Option");

                } else {

                    // Option good to go.
                    optionInstances.add(specifiedOption);
                }
            } else {
                throw new CmdLineConstructionException("Invalid argument: '" + arg + "'");
            }
        }
        while (!groupOptions.isEmpty()) {
            CmdLineOptionInstance currentGroup = groupOptions.pop();
            Set<CmdLineOption> requiredSubOptions = verifyGroupHasRequiredSubOptions(currentGroup);
            if (!requiredSubOptions.isEmpty()) {
                throw new CmdLineConstructionException("Missing the following required subOptions for '"
                        + currentGroup.getOption() + "': " + sortOptionsByRequiredStatus(requiredSubOptions));

            } else {
                optionInstances.add(currentGroup);
            }
        }
        return optionInstances;
    }

    @VisibleForTesting
    /* package */static CmdLineOptionInstance getOption(CmdLineIterable<ParsedArg> args, CmdLineOption option)
            throws CmdLineConstructionException {
        CmdLineOptionInstance specifiedOption = new CmdLineOptionInstance();
        specifiedOption.setOption(option);
        List<String> values = getValues(args);
        if (isHelpOption(option)) {
            specifiedOption.setValues(values);
        } else if (option.hasArgs()) {
            if (!values.isEmpty()) {
                specifiedOption.setValues(values);
            } else if (!option.hasStaticArgs()) {
                throw new CmdLineConstructionException("Option " + option + " requires args");
            }
        } else if (!option.hasArgs() && !values.isEmpty()) {
            throw new CmdLineConstructionException("Option " + option + " does not support args");
        }
        return specifiedOption;
    }

    @VisibleForTesting
    /* package */static Set<CmdLineOption> verifyGroupHasRequiredSubOptions(CmdLineOptionInstance group) {
        Validate.isTrue(group.isGroup());

        Set<CmdLineOption> missingSubOptions = new HashSet<CmdLineOption>();
        TOP: for (GroupSubOption subOption : ((GroupCmdLineOption) group.getOption()).getSubOptions()) {
            if (subOption.isRequired()) {
                for (CmdLineOptionInstance specifiedSubOption : group.getSubOptions()) {
                    if (specifiedSubOption.getOption().equals(subOption.getOption())) {
                        continue TOP;
                    }
                }
                missingSubOptions.add(subOption.getOption());
            }
        }
        return missingSubOptions;
    }

    @VisibleForTesting
    /* package */static List<String> getValues(CmdLineIterable<ParsedArg> args) {
        List<String> values = new ArrayList<String>();
        ParsedArg nextValue = args.incrementAndGet();
        while (nextValue != null && nextValue.getType().equals(ParsedArg.Type.VALUE)) {
            values.add(nextValue.getName());
            nextValue = args.incrementAndGet();
        }
        args.descrementIndex();
        return values;
    }
}