001    /*
002     * Copyright 2005 Stephen J. McConnell
003     *
004     * Licensed under the Apache License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     *     http://www.apache.org/licenses/LICENSE-2.0
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    package net.dpml.cli.validation;
017    
018    import java.net.URISyntaxException;
019    import java.net.URI;
020    
021    import java.util.List;
022    import java.util.ListIterator;
023    
024    /**
025     * The <code>URIValidator</code> validates the string argument
026     * values are valid URIs.  If the value is a URI, the string value in
027     * the {@link java.util.List} of values is replaced with the
028     * {@link java.net.URI} instance.
029     *
030     * The following example shows how to limit the valid values
031     * for the site argument to 'artifact' URIs.
032     *
033     * <pre>
034     * ...
035     * ArgumentBuilder builder = new ArgumentBuilder();
036     * Argument plugin =
037     *   builder
038     *     .withName("plugin");
039     *     .withValidator( new URIValidator( "artifact", "link" ) );
040     * </pre>
041     *
042     * @author <a href="http://www.dpml.net">Digital Product Meta Library</a>
043     * @version 1.0.0
044     */
045    public class URIValidator implements Validator 
046    {
047        private final String[] m_schemes;
048    
049       /**
050        * Creates a UriValidator.
051        */
052        public URIValidator() 
053        {
054            m_schemes = new String[0];
055        }
056    
057       /**
058        * Creates a UriValidator for the specified scheme.
059        * @param scheme the uri scheme
060        */
061        public URIValidator( final String scheme ) 
062        {
063            m_schemes = new String[]{scheme};
064        }
065        
066       /**
067        * Creates a UriValidator for the specified schemes.
068        * @param schemes an array of schemes
069        */
070        public URIValidator( final String[] schemes ) 
071        {
072            m_schemes = schemes;
073        }
074        
075       /**
076        * Validate the list of values against the list of permitted values.
077        * If a value is valid, replace the string in the <code>values</code>
078        * {@link java.util.List} with the {@link java.net.URI} instance.
079        *
080        * @param values the list of values to validate 
081        * @exception InvalidArgumentException if a value is invalid
082        * @see net.dpml.cli.validation.Validator#validate(java.util.List)
083        */
084        public void validate( final List values )
085            throws InvalidArgumentException 
086        {
087            for( final ListIterator i = values.listIterator(); i.hasNext();) 
088            {
089                final Object object = i.next();
090                if( object instanceof URI )
091                {
092                    break;
093                }
094                final String name = (String) object;
095                try 
096                {
097                    final URI uri = new URI( name );
098                    if( m_schemes.length == 0 )
099                    {
100                        i.set( uri );
101                    }
102                    else 
103                    {
104                        if( match( uri ) )
105                        {
106                            i.set( uri );
107                        }
108                        else
109                        {
110                            throw new InvalidArgumentException( name );
111                        }
112                    }
113                } 
114                catch( final URISyntaxException e )
115                {
116                    final String error =
117                      "Bad uri syntax in value [" + name + "].";
118                    throw new InvalidArgumentException( error );
119                }
120            }
121        }
122        
123        private boolean match( URI uri )
124        {
125            String scheme = uri.getScheme();
126            for( int i=0; i<m_schemes.length; i++ )
127            {
128                if( scheme.startsWith( m_schemes[i] ) )
129                {
130                    return true;
131                }
132            }
133            return false;
134        }
135    }