Skip to content

Commit d77ab6f

Browse files
committed
add
1 parent 525cda1 commit d77ab6f

File tree

8 files changed

+162
-214
lines changed

8 files changed

+162
-214
lines changed
Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,20 @@
11
package hexlet.code;
22

3-
import hexlet.code.schemas.StringSchema;
4-
import hexlet.code.schemas.NumberSchema;
53
import hexlet.code.schemas.MapSchema;
4+
import hexlet.code.schemas.NumberSchema;
5+
import hexlet.code.schemas.StringSchema;
66

77
public class Validator {
8-
public StringSchema string() {
8+
9+
public static StringSchema string() {
910
return new StringSchema();
1011
}
1112

12-
public NumberSchema number() {
13+
public static NumberSchema number() {
1314
return new NumberSchema();
1415
}
1516

16-
public MapSchema map() {
17+
public static MapSchema map() {
1718
return new MapSchema();
1819
}
1920
}
Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,34 @@
11
package hexlet.code.schemas;
22

3+
import java.util.LinkedHashMap;
4+
import java.util.Map;
5+
import java.util.Objects;
36
import java.util.function.Predicate;
47

5-
public abstract class BaseSchema<T> {
6-
protected boolean required;
7-
protected Predicate<Object> validator = value -> true;
8+
public class BaseSchema<T> {
9+
protected Map<String, Predicate<T>> checks = new LinkedHashMap<>();
10+
protected final String isRequired = "required";
811

9-
public T required() {
10-
this.required = true;
11-
this.validator = this.validator.and(value -> value != null);
12-
return (T) this;
12+
protected final void addCheck(String name, Predicate<T> predicate) {
13+
checks.put(name, predicate);
1314
}
1415

15-
public boolean isValid(Object value) {
16-
if (!required && value == null) {
17-
return true;
16+
public final boolean isValid(T t) {
17+
if (checks.containsKey(isRequired)) {
18+
if (!checks.get(isRequired).test(t)) {
19+
return false;
20+
}
21+
} else {
22+
if (Objects.isNull(t)) {
23+
return true;
24+
}
1825
}
19-
return validator.test(value);
20-
}
21-
22-
protected void addCondition(Predicate<Object> condition) {
23-
this.validator = this.validator.and(condition);
26+
for (var check : checks.keySet()) {
27+
var predicate = checks.get(check);
28+
if (!predicate.test(t)) {
29+
return false;
30+
}
31+
}
32+
return true;
2433
}
2534
}

app/src/main/java/hexlet/code/schemas/MapSchema.java

Lines changed: 20 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,36 +2,34 @@
22

33
import java.util.HashMap;
44
import java.util.Map;
5+
import java.util.Objects;
6+
import java.util.function.Predicate;
57

6-
public class MapSchema extends BaseSchema<MapSchema> {
7-
private Integer size;
8-
private Map<String, BaseSchema<?>> shapeSchemas;
8+
public final class MapSchema<T> extends BaseSchema<Map> {
9+
private final String shape = "shape";
10+
private final String sizeOfMap = "size";
911

10-
public MapSchema sizeof(int newSize) {
11-
this.size = newSize;
12-
addCondition(value -> ((Map<?, ?>) value).size() == size);
12+
public MapSchema required() {
13+
Predicate<Map> requiredPredicate = e -> !Objects.isNull(e) && (e instanceof HashMap);
14+
this.addCheck(isRequired, requiredPredicate);
1315
return this;
1416
}
1517

16-
public MapSchema shape(Map<String, ? extends BaseSchema<?>> schemas) {
17-
this.shapeSchemas = new HashMap<>(schemas);
18-
addCondition(value -> {
19-
Map<?, ?> mapValue = (Map<?, ?>) value;
20-
for (Map.Entry<String, BaseSchema<?>> entry : shapeSchemas.entrySet()) {
21-
String key = entry.getKey();
22-
BaseSchema<?> schema = entry.getValue();
23-
if (!mapValue.containsKey(key) || !schema.isValid(mapValue.get(key))) {
24-
return false;
25-
}
26-
}
27-
return true;
28-
});
18+
public MapSchema sizeof(int size) {
19+
Predicate<Map> sizeOfPredicate = e -> e.size() == size;
20+
this.addCheck(sizeOfMap, sizeOfPredicate);
2921
return this;
3022
}
3123

32-
@Override
33-
public MapSchema required() {
34-
super.required();
24+
public <T> MapSchema shape(Map<String, BaseSchema<T>> schemas) {
25+
addCheck(shape,
26+
map -> {
27+
return schemas.entrySet().stream().allMatch(e -> {
28+
var k = map.get(e.getKey());
29+
var schema = e.getValue();
30+
return schema.isValid((T) k);
31+
});
32+
});
3533
return this;
3634
}
3735
}
Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,33 @@
11
package hexlet.code.schemas;
22

3-
public class NumberSchema extends BaseSchema<NumberSchema> {
4-
public NumberSchema positive() {
5-
addCondition(value -> ((Integer) value) > 0);
3+
import java.util.Objects;
4+
import java.util.function.Predicate;
5+
6+
public final class NumberSchema extends BaseSchema<Integer> {
7+
private final String numberIsPositive = "positive";
8+
private final String numberInRange = "range";
9+
10+
public NumberSchema required() {
11+
Predicate<Integer> requiredPredicate = e -> !Objects.isNull(e);
12+
this.addCheck(isRequired, requiredPredicate);
613
return this;
714
}
815

9-
public NumberSchema range(int min, int max) {
10-
addCondition(value -> ((Integer) value) >= min && ((Integer) value) <= max);
16+
public NumberSchema positive() {
17+
Predicate<Integer> positive = e -> {
18+
if (e == 0) {
19+
return false;
20+
} else {
21+
return e > 0;
22+
}
23+
};
24+
addCheck(numberIsPositive, positive);
1125
return this;
1226
}
1327

14-
@Override
15-
public NumberSchema required() {
16-
super.required();
28+
public NumberSchema range(Integer a, Integer b) {
29+
Predicate<Integer> rangePredicate = e -> e >= a && e <= b;
30+
addCheck(numberInRange, rangePredicate);
1731
return this;
1832
}
1933
}
Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,27 @@
11
package hexlet.code.schemas;
22

3-
public class StringSchema extends BaseSchema<StringSchema> {
4-
public StringSchema minLength(int length) {
5-
addCondition(value -> ((String) value).length() >= length);
3+
import java.util.Objects;
4+
import java.util.function.Predicate;
5+
6+
public final class StringSchema extends BaseSchema<String> {
7+
private final String minLengthCheckName = "minLength";
8+
private final String containsCheckName = "contains";
9+
10+
public StringSchema required() {
11+
Predicate<String> requiredPredicate = e -> !Objects.isNull(e) && !e.equals("");
12+
this.addCheck(isRequired, requiredPredicate);
613
return this;
714
}
815

9-
public StringSchema contains(String substring) {
10-
addCondition(value -> ((String) value).contains(substring));
16+
public StringSchema minLength(int number) {
17+
Predicate<String> isMinLength = e -> e.length() >= number;
18+
this.addCheck(minLengthCheckName, isMinLength);
1119
return this;
1220
}
1321

14-
@Override
15-
public StringSchema required() {
16-
super.required();
17-
addCondition(value -> !((String) value).isEmpty());
22+
public StringSchema contains(String str) {
23+
Predicate<String> containsPredicate = e -> e.contains(str);
24+
this.addCheck(containsCheckName, containsPredicate);
1825
return this;
1926
}
2027
}
Lines changed: 35 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,53 @@
1-
package hexlet.code;
1+
package hexlet.code.schemas;
22

3-
import hexlet.code.schemas.MapSchema;
4-
import hexlet.code.schemas.BaseSchema;
53
import org.junit.jupiter.api.Test;
64
import java.util.HashMap;
75
import java.util.Map;
8-
6+
import hexlet.code.Validator;
97
import static org.junit.jupiter.api.Assertions.assertFalse;
108
import static org.junit.jupiter.api.Assertions.assertTrue;
119

1210
public class MapSchemaTest {
1311

1412
@Test
15-
public void testShapeValidation() {
16-
Validator validator = new Validator();
17-
MapSchema schema = validator.map();
18-
19-
Map<String, BaseSchema<?>> schemas = new HashMap<>();
20-
schemas.put("firstName", validator.string().required());
21-
schemas.put("lastName", validator.string().required().minLength(2));
22-
schemas.put("age", validator.number().positive());
23-
24-
schema.shape(schemas);
25-
26-
Map<String, Object> human1 = new HashMap<>();
27-
human1.put("firstName", "John");
28-
human1.put("lastName", "Smith");
29-
human1.put("age", 30);
30-
assertTrue(schema.isValid(human1));
31-
32-
Map<String, Object> human2 = new HashMap<>();
33-
human2.put("firstName", "John");
34-
human2.put("lastName", null);
35-
human2.put("age", 30);
36-
assertFalse(schema.isValid(human2));
13+
public void testRequired() {
14+
MapSchema mapSchema = new MapSchema().required();
15+
16+
assertTrue(mapSchema.isValid(new HashMap<>()));
17+
assertFalse(mapSchema.isValid(null));
3718
}
3819

3920
@Test
40-
public void testMissingKeys() {
41-
Validator validator = new Validator();
42-
MapSchema schema = validator.map();
21+
public void testSizeof() {
22+
MapSchema mapSchema = new MapSchema().sizeof(2);
23+
24+
Map<String, Object> map = new HashMap<>();
25+
map.put("key1", "value1");
26+
map.put("key2", "value2");
27+
28+
assertTrue(mapSchema.isValid(map));
29+
30+
map.put("key3", "value3");
31+
assertFalse(mapSchema.isValid(map));
32+
}
33+
34+
@Test
35+
public void testShape() {
36+
MapSchema mapSchema = new MapSchema().shape(Map.of(
37+
"name", Validator.string().required().minLength(3),
38+
"age", Validator.number().required().range(18, 99)
39+
));
40+
41+
Map<String, Object> validData = new HashMap<>();
42+
validData.put("name", "John");
43+
validData.put("age", 25);
4344

44-
Map<String, BaseSchema<?>> schemas = new HashMap<>();
45-
schemas.put("firstName", validator.string().required());
46-
schemas.put("lastName", validator.string().required());
45+
assertTrue(mapSchema.isValid(validData));
4746

48-
schema.shape(schemas);
47+
Map<String, Object> invalidData = new HashMap<>();
48+
invalidData.put("name", "Jo");
49+
invalidData.put("age", 17);
4950

50-
Map<String, Object> human = new HashMap<>();
51-
human.put("firstName", "John");
52-
assertFalse(schema.isValid(human));
51+
assertFalse(mapSchema.isValid(invalidData));
5352
}
5453
}

0 commit comments

Comments
 (0)