This is an automated email from the ASF dual-hosted git repository. btellier pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/james-project.git
commit 51351f273ae268c05937a4d869572b2f19a30e82 Author: Rene Cordier <[email protected]> AuthorDate: Tue Mar 23 11:59:13 2021 +0700 JAMES-3331 Add filter versioning --- .../james/eventsourcing/eventstore/History.scala | 4 ++ .../jmap/api/filtering/FilteringManagement.java | 2 +- .../{FilteringManagement.java => Rules.java} | 44 ++++++++++++++++------ .../{FilteringManagement.java => Version.java} | 39 +++++++++++++------ .../impl/EventSourcingFilteringManagement.java | 8 +++- .../api/filtering/impl/FilteringAggregate.java | 8 +++- .../api/filtering/FilteringManagementContract.java | 27 +++++++------ .../james/jmap/api/filtering/RulesTest.java} | 26 ++++--------- .../james/jmap/api/filtering/VersionTest.java} | 26 ++++--------- .../james/jmap/draft/methods/GetFilterMethod.java | 6 +-- .../james/jmap/mailet/filter/JMAPFiltering.java | 11 ++---- 11 files changed, 113 insertions(+), 88 deletions(-) diff --git a/event-sourcing/event-store-api/src/main/scala/org/apache/james/eventsourcing/eventstore/History.scala b/event-sourcing/event-store-api/src/main/scala/org/apache/james/eventsourcing/eventstore/History.scala index ad03e82..9eeff9d 100644 --- a/event-sourcing/event-store-api/src/main/scala/org/apache/james/eventsourcing/eventstore/History.scala +++ b/event-sourcing/event-store-api/src/main/scala/org/apache/james/eventsourcing/eventstore/History.scala @@ -20,8 +20,10 @@ package org.apache.james.eventsourcing.eventstore import org.apache.james.eventsourcing.{Event, EventId} +import java.util.Optional import scala.annotation.varargs import scala.jdk.CollectionConverters._ +import scala.jdk.OptionConverters._ object History { def empty: History = new History(Nil) @@ -48,6 +50,8 @@ final case class History private(events: List[Event]) { .map(event => event.eventId) .maxOption + def getVersionAsJava: Optional[EventId] = getVersion.toJava + def getEvents:List[Event] = events def getEventsJava:java.util.List[Event] = events.asJava diff --git a/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/filtering/FilteringManagement.java b/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/filtering/FilteringManagement.java index 3305ead..ebff33c 100644 --- a/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/filtering/FilteringManagement.java +++ b/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/filtering/FilteringManagement.java @@ -39,6 +39,6 @@ public interface FilteringManagement { return defineRulesForUser(username, ImmutableList.of()); } - Publisher<Rule> listRulesForUser(Username username); + Publisher<Rules> listRulesForUser(Username username); } diff --git a/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/filtering/FilteringManagement.java b/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/filtering/Rules.java similarity index 56% copy from server/data/data-jmap/src/main/java/org/apache/james/jmap/api/filtering/FilteringManagement.java copy to server/data/data-jmap/src/main/java/org/apache/james/jmap/api/filtering/Rules.java index 3305ead..55d7897 100644 --- a/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/filtering/FilteringManagement.java +++ b/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/filtering/Rules.java @@ -19,26 +19,48 @@ package org.apache.james.jmap.api.filtering; -import java.util.Arrays; import java.util.List; +import java.util.Objects; -import org.apache.james.core.Username; -import org.reactivestreams.Publisher; +import com.google.common.base.MoreObjects; -import com.google.common.collect.ImmutableList; +public class Rules { + private final List<Rule> rules; + private final Version version; -public interface FilteringManagement { + public Rules(List<Rule> rules, Version version) { + this.rules = rules; + this.version = version; + } - Publisher<Void> defineRulesForUser(Username username, List<Rule> rules); + public List<Rule> getRules() { + return rules; + } - default Publisher<Void> defineRulesForUser(Username username, Rule... rules) { - return defineRulesForUser(username, Arrays.asList(rules)); + public Version getVersion() { + return version; } - default Publisher<Void> clearRulesForUser(Username username) { - return defineRulesForUser(username, ImmutableList.of()); + @Override + public final boolean equals(Object o) { + if (o instanceof Rules) { + Rules that = (Rules) o; + return Objects.equals(this.rules, that.rules) + && Objects.equals(this.version, that.version); + } + return false; } - Publisher<Rule> listRulesForUser(Username username); + @Override + public final int hashCode() { + return Objects.hash(rules, version); + } + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("rules", rules) + .add("version", version) + .toString(); + } } diff --git a/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/filtering/FilteringManagement.java b/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/filtering/Version.java similarity index 60% copy from server/data/data-jmap/src/main/java/org/apache/james/jmap/api/filtering/FilteringManagement.java copy to server/data/data-jmap/src/main/java/org/apache/james/jmap/api/filtering/Version.java index 3305ead..25c37b1 100644 --- a/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/filtering/FilteringManagement.java +++ b/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/filtering/Version.java @@ -19,26 +19,41 @@ package org.apache.james.jmap.api.filtering; -import java.util.Arrays; -import java.util.List; +import java.util.Objects; -import org.apache.james.core.Username; -import org.reactivestreams.Publisher; +import com.google.common.base.MoreObjects; -import com.google.common.collect.ImmutableList; +public class Version { + public static final Version INITIAL = new Version(-1); -public interface FilteringManagement { + private final int version; - Publisher<Void> defineRulesForUser(Username username, List<Rule> rules); + public Version(int version) { + this.version = version; + } - default Publisher<Void> defineRulesForUser(Username username, Rule... rules) { - return defineRulesForUser(username, Arrays.asList(rules)); + @Override + public final boolean equals(Object o) { + if (o instanceof Version) { + Version that = (Version) o; + return Objects.equals(this.version, that.version); + } + return false; } - default Publisher<Void> clearRulesForUser(Username username) { - return defineRulesForUser(username, ImmutableList.of()); + @Override + public final int hashCode() { + return Objects.hash(version); } - Publisher<Rule> listRulesForUser(Username username); + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("version", version) + .toString(); + } + public String asString() { + return String.valueOf(version); + } } diff --git a/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/filtering/impl/EventSourcingFilteringManagement.java b/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/filtering/impl/EventSourcingFilteringManagement.java index 485c194..c365d5e 100644 --- a/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/filtering/impl/EventSourcingFilteringManagement.java +++ b/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/filtering/impl/EventSourcingFilteringManagement.java @@ -29,9 +29,12 @@ import org.apache.james.eventsourcing.Subscriber; import org.apache.james.eventsourcing.eventstore.EventStore; import org.apache.james.jmap.api.filtering.FilteringManagement; import org.apache.james.jmap.api.filtering.Rule; +import org.apache.james.jmap.api.filtering.Rules; +import org.apache.james.jmap.api.filtering.Version; import org.reactivestreams.Publisher; import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import reactor.core.publisher.Mono; @@ -58,12 +61,13 @@ public class EventSourcingFilteringManagement implements FilteringManagement { } @Override - public Publisher<Rule> listRulesForUser(Username username) { + public Publisher<Rules> listRulesForUser(Username username) { Preconditions.checkNotNull(username); FilteringAggregateId aggregateId = new FilteringAggregateId(username); return Mono.from(eventStore.getEventsOfAggregate(aggregateId)) - .flatMapIterable(history -> FilteringAggregate.load(aggregateId, history).listRules()); + .map(history -> FilteringAggregate.load(aggregateId, history).listRules()) + .defaultIfEmpty(new Rules(ImmutableList.of(), Version.INITIAL)); } } diff --git a/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/filtering/impl/FilteringAggregate.java b/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/filtering/impl/FilteringAggregate.java index 1a4772f..1a859c6 100644 --- a/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/filtering/impl/FilteringAggregate.java +++ b/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/filtering/impl/FilteringAggregate.java @@ -22,8 +22,11 @@ package org.apache.james.jmap.api.filtering.impl; import java.util.List; import org.apache.james.eventsourcing.Event; +import org.apache.james.eventsourcing.EventId; import org.apache.james.eventsourcing.eventstore.History; import org.apache.james.jmap.api.filtering.Rule; +import org.apache.james.jmap.api.filtering.Rules; +import org.apache.james.jmap.api.filtering.Version; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; @@ -78,8 +81,9 @@ public class FilteringAggregate { return uniqueIdCount == rules.size(); } - public List<Rule> listRules() { - return state.rules; + public Rules listRules() { + return new Rules(state.rules, + history.getVersionAsJava().map(EventId::value).map(Version::new).orElse(Version.INITIAL)); } private void apply(Event event) { diff --git a/server/data/data-jmap/src/test/java/org/apache/james/jmap/api/filtering/FilteringManagementContract.java b/server/data/data-jmap/src/test/java/org/apache/james/jmap/api/filtering/FilteringManagementContract.java index 6dcf8c6..913df44 100644 --- a/server/data/data-jmap/src/test/java/org/apache/james/jmap/api/filtering/FilteringManagementContract.java +++ b/server/data/data-jmap/src/test/java/org/apache/james/jmap/api/filtering/FilteringManagementContract.java @@ -35,6 +35,8 @@ import org.apache.james.eventsourcing.eventstore.EventStore; import org.apache.james.jmap.api.filtering.impl.EventSourcingFilteringManagement; import org.junit.jupiter.api.Test; +import com.google.common.collect.ImmutableList; + import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @@ -49,8 +51,8 @@ public interface FilteringManagementContract { @Test default void listingRulesForUnknownUserShouldReturnEmptyList(EventStore eventStore) { - assertThat(Flux.from(instantiateFilteringManagement(eventStore).listRulesForUser(USERNAME)).toStream()) - .isEmpty(); + assertThat(Mono.from(instantiateFilteringManagement(eventStore).listRulesForUser(USERNAME)).block()) + .isEqualTo(new Rules(ImmutableList.of(), new Version(-1))); } @Test @@ -66,8 +68,8 @@ public interface FilteringManagementContract { Mono.from(testee.defineRulesForUser(USERNAME, RULE_1, RULE_2)).block(); - assertThat(Flux.from(testee.listRulesForUser(USERNAME)).toStream()) - .containsExactly(RULE_1, RULE_2); + assertThat(Mono.from(testee.listRulesForUser(USERNAME)).block()) + .isEqualTo(new Rules(ImmutableList.of(RULE_1, RULE_2), new Version(0))); } @Test @@ -77,8 +79,8 @@ public interface FilteringManagementContract { Mono.from(testee.defineRulesForUser(USERNAME, RULE_1, RULE_2)).block(); Mono.from(testee.defineRulesForUser(USERNAME, RULE_2, RULE_1)).block(); - assertThat(Flux.from(testee.listRulesForUser(USERNAME)).toStream()) - .containsExactly(RULE_2, RULE_1); + assertThat(Mono.from(testee.listRulesForUser(USERNAME)).block()) + .isEqualTo(new Rules(ImmutableList.of(RULE_2, RULE_1), new Version(1))); } @Test @@ -111,8 +113,9 @@ public interface FilteringManagementContract { FilteringManagement testee = instantiateFilteringManagement(eventStore); Mono.from(testee.defineRulesForUser(USERNAME, RULE_3, RULE_2, RULE_1)).block(); - assertThat(Flux.from(testee.listRulesForUser(USERNAME)).toStream()) - .containsExactly(RULE_3, RULE_2, RULE_1); + + assertThat(Mono.from(testee.listRulesForUser(USERNAME)).block()) + .isEqualTo(new Rules(ImmutableList.of(RULE_3, RULE_2, RULE_1), new Version(0))); } @Test @@ -122,7 +125,8 @@ public interface FilteringManagementContract { Mono.from(testee.defineRulesForUser(USERNAME, RULE_3, RULE_2, RULE_1)).block(); Mono.from(testee.clearRulesForUser(USERNAME)).block(); - assertThat(Flux.from(testee.listRulesForUser(USERNAME)).toStream()).isEmpty(); + assertThat(Mono.from(testee.listRulesForUser(USERNAME)).block()) + .isEqualTo(new Rules(ImmutableList.of(), new Version(1))); } @Test @@ -131,8 +135,9 @@ public interface FilteringManagementContract { Mono.from(testee.defineRulesForUser(USERNAME, RULE_FROM, RULE_RECIPIENT, RULE_SUBJECT, RULE_TO, RULE_1)).block(); - assertThat(Flux.from(testee.listRulesForUser(USERNAME)).toStream()) - .containsExactly(RULE_FROM, RULE_RECIPIENT, RULE_SUBJECT, RULE_TO, RULE_1); + + assertThat(Mono.from(testee.listRulesForUser(USERNAME)).block()) + .isEqualTo(new Rules(ImmutableList.of(RULE_FROM, RULE_RECIPIENT, RULE_SUBJECT, RULE_TO, RULE_1), new Version(0))); } } \ No newline at end of file diff --git a/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/filtering/FilteringManagement.java b/server/data/data-jmap/src/test/java/org/apache/james/jmap/api/filtering/RulesTest.java similarity index 66% copy from server/data/data-jmap/src/main/java/org/apache/james/jmap/api/filtering/FilteringManagement.java copy to server/data/data-jmap/src/test/java/org/apache/james/jmap/api/filtering/RulesTest.java index 3305ead..8c77696 100644 --- a/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/filtering/FilteringManagement.java +++ b/server/data/data-jmap/src/test/java/org/apache/james/jmap/api/filtering/RulesTest.java @@ -19,26 +19,14 @@ package org.apache.james.jmap.api.filtering; -import java.util.Arrays; -import java.util.List; +import org.junit.jupiter.api.Test; -import org.apache.james.core.Username; -import org.reactivestreams.Publisher; +import nl.jqno.equalsverifier.EqualsVerifier; -import com.google.common.collect.ImmutableList; - -public interface FilteringManagement { - - Publisher<Void> defineRulesForUser(Username username, List<Rule> rules); - - default Publisher<Void> defineRulesForUser(Username username, Rule... rules) { - return defineRulesForUser(username, Arrays.asList(rules)); +class RulesTest { + @Test + void shouldMatchBeanContract() { + EqualsVerifier.forClass(Rules.class) + .verify(); } - - default Publisher<Void> clearRulesForUser(Username username) { - return defineRulesForUser(username, ImmutableList.of()); - } - - Publisher<Rule> listRulesForUser(Username username); - } diff --git a/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/filtering/FilteringManagement.java b/server/data/data-jmap/src/test/java/org/apache/james/jmap/api/filtering/VersionTest.java similarity index 66% copy from server/data/data-jmap/src/main/java/org/apache/james/jmap/api/filtering/FilteringManagement.java copy to server/data/data-jmap/src/test/java/org/apache/james/jmap/api/filtering/VersionTest.java index 3305ead..18dce62 100644 --- a/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/filtering/FilteringManagement.java +++ b/server/data/data-jmap/src/test/java/org/apache/james/jmap/api/filtering/VersionTest.java @@ -19,26 +19,14 @@ package org.apache.james.jmap.api.filtering; -import java.util.Arrays; -import java.util.List; +import org.junit.jupiter.api.Test; -import org.apache.james.core.Username; -import org.reactivestreams.Publisher; +import nl.jqno.equalsverifier.EqualsVerifier; -import com.google.common.collect.ImmutableList; - -public interface FilteringManagement { - - Publisher<Void> defineRulesForUser(Username username, List<Rule> rules); - - default Publisher<Void> defineRulesForUser(Username username, Rule... rules) { - return defineRulesForUser(username, Arrays.asList(rules)); +class VersionTest { + @Test + void shouldMatchBeanContract() { + EqualsVerifier.forClass(Version.class) + .verify(); } - - default Publisher<Void> clearRulesForUser(Username username) { - return defineRulesForUser(username, ImmutableList.of()); - } - - Publisher<Rule> listRulesForUser(Username username); - } diff --git a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/GetFilterMethod.java b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/GetFilterMethod.java index ebf9b53..1f7eccb 100644 --- a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/GetFilterMethod.java +++ b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/GetFilterMethod.java @@ -35,7 +35,6 @@ import org.apache.james.util.MDCBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.github.steveash.guavate.Guavate; import com.google.common.base.Preconditions; import reactor.core.publisher.Flux; @@ -90,10 +89,9 @@ public class GetFilterMethod implements Method { } private Mono<JmapResponse> retrieveFilter(MethodCallId methodCallId, Username username) { - return Flux.from(filteringManagement.listRulesForUser(username)) - .collect(Guavate.toImmutableList()) + return Mono.from(filteringManagement.listRulesForUser(username)) .map(rules -> GetFilterResponse.builder() - .rules(rules) + .rules(rules.getRules()) .build()) .map(getFilterResponse -> JmapResponse.builder() .methodCallId(methodCallId) diff --git a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/mailet/filter/JMAPFiltering.java b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/mailet/filter/JMAPFiltering.java index efd5fc7..d7ddd31 100644 --- a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/mailet/filter/JMAPFiltering.java +++ b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/mailet/filter/JMAPFiltering.java @@ -19,7 +19,6 @@ package org.apache.james.jmap.mailet.filter; -import java.util.List; import java.util.Optional; import java.util.stream.Stream; @@ -29,6 +28,7 @@ import org.apache.james.core.MailAddress; import org.apache.james.core.Username; import org.apache.james.jmap.api.filtering.FilteringManagement; import org.apache.james.jmap.api.filtering.Rule; +import org.apache.james.jmap.api.filtering.Rules; import org.apache.james.user.api.UsersRepository; import org.apache.james.user.api.UsersRepositoryException; import org.apache.mailet.Mail; @@ -36,9 +36,7 @@ import org.apache.mailet.base.GenericMailet; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.github.steveash.guavate.Guavate; - -import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; /** * Mailet for applying JMAP filtering to incoming email. @@ -81,10 +79,9 @@ public class JMAPFiltering extends GenericMailet { } private void findFirstApplicableRule(Username username, Mail mail) { - List<Rule> filteringRules = Flux.from(filteringManagement.listRulesForUser(username)) - .collect(Guavate.toImmutableList()) + Rules filteringRules = Mono.from(filteringManagement.listRulesForUser(username)) .block(); - RuleMatcher ruleMatcher = new RuleMatcher(filteringRules); + RuleMatcher ruleMatcher = new RuleMatcher(filteringRules.getRules()); Stream<Rule> matchingRules = ruleMatcher.findApplicableRules(mail); actionApplierFactory.forMail(mail) --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
