Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/jdk.internal.opt/share/classes/jdk/internal/joptsimple/OptionSet.java
40948 views
1
/*
2
* Copyright (c) 2009, 2015, 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
/*
27
* This file is available under and governed by the GNU General Public
28
* License version 2 only, as published by the Free Software Foundation.
29
* However, the following notice accompanied the original version of this
30
* file:
31
*
32
* The MIT License
33
*
34
* Copyright (c) 2004-2015 Paul R. Holser, Jr.
35
*
36
* Permission is hereby granted, free of charge, to any person obtaining
37
* a copy of this software and associated documentation files (the
38
* "Software"), to deal in the Software without restriction, including
39
* without limitation the rights to use, copy, modify, merge, publish,
40
* distribute, sublicense, and/or sell copies of the Software, and to
41
* permit persons to whom the Software is furnished to do so, subject to
42
* the following conditions:
43
*
44
* The above copyright notice and this permission notice shall be
45
* included in all copies or substantial portions of the Software.
46
*
47
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
48
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
49
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
50
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
51
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
52
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
53
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
54
*/
55
56
package jdk.internal.joptsimple;
57
58
import java.util.ArrayList;
59
import java.util.HashMap;
60
import java.util.IdentityHashMap;
61
import java.util.List;
62
import java.util.Map;
63
64
import static java.util.Collections.*;
65
import static java.util.Objects.*;
66
67
/**
68
* Representation of a group of detected command line options, their arguments, and non-option arguments.
69
*
70
* @author <a href="mailto:[email protected]">Paul Holser</a>
71
*/
72
public class OptionSet {
73
private final List<OptionSpec<?>> detectedSpecs;
74
private final Map<String, AbstractOptionSpec<?>> detectedOptions;
75
private final Map<AbstractOptionSpec<?>, List<String>> optionsToArguments;
76
private final Map<String, AbstractOptionSpec<?>> recognizedSpecs;
77
private final Map<String, List<?>> defaultValues;
78
79
/*
80
* Package-private because clients don't create these.
81
*/
82
OptionSet( Map<String, AbstractOptionSpec<?>> recognizedSpecs ) {
83
detectedSpecs = new ArrayList<>();
84
detectedOptions = new HashMap<>();
85
optionsToArguments = new IdentityHashMap<>();
86
defaultValues = defaultValues( recognizedSpecs );
87
this.recognizedSpecs = recognizedSpecs;
88
}
89
90
/**
91
* Tells whether any options were detected.
92
*
93
* @return {@code true} if any options were detected
94
*/
95
public boolean hasOptions() {
96
return !( detectedOptions.size() == 1 && detectedOptions.values().iterator().next().representsNonOptions() );
97
}
98
99
/**
100
* Tells whether the given option was detected.
101
*
102
* @param option the option to search for
103
* @return {@code true} if the option was detected
104
* @see #has(OptionSpec)
105
*/
106
public boolean has( String option ) {
107
return detectedOptions.containsKey( option );
108
}
109
110
/**
111
* Tells whether the given option was detected.
112
*
113
* <p>This method recognizes only instances of options returned from the fluent interface methods.</p>
114
*
115
* <p>Specifying a {@linkplain ArgumentAcceptingOptionSpec#defaultsTo(Object, Object[])} default argument value}
116
* for an option does not cause this method to return {@code true} if the option was not detected on the command
117
* line.</p>
118
*
119
* @param option the option to search for
120
* @return {@code true} if the option was detected
121
* @see #has(String)
122
*/
123
public boolean has( OptionSpec<?> option ) {
124
return optionsToArguments.containsKey( option );
125
}
126
127
/**
128
* Tells whether there are any arguments associated with the given option.
129
*
130
* @param option the option to search for
131
* @return {@code true} if the option was detected and at least one argument was detected for the option
132
* @see #hasArgument(OptionSpec)
133
*/
134
public boolean hasArgument( String option ) {
135
AbstractOptionSpec<?> spec = detectedOptions.get( option );
136
return spec != null && hasArgument( spec );
137
}
138
139
/**
140
* Tells whether there are any arguments associated with the given option.
141
*
142
* <p>This method recognizes only instances of options returned from the fluent interface methods.</p>
143
*
144
* <p>Specifying a {@linkplain ArgumentAcceptingOptionSpec#defaultsTo(Object, Object[]) default argument value}
145
* for an option does not cause this method to return {@code true} if the option was not detected on the command
146
* line, or if the option can take an optional argument but did not have one on the command line.</p>
147
*
148
* @param option the option to search for
149
* @return {@code true} if the option was detected and at least one argument was detected for the option
150
* @throws NullPointerException if {@code option} is {@code null}
151
* @see #hasArgument(String)
152
*/
153
public boolean hasArgument( OptionSpec<?> option ) {
154
requireNonNull( option );
155
156
List<String> values = optionsToArguments.get( option );
157
return values != null && !values.isEmpty();
158
}
159
160
/**
161
* Gives the argument associated with the given option. If the option was given an argument type, the argument
162
* will take on that type; otherwise, it will be a {@link String}.
163
*
164
* <p>Specifying a {@linkplain ArgumentAcceptingOptionSpec#defaultsTo(Object, Object[]) default argument value}
165
* for an option will cause this method to return that default value even if the option was not detected on the
166
* command line, or if the option can take an optional argument but did not have one on the command line.</p>
167
*
168
* @param option the option to search for
169
* @return the argument of the given option; {@code null} if no argument is present, or that option was not
170
* detected
171
* @throws NullPointerException if {@code option} is {@code null}
172
* @throws OptionException if more than one argument was detected for the option
173
*/
174
public Object valueOf( String option ) {
175
requireNonNull( option );
176
177
AbstractOptionSpec<?> spec = detectedOptions.get( option );
178
if ( spec == null ) {
179
List<?> defaults = defaultValuesFor( option );
180
return defaults.isEmpty() ? null : defaults.get( 0 );
181
}
182
183
return valueOf( spec );
184
}
185
186
/**
187
* Gives the argument associated with the given option.
188
*
189
* <p>This method recognizes only instances of options returned from the fluent interface methods.</p>
190
*
191
* @param <V> represents the type of the arguments the given option accepts
192
* @param option the option to search for
193
* @return the argument of the given option; {@code null} if no argument is present, or that option was not
194
* detected
195
* @throws OptionException if more than one argument was detected for the option
196
* @throws NullPointerException if {@code option} is {@code null}
197
* @throws ClassCastException if the arguments of this option are not of the expected type
198
*/
199
public <V> V valueOf( OptionSpec<V> option ) {
200
requireNonNull( option );
201
202
List<V> values = valuesOf( option );
203
switch ( values.size() ) {
204
case 0:
205
return null;
206
case 1:
207
return values.get( 0 );
208
default:
209
throw new MultipleArgumentsForOptionException( option );
210
}
211
}
212
213
/**
214
* <p>Gives any arguments associated with the given option. If the option was given an argument type, the
215
* arguments will take on that type; otherwise, they will be {@link String}s.</p>
216
*
217
* @param option the option to search for
218
* @return the arguments associated with the option, as a list of objects of the type given to the arguments; an
219
* empty list if no such arguments are present, or if the option was not detected
220
* @throws NullPointerException if {@code option} is {@code null}
221
*/
222
public List<?> valuesOf( String option ) {
223
requireNonNull( option );
224
225
AbstractOptionSpec<?> spec = detectedOptions.get( option );
226
return spec == null ? defaultValuesFor( option ) : valuesOf( spec );
227
}
228
229
/**
230
* <p>Gives any arguments associated with the given option. If the option was given an argument type, the
231
* arguments will take on that type; otherwise, they will be {@link String}s.</p>
232
*
233
* <p>This method recognizes only instances of options returned from the fluent interface methods.</p>
234
*
235
* @param <V> represents the type of the arguments the given option accepts
236
* @param option the option to search for
237
* @return the arguments associated with the option; an empty list if no such arguments are present, or if the
238
* option was not detected
239
* @throws NullPointerException if {@code option} is {@code null}
240
* @throws OptionException if there is a problem converting the option's arguments to the desired type; for
241
* example, if the type does not implement a correct conversion constructor or method
242
*/
243
public <V> List<V> valuesOf( OptionSpec<V> option ) {
244
requireNonNull( option );
245
246
List<String> values = optionsToArguments.get( option );
247
if ( values == null || values.isEmpty() )
248
return defaultValueFor( option );
249
250
AbstractOptionSpec<V> spec = (AbstractOptionSpec<V>) option;
251
List<V> convertedValues = new ArrayList<>();
252
for ( String each : values )
253
convertedValues.add( spec.convert( each ) );
254
255
return unmodifiableList( convertedValues );
256
}
257
258
/**
259
* Gives the set of options that were detected, in the form of {@linkplain OptionSpec}s, in the order in which the
260
* options were found on the command line.
261
*
262
* @return the set of detected command line options
263
*/
264
public List<OptionSpec<?>> specs() {
265
List<OptionSpec<?>> specs = detectedSpecs;
266
specs.removeAll( singletonList( detectedOptions.get( NonOptionArgumentSpec.NAME ) ) );
267
268
return unmodifiableList( specs );
269
}
270
271
/**
272
* Gives all declared options as a map of string to {@linkplain OptionSpec}.
273
*
274
* @return the declared options as a map
275
*/
276
public Map<OptionSpec<?>, List<?>> asMap() {
277
Map<OptionSpec<?>, List<?>> map = new HashMap<>();
278
279
for ( AbstractOptionSpec<?> spec : recognizedSpecs.values() ) {
280
if ( !spec.representsNonOptions() )
281
map.put( spec, valuesOf( spec ) );
282
}
283
284
return unmodifiableMap( map );
285
}
286
287
/**
288
* @return the detected non-option arguments
289
*/
290
public List<?> nonOptionArguments() {
291
AbstractOptionSpec<?> spec = detectedOptions.get( NonOptionArgumentSpec.NAME );
292
return valuesOf( spec );
293
}
294
295
void add( AbstractOptionSpec<?> spec ) {
296
addWithArgument( spec, null );
297
}
298
299
void addWithArgument( AbstractOptionSpec<?> spec, String argument ) {
300
detectedSpecs.add( spec );
301
302
for ( String each : spec.options() )
303
detectedOptions.put( each, spec );
304
305
List<String> optionArguments = optionsToArguments.get( spec );
306
307
if ( optionArguments == null ) {
308
optionArguments = new ArrayList<>();
309
optionsToArguments.put( spec, optionArguments );
310
}
311
312
if ( argument != null )
313
optionArguments.add( argument );
314
}
315
316
@Override
317
public boolean equals( Object that ) {
318
if ( this == that )
319
return true;
320
321
if ( that == null || !getClass().equals( that.getClass() ) )
322
return false;
323
324
OptionSet other = (OptionSet) that;
325
Map<AbstractOptionSpec<?>, List<String>> thisOptionsToArguments = new HashMap<>( optionsToArguments );
326
Map<AbstractOptionSpec<?>, List<String>> otherOptionsToArguments = new HashMap<>( other.optionsToArguments );
327
return detectedOptions.equals( other.detectedOptions )
328
&& thisOptionsToArguments.equals( otherOptionsToArguments );
329
}
330
331
@Override
332
public int hashCode() {
333
Map<AbstractOptionSpec<?>, List<String>> thisOptionsToArguments = new HashMap<>( optionsToArguments );
334
return detectedOptions.hashCode() ^ thisOptionsToArguments.hashCode();
335
}
336
337
@SuppressWarnings( "unchecked" )
338
private <V> List<V> defaultValuesFor( String option ) {
339
if ( defaultValues.containsKey( option ) )
340
return unmodifiableList( (List<V>) defaultValues.get( option ) );
341
342
return emptyList();
343
}
344
345
private <V> List<V> defaultValueFor( OptionSpec<V> option ) {
346
return defaultValuesFor( option.options().iterator().next() );
347
}
348
349
private static Map<String, List<?>> defaultValues( Map<String, AbstractOptionSpec<?>> recognizedSpecs ) {
350
Map<String, List<?>> defaults = new HashMap<>();
351
for ( Map.Entry<String, AbstractOptionSpec<?>> each : recognizedSpecs.entrySet() )
352
defaults.put( each.getKey(), each.getValue().defaultValues() );
353
return defaults;
354
}
355
}
356
357