-
Notifications
You must be signed in to change notification settings - Fork 5
/
UniquenessValidationUtils.java
174 lines (156 loc) · 6.48 KB
/
UniquenessValidationUtils.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
/*
* © 2024. TU Dortmund University,
* Institute of Energy Systems, Energy Efficiency and Energy Economics,
* Research group Distribution grid planning and operation
*/
package edu.ie3.datamodel.utils.validation;
import edu.ie3.datamodel.exceptions.DuplicateEntitiesException;
import edu.ie3.datamodel.io.source.TimeSeriesMappingSource.MappingEntry;
import edu.ie3.datamodel.models.Entity;
import edu.ie3.datamodel.models.UniqueEntity;
import edu.ie3.datamodel.models.input.AssetInput;
import edu.ie3.datamodel.models.result.ResultEntity;
import edu.ie3.datamodel.models.timeseries.individual.TimeBasedValue;
import edu.ie3.datamodel.models.value.WeatherValue;
import edu.ie3.datamodel.utils.Try;
import edu.ie3.datamodel.utils.Try.*;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
/** Validation utils for checking the uniqueness of a given collection of entities. */
public class UniquenessValidationUtils extends ValidationUtils {
// default field set supplier
protected static FieldSetSupplier<UniqueEntity> uuidFieldSupplier =
entity -> Set.of(entity.getUuid());
protected static FieldSetSupplier<AssetInput> idFieldSupplier = e -> Set.of(e.getId());
protected static FieldSetSupplier<ResultEntity> resultFieldSupplier =
entity -> Set.of(entity.getTime(), entity.getInputModel());
protected static FieldSetSupplier<MappingEntry> mappingFieldSupplier =
entity -> Set.of(entity.participant());
protected static FieldSetSupplier<TimeBasedValue<WeatherValue>> timeBasedValueFieldSupplier =
entity -> Set.of(entity.getTime(), entity.getValue().getCoordinate());
/**
* Checks the uniqueness of a collection of {@link UniqueEntity}.
*
* @param entities to be checked
* @throws DuplicateEntitiesException if uniqueness is violated
*/
public static void checkUniqueEntities(Collection<? extends UniqueEntity> entities)
throws DuplicateEntitiesException {
checkUniqueness(entities, uuidFieldSupplier).getOrThrow();
}
/**
* Checks the uniqueness of a collection of {@link AssetInput}.
*
* @param entities to be checked
* @throws DuplicateEntitiesException if uniqueness is violated
*/
public static void checkAssetUniqueness(Collection<? extends AssetInput> entities)
throws DuplicateEntitiesException {
List<DuplicateEntitiesException> exceptions =
Try.getExceptions(
Try.ofVoid(() -> checkUniqueEntities(entities), DuplicateEntitiesException.class),
checkUniqueness(entities, idFieldSupplier));
if (!exceptions.isEmpty()) {
throw new DuplicateEntitiesException("AssetInput", exceptions);
}
}
/**
* Checks the uniqueness of a collection of {@link ResultEntity}.
*
* @param entities to be checked
* @throws DuplicateEntitiesException if uniqueness is violated
*/
public static void checkResultUniqueness(Collection<? extends ResultEntity> entities)
throws DuplicateEntitiesException {
checkUniqueness(entities, resultFieldSupplier).getOrThrow();
}
/**
* Checks the uniqueness of a collection of {@link MappingEntry}.
*
* @param entities to be checked
* @throws DuplicateEntitiesException if uniqueness is violated
*/
public static void checkMappingEntryUniqueness(Collection<? extends MappingEntry> entities)
throws DuplicateEntitiesException {
checkUniqueness(entities, mappingFieldSupplier).getOrThrow();
}
/**
* Checks the uniqueness of TimeBasedWeatherValues.
*
* @param entities to be checked
* @throws DuplicateEntitiesException if uniqueness is violated
*/
public static void checkWeatherUniqueness(Collection<TimeBasedValue<WeatherValue>> entities)
throws DuplicateEntitiesException {
checkUniqueness(entities, timeBasedValueFieldSupplier).getOrThrow();
}
/**
* Checking the uniqueness for a given {@link Entity}.
*
* @param entities to be checked
* @param supplier for the field set
* @return a try object
* @param <E> type of entity
*/
private static <E extends Entity> Try<Void, DuplicateEntitiesException> checkUniqueness(
Collection<? extends E> entities, FieldSetSupplier<E> supplier) {
if (entities.size() < 2) {
return Success.empty();
}
return entities.stream()
.findAny()
.map(
entity -> {
List<Set<Object>> elements = entities.stream().map(supplier::getFieldSets).toList();
Set<Set<Object>> uniqueElements = new HashSet<>(elements);
return Try.ofVoid(
elements.size() != uniqueElements.size(),
() -> buildDuplicationException(entity.getClass(), elements));
})
.orElse(Success.empty());
}
/**
* Method for building a {@link DuplicateEntitiesException}.
*
* @param entityClass class of the entity
* @param notUniqueElements list of not unique elements
* @return a {@link DuplicateEntitiesException}
*/
protected static DuplicateEntitiesException buildDuplicationException(
Class<? extends Entity> entityClass, List<Set<Object>> notUniqueElements) {
String fieldName =
notUniqueElements.get(0).stream()
.map(f -> f.getClass().getSimpleName())
.collect(Collectors.joining("-"));
// calculating the elements that violate the uniqueness
Map<Set<Object>, Long> counts =
notUniqueElements.stream()
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
String duplicates =
counts.entrySet().stream()
.filter(e -> e.getValue() > 1)
.map(m -> String.join("-", m.getKey().toString()))
.collect(Collectors.joining(",\n"));
return new DuplicateEntitiesException(
"'"
+ entityClass.getSimpleName()
+ "' entities with duplicated "
+ fieldName
+ " key, but different field "
+ "values found! Affected primary keys: "
+ duplicates);
}
/**
* Supplier for sets of fields that are required to be unique throughout the whole dataset. For
* each set, the combination of all members of the set must be unique. This means that individual
* members of the set are not required to be unique, but only their combination. A set can contain
* only a single member. In this case the single field must be unique throughout the dataset.
*
* @param <E> type of entity
*/
@FunctionalInterface
protected interface FieldSetSupplier<E extends Entity> {
Set<Object> getFieldSets(E entity);
}
}