aboutsummaryrefslogtreecommitdiff
path: root/src/org/gnunet/util/getopt/Parser.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/org/gnunet/util/getopt/Parser.java')
-rw-r--r--src/org/gnunet/util/getopt/Parser.java66
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
23import org.gnunet.construct.ReflectUtil; 23import org.gnunet.construct.ReflectUtil;
24import java.lang.reflect.Field; 24import java.lang.reflect.Field;
25import java.lang.reflect.Modifier;
26import java.util.*; 25import 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