001package org.unix4j.convert;
002
003import org.unix4j.option.DefaultOptionSet;
004import org.unix4j.option.Option;
005import org.unix4j.option.OptionSet;
006
007public class OptionSetConverters {
008        public static class OptionToSingletonSetConverter<O extends Enum<O> & Option> implements ValueConverter<OptionSet<O>> {
009                private final Class<O> optionEnumClass;
010                public OptionToSingletonSetConverter(Class<O> optionEnumClass) {
011                        this.optionEnumClass = optionEnumClass;
012                }
013                @Override
014                public OptionSet<O> convert(Object value) throws IllegalArgumentException {
015                        if (optionEnumClass.isInstance(value)) {
016                                final O option = optionEnumClass.cast(value);
017                                return toSingletonSet(option);
018                        }
019                        return null;
020                }
021        }
022        public static class NameOrAcronymToOptionConverter<O extends Enum<O> & Option> implements ValueConverter<O> {
023                private final O[] options;
024                public NameOrAcronymToOptionConverter(Class<O> optionEnumClass) {
025                        this.options = optionEnumClass.getEnumConstants();
026                }
027                @Override
028                public O convert(Object value) throws IllegalArgumentException {
029                        if (value != null) {
030                                final String optionString = value.toString();
031                                if (optionString.length() > 0) {
032                                        for (final O option : options) {
033                                                if (option.name().equals(optionString) || (optionString.length() == 1 && optionString.charAt(0) == option.acronym())) {
034                                                        return option;
035                                                }
036                                        }
037                                }
038                        }
039                        return null;
040                }
041        }
042        public static class OptionNameStringToSingletonSetConverter<O extends Enum<O> & Option> implements ValueConverter<OptionSet<O>> {
043                private final Class<O> optionEnumClass;
044                public OptionNameStringToSingletonSetConverter(Class<O> optionEnumClass) {
045                        this.optionEnumClass = optionEnumClass;
046                }
047                @Override
048                public OptionSet<O> convert(Object value) throws IllegalArgumentException {
049                        if (value != null) {
050                                final String optionString = value.toString();
051                                if (optionString.startsWith("--")) {
052                                        final String optionName = optionString.substring(2);  
053                                        final O option;
054                                        try {
055                                                option = Enum.valueOf(optionEnumClass, optionName);
056                                        } catch (IllegalArgumentException e) {
057                                                return null;
058                                        }
059                                        return toSingletonSet(option);
060                                }
061                        }
062                        return null;
063                }
064        }
065        public static class AcronymStringToOptionSetConverter<O extends Enum<O> & Option> implements ValueConverter<OptionSet<O>> {
066                private final Class<O> optionEnumClass;
067                private final O[] options;
068                public AcronymStringToOptionSetConverter(Class<O> optionEnumClass) {
069                        this.optionEnumClass = optionEnumClass;
070                        this.options = optionEnumClass.getEnumConstants();
071                }
072                @Override
073                public OptionSet<O> convert(Object value) throws IllegalArgumentException {
074                        if (value != null) {
075                                final String optionString = value.toString();
076                                if (optionString.startsWith("-")) {
077                                        DefaultOptionSet<O> set = null;
078                                        for (int i = 1; i < optionString.length(); i++) {
079                                                final char acronym = optionString.charAt(i);
080                                                O found = null;
081                                                for (final O option : options) {
082                                                        if (option.acronym() == acronym) {
083                                                                found = option;
084                                                                break;
085                                                        }
086                                                }
087                                                if (found == null) {
088                                                        return null;
089                                                }
090                                                if (set == null) {
091                                                        set = new DefaultOptionSet<O>(optionEnumClass);
092                                                }
093                                                set.set(found);
094                                                set.setUseAcronymFor(found, true);
095                                        } 
096                                        return set;
097                                }
098                        }
099                        return null;
100                }
101        }
102        public static class IterableOfOptionNameOrAcronymToOptionSetConverter<O extends Enum<O> & Option> implements ValueConverter<OptionSet<O>> {
103                private final Class<O> optionEnumClass;
104                private final NameOrAcronymToOptionConverter<O> optionConverter;
105                public IterableOfOptionNameOrAcronymToOptionSetConverter(Class<O> optionEnumClass) {
106                        this.optionEnumClass = optionEnumClass;
107                        this.optionConverter = new NameOrAcronymToOptionConverter<O>(optionEnumClass);
108                }
109                @Override
110                public OptionSet<O> convert(Object value) throws IllegalArgumentException {
111                        if (value instanceof Iterable) {
112                                final Iterable<?> iterable = (Iterable<?>)value;
113                                DefaultOptionSet<O> set = null;
114                                for (final Object optionNameOrAcronym : iterable) {
115                                        final O option = optionConverter.convert(optionNameOrAcronym);
116                                        if (option == null) {
117                                                return null;
118                                        }
119                                        if (set == null) {
120                                                set = new DefaultOptionSet<O>(optionEnumClass);
121                                        }
122                                        set.set(option);
123                                        set.setUseAcronymFor(option, !option.name().equals(optionNameOrAcronym));
124                                }
125                                return set;
126                        }
127                        return null;
128                }
129        }
130        
131        public static class OptionSetConverter<O extends Enum<O> & Option> extends CompositeValueConverter<OptionSet<O>> {
132                public OptionSetConverter(Class<O> optionEnumClass) {
133                        add(new OptionToSingletonSetConverter<O>(optionEnumClass));
134                        add(new IterableOfOptionNameOrAcronymToOptionSetConverter<O>(optionEnumClass));
135                        add(new ConcatenatedConverter<OptionSet<O>>(new NameOrAcronymToOptionConverter<O>(optionEnumClass), new OptionToSingletonSetConverter<O>(optionEnumClass)));
136                }
137        }
138        
139        private static <O extends Enum<O> & Option> OptionSet<O> toSingletonSet(O option) {
140                if (option instanceof OptionSet) {
141                        @SuppressWarnings("unchecked")
142                        final OptionSet<O> set = (OptionSet<O>)option;
143                        return set;
144                }
145                return new DefaultOptionSet<O>(option);
146        }
147}