public static Optional ofDiff()

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()));
    }