diff --git a/src/main/java/chapter14/args/Args.java b/src/main/java/chapter14/args/Args.java index 1f4429a..0e79af4 100644 --- a/src/main/java/chapter14/args/Args.java +++ b/src/main/java/chapter14/args/Args.java @@ -8,9 +8,7 @@ public class Args { private String[] args; private boolean valid = true; private Set unexpectedArguments = new TreeSet<>(); - private Map booleanArgs = new HashMap<>(); - private Map stringArgs = new HashMap<>(); - private Map intArgs = new HashMap<>(); + private Map marshalers = new HashMap<>(); private Set argsFound = new HashSet<>(); private int currentArgument; private char errorArgumentId = '\0'; @@ -52,13 +50,13 @@ private void parseSchemaElement(String element) throws ParseException { char elementId = element.charAt(0); String elementTail = element.substring(1); validateSchemaElementId(elementId); - if (isBooleanSchemaElement(elementTail)) - parseBooleanSchemaElement(elementId); - else if (isStringSchemaElement(elementTail)) - parseStringSchemaElement(elementId); - else if (isIntegerSchemaElement(elementTail)) - parseIntegerSchemaElement(elementId); - else { + if (isBooleanSchemaElement(elementTail)) { + marshalers.put(elementId, new BooleanArgumentMarshaler()); + } else if (isStringSchemaElement(elementTail)) { + marshalers.put(elementId, new StringArgumentMarshaler()); + } else if (isIntegerSchemaElement(elementTail)) { + marshalers.put(elementId, new IntegerArgumentMarshaler()); + } else { throw new ParseException( String.format("Argument: %c has invalid format: %s.", elementId, elementTail), 0); @@ -72,18 +70,6 @@ private void validateSchemaElementId(char elementId) throws ParseException { } } - private void parseBooleanSchemaElement(char elementId) { - booleanArgs.put(elementId, false); - } - - private void parseIntegerSchemaElement(char elementId) { - intArgs.put(elementId, 0); - } - - private void parseStringSchemaElement(char elementId) { - stringArgs.put(elementId, ""); - } - private boolean isStringSchemaElement(String elementTail) { return elementTail.equals("*"); } @@ -126,63 +112,55 @@ private void parseElement(char argChar) throws ArgsException { } private boolean setArgument(char argChar) throws ArgsException { - if (isBooleanArg(argChar)) - setBooleanArg(argChar, true); - else if (isStringArg(argChar)) - setStringArg(argChar); - else if (isIntArg(argChar)) - setIntArg(argChar); - else - return false; - + ArgumentMarshaler m = marshalers.get(argChar); + try { + if (m instanceof BooleanArgumentMarshaler) + setBooleanArg(m); + else if (m instanceof StringArgumentMarshaler) + setStringArg(m); + else if (m instanceof IntegerArgumentMarshaler) + setIntArg(m); + else + return false; + } catch (ArgsException e) { + valid = false; + errorArgumentId = argChar; + throw e; + } return true; } - private boolean isIntArg(char argChar) { - return intArgs.containsKey(argChar); - } - - private void setIntArg(char argChar) throws ArgsException { + private void setIntArg(ArgumentMarshaler m) throws ArgsException { currentArgument++; String parameter = null; try { parameter = args[currentArgument]; - intArgs.put(argChar, new Integer(parameter)); + m.set(parameter); } catch (ArrayIndexOutOfBoundsException e) { - valid = false; - errorArgumentId = argChar; errorCode = ErrorCode.MISSING_INTEGER; throw new ArgsException(); - } catch (NumberFormatException e) { - valid = false; - errorArgumentId = argChar; + } catch (ArgsException e) { errorParameter = parameter; errorCode = ErrorCode.INVALID_INTEGER; - throw new ArgsException(); + throw e; } } - private void setStringArg(char argChar) { + private void setStringArg(ArgumentMarshaler m) throws ArgsException { currentArgument++; try { - stringArgs.put(argChar, args[currentArgument]); + m.set(args[currentArgument]); } catch (ArrayIndexOutOfBoundsException e) { - valid = false; - errorArgumentId = argChar; errorCode = ErrorCode.MISSING_STRING; + throw new ArgsException(); } } - private boolean isStringArg(char argChar) { - return stringArgs.containsKey(argChar); - } - - private void setBooleanArg(char argChar, boolean value) { - booleanArgs.put(argChar, value); - } - - private boolean isBooleanArg(char argChar) { - return booleanArgs.containsKey(argChar); + private void setBooleanArg(ArgumentMarshaler m) { + try { + m.set("true"); + } catch (ArgsException e) { + } } public int cardinality() { @@ -226,28 +204,33 @@ private String unexpectedArgumentMessage() { return message.toString(); } - private boolean falseIfNull(Boolean b) { - return b == null ? false : b; - } - - private int zeroIfNull(Integer i) { - return i == null ? 0 : i; - } - - private String blankIfNull(String s) { - return s == null ? "" : s; - } - public String getString(char arg) { - return blankIfNull(stringArgs.get(arg)); + ArgumentMarshaler am = marshalers.get(arg); + try { + return am == null ? "" : (String) am.get(); + } catch (ClassCastException e) { + return ""; + } } public int getInt(char arg) { - return zeroIfNull(intArgs.get(arg)); + ArgumentMarshaler am = marshalers.get(arg); + try { + return am == null ? 0 : (Integer) am.get(); + } catch (ClassCastException e) { + return 0; + } } public boolean getBoolean(char arg) { - return falseIfNull(booleanArgs.get(arg)); + ArgumentMarshaler am = marshalers.get(arg); + boolean b = false; + try { + b = am != null && (Boolean) am.get(); + } catch (ClassCastException e) { + b = false; + } + return b; } public boolean has(char arg) { @@ -260,4 +243,56 @@ public boolean isValid() { private class ArgsException extends Exception { } + + private abstract class ArgumentMarshaler { + public abstract void set(String s) throws ArgsException; + + public abstract Object get(); + } + + private class BooleanArgumentMarshaler extends ArgumentMarshaler { + private boolean booleanValue = false; + + @Override + public void set(String s) { + booleanValue = true; + } + + @Override + public Object get() { + return booleanValue; + } + } + + private class StringArgumentMarshaler extends ArgumentMarshaler { + private String stringValue = ""; + + @Override + public void set(String s) { + stringValue = s; + } + + @Override + public Object get() { + return stringValue; + } + } + + private class IntegerArgumentMarshaler extends ArgumentMarshaler { + private int intValue = 0; + + @Override + public void set(String s) throws ArgsException { + try { + intValue = Integer.parseInt(s); + } catch (NumberFormatException e) { + throw new ArgsException(); + } + } + + @Override + public Object get() { + return intValue; + } + } }