OptionTemplate.java revision 1354:a5e202d6eb99
1/* 2 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26package jdk.nashorn.internal.runtime.options; 27 28import java.util.Locale; 29import java.util.TimeZone; 30import jdk.nashorn.internal.runtime.QuotedStringTokenizer; 31 32/** 33 * This describes the valid input for an option, as read from the resource 34 * bundle file. Metainfo such as parameters and description is here as well 35 * for context sensitive help generation. 36 */ 37public final class OptionTemplate implements Comparable<OptionTemplate> { 38 /** Resource, e.g. "nashorn" for this option */ 39 private final String resource; 40 41 /** Key in the resource bundle */ 42 private final String key; 43 44 /** Is this option a help option? */ 45 private final boolean isHelp; 46 47 /** Is this option a extended help option? */ 48 private final boolean isXHelp; 49 50 /** Name - for example --dump-on-error (usually prefixed with --) */ 51 private String name; 52 53 /** Short name - for example -doe (usually prefixed with -) */ 54 private String shortName; 55 56 /** Params - a parameter template string */ 57 private String params; 58 59 /** Type - e.g. "boolean". */ 60 private String type; 61 62 /** Does this option have a default value? */ 63 private String defaultValue; 64 65 /** Does this option activate another option when set? */ 66 private String dependency; 67 68 /** Does this option conflict with another? */ 69 private String conflict; 70 71 /** Is this a documented option that should show up in help? */ 72 private boolean isUndocumented; 73 74 /** A longer description of what this option does */ 75 private String description; 76 77 /** is the option value specified as next argument? */ 78 private boolean valueNextArg; 79 80 OptionTemplate(final String resource, final String key, final String value, final boolean isHelp, final boolean isXHelp) { 81 this.resource = resource; 82 this.key = key; 83 this.isHelp = isHelp; 84 this.isXHelp = isXHelp; 85 parse(value); 86 } 87 88 /** 89 * Is this the special help option, used to generate help for 90 * all the others 91 * 92 * @return true if this is the help option 93 */ 94 public boolean isHelp() { 95 return this.isHelp; 96 } 97 98 /** 99 * Is this the special extended help option, used to generate extended help for 100 * all the others 101 * 102 * @return true if this is the extended help option 103 */ 104 public boolean isXHelp() { 105 return this.isXHelp; 106 } 107 108 /** 109 * Get the resource name used to prefix this option set, e.g. "nashorn" 110 * 111 * @return the name of the resource 112 */ 113 public String getResource() { 114 return this.resource; 115 } 116 117 /** 118 * Get the type of this option 119 * 120 * @return the type of the option 121 */ 122 public String getType() { 123 return this.type; 124 } 125 126 /** 127 * Get the key of this option 128 * 129 * @return the key 130 */ 131 public String getKey() { 132 return this.key; 133 } 134 135 /** 136 * Get the default value for this option 137 * 138 * @return the default value as a string 139 */ 140 public String getDefaultValue() { 141 switch (getType()) { 142 case "boolean": 143 if (this.defaultValue == null) { 144 this.defaultValue = "false"; 145 } 146 break; 147 case "integer": 148 if (this.defaultValue == null) { 149 this.defaultValue = "0"; 150 } 151 break; 152 case "timezone": 153 this.defaultValue = TimeZone.getDefault().getID(); 154 break; 155 case "locale": 156 this.defaultValue = Locale.getDefault().toLanguageTag(); 157 break; 158 default: 159 break; 160 } 161 return this.defaultValue; 162 } 163 164 /** 165 * Does this option automatically enable another option, i.e. a dependency. 166 * @return the dependency or null if none exists 167 */ 168 public String getDependency() { 169 return this.dependency; 170 } 171 172 /** 173 * Is this option in conflict with another option so that both can't be enabled 174 * at the same time 175 * 176 * @return the conflicting option or null if none exists 177 */ 178 public String getConflict() { 179 return this.conflict; 180 } 181 182 /** 183 * Is this option undocumented, i.e. should not show up in the standard help output 184 * 185 * @return true if option is undocumented 186 */ 187 public boolean isUndocumented() { 188 return this.isUndocumented; 189 } 190 191 /** 192 * Get the short version of this option name if one exists, e.g. "-co" for "--compile-only" 193 * 194 * @return the short name 195 */ 196 public String getShortName() { 197 return this.shortName; 198 } 199 200 /** 201 * Get the name of this option, e.g. "--compile-only". A name always exists 202 * 203 * @return the name of the option 204 */ 205 public String getName() { 206 return this.name; 207 } 208 209 /** 210 * Get the description of this option. 211 * 212 * @return the description 213 */ 214 public String getDescription() { 215 return this.description; 216 } 217 218 /** 219 * Is value of this option passed as next argument? 220 * @return boolean 221 */ 222 public boolean isValueNextArg() { 223 return valueNextArg; 224 } 225 226 private static String strip(final String value, final char start, final char end) { 227 final int len = value.length(); 228 if (len > 1 && value.charAt(0) == start && value.charAt(len - 1) == end) { 229 return value.substring(1, len - 1); 230 } 231 return null; 232 } 233 234 private void parse(final String origValue) { 235 String value = origValue.trim(); 236 237 try { 238 value = OptionTemplate.strip(value, '{', '}'); 239 final QuotedStringTokenizer keyValuePairs = new QuotedStringTokenizer(value, ","); 240 241 while (keyValuePairs.hasMoreTokens()) { 242 final String keyValue = keyValuePairs.nextToken(); 243 final QuotedStringTokenizer st = new QuotedStringTokenizer(keyValue, "="); 244 final String keyToken = st.nextToken(); 245 final String arg = st.nextToken(); 246 247 switch (keyToken) { 248 case "is_undocumented": 249 this.isUndocumented = Boolean.parseBoolean(arg); 250 break; 251 case "name": 252 if (!arg.startsWith("-")) { 253 throw new IllegalArgumentException(arg); 254 } 255 this.name = arg; 256 break; 257 case "short_name": 258 if (!arg.startsWith("-")) { 259 throw new IllegalArgumentException(arg); 260 } 261 this.shortName = arg; 262 break; 263 case "desc": 264 this.description = arg; 265 break; 266 case "params": 267 this.params = arg; 268 break; 269 case "type": 270 this.type = arg.toLowerCase(Locale.ENGLISH); 271 break; 272 case "default": 273 this.defaultValue = arg; 274 break; 275 case "dependency": 276 this.dependency = arg; 277 break; 278 case "conflict": 279 this.conflict = arg; 280 break; 281 case "value_next_arg": 282 this.valueNextArg = Boolean.parseBoolean(arg); 283 break; 284 default: 285 throw new IllegalArgumentException(keyToken); 286 } 287 } 288 289 // default to boolean if no type is given 290 if (this.type == null) { 291 this.type = "boolean"; 292 } 293 294 if (this.params == null && "boolean".equals(this.type)) { 295 this.params = "[true|false]"; 296 } 297 298 } catch (final Exception e) { 299 throw new IllegalArgumentException(origValue); 300 } 301 302 if (name == null && shortName == null) { 303 throw new IllegalArgumentException(origValue); 304 } 305 } 306 307 boolean matches(final String key0) { 308 return key0.equals(this.shortName) || key0.equals(this.name); 309 } 310 311 private static final int LINE_BREAK = 64; 312 313 @Override 314 public String toString() { 315 final StringBuilder sb = new StringBuilder(); 316 317 sb.append('\t'); 318 319 if (shortName != null) { 320 sb.append(shortName); 321 if (name != null) { 322 sb.append(", "); 323 } 324 } 325 326 if (name != null) { 327 sb.append(name); 328 } 329 330 if (description != null) { 331 final int indent = sb.length(); 332 sb.append(' '); 333 sb.append('('); 334 int pos = 0; 335 for (final char c : description.toCharArray()) { 336 sb.append(c); 337 pos++; 338 if (pos >= LINE_BREAK && Character.isWhitespace(c)) { 339 pos = 0; 340 sb.append("\n\t"); 341 for (int i = 0; i < indent; i++) { 342 sb.append(' '); 343 } 344 } 345 } 346 sb.append(')'); 347 } 348 349 if (params != null) { 350 sb.append('\n'); 351 sb.append('\t'); 352 sb.append('\t'); 353 sb.append(Options.getMsg("nashorn.options.param")).append(": "); 354 sb.append(params); 355 sb.append(" "); 356 final Object def = this.getDefaultValue(); 357 if (def != null) { 358 sb.append(Options.getMsg("nashorn.options.default")).append(": "); 359 sb.append(this.getDefaultValue()); 360 } 361 } 362 363 364 return sb.toString(); 365 } 366 367 @Override 368 public int compareTo(final OptionTemplate o) { 369 return this.getKey().compareTo(o.getKey()); 370 } 371} 372