Skip to content

Commit efb5b2e

Browse files
authored
Implement validator using Visitor pattern and move Customer to a dedicated package (#71)
1 parent ab42078 commit efb5b2e

22 files changed

+149
-22
lines changed

DesignPatterns/src/main/java/pl/mperor/lab/java/design/pattern/behavioral/visitor/CorporateCustomer.java

Lines changed: 0 additions & 4 deletions
This file was deleted.

DesignPatterns/src/main/java/pl/mperor/lab/java/design/pattern/behavioral/visitor/Letter.java

Lines changed: 0 additions & 4 deletions
This file was deleted.

DesignPatterns/src/main/java/pl/mperor/lab/java/design/pattern/behavioral/visitor/PremiumCustomer.java

Lines changed: 0 additions & 4 deletions
This file was deleted.

DesignPatterns/src/main/java/pl/mperor/lab/java/design/pattern/behavioral/visitor/RegularCustomer.java

Lines changed: 0 additions & 4 deletions
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package pl.mperor.lab.java.design.pattern.behavioral.visitor.customer;
2+
3+
record CorporateCustomer() implements Customer {
4+
}

DesignPatterns/src/main/java/pl/mperor/lab/java/design/pattern/behavioral/visitor/Customer.java renamed to DesignPatterns/src/main/java/pl/mperor/lab/java/design/pattern/behavioral/visitor/customer/Customer.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package pl.mperor.lab.java.design.pattern.behavioral.visitor;
1+
package pl.mperor.lab.java.design.pattern.behavioral.visitor.customer;
22

33
public sealed interface Customer permits CorporateCustomer, RegularCustomer, PremiumCustomer {
44

DesignPatterns/src/main/java/pl/mperor/lab/java/design/pattern/behavioral/visitor/CustomerVisitor.java renamed to DesignPatterns/src/main/java/pl/mperor/lab/java/design/pattern/behavioral/visitor/customer/CustomerVisitor.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package pl.mperor.lab.java.design.pattern.behavioral.visitor;
1+
package pl.mperor.lab.java.design.pattern.behavioral.visitor.customer;
22

33
public interface CustomerVisitor<T> {
44

DesignPatterns/src/main/java/pl/mperor/lab/java/design/pattern/behavioral/visitor/DiscountLevel.java renamed to DesignPatterns/src/main/java/pl/mperor/lab/java/design/pattern/behavioral/visitor/customer/DiscountLevel.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package pl.mperor.lab.java.design.pattern.behavioral.visitor;
1+
package pl.mperor.lab.java.design.pattern.behavioral.visitor.customer;
22

33
enum DiscountLevel {
44
BRONZE(10),

DesignPatterns/src/main/java/pl/mperor/lab/java/design/pattern/behavioral/visitor/DiscountProvider.java renamed to DesignPatterns/src/main/java/pl/mperor/lab/java/design/pattern/behavioral/visitor/customer/DiscountProvider.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package pl.mperor.lab.java.design.pattern.behavioral.visitor;
1+
package pl.mperor.lab.java.design.pattern.behavioral.visitor.customer;
22

33
public class DiscountProvider implements CustomerVisitor<DiscountLevel> {
44

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package pl.mperor.lab.java.design.pattern.behavioral.visitor;
1+
package pl.mperor.lab.java.design.pattern.behavioral.visitor.customer;
22

33
public class InvitationLetterGenerator implements CustomerVisitor<Letter> {
44

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package pl.mperor.lab.java.design.pattern.behavioral.visitor.customer;
2+
3+
record Letter(String content) {
4+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package pl.mperor.lab.java.design.pattern.behavioral.visitor.customer;
2+
3+
record PremiumCustomer() implements Customer {
4+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package pl.mperor.lab.java.design.pattern.behavioral.visitor.customer;
2+
3+
record RegularCustomer() implements Customer {
4+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package pl.mperor.lab.java.design.pattern.behavioral.visitor.validator;
2+
3+
import java.util.ArrayList;
4+
import java.util.List;
5+
6+
class AggregatingValidationExceptionHandler implements ValidationExceptionHandler {
7+
8+
private List<ValidationException> errors = new ArrayList<>();
9+
10+
@Override
11+
public void handle(ValidationException exception) {
12+
errors.add(exception);
13+
}
14+
15+
boolean hasErrors() {
16+
return !errors.isEmpty();
17+
}
18+
19+
public List<ValidationException> getErrors() {
20+
return List.copyOf(errors);
21+
}
22+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package pl.mperor.lab.java.design.pattern.behavioral.visitor.validator;
2+
3+
import java.util.regex.Pattern;
4+
5+
record Email(String address) {
6+
7+
public Email {
8+
test(address, new ThrowingValidationExceptionHandler());
9+
}
10+
11+
public static void test(String address, ValidationExceptionHandler handler) {
12+
new EmailValidator().validate(address, handler);
13+
}
14+
15+
static class EmailValidator implements Validator<String> {
16+
17+
public static final Pattern FORMAT_PATTERN = Pattern.compile("^[a-zA-Z0-9+_.-]+@[a-zA-Z0-9.-]+$");
18+
19+
@Override
20+
public void validate(String address, ValidationExceptionHandler validationExceptionHandler) {
21+
if (FORMAT_PATTERN.asMatchPredicate().negate().test(address)) {
22+
validationExceptionHandler.handle(new InvalidFormatException());
23+
}
24+
}
25+
}
26+
27+
static class InvalidFormatException extends ValidationException {
28+
}
29+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package pl.mperor.lab.java.design.pattern.behavioral.visitor.validator;
2+
3+
record Password(String value) {
4+
5+
public Password {
6+
Password.test(value, new ThrowingValidationExceptionHandler());
7+
}
8+
9+
public static void test(String password, ValidationExceptionHandler validationExceptionHandler) {
10+
new PasswordValidator().validate(password, validationExceptionHandler);
11+
}
12+
13+
static class PasswordValidator implements Validator<String> {
14+
15+
@Override
16+
public void validate(String password, ValidationExceptionHandler validationExceptionHandler) {
17+
if (password.length() < 8 || password.length() > 16) {
18+
validationExceptionHandler.handle(new InvalidLengthException());
19+
}
20+
}
21+
}
22+
23+
static class InvalidLengthException extends ValidationException {
24+
}
25+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package pl.mperor.lab.java.design.pattern.behavioral.visitor.validator;
2+
3+
class ThrowingValidationExceptionHandler implements ValidationExceptionHandler{
4+
5+
@Override
6+
public void handle(ValidationException exception) {
7+
throw exception;
8+
}
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package pl.mperor.lab.java.design.pattern.behavioral.visitor.validator;
2+
3+
abstract class ValidationException extends RuntimeException {
4+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package pl.mperor.lab.java.design.pattern.behavioral.visitor.validator;
2+
3+
interface ValidationExceptionHandler {
4+
5+
void handle(ValidationException exception);
6+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package pl.mperor.lab.java.design.pattern.behavioral.visitor.validator;
2+
3+
interface Validator<T> {
4+
5+
void validate(T toValid, ValidationExceptionHandler validationExceptionHandler);
6+
}

DesignPatterns/src/test/java/pl/mperor/lab/java/design/pattern/behavioral/visitor/CustomerVisitorTest.java renamed to DesignPatterns/src/test/java/pl/mperor/lab/java/design/pattern/behavioral/visitor/customer/CustomerVisitorTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package pl.mperor.lab.java.design.pattern.behavioral.visitor;
1+
package pl.mperor.lab.java.design.pattern.behavioral.visitor.customer;
22

33
import org.junit.jupiter.api.Assertions;
44
import org.junit.jupiter.api.Test;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package pl.mperor.lab.java.design.pattern.behavioral.visitor.validator;
2+
3+
import org.junit.jupiter.api.Assertions;
4+
import org.junit.jupiter.api.Test;
5+
6+
class ValidatorVisitorTest {
7+
8+
@Test
9+
public void testValidatePasswordAndEmailWithExceptionAggregation() {
10+
var aggregationHandler = new AggregatingValidationExceptionHandler();
11+
Password.test("xyz", aggregationHandler);
12+
Email.test("user1$gmail.com", aggregationHandler);
13+
Assertions.assertTrue(aggregationHandler.hasErrors());
14+
Assertions.assertEquals(aggregationHandler.getErrors().size(), 2);
15+
}
16+
17+
@Test
18+
public void testValidatePasswordAndEmailWithExceptionThrowing() {
19+
Assertions.assertThrows(Password.InvalidLengthException.class, () -> new Password("xyz"));
20+
Assertions.assertThrows(Email.InvalidFormatException.class, () -> new Email("user1$gmail.com"));
21+
22+
var throwingHandler = new ThrowingValidationExceptionHandler();
23+
Assertions.assertThrows(Password.InvalidLengthException.class, () -> Password.test("xyz", throwingHandler));
24+
Assertions.assertThrows(Email.InvalidFormatException.class, () -> Email.test("user1$gmail.com", throwingHandler));
25+
}
26+
}

0 commit comments

Comments
 (0)