001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. 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 */ 017package org.apache.commons.cli2.option; 018 019import java.util.ArrayList; 020import java.util.Collections; 021import java.util.Comparator; 022import java.util.HashSet; 023import java.util.Iterator; 024import java.util.List; 025import java.util.ListIterator; 026import java.util.Set; 027 028import org.apache.commons.cli2.Argument; 029import org.apache.commons.cli2.DisplaySetting; 030import org.apache.commons.cli2.Group; 031import org.apache.commons.cli2.OptionException; 032import org.apache.commons.cli2.WriteableCommandLine; 033import org.apache.commons.cli2.resource.ResourceConstants; 034import org.apache.commons.cli2.resource.ResourceHelper; 035 036/** 037 * A Parent implementation representing normal switch options. 038 * For example: <code>+d|-d</code> or <code>--enable-x|--disable-x</code>. 039 */ 040public class Switch 041 extends ParentImpl { 042 /** i18n */ 043 public static final ResourceHelper resources = ResourceHelper.getResourceHelper(); 044 045 /** 046 * The default prefix for enabled switches 047 */ 048 public static final String DEFAULT_ENABLED_PREFIX = "+"; 049 050 /** 051 * The default prefix for disabled switches 052 */ 053 public static final String DEFAULT_DISABLED_PREFIX = "-"; 054 private final String enabledPrefix; 055 private final String disabledPrefix; 056 private final Set triggers; 057 private final String preferredName; 058 private final Set aliases; 059 private final Set prefixes; 060 private final Boolean defaultSwitch; 061 062 /** 063 * Creates a new Switch with the specified parameters 064 * @param enabledPrefix the prefix used for enabled switches 065 * @param disabledPrefix the prefix used for disabled switches 066 * @param preferredName the preferred name of the switch 067 * @param aliases the aliases by which the Switch is known 068 * @param description a description of the Switch 069 * @param required whether the Option is strictly required 070 * @param argument the Argument belonging to this Parent, or null 071 * @param children the Group children belonging to this Parent, ot null 072 * @param id the unique identifier for this Option 073 * @throws IllegalArgumentException if the preferredName or an alias isn't 074 * prefixed with enabledPrefix or disabledPrefix 075 */ 076 public Switch(final String enabledPrefix, 077 final String disabledPrefix, 078 final String preferredName, 079 final Set aliases, 080 final String description, 081 final boolean required, 082 final Argument argument, 083 final Group children, 084 final int id, 085 final Boolean switchDefault) { 086 super(argument, children, description, id, required); 087 088 if (enabledPrefix == null) { 089 throw new IllegalArgumentException(resources.getMessage(ResourceConstants.SWITCH_NO_ENABLED_PREFIX)); 090 } 091 092 if (disabledPrefix == null) { 093 throw new IllegalArgumentException(resources.getMessage(ResourceConstants.SWITCH_NO_DISABLED_PREFIX)); 094 } 095 096 if (enabledPrefix.startsWith(disabledPrefix)) { 097 throw new IllegalArgumentException(resources.getMessage(ResourceConstants.SWITCH_ENABLED_STARTS_WITH_DISABLED)); 098 } 099 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}