package com.lexicalscope.jewel.cli; import java.util.ArrayList; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import com.lexicalscope.jewel.cli.parser.ParsedArguments; import com.lexicalscope.jewel.cli.validation.ArgumentValidator; import com.lexicalscope.jewel.cli.validation.OptionCollection; /* * Copyright 2011 Tim Wood * * 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. */ public class ArgumentCollectionBuilder implements ParsedArguments { private interface IParsingState { IParsingState addValue(String value); IParsingState addOption(String option) throws ArgumentValidationException; } private class Initial implements IParsingState { @Override public IParsingState addValue(final String value) { return new NoOptions(value); } @Override public IParsingState addOption(final String option) { return new OptionOrValue(option); } } private class NoOptions implements IParsingState { public NoOptions(final String value) { addUnparsedValue(value); } @Override public IParsingState addValue(final String value) { addUnparsedValue(value); return this; } @Override public IParsingState addOption(final String option) throws ArgumentValidationException { throw misplacedOption(option); } } private class UnparsedState implements IParsingState { public UnparsedState() { valuesForCurrentArgument = null; } @Override public IParsingState addValue(final String value) { addUnparsedValue(value); return this; } @Override public IParsingState addOption(final String option) throws ArgumentValidationException { throw misplacedOption(option); } } private class OptionOrValue implements IParsingState { public OptionOrValue(final String option) { addFirstValueForOption(option); } @Override public IParsingState addValue(final String value) { valuesForCurrentArgument.add(value); return this; } @Override public IParsingState addOption(final String option) { return new OptionOrValue(option); } } private final Map<String, List<String>> arguments = new LinkedHashMap<String, List<String>>(); private final List<String> unparsed = new ArrayList<String>(); private IParsingState state = new Initial(); private List<String> valuesForCurrentArgument; @Override public void unparsedOptionsFollow() { state = new UnparsedState(); } @Override public void addValue(final String value) { state = state.addValue(value); } @Override public void addOption(final String option) { state = state.addOption(option); } @Override public OptionCollection processArguments(final ArgumentValidator argumentProcessor) { final Set<Entry<String, List<String>>> entrySet = arguments.entrySet(); final Iterator<Entry<String, List<String>>> iterator = entrySet.iterator(); while (iterator.hasNext()) { final Map.Entry<java.lang.String, java.util.List<java.lang.String>> entry = iterator.next(); if(iterator.hasNext()) { argumentProcessor.processOption(entry.getKey(), entry.getValue()); } else { argumentProcessor.processLastOption(entry.getKey(), entry.getValue()); } } argumentProcessor.processUnparsed(unparsed); return argumentProcessor.finishedProcessing(); } private ArgumentValidationException misplacedOption(final String option) { return new ArgumentValidationException(new ValidationFailureMisplacedOption(option)); } private void addUnparsedValue(final String value) { unparsed.add(value); } private void addFirstValueForOption(final String option) { if(!arguments.containsKey(option)) { valuesForCurrentArgument = new ArrayList<String>(); arguments.put(option, valuesForCurrentArgument); } valuesForCurrentArgument = arguments.get(option); } }