Resolves #13 - Exclusion based on type in ArgumentValidator

This commit is contained in:
Mike Cifelli 2017-03-02 11:39:07 -05:00
parent ef4c03a672
commit d55ebdd22f
4 changed files with 58 additions and 43 deletions

View File

@ -12,18 +12,20 @@ public class ArgumentValidator {
private Class<? extends SExpression> firstArgumentType;
private Class<? extends SExpression> trailingArgumentType;
private Class<? extends SExpression> excludedFirstArgumentType;
private Class<? extends SExpression> excludedTrailingArgumentType;
private String functionName;
private BigInteger maximumNumberOfArguments;
private BigInteger minimumNumberOfArguments;
private boolean isNilAcceptable;
public ArgumentValidator(String functionName) {
this.firstArgumentType = SExpression.class;
this.trailingArgumentType = SExpression.class;
this.excludedFirstArgumentType = null;
this.excludedTrailingArgumentType = null;
this.functionName = functionName;
this.minimumNumberOfArguments = null;
this.maximumNumberOfArguments = null;
this.isNilAcceptable = true;
}
public void setFirstArgumentExpectedType(Class<? extends SExpression> argumentType) {
@ -38,6 +40,19 @@ public class ArgumentValidator {
this.firstArgumentType = argumentType;
this.trailingArgumentType = argumentType;
}
public void setFirstArgumentExcludedType(Class<? extends SExpression> argumentType) {
this.excludedFirstArgumentType = argumentType;
}
public void setTrailingArgumentExcludedType(Class<? extends SExpression> argumentType) {
this.excludedTrailingArgumentType = argumentType;
}
public void setEveryArgumentExcludedType(Class<? extends SExpression> argumentType) {
this.excludedFirstArgumentType = argumentType;
this.excludedTrailingArgumentType = argumentType;
}
public void setMaximumNumberOfArguments(int maximumNumberOfArguments) {
this.maximumNumberOfArguments = BigInteger.valueOf(maximumNumberOfArguments);
@ -52,10 +67,6 @@ public class ArgumentValidator {
this.maximumNumberOfArguments = BigInteger.valueOf(exactNumberOfArguments);
}
public void doNotAcceptNil() {
this.isNilAcceptable = false;
}
public void validate(Cons argumentList) {
validateListNotDotted(argumentList);
validateListLength(argumentList);
@ -118,11 +129,11 @@ public class ArgumentValidator {
}
private boolean isExpectedFirstArgumentType(SExpression firstArgument) {
return firstArgumentType.isInstance(firstArgument) && !isDisallowedNil(firstArgument);
return firstArgumentType.isInstance(firstArgument) && !isExcludedFirstArgumentType(firstArgument);
}
private boolean isDisallowedNil(SExpression argument) {
return !isNilAcceptable && argument.isNull();
private boolean isExcludedFirstArgumentType(SExpression firstArgument) {
return excludedFirstArgumentType != null && excludedFirstArgumentType.isInstance(firstArgument);
}
private void validateTrailingArguments(Cons argumentList) {
@ -132,7 +143,11 @@ public class ArgumentValidator {
}
private boolean isExpectedTrailingArgumentType(SExpression trailingArgument) {
return trailingArgumentType.isInstance(trailingArgument) && !isDisallowedNil(trailingArgument);
return trailingArgumentType.isInstance(trailingArgument) && !isExcludedTrailingArgumentType(trailingArgument);
}
private boolean isExcludedTrailingArgumentType(SExpression trailingArgument) {
return excludedTrailingArgumentType != null && excludedTrailingArgumentType.isInstance(trailingArgument);
}
public static class TooFewArgumentsException extends LispException {

View File

@ -17,7 +17,7 @@ public class CASE extends LispSpecialFunction {
this.argumentValidator = new ArgumentValidator("CASE");
this.argumentValidator.setMinimumNumberOfArguments(1);
this.argumentValidator.setTrailingArgumentExpectedType(Cons.class);
this.argumentValidator.doNotAcceptNil();
this.argumentValidator.setTrailingArgumentExcludedType(Nil.class);
}
public SExpression call(Cons argumentList) {

View File

@ -14,7 +14,7 @@ public class COND extends LispSpecialFunction {
public COND() {
this.argumentValidator = new ArgumentValidator("COND");
this.argumentValidator.setEveryArgumentExpectedType(Cons.class);
this.argumentValidator.doNotAcceptNil();
this.argumentValidator.setEveryArgumentExcludedType(Nil.class);
}
public SExpression call(Cons argumentList) {

View File

@ -74,46 +74,28 @@ public class ArgumentValidatorTester {
}
@Test
public void tooManyArgumentsException_HasCorrectSeverity() {
public void tooManyArgumentsException_HasCorrectAttributes() {
TooManyArgumentsException e = new TooManyArgumentsException("TEST", NIL);
assertEquals(ERROR, e.getSeverity());
}
@Test
public void tooManyArgumentsException_HasMessageText() {
TooManyArgumentsException e = new TooManyArgumentsException("TEST", NIL);
assertNotNull(e.getMessage());
assertTrue(e.getMessage().length() > 0);
}
@Test
public void tooFewArgumentsException_HasCorrectSeverity() {
public void tooFewArgumentsException_HasCorrectAttributes() {
TooFewArgumentsException e = new TooFewArgumentsException("TEST", NIL);
assertEquals(ERROR, e.getSeverity());
}
@Test
public void tooFewArgumentsException_HasMessageText() {
TooFewArgumentsException e = new TooFewArgumentsException("TEST", NIL);
assertNotNull(e.getMessage());
assertTrue(e.getMessage().length() > 0);
}
@Test
public void BadArgumentTypeException_HasCorrectSeverity() {
public void badArgumentTypeException_HasCorrectAttributes() {
BadArgumentTypeException e = new BadArgumentTypeException("TEST", NIL, SExpression.class);
assertEquals(ERROR, e.getSeverity());
}
@Test
public void BadArgumentTypeException_HasMessageText() {
BadArgumentTypeException e = new BadArgumentTypeException("TEST", NIL, SExpression.class);
assertNotNull(e.getMessage());
assertTrue(e.getMessage().length() > 0);
}
@ -201,22 +183,40 @@ public class ArgumentValidatorTester {
assertTrue(e.getMessage().length() > 0);
}
@Test(expected = BadArgumentTypeException.class)
public void doNotAcceptNil_ThrowsExceptionOnNilArgument() {
validator.doNotAcceptNil();
@Test
public void excludedFirstArgumentType_DoesNotAffectTrailingArguments() {
validator.setFirstArgumentExcludedType(Nil.class);
validator.validate(new Cons(T, new Cons(NIL, NIL)));
}
@Test
public void doNotAcceptNil_AllowsEmptyArgumentList() {
validator.doNotAcceptNil();
validator.validate(NIL);
public void excludedTrailingArgumentType_DoesNotAffectFirstArgument() {
validator.setTrailingArgumentExcludedType(Nil.class);
validator.validate(new Cons(NIL, new Cons(T, NIL)));
}
@Test
public void doNotAcceptNil_AllowsProperList() {
validator.doNotAcceptNil();
validator.validate(new Cons(T, new Cons(T, NIL)));
@Test(expected = BadArgumentTypeException.class)
public void excludedFirstArgumentType_ThrowsException() {
validator.setFirstArgumentExcludedType(Nil.class);
validator.validate(new Cons(NIL, new Cons(T, NIL)));
}
@Test(expected = BadArgumentTypeException.class)
public void excludedTrailingArgumentType_ThrowsException() {
validator.setTrailingArgumentExcludedType(Nil.class);
validator.validate(new Cons(T, new Cons(NIL, NIL)));
}
@Test(expected = BadArgumentTypeException.class)
public void excludedArgumentType_ThrowsExceptionOnFirstArgument() {
validator.setEveryArgumentExcludedType(Nil.class);
validator.validate(new Cons(NIL, new Cons(T, NIL)));
}
@Test(expected = BadArgumentTypeException.class)
public void excludedArgumentType_ThrowsExceptionOnTrailingArgument() {
validator.setEveryArgumentExcludedType(Nil.class);
validator.validate(new Cons(T, new Cons(NIL, NIL)));
}
}