View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *     http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.cli2.commandline;
18  
19  import java.util.ArrayList;
20  import java.util.Collections;
21  import java.util.HashMap;
22  import java.util.Iterator;
23  import java.util.List;
24  import java.util.Map;
25  import java.util.Properties;
26  import java.util.Set;
27  
28  import org.apache.commons.cli2.Argument;
29  import org.apache.commons.cli2.Option;
30  import org.apache.commons.cli2.WriteableCommandLine;
31  import org.apache.commons.cli2.option.PropertyOption;
32  import org.apache.commons.cli2.resource.ResourceConstants;
33  import org.apache.commons.cli2.resource.ResourceHelper;
34  
35  /**
36   * A WriteableCommandLine implementation allowing Options to write their
37   * processed information to a CommandLine.
38   */
39  public class WriteableCommandLineImpl
40      extends CommandLineImpl implements WriteableCommandLine {
41      private final Map optionToProperties = new HashMap();
42  //    private final Properties properties = new Properties();
43      private final List options = new ArrayList();
44      private final Map nameToOption = new HashMap();
45      private final Map values = new HashMap();
46      private final Map switches = new HashMap();
47      private final Map defaultValues = new HashMap();
48      private final Map defaultSwitches = new HashMap();
49      private final List normalised;
50      private final Set prefixes;
51      private Option currentOption;
52      private String checkForOption;
53  
54      /**
55       * Creates a new WriteableCommandLineImpl rooted on the specified Option, to
56       * hold the parsed arguments.
57       *
58       * @param rootOption the CommandLine's root Option
59       * @param arguments the arguments this CommandLine represents
60       */
61      public WriteableCommandLineImpl(final Option rootOption,
62                                      final List arguments) {
63          this.prefixes = rootOption.getPrefixes();
64          this.normalised = arguments;
65          setCurrentOption(rootOption);
66      }
67  
68      public Option getCurrentOption() {
69          return currentOption;
70      }
71  
72      public void setCurrentOption(Option currentOption) {
73          this.currentOption = currentOption;
74      }
75  
76      public void addOption(Option option) {
77          options.add(option);
78          nameToOption.put(option.getPreferredName(), option);
79  
80          for (Iterator i = option.getTriggers().iterator(); i.hasNext();) {
81              nameToOption.put(i.next(), option);
82          }
83  
84          // ensure that all parent options are also added
85          Option parent = option.getParent();
86          while (parent != null && !options.contains(parent)) {
87              options.add(parent);
88              parent = parent.getParent();
89          }
90      }
91  
92      public void addValue(final Option option,
93                           final Object value) {
94          if (option instanceof Argument) {
95              addOption(option);
96          }
97  
98          List valueList = (List) values.get(option);
99  
100         if (valueList == null) {
101             valueList = new ArrayList();
102             values.put(option, valueList);
103         }
104 
105         valueList.add(value);
106     }
107 
108     public void addSwitch(final Option option,
109                           final boolean value) {
110         addOption(option);
111 
112         if (switches.containsKey(option)) {
113             throw new IllegalStateException(ResourceHelper.getResourceHelper().getMessage(ResourceConstants.SWITCH_ALREADY_SET));
114         } else {
115             switches.put(option, value ? Boolean.TRUE : Boolean.FALSE);
116         }
117     }
118 
119     public boolean hasOption(final Option option) {
120         final boolean present = options.contains(option);
121 
122         return present;
123     }
124 
125     public Option getOption(final String trigger) {
126         return (Option) nameToOption.get(trigger);
127     }
128 
129     public List getValues(final Option option,
130                           List defaultValues) {
131         // initialize the return list
132         List valueList = (List) values.get(option);
133 
134         // grab the correct default values
135         if (defaultValues == null || defaultValues.isEmpty()) {
136             defaultValues = (List) this.defaultValues.get(option);
137         }
138 
139         // augment the list with the default values
140         if (defaultValues != null && !defaultValues.isEmpty()) {
141             if (valueList == null || valueList.isEmpty()) {
142                 valueList = defaultValues;
143             } else {
144                 // if there are more default values as specified, add them to
145                 // the list.
146                 if (defaultValues.size() > valueList.size()) {
147                     // copy the list first
148                     valueList = new ArrayList(valueList);
149                     for (int i=valueList.size(); i<defaultValues.size(); i++) {
150                         valueList.add(defaultValues.get(i));
151                     }
152                 }
153             }
154         }
155 
156         return valueList == null ? Collections.EMPTY_LIST : valueList;
157     }
158 
159     public List getUndefaultedValues(Option option) {
160       // First grab the command line values
161       List valueList = (List) values.get(option);
162 
163       // Finally use an empty list
164       if (valueList == null) {
165         valueList = Collections.EMPTY_LIST;
166       }
167 
168       return valueList;
169     }
170 
171     public Boolean getSwitch(final Option option,
172                              final Boolean defaultValue) {
173         // First grab the command line values
174         Boolean bool = (Boolean) switches.get(option);
175 
176         // Secondly try the defaults supplied to the method
177         if (bool == null) {
178             bool = defaultValue;
179         }
180 
181         // Thirdly try the option's default values
182         if (bool == null) {
183             bool = (Boolean) this.defaultSwitches.get(option);
184         }
185 
186         return bool;
187     }
188 
189     public String getProperty(final String property) {
190         return getProperty(new PropertyOption(), property);
191     }
192 
193     public void addProperty(final Option option,
194                             final String property,
195                             final String value) {
196         Properties properties = (Properties) optionToProperties.get(option);
197         if (properties == null) {
198             properties = new Properties();
199             optionToProperties.put(option, properties);
200         }
201         properties.setProperty(property, value);
202     }
203 
204     public void addProperty(final String property, final String value) {
205         addProperty(new PropertyOption(), property, value);
206     }
207 
208     public String getProperty(final Option option,
209                               final String property,
210                               final String defaultValue) {
211         Properties properties = (Properties) optionToProperties.get(option);
212         if (properties == null) {
213             return defaultValue;
214         }
215         return properties.getProperty(property, defaultValue);
216     }
217 
218     public Set getProperties(final Option option) {
219         Properties properties = (Properties) optionToProperties.get(option);
220         if (properties == null) {
221             return Collections.EMPTY_SET;
222         }
223         return Collections.unmodifiableSet(properties.keySet());
224     }
225 
226     public Set getProperties() {
227         return getProperties(new PropertyOption());
228     }
229 
230     /**
231      * Tests whether the passed in trigger looks like an option. This
232      * implementation first checks whether the passed in string starts with a
233      * prefix that indicates an option. If this is the case, it is also checked
234      * whether an option of this name is known for the current option. (This can
235      * lead to reentrant invocations of this method, so care has to be taken
236      * about this.)
237      *
238      * @param trigger the command line element to test
239      * @return a flag whether this element seems to be an option
240      */
241     public boolean looksLikeOption(final String trigger)
242     {
243         if (checkForOption != null)
244         {
245             // this is a reentrant call
246             return !checkForOption.equals(trigger);
247         }
248 
249         checkForOption = trigger;
250         try
251         {
252             for (final Iterator i = prefixes.iterator(); i.hasNext();)
253             {
254                 final String prefix = (String) i.next();
255 
256                 if (trigger.startsWith(prefix))
257                 {
258                     if (getCurrentOption().canProcess(this, trigger)
259                             || getCurrentOption().findOption(trigger) != null)
260                     {
261                         return true;
262                     }
263                 }
264             }
265 
266             return false;
267         }
268         finally
269         {
270             checkForOption = null;
271         }
272     }
273 
274     public String toString() {
275         final StringBuffer buffer = new StringBuffer();
276 
277         // need to add group header
278         for (final Iterator i = normalised.iterator(); i.hasNext();) {
279             final String arg = (String) i.next();
280 
281             if (arg.indexOf(' ') >= 0) {
282                 buffer.append("\"").append(arg).append("\"");
283             } else {
284                 buffer.append(arg);
285             }
286 
287             if (i.hasNext()) {
288                 buffer.append(' ');
289             }
290         }
291 
292         return buffer.toString();
293     }
294 
295     public List getOptions() {
296         return Collections.unmodifiableList(options);
297     }
298 
299     public Set getOptionTriggers() {
300         return Collections.unmodifiableSet(nameToOption.keySet());
301     }
302 
303     public void setDefaultValues(final Option option,
304                                  final List defaults) {
305         if (defaults == null) {
306             defaultValues.remove(option);
307         } else {
308             defaultValues.put(option, defaults);
309         }
310     }
311 
312     public void setDefaultSwitch(final Option option,
313                                  final Boolean defaultSwitch) {
314         if (defaultSwitch == null) {
315             defaultSwitches.remove(option);
316         } else {
317             defaultSwitches.put(option, defaultSwitch);
318         }
319     }
320 
321     public List getNormalised() {
322         return Collections.unmodifiableList(normalised);
323     }
324 }