Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions src/main/java/chapter14/Application.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package chapter14;

import chapter14.args.Args;
import chapter14.args.ArgsException;

class Application {

public static void main(String[] args) {
try {
Args arg = new Args("l,p#,d*", args);
boolean logging = arg.getBoolean('l');
int port = arg.getInt('p');
String directory = arg.getString('d');
executeApplication(logging, port, directory);
} catch (ArgsException e) {
System.out.printf("Argument error: %s\n", e.errorMessage());
}
}

// stub
private static void executeApplication(boolean logging, int port, String directory) {
System.out.printf("logging: %b, port: %d, directory: %s\n", logging, port, directory);
}
}
107 changes: 107 additions & 0 deletions src/main/java/chapter14/args/Args.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package chapter14.args;

import java.util.*;

import static chapter14.args.ArgsException.ErrorCode.*;

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
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 argChars) throws ArgsException {
for (int i = 0; i < argChars.length(); i++) {
parseArgumentCharacter(argChars.charAt(i));
}
}

private void parseArgumentCharacter(char argChar) throws ArgsException {
ArgumentMarshaler m = marshalers.get(argChar);
if (m == null) {
throw new ArgsException(UNEXPECTED_ARGUMENT, argChar, null);
} else {
argsFound.add(argChar);
try {
m.set(currentArgument);
} catch (ArgsException e) {
e.setErrorArgumentId(argChar);
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));
}
}
92 changes: 92 additions & 0 deletions src/main/java/chapter14/args/ArgsException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package chapter14.args;

public class ArgsException extends Exception {
private char errorArgumentId = '\0';
private String errorParameter = "TILT";
private ErrorCode errorCode = ErrorCode.OK;

public ArgsException() {
}

public ArgsException(String message) {
super(message);
}

public ArgsException(ErrorCode errorCode) {
this.errorCode = errorCode;
}

public ArgsException(ErrorCode errorCode, String errorParameter) {
this.errorCode = errorCode;
this.errorParameter = errorParameter;
}

public ArgsException(ErrorCode errorCode, char errorArgumentId, String errorParameter) {
this.errorCode = errorCode;
this.errorArgumentId = errorArgumentId;
this.errorParameter = errorParameter;
}

public char getErrorArgumentId() {
return errorArgumentId;
}

public void setErrorArgumentId(char errorArgumentId) {
this.errorArgumentId = errorArgumentId;
}

public String getErrorParameter() {
return errorParameter;
}

public void setErrorParameter(String errorParameter) {
this.errorParameter = errorParameter;
}

public ErrorCode getErrorCode() {
return errorCode;
}

public void setErrorCode(ErrorCode errorCode) {
this.errorCode = errorCode;
}

public String errorMessage() {
switch (errorCode) {
case OK:
return "TILT: Should not get here.";
case UNEXPECTED_ARGUMENT:
return String.format("Argument(s) -%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 an double but was '%s'.",
errorArgumentId, errorParameter);
case MISSING_DOUBLE:
return String.format("Could not find double parameter for -%c.",
errorArgumentId);
case INVALID_ARGUMENT_NAME:
return String.format("'%c' is not a valid argument name.",
errorArgumentId);
case INVALID_ARGUMENT_FORMAT:
return String.format("'%s' is not a valid argument format.",
errorParameter);
}
return "";
}

public enum ErrorCode {
OK, INVALID_ARGUMENT_FORMAT, UNEXPECTED_ARGUMENT,
INVALID_ARGUMENT_NAME,
MISSING_STRING,
MISSING_INTEGER, INVALID_INTEGER,
MISSING_DOUBLE, INVALID_DOUBLE
}
}
7 changes: 7 additions & 0 deletions src/main/java/chapter14/args/ArgumentMarshaler.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package chapter14.args;

import java.util.Iterator;

public interface ArgumentMarshaler {
void set(Iterator<String> currentArgument) throws ArgsException;
}
20 changes: 20 additions & 0 deletions src/main/java/chapter14/args/BooleanArgumentMarshaler.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package chapter14.args;

import java.util.Iterator;

public class BooleanArgumentMarshaler implements ArgumentMarshaler {
private boolean booleanValue = false;

@Override
public void set(Iterator<String> currentArgument) throws ArgsException {
booleanValue = true;
}

public static boolean getValue(ArgumentMarshaler am) {
if (am != null && am instanceof BooleanArgumentMarshaler) {
return ((BooleanArgumentMarshaler) am).booleanValue;
} else {
return false;
}
}
}
32 changes: 32 additions & 0 deletions src/main/java/chapter14/args/DoubleArgumentMarshaler.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package chapter14.args;

import java.util.Iterator;
import java.util.NoSuchElementException;

import static chapter14.args.ArgsException.ErrorCode.INVALID_DOUBLE;
import static chapter14.args.ArgsException.ErrorCode.MISSING_DOUBLE;

public class DoubleArgumentMarshaler implements ArgumentMarshaler {
private double doubleValue = 0;

@Override
public void set(Iterator<String> currentArgument) throws ArgsException {
String parameter = null;
try {
parameter = currentArgument.next();
doubleValue = Double.parseDouble(parameter);
} catch (NoSuchElementException e) {
throw new ArgsException(MISSING_DOUBLE);
} catch (NumberFormatException e) {
throw new ArgsException(INVALID_DOUBLE, parameter);
}
}

public static double getValue(ArgumentMarshaler am) {
if (am != null && am instanceof DoubleArgumentMarshaler) {
return ((DoubleArgumentMarshaler) am).doubleValue;
} else {
return 0.0;
}
}
}
32 changes: 32 additions & 0 deletions src/main/java/chapter14/args/IntegerArgumentMarshaler.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package chapter14.args;

import java.util.Iterator;
import java.util.NoSuchElementException;

import static chapter14.args.ArgsException.ErrorCode.INVALID_INTEGER;
import static chapter14.args.ArgsException.ErrorCode.MISSING_INTEGER;

public class IntegerArgumentMarshaler implements ArgumentMarshaler {
private int intValue = 0;

@Override
public void set(Iterator<String> currentArgument) throws ArgsException {
String parameter = null;
try {
parameter = currentArgument.next();
intValue = Integer.parseInt(parameter);
} catch (NoSuchElementException e) {
throw new ArgsException(MISSING_INTEGER);
} catch (NumberFormatException e) {
throw new ArgsException(INVALID_INTEGER, parameter);
}
}

public static int getValue(ArgumentMarshaler am) {
if (am != null && am instanceof IntegerArgumentMarshaler) {
return ((IntegerArgumentMarshaler) am).intValue;
} else {
return 0;
}
}
}
27 changes: 27 additions & 0 deletions src/main/java/chapter14/args/StringArgumentMarshaler.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package chapter14.args;

import java.util.Iterator;
import java.util.NoSuchElementException;

import static chapter14.args.ArgsException.ErrorCode.MISSING_STRING;

public class StringArgumentMarshaler implements ArgumentMarshaler {
private String stringValue = "";

@Override
public void set(Iterator<String> currentArgument) throws ArgsException {
try {
stringValue = currentArgument.next();
} catch (NoSuchElementException e) {
throw new ArgsException(MISSING_STRING);
}
}

public static String getValue(ArgumentMarshaler am) {
if (am != null && am instanceof StringArgumentMarshaler) {
return ((StringArgumentMarshaler) am).stringValue;
} else {
return "";
}
}
}
Loading