/*
 * Copyright 2013 the original author or authors.
 *
 * 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.gradle.api.internal.tasks.options;

import org.gradle.internal.exceptions.DiagnosticsVisitor;
import org.gradle.internal.typeconversion.*;

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

public class OptionNotationParserFactory {
    public ValueAwareNotationParser<Object> toComposite(Class<?> targetType) throws OptionValidationException {
        assert targetType != null : "resultingType cannot be null";
        List<ValueAwareNotationParser<?>> parsers = new ArrayList<ValueAwareNotationParser<?>>();

        if (targetType == Void.TYPE) {
            parsers.add(new UnsupportedNotationParser());
        }
        if (targetType.isAssignableFrom(String.class)) {
            parsers.add(new NoDescriptionValuesJustReturningParser<String>(targetType.asSubclass(String.class)));
        }
        if (targetType.isEnum()) {
            parsers.add(new EnumFromCharSequenceNotationParser<Enum>(targetType.asSubclass(Enum.class)));
        }
        if (parsers.isEmpty()) {
            throw new OptionValidationException(String.format("Don't know how to convert strings to type '%s'.", targetType.getName()));
        }
        return new ValueAwareCompositeNotationParser<Object>(parsers);
    }

    private static class UnsupportedNotationParser implements ValueAwareNotationParser<Object> {

        public Object parseNotation(CharSequence notation) throws UnsupportedNotationException, TypeConversionException {
            throw new UnsupportedOperationException();
        }

        @Override
        public void describe(DiagnosticsVisitor visitor) {
        }

        public void describeValues(Collection<String> collector) {
        }
    }

    private static class NoDescriptionValuesJustReturningParser<T extends CharSequence> implements ValueAwareNotationParser<T> {
        private final Class<? extends T> passThroughType;

        public NoDescriptionValuesJustReturningParser(Class<? extends T> targetType) {
            this.passThroughType = targetType;
        }

        public T parseNotation(CharSequence notation) {
            if (!passThroughType.isInstance(notation)) {
                throw new UnsupportedNotationException(notation);
            }
            return passThroughType.cast(notation);
        }

        @Override
        public void describe(DiagnosticsVisitor visitor) {
            visitor.candidate(String.format("Instances of %s.", passThroughType.getSimpleName()));
        }

        public void describeValues(Collection<String> collector) {
        }
    }

    private static class ValueAwareCompositeNotationParser<T> extends CompositeNotationParser<CharSequence, T> implements ValueAwareNotationParser<T> {
        private final Collection<ValueAwareNotationParser<? extends T>> delegates;

        public ValueAwareCompositeNotationParser(Collection<ValueAwareNotationParser<? extends T>> delegates) {
            super(delegates);
            this.delegates = delegates;
        }

        public void describeValues(Collection<String> collector) {
            for (ValueAwareNotationParser<? extends T> delegate : delegates) {
                delegate.describeValues(collector);
            }
        }
    }
}

@@ -1399,52 +1399,9 @@
 rser
-%3CString%3E(targetType.asSubclass(String.class)
+(
 ));%0A
@@ -2344,32 +2344,8 @@
 rser
-%3CT extends CharSequence%3E
  imp
@@ -2381,458 +2381,116 @@
 ser%3C
-T%3E %7B%0A        private final Class%3C? extends T%3E passThroughType;%0A%0A        public NoDescriptionValuesJustReturningParser(Class%3C? extends T%3E targetType) %7B%0A            this.passThroughType = targetType;%0A        %7D%0A%0A        public T parseNotation(CharSequence notation) %7B%0A            if (!passThroughType.isInstance(notation)) %7B%0A                throw new UnsupportedNotationException(notation);%0A            %7D%0A            return passThroughType.cast(notation
+String%3E %7B%0A        public String parseNotation(CharSequence notation) %7B%0A            return notation.toString(
 );%0A 
@@ -2610,74 +2610,46 @@
 ate(
-String.format(%22Instances of %25s.%22, passThroughType.getSimpleName())
+%22Instances of String or CharSequence.%22
 );%0A 

Simplify option parser a little more (also happens to make it actually work).