JAMES-2528 implementation of a FilteringManagement API using Event Sourcing
Project: http://git-wip-us.apache.org/repos/asf/james-project/repo Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/58f0f800 Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/58f0f800 Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/58f0f800 Branch: refs/heads/master Commit: 58f0f800632189fda5fd1a4b9d5cfd89e991f2c4 Parents: d125ba9 Author: Matthieu Baechler <matth...@apache.org> Authored: Wed Aug 22 16:08:23 2018 +0200 Committer: Matthieu Baechler <matth...@apache.org> Committed: Thu Aug 23 14:29:33 2018 +0200 ---------------------------------------------------------------------- server/data/data-jmap/pom.xml | 23 ++++- .../jmap/api/filtering/FilteringManagement.java | 32 +++++++ .../apache/james/jmap/api/filtering/Rule.java | 67 +++++++++++++ .../api/filtering/impl/DefineRulesCommand.java | 76 +++++++++++++++ .../impl/DefineRulesCommandHandler.java | 52 +++++++++++ .../impl/EventSourcingFilteringManagement.java | 69 ++++++++++++++ .../api/filtering/impl/FilteringAggregate.java | 90 ++++++++++++++++++ .../filtering/impl/FilteringAggregateId.java | 73 +++++++++++++++ .../jmap/api/filtering/impl/RuleSetDefined.java | 85 +++++++++++++++++ .../api/filtering/FilteringAggregateIdTest.java | 86 +++++++++++++++++ .../filtering/FilteringManagementContract.java | 98 ++++++++++++++++++++ .../james/jmap/api/filtering/RuleTest.java | 41 ++++++++ .../filtering/impl/DefineRulesCommandTest.java | 51 ++++++++++ .../EventSourcingFilteringManagementTest.java | 32 +++++++ 14 files changed, 873 insertions(+), 2 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/james-project/blob/58f0f800/server/data/data-jmap/pom.xml ---------------------------------------------------------------------- diff --git a/server/data/data-jmap/pom.xml b/server/data/data-jmap/pom.xml index 7c7f049..169120b 100644 --- a/server/data/data-jmap/pom.xml +++ b/server/data/data-jmap/pom.xml @@ -42,6 +42,15 @@ <artifactId>james-server-util</artifactId> </dependency> <dependency> + <groupId>${james.groupId}</groupId> + <artifactId>event-sourcing-core</artifactId> + </dependency> + <dependency> + <groupId>${james.groupId}</groupId> + <artifactId>event-sourcing-event-store-memory</artifactId> + <scope>test</scope> + </dependency> + <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <scope>test</scope> @@ -55,8 +64,8 @@ <artifactId>javax.inject</artifactId> </dependency> <dependency> - <groupId>junit</groupId> - <artifactId>junit</artifactId> + <groupId>nl.jqno.equalsverifier</groupId> + <artifactId>equalsverifier</artifactId> <scope>test</scope> </dependency> <dependency> @@ -74,6 +83,16 @@ <scope>test</scope> </dependency> <dependency> + <groupId>org.junit.jupiter</groupId> + <artifactId>junit-jupiter-engine</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.junit.vintage</groupId> + <artifactId>junit-vintage-engine</artifactId> + <scope>test</scope> + </dependency> + <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-core</artifactId> <scope>test</scope> http://git-wip-us.apache.org/repos/asf/james-project/blob/58f0f800/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/filtering/FilteringManagement.java ---------------------------------------------------------------------- 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 new file mode 100644 index 0000000..a8b1c4b --- /dev/null +++ b/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/filtering/FilteringManagement.java @@ -0,0 +1,32 @@ +/**************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you under the Apache License, Version 2.0 (the * + * "License"); you may not use this file except in compliance * + * with the License. You may obtain a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, * + * software distributed under the License is distributed on an * + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * + * KIND, either express or implied. See the License for the * + * specific language governing permissions and limitations * + * under the License. * + ****************************************************************/ + +package org.apache.james.jmap.api.filtering; + +import java.util.List; + +import org.apache.james.core.User; + +public interface FilteringManagement { + + void defineRulesForUser(User user, List<Rule> rules); + + List<Rule> listRulesForUser(User user); + +} http://git-wip-us.apache.org/repos/asf/james-project/blob/58f0f800/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/filtering/Rule.java ---------------------------------------------------------------------- diff --git a/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/filtering/Rule.java b/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/filtering/Rule.java new file mode 100644 index 0000000..8bca30a --- /dev/null +++ b/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/filtering/Rule.java @@ -0,0 +1,67 @@ +/**************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you under the Apache License, Version 2.0 (the * + * "License"); you may not use this file except in compliance * + * with the License. You may obtain a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, * + * software distributed under the License is distributed on an * + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * + * KIND, either express or implied. See the License for the * + * specific language governing permissions and limitations * + * under the License. * + ****************************************************************/ + +package org.apache.james.jmap.api.filtering; + +import java.util.Objects; + +import com.google.common.base.MoreObjects; +import com.google.common.base.Preconditions; + +public class Rule { + + private final String id; + + public static Rule of(String id) { + return new Rule(id); + } + + public Rule(String id) { + Preconditions.checkNotNull(id); + + this.id = id; + } + + public String getId() { + return id; + } + + @Override + public final boolean equals(Object o) { + if (o instanceof Rule) { + Rule rule = (Rule) o; + + return Objects.equals(this.id, rule.id); + } + return false; + } + + @Override + public final int hashCode() { + return Objects.hash(id); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("id", id) + .toString(); + } + +} http://git-wip-us.apache.org/repos/asf/james-project/blob/58f0f800/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/filtering/impl/DefineRulesCommand.java ---------------------------------------------------------------------- diff --git a/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/filtering/impl/DefineRulesCommand.java b/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/filtering/impl/DefineRulesCommand.java new file mode 100644 index 0000000..0cd256c --- /dev/null +++ b/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/filtering/impl/DefineRulesCommand.java @@ -0,0 +1,76 @@ +/**************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you under the Apache License, Version 2.0 (the * + * "License"); you may not use this file except in compliance * + * with the License. You may obtain a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, * + * software distributed under the License is distributed on an * + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * + * KIND, either express or implied. See the License for the * + * specific language governing permissions and limitations * + * under the License. * + ****************************************************************/ + +package org.apache.james.jmap.api.filtering.impl; + +import java.util.List; +import java.util.Objects; + +import org.apache.james.core.User; +import org.apache.james.eventsourcing.Command; +import org.apache.james.jmap.api.filtering.Rule; + +import com.google.common.base.MoreObjects; +import com.google.common.base.Preconditions; + +public class DefineRulesCommand implements Command { + + private final User user; + private final List<Rule> rules; + + public DefineRulesCommand(User user, List<Rule> rules) { + Preconditions.checkNotNull(user); + Preconditions.checkNotNull(rules); + + this.user = user; + this.rules = rules; + } + + public List<Rule> getRules() { + return rules; + } + + public User getUser() { + return user; + } + + @Override + public final boolean equals(Object o) { + if (o instanceof DefineRulesCommand) { + DefineRulesCommand that = (DefineRulesCommand) o; + + return Objects.equals(this.user, that.user) + && Objects.equals(this.rules, that.rules); + } + return false; + } + + @Override + public final int hashCode() { + return Objects.hash(user, rules); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("user", user) + .add("rules", rules) + .toString(); + } +} http://git-wip-us.apache.org/repos/asf/james-project/blob/58f0f800/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/filtering/impl/DefineRulesCommandHandler.java ---------------------------------------------------------------------- diff --git a/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/filtering/impl/DefineRulesCommandHandler.java b/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/filtering/impl/DefineRulesCommandHandler.java new file mode 100644 index 0000000..a613893 --- /dev/null +++ b/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/filtering/impl/DefineRulesCommandHandler.java @@ -0,0 +1,52 @@ +/**************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you under the Apache License, Version 2.0 (the * + * "License"); you may not use this file except in compliance * + * with the License. You may obtain a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, * + * software distributed under the License is distributed on an * + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * + * KIND, either express or implied. See the License for the * + * specific language governing permissions and limitations * + * under the License. * + ****************************************************************/ + +package org.apache.james.jmap.api.filtering.impl; + +import java.util.List; + +import org.apache.james.eventsourcing.CommandHandler; +import org.apache.james.eventsourcing.Event; +import org.apache.james.eventsourcing.eventstore.EventStore; + +public class DefineRulesCommandHandler implements CommandHandler<DefineRulesCommand> { + + private final EventStore eventStore; + + public DefineRulesCommandHandler(EventStore eventStore) { + this.eventStore = eventStore; + } + + @Override + public Class<DefineRulesCommand> handledClass() { + return DefineRulesCommand.class; + } + + @Override + public List<? extends Event> handle(DefineRulesCommand storeCommand) { + FilteringAggregateId aggregateId = new FilteringAggregateId(storeCommand.getUser()); + + return FilteringAggregate + .load( + aggregateId, + eventStore.getEventsOfAggregate(aggregateId)) + .defineRules(storeCommand.getRules()); + } + +} http://git-wip-us.apache.org/repos/asf/james-project/blob/58f0f800/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/filtering/impl/EventSourcingFilteringManagement.java ---------------------------------------------------------------------- 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 new file mode 100644 index 0000000..2fbba65 --- /dev/null +++ b/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/filtering/impl/EventSourcingFilteringManagement.java @@ -0,0 +1,69 @@ +/**************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you under the Apache License, Version 2.0 (the * + * "License"); you may not use this file except in compliance * + * with the License. You may obtain a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, * + * software distributed under the License is distributed on an * + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * + * KIND, either express or implied. See the License for the * + * specific language governing permissions and limitations * + * under the License. * + ****************************************************************/ + +package org.apache.james.jmap.api.filtering.impl; + +import java.util.List; + +import javax.inject.Inject; + +import org.apache.james.core.User; +import org.apache.james.eventsourcing.EventSourcingSystem; +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 com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableSet; + +public class EventSourcingFilteringManagement implements FilteringManagement { + + private static final ImmutableSet<Subscriber> NO_SUBSCRIBER = ImmutableSet.of(); + + private final EventStore eventStore; + private final EventSourcingSystem eventSourcingSystem; + + @Inject + public EventSourcingFilteringManagement(EventStore eventStore) { + this.eventSourcingSystem = new EventSourcingSystem( + ImmutableSet.of(new DefineRulesCommandHandler(eventStore)), + NO_SUBSCRIBER, + eventStore); + this.eventStore = eventStore; + } + + @Override + public void defineRulesForUser(User user, List<Rule> rules) { + eventSourcingSystem.dispatch(new DefineRulesCommand(user, rules)); + } + + @Override + public List<Rule> listRulesForUser(User user) { + Preconditions.checkNotNull(user); + + FilteringAggregateId aggregateId = new FilteringAggregateId(user); + + return FilteringAggregate + .load( + aggregateId, + eventStore.getEventsOfAggregate(aggregateId)) + .listRules(); + } +} http://git-wip-us.apache.org/repos/asf/james-project/blob/58f0f800/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/filtering/impl/FilteringAggregate.java ---------------------------------------------------------------------- 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 new file mode 100644 index 0000000..33970f2 --- /dev/null +++ b/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/filtering/impl/FilteringAggregate.java @@ -0,0 +1,90 @@ +/**************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you under the Apache License, Version 2.0 (the * + * "License"); you may not use this file except in compliance * + * with the License. You may obtain a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, * + * software distributed under the License is distributed on an * + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * + * KIND, either express or implied. See the License for the * + * specific language governing permissions and limitations * + * under the License. * + ****************************************************************/ + +package org.apache.james.jmap.api.filtering.impl; + +import java.util.List; + +import org.apache.james.eventsourcing.Event; +import org.apache.james.eventsourcing.eventstore.History; +import org.apache.james.jmap.api.filtering.Rule; + +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; + +public class FilteringAggregate { + + public static FilteringAggregate load(FilteringAggregateId aggregateId, History eventsOfAggregate) { + return new FilteringAggregate(aggregateId, eventsOfAggregate); + } + + private static class State { + + static State initial() { + return new State(ImmutableList.of()); + } + + final ImmutableList<Rule> rules; + + private State(ImmutableList<Rule> rules) { + this.rules = rules; + } + + State set(ImmutableList<Rule> rules) { + return new State(rules); + } + } + + private final FilteringAggregateId aggregateId; + private final History history; + private State state; + + private FilteringAggregate(FilteringAggregateId aggregateId, History history) { + this.aggregateId = aggregateId; + this.state = State.initial(); + history.getEvents().forEach(this::apply); + this.history = history; + } + + public List<? extends Event> defineRules(List<Rule> rules) { + Preconditions.checkArgument(shouldNotContainDuplicates(rules)); + ImmutableList<RuleSetDefined> events = ImmutableList.of( + new RuleSetDefined(aggregateId, history.getNextEventId(), ImmutableList.copyOf(rules))); + events.forEach(this::apply); + return events; + } + + private boolean shouldNotContainDuplicates(List<Rule> rules) { + long uniqueIdCount = rules.stream() + .map(Rule::getId) + .distinct() + .count(); + return uniqueIdCount == rules.size(); + } + + public List<Rule> listRules() { + return state.rules; + } + + private void apply(Event event) { + if (event instanceof RuleSetDefined) { + state = state.set(((RuleSetDefined)event).getRules()); + } + } +} http://git-wip-us.apache.org/repos/asf/james-project/blob/58f0f800/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/filtering/impl/FilteringAggregateId.java ---------------------------------------------------------------------- diff --git a/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/filtering/impl/FilteringAggregateId.java b/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/filtering/impl/FilteringAggregateId.java new file mode 100644 index 0000000..635f045 --- /dev/null +++ b/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/filtering/impl/FilteringAggregateId.java @@ -0,0 +1,73 @@ +/**************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you under the Apache License, Version 2.0 (the * + * "License"); you may not use this file except in compliance * + * with the License. You may obtain a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, * + * software distributed under the License is distributed on an * + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * + * KIND, either express or implied. See the License for the * + * specific language governing permissions and limitations * + * under the License. * + ****************************************************************/ + +package org.apache.james.jmap.api.filtering.impl; + +import java.util.Objects; + +import org.apache.james.core.User; +import org.apache.james.eventsourcing.AggregateId; + +import com.google.common.base.MoreObjects; +import com.google.common.base.Preconditions; + +public class FilteringAggregateId implements AggregateId { + private static final String SEPARATOR = "/"; + private static final String PREFIX = "FilteringRule"; + + public static final FilteringAggregateId parse(String rawString) { + Preconditions.checkArgument(rawString.startsWith(PREFIX + SEPARATOR)); + return new FilteringAggregateId(User.fromUsername(rawString.substring(PREFIX.length() + SEPARATOR.length()))); + } + + private final User user; + + public FilteringAggregateId(User user) { + Preconditions.checkNotNull(user); + + this.user = user; + } + + @Override + public String asAggregateKey() { + return PREFIX + SEPARATOR + user.asString(); + } + + @Override + public final boolean equals(Object o) { + if (o instanceof FilteringAggregateId) { + FilteringAggregateId that = (FilteringAggregateId) o; + + return Objects.equals(this.user, that.user); + } + return false; + } + + @Override + public final int hashCode() { + return Objects.hash(user); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("user", user) + .toString(); + } +} http://git-wip-us.apache.org/repos/asf/james-project/blob/58f0f800/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/filtering/impl/RuleSetDefined.java ---------------------------------------------------------------------- diff --git a/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/filtering/impl/RuleSetDefined.java b/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/filtering/impl/RuleSetDefined.java new file mode 100644 index 0000000..dacba35 --- /dev/null +++ b/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/filtering/impl/RuleSetDefined.java @@ -0,0 +1,85 @@ +/**************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you under the Apache License, Version 2.0 (the * + * "License"); you may not use this file except in compliance * + * with the License. You may obtain a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, * + * software distributed under the License is distributed on an * + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * + * KIND, either express or implied. See the License for the * + * specific language governing permissions and limitations * + * under the License. * + ****************************************************************/ + +package org.apache.james.jmap.api.filtering.impl; + +import java.util.Objects; + +import org.apache.james.eventsourcing.AggregateId; +import org.apache.james.eventsourcing.Event; +import org.apache.james.eventsourcing.EventId; +import org.apache.james.jmap.api.filtering.Rule; + +import com.google.common.base.MoreObjects; +import com.google.common.collect.ImmutableList; + +public class RuleSetDefined implements Event { + + private final FilteringAggregateId aggregateId; + private final EventId eventId; + private final ImmutableList<Rule> rules; + + RuleSetDefined(FilteringAggregateId aggregateId, EventId eventId, ImmutableList<Rule> rules) { + this.aggregateId = aggregateId; + this.eventId = eventId; + this.rules = rules; + } + + @Override + public EventId eventId() { + return eventId; + } + + @Override + public AggregateId getAggregateId() { + return aggregateId; + } + + public ImmutableList<Rule> getRules() { + return rules; + } + + @Override + public final boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + RuleSetDefined that = (RuleSetDefined) o; + return Objects.equals(aggregateId, that.aggregateId) && + Objects.equals(eventId, that.eventId) && + Objects.equals(rules, that.rules); + } + + @Override + public final int hashCode() { + return Objects.hash(aggregateId, eventId, rules); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("aggregateId", aggregateId) + .add("eventId", eventId) + .add("rules", rules) + .toString(); + } +} http://git-wip-us.apache.org/repos/asf/james-project/blob/58f0f800/server/data/data-jmap/src/test/java/org/apache/james/jmap/api/filtering/FilteringAggregateIdTest.java ---------------------------------------------------------------------- diff --git a/server/data/data-jmap/src/test/java/org/apache/james/jmap/api/filtering/FilteringAggregateIdTest.java b/server/data/data-jmap/src/test/java/org/apache/james/jmap/api/filtering/FilteringAggregateIdTest.java new file mode 100644 index 0000000..8588938 --- /dev/null +++ b/server/data/data-jmap/src/test/java/org/apache/james/jmap/api/filtering/FilteringAggregateIdTest.java @@ -0,0 +1,86 @@ +/**************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you under the Apache License, Version 2.0 (the * + * "License"); you may not use this file except in compliance * + * with the License. You may obtain a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, * + * software distributed under the License is distributed on an * + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * + * KIND, either express or implied. See the License for the * + * specific language governing permissions and limitations * + * under the License. * + ****************************************************************/ +package org.apache.james.jmap.api.filtering; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import org.apache.james.core.User; + +import org.apache.james.jmap.api.filtering.impl.FilteringAggregateId; +import org.junit.jupiter.api.Test; + +import nl.jqno.equalsverifier.EqualsVerifier; + +class FilteringAggregateIdTest { + + @Test + void shouldMatchBeanContract() { + EqualsVerifier.forClass(FilteringAggregateId.class).verify(); + } + + @Test + void constructorShouldThrowWhenNullDomain() { + assertThatThrownBy(() -> new FilteringAggregateId(null)) + .isInstanceOf(NullPointerException.class); + } + + @Test + void asAggregateKeyShouldReturnAStringContainingThePrefixAndTheDomain() { + assertThat(new FilteringAggregateId(User.fromUsername("foo@bar.space")).asAggregateKey()) + .isEqualTo("FilteringRule/foo@bar.space"); + } + + @Test + void parseShouldThrowWhenNullString() { + assertThatThrownBy(() -> FilteringAggregateId.parse(null)) + .isInstanceOf(NullPointerException.class); + } + + @Test + void parseShouldThrowWhenStringDoesntMatchPrefix() { + assertThatThrownBy(() -> FilteringAggregateId.parse("WrongPrefix/foo")) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + void parseShouldThrowWhenStringDoesntContainSeparator() { + assertThatThrownBy(() -> FilteringAggregateId.parse("WrongPrefix")) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + void parseShouldThrowWhenStringDoesntContainUser() { + assertThatThrownBy(() -> FilteringAggregateId.parse("FilteringRule/")) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + void parseShouldThrowWhenStringDoesntHavePrefix() { + assertThatThrownBy(() -> FilteringAggregateId.parse("FilteringRulefoo")) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + void parseShouldKeepSlashInUsername() { + assertThat(FilteringAggregateId.parse("FilteringRule/f/oo@bar.space").asAggregateKey()) + .isEqualTo("FilteringRule/f/oo@bar.space"); + } + +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/james-project/blob/58f0f800/server/data/data-jmap/src/test/java/org/apache/james/jmap/api/filtering/FilteringManagementContract.java ---------------------------------------------------------------------- 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 new file mode 100644 index 0000000..98683b8 --- /dev/null +++ b/server/data/data-jmap/src/test/java/org/apache/james/jmap/api/filtering/FilteringManagementContract.java @@ -0,0 +1,98 @@ +/**************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you under the Apache License, Version 2.0 (the * + * "License"); you may not use this file except in compliance * + * with the License. You may obtain a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, * + * software distributed under the License is distributed on an * + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * + * KIND, either express or implied. See the License for the * + * specific language governing permissions and limitations * + * under the License. * + ****************************************************************/ +package org.apache.james.jmap.api.filtering; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import org.apache.james.core.User; +import org.junit.jupiter.api.Test; + +import com.google.common.collect.ImmutableList; + +public interface FilteringManagementContract { + + String BART_SIMPSON_CARTOON = "bart@simpson.cartoon"; + Rule RULE_1 = Rule.of("1"); + Rule RULE_2 = Rule.of("2"); + Rule RULE_3 = Rule.of("3"); + + FilteringManagement instanciateFilteringManagement(); + + @Test + default void listingRulesForUnknownUserShouldReturnEmptyList() { + User user = User.fromUsername(BART_SIMPSON_CARTOON); + assertThat(instanciateFilteringManagement().listRulesForUser(user)).isEmpty(); + } + + @Test + default void listingRulesShouldThrowWhenNullUser() { + User user = null; + assertThatThrownBy(() -> instanciateFilteringManagement().listRulesForUser(user)).isInstanceOf(NullPointerException.class); + } + + @Test + default void listingRulesShouldReturnDefinedRules() { + User user = User.fromUsername(BART_SIMPSON_CARTOON); + FilteringManagement testee = instanciateFilteringManagement(); + testee.defineRulesForUser(user, ImmutableList.of(RULE_1, RULE_2)); + assertThat(testee.listRulesForUser(user)).containsExactly(RULE_1, RULE_2); + } + + @Test + default void listingRulesShouldReturnLastDefinedRules() { + User user = User.fromUsername(BART_SIMPSON_CARTOON); + FilteringManagement testee = instanciateFilteringManagement(); + testee.defineRulesForUser(user, ImmutableList.of(RULE_1, RULE_2)); + testee.defineRulesForUser(user, ImmutableList.of(RULE_2, RULE_1)); + assertThat(testee.listRulesForUser(user)).containsExactly(RULE_2, RULE_1); + } + + @Test + default void definingRulesShouldThrowWhenDuplicateRules() { + User user = User.fromUsername(BART_SIMPSON_CARTOON); + FilteringManagement testee = instanciateFilteringManagement(); + assertThatThrownBy(() -> testee.defineRulesForUser(user, ImmutableList.of(RULE_1, RULE_1))) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + default void definingRulesShouldThrowWhenNullUser() { + FilteringManagement testee = instanciateFilteringManagement(); + assertThatThrownBy(() -> testee.defineRulesForUser(null, ImmutableList.of(RULE_1, RULE_1))) + .isInstanceOf(NullPointerException.class); + } + + @Test + default void definingRulesShouldThrowWhenNullRuleList() { + User user = User.fromUsername(BART_SIMPSON_CARTOON); + FilteringManagement testee = instanciateFilteringManagement(); + assertThatThrownBy(() -> testee.defineRulesForUser(user, null)) + .isInstanceOf(NullPointerException.class); + } + + @Test + default void definingRulesShouldKeepOrdering() { + User user = User.fromUsername(BART_SIMPSON_CARTOON); + FilteringManagement testee = instanciateFilteringManagement(); + testee.defineRulesForUser(user, ImmutableList.of(RULE_3, RULE_2, RULE_1)); + assertThat(testee.listRulesForUser(user)).containsExactly(RULE_3, RULE_2, RULE_1); + } + +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/james-project/blob/58f0f800/server/data/data-jmap/src/test/java/org/apache/james/jmap/api/filtering/RuleTest.java ---------------------------------------------------------------------- diff --git a/server/data/data-jmap/src/test/java/org/apache/james/jmap/api/filtering/RuleTest.java b/server/data/data-jmap/src/test/java/org/apache/james/jmap/api/filtering/RuleTest.java new file mode 100644 index 0000000..fc10f6a --- /dev/null +++ b/server/data/data-jmap/src/test/java/org/apache/james/jmap/api/filtering/RuleTest.java @@ -0,0 +1,41 @@ +/**************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you under the Apache License, Version 2.0 (the * + * "License"); you may not use this file except in compliance * + * with the License. You may obtain a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, * + * software distributed under the License is distributed on an * + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * + * KIND, either express or implied. See the License for the * + * specific language governing permissions and limitations * + * under the License. * + ****************************************************************/ + +package org.apache.james.jmap.api.filtering; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import org.junit.jupiter.api.Test; + +import nl.jqno.equalsverifier.EqualsVerifier; + +class RuleTest { + + @Test + void shouldMatchBeanContract() { + EqualsVerifier.forClass(Rule.class) + .verify(); + } + + @Test + void constructorShouldThrowWhenNullId() { + assertThatThrownBy(() -> new Rule(null)) + .isInstanceOf(NullPointerException.class); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/james-project/blob/58f0f800/server/data/data-jmap/src/test/java/org/apache/james/jmap/api/filtering/impl/DefineRulesCommandTest.java ---------------------------------------------------------------------- diff --git a/server/data/data-jmap/src/test/java/org/apache/james/jmap/api/filtering/impl/DefineRulesCommandTest.java b/server/data/data-jmap/src/test/java/org/apache/james/jmap/api/filtering/impl/DefineRulesCommandTest.java new file mode 100644 index 0000000..a917fdd --- /dev/null +++ b/server/data/data-jmap/src/test/java/org/apache/james/jmap/api/filtering/impl/DefineRulesCommandTest.java @@ -0,0 +1,51 @@ +/**************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you under the Apache License, Version 2.0 (the * + * "License"); you may not use this file except in compliance * + * with the License. You may obtain a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, * + * software distributed under the License is distributed on an * + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * + * KIND, either express or implied. See the License for the * + * specific language governing permissions and limitations * + * under the License. * + ****************************************************************/ + +package org.apache.james.jmap.api.filtering.impl; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import org.apache.james.core.User; +import org.apache.james.jmap.api.filtering.Rule; +import org.junit.jupiter.api.Test; + +import com.google.common.collect.ImmutableList; + +import nl.jqno.equalsverifier.EqualsVerifier; + +class DefineRulesCommandTest { + + @Test + void shouldMatchBeanContract() { + EqualsVerifier.forClass(DefineRulesCommand.class) + .verify(); + } + + @Test + void constructorShouldThrowWhenNullUser() { + assertThatThrownBy(() -> new DefineRulesCommand(null, ImmutableList.of(Rule.of("1"), Rule.of("2")))) + .isInstanceOf(NullPointerException.class); + } + + @Test + void constructorShouldThrowWhenNullRuleList() { + assertThatThrownBy(() -> new DefineRulesCommand(User.fromUsername("a...@james.org"), null)) + .isInstanceOf(NullPointerException.class); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/james-project/blob/58f0f800/server/data/data-jmap/src/test/java/org/apache/james/jmap/api/filtering/impl/EventSourcingFilteringManagementTest.java ---------------------------------------------------------------------- diff --git a/server/data/data-jmap/src/test/java/org/apache/james/jmap/api/filtering/impl/EventSourcingFilteringManagementTest.java b/server/data/data-jmap/src/test/java/org/apache/james/jmap/api/filtering/impl/EventSourcingFilteringManagementTest.java new file mode 100644 index 0000000..45120c3 --- /dev/null +++ b/server/data/data-jmap/src/test/java/org/apache/james/jmap/api/filtering/impl/EventSourcingFilteringManagementTest.java @@ -0,0 +1,32 @@ +/**************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you under the Apache License, Version 2.0 (the * + * "License"); you may not use this file except in compliance * + * with the License. You may obtain a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, * + * software distributed under the License is distributed on an * + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * + * KIND, either express or implied. See the License for the * + * specific language governing permissions and limitations * + * under the License. * + ****************************************************************/ + +package org.apache.james.jmap.api.filtering.impl; + +import org.apache.james.eventsourcing.eventstore.memory.InMemoryEventStore; +import org.apache.james.jmap.api.filtering.FilteringManagement; +import org.apache.james.jmap.api.filtering.FilteringManagementContract; + +public class EventSourcingFilteringManagementTest implements FilteringManagementContract { + + @Override + public FilteringManagement instanciateFilteringManagement() { + return new EventSourcingFilteringManagement(new InMemoryEventStore()); + } +} --------------------------------------------------------------------- To unsubscribe, e-mail: server-dev-unsubscr...@james.apache.org For additional commands, e-mail: server-dev-h...@james.apache.org