001package org.unix4j.unix.sort;
002
003import java.util.Collections;
004import java.util.Iterator;
005
006import org.unix4j.convert.OptionSetConverters.OptionSetConverter;
007import org.unix4j.convert.ValueConverter;
008import org.unix4j.option.DefaultOptionSet;
009import org.unix4j.option.Option;
010import org.unix4j.option.OptionSet;
011
012import org.unix4j.unix.Sort;
013import org.unix4j.unix.sort.SortOption;
014
015/**
016 * Interface implemented by all option sets for the {@link Sort sort} command.
017 * It is recommended to use {@link Sort#Options} to specify a valid 
018 * combination of options.
019 * <p>
020 * The options for the sort command are: 
021 * <p>
022 * <table>
023 * <tr valign="top"><td width="10px"></td><td nowrap="nowrap">{@code -c}</td><td>&nbsp;&nbsp;</td><td nowrap="nowrap">{@code --check}</td><td>&nbsp;</td><td>Checks that the single input file is ordered as specified by the
024                        arguments and the collating sequence of the current locale. No 
025                        output is produced; only the exit code is affected.</td></tr>
026 * <tr valign="top"><td width="10px"></td><td nowrap="nowrap">{@code -m}</td><td>&nbsp;&nbsp;</td><td nowrap="nowrap">{@code --merge}</td><td>&nbsp;</td><td>Merge only; the input file are assumed to be already sorted.</td></tr>
027 * <tr valign="top"><td width="10px"></td><td nowrap="nowrap">{@code -u}</td><td>&nbsp;&nbsp;</td><td nowrap="nowrap">{@code --unique}</td><td>&nbsp;</td><td>Unique: suppress all but one in each set of lines having equal keys.
028                        If used with the {@code -c} option, checks that there are no lines 
029                        with duplicate keys, in addition to checking that the input file is 
030                        sorted.</td></tr>
031 * <tr valign="top"><td width="10px"></td><td nowrap="nowrap">{@code -b}</td><td>&nbsp;&nbsp;</td><td nowrap="nowrap">{@code --ignoreLeadingBlanks}</td><td>&nbsp;</td><td>Ignore leading blanks. 
032                        (This option is ignored if a comparator operand is present).</td></tr>
033 * <tr valign="top"><td width="10px"></td><td nowrap="nowrap">{@code -d}</td><td>&nbsp;&nbsp;</td><td nowrap="nowrap">{@code --dictionaryOrder}</td><td>&nbsp;</td><td>Consider only blanks and alphanumeric characters.
034                        (This option is ignored if a comparator operand is present).</td></tr>
035 * <tr valign="top"><td width="10px"></td><td nowrap="nowrap">{@code -f}</td><td>&nbsp;&nbsp;</td><td nowrap="nowrap">{@code --ignoreCase}</td><td>&nbsp;</td><td>Consider all lowercase characters that have uppercase equivalents to
036                        be the uppercase equivalent for the purposes of comparison.
037                        (This option is ignored if a comparator operand is present).</td></tr>
038 * <tr valign="top"><td width="10px"></td><td nowrap="nowrap">{@code -n}</td><td>&nbsp;&nbsp;</td><td nowrap="nowrap">{@code --numericSort}</td><td>&nbsp;</td><td>Sort numerically; the number begins each line and consists of 
039                        optional blanks, an optional minus sign, and zero or more digits
040                        possibly separated by thousands separators, optionally followed by a
041                        decimal-point character and zero or more digits. An empty number is
042                        treated as '0'. The current local specifies the decimal-point 
043                        character and thousands separator.
044                        <p>
045                        Comparison is exact; there is no rounding error.
046                        <p>
047                        Neither a leading '+' nor exponential notation is recognized. To 
048                        compare such strings numerically, use the
049                        {@code -genericNumericSort (-g)} option. 
050<p>
051                        (This option is ignored if a comparator operand is present).</td></tr>
052 * <tr valign="top"><td width="10px"></td><td nowrap="nowrap">{@code -g}</td><td>&nbsp;&nbsp;</td><td nowrap="nowrap">{@code --generalNumericSort}</td><td>&nbsp;</td><td>Sort numerically, using the standard {@link Double#parseDouble(String)}  
053                        function to convert a trimmed line to a double-precision floating 
054                        point number. This allows floating point numbers to be specified in 
055                        scientific notation, like 1.0e-34 and 10e100. 
056                        <p>
057                        Uses the following collating sequence: Lines that cannot be parsed 
058                        because they do not represent valid double values (in alpha-numeric
059                        order); "-Infinity"; finite numbers in ascending numeric order 
060                        (with -0 < +0); "Infinity"; "NaN".
061<p>
062                        This option is usually slower than {@code -numeric-sort (-n)} and it
063                        can lose information when converting to floating point.         
064                <p>
065                        (This option is ignored if a comparator operand is present).</td></tr>
066 * <tr valign="top"><td width="10px"></td><td nowrap="nowrap">{@code -h}</td><td>&nbsp;&nbsp;</td><td nowrap="nowrap">{@code --humanNumericSort}</td><td>&nbsp;</td><td>Sort numerically, first by numeric sign (negative, zero, or 
067                        positive); then by SI suffix (either empty, or 'k' or 'K', or one 
068                        of 'MGTPEZY', in that order); and finally by numeric value. For
069                        example, '1023M' sorts before '1G' because 'M' (mega) precedes 'G' 
070                        (giga) as an SI suffix. 
071                        <p>
072                        This option sorts values that are consistently scaled to the nearest
073                        suffix, regardless of whether suffixes denote powers of 1000 or
074                        1024, and it therefore sorts the output of any single invocation of 
075                        the {@code ls} command that are invoked with the --human-readable 
076                        option. 
077                        <p>
078                        The syntax for numbers is the same as for the
079                        {@code --numericSort (-n)} option; the SI suffix must immediately 
080                        follow the number.              
081<p>
082                        (This option is ignored if a comparator operand is present).</td></tr>
083 * <tr valign="top"><td width="10px"></td><td nowrap="nowrap">{@code -M}</td><td>&nbsp;&nbsp;</td><td nowrap="nowrap">{@code --monthSort}</td><td>&nbsp;</td><td>An initial string, consisting of any amount of blanks, followed by a
084                        month name abbreviation, is folded to UPPER case and compared in the
085                        order: (unknown) < 'JAN' < ... < 'DEC'. The current locale
086                        determines the month spellings.</td></tr>
087 * <tr valign="top"><td width="10px"></td><td nowrap="nowrap">{@code -V}</td><td>&nbsp;&nbsp;</td><td nowrap="nowrap">{@code --versionSort}</td><td>&nbsp;</td><td>Sort by version name and number. It behaves like a standard sort, 
088                        except that each sequence of decimal digits is treated numerically 
089                        as an index/version number.
090                        <p>
091                        (This option is ignored if a comparator operand is present).</td></tr>
092 * <tr valign="top"><td width="10px"></td><td nowrap="nowrap">{@code -r}</td><td>&nbsp;&nbsp;</td><td nowrap="nowrap">{@code --reverse}</td><td>&nbsp;</td><td>Reverse the sense of comparisons.</td></tr>
093 * </table>
094 * <p>
095 * This interface serves as an alias for the extended interface to simplify the
096 * command signature methods by avoiding generic parameters.
097 */
098public interface SortOptions extends OptionSet<SortOption> {
099        /**
100         * Constant for an empty option set.
101         */
102        SortOptions EMPTY = new SortOptions() {
103                @Override
104                public Class<SortOption> optionType() {
105                        return SortOption.class;
106                }
107                @Override
108                public boolean isSet(SortOption option) {
109                        return false;
110                }
111                /**
112                 * Returns 0 as this is a set with no active options.
113                 * 
114                 * @return zero
115                 */
116                @Override
117                public int size() {
118                        return 0;
119                }
120                /**
121                 * Returns an immutable empty set.
122                 * 
123                 * @return an immutable empty set.
124                 */
125                @Override
126                public java.util.Set<SortOption> asSet() {
127                        return Collections.emptySet();
128                }
129                
130                /**
131                 * Returns an iterator returning no elements. 
132                 * 
133                 * @return an immutable iterator with no elements.
134                 */
135                @Override
136                public Iterator<SortOption> iterator() {
137                        return asSet().iterator();
138                }
139                
140                /**
141                 * Returns true if the {@link Option#acronym() acronym} should be used
142                 * for the specified {@code option} in string representations. 
143                 * <p>
144                 * This method returns always true;
145                 *  
146                 * @param option
147                 *            the option of interest
148                 * @return always true
149                 */
150                @Override
151                public boolean useAcronymFor(SortOption option) {
152                        return true;
153                }
154        };
155        /**
156         * Default implementation for a modifiable option set.
157         */
158        class Default extends DefaultOptionSet<SortOption> implements SortOptions {
159                /**
160                 * Default constructor for an empty option set with no active options.
161                 */
162                public Default() {
163                        super(SortOption.class);
164                }
165                /**
166                 * Constructor for an option set with a single active option.
167                 * @param option the option to be set
168                 */
169                public Default(SortOption option) {
170                        super(option);
171                }
172                /**
173                 * Constructor for an option set with the given active options.
174                 * @param options the options to be set
175                 */
176                public Default(SortOption... options) {
177                        this();
178                        setAll(options);
179                }
180                /**
181                 * Constructor for an option set initialized with the options given by
182                 * another option set.
183                 * 
184                 * @param optionSet set with the options to be active
185                 */
186                public Default(OptionSet<SortOption> optionSet) {
187                        this();
188                        setAll(optionSet);
189                }
190        }
191        
192        /**
193         * Value converter for {@link SortOptions} based on an {@link OptionSetConverter}. 
194         */
195        ValueConverter<SortOptions> CONVERTER = new ValueConverter<SortOptions>() {
196                private final OptionSetConverter<SortOption> converter = new OptionSetConverter<SortOption>(SortOption.class);
197                @Override
198                public SortOptions convert(Object value) {
199                        final OptionSet<SortOption> set = converter.convert(value);
200                        return set == null ? null : new Default(set);
201                }
202        };
203}