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.option;
18  
19  import java.util.ArrayList;
20  import java.util.Collections;
21  import java.util.Comparator;
22  import java.util.HashSet;
23  import java.util.Iterator;
24  import java.util.List;
25  import java.util.ListIterator;
26  import java.util.Set;
27  
28  import org.apache.commons.cli2.Argument;
29  import org.apache.commons.cli2.DisplaySetting;
30  import org.apache.commons.cli2.Group;
31  import org.apache.commons.cli2.OptionException;
32  import org.apache.commons.cli2.WriteableCommandLine;
33  import org.apache.commons.cli2.resource.ResourceConstants;
34  import org.apache.commons.cli2.resource.ResourceHelper;
35  
36  /**
37   * A Parent implementation representing normal switch options.
38   * For example: <code>+d|-d</code> or <code>--enable-x|--disable-x</code>.
39   */
40  public class Switch
41      extends ParentImpl {
42      /** i18n */
43      public static final ResourceHelper resources = ResourceHelper.getResourceHelper();
44  
45      /**
46       * The default prefix for enabled switches
47       */
48      public static final String DEFAULT_ENABLED_PREFIX = "+";
49  
50      /**
51       * The default prefix for disabled switches
52       */
53      public static final String DEFAULT_DISABLED_PREFIX = "-";
54      private final String enabledPrefix;
55      private final String disabledPrefix;
56      private final Set triggers;
57      private final String preferredName;
58      private final Set aliases;
59      private final Set prefixes;
60      private final Boolean defaultSwitch;
61  
62      /**
63       * Creates a new Switch with the specified parameters
64       * @param enabledPrefix the prefix used for enabled switches
65       * @param disabledPrefix the prefix used for disabled switches
66       * @param preferredName the preferred name of the switch
67       * @param aliases the aliases by which the Switch is known
68       * @param description a description of the Switch
69       * @param required whether the Option is strictly required
70       * @param argument the Argument belonging to this Parent, or null
71       * @param children the Group children belonging to this Parent, ot null
72       * @param id the unique identifier for this Option
73       * @throws IllegalArgumentException if the preferredName or an alias isn't
74       *     prefixed with enabledPrefix or disabledPrefix
75       */
76      public Switch(final String enabledPrefix,
77                    final String disabledPrefix,
78                    final String preferredName,
79                    final Set aliases,
80                    final String description,
81                    final boolean required,
82                    final Argument argument,
83                    final Group children,
84                    final int id,
85                    final Boolean switchDefault) {
86          super(argument, children, description, id, required);
87  
88          if (enabledPrefix == null) {
89              throw new IllegalArgumentException(resources.getMessage(ResourceConstants.SWITCH_NO_ENABLED_PREFIX));
90          }
91  
92          if (disabledPrefix == null) {
93              throw new IllegalArgumentException(resources.getMessage(ResourceConstants.SWITCH_NO_DISABLED_PREFIX));
94          }
95  
96          if (enabledPrefix.startsWith(disabledPrefix)) {
97              throw new IllegalArgumentException(resources.getMessage(ResourceConstants.SWITCH_ENABLED_STARTS_WITH_DISABLED));
98          }
99  
100         if (disabledPrefix.startsWith(enabledPrefix)) {
101             throw new IllegalArgumentException(resources.getMessage(ResourceConstants.SWITCH_DISABLED_STARTWS_WITH_ENABLED));
102         }
103 
104         this.enabledPrefix = enabledPrefix;
105         this.disabledPrefix = disabledPrefix;
106         this.preferredName = preferredName;
107 
108         if ((preferredName == null) || (preferredName.length() < 1)) {
109             throw new IllegalArgumentException(resources.getMessage(ResourceConstants.SWITCH_PREFERRED_NAME_TOO_SHORT));
110         }
111 
112         final Set newTriggers = new HashSet();
113         newTriggers.add(enabledPrefix + preferredName);
114         newTriggers.add(disabledPrefix + preferredName);
115         this.triggers = Collections.unmodifiableSet(newTriggers);
116 
117         if (aliases == null) {
118             this.aliases = Collections.EMPTY_SET;
119         } else {
120             this.aliases = Collections.unmodifiableSet(new HashSet(aliases));
121 
122             for (final Iterator i = aliases.iterator(); i.hasNext();) {
123                 final String alias = (String) i.next();
124                 newTriggers.add(enabledPrefix + alias);
125                 newTriggers.add(disabledPrefix + alias);
126             }
127         }
128 
129         final Set newPrefixes = new HashSet(super.getPrefixes());
130         newPrefixes.add(enabledPrefix);
131         newPrefixes.add(disabledPrefix);
132         this.prefixes = Collections.unmodifiableSet(newPrefixes);
133 
134         this.defaultSwitch = switchDefault;
135 
136         checkPrefixes(newPrefixes);
137     }
138 
139     public void processParent(final WriteableCommandLine commandLine,
140                               final ListIterator arguments)
141         throws OptionException {
142         final String arg = (String) arguments.next();
143 
144         if (canProcess(commandLine, arg)) {
145             if (arg.startsWith(enabledPrefix)) {
146                 commandLine.addSwitch(this, true);
147                 arguments.set(enabledPrefix + preferredName);
148             }
149 
150             if (arg.startsWith(disabledPrefix)) {
151                 commandLine.addSwitch(this, false);
152                 arguments.set(disabledPrefix + preferredName);
153             }
154         } else {
155             throw new OptionException(this, ResourceConstants.UNEXPECTED_TOKEN, arg);
156         }
157     }
158 
159     public Set getTriggers() {
160         return triggers;
161     }
162 
163     public Set getPrefixes() {
164         return prefixes;
165     }
166 
167     public void validate(WriteableCommandLine commandLine)
168         throws OptionException {
169         if (isRequired() && !commandLine.hasOption(this)) {
170             throw new OptionException(this, ResourceConstants.OPTION_MISSING_REQUIRED,
171                                       getPreferredName());
172         }
173 
174         super.validate(commandLine);
175     }
176 
177     public void appendUsage(final StringBuffer buffer,
178                             final Set helpSettings,
179                             final Comparator comp) {
180         // do we display optionality
181         final boolean optional =
182             !isRequired() && helpSettings.contains(DisplaySetting.DISPLAY_OPTIONAL);
183         final boolean displayAliases = helpSettings.contains(DisplaySetting.DISPLAY_ALIASES);
184         final boolean disabled = helpSettings.contains(DisplaySetting.DISPLAY_SWITCH_DISABLED);
185         final boolean enabled =
186             !disabled || helpSettings.contains(DisplaySetting.DISPLAY_SWITCH_ENABLED);
187         final boolean both = disabled && enabled;
188 
189         if (optional) {
190             buffer.append('[');
191         }
192 
193         if (enabled) {
194             buffer.append(enabledPrefix).append(preferredName);
195         }
196 
197         if (both) {
198             buffer.append('|');
199         }
200 
201         if (disabled) {
202             buffer.append(disabledPrefix).append(preferredName);
203         }
204 
205         if (displayAliases && !aliases.isEmpty()) {
206             buffer.append(" (");
207 
208             final List list = new ArrayList(aliases);
209             Collections.sort(list);
210 
211             for (final Iterator i = list.iterator(); i.hasNext();) {
212                 final String alias = (String) i.next();
213 
214                 if (enabled) {
215                     buffer.append(enabledPrefix).append(alias);
216                 }
217 
218                 if (both) {
219                     buffer.append('|');
220                 }
221 
222                 if (disabled) {
223                     buffer.append(disabledPrefix).append(alias);
224                 }
225 
226                 if (i.hasNext()) {
227                     buffer.append(',');
228                 }
229             }
230 
231             buffer.append(')');
232         }
233 
234         super.appendUsage(buffer, helpSettings, comp);
235 
236         if (optional) {
237             buffer.append(']');
238         }
239     }
240 
241     public String getPreferredName() {
242         return enabledPrefix + preferredName;
243     }
244 
245     public void defaults(final WriteableCommandLine commandLine) {
246         commandLine.setDefaultSwitch(this, defaultSwitch);
247     }
248 }