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]

Reply via email to