001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *     http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.apache.commons.cli2.validation;
018    
019    import java.io.File;
020    import java.util.List;
021    import java.util.ListIterator;
022    
023    /**
024     * The <code>FileValidator</code> validates the string argument
025     * values are files.  If the value is a file, the string value in
026     * the {@link java.util.List} of values is replaced with the
027     * {@link java.io.File} instance.
028     *
029     * The following attributes can also be specified using the
030     * appropriate settors:
031     * <ul>
032     *  <li>writable</li>
033     *  <li>readable</li>
034     *  <li>hidden</li>
035     *  <li>existing</li>
036     *  <li>is a file</li>
037     *  <li>is a directory</li>
038     * </ul>
039     *
040     * The following example shows how to limit the valid values
041     * for the config attribute to files that are readable, writeable,
042     * and that already existing.
043     *
044     * <pre>
045     * ...
046     * ArgumentBuilder builder = new ArgumentBuilder();
047     * FileValidator validator = FileValidator.getExistingFileInstance();
048     * validator.setReadable(true);
049     * validator.setWritable(true);
050     *
051     * Argument age =
052     *     builder.withName("config");
053     *            .withValidator(validator);
054     * </pre>
055     *
056     * @author Rob Oxspring
057     * @author John Keyes
058     */
059    public class FileValidator implements Validator {
060    
061        /**
062         * Returns a <code>FileValidator</code> for existing files/directories.
063         *
064         * @return a <code>FileValidator</code> for existing files/directories.
065         */
066        public static FileValidator getExistingInstance() {
067            final FileValidator validator = new FileValidator();
068            validator.setExisting(true);
069            return validator;
070        }
071    
072        /**
073         * Returns a <code>FileValidator</code> for existing files.
074         *
075         * @return a <code>FileValidator</code> for existing files.
076         */
077        public static FileValidator getExistingFileInstance() {
078            final FileValidator validator = new FileValidator();
079            validator.setExisting(true);
080            validator.setFile(true);
081            return validator;
082        }
083    
084        /**
085         * Returns a <code>FileValidator</code> for existing directories.
086         *
087         * @return a <code>FileValidator</code> for existing directories.
088         */
089        public static FileValidator getExistingDirectoryInstance() {
090            final FileValidator validator = new FileValidator();
091            validator.setExisting(true);
092            validator.setDirectory(true);
093            return validator;
094        }
095    
096        /** whether the argument value is readable */
097        private boolean readable = false;
098    
099        /** whether the argument value is writable */
100        private boolean writable = false;
101    
102        /** whether the argument value exists */
103        private boolean existing = false;
104    
105        /** whether the argument value is a directory */
106        private boolean directory = false;
107    
108        /** whether the argument value is a file */
109        private boolean file = false;
110    
111        /** whether the argument value is a hidden file or directory */
112        private boolean hidden = false;
113    
114        /**
115         * Validate the list of values against the list of permitted values.
116         * If a value is valid, replace the string in the <code>values</code>
117         * {@link java.util.List} with the {@link java.io.File} instance.
118         *
119         * @see org.apache.commons.cli2.validation.Validator#validate(java.util.List)
120         */
121        public void validate(final List values) throws InvalidArgumentException {
122            for (final ListIterator i = values.listIterator(); i.hasNext();) {
123                final String name = (String)i.next();
124                final File f = new File(name);
125    
126                if ((existing && !f.exists())
127                    || (file && !f.isFile())
128                    || (directory && !f.isDirectory())
129                    || (hidden && !f.isHidden())
130                    || (readable && !f.canRead())
131                    || (writable && !f.canWrite())) {
132    
133                    throw new InvalidArgumentException(name);
134                }
135    
136                i.set(f);
137            }
138        }
139    
140        /**
141         * Returns whether the argument values must represent directories.
142         *
143         * @return whether the argument values must represent directories.
144         */
145        public boolean isDirectory() {
146            return directory;
147        }
148    
149        /**
150         * Specifies whether the argument values must represent directories.
151         *
152         * @param directory specifies whether the argument values must
153         * represent directories.
154         */
155        public void setDirectory(boolean directory) {
156            this.directory = directory;
157        }
158    
159        /**
160         * Returns whether the argument values must represent existing
161         * files/directories.
162         *
163         * @return whether the argument values must represent existing
164         * files/directories.
165         */
166        public boolean isExisting() {
167            return existing;
168        }
169    
170        /**
171         * Specifies whether the argument values must represent existing
172         * files/directories.
173         *
174         * @param existing specifies whether the argument values must
175         * represent existing files/directories.
176         */
177        public void setExisting(boolean existing) {
178            this.existing = existing;
179        }
180    
181        /**
182         * Returns whether the argument values must represent directories.
183         *
184         * @return whether the argument values must represent directories.
185         */
186        public boolean isFile() {
187            return file;
188        }
189    
190        /**
191         * Specifies whether the argument values must represent files.
192         *
193         * @param file specifies whether the argument values must
194         * represent files.
195         */
196        public void setFile(boolean file) {
197            this.file = file;
198        }
199    
200        /**
201         * Returns whether the argument values must represent hidden
202         * files/directories.
203         *
204         * @return whether the argument values must represent hidden
205         * files/directories.
206         */
207        public boolean isHidden() {
208            return hidden;
209        }
210    
211        /**
212         * Specifies whether the argument values must represent hidden
213         * files/directories.
214         *
215         * @param hidden specifies whether the argument values must
216         * represent hidden files/directories.
217         */
218        public void setHidden(boolean hidden) {
219            this.hidden = hidden;
220        }
221    
222        /**
223         * Returns whether the argument values must represent readable
224         * files/directories.
225         *
226         * @return whether the argument values must represent readable
227         * files/directories.
228         */
229        public boolean isReadable() {
230            return readable;
231        }
232    
233        /**
234         * Specifies whether the argument values must represent readable
235         * files/directories.
236         *
237         * @param readable specifies whether the argument values must
238         * represent readable files/directories.
239         */
240        public void setReadable(boolean readable) {
241            this.readable = readable;
242        }
243    
244        /**
245         * Returns whether the argument values must represent writable
246         * files/directories.
247         *
248         * @return whether the argument values must represent writable
249         * files/directories.
250         */
251        public boolean isWritable() {
252            return writable;
253        }
254    
255        /**
256         * Specifies whether the argument values must represent writable
257         * files/directories.
258         *
259         * @param writable specifies whether the argument values must
260         * represent writable files/directories.
261         */
262        public void setWritable(boolean writable) {
263            this.writable = writable;
264        }
265    }