in server/data/data-jmap/src/main/java/org/apache/james/jmap/api/filtering/impl/IncrementalRuleChange.java [38:125]
public static Optional<IncrementalRuleChange> ofDiff(FilteringAggregateId aggregateId, EventId eventId, List<Rule> before, List<Rule> after) {
ImmutableSet<Rule.Id> idsBefore = before.stream().map(Rule::getId).collect(ImmutableSet.toImmutableSet());
ImmutableSet<Rule.Id> idsAfter = after.stream().map(Rule::getId).collect(ImmutableSet.toImmutableSet());
ImmutableMap<Rule.Id, Rule> beforeIndexed = before.stream()
.collect(ImmutableMap.toImmutableMap(Rule::getId, rule -> rule));
ImmutableMap<Rule.Id, Rule> afterIndexed = after.stream()
.collect(ImmutableMap.toImmutableMap(Rule::getId, rule -> rule));
// Deleted elements appears in
ImmutableSet<Rule.Id> deleted = Sets.difference(idsBefore, idsAfter).immutableCopy();
List<Rule.Id> commonElements = ImmutableList.copyOf(Sets.intersection(idsBefore, idsAfter).immutableCopy());
ImmutableList<Rule.Id> idsAfterList = idsAfter.asList();
ImmutableList.Builder<Rule> updatedRules = ImmutableList.builder();
int prependedItems = 0;
int postPendedItems = 0;
boolean inPrepended = true;
boolean inCommonSection = false;
boolean inPostpended = false;
int position = 0;
while (position < idsAfter.size()) {
Rule.Id id = idsAfterList.get(position);
if (inPrepended) {
if (commonElements.contains(id)) {
inPrepended = false;
inCommonSection = true;
continue;
} else {
prependedItems++;
position++;
continue;
}
}
if (inPostpended) {
if (commonElements.contains(id)) {
return Optional.empty();
} else {
postPendedItems++;
position++;
continue;
}
}
if (inCommonSection) {
if (!commonElements.contains(id)) {
inCommonSection = false;
inPostpended = true;
continue;
}
int positionInCommonElements = position - prependedItems;
if (positionInCommonElements > commonElements.size()) {
// Safeguard
return Optional.empty();
}
if (!commonElements.get(positionInCommonElements).equals(id)) {
// Order of commons items changed
return Optional.empty();
}
if (!beforeIndexed.get(id).equals(afterIndexed.get(id))) {
updatedRules.add(afterIndexed.get(id));
position++;
continue;
}
// All fine
position++;
continue;
}
throw new RuntimeException("Unexpected status");
}
ImmutableList<Rule> preprended = idsAfter.stream()
.limit(prependedItems)
.map(afterIndexed::get)
.collect(ImmutableList.toImmutableList());
ImmutableList<Rule> postPended = idsAfter.asList()
.reverse()
.stream()
.limit(postPendedItems)
.map(afterIndexed::get)
.collect(ImmutableList.toImmutableList())
.reverse();
return Optional.of(new IncrementalRuleChange(aggregateId, eventId,
preprended, postPended, deleted, updatedRules.build()));
}