// 목록 14-2 Args.java
public class Args {
private Map<Character, ArgumentMarshaler> marshalers;
private Set<Character> argsFound;
private ListIterator<String> currentArgument;
public Args(String schema, String[] args) throws ArgsException {
marshalers = new HashMap<>();
argsFound = new HashSet<>();
parseSchema(schema);
parseArgumentStrings(Arrays.asList(args));
}
private void parseSchema(String schema) throws ArgsException {
for (String element : schema.split(",")) {
if (element.length() > 0) {
parseSchemaElement(element.trim());
}
}
}
private void parseSchemaElement(String element) throws ArgsException {
char elementId = element.charAt(0);
String elementTail = element.substring(1);
validateSchemaElementId(elementId);
if (elementTail.length() == 0) {
marshalers.put(elementId, new BooleanArgumentMarshaler());
} else if (elementTail.equals("*")) {
marshalers.put(elementId, new StringArgumentMarshaler());
} else if (elementTail.equals("#")) {
marshalers.put(elementId, new IntegerArgumentMarshaler());
} else if (elementTail.equals("##")) {
marshalers.put(elementId, new DoubleArgumentMarshaler());
} else if (elementTail.equals("[*]")) {
marshalers.put(elementId, new StringArrayArgumentMarshaler());
} else {
throw new ArgsException(INVALID_ARGUMENT_FORMAT, elementId, elementTail);
}
}
private void validateSchemaElementId(char elementId) throws ArgsException {
if (!Character.isLetter(elementId)) {
throw new ArgsException(INVALID_ARGUMENT_NAME, elementId, null);
}
}
private void parseArgumentStrings(List<String> argsList) throws ArgsException {
for (currentArgument = argsList.listIterator(); currentArgument.hasNext();) {
String argString = currentArgument.next();
if (argString.startsWith("-")) {
parseArgumentCharacters(argString.substring(1));
} else {
currentArgument.previous();
break;
}
}
}
private void parseArgumentCharacters(String argsChars) throws ArgsException {
for (int i = 0; i < argsChars.length(); i++) {
parseArgumentCharacter(argsChars.charAt(i));
}
}
private void parseArgumentCharacter(char argChars) throws ArgsException {
ArgumentMarshaler m = marshalers.get(argChars);
if (m == null) {
throw new ArgsException(UNEXPECTED_ARGUMENT, argChars, null);
} else {
argsFound.add(argChars);
try {
m.set(currentArgument);
} catch (ArgsException e) {
e.setErrorArgumentId(argChars);
throw e;
}
}
}
public boolean has(char arg) {
return argsFound.contains(arg);
}
public int nextArgument() {
return currentArgument.nextIndex();
}
public boolean getBoolean(char arg) {
return BooleanArgumentMarshaler.getValue(marshalers.get(arg));
}
public String getString(char arg) {
return StringArgumentMarshaler.getValue(marshalers.get(arg));
}
public int getInt(char arg) {
return IntegerArgumentMarshaler.getValue(marshalers.get(arg));
}
public double getDouble(char arg) {
return DoubleArgumentMarshaler.getValue(marshalers.get(arg));
}
public String[] getStringArray(char arg) {
return StringArrayArgumentMarshaler.getValue(marshalers.get(arg));
}
}
public class ArgsException extends RuntimeException {
//... 상단 생략
public String errorMessage() throws Exception {
switch (errorCode) {
case OK:
throw new Exception("TILT: Should not get here.");
case UNEXPECTED_ARGUMENT:
return String.format("Argument -%c unexpected.", errorArgumentId);
case MISSING_STRING:
return String.format("Could not find string parameter for -%c.", errorArgumentId);
case INVALID_INTEGER:
return String.format("Argument -%c expects an integer but was '%s'.", errorArgumentId, errorParameter);
case MISSING_INTEGER:
return String.format("Could not find integer parameter for -%c.", errorArgumentId);
case INVALID_DOUBLE:
return String.format("Argument -%c expects a double but was '%s'.", errorArgumentId, errorParameter);
case MISSING_DOUBLE:
return String.format("Could not find double parameter for -%c.", errorArgumentId);
}
return "";
}
public enum ErrorCode {
OK, INVALID_FORMAT, UNEXPECTED_ARGUMENT, INVALID_ARGUMENT_NAME, MISSING_STRING,
MISSING_INTEGER, INVALID_INTEGER,
MISSING_DOUBLE, INVALID_DOUBLE
}
}
코드는 언제나 최대한 깔끔하고 단순하게 정리하자. 절대로 썩어가게 방치하면 안된다.