001    /**
002     * Copyright 2003-2004 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     */
017    package net.dpml.cli.builder;
018    
019    import java.util.HashSet;
020    import java.util.Iterator;
021    import java.util.Set;
022    
023    import net.dpml.cli.Argument;
024    import net.dpml.cli.Option;
025    import net.dpml.cli.validation.ClassValidator;
026    import net.dpml.cli.validation.DateValidator;
027    import net.dpml.cli.validation.FileValidator;
028    import net.dpml.cli.validation.NumberValidator;
029    import net.dpml.cli.validation.URLValidator;
030    import net.dpml.cli.validation.Validator;
031    
032    /**
033     * Builds Options using a String pattern
034     *
035     * @author <a href="http://www.dpml.net">Digital Product Meta Library</a>
036     * @version 1.0.0
037     */
038    public class PatternBuilder 
039    {
040        private final GroupBuilder m_gbuilder;
041        private final DefaultOptionBuilder m_obuilder;
042        private final ArgumentBuilder m_abuilder;
043        private final Set m_options = new HashSet();
044    
045        /**
046         * Creates a new PatternBuilder
047         */
048        public PatternBuilder()
049        {
050            this(
051                new GroupBuilder(),
052                new DefaultOptionBuilder(),
053                new ArgumentBuilder() );
054        }
055    
056        /**
057         * Creates a new PatternBuilder
058         * @param gbuilder the GroupBuilder to use
059         * @param obuilder the DefaultOptionBuilder to use
060         * @param abuilder the ArgumentBuilder to use
061         */
062        public PatternBuilder(
063            final GroupBuilder gbuilder,
064            final DefaultOptionBuilder obuilder,
065            final ArgumentBuilder abuilder )
066        {
067            m_gbuilder = gbuilder;
068            m_obuilder = obuilder;
069            m_abuilder = abuilder;
070        }
071    
072        /**
073         * Creates a new Option instance.
074         * @return a new Option instance
075         */
076        public Option create()
077        {
078            final Option option;
079            if( m_options.size() == 1 )
080            {
081                option = (Option) m_options.iterator().next();
082            }
083            else
084            {
085                m_gbuilder.reset();
086                for( final Iterator i = m_options.iterator(); i.hasNext();)
087                {
088                    m_gbuilder.withOption( (Option) i.next() );
089                }
090                option = m_gbuilder.create();
091            }
092            reset();
093            return option;
094        }
095    
096        /**
097         * Resets this builder
098         * @return the builder
099         */
100        public PatternBuilder reset()
101        {
102            m_options.clear();
103            return this;
104        }
105    
106        private void createOption( final char type, final boolean required, final char opt ) 
107        {
108            final Argument argument;
109            if( type != ' ' )
110            {
111                m_abuilder.reset();
112                m_abuilder.withValidator( validator( type ) );
113                if( required )
114                {
115                    m_abuilder.withMinimum( 1 );
116                }
117                if( type != '*' )
118                {
119                    m_abuilder.withMaximum( 1 );
120                }
121                argument = m_abuilder.create();
122            }
123            else
124            {
125                argument = null;
126            }
127    
128            m_obuilder.reset();
129            m_obuilder.withArgument( argument );
130            m_obuilder.withShortName( String.valueOf( opt ) );
131            m_obuilder.withRequired( required );
132            m_options.add( m_obuilder.create() );
133        }
134    
135        /**
136         * Builds an Option using a pattern string.
137         * @param pattern the pattern to build from
138         */
139        public void withPattern( final String pattern )
140        {
141            int sz = pattern.length();
142            char opt = ' ';
143            char ch = ' ';
144            char type = ' ';
145            boolean required = false;
146    
147            for( int i=0; i < sz; i++ )
148            {
149                ch = pattern.charAt( i );
150                switch( ch ) 
151                {
152                    case '!' :
153                        required = true;
154                        break;
155                    case '@' :
156                    case ':' :
157                    case '%' :
158                    case '+' :
159                    case '#' :
160                    case '<' :
161                    case '>' :
162                    case '*' :
163                    case '/' :
164                        type = ch;
165                        break;
166                    default :
167                        if( opt != ' ' )
168                        {
169                            createOption( type, required, opt );
170                            required = false;
171                            type = ' ';
172                        }
173                        opt = ch;
174                }
175            }
176            if( opt != ' ' )
177            {
178                createOption( type, required, opt );
179            }
180        }
181    
182        private static Validator validator( final char c )
183        {
184            switch( c )
185            {
186                case '@' :
187                    final ClassValidator classv = new ClassValidator();
188                    classv.setInstance( true );
189                    return classv;
190                case '+' :
191                    final ClassValidator instancev = new ClassValidator();
192                    return instancev;
193                    //case ':':// no validator needed for a string
194                case '%' :
195                    return NumberValidator.getNumberInstance();
196                case '#' :
197                    return DateValidator.getDateInstance();
198                case '<' :
199                    final FileValidator existingv = new FileValidator();
200                    existingv.setExisting( true );
201                    existingv.setFile( true );
202                    return existingv;
203                case '>' :
204                case '*' :
205                    return new FileValidator();
206                case '/' :
207                    return new URLValidator();
208                default :
209                    return null;
210            }
211        }
212    }