diff options
Diffstat (limited to 'src/org/gnunet/util/getopt/Parser.java')
-rw-r--r-- | src/org/gnunet/util/getopt/Parser.java | 66 |
1 files changed, 28 insertions, 38 deletions
diff --git a/src/org/gnunet/util/getopt/Parser.java b/src/org/gnunet/util/getopt/Parser.java index 9807146..6ecc220 100644 --- a/src/org/gnunet/util/getopt/Parser.java +++ b/src/org/gnunet/util/getopt/Parser.java | |||
@@ -22,7 +22,6 @@ package org.gnunet.util.getopt; | |||
22 | 22 | ||
23 | import org.gnunet.construct.ReflectUtil; | 23 | import org.gnunet.construct.ReflectUtil; |
24 | import java.lang.reflect.Field; | 24 | import java.lang.reflect.Field; |
25 | import java.lang.reflect.Modifier; | ||
26 | import java.util.*; | 25 | import java.util.*; |
27 | 26 | ||
28 | /** | 27 | /** |
@@ -45,10 +44,10 @@ public class Parser { | |||
45 | * An option together with its target field. | 44 | * An option together with its target field. |
46 | */ | 45 | */ |
47 | static class OptionField { | 46 | static class OptionField { |
48 | Option opt; | 47 | Argument opt; |
49 | Field f; | 48 | Field f; |
50 | 49 | ||
51 | public OptionField(Option opt, Field f) { | 50 | public OptionField(Argument opt, Field f) { |
52 | this.opt = opt; | 51 | this.opt = opt; |
53 | this.f = f; | 52 | this.f = f; |
54 | } | 53 | } |
@@ -66,7 +65,7 @@ public class Parser { | |||
66 | private Map<String, OptionField> longOpt = new HashMap<String, OptionField>(); | 65 | private Map<String, OptionField> longOpt = new HashMap<String, OptionField>(); |
67 | private Map<String, OptionField> shortOpt = new HashMap<String, OptionField>(); | 66 | private Map<String, OptionField> shortOpt = new HashMap<String, OptionField>(); |
68 | 67 | ||
69 | private Collection<Option> options = new LinkedList<Option>(); | 68 | private Collection<Argument> arguments = new LinkedList<Argument>(); |
70 | 69 | ||
71 | private Object targetObject; | 70 | private Object targetObject; |
72 | 71 | ||
@@ -75,11 +74,7 @@ public class Parser { | |||
75 | this.targetObject = targetObject; | 74 | this.targetObject = targetObject; |
76 | // gather option annotations | 75 | // gather option annotations |
77 | for (Field f : getFields(targetObject.getClass())) { | 76 | for (Field f : getFields(targetObject.getClass())) { |
78 | if (f.isSynthetic() || Modifier.isStatic(f.getModifiers())) { | 77 | Argument opt = f.getAnnotation(Argument.class); |
79 | continue; | ||
80 | } | ||
81 | // todo: validity checking of annotations | ||
82 | Option opt = f.getAnnotation(Option.class); | ||
83 | if (opt != null) { | 78 | if (opt != null) { |
84 | if (opt.shortname().length() != 1) { | 79 | if (opt.shortname().length() != 1) { |
85 | throw new AssertionError("short name must be of length 1"); | 80 | throw new AssertionError("short name must be of length 1"); |
@@ -89,14 +84,14 @@ public class Parser { | |||
89 | 84 | ||
90 | longOpt.put(opt.longname(), new OptionField(opt, f)); | 85 | longOpt.put(opt.longname(), new OptionField(opt, f)); |
91 | shortOpt.put(opt.shortname(), new OptionField(opt, f)); | 86 | shortOpt.put(opt.shortname(), new OptionField(opt, f)); |
92 | options.add(opt); | 87 | arguments.add(opt); |
93 | } | 88 | } |
94 | } | 89 | } |
95 | } | 90 | } |
96 | 91 | ||
97 | public String getHelp() { | 92 | public String getHelp() { |
98 | StringBuilder helpString = new StringBuilder(); | 93 | StringBuilder helpString = new StringBuilder(); |
99 | for (Option opt : options) { | 94 | for (Argument opt : arguments) { |
100 | StringBuilder line = new StringBuilder(); | 95 | StringBuilder line = new StringBuilder(); |
101 | line.append(" -"); | 96 | line.append(" -"); |
102 | line.append(opt.shortname()); | 97 | line.append(opt.shortname()); |
@@ -118,10 +113,10 @@ public class Parser { | |||
118 | return helpString.toString(); | 113 | return helpString.toString(); |
119 | } | 114 | } |
120 | 115 | ||
121 | public void doLongOpt(final LinkedList<String> argsList, Field targetField, Option option, String right) { | 116 | private void doLongOpt(final LinkedList<String> argsList, Field targetField, Argument argument, String right) { |
122 | try { | 117 | try { |
123 | Class targetFieldType = targetField.getType(); | 118 | Class targetFieldType = targetField.getType(); |
124 | switch (option.action()) { | 119 | switch (argument.action()) { |
125 | case SET: | 120 | case SET: |
126 | if (!targetFieldType.equals(Boolean.TYPE)) { | 121 | if (!targetFieldType.equals(Boolean.TYPE)) { |
127 | throw new AssertionError("action SET only valid on boolean member"); | 122 | throw new AssertionError("action SET only valid on boolean member"); |
@@ -141,7 +136,7 @@ public class Parser { | |||
141 | if (right == null) { | 136 | if (right == null) { |
142 | argsList.removeFirst(); | 137 | argsList.removeFirst(); |
143 | if (argsList.isEmpty()) { | 138 | if (argsList.isEmpty()) { |
144 | throw new ArgumentError("missing string argument to option " + option.longname()); | 139 | throw new ArgumentError("missing string argument to option " + argument.longname()); |
145 | } | 140 | } |
146 | targetField.set(targetObject, argsList.getFirst()); | 141 | targetField.set(targetObject, argsList.getFirst()); |
147 | } else { | 142 | } else { |
@@ -154,7 +149,7 @@ public class Parser { | |||
154 | if (right == null) { | 149 | if (right == null) { |
155 | argsList.removeFirst(); | 150 | argsList.removeFirst(); |
156 | if (argsList.isEmpty()) { | 151 | if (argsList.isEmpty()) { |
157 | throw new ArgumentError("missing number argument to option " + option.longname()); | 152 | throw new ArgumentError("missing number argument to option " + argument.longname()); |
158 | } | 153 | } |
159 | numString = argsList.getFirst(); | 154 | numString = argsList.getFirst(); |
160 | } else { | 155 | } else { |
@@ -163,11 +158,9 @@ public class Parser { | |||
163 | try { | 158 | try { |
164 | nf.set(targetObject, Long.parseLong(numString)); | 159 | nf.set(targetObject, Long.parseLong(numString)); |
165 | } catch (NumberFormatException e) { | 160 | } catch (NumberFormatException e) { |
166 | throw new ArgumentError("error in number format to option " + option.longname()); | 161 | throw new ArgumentError("error in number format to option " + argument.longname()); |
167 | } | 162 | } |
168 | break; | 163 | break; |
169 | case INCREMENT: | ||
170 | throw new UnsupportedOperationException("not yet implemented"); | ||
171 | } | 164 | } |
172 | } catch (IllegalAccessException e) { | 165 | } catch (IllegalAccessException e) { |
173 | throw new AssertionError( | 166 | throw new AssertionError( |
@@ -175,9 +168,13 @@ public class Parser { | |||
175 | } | 168 | } |
176 | } | 169 | } |
177 | 170 | ||
178 | public boolean doShortOpt(final LinkedList<String> argsList, Field targetField, Option option, String shortName) { | 171 | /** |
172 | * returns true if we processed a shortopt with a parameter, and thus have to discard the rest | ||
173 | * of the current argument string (that is, stop scanning for more shortopts) | ||
174 | */ | ||
175 | private boolean doShortOpt(final LinkedList<String> argsList, Field targetField, Argument argument, String shortName) { | ||
179 | try { | 176 | try { |
180 | switch (option.action()) { | 177 | switch (argument.action()) { |
181 | case SET: | 178 | case SET: |
182 | if (!targetField.getType().equals(Boolean.TYPE)) { | 179 | if (!targetField.getType().equals(Boolean.TYPE)) { |
183 | throw new AssertionError("action SET only valid on boolean member"); | 180 | throw new AssertionError("action SET only valid on boolean member"); |
@@ -186,16 +183,15 @@ public class Parser { | |||
186 | break; | 183 | break; |
187 | case RESET: | 184 | case RESET: |
188 | if (!targetField.getType().equals(Boolean.TYPE)) { | 185 | if (!targetField.getType().equals(Boolean.TYPE)) { |
189 | throw new AssertionError("action RESET only valid on boolean member"); | 186 | throw new AssertionError("action RESET only valid on boolean field"); |
190 | } | 187 | } |
191 | targetField.set(targetObject, false); | 188 | targetField.set(targetObject, false); |
192 | break; | 189 | break; |
193 | case STORE_STRING: | 190 | case STORE_STRING: |
194 | if (!targetField.getType().equals(String.class)) { | 191 | if (!targetField.getType().equals(String.class)) { |
195 | throw new AssertionError("action STORE_STRING only valid on boolean " + | 192 | throw new AssertionError("action STORE_STRING only valid on 'String' field"); |
196 | "member"); | ||
197 | } | 193 | } |
198 | if (argsList.getFirst().length() == 2) { // -X | 194 | if (argsList.getFirst().length() == 2) { // -P xxx (with space) |
199 | argsList.removeFirst(); | 195 | argsList.removeFirst(); |
200 | if (argsList.isEmpty()) { | 196 | if (argsList.isEmpty()) { |
201 | throw new ArgumentError(String.format("no argument for short option '%s'", | 197 | throw new ArgumentError(String.format("no argument for short option '%s'", |
@@ -205,31 +201,25 @@ public class Parser { | |||
205 | } else { | 201 | } else { |
206 | targetField.set(targetObject, argsList.getFirst().substring(2)); // -Pxxx... | 202 | targetField.set(targetObject, argsList.getFirst().substring(2)); // -Pxxx... |
207 | } | 203 | } |
208 | // consumed entire shortopt | ||
209 | return true; | 204 | return true; |
210 | case STORE_NUMBER: | 205 | case STORE_NUMBER: |
211 | ReflectUtil.NumField nf = new ReflectUtil.NumField(targetField); | 206 | ReflectUtil.NumField nf = new ReflectUtil.NumField(targetField); |
212 | String numString; | 207 | String numString; |
213 | boolean consumed; | ||
214 | if (argsList.getFirst().length() == 2) { // -X | 208 | if (argsList.getFirst().length() == 2) { // -X |
215 | argsList.removeFirst(); | 209 | argsList.removeFirst(); |
216 | if (argsList.isEmpty()) { | 210 | if (argsList.isEmpty()) { |
217 | throw new ArgumentError("missing number argument to option " + option.longname()); | 211 | throw new ArgumentError("missing number argument to option " + argument.longname()); |
218 | } | 212 | } |
219 | numString = argsList.getFirst(); | 213 | numString = argsList.getFirst(); |
220 | consumed = false; | ||
221 | } else { | 214 | } else { |
222 | numString = argsList.getFirst().substring(2); | 215 | numString = argsList.getFirst().substring(2); |
223 | consumed = true; | ||
224 | } | 216 | } |
225 | try { | 217 | try { |
226 | nf.set(targetObject, Long.parseLong(numString)); | 218 | nf.set(targetObject, Long.parseLong(numString)); |
227 | } catch (NumberFormatException e) { | 219 | } catch (NumberFormatException e) { |
228 | throw new ArgumentError("error in number format to option " + option.longname()); | 220 | throw new ArgumentError("error in number format to option " + argument.longname()); |
229 | } | 221 | } |
230 | return consumed; | 222 | return true; |
231 | case INCREMENT: | ||
232 | throw new UnsupportedOperationException("not yet implemented"); | ||
233 | } | 223 | } |
234 | } catch (IllegalAccessException e) { | 224 | } catch (IllegalAccessException e) { |
235 | throw new ArgumentError( | 225 | throw new ArgumentError( |
@@ -238,7 +228,6 @@ public class Parser { | |||
238 | return false; // did not consume entire shortopt -Xxxxxx | 228 | return false; // did not consume entire shortopt -Xxxxxx |
239 | } | 229 | } |
240 | 230 | ||
241 | |||
242 | /** | 231 | /** |
243 | * Parses the given arguments, and sets the target object's fields | 232 | * Parses the given arguments, and sets the target object's fields |
244 | * according to its annotations. | 233 | * according to its annotations. |
@@ -271,7 +260,8 @@ public class Parser { | |||
271 | } | 260 | } |
272 | String right = (components.length == 2) ? components[1] : null; | 261 | String right = (components.length == 2) ? components[1] : null; |
273 | doLongOpt(argsList, of.f, of.opt, right); | 262 | doLongOpt(argsList, of.f, of.opt, right); |
274 | } else if (argsList.getFirst().length() > 1 && argsList.getFirst().startsWith("-")) { | 263 | } else if ((argsList.getFirst().length() > 1) && argsList.getFirst().startsWith("-")) { |
264 | // handle each flag after the "-" | ||
275 | for (int i = 1; i < argsList.getFirst().length(); ++i) { | 265 | for (int i = 1; i < argsList.getFirst().length(); ++i) { |
276 | String optShortName = argsList.getFirst().substring(i, i + 1); | 266 | String optShortName = argsList.getFirst().substring(i, i + 1); |
277 | OptionField of = shortOpt.get(optShortName); | 267 | OptionField of = shortOpt.get(optShortName); |
@@ -280,13 +270,13 @@ public class Parser { | |||
280 | String.format("unknown short option: -%s", argsList.getFirst().charAt(i))); | 270 | String.format("unknown short option: -%s", argsList.getFirst().charAt(i))); |
281 | } | 271 | } |
282 | 272 | ||
283 | boolean consumed = doShortOpt(argsList, of.f, of.opt, optShortName); | 273 | boolean discard = doShortOpt(argsList, of.f, of.opt, optShortName); |
284 | 274 | ||
285 | if (consumed && i != 1) { | 275 | if (discard && (i != 1)) { |
286 | throw new ArgumentError("short options with argument must be seperate"); | 276 | throw new ArgumentError("short options with argument must be seperate"); |
287 | } | 277 | } |
288 | 278 | ||
289 | if (consumed) { | 279 | if (discard) { |
290 | break; | 280 | break; |
291 | } | 281 | } |
292 | 282 | ||