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