001/*
002 * Copyright 2003-2005 The Apache Software Foundation
003 * Copyright 2005 Stephen McConnell
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * 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 */
017package net.dpml.cli.validation;
018
019import java.io.File;
020import java.util.List;
021import 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>existing</li>
033 *  <li>is a file</li>
034 *  <li>is a directory</li>
035 * </ul>
036 *
037 * The following example shows how to limit the valid values
038 * for the config attribute to files that exist.
039 *
040 * <pre>
041 * ...
042 * ArgumentBuilder builder = new ArgumentBuilder();
043 * FileValidator validator = FileValidator.getExistingFileInstance();
044 * Argument age = 
045 *     builder.withName("config");
046 *            .withValidator(validator);
047 * </pre>
048 * 
049 * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
050 * @version @PROJECT-VERSION@
051 */
052public class FileValidator implements Validator
053{
054    /**
055     * Returns a <code>FileValidator</code> for existing files/directories.
056     *
057     * @return a <code>FileValidator</code> for existing files/directories.
058     */
059    public static FileValidator getExistingInstance() 
060    {
061        final FileValidator validator = new FileValidator();
062        validator.setExisting( true );
063        return validator;
064    }
065
066    /**
067     * Returns a <code>FileValidator</code> for existing files.
068     *
069     * @return a <code>FileValidator</code> for existing files.
070     */
071    public static FileValidator getExistingFileInstance()
072    {
073        final FileValidator validator = new FileValidator();
074        validator.setExisting( true );
075        validator.setFile( true );
076        return validator;
077    }
078
079    /**
080     * Returns a <code>FileValidator</code> for existing directories.
081     *
082     * @return a <code>FileValidator</code> for existing directories.
083     */
084    public static FileValidator getExistingDirectoryInstance()
085    {
086        final FileValidator validator = new FileValidator();
087        validator.setExisting( true );
088        validator.setDirectory( true );
089        return validator;
090    }
091
092    /** whether the argument value exists */
093    private boolean m_existing = false;
094    
095    /** whether the argument value is a directory */
096    private boolean m_directory = false;
097    
098    /** whether the argument value is a file */
099    private boolean m_file = false;
100
101   /**
102    * Validate the list of values against the list of permitted values.
103    * If a value is valid, replace the string in the <code>values</code>
104    * {@link java.util.List} with the {@link java.io.File} instance.
105    * 
106    * @param values the list of values to validate 
107    * @exception InvalidArgumentException if a value is invalid
108    * @see net.dpml.cli.validation.Validator#validate(java.util.List)
109    */
110    public void validate( final List values ) throws InvalidArgumentException 
111    {
112        for( final ListIterator i = values.listIterator(); i.hasNext();) 
113        {
114            final Object next = i.next();
115            if( next instanceof File )
116            {
117                return;
118            }
119            final String name = (String) next;
120            final File f = new File( name );
121            if( ( m_existing && !f.exists() )
122              || ( m_file && !f.isFile() )
123              || ( m_directory && !f.isDirectory() ) )
124            {
125                throw new InvalidArgumentException( name );
126            }
127            i.set( f );
128        }
129    }
130
131    /**
132     * Returns whether the argument values must represent directories.
133     *
134     * @return whether the argument values must represent directories.
135     */
136    public boolean isDirectory()
137    {
138        return m_directory;
139    }
140
141    /**
142     * Specifies whether the argument values must represent directories.
143     *
144     * @param directory specifies whether the argument values must 
145     * represent directories.
146     */
147    public void setDirectory( boolean directory )
148    {
149        m_directory = directory;
150    }
151
152    /**
153     * Returns whether the argument values must represent existing 
154     * files/directories.
155     *
156     * @return whether the argument values must represent existing 
157     * files/directories.
158     */
159    public boolean isExisting()
160    {
161        return m_existing;
162    }
163
164    /**
165     * Specifies whether the argument values must represent existing 
166     * files/directories.
167     *
168     * @param existing specifies whether the argument values must 
169     * represent existing files/directories.
170     */
171    public void setExisting( boolean existing )
172    {
173        m_existing = existing;
174    }
175
176    /**
177     * Returns whether the argument values must represent directories.
178     *
179     * @return whether the argument values must represent directories.
180     */
181    public boolean isFile()
182    {
183        return m_file;
184    }
185
186    /**
187     * Specifies whether the argument values must represent files.
188     *
189     * @param file specifies whether the argument values must 
190     * represent files.
191     */
192    public void setFile( boolean file )
193    {
194        m_file = file;
195    }
196}