se.softhouse.jargo.ParsedArguments.java Source code

Java tutorial

Introduction

Here is the source code for se.softhouse.jargo.ParsedArguments.java

Source

/* Copyright 2013 Jonatan Jnsson
 *
 *    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 se.softhouse.jargo;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Predicates.and;
import static com.google.common.base.Predicates.in;
import static com.google.common.base.Predicates.not;
import static com.google.common.collect.Collections2.filter;
import static com.google.common.collect.Maps.newLinkedHashMap;
import static se.softhouse.jargo.Argument.IS_REQUIRED;

import java.util.Collection;
import java.util.Locale;
import java.util.Map;
import java.util.Set;

import javax.annotation.CheckReturnValue;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;

import se.softhouse.jargo.internal.Texts.ProgrammaticErrors;

import com.google.common.collect.Sets;

/**
 * Holds parsed arguments for a {@link CommandLineParser#parse(String...)} invocation.
 * Use {@link #get(Argument)} to fetch a parsed command line value.
 */
@Immutable
public final class ParsedArguments {
    /**
     * Stores results from {@link StringParser#parse(String, Locale)}
     */
    @Nonnull
    private final Map<Argument<?>, Object> parsedArguments = newLinkedHashMap();
    @Nonnull
    private final Set<Argument<?>> allArguments;
    /**
     * Keeps a running total of how many indexed arguments that have been parsed
     */
    private int indexedArgumentsParsed = 0;

    ParsedArguments(Set<Argument<?>> arguments) {
        allArguments = arguments;
    }

    /**
     * Returns the parsed value for the given {@code argumentToFetch},
     * if no value was given on the command line the default value is
     * returned.
     * 
     * @see StringParser#defaultValue()
     */
    @Nullable
    @CheckReturnValue
    public <T> T get(final Argument<T> argumentToFetch) {
        if (!wasGiven(argumentToFetch)) {
            checkArgument(allArguments.contains(argumentToFetch), ProgrammaticErrors.ILLEGAL_ARGUMENT,
                    argumentToFetch);
            return argumentToFetch.defaultValue();
        }
        return getValue(argumentToFetch);
    }

    /**
     * Checks if an {@link Argument} was given in the command line arguments
     * 
     * @param argument the {@link Argument} to check
     * @return true if {@code argument} was given, that is, the default value will not be used
     */
    public boolean wasGiven(Argument<?> argument) {
        return parsedArguments.containsKey(checkNotNull(argument));
    }

    @Override
    public String toString() {
        return parsedArguments.toString();
    }

    @Override
    public boolean equals(@Nullable Object other) {
        if (this == other)
            return true;
        if (!(other instanceof ParsedArguments))
            return false;

        return parsedArguments.equals(((ParsedArguments) other).parsedArguments);
    }

    @Override
    public int hashCode() {
        return parsedArguments.hashCode();
    }

    // Publicly this class is Immutable, CommandLineParserInstance is only allowed to modify it
    // during parsing

    <T> void put(final Argument<T> definition, @Nullable final T value) {
        if (definition.isIndexed()) {
            indexedArgumentsParsed++;
        }
        parsedArguments.put(definition, value);
    }

    /**
     * Makes the parsed value for {@code definition} unmodifiable.
     */
    <T> void finalize(final Argument<T> definition) {
        T value = getValue(definition);
        T finalizedValue = definition.finalizer().apply(value);
        put(definition, finalizedValue);
    }

    <T> T getValue(final Argument<T> definition) {
        // Safe because put guarantees that the map is heterogeneous
        @SuppressWarnings("unchecked")
        T value = (T) parsedArguments.get(definition);
        return value;
    }

    Collection<Argument<?>> requiredArgumentsLeft() {
        return filter(allArguments, and(not(in(parsedArguments.keySet())), IS_REQUIRED));
    }

    int indexedArgumentsParsed() {
        return indexedArgumentsParsed;
    }

    Set<Argument<?>> parsedArguments() {
        return parsedArguments.keySet();
    }

    Set<String> nonParsedArguments() {
        Set<String> validArguments = Sets.newHashSetWithExpectedSize(allArguments.size());
        for (Argument<?> argument : allArguments) {
            boolean wasGiven = wasGiven(argument);
            if (!wasGiven || argument.isAllowedToRepeat()) {
                for (String name : argument.names()) {
                    if (argument.separator().equals(ArgumentBuilder.DEFAULT_SEPARATOR)
                            || argument.isPropertyMap()) {
                        validArguments.add(name);
                    } else {
                        validArguments.add(name + argument.separator());
                    }

                }
            }
        }
        return validArguments;
    }
}