001package org.unix4j.unix.find;
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.Find;
013import org.unix4j.unix.find.FindOption;
014
015/**
016 * Interface implemented by all option sets for the {@link Find find} command.
017 * It is recommended to use {@link Find#Options} to specify a valid 
018 * combination of options.
019 * <p>
020 * The options for the find command are: 
021 * <p>
022 * <table>
023 * <tr valign="top"><td width="10px"></td><td nowrap="nowrap">{@code -d}</td><td>&nbsp;&nbsp;</td><td nowrap="nowrap">{@code --typeDirectory}</td><td>&nbsp;</td><td>Consider only directories</td></tr>
024 * <tr valign="top"><td width="10px"></td><td nowrap="nowrap">{@code -f}</td><td>&nbsp;&nbsp;</td><td nowrap="nowrap">{@code --typeFile}</td><td>&nbsp;</td><td>Consider only regular files</td></tr>
025 * <tr valign="top"><td width="10px"></td><td nowrap="nowrap">{@code -l}</td><td>&nbsp;&nbsp;</td><td nowrap="nowrap">{@code --typeSymlink}</td><td>&nbsp;</td><td>Consider only symbolic links</td></tr>
026 * <tr valign="top"><td width="10px"></td><td nowrap="nowrap">{@code -x}</td><td>&nbsp;&nbsp;</td><td nowrap="nowrap">{@code --typeOther}</td><td>&nbsp;</td><td>Consider only files that are neither of directory (d), 
027                        regular file (f) or symlink (l).</td></tr>
028 * <tr valign="top"><td width="10px"></td><td nowrap="nowrap">{@code -r}</td><td>&nbsp;&nbsp;</td><td nowrap="nowrap">{@code --regex}</td><td>&nbsp;</td><td>Use full regular expression syntax for the patterns specified by the
029                        name operand
030<p>
031                        (This option is ignored if no name operand is specified).</td></tr>
032 * <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 matching when applying the file name pattern
033                        specified by the name operand
034<p>
035                        (This option is ignored if no name operand is specified).</td></tr>
036 * <tr valign="top"><td width="10px"></td><td nowrap="nowrap">{@code -n}</td><td>&nbsp;&nbsp;</td><td nowrap="nowrap">{@code --timeNewer}</td><td>&nbsp;</td><td>Consider only files that have been created, modified or accessed
037                        after or at the time specified by the time operand (the default)
038                        <p>
039                        (This option is ignored if no time operand is specified).</td></tr>
040 * <tr valign="top"><td width="10px"></td><td nowrap="nowrap">{@code -o}</td><td>&nbsp;&nbsp;</td><td nowrap="nowrap">{@code --timeOlder}</td><td>&nbsp;</td><td>Consider only files that have been created, modified or accessed
041                        before or at the time specified by the time operand
042                        <p>
043                        (This option is ignored if no time operand is specified).</td></tr>
044 * <tr valign="top"><td width="10px"></td><td nowrap="nowrap">{@code -c}</td><td>&nbsp;&nbsp;</td><td nowrap="nowrap">{@code --timeCreate}</td><td>&nbsp;</td><td>The time operand refers to the creation time of the file
045                        <p>
046                        (This option is ignored if no time operand is specified).</td></tr>
047 * <tr valign="top"><td width="10px"></td><td nowrap="nowrap">{@code -a}</td><td>&nbsp;&nbsp;</td><td nowrap="nowrap">{@code --timeAccess}</td><td>&nbsp;</td><td>The time operand refers to the last access time of the file
048                        <p>
049                        (This option is ignored if no time operand is specified).</td></tr>
050 * <tr valign="top"><td width="10px"></td><td nowrap="nowrap">{@code -m}</td><td>&nbsp;&nbsp;</td><td nowrap="nowrap">{@code --timeModified}</td><td>&nbsp;</td><td>The time operand refers to the last modification time of the file
051                        (the default)
052                        <p>
053                        (This option is ignored if no time operand is specified).</td></tr>
054 * <tr valign="top"><td width="10px"></td><td nowrap="nowrap">{@code -z}</td><td>&nbsp;&nbsp;</td><td nowrap="nowrap">{@code --print0}</td><td>&nbsp;</td><td>Print the full file name on the standard output, followed by a null 
055                        character (instead of the newline character used by default). This
056                        allows file names that contain newlines or other types of white 
057                        space to be correctly interpreted by programs that process the find 
058                        output. This option corresponds to the --delimiter0 option of xargs.</td></tr>
059 * </table>
060 * <p>
061 * This interface serves as an alias for the extended interface to simplify the
062 * command signature methods by avoiding generic parameters.
063 */
064public interface FindOptions extends OptionSet<FindOption> {
065        /**
066         * Constant for an empty option set.
067         */
068        FindOptions EMPTY = new FindOptions() {
069                @Override
070                public Class<FindOption> optionType() {
071                        return FindOption.class;
072                }
073                @Override
074                public boolean isSet(FindOption option) {
075                        return false;
076                }
077                /**
078                 * Returns 0 as this is a set with no active options.
079                 * 
080                 * @return zero
081                 */
082                @Override
083                public int size() {
084                        return 0;
085                }
086                /**
087                 * Returns an immutable empty set.
088                 * 
089                 * @return an immutable empty set.
090                 */
091                @Override
092                public java.util.Set<FindOption> asSet() {
093                        return Collections.emptySet();
094                }
095                
096                /**
097                 * Returns an iterator returning no elements. 
098                 * 
099                 * @return an immutable iterator with no elements.
100                 */
101                @Override
102                public Iterator<FindOption> iterator() {
103                        return asSet().iterator();
104                }
105                
106                /**
107                 * Returns true if the {@link Option#acronym() acronym} should be used
108                 * for the specified {@code option} in string representations. 
109                 * <p>
110                 * This method returns always true;
111                 *  
112                 * @param option
113                 *            the option of interest
114                 * @return always true
115                 */
116                @Override
117                public boolean useAcronymFor(FindOption option) {
118                        return true;
119                }
120        };
121        /**
122         * Default implementation for a modifiable option set.
123         */
124        class Default extends DefaultOptionSet<FindOption> implements FindOptions {
125                /**
126                 * Default constructor for an empty option set with no active options.
127                 */
128                public Default() {
129                        super(FindOption.class);
130                }
131                /**
132                 * Constructor for an option set with a single active option.
133                 * @param option the option to be set
134                 */
135                public Default(FindOption option) {
136                        super(option);
137                }
138                /**
139                 * Constructor for an option set with the given active options.
140                 * @param options the options to be set
141                 */
142                public Default(FindOption... options) {
143                        this();
144                        setAll(options);
145                }
146                /**
147                 * Constructor for an option set initialized with the options given by
148                 * another option set.
149                 * 
150                 * @param optionSet set with the options to be active
151                 */
152                public Default(OptionSet<FindOption> optionSet) {
153                        this();
154                        setAll(optionSet);
155                }
156        }
157        
158        /**
159         * Value converter for {@link FindOptions} based on an {@link OptionSetConverter}. 
160         */
161        ValueConverter<FindOptions> CONVERTER = new ValueConverter<FindOptions>() {
162                private final OptionSetConverter<FindOption> converter = new OptionSetConverter<FindOption>(FindOption.class);
163                @Override
164                public FindOptions convert(Object value) {
165                        final OptionSet<FindOption> set = converter.convert(value);
166                        return set == null ? null : new Default(set);
167                }
168        };
169}