001    /**
002     * Copyright 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.commandline;
018    
019    import java.util.ArrayList;
020    import java.util.Collections;
021    import java.util.HashSet;
022    import java.util.Iterator;
023    import java.util.List;
024    import java.util.Properties;
025    import java.util.Set;
026    import java.util.StringTokenizer;
027    
028    import net.dpml.cli.Option;
029    
030    /**
031     * A CommandLine implementation using a java Properties instance, useful for
032     * constructing a complex DefaultingCommandLine
033     *
034     * Options are keyed from their property name and presence in the Properties
035     * instance is taken as presence in the CommandLine.  Argument values are taken
036     * from the property value and are optionally separated using the separator
037     * char, defined at construction time.  Switch values can be specified using a
038     * simple value of <code>true</code> or <code>false</code>; obviously this means
039     * that Switches with Arguments are not supported by this implementation.
040     *
041     * @author <a href="http://www.dpml.net">Digital Product Meta Library</a>
042     * @version 1.0.0
043     * @see java.util.Properties
044     * @see net.dpml.cli.commandline.DefaultingCommandLine
045     * @see net.dpml.cli.Option#getPreferredName() 
046     */
047    public class PropertiesCommandLine extends CommandLineImpl
048    {
049        
050        private static final char NUL = '\0';
051        private final Properties m_properties;
052        private final Option m_root;
053        private final char m_separator;
054        
055        /**
056         * Creates a new PropertiesCommandLine using the specified root Option,
057         * Properties instance.  The character 0 is used as the value separator.
058         *
059         * @param root the CommandLine's root Option
060         * @param properties the Properties instance to get values from
061         */
062        public PropertiesCommandLine( final Option root, final Properties properties )
063        {
064            this( root, properties, NUL );
065        }
066        
067        /**
068         * Creates a new PropertiesCommandLine using the specified root Option,
069         * Properties instance and value separator.
070         *
071         * @param root the CommandLine's root Option
072         * @param properties the Properties instance to get values from
073         * @param separator the character to split argument values
074         */
075        public PropertiesCommandLine( final Option root, final Properties properties, final char separator )
076        {
077            m_root = root;
078            m_properties = properties;
079            m_separator = separator;
080        }
081        
082        /**
083         * Detects the presence of an option in this CommandLine.
084         * 
085         * @param option the Option to search for
086         * @return true iff the option is present
087         */
088        public boolean hasOption( Option option )
089        {
090            if( option==null )
091            {
092                return false;
093            }
094            else
095            {
096                return m_properties.containsKey( option.getPreferredName() );
097            }
098        }
099    
100        /**
101         * Finds the Option with the specified trigger
102         * 
103         * @param trigger the name of the option to retrieve
104         * @return the Option matching the trigger or null if none exists
105         */
106        public Option getOption( String trigger )
107        {
108            return m_root.findOption( trigger );
109        }
110    
111        /**
112         * Retrieves the Argument values associated with the specified Option
113         * 
114         * @param option the Option associated with the values
115         * @param defaultValues the result to return if no values are found
116         * @return a list of values or defaultValues if none are found
117         */
118        public List getValues( final Option option, final List defaultValues )
119        {
120            final String value = m_properties.getProperty( option.getPreferredName() );
121            
122            if( value==null )
123            {
124                return defaultValues;
125            }
126            else if( m_separator > NUL )
127            {
128                final List values = new ArrayList();
129                final StringTokenizer tokens = new StringTokenizer( value, String.valueOf( m_separator ) );
130                
131                while( tokens.hasMoreTokens() )
132                {
133                    values.add( tokens.nextToken() );
134                }
135                return values;
136            }
137            else
138            {
139                return Collections.singletonList( value );
140            }
141        }
142    
143        /**
144         * Retrieves the Boolean value associated with the specified Switch
145         * 
146         * @param option the Option associated with the value
147         * @param defaultValue the Boolean to use if none match
148         * @return the Boolean associated with option or defaultValue if none exists
149         */
150        public Boolean getSwitch( final Option option, final Boolean defaultValue ) 
151        {
152            final String value = m_properties.getProperty( option.getPreferredName() );
153            if( "true".equals( value ) )
154            {
155                return Boolean.TRUE;
156            }
157            else if( "false".equals( value ) )
158            {
159                return Boolean.FALSE;
160            }
161            else
162            {
163                return defaultValue;
164            }
165        }
166        
167        /**
168         * Retrieves the value associated with the specified property 
169         * 
170         * @param property the property name to lookup
171         * @param defaultValue the value to use if no other is found
172         * @return the value of the property or defaultValue
173         */
174        public String getProperty( final String property, final String defaultValue )
175        {
176            return m_properties.getProperty( property, defaultValue );
177        }
178    
179        /**
180         * Retrieves the set of all property names associated with this CommandLine
181         * 
182         * @return a none null set of property names 
183         */
184        public Set getProperties()
185        {
186            return m_properties.keySet();
187        }
188    
189        /**
190         * Retrieves a list of all Options found in this CommandLine
191         * 
192         * @return a none null list of Options
193         */
194        public List getOptions()
195        {
196            final List options = new ArrayList();
197            final Iterator keys = m_properties.keySet().iterator();
198            while( keys.hasNext() )
199            {
200                final String trigger = (String) keys.next();
201                final Option option = m_root.findOption( trigger );
202                if( option!=null )
203                {
204                    options.add( option );
205                }
206            }
207            return Collections.unmodifiableList( options );
208        }
209    
210        /**
211         * Retrieves a list of all Option triggers found in this CommandLine
212         * 
213         * @return a none null list of Option triggers
214         */
215        public Set getOptionTriggers()
216        {
217            final Set triggers = new HashSet();
218            final Iterator options = getOptions().iterator();
219            while( options.hasNext() ) 
220            {
221                final Option option = (Option) options.next();
222                triggers.addAll( option.getTriggers() );
223            }
224            return Collections.unmodifiableSet( triggers );
225        }
226    }