/*
* Copyright 2006 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.
*/
package org.caudexorigo.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;
class ArgumentValidatorImpl<O> implements ArgumentValidator<O>
{
private final ValidationErrorBuilder m_validationErrorBuilder;
private final List<String> m_validatedUnparsedArguments;
private final Map<String, List<String>> m_validatedArguments;
private final OptionsSpecification<O> m_specification;
public ArgumentValidatorImpl(OptionsSpecification<O> specification)
{
this.m_specification = specification;
m_validatedArguments = new LinkedHashMap<String, List<String>>();
m_validatedUnparsedArguments = new ArrayList<String>();
m_validationErrorBuilder = new ValidationErrorBuilderImpl();
}
/**
* @inheritdoc
*/
public ValidatedArguments validateArguments(final ParsedArguments arguments) throws ArgumentValidationException
{
m_validatedUnparsedArguments.addAll(arguments.getUnparsed());
final Iterator<Entry<String, List<String>>> argumentsIterator = arguments.iterator();
while (argumentsIterator.hasNext())
{
final Entry<String, List<String>> entry = argumentsIterator.next();
boolean isLast = !argumentsIterator.hasNext();
if (!m_specification.isSpecified(entry.getKey()))
{
m_validationErrorBuilder.unexpectedOption(entry.getKey());
}
else
{
final OptionSpecification optionSpecification = m_specification.getSpecification(entry.getKey());
if (optionSpecification.isHelpOption())
{
m_validationErrorBuilder.helpRequested(m_specification);
}
else if (entry.getValue().size() == 0 && optionSpecification.hasValue() && !optionSpecification.isMultiValued())
{
m_validationErrorBuilder.missingValue(optionSpecification);
}
else if (!isLast && entry.getValue().size() > 0 && !optionSpecification.hasValue())
{
m_validationErrorBuilder.unexpectedValue(optionSpecification);
}
else if (!isLast && entry.getValue().size() > 1 && !optionSpecification.isMultiValued())
{
m_validationErrorBuilder.unexpectedAdditionalValues(optionSpecification);
}
if (isLast && hasExcessValues(entry, optionSpecification))
{
final List<String> values = new ArrayList<String>();
final List<String> unparsed;
if (optionSpecification.hasValue())
{
values.add(entry.getValue().get(0));
unparsed = new ArrayList<String>(entry.getValue().subList(1, entry.getValue().size()));
}
else
{
unparsed = entry.getValue();
}
m_validatedArguments.put(entry.getKey(), values);
m_validatedUnparsedArguments.addAll(0, unparsed);
}
else
{
checkAndAddValues(optionSpecification, entry.getKey(), new ArrayList<String>(entry.getValue()));
}
}
}
for (final OptionSpecification optionSpecification : m_specification.getMandatoryOptions())
{
if (!(arguments.containsAny(optionSpecification.getAllNames())))
{
m_validationErrorBuilder.missingOption(optionSpecification);
}
}
m_validationErrorBuilder.validate();
return new ArgumentsImpl(m_validatedArguments, m_validatedUnparsedArguments);
}
private boolean hasExcessValues(final Entry<String, List<String>> entry, final OptionSpecification optionSpecification)
{
return (!optionSpecification.isMultiValued() && (entry.getValue().size() > 1 || (entry.getValue().size() > 0 && !optionSpecification.hasValue())));
}
private void checkAndAddValues(final OptionSpecification optionSpecification, final String option, final ArrayList<String> values)
{
for (final String value : values)
{
if (!optionSpecification.patternMatches(value))
{
m_validationErrorBuilder.patternMismatch(optionSpecification, value);
}
}
m_validatedArguments.put(option, new ArrayList<String>(values));
}
}