由于没有纸质书或pdf没有代码,不在编辑器里看代码,实在难看懂。所以跟着写了一遍。代码不完全一样,没有单元测试,不保证没问题。大概可以一用吧。
代码14-9
package com.example.demo.args;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
/**
* 代码清单 14-9 一个早期版本代码,只支持Boolean 参数
*/
public class Args149 {
private String schema;
private String[] args;
private boolean valid;
private Set<Character> unexpectArguments = new TreeSet<>();
private Map<Character, Boolean> booleanArgs = new HashMap<>();
private int numberOfArguments = 0;
public Args149(String schema, String[] args) {
this.schema = schema;
this.args = args;
valid = parse();
}
public boolean getBoolean(char arg) {
return booleanArgs.get(arg);//TODO 校验key是否存在,不存在:给提示(抛错太不友好;了)
}
public int cardinality() {
return numberOfArguments;
}
public String usage() {
if (schema.length() > 0)
return "-[" + schema + "]";
else
return "";
}
public String errorMessage() {
if (unexpectArguments.size() > 0)
return unexpectArgumentsMessage();
else
return "";
}
public boolean isValid() {
return valid;
}
private boolean parse() {
if (schema.length() == 0 && args.length == 0) return true;
parseSchema();
parseArguments();
return unexpectArguments.size() == 0;
}
private boolean parseSchema() {
for (String element : schema.split(",")) {
parseSchemaElement(element);
}
return true;
}
private void parseSchemaElement(String element) {
if (element.length() == 1) {
parseBooleanSchemaElement(element);
}
}
private void parseBooleanSchemaElement(String element) {
char c = element.charAt(0);
if (Character.isLetter(c)) {
booleanArgs.put(c, false);
}
}
private boolean parseArguments() {
for (String arg : args)
parseArgument(arg);
return true;
}
private void parseArgument(String arg) {
if (arg.startsWith("-")) {
parseElements(arg);
}
}
private void parseElements(String arg) {
for (int i = 1; i < arg.length(); i++) {
parseElement(arg.charAt(i));
}
}
private void parseElement(char argChar) {
if (isBoolean(argChar)) {
numberOfArguments++;
setBooleanArg(argChar, true);
} else
unexpectArguments.add(argChar);
}
private void setBooleanArg(char argChar, boolean value) {
booleanArgs.put(argChar, value);
}
private boolean isBoolean(char argChar) {
return booleanArgs.containsKey(argChar);
}
private String unexpectArgumentsMessage() {
StringBuffer message = new StringBuffer("Argument(s) -");
for (Character c : unexpectArguments) {
message.append(c);
}
message.append(" unexpected.");
return message.toString();
}
}
代码14-10
package com.example.demo.args;
import java.text.ParseException;
import java.util.*;
/**
* 代码清单 14-10
*/
public class Args1410 {
private String schema;
private String[] args;
private boolean valid = true;
private Set<Character> unexpectArguments = new TreeSet<>();
private Map<Character, Boolean> booleanArgs = new HashMap<>();
private Map<Character, String> stringArgs = new HashMap<>();
private Set<Character> argsFound = new HashSet<>();
private int currentArgument;
private char errorArgument = '\0';
enum ErrorCode {
OK, MISSING_STRING
}
private ErrorCode errorCode = ErrorCode.OK;
private int numberOfArguments = 0;
public Args1410(String schema, String[] args) throws ParseException {
this.schema = schema;
this.args = args;
valid = parse();
}
private boolean parse() throws ParseException {
if (schema.length() == 0 && args.length == 0) return true;
parseSchema();
parseArguments();
return valid;
}
private boolean parseSchema() throws ParseException {
for (String element : schema.split(",")) {
if (element.length() > 0) {
String trimElement = element.trim();
parseSchemaElement(trimElement);
}
}
return true;
}
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);
}
private void validateSchemaElementId(char elementId) throws ParseException {
if (!Character.isLetter(elementId)) {
throw new ParseException("Bad character:" + elementId + "in Args format: " + schema, 0);
}
}
private boolean isBooleanSchemaElement(String elementTail) {
return elementTail.length() == 0;
}
private boolean isStringSchemaElement(String elementTail) {
return "*".equals(elementTail);
}
private void parseBooleanSchemaElement(char elementId) {
booleanArgs.put(elementId, false);
}
private void parseStringSchemaElement(char elementId) {
stringArgs.put(elementId, "");
}
private boolean parseArguments() {
for (currentArgument = 0; currentArgument < args.length; currentArgument++) {
String arg = args[currentArgument];
parseArgument(arg);
}
return true;
}
private void parseArgument(String arg) {
if (arg.startsWith("-")) {
parseElements(arg);
}
}
private void parseElements(String arg) {
for (int i = 1; i < arg.length(); i++) {
parseElement(arg.charAt(i));
}
}
private void parseElement(char argChar) {
if (setArgument(argChar)) {
argsFound.add(argChar);
} else {
unexpectArguments.add(argChar);
valid = false;
}
}
private boolean setArgument(char argChar) {
boolean set = true;
if (isBoolean(argChar))
setBooleanArg(argChar, true);
else if (isString(argChar))
setStringArg(argChar);
else
set = false;
return set;
}
private void setBooleanArg(char argChar, boolean value) {
booleanArgs.put(argChar, value);
}
private void setStringArg(char argChar) {
currentArgument++;
try {
stringArgs.put(argChar, args[currentArgument]);
} catch (ArrayIndexOutOfBoundsException e) {
valid = false;
errorArgument = argChar;
errorCode = ErrorCode.MISSING_STRING;
}
}
private boolean isBoolean(char argChar) {
return booleanArgs.containsKey(argChar);
}
private boolean isString(char argChar) {
return stringArgs.containsKey(argChar);
}
public int cardinality() {
return argsFound.size();
}
public String usage() {
if (schema.length() > 0)
return "-[" + schema + "]";
else
return "";
}
public String errorMessage() throws Exception {
if (unexpectArguments.size() > 0)
return unexpectArgumentsMessage();
else
switch (errorCode) {
case MISSING_STRING:
return String.format("Could not find string paramenter for -%c.", errorArgument);
case OK:
throw new Exception("TILT: should not get here.");
}
return "";
}
private String unexpectArgumentsMessage() {
StringBuffer message = new StringBuffer("Argument(s) -");
for (Character c : unexpectArguments) {
message.append(c);
}
message.append(" unexpected.");
return message.toString();
}
public boolean getBoolean(char arg) {
return falseIfNull(booleanArgs.get(arg));
}
private boolean falseIfNull(Boolean b) {
return b == null ? false : b;
}
public String getString(char arg) {
return blankIfNull(stringArgs.get(arg));
}
public String blankIfNull(String s) {
return s == null ? "" : s;
}
public boolean has(char arg) {
return argsFound.contains(arg);
}
public boolean isValid() {
return valid;
}
}
基本上算完成的代码:
Args1411
package com.example.demo.args;
import com.example.demo.args.marshaler.ArgumentMarshaler;
import com.example.demo.args.marshaler.BooleanArgumentMarshaler;
import com.example.demo.args.marshaler.IntegerArgumentMarshaler;
import com.example.demo.args.marshaler.StringArgumentMarshaler;
import java.text.ParseException;
import java.util.*;
public class Args1411 {
private String schema;
private List<String> argsList;
private boolean valid = true;
private Set<Character> unexpectArguments = new TreeSet<>();
private Map<Character, ArgumentMarshaler> argumentMarshaler = new HashMap<>();
private Set<Character> argsFound = new HashSet<>();
private Iterator<String> currentArgument;
private ArgsException.ErrorCode errorCode = ArgsException.ErrorCode.OK;
public Args1411(String schema, String[] args) throws ParseException {
this.schema = schema;
this.argsList = Arrays.asList(args);
valid = parse();
}
private boolean parse() throws ParseException {
if (schema.length() == 0 && argsList.size() == 0) return true;
parseSchema();
parseArguments();
return valid;
}
private boolean parseSchema() throws ParseException {
for (String element : schema.split(",")) {
if (element.length() > 0) {
String trimElement = element.trim();
parseSchemaElement(trimElement);
}
}
return true;
}
private void parseSchemaElement(String element) throws ParseException {
char elementId = element.charAt(0);
String elementTail = element.substring(1);
validateSchemaElementId(elementId);
if (elementTail.length() == 0)
argumentMarshaler.put(elementId, new BooleanArgumentMarshaler());
else if ("*".equals(elementTail))
argumentMarshaler.put(elementId, new StringArgumentMarshaler());
else if ("#".equals(elementTail))
argumentMarshaler.put(elementId, new IntegerArgumentMarshaler());
}
private void validateSchemaElementId(char elementId) throws ParseException {
if (!Character.isLetter(elementId)) {
throw new ParseException("Bad character:" + elementId + "in Args format: " + schema, 0);
}
}
private boolean parseArguments() {
for (currentArgument = argsList.iterator(); currentArgument.hasNext(); ) {
String arg = currentArgument.next();
parseArgument(arg);
}
return true;
}
private void parseArgument(String arg) {
if (arg.startsWith("-")) {
parseElements(arg);
}
}
private void parseElements(String arg) {
for (int i = 1; i < arg.length(); i++) {
parseElement(arg.charAt(i));
}
}
private void parseElement(char argChar) {
if (setArgument(argChar)) {
argsFound.add(argChar);
} else {
unexpectArguments.add(argChar);
valid = false;
}
}
private boolean setArgument(char argChar) {
boolean set = true;
ArgumentMarshaler marshaler = this.argumentMarshaler.get(argChar);
if (marshaler == null) return false;
try {
marshaler.set(currentArgument);
} catch (ArgsException e) {
errorCode = e.getErrorCode();
valid = false;
}
return set;
}
public int cardinality() {
return argsFound.size();
}
public String usage() {
if (schema.length() > 0)
return "-[" + schema + "]";
else
return "";
}
public String errorMessage() throws Exception {
if (unexpectArguments.size() > 0)
return unexpectArgumentsMessage();
else
switch (errorCode) {
case MISSING_STRING:
return "Could not find string paramenter for -%c.";
//其他的省略
case OK:
throw new Exception("TILT: should not get here.");
}
return "";
}
private String unexpectArgumentsMessage() {
StringBuffer message = new StringBuffer("Argument(s) -");
for (Character c : unexpectArguments) {
message.append(c);
}
message.append(" unexpected.");
return message.toString();
}
public boolean getBoolean(char arg) {
ArgumentMarshaler am = argumentMarshaler.get(arg);
boolean b;
try {
b = am != null && (boolean) am.get();
} catch (ClassCastException e) {
b = false;
}
return b;
}
public String getString(char arg) {
ArgumentMarshaler am = argumentMarshaler.get(arg);
return am == null ? "" : (String) am.get();
}
public String blankIfNull(String s) {
return s == null ? "" : s;
}
public Integer getInteger(char arg) {
ArgumentMarshaler am = argumentMarshaler.get(arg);
return am == null ? 0 : (Integer) am.get();
}
public boolean has(char arg) {
return argsFound.contains(arg);
}
public boolean isValid() {
return valid;
}
}
ArgumentMarshaler
package com.example.demo.args.marshaler;
import com.example.demo.args.ArgsException;
import java.util.Iterator;
public abstract class ArgumentMarshaler {
public abstract void set(Iterator<String> integerValue) throws ArgsException;
public abstract Object get();
}
BooleanArgumentMarshaler
package com.example.demo.args.marshaler;
import java.util.Iterator;
public class BooleanArgumentMarshaler extends ArgumentMarshaler {
private boolean booleanValue = false;
public void set(Iterator<String> currentArgument) {
booleanValue = true;
}
public Object get() {
return booleanValue;
}
}
IntegerArgumentMarshaler
package com.example.demo.args.marshaler;
import com.example.demo.args.ArgsException;
import java.util.Iterator;
public class IntegerArgumentMarshaler extends ArgumentMarshaler {
private Integer integerValue;
public void set(Iterator<String> currentArgument) throws ArgsException {
try {
this.integerValue = Integer.valueOf(currentArgument.next());
} catch (NumberFormatException e) {
throw new ArgsException(ArgsException.ErrorCode.INALID_INTEGER);
}
}
public Object get() {
return integerValue == null ? 0 : integerValue;
}
}
StringArgumentMarshaler
package com.example.demo.args.marshaler;
import com.example.demo.args.ArgsException;
import java.util.Iterator;
public class StringArgumentMarshaler extends ArgumentMarshaler {
private String stringValue;
public void set(Iterator<String> currentArgument) throws ArgsException {
try {
this.stringValue = currentArgument.next();
} catch (ArrayIndexOutOfBoundsException e) {
throw new ArgsException(ArgsException.ErrorCode.MISSING_STRING);
} catch (ClassCastException e) {
throw new ArgsException(ArgsException.ErrorCode.INALID_STRING);
}
}
public String get() {
return stringValue == null ? "" : stringValue;
}
}
ArgsException
package com.example.demo.args;
public class ArgsException extends Exception {
private char errorArgument = '\0';
private String errorParameter = "TILT";
private ErrorCode errorCode = ErrorCode.OK;
public ErrorCode getErrorCode() {
return errorCode;
}
public void setErrorCode(ErrorCode errorCode) {
this.errorCode = errorCode;
}
public ArgsException() {
}
public ArgsException(String message) {
super(message);
}
public ArgsException(ErrorCode errorCode) {
this.errorCode = errorCode;
}
public enum ErrorCode {
OK, MISSING_STRING, MISSING_INTEGER,
INALID_INTEGER, INALID_STRING, UNEXPECTED_ARGUMENT;
}
}
Args1410Test
package com.example.demo.args;
import java.text.ParseException;
/**
* description
*
* @author lilei
* @date 2022/4/12 16:32
*/
public class Args1410Test {
public static void main(String[] args) throws Exception {
Args1410 args1410 = null;
String[] args2 = new String[]{"-b", "-s", "A", "-S", "B", "c"};
try {
args1410 = new Args1410("b,s*,S*", args2);
} catch (ParseException e) {
System.out.println(e.getMessage());
}
System.out.printf("usage:%s", args1410.usage());
System.out.println();
System.out.printf("boolean:%b", args1410.getBoolean('b'));
System.out.println();
System.out.printf("String:%s", args1410.getString('s'));
System.out.println();
System.out.printf("String:%s", args1410.getString('S'));
System.out.println();
System.out.printf("isValid:%s", args1410.isValid());
System.out.println();
System.out.printf("errorMessage:%s", args1410.errorMessage());
}
}