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