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> </td><td nowrap="nowrap">{@code --check}</td><td> </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> </td><td nowrap="nowrap">{@code --merge}</td><td> </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> </td><td nowrap="nowrap">{@code --unique}</td><td> </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> </td><td nowrap="nowrap">{@code --ignoreLeadingBlanks}</td><td> </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> </td><td nowrap="nowrap">{@code --dictionaryOrder}</td><td> </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> </td><td nowrap="nowrap">{@code --ignoreCase}</td><td> </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> </td><td nowrap="nowrap">{@code --numericSort}</td><td> </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> </td><td nowrap="nowrap">{@code --generalNumericSort}</td><td> </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> </td><td nowrap="nowrap">{@code --humanNumericSort}</td><td> </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> </td><td nowrap="nowrap">{@code --monthSort}</td><td> </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> </td><td nowrap="nowrap">{@code --versionSort}</td><td> </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> </td><td nowrap="nowrap">{@code --reverse}</td><td> </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}