How to eliminate all "if" statements from my validator class - java

Is there a way to eliminate all the "if" statements from this class and still maintain the exact same functionality ?
So far I managed to simplify the code by creating the 2 extra functions: isNameValid and isPhoneValid, but I need a way to get rid of all the "if" statements.
public class ClientValidator implements Validator<Client> {
#Override
public void validate(Client entity) throws ValidatorException {
if(!isNameValid(entity.getName())){
throw new ClientException("Invalid name!");
}
if(!isPhoneValid(entity.getPhone())){
throw new ClientException("Invalid phone number!");
}
}
private boolean isNameValid(String name) {
return name.length() > 1 && name.length() < 100;
}
private boolean isPhoneValid(String phone) {
try {
Long.parseLong(phone);
} catch (NumberFormatException e) {
return false;
}
return true;
}
}

you can try optionals and do filtering on the methods, but you miss reason specific exceptions:
Optional
.of(entity)
.filter(entity -> isNameValid(entity.getName())
.filter(entity -> isPhoneValid(entity.getPhone())
.orElseThrow(() -> new ClientException("Wrong client data"));

Is there a way to eliminate all the "if" statements from this class and still maintain the exact same functionality ?
Yes. It's a hack, but if isn't the only flow-control. Easiest I see, a while loop with the same logic. Like,
#Override
public void validate(Client entity) throws ValidatorException {
while (!isNameValid(entity.getName())) {
throw new ClientException("Invalid name!");
}
while (!isPhoneValid(entity.getPhone())) {
throw new ClientException("Invalid phone number!");
}
}
You could also use switch statements like
#Override
public void validate(Client entity) throws ValidatorException {
switch (isNameValid(entity.getName())) {
case false:
throw new ClientException("Invalid name!");
}
switch (isPhoneValid(entity.getPhone())) {
case false:
throw new ClientException("Invalid phone number!");
}
}

What about this :
#Override
public void validate(String entity) throws ClientException {
String message = !isNameValid(entity.getName()) ? "Invalid name!"
: !isPhoneValid(entity.getPhone()) ? "Invalid phone number!" : "";
Stream.of(message).filter(m -> m.isEmpty()).findAny()
.orElseThrow(() -> new ClientException (message));
}

I could think of some dirty tricks like
public void validate(Client entity) throws ValidatorException {
try {
int len = entity.getName().length();
int isshort = 1 / len;
int islong = 1 / max (0, 100- length);
} catch (Exception e) {
throw new ClientException("Invalid name!");
}
try {
Long.parseLong(entity.getPhone());
} catch (NumberFormatException e) {
throw new ClientException("Invalid phone number!");
}
}
So no if needed

Related

CompletableFuture exceptional handler chain

Is it possible to make exceptional handlers in chain with ComplatableFuture?
For example: I have this code, the idea is that if location service methods throws an error, make a generic call to findClosest method (with no params). So basically, I want to return List <Closest> form either of these methods. This works ok. But on the external code, I need to fire an event in case the method call was generic (in case locationService fail).
#Async
#Override
public CompletionStage<List<Closest>> getClosestByZip(final String zip) {
return locationService.getCoordinates(zip)
.handle((c, ex) -> ex == null ? closestService.findClosest(c) : closestService.findClosest())
.thenCompose(list -> list);
}
In the test, the exceptional section never executed, cause the future appears to be completed successfully.
CompletableFuture<List<Closest>> closest = distanceService.getClosestByZip("111111")
.exceptionally(ex -> {
System.out.println("From exceptionally");
return null;
})
.toCompletableFuture();
try {
List<Closest> list = closest.get();
Assert.assertEquals(2, list.size());
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
Assert.fail("Exception was not caught");
}
How is it possible to handle this situation?
Please check if this is helpful.
public class CompleteableFutureEx {
public static void main(String[] args) throws Throwable {
try {
test(-1);
} catch (ArithmeticException e) {
System.out.println("Oops! We have an ArithmeticException");
}
catch (IllegalArgumentException e) {
System.out.println("Oops! We have an IllegalArgumentException");
}
catch (Exception e) {
System.out.println("Oops! We have an Exception ");
}
}
public static void test(int age) throws Throwable {
try {
CompletableFuture<String> maturityFuture = CompletableFuture.supplyAsync(() -> {
//ArithmeticException
//int age1 = age/0;
if (age < 0) {
throw new IllegalArgumentException("Age can not be negative");
}
if (age > 18) {
return "Adult";
} else {
return "Child";
}
});
maturityFuture.join();
}catch (CompletionException ce) {
throw ce.getCause();
}
}
}

Is there another method to replace Exception message with custom message instead of try{}catch(Exception e){} method?

Instead of the try{}catch(Exception e){} method, is there a way to just state a custom message that replaces the exception message when exceptions like InputMismatchException, NoSuchElementException etc. occurs anywhere on the program?
EDIT: I want another method because if I use try{}catch(Exception e){} method than I will have to do it everywhere and the code also becomes longer.
For example:
public static String genderOutput()
{
try
{
System.out.print("\nMale - 1 \nFemale - 2 \n\nEnter either 1 or 2: ");
int genderInput = userInput.nextInt();
if(genderInput == 1)
{
String userGender = "Mr.";
return userGender;
}
else if(genderInput == 2)
{
String userGender = "Mrs.";
return userGender;
}
else
{
String userGender = " ";
return userGender;
}
}
catch (Exception e)
{
return null;
}
}
I have this function, now if there were multiple functions in a class like this then I would have to have the try{}catch(Exception e){} method everywhere. Wouldn't it be more efficient if you can just replace the exception message with your own and when such exception occurs which has a custom message stated to them then it would just throw out the custom message instead. This way, the code will be shorter as well.
SOLUTION TO MY PROBLEM:
public class Test
{
public static Scanner userInput = new Scanner(System.in);
public static String titleName = "TheRivalsRage";
public static String exitLevelMessage = "Program exited!";
public static String errorMessageTitle = "\n[Error] ";
public static String intInputMismatchException = "Please enter an Integer Value!";
public static String intNoSuchElementException = "Please enter either '1' or '2' without the quotes!";
public static String lineNoSuchElementException = "Please enter something!";
public static String bothIllegalStateException = "Scanner closed unexpectedly!";
public static void main(String[] args)
throws Exception
{
String usernameOutput;
String userGender;
try
{
System.out.print("Enter your username: ");
usernameOutput = userInput.nextLine();
userGender = genderOutput();
userInput.close();
}
catch(IllegalStateException e)
{
throw new IllegalStateException(errorMessageTitle + bothIllegalStateException);
}
if(userGender == null)
{
noSuchElementException();
}
else
{
System.out.println("\nWelcome " + userGender + " " + usernameOutput + " to " + titleName);
}
}
public static String genderOutput()
{
String userGender;
int genderInput;
System.out.print("\nMale - 1 \nFemale - 2 \n\nEnter either 1 or 2: ");
try
{
genderInput = userInput.nextInt();
}
catch(InputMismatchException e)
{
genderInput = 0;
inputMismatchException();
}
if(genderInput == 1)
{
userGender = "Mr.";
}
else if(genderInput == 2)
{
userGender = "Mrs.";
}
else
{
userGender = null;
}
return userGender;
}
public static void inputMismatchException()
throws InputMismatchException
{
throw new InputMismatchException(errorMessageTitle + intInputMismatchException);
}
public static void noSuchElementException()
throws NoSuchElementException
{
throw new NoSuchElementException(errorMessageTitle + intNoSuchElementException);
}
}
don't handle exception in each and every method just use throws Exception after method signature and handle it at end where the methods are being called.
and there in catch block you can throw your custom exception.
void method1() throws Exception{
//
}
void method2() throws Exception{
//
}
void finalmethod(){
try{
method1();
method2();
}catch(InputMismatchException e){
throw customExcpetion("custommessage1");
}catch(Exception e){
throw customExcpetion("custommessage2");
}
}
You need a try/catch.
However, you do not need to catch all exceptions separately, because the exceptions that you mention are all subclasses of RuntimeException. Hence, it is sufficient to make a single try/catch in your main to intercept RuntimeException, and print the replacement message:
public static void main(String[] args) {
try {
... // Actual code
} catch (RuntimeException ex) {
System.err.println("A runtime error has occurred.");
}
}
You can try Aspectj or Spring aop by creating around advice. You can replace message by catching exception inside advice and rethrow.
Check http://howtodoinjava.com/spring/spring-aop/aspectj-around-advice-example/
To know about how to use spring aop for anound advice
Java doesn't provide this feature out of the box but nobody prevents you to create a class that composes a Scanner object and that decorates methods that you are using as nextInt().
Inside the decorated method, invoke nextInt(), catch the exception that it may throw and handle it by returning null as in your question.
If it makes sense, you could even provide a nextInt() method with a default value as parameter if the input fails.
public class MyCustomScanner{
private Scanner scanner;
...
public Integer nextInt(){
try{
return scanner.nextInt()
}
catch(InputMismatchException e){
myStateObj.setErrorMessage("....");
return null;
}
}
public Integer nextInt(Integer defaultValue){
try{
return scanner.nextInt()
}
catch(InputMismatchException e){
myStateObj.setErrorMessage("....");
return defaultValue;
}
}
}
Now you can use the class in this way :
MyCustomScanner scanner = new MyCustomScanner();
Integer intValue = scanner.nextInt();
Integer otherIntValue = scanner.nextInt(Integer.valueOf(4));

Dealing with exception in other method by using other method catch

I need to see the result as a boolean result: true. But there's a catch I need to do it in a non-ordinary way.
import java.io.IOException;
public class FlashLight {
private Bulb bulb;
private Battery[] batteries;
public void on() {
try {
if (this.IsThereEnoughPower()) {
this.bulb.setOn(true);
for (Battery b : batteries) {
b.setPower(b.getPower() - this.bulb.getBrightness());
}
}
} catch (IOException e) {
System.out.println(e.getMessage());
this.setBatteries(new Battery[4]);
}
}
I need to catch the exception in method on() but i can only modify method: DetermineIfFlashlightCanBeTurnedOn
public boolean DetermineIfFlashlightCanBeTurnedOn() throws IOException {
return bulb != null && DetermineIfBatteriesAreInstalled() && IsThereEnoughPower();
}
private boolean DetermineIfBatteriesAreInstalled() throws IOException {
if (batteries.length < 4) {
throw new IOException(Math.abs(-4 + batteries.length));
}
for (Battery b : batteries) {
if (b == null) {
return false;
}
}
return true;
}
private boolean IsThereEnoughPower() {
for (Battery b : batteries) {
if (b.getPower() < MIN_BATTERY_POWER) {
return false;
}
}
return true;
}
private static void testLatarki(String... args) {
FlashLight flashlight = new Flashlight();
System.out.println(flashlight.DetermineIfFlashlightCanBeTurnedOn());
}
}
Exception can be caught only in on() method.
DetermineIfBatteriesAreInstalled() DetermineIfFlashlightCanBeTurnedOn
must be signed as: throws IOException.
You can use try{}catch(){} instead :
public boolean DetermineIfFlashlightCanBeTurnedOn() {
try {
return bulb != null && DetermineIfBatteriesAreInstalled() && IsThereEnoughPower();
} catch (Exception e) {
//log your exception
}
return false;
}
I forgot to tell you guys i can use try/catch blocks only in on()
method
In this case you can use RuntimeException you don't need to use throws IOException in your method:
if (batteries.length < 4) {
throw new RuntimeException(Math.abs(-4 + batteries.length)+"");
}
So :
public boolean DetermineIfFlashlightCanBeTurnedOn() {
//--not need to use throw throws IOException-------^
return bulb != null && DetermineIfBatteriesAreInstalled() && IsThereEnoughPower();
}
private boolean DetermineIfBatteriesAreInstalled() {
//--not need to use throw throws IOException------^
if (batteries.length < 4) {
throw new RuntimeException(Math.abs(-4 + batteries.length) + "");
//----------^^
}
for (Battery b : batteries) {
if (b == null) {
return false;
}
}
return true;
}
You can read more here Is there a way to throw an exception without adding the throws declaration?

Try Catch Exceptions of the Same Type Java

I want to know if there is a way to have the same exception type in a catch.
So basically we have this:
catch(IllegalArgumentException exception){
throw new IllegalArgumentException("Error CheckingAccount: negative initial balance");
throw new IllegalArgumentException("Error deposit: negative amount");
throw new IllegalArgumentException("Error withdraw: illegal amount");
}
I was wondering how it can change between the same exception type but have it be called when it is needed. Do I need if-else statements? By the way this is not in main.
To be specific this is String getMessage().
You don't shuffle.
Your method simply does multiple checks, and throws the same kind of exception but with different messages.
And your code that calls this method has one catch for this type of exception and prints the message.
That is all there is to this.
According to the your code always throw the first one inside the catch clause.
You can define your own exception class and throw all exceptions to it. Then you can log your errors by using Loggers.
catch(IllegalArgumentException exception){
throw new MyExceptionClass(exception.getMessage(),exception);
}
your class can be like this:
public class MyExceptionClass extends Exception {
/**
* #param messages
* #param e
*/
public MyExceptionClass (String messages,Exception e ){
super(messages,e);
}
}
You'll need an if-else to choose between then.
double div(double d1, double d2){
if(d2 == 0)
throw new IllegalArgumentException("Division by 0.");
if(d2 > d1)
throw new IllegalArgumentException("Some message.");
if(something else)
throw new IllegalArgumentException("Your message.");
return d1/d2;
}
You can also use try-catch as well.
double div(Double d1, Double d2){
try{
return d1/d2;
}catch(ArithmeticException e){
throw new ArithmeticException("Division by 0");
}catch(NullPointerException e2){
throw e2;
}
}
For different type of scenarios, you can create different type of user defined exceptions.
In your case, you can defined three new exceptions like this:
class NegativeInitialBalance extends Exception {}
class NegativeAmount extends Exception {}
class IllegalAmount extends Exception {}
Just declaring the class would be enough if you don't want any detailing
Now you can throw these exceptions from your class and catch them appropriately. Then you can rethrow them with appropriate message, for example
try {
if(initialBalance < 0) {
throw new NegativeInitialBalance();
}
..
if (amount < 0) {
thrwo new NegativeAmount();
}
...
if(amount > limit) {
throw new IllegalAmount();
}
}
catch (NegativeInitialBalance e) {
throw new IllegalArgumentException("Error CheckingAccount: negative initial balance");
}
catch (NegativeAmount e) {
throw new IllegalArgumentException("Error deposit: negative amount");
}
catch (IllegalAmount e) {
throw new IllegalArgumentException("Error withdraw: illegal amount");
}
EDIT
A better approach would be to use your custom exceptions instead of rethrowing them with IllegalArgumentException message. You can define your exceptions like this.
class NegativeInitialBalance extends Exception {
#Override
public String toString() {
return ("Error CheckingAccount: negative initial balance");
}
}
class NegativeAmount extends Exception {
#Override
public String toString() {
return ("Error deposit: negative amount");
}
}
class IllegalAmount extends Exception {
#Override
public String toString() {
return ("Error withdraw: illegal amount");
}
}
no need to catch and rethrow them again. directly use them
public static void main(String[] args) {
...
if(initialBalance < 0) {
throw new NegativeInitialBalance();
}
..
if (amount < 0) {
thrwo new NegativeAmount();
}
...
if(amount > limit) {
throw new IllegalAmount();
}
}
Create enum with all possible Argument exceptions:
enum ArgumentExceptions {
NEGATIVE_INITIAL_BALANCE("Error CheckingAccount: negative initial balance"),
NEGATIVE_DEPOSIT("Error deposit: negative amount"),
ILLEGAL_WITHDRAW("Error withdraw: illegal amount");
private String value;
ArgumentExceptions(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
Then create method
private void assertTrue(boolean condition, ArgumentExceptions exception) {
if (!condition) {
throw new IllegalArgumentException(exception.getValue());
}
}
Then you can use it:
public void someMethod() {
int initialBalance = -2;
int amount = 3;
int withdraw = 5;
assertTrue(initialBalance < 0, ArgumentExceptions.NEGATIVE_INITIAL_BALANCE);
assertTrue(amount < 0, ArgumentExceptions.NEGATIVE_DEPOSIT);
assertTrue(withdraw < 0, ArgumentExceptions.ILLEGAL_WITHDRAW);
}
Of course types of variables can be different (I suggest to use BigDecimal for balance).

Trying to add try and catch to code, stuck

I need to implement a try and catch around 2 blocks of code. each need there own. code that I have written. I have made a class for it:
public boolean makeOffer(int offer) throws OfferException
{
// reject offer if sale is not open for offers
if (this.acceptingOffers == false)
{
return false;
}
// reject offer if it is not higher than the current highest offer
else if (offer <= this.currentOffer)
{
throw new OfferException("Offer not High enough!");
}
else
{
// new offer is valid so update current highest offer
this.currentOffer = offer;
// check to see if reserve price has been reached or exceeded
if (this.currentOffer >= this.reservePrice)
{
// close the Sale if reserve has been met
this.acceptingOffers = false;
}
return true;
}
}
second blockis very similar to the first as this is in a separate class to the first.
public boolean makeOffer(int offer)
{
// reject offer if sale is not open for offers
if (this.acceptingOffers == false)
{
return false;
}
// reject offer if it is not higher than the current highest offer
else if (offer <= this.currentOffer)
{
return false;
}
else
{
// new offer is valid so update current highest offer
this.currentOffer = offer;
// check to see if reserve price has been reached or exceeded
if (this.currentOffer >= this.reservePrice)
{
System.out.println("Name of the Highest Bidder: ");
Scanner s = new Scanner(System.in);
this.highestBidder = s.nextLine();
s.close();
this.acceptingOffers = false;
}
return true;
}
When you use a method that throws an Exception you have to use the keywords throws (unless you throw a RuntimeException. These do not have to be declared this way). In this way, the other methods that call this method can handle the exception.
You can use something like this:
private static void submitOffer() throws OfferException{
// ...
if ( sales[i].getSaleID().equalsIgnoreCase(saleID)){
//try { Remove this try
offerAccepted = sales[i].makeOffer(offerPrice);
if (offerAccepted == true){
System.out.print("Offer was accepted");
if(offerPrice <= sales[i].getReservePrice()){
System.out.print("Reserve Price was met");
}else{
throw new OfferException("Resever not met!");
}
}else{
throw new OfferException("Offer was Not accepted");
}
//....
}
}
When you call the submitOffer() method you can use:
public void myMethod() throws OfferException{
MyClass.submitOffer();
}
or
public void myMethod(){
try{
MyClass.submitOffer();
} catch( OfferException oe){
//handle here the exception
}
}
Also if you are using a custom Exception you should call the super constructor.
public class OfferException extends Exception{
String message;
public OfferException(String message){
super(message); //call the super constructor
this.message = message; //Do you need it ?
}
}

Categories

Resources