001package org.unix4j.unix.sed;
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.Sed;
013import org.unix4j.unix.sed.SedOption;
014
015/**
016 * Interface implemented by all option sets for the {@link Sed sed} command.
017 * It is recommended to use {@link Sed#Options} to specify a valid 
018 * combination of options.
019 * <p>
020 * The options for the sed command are: 
021 * <p>
022 * <table>
023 * <tr valign="top"><td width="10px"></td><td nowrap="nowrap">{@code -n}</td><td>&nbsp;&nbsp;</td><td nowrap="nowrap">{@code --quiet}</td><td>&nbsp;</td><td>Suppress the default output (in which each line, after it is 
024                        examined for editing, is written to standard output). Only lines 
025                        explicitly selected for output are written.</td></tr>
026 * <tr valign="top"><td width="10px"></td><td nowrap="nowrap">{@code -g}</td><td>&nbsp;&nbsp;</td><td nowrap="nowrap">{@code --global}</td><td>&nbsp;</td><td>Globally substitute for all non-overlapping instances of the regexp 
027                        rather than just the first one. 
028                        <p>
029                        (This option is ignored if the occurrence operand is specified).</td></tr>
030 * <tr valign="top"><td width="10px"></td><td nowrap="nowrap">{@code -p}</td><td>&nbsp;&nbsp;</td><td nowrap="nowrap">{@code --print}</td><td>&nbsp;</td><td>Write the matched line to standard output.</td></tr>
031 * <tr valign="top"><td width="10px"></td><td nowrap="nowrap">{@code -l}</td><td>&nbsp;&nbsp;</td><td nowrap="nowrap">{@code --lineNumber}</td><td>&nbsp;</td><td>Writes the current line number on a separate line to the standard 
032                        output.</td></tr>
033 * <tr valign="top"><td width="10px"></td><td nowrap="nowrap">{@code -I}</td><td>&nbsp;&nbsp;</td><td nowrap="nowrap">{@code --ignoreCase}</td><td>&nbsp;</td><td>Use case insensitive pattern matching.</td></tr>
034 * <tr valign="top"><td width="10px"></td><td nowrap="nowrap">{@code -s}</td><td>&nbsp;&nbsp;</td><td nowrap="nowrap">{@code --substitute}</td><td>&nbsp;</td><td>Substitutes the replacement string for instances of the regexp in 
035                        the matched line.
036                        <p>
037                        An ampersand ('&') appearing in the replacement is be replaced 
038                        by the line matching the regexp. The characters "\n", where n is a 
039                        digit, are replaced by the text matched by the corresponding 
040                        backreference expression.  The special meaning of '&' and "\n" 
041                        in this context can be suppressed by preceding it by a backslash. 
042<p>
043                        A line can be split by substituting a newline ('\n') into it. 
044                        <p>
045                        A substitution is considered to have been performed even if the 
046                        replacement string is identical to the string that it replaces.</td></tr>
047 * <tr valign="top"><td width="10px"></td><td nowrap="nowrap">{@code -a}</td><td>&nbsp;&nbsp;</td><td nowrap="nowrap">{@code --append}</td><td>&nbsp;</td><td>Append string2 as a separate line after the matched line.</td></tr>
048 * <tr valign="top"><td width="10px"></td><td nowrap="nowrap">{@code -i}</td><td>&nbsp;&nbsp;</td><td nowrap="nowrap">{@code --insert}</td><td>&nbsp;</td><td>Insert string2 as a separate line before the matched line.</td></tr>
049 * <tr valign="top"><td width="10px"></td><td nowrap="nowrap">{@code -c}</td><td>&nbsp;&nbsp;</td><td nowrap="nowrap">{@code --change}</td><td>&nbsp;</td><td>Write string2 as a separate line instead of the matched line.</td></tr>
050 * <tr valign="top"><td width="10px"></td><td nowrap="nowrap">{@code -d}</td><td>&nbsp;&nbsp;</td><td nowrap="nowrap">{@code --delete}</td><td>&nbsp;</td><td>Delete the matched line.</td></tr>
051 * <tr valign="top"><td width="10px"></td><td nowrap="nowrap">{@code -y}</td><td>&nbsp;&nbsp;</td><td nowrap="nowrap">{@code --translate}</td><td>&nbsp;</td><td>Replace all occurrences of characters in string1 with the 
052                        corresponding characters in string2. If the number of characters in 
053                        the two strings are not equal, or if any of the characters in 
054                        string1 appear more than once, the results are undefined.</td></tr>
055 * </table>
056 * <p>
057 * This interface serves as an alias for the extended interface to simplify the
058 * command signature methods by avoiding generic parameters.
059 */
060public interface SedOptions extends OptionSet<SedOption> {
061        /**
062         * Constant for an empty option set.
063         */
064        SedOptions EMPTY = new SedOptions() {
065                @Override
066                public Class<SedOption> optionType() {
067                        return SedOption.class;
068                }
069                @Override
070                public boolean isSet(SedOption option) {
071                        return false;
072                }
073                /**
074                 * Returns 0 as this is a set with no active options.
075                 * 
076                 * @return zero
077                 */
078                @Override
079                public int size() {
080                        return 0;
081                }
082                /**
083                 * Returns an immutable empty set.
084                 * 
085                 * @return an immutable empty set.
086                 */
087                @Override
088                public java.util.Set<SedOption> asSet() {
089                        return Collections.emptySet();
090                }
091                
092                /**
093                 * Returns an iterator returning no elements. 
094                 * 
095                 * @return an immutable iterator with no elements.
096                 */
097                @Override
098                public Iterator<SedOption> iterator() {
099                        return asSet().iterator();
100                }
101                
102                /**
103                 * Returns true if the {@link Option#acronym() acronym} should be used
104                 * for the specified {@code option} in string representations. 
105                 * <p>
106                 * This method returns always true;
107                 *  
108                 * @param option
109                 *            the option of interest
110                 * @return always true
111                 */
112                @Override
113                public boolean useAcronymFor(SedOption option) {
114                        return true;
115                }
116        };
117        /**
118         * Default implementation for a modifiable option set.
119         */
120        class Default extends DefaultOptionSet<SedOption> implements SedOptions {
121                /**
122                 * Default constructor for an empty option set with no active options.
123                 */
124                public Default() {
125                        super(SedOption.class);
126                }
127                /**
128                 * Constructor for an option set with a single active option.
129                 * @param option the option to be set
130                 */
131                public Default(SedOption option) {
132                        super(option);
133                }
134                /**
135                 * Constructor for an option set with the given active options.
136                 * @param options the options to be set
137                 */
138                public Default(SedOption... options) {
139                        this();
140                        setAll(options);
141                }
142                /**
143                 * Constructor for an option set initialized with the options given by
144                 * another option set.
145                 * 
146                 * @param optionSet set with the options to be active
147                 */
148                public Default(OptionSet<SedOption> optionSet) {
149                        this();
150                        setAll(optionSet);
151                }
152        }
153        
154        /**
155         * Value converter for {@link SedOptions} based on an {@link OptionSetConverter}. 
156         */
157        ValueConverter<SedOptions> CONVERTER = new ValueConverter<SedOptions>() {
158                private final OptionSetConverter<SedOption> converter = new OptionSetConverter<SedOption>(SedOption.class);
159                @Override
160                public SedOptions convert(Object value) {
161                        final OptionSet<SedOption> set = converter.convert(value);
162                        return set == null ? null : new Default(set);
163                }
164        };
165}