You are viewing a plain text version of this content. The canonical link for it is here.
Posted to server-dev@james.apache.org by bt...@apache.org on 2018/05/10 02:31:15 UTC
[08/15] james-project git commit: MAILBOX-332 Cassandra
implementation for Quota Threshold Crossing notification
MAILBOX-332 Cassandra implementation for Quota Threshold Crossing notification
Project: http://git-wip-us.apache.org/repos/asf/james-project/repo
Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/c3a1bda2
Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/c3a1bda2
Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/c3a1bda2
Branch: refs/heads/master
Commit: c3a1bda2d0bd84c936b5848d06ec6fd9a176868c
Parents: a686c2b
Author: Matthieu Baechler <ma...@apache.org>
Authored: Mon May 7 18:05:45 2018 +0200
Committer: benwa <bt...@linagora.com>
Committed: Thu May 10 09:15:40 2018 +0700
----------------------------------------------------------------------
.../cassandra/DockerCassandraExtension.java | 4 +
.../apache/james/mailbox/quota/QuotaCount.java | 6 +-
.../apache/james/mailbox/quota/QuotaSize.java | 6 +-
mailbox/plugin/quota-mailing-cassandra/pom.xml | 135 +++++++++++++++++
.../cassandra/CassandraEventStore.java | 62 ++++++++
.../cassandra/CassandraEventStoreModule.java | 62 ++++++++
.../cassandra/CassandraEventStoreTable.java | 27 ++++
.../eventsourcing/cassandra/EventStoreDao.java | 122 +++++++++++++++
.../cassandra/JsonEventSerializer.java | 98 +++++++++++++
.../eventsourcing/cassandra/dto/EventDTO.java | 26 ++++
.../cassandra/dto/EventDTOModule.java | 32 ++++
.../cassandra/dto/HistoryEvolutionDTO.java | 98 +++++++++++++
.../mailbox/quota/cassandra/dto/QuotaDTO.java | 73 +++++++++
.../dto/QuotaThresholdChangedEventDTO.java | 110 ++++++++++++++
.../QuotaThresholdChangedEventDTOModule.java | 54 +++++++
.../CassandraEventSourcingSystemTest.java | 28 ++++
.../cassandra/CassandraEventStoreExtension.java | 86 +++++++++++
.../cassandra/CassandraEventStoreTest.java | 28 ++++
.../cassandra/JsonEventSerializerTest.java | 67 +++++++++
.../cassandra/dto/TestEventDTO.java | 73 +++++++++
.../cassandra/dto/TestEventDTOModule.java | 56 +++++++
.../mailbox/quota/cassandra/dto/DTOTest.java | 147 +++++++++++++++++++
...draQuotaMailingListenersIntegrationTest.java | 29 ++++
.../james/eventsource/InMemoryEventStore.java | 11 +-
.../org/apache/james/eventsourcing/Event.java | 11 ++
.../events/QuotaThresholdChangedEvent.java | 20 +++
.../mailbox/quota/model/HistoryEvolution.java | 22 +--
.../quota/model/QuotaThresholdHistory.java | 8 +
.../eventsourcing/EventSourcingSystemTest.java | 3 +-
.../james/eventsourcing/EventStoreTest.java | 2 +-
.../james/eventsourcing/TestAggregateId.java | 4 +
mailbox/pom.xml | 1 +
32 files changed, 1488 insertions(+), 23 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/james-project/blob/c3a1bda2/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/DockerCassandraExtension.java
----------------------------------------------------------------------
diff --git a/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/DockerCassandraExtension.java b/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/DockerCassandraExtension.java
index 43a3cb5..add70c8 100644
--- a/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/DockerCassandraExtension.java
+++ b/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/DockerCassandraExtension.java
@@ -56,6 +56,10 @@ public class DockerCassandraExtension implements BeforeAllCallback, AfterAllCall
public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException {
return dockerCassandra;
}
+
+ public DockerCassandra getDockerCassandra() {
+ return dockerCassandra;
+ }
public static class DockerCassandra {
http://git-wip-us.apache.org/repos/asf/james-project/blob/c3a1bda2/mailbox/api/src/main/java/org/apache/james/mailbox/quota/QuotaCount.java
----------------------------------------------------------------------
diff --git a/mailbox/api/src/main/java/org/apache/james/mailbox/quota/QuotaCount.java b/mailbox/api/src/main/java/org/apache/james/mailbox/quota/QuotaCount.java
index a932c33..ac17fa0 100644
--- a/mailbox/api/src/main/java/org/apache/james/mailbox/quota/QuotaCount.java
+++ b/mailbox/api/src/main/java/org/apache/james/mailbox/quota/QuotaCount.java
@@ -30,7 +30,11 @@ public class QuotaCount implements QuotaValue<QuotaCount> {
}
public static QuotaCount count(long value) {
- return new QuotaCount(Optional.of(value));
+ return count(Optional.of(value));
+ }
+
+ public static QuotaCount count(Optional<Long> value) {
+ return new QuotaCount(value);
}
private final Optional<Long> value;
http://git-wip-us.apache.org/repos/asf/james-project/blob/c3a1bda2/mailbox/api/src/main/java/org/apache/james/mailbox/quota/QuotaSize.java
----------------------------------------------------------------------
diff --git a/mailbox/api/src/main/java/org/apache/james/mailbox/quota/QuotaSize.java b/mailbox/api/src/main/java/org/apache/james/mailbox/quota/QuotaSize.java
index c8fb1a0..4d16e52 100644
--- a/mailbox/api/src/main/java/org/apache/james/mailbox/quota/QuotaSize.java
+++ b/mailbox/api/src/main/java/org/apache/james/mailbox/quota/QuotaSize.java
@@ -32,7 +32,11 @@ public class QuotaSize implements QuotaValue<QuotaSize> {
}
public static QuotaSize size(long value) {
- return new QuotaSize(Optional.of(value));
+ return size(Optional.of(value));
+ }
+
+ public static QuotaSize size(Optional<Long> value) {
+ return new QuotaSize(value);
}
private final Optional<Long> value;
http://git-wip-us.apache.org/repos/asf/james-project/blob/c3a1bda2/mailbox/plugin/quota-mailing-cassandra/pom.xml
----------------------------------------------------------------------
diff --git a/mailbox/plugin/quota-mailing-cassandra/pom.xml b/mailbox/plugin/quota-mailing-cassandra/pom.xml
new file mode 100644
index 0000000..38dbda2
--- /dev/null
+++ b/mailbox/plugin/quota-mailing-cassandra/pom.xml
@@ -0,0 +1,135 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <artifactId>apache-james-mailbox</artifactId>
+ <groupId>org.apache.james</groupId>
+ <version>3.1.0-SNAPSHOT</version>
+ <relativePath>../../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>quota-mailing-cassandra</artifactId>
+ <name>Apache James :: Mailbox :: Plugin :: Quota Mailing :: Cassandra</name>
+ <description>Apache James Mailbox Cassandra implementation of Quota mailing listener</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>apache-james-backends-cassandra</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>apache-james-backends-cassandra</artifactId>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>apache-james-mailbox-api</artifactId>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>apache-james-mailbox-quota-mailing</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>apache-james-mailbox-quota-mailing</artifactId>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>apache-james-mailbox-store</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>apache-mailet-base</artifactId>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>james-server-data-memory</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>ch.qos.logback</groupId>
+ <artifactId>logback-classic</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.assertj</groupId>
+ <artifactId>assertj-core</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-databind</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.datatype</groupId>
+ <artifactId>jackson-datatype-jdk8</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>net.javacrumbs.json-unit</groupId>
+ <artifactId>json-unit</artifactId>
+ <version>1.5.5</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>net.javacrumbs.json-unit</groupId>
+ <artifactId>json-unit-fluent</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>nl.jqno.equalsverifier</groupId>
+ <artifactId>equalsverifier</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.junit.jupiter</groupId>
+ <artifactId>junit-jupiter-engine</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.junit.platform</groupId>
+ <artifactId>junit-platform-launcher</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.testcontainers</groupId>
+ <artifactId>testcontainers</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+</project>
http://git-wip-us.apache.org/repos/asf/james-project/blob/c3a1bda2/mailbox/plugin/quota-mailing-cassandra/src/main/java/org/apache/james/eventsourcing/cassandra/CassandraEventStore.java
----------------------------------------------------------------------
diff --git a/mailbox/plugin/quota-mailing-cassandra/src/main/java/org/apache/james/eventsourcing/cassandra/CassandraEventStore.java b/mailbox/plugin/quota-mailing-cassandra/src/main/java/org/apache/james/eventsourcing/cassandra/CassandraEventStore.java
new file mode 100644
index 0000000..61c5a06
--- /dev/null
+++ b/mailbox/plugin/quota-mailing-cassandra/src/main/java/org/apache/james/eventsourcing/cassandra/CassandraEventStore.java
@@ -0,0 +1,62 @@
+/****************************************************************
+ * 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.eventsourcing.cassandra;
+
+import java.util.List;
+
+import javax.inject.Inject;
+
+import org.apache.james.eventsourcing.AggregateId;
+import org.apache.james.eventsourcing.Event;
+import org.apache.james.eventsourcing.EventStore;
+
+import com.google.common.base.Preconditions;
+
+public class CassandraEventStore implements EventStore {
+
+ private final EventStoreDao eventStoreDao;
+
+ @Inject
+ public CassandraEventStore(EventStoreDao eventStoreDao) {
+ this.eventStoreDao = eventStoreDao;
+ }
+
+ @Override
+ public void appendAll(List<Event> events) {
+ if (events.isEmpty()) {
+ return;
+ }
+ doAppendAll(events);
+ }
+
+ public void doAppendAll(List<Event> events) {
+ Preconditions.checkArgument(Event.belongsToSameAggregate(events));
+
+ boolean success = eventStoreDao.appendAll(events).join();
+ if (!success) {
+ throw new EventStoreFailedException();
+ }
+ }
+
+ @Override
+ public History getEventsOfAggregate(AggregateId aggregateId) {
+ return eventStoreDao.getEventsOfAggregate(aggregateId);
+ }
+}
http://git-wip-us.apache.org/repos/asf/james-project/blob/c3a1bda2/mailbox/plugin/quota-mailing-cassandra/src/main/java/org/apache/james/eventsourcing/cassandra/CassandraEventStoreModule.java
----------------------------------------------------------------------
diff --git a/mailbox/plugin/quota-mailing-cassandra/src/main/java/org/apache/james/eventsourcing/cassandra/CassandraEventStoreModule.java b/mailbox/plugin/quota-mailing-cassandra/src/main/java/org/apache/james/eventsourcing/cassandra/CassandraEventStoreModule.java
new file mode 100644
index 0000000..ed15cb2
--- /dev/null
+++ b/mailbox/plugin/quota-mailing-cassandra/src/main/java/org/apache/james/eventsourcing/cassandra/CassandraEventStoreModule.java
@@ -0,0 +1,62 @@
+/****************************************************************
+ * 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.eventsourcing.cassandra;
+
+import java.util.List;
+
+import org.apache.james.backends.cassandra.components.CassandraModule;
+import org.apache.james.backends.cassandra.components.CassandraTable;
+import org.apache.james.backends.cassandra.components.CassandraType;
+import org.apache.james.backends.cassandra.utils.CassandraConstants;
+
+import com.datastax.driver.core.DataType;
+import com.datastax.driver.core.schemabuilder.SchemaBuilder;
+import com.google.common.collect.ImmutableList;
+
+public class CassandraEventStoreModule implements CassandraModule {
+ private final List<CassandraTable> tables;
+ private final List<CassandraType> types;
+
+ public CassandraEventStoreModule() {
+ tables = ImmutableList.of(
+ new CassandraTable(CassandraEventStoreTable.EVENTS_TABLE,
+ SchemaBuilder.createTable(CassandraEventStoreTable.EVENTS_TABLE)
+ .ifNotExists()
+ .addPartitionKey(CassandraEventStoreTable.AGGREGATE_ID, DataType.varchar())
+ .addClusteringColumn(CassandraEventStoreTable.EVENT_ID, DataType.cint())
+ .addColumn(CassandraEventStoreTable.EVENT, DataType.text())
+ .withOptions()
+ .comment("Store events of a EventSourcing aggregate")
+ .caching(SchemaBuilder.KeyCaching.ALL,
+ SchemaBuilder.rows(CassandraConstants.DEFAULT_CACHED_ROW_PER_PARTITION))));
+ types = ImmutableList.of();
+ }
+
+ @Override
+ public List<CassandraTable> moduleTables() {
+ return tables;
+ }
+
+ @Override
+ public List<CassandraType> moduleTypes() {
+ return types;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/james-project/blob/c3a1bda2/mailbox/plugin/quota-mailing-cassandra/src/main/java/org/apache/james/eventsourcing/cassandra/CassandraEventStoreTable.java
----------------------------------------------------------------------
diff --git a/mailbox/plugin/quota-mailing-cassandra/src/main/java/org/apache/james/eventsourcing/cassandra/CassandraEventStoreTable.java b/mailbox/plugin/quota-mailing-cassandra/src/main/java/org/apache/james/eventsourcing/cassandra/CassandraEventStoreTable.java
new file mode 100644
index 0000000..c90b81e
--- /dev/null
+++ b/mailbox/plugin/quota-mailing-cassandra/src/main/java/org/apache/james/eventsourcing/cassandra/CassandraEventStoreTable.java
@@ -0,0 +1,27 @@
+/****************************************************************
+ * 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.eventsourcing.cassandra;
+
+public interface CassandraEventStoreTable {
+ String EVENTS_TABLE = "eventStore";
+ String AGGREGATE_ID = "aggregateId";
+ String EVENT = "event";
+ String EVENT_ID = "eventId";
+}
http://git-wip-us.apache.org/repos/asf/james-project/blob/c3a1bda2/mailbox/plugin/quota-mailing-cassandra/src/main/java/org/apache/james/eventsourcing/cassandra/EventStoreDao.java
----------------------------------------------------------------------
diff --git a/mailbox/plugin/quota-mailing-cassandra/src/main/java/org/apache/james/eventsourcing/cassandra/EventStoreDao.java b/mailbox/plugin/quota-mailing-cassandra/src/main/java/org/apache/james/eventsourcing/cassandra/EventStoreDao.java
new file mode 100644
index 0000000..2518f02
--- /dev/null
+++ b/mailbox/plugin/quota-mailing-cassandra/src/main/java/org/apache/james/eventsourcing/cassandra/EventStoreDao.java
@@ -0,0 +1,122 @@
+/****************************************************************
+ * 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.eventsourcing.cassandra;
+
+import static com.datastax.driver.core.querybuilder.QueryBuilder.bindMarker;
+import static com.datastax.driver.core.querybuilder.QueryBuilder.eq;
+import static com.datastax.driver.core.querybuilder.QueryBuilder.insertInto;
+import static com.datastax.driver.core.querybuilder.QueryBuilder.select;
+import static org.apache.james.eventsourcing.cassandra.CassandraEventStoreTable.AGGREGATE_ID;
+import static org.apache.james.eventsourcing.cassandra.CassandraEventStoreTable.EVENT;
+import static org.apache.james.eventsourcing.cassandra.CassandraEventStoreTable.EVENTS_TABLE;
+import static org.apache.james.eventsourcing.cassandra.CassandraEventStoreTable.EVENT_ID;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+
+import javax.inject.Inject;
+
+import org.apache.james.backends.cassandra.utils.CassandraAsyncExecutor;
+import org.apache.james.backends.cassandra.utils.CassandraUtils;
+import org.apache.james.eventsourcing.AggregateId;
+import org.apache.james.eventsourcing.Event;
+import org.apache.james.eventsourcing.EventStore;
+
+import com.datastax.driver.core.BatchStatement;
+import com.datastax.driver.core.BoundStatement;
+import com.datastax.driver.core.PreparedStatement;
+import com.datastax.driver.core.ResultSet;
+import com.datastax.driver.core.Row;
+import com.datastax.driver.core.Session;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.github.steveash.guavate.Guavate;
+
+public class EventStoreDao {
+ private final CassandraUtils cassandraUtils;
+ private final CassandraAsyncExecutor cassandraAsyncExecutor;
+ private final PreparedStatement insert;
+ private final PreparedStatement select;
+ private final JsonEventSerializer jsonEventSerializer;
+
+ @Inject
+ public EventStoreDao(Session session, CassandraUtils cassandraUtils, JsonEventSerializer jsonEventSerializer) {
+ this.cassandraUtils = cassandraUtils;
+ this.cassandraAsyncExecutor = new CassandraAsyncExecutor(session);
+ this.jsonEventSerializer = jsonEventSerializer;
+ this.insert = prepareInsert(session);
+ this.select = prepareSelect(session);
+ }
+
+ private PreparedStatement prepareInsert(Session session) {
+ return session.prepare(insertInto(EVENTS_TABLE)
+ .value(AGGREGATE_ID, bindMarker(AGGREGATE_ID))
+ .value(EVENT_ID, bindMarker(EVENT_ID))
+ .value(EVENT, bindMarker(EVENT))
+ .ifNotExists());
+ }
+
+ private PreparedStatement prepareSelect(Session session) {
+ return session.prepare(select()
+ .from(EVENTS_TABLE)
+ .where(eq(AGGREGATE_ID, bindMarker(AGGREGATE_ID))));
+ }
+
+ public CompletableFuture<Boolean> appendAll(List<Event> events) {
+ BatchStatement batch = new BatchStatement();
+ events.forEach(event -> batch.add(insertEvent(event)));
+ return cassandraAsyncExecutor.executeReturnApplied(batch);
+ }
+
+ private BoundStatement insertEvent(Event event) {
+ try {
+ return insert
+ .bind()
+ .setString(AGGREGATE_ID, event.getAggregateId().asAggregateKey())
+ .setInt(EVENT_ID, event.eventId().serialize())
+ .setString(EVENT, jsonEventSerializer.serialize(event));
+ } catch (JsonProcessingException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public EventStore.History getEventsOfAggregate(AggregateId aggregateId) {
+ return toHistory(
+ cassandraAsyncExecutor.execute(
+ select.bind()
+ .setString(AGGREGATE_ID, aggregateId.asAggregateKey()))
+ .join());
+ }
+
+ private EventStore.History toHistory(ResultSet resultSet) {
+ List<Event> events = cassandraUtils.convertToStream(resultSet)
+ .map(this::toEvent)
+ .collect(Guavate.toImmutableList());
+ return EventStore.History.of(events);
+ }
+
+ private Event toEvent(Row row) {
+ try {
+ return jsonEventSerializer.deserialize(row.getString(EVENT));
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/james-project/blob/c3a1bda2/mailbox/plugin/quota-mailing-cassandra/src/main/java/org/apache/james/eventsourcing/cassandra/JsonEventSerializer.java
----------------------------------------------------------------------
diff --git a/mailbox/plugin/quota-mailing-cassandra/src/main/java/org/apache/james/eventsourcing/cassandra/JsonEventSerializer.java b/mailbox/plugin/quota-mailing-cassandra/src/main/java/org/apache/james/eventsourcing/cassandra/JsonEventSerializer.java
new file mode 100644
index 0000000..bf3a5dc
--- /dev/null
+++ b/mailbox/plugin/quota-mailing-cassandra/src/main/java/org/apache/james/eventsourcing/cassandra/JsonEventSerializer.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.eventsourcing.cassandra;
+
+import java.io.IOException;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.function.Function;
+
+import javax.inject.Inject;
+
+import org.apache.james.eventsourcing.Event;
+import org.apache.james.eventsourcing.cassandra.dto.EventDTO;
+import org.apache.james.eventsourcing.cassandra.dto.EventDTOModule;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
+import com.github.steveash.guavate.Guavate;
+import com.google.common.collect.ImmutableSet;
+
+public class JsonEventSerializer {
+ public static class UnknownEventException extends RuntimeException {
+ public UnknownEventException(String message) {
+ super(message);
+ }
+ }
+
+ private final Map<Class<? extends Event>, EventDTOModule> eventClassToModule;
+ private final Map<String, EventDTOModule> typeToModule;
+ private final ObjectMapper objectMapper;
+
+ @Inject
+ public JsonEventSerializer(Set<EventDTOModule> modules) {
+ objectMapper = new ObjectMapper();
+ objectMapper.registerModule(new Jdk8Module());
+ objectMapper.setSerializationInclusion(JsonInclude.Include.NON_ABSENT);
+
+ typeToModule = modules.stream()
+ .collect(Guavate.toImmutableMap(
+ EventDTOModule::getType,
+ Function.identity()));
+
+ eventClassToModule = modules.stream()
+ .collect(Guavate.toImmutableMap(
+ EventDTOModule::getEventClass,
+ Function.identity()));
+ }
+
+ public JsonEventSerializer(EventDTOModule... modules) {
+ this(ImmutableSet.copyOf(modules));
+ }
+
+ public String serialize(Event event) throws JsonProcessingException {
+ Object dto = Optional.ofNullable(eventClassToModule.get(event.getClass()))
+ .orElseThrow(() -> new UnknownEventException("unknown event class " + event.getClass()))
+ .toDTO(event);
+ return objectMapper.writeValueAsString(dto);
+ }
+
+ public Event deserialize(String value) throws IOException {
+ JsonNode jsonNode = objectMapper.readTree(value);
+
+ String type = jsonNode.path("type").asText();
+
+ EventDTO dto = objectMapper.readValue(
+ objectMapper.treeAsTokens(jsonNode),
+ retrieveDTOClass(type));
+ return dto.toEvent();
+ }
+
+ public Class<? extends EventDTO> retrieveDTOClass(String type) {
+ return Optional.ofNullable(typeToModule.get(type))
+ .map(EventDTOModule::getDTOClass)
+ .orElseThrow(() -> new UnknownEventException("unknown event type " + type));
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/james-project/blob/c3a1bda2/mailbox/plugin/quota-mailing-cassandra/src/main/java/org/apache/james/eventsourcing/cassandra/dto/EventDTO.java
----------------------------------------------------------------------
diff --git a/mailbox/plugin/quota-mailing-cassandra/src/main/java/org/apache/james/eventsourcing/cassandra/dto/EventDTO.java b/mailbox/plugin/quota-mailing-cassandra/src/main/java/org/apache/james/eventsourcing/cassandra/dto/EventDTO.java
new file mode 100644
index 0000000..4616248
--- /dev/null
+++ b/mailbox/plugin/quota-mailing-cassandra/src/main/java/org/apache/james/eventsourcing/cassandra/dto/EventDTO.java
@@ -0,0 +1,26 @@
+/****************************************************************
+ * 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.eventsourcing.cassandra.dto;
+
+import org.apache.james.eventsourcing.Event;
+
+public interface EventDTO {
+ Event toEvent();
+}
http://git-wip-us.apache.org/repos/asf/james-project/blob/c3a1bda2/mailbox/plugin/quota-mailing-cassandra/src/main/java/org/apache/james/eventsourcing/cassandra/dto/EventDTOModule.java
----------------------------------------------------------------------
diff --git a/mailbox/plugin/quota-mailing-cassandra/src/main/java/org/apache/james/eventsourcing/cassandra/dto/EventDTOModule.java b/mailbox/plugin/quota-mailing-cassandra/src/main/java/org/apache/james/eventsourcing/cassandra/dto/EventDTOModule.java
new file mode 100644
index 0000000..d86d1d7
--- /dev/null
+++ b/mailbox/plugin/quota-mailing-cassandra/src/main/java/org/apache/james/eventsourcing/cassandra/dto/EventDTOModule.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.eventsourcing.cassandra.dto;
+
+import org.apache.james.eventsourcing.Event;
+
+public interface EventDTOModule {
+ String getType();
+
+ Class<? extends EventDTO> getDTOClass();
+
+ Class<? extends Event> getEventClass();
+
+ EventDTO toDTO(Event event);
+}
http://git-wip-us.apache.org/repos/asf/james-project/blob/c3a1bda2/mailbox/plugin/quota-mailing-cassandra/src/main/java/org/apache/james/mailbox/quota/cassandra/dto/HistoryEvolutionDTO.java
----------------------------------------------------------------------
diff --git a/mailbox/plugin/quota-mailing-cassandra/src/main/java/org/apache/james/mailbox/quota/cassandra/dto/HistoryEvolutionDTO.java b/mailbox/plugin/quota-mailing-cassandra/src/main/java/org/apache/james/mailbox/quota/cassandra/dto/HistoryEvolutionDTO.java
new file mode 100644
index 0000000..2d1dda1
--- /dev/null
+++ b/mailbox/plugin/quota-mailing-cassandra/src/main/java/org/apache/james/mailbox/quota/cassandra/dto/HistoryEvolutionDTO.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.mailbox.quota.cassandra.dto;
+
+import java.time.Instant;
+import java.util.Optional;
+
+import org.apache.james.mailbox.quota.model.HistoryEvolution;
+import org.apache.james.mailbox.quota.model.QuotaThreshold;
+import org.apache.james.mailbox.quota.model.QuotaThresholdChange;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.google.common.base.Preconditions;
+import com.google.common.primitives.Booleans;
+
+class HistoryEvolutionDTO {
+
+ public static HistoryEvolutionDTO toDto(HistoryEvolution historyEvolution) {
+ return new HistoryEvolutionDTO(
+ historyEvolution.getThresholdHistoryChange(),
+ historyEvolution.getRecentness(),
+ historyEvolution.getThresholdChange()
+ .map(QuotaThresholdChange::getQuotaThreshold)
+ .map(QuotaThreshold::getQuotaOccupationRatio),
+ historyEvolution.getThresholdChange()
+ .map(QuotaThresholdChange::getInstant)
+ .map(Instant::toEpochMilli));
+ }
+
+ private final HistoryEvolution.HistoryChangeType change;
+ private final Optional<HistoryEvolution.HighestThresholdRecentness> recentness;
+ private final Optional<Double> threshold;
+ private final Optional<Long> instant;
+
+ @JsonCreator
+ public HistoryEvolutionDTO(
+ @JsonProperty("changeType") HistoryEvolution.HistoryChangeType change,
+ @JsonProperty("recentness") Optional<HistoryEvolution.HighestThresholdRecentness> recentness,
+ @JsonProperty("threshold") Optional<Double> threshold,
+ @JsonProperty("instant") Optional<Long> instant) {
+ this.change = change;
+ this.recentness = recentness;
+ this.threshold = threshold;
+ this.instant = instant;
+ }
+
+ public HistoryEvolution.HistoryChangeType getChange() {
+ return change;
+ }
+
+ public Optional<HistoryEvolution.HighestThresholdRecentness> getRecentness() {
+ return recentness;
+ }
+
+ public Optional<Double> getThreshold() {
+ return threshold;
+ }
+
+ public Optional<Long> getInstant() {
+ return instant;
+ }
+
+ @JsonIgnore
+ public HistoryEvolution toHistoryEvolution() {
+ Preconditions.checkState(Booleans.countTrue(
+ threshold.isPresent(), instant.isPresent()) != 1,
+ "threshold and instant needs to be both set, or both unset. Mixed states not allowed.");
+
+ Optional<QuotaThresholdChange> quotaThresholdChange = threshold
+ .map(QuotaThreshold::new)
+ .map(value -> new QuotaThresholdChange(value, Instant.ofEpochMilli(instant.get())));
+
+ return new HistoryEvolution(
+ change,
+ recentness,
+ quotaThresholdChange);
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/james-project/blob/c3a1bda2/mailbox/plugin/quota-mailing-cassandra/src/main/java/org/apache/james/mailbox/quota/cassandra/dto/QuotaDTO.java
----------------------------------------------------------------------
diff --git a/mailbox/plugin/quota-mailing-cassandra/src/main/java/org/apache/james/mailbox/quota/cassandra/dto/QuotaDTO.java b/mailbox/plugin/quota-mailing-cassandra/src/main/java/org/apache/james/mailbox/quota/cassandra/dto/QuotaDTO.java
new file mode 100644
index 0000000..bf204c8
--- /dev/null
+++ b/mailbox/plugin/quota-mailing-cassandra/src/main/java/org/apache/james/mailbox/quota/cassandra/dto/QuotaDTO.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.mailbox.quota.cassandra.dto;
+
+import java.util.Optional;
+
+import org.apache.james.mailbox.model.Quota;
+import org.apache.james.mailbox.quota.QuotaCount;
+import org.apache.james.mailbox.quota.QuotaSize;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+class QuotaDTO {
+ public static QuotaDTO from(Quota<?> quota) {
+ if (quota.getLimit().isUnlimited()) {
+ return new QuotaDTO(quota.getUsed().asLong(), Optional.empty());
+ }
+ return new QuotaDTO(quota.getUsed().asLong(), Optional.of(quota.getLimit().asLong()));
+ }
+
+ private final long used;
+ private final Optional<Long> limit;
+
+ @JsonCreator
+ private QuotaDTO(@JsonProperty("used") long used,
+ @JsonProperty("limit") Optional<Long> limit) {
+ this.used = used;
+ this.limit = limit;
+ }
+
+ public long getUsed() {
+ return used;
+ }
+
+ public Optional<Long> getLimit() {
+ return limit;
+ }
+
+ @JsonIgnore
+ public Quota<QuotaSize> asSizeQuota() {
+ return Quota.<QuotaSize>builder()
+ .used(QuotaSize.size(used))
+ .computedLimit(QuotaSize.size(limit))
+ .build();
+ }
+
+ @JsonIgnore
+ public Quota<QuotaCount> asCountQuota() {
+ return Quota.<QuotaCount>builder()
+ .used(QuotaCount.count(used))
+ .computedLimit(QuotaCount.count(limit))
+ .build();
+ }
+}
http://git-wip-us.apache.org/repos/asf/james-project/blob/c3a1bda2/mailbox/plugin/quota-mailing-cassandra/src/main/java/org/apache/james/mailbox/quota/cassandra/dto/QuotaThresholdChangedEventDTO.java
----------------------------------------------------------------------
diff --git a/mailbox/plugin/quota-mailing-cassandra/src/main/java/org/apache/james/mailbox/quota/cassandra/dto/QuotaThresholdChangedEventDTO.java b/mailbox/plugin/quota-mailing-cassandra/src/main/java/org/apache/james/mailbox/quota/cassandra/dto/QuotaThresholdChangedEventDTO.java
new file mode 100644
index 0000000..80eae8d
--- /dev/null
+++ b/mailbox/plugin/quota-mailing-cassandra/src/main/java/org/apache/james/mailbox/quota/cassandra/dto/QuotaThresholdChangedEventDTO.java
@@ -0,0 +1,110 @@
+/****************************************************************
+ * 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.mailbox.quota.cassandra.dto;
+
+import org.apache.james.core.User;
+import org.apache.james.eventsourcing.EventId;
+import org.apache.james.eventsourcing.cassandra.dto.EventDTO;
+import org.apache.james.mailbox.quota.mailing.aggregates.UserQuotaThresholds;
+import org.apache.james.mailbox.quota.mailing.events.QuotaThresholdChangedEvent;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+class QuotaThresholdChangedEventDTO implements EventDTO {
+
+ @JsonIgnore
+ public static QuotaThresholdChangedEventDTO from(QuotaThresholdChangedEvent event, String type) {
+ return new QuotaThresholdChangedEventDTO(
+ type, event.eventId().serialize(),
+ event.getAggregateId().getUser().asString(),
+ QuotaDTO.from(event.getSizeQuota()),
+ QuotaDTO.from(event.getCountQuota()),
+ HistoryEvolutionDTO.toDto(event.getSizeHistoryEvolution()),
+ HistoryEvolutionDTO.toDto(event.getCountHistoryEvolution()));
+ }
+
+ private final String type;
+ private final int eventId;
+ private final String user;
+ private final QuotaDTO sizeQuota;
+ private final QuotaDTO countQuota;
+ private final HistoryEvolutionDTO sizeEvolution;
+ private final HistoryEvolutionDTO countEvolution;
+
+ @JsonCreator
+ private QuotaThresholdChangedEventDTO(
+ @JsonProperty("type") String type,
+ @JsonProperty("eventId") int eventId,
+ @JsonProperty("user") String user,
+ @JsonProperty("sizeQuota") QuotaDTO sizeQuota,
+ @JsonProperty("countQuota") QuotaDTO countQuota,
+ @JsonProperty("sizeEvolution") HistoryEvolutionDTO sizeEvolution,
+ @JsonProperty("countEvolution") HistoryEvolutionDTO countEvolution) {
+ this.type = type;
+ this.eventId = eventId;
+ this.user = user;
+ this.sizeQuota = sizeQuota;
+ this.countQuota = countQuota;
+ this.sizeEvolution = sizeEvolution;
+ this.countEvolution = countEvolution;
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ public long getEventId() {
+ return eventId;
+ }
+
+ public String getUser() {
+ return user;
+ }
+
+ public QuotaDTO getSizeQuota() {
+ return sizeQuota;
+ }
+
+ public QuotaDTO getCountQuota() {
+ return countQuota;
+ }
+
+ public HistoryEvolutionDTO getSizeEvolution() {
+ return sizeEvolution;
+ }
+
+ public HistoryEvolutionDTO getCountEvolution() {
+ return countEvolution;
+ }
+
+ @JsonIgnore
+ @Override
+ public QuotaThresholdChangedEvent toEvent() {
+ return new QuotaThresholdChangedEvent(
+ EventId.fromSerialized(eventId),
+ sizeEvolution.toHistoryEvolution(),
+ countEvolution.toHistoryEvolution(),
+ sizeQuota.asSizeQuota(),
+ countQuota.asCountQuota(),
+ UserQuotaThresholds.Id.from(User.fromUsername(user)));
+ }
+}
http://git-wip-us.apache.org/repos/asf/james-project/blob/c3a1bda2/mailbox/plugin/quota-mailing-cassandra/src/main/java/org/apache/james/mailbox/quota/cassandra/dto/QuotaThresholdChangedEventDTOModule.java
----------------------------------------------------------------------
diff --git a/mailbox/plugin/quota-mailing-cassandra/src/main/java/org/apache/james/mailbox/quota/cassandra/dto/QuotaThresholdChangedEventDTOModule.java b/mailbox/plugin/quota-mailing-cassandra/src/main/java/org/apache/james/mailbox/quota/cassandra/dto/QuotaThresholdChangedEventDTOModule.java
new file mode 100644
index 0000000..328cb09
--- /dev/null
+++ b/mailbox/plugin/quota-mailing-cassandra/src/main/java/org/apache/james/mailbox/quota/cassandra/dto/QuotaThresholdChangedEventDTOModule.java
@@ -0,0 +1,54 @@
+/****************************************************************
+ * 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.mailbox.quota.cassandra.dto;
+
+import org.apache.james.eventsourcing.Event;
+import org.apache.james.eventsourcing.cassandra.dto.EventDTO;
+import org.apache.james.eventsourcing.cassandra.dto.EventDTOModule;
+import org.apache.james.mailbox.quota.mailing.events.QuotaThresholdChangedEvent;
+
+import com.google.common.base.Preconditions;
+
+public class QuotaThresholdChangedEventDTOModule implements EventDTOModule {
+ private static final String QUOTA_THRESHOLD_CHANGE = "quota-threshold-change";
+
+ @Override
+ public String getType() {
+ return QUOTA_THRESHOLD_CHANGE;
+ }
+
+ @Override
+ public Class<? extends EventDTO> getDTOClass() {
+ return QuotaThresholdChangedEventDTO.class;
+ }
+
+ @Override
+ public Class<? extends Event> getEventClass() {
+ return QuotaThresholdChangedEvent.class;
+ }
+
+ @Override
+ public EventDTO toDTO(Event event) {
+ Preconditions.checkArgument(event instanceof QuotaThresholdChangedEvent);
+ return QuotaThresholdChangedEventDTO.from(
+ (QuotaThresholdChangedEvent) event,
+ QUOTA_THRESHOLD_CHANGE);
+ }
+}
http://git-wip-us.apache.org/repos/asf/james-project/blob/c3a1bda2/mailbox/plugin/quota-mailing-cassandra/src/test/java/org/apache/james/eventsourcing/cassandra/CassandraEventSourcingSystemTest.java
----------------------------------------------------------------------
diff --git a/mailbox/plugin/quota-mailing-cassandra/src/test/java/org/apache/james/eventsourcing/cassandra/CassandraEventSourcingSystemTest.java b/mailbox/plugin/quota-mailing-cassandra/src/test/java/org/apache/james/eventsourcing/cassandra/CassandraEventSourcingSystemTest.java
new file mode 100644
index 0000000..bee6e88
--- /dev/null
+++ b/mailbox/plugin/quota-mailing-cassandra/src/test/java/org/apache/james/eventsourcing/cassandra/CassandraEventSourcingSystemTest.java
@@ -0,0 +1,28 @@
+/****************************************************************
+ * 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.eventsourcing.cassandra;
+
+import org.apache.james.eventsourcing.EventSourcingSystemTest;
+import org.junit.jupiter.api.extension.ExtendWith;
+
+@ExtendWith(CassandraEventStoreExtension.class)
+public class CassandraEventSourcingSystemTest implements EventSourcingSystemTest {
+
+}
http://git-wip-us.apache.org/repos/asf/james-project/blob/c3a1bda2/mailbox/plugin/quota-mailing-cassandra/src/test/java/org/apache/james/eventsourcing/cassandra/CassandraEventStoreExtension.java
----------------------------------------------------------------------
diff --git a/mailbox/plugin/quota-mailing-cassandra/src/test/java/org/apache/james/eventsourcing/cassandra/CassandraEventStoreExtension.java b/mailbox/plugin/quota-mailing-cassandra/src/test/java/org/apache/james/eventsourcing/cassandra/CassandraEventStoreExtension.java
new file mode 100644
index 0000000..1b0066f
--- /dev/null
+++ b/mailbox/plugin/quota-mailing-cassandra/src/test/java/org/apache/james/eventsourcing/cassandra/CassandraEventStoreExtension.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.eventsourcing.cassandra;
+
+import org.apache.james.backends.cassandra.CassandraCluster;
+import org.apache.james.backends.cassandra.DockerCassandraExtension;
+import org.apache.james.backends.cassandra.DockerCassandraExtension.DockerCassandra;
+import org.apache.james.backends.cassandra.utils.CassandraUtils;
+import org.apache.james.eventsourcing.EventStore;
+import org.apache.james.eventsourcing.cassandra.dto.TestEventDTOModule;
+import org.apache.james.mailbox.quota.cassandra.dto.QuotaThresholdChangedEventDTOModule;
+import org.junit.jupiter.api.extension.AfterAllCallback;
+import org.junit.jupiter.api.extension.AfterEachCallback;
+import org.junit.jupiter.api.extension.BeforeAllCallback;
+import org.junit.jupiter.api.extension.BeforeEachCallback;
+import org.junit.jupiter.api.extension.ExtensionContext;
+import org.junit.jupiter.api.extension.ParameterContext;
+import org.junit.jupiter.api.extension.ParameterResolutionException;
+import org.junit.jupiter.api.extension.ParameterResolver;
+
+public class CassandraEventStoreExtension implements BeforeAllCallback, AfterAllCallback, BeforeEachCallback, AfterEachCallback, ParameterResolver {
+ private final DockerCassandraExtension dockerCassandraExtension;
+ private CassandraCluster cassandra;
+ private DockerCassandra dockerCassandra;
+ private EventStoreDao eventStoreDao;
+
+ public CassandraEventStoreExtension() {
+ dockerCassandraExtension = new DockerCassandraExtension();
+ }
+
+ @Override
+ public void beforeAll(ExtensionContext context) throws Exception {
+ dockerCassandraExtension.beforeAll(context);
+ dockerCassandra = dockerCassandraExtension.getDockerCassandra();
+ }
+
+ @Override
+ public void afterAll(ExtensionContext context) throws Exception {
+ dockerCassandraExtension.afterAll(context);
+ }
+
+ @Override
+ public void beforeEach(ExtensionContext context) {
+ cassandra = CassandraCluster.create(
+ new CassandraEventStoreModule(), dockerCassandra.getIp(), dockerCassandra.getBindingPort());
+
+ JsonEventSerializer jsonEventSerializer = new JsonEventSerializer(
+ new QuotaThresholdChangedEventDTOModule(),
+ new TestEventDTOModule());
+
+ eventStoreDao = new EventStoreDao(cassandra.getConf(), CassandraUtils.WITH_DEFAULT_CONFIGURATION,
+ jsonEventSerializer);
+ }
+
+ @Override
+ public void afterEach(ExtensionContext context) {
+ cassandra.close();
+ }
+
+ @Override
+ public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException {
+ return (parameterContext.getParameter().getType() == EventStore.class);
+ }
+
+ @Override
+ public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException {
+ return new CassandraEventStore(eventStoreDao);
+ }
+}
http://git-wip-us.apache.org/repos/asf/james-project/blob/c3a1bda2/mailbox/plugin/quota-mailing-cassandra/src/test/java/org/apache/james/eventsourcing/cassandra/CassandraEventStoreTest.java
----------------------------------------------------------------------
diff --git a/mailbox/plugin/quota-mailing-cassandra/src/test/java/org/apache/james/eventsourcing/cassandra/CassandraEventStoreTest.java b/mailbox/plugin/quota-mailing-cassandra/src/test/java/org/apache/james/eventsourcing/cassandra/CassandraEventStoreTest.java
new file mode 100644
index 0000000..314b185
--- /dev/null
+++ b/mailbox/plugin/quota-mailing-cassandra/src/test/java/org/apache/james/eventsourcing/cassandra/CassandraEventStoreTest.java
@@ -0,0 +1,28 @@
+/****************************************************************
+ * 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.eventsourcing.cassandra;
+
+import org.apache.james.eventsourcing.EventStoreTest;
+import org.junit.jupiter.api.extension.ExtendWith;
+
+@ExtendWith(CassandraEventStoreExtension.class)
+class CassandraEventStoreTest implements EventStoreTest {
+
+}
http://git-wip-us.apache.org/repos/asf/james-project/blob/c3a1bda2/mailbox/plugin/quota-mailing-cassandra/src/test/java/org/apache/james/eventsourcing/cassandra/JsonEventSerializerTest.java
----------------------------------------------------------------------
diff --git a/mailbox/plugin/quota-mailing-cassandra/src/test/java/org/apache/james/eventsourcing/cassandra/JsonEventSerializerTest.java b/mailbox/plugin/quota-mailing-cassandra/src/test/java/org/apache/james/eventsourcing/cassandra/JsonEventSerializerTest.java
new file mode 100644
index 0000000..893647b
--- /dev/null
+++ b/mailbox/plugin/quota-mailing-cassandra/src/test/java/org/apache/james/eventsourcing/cassandra/JsonEventSerializerTest.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.eventsourcing.cassandra;
+
+import static net.javacrumbs.jsonunit.fluent.JsonFluentAssert.assertThatJson;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import org.apache.james.eventsourcing.EventId;
+import org.apache.james.eventsourcing.TestAggregateId;
+import org.apache.james.eventsourcing.TestEvent;
+import org.apache.james.eventsourcing.cassandra.dto.TestEventDTOModule;
+import org.junit.jupiter.api.Test;
+
+class JsonEventSerializerTest {
+ public static final String TEST_EVENT_JSON = "{\"type\":\"TestType\",\"data\":\"first\",\"eventId\":0,\"aggregate\":1}";
+ public static final TestEvent TEST_EVENT = new TestEvent(
+ EventId.fromSerialized(0),
+ TestAggregateId.testId(1),
+ "first");
+
+ @Test
+ void shouldDeserializeKnownEvent() throws Exception {
+ assertThat(new JsonEventSerializer(new TestEventDTOModule())
+ .deserialize(TEST_EVENT_JSON))
+ .isEqualTo(TEST_EVENT);
+ }
+
+ @Test
+ void shouldThrowWhenDeserializeUnknownEvent() {
+ assertThatThrownBy(() -> new JsonEventSerializer()
+ .deserialize(TEST_EVENT_JSON))
+ .isInstanceOf(JsonEventSerializer.UnknownEventException.class);
+ }
+
+ @Test
+ void shouldSerializeKnownEvent() throws Exception {
+ assertThatJson(new JsonEventSerializer(new TestEventDTOModule())
+ .serialize(TEST_EVENT))
+ .isEqualTo(TEST_EVENT_JSON);
+ }
+
+ @Test
+ void shouldThrowWhenSerializeUnknownEvent() {
+ assertThatThrownBy(() -> new JsonEventSerializer()
+ .serialize(TEST_EVENT))
+ .isInstanceOf(JsonEventSerializer.UnknownEventException.class);
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/james-project/blob/c3a1bda2/mailbox/plugin/quota-mailing-cassandra/src/test/java/org/apache/james/eventsourcing/cassandra/dto/TestEventDTO.java
----------------------------------------------------------------------
diff --git a/mailbox/plugin/quota-mailing-cassandra/src/test/java/org/apache/james/eventsourcing/cassandra/dto/TestEventDTO.java b/mailbox/plugin/quota-mailing-cassandra/src/test/java/org/apache/james/eventsourcing/cassandra/dto/TestEventDTO.java
new file mode 100644
index 0000000..529d8a9
--- /dev/null
+++ b/mailbox/plugin/quota-mailing-cassandra/src/test/java/org/apache/james/eventsourcing/cassandra/dto/TestEventDTO.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.eventsourcing.cassandra.dto;
+
+import org.apache.james.eventsourcing.Event;
+import org.apache.james.eventsourcing.EventId;
+import org.apache.james.eventsourcing.TestAggregateId;
+import org.apache.james.eventsourcing.TestEvent;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class TestEventDTO implements EventDTO {
+ private final String type;
+ private final String data;
+ private final int eventId;
+ private final int aggregate;
+
+ @JsonCreator
+ public TestEventDTO(
+ @JsonProperty("type") String type,
+ @JsonProperty("data") String data,
+ @JsonProperty("eventId") int eventId,
+ @JsonProperty("aggregate") int aggregate) {
+ this.type = type;
+ this.data = data;
+ this.eventId = eventId;
+ this.aggregate = aggregate;
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ public String getData() {
+ return data;
+ }
+
+ public long getEventId() {
+ return eventId;
+ }
+
+ public int getAggregate() {
+ return aggregate;
+ }
+
+ @JsonIgnore
+ @Override
+ public Event toEvent() {
+ return new TestEvent(
+ EventId.fromSerialized(eventId),
+ TestAggregateId.testId(aggregate),
+ data);
+ }
+}
http://git-wip-us.apache.org/repos/asf/james-project/blob/c3a1bda2/mailbox/plugin/quota-mailing-cassandra/src/test/java/org/apache/james/eventsourcing/cassandra/dto/TestEventDTOModule.java
----------------------------------------------------------------------
diff --git a/mailbox/plugin/quota-mailing-cassandra/src/test/java/org/apache/james/eventsourcing/cassandra/dto/TestEventDTOModule.java b/mailbox/plugin/quota-mailing-cassandra/src/test/java/org/apache/james/eventsourcing/cassandra/dto/TestEventDTOModule.java
new file mode 100644
index 0000000..6b46268
--- /dev/null
+++ b/mailbox/plugin/quota-mailing-cassandra/src/test/java/org/apache/james/eventsourcing/cassandra/dto/TestEventDTOModule.java
@@ -0,0 +1,56 @@
+/****************************************************************
+ * 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.eventsourcing.cassandra.dto;
+
+import org.apache.james.eventsourcing.Event;
+import org.apache.james.eventsourcing.TestEvent;
+import org.testcontainers.shaded.com.google.common.base.Preconditions;
+
+public class TestEventDTOModule implements EventDTOModule {
+
+ public static final String TEST_TYPE = "TestType";
+
+ @Override
+ public String getType() {
+ return TEST_TYPE;
+ }
+
+ @Override
+ public Class<? extends EventDTO> getDTOClass() {
+ return TestEventDTO.class;
+ }
+
+ @Override
+ public Class<? extends Event> getEventClass() {
+ return TestEvent.class;
+ }
+
+ @Override
+ public EventDTO toDTO(Event event) {
+ Preconditions.checkArgument(event instanceof TestEvent);
+
+ TestEvent testEvent = (TestEvent) event;
+ return new TestEventDTO(
+ TEST_TYPE,
+ testEvent.getData(),
+ testEvent.eventId().serialize(),
+ testEvent.getAggregateId().getId());
+ }
+}
http://git-wip-us.apache.org/repos/asf/james-project/blob/c3a1bda2/mailbox/plugin/quota-mailing-cassandra/src/test/java/org/apache/james/mailbox/quota/cassandra/dto/DTOTest.java
----------------------------------------------------------------------
diff --git a/mailbox/plugin/quota-mailing-cassandra/src/test/java/org/apache/james/mailbox/quota/cassandra/dto/DTOTest.java b/mailbox/plugin/quota-mailing-cassandra/src/test/java/org/apache/james/mailbox/quota/cassandra/dto/DTOTest.java
new file mode 100644
index 0000000..a42725a
--- /dev/null
+++ b/mailbox/plugin/quota-mailing-cassandra/src/test/java/org/apache/james/mailbox/quota/cassandra/dto/DTOTest.java
@@ -0,0 +1,147 @@
+/****************************************************************
+ * 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.mailbox.quota.cassandra.dto;
+
+import static net.javacrumbs.jsonunit.fluent.JsonFluentAssert.assertThatJson;
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.apache.james.core.User;
+import org.apache.james.eventsourcing.EventId;
+import org.apache.james.eventsourcing.cassandra.JsonEventSerializer;
+import org.apache.james.mailbox.model.Quota;
+import org.apache.james.mailbox.quota.QuotaCount;
+import org.apache.james.mailbox.quota.QuotaSize;
+import org.apache.james.mailbox.quota.mailing.aggregates.UserQuotaThresholds;
+import org.apache.james.mailbox.quota.mailing.events.QuotaThresholdChangedEvent;
+import org.apache.james.mailbox.quota.model.HistoryEvolution;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
+
+class DTOTest {
+
+ public static final Quota<QuotaSize> SIZE_QUOTA = Quota.<QuotaSize>builder().used(QuotaSize.size(23)).computedLimit(QuotaSize.size(33)).build();
+ public static final Quota<QuotaCount> COUNT_QUOTA = Quota.<QuotaCount>builder().used(QuotaCount.count(12)).computedLimit(QuotaCount.count(45)).build();
+ public static final QuotaThresholdChangedEvent EVENT = new QuotaThresholdChangedEvent(
+ EventId.first(),
+ HistoryEvolution.noChanges(),
+ HistoryEvolution.noChanges(),
+ SIZE_QUOTA,
+ COUNT_QUOTA,
+ UserQuotaThresholds.Id.from(User.fromUsername("foo@bar.com")));
+
+ public static final String EVENT_JSON = "{" +
+ " \"type\": \"quota-threshold-change\"," +
+ " \"eventId\": 0," +
+ " \"user\": \"foo@bar.com\"," +
+ " \"sizeQuota\": {" +
+ " \"used\": 23," +
+ " \"limit\": 33" +
+ " }," +
+ " \"countQuota\": {" +
+ " \"used\": 12," +
+ " \"limit\": 45" +
+ " }," +
+ " \"sizeEvolution\": {" +
+ " \"change\": \"NoChange\"," +
+ " \"threshold\": null," +
+ " \"instant\": null," +
+ " \"recentness\": null" +
+ " }," +
+ " \"countEvolution\": {" +
+ " \"change\": \"NoChange\"," +
+ " \"threshold\": null," +
+ " \"instant\": null," +
+ " \"recentness\": null" +
+ " }" +
+ "}";
+
+ public static final String COUNT_QUOTA_JSON = "{" +
+ " \"used\": 12," +
+ " \"limit\": 45" +
+ " }";
+
+ public static final String NO_CHANGES_JSON = "{" +
+ " \"change\":\"NoChange\"" +
+ "}";
+
+ private ObjectMapper objectMapper;
+
+ @BeforeEach
+ public void setUp() {
+ objectMapper = new ObjectMapper();
+ objectMapper.registerModule(new Jdk8Module());
+ objectMapper.setSerializationInclusion(JsonInclude.Include.NON_ABSENT);
+ }
+
+ @Test
+ void shouldSerializeQuotaDTO() throws Exception {
+ assertThatJson(objectMapper.writeValueAsString(QuotaDTO.from(COUNT_QUOTA)))
+ .isEqualTo(COUNT_QUOTA_JSON);
+ }
+
+ @Test
+ void shouldDeserializeQuotaDTO() throws Exception {
+ assertThat(objectMapper.readValue(COUNT_QUOTA_JSON, QuotaDTO.class).asCountQuota())
+ .isEqualTo(COUNT_QUOTA);
+ }
+
+ @Test
+ void shouldSerializeHistoryEvolutionDTO() throws Exception {
+ assertThatJson(objectMapper.writeValueAsString(HistoryEvolutionDTO.toDto(
+ HistoryEvolution.noChanges())))
+ .isEqualTo(NO_CHANGES_JSON);
+ }
+
+ @Test
+ void shouldDeserializeHistoryEvolutionDTO() throws Exception {
+ assertThat(objectMapper.readValue(NO_CHANGES_JSON, HistoryEvolutionDTO.class)
+ .toHistoryEvolution())
+ .isEqualTo(HistoryEvolution.noChanges());
+ }
+
+ @Test
+ void shouldSerializeQuotaThresholdChangedEventDTO() throws Exception {
+ assertThatJson(objectMapper.writeValueAsString(
+ new QuotaThresholdChangedEventDTOModule().toDTO(EVENT)))
+ .isEqualTo(EVENT_JSON);
+ }
+
+ @Test
+ void shouldDeserializeQuotaThresholdChangedEventDTO() throws Exception {
+ ObjectMapper objectMapper = new ObjectMapper();
+ objectMapper.registerModule(new Jdk8Module());
+
+ assertThat(objectMapper.readValue(EVENT_JSON, QuotaThresholdChangedEventDTO.class)
+ .toEvent())
+ .isEqualTo(EVENT);
+ }
+
+ @Test
+ void shouldSerializeQuotaThresholdChangedEvent() throws Exception {
+ assertThatJson(new JsonEventSerializer(new QuotaThresholdChangedEventDTOModule())
+ .serialize(EVENT))
+ .isEqualTo(EVENT_JSON);
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/james-project/blob/c3a1bda2/mailbox/plugin/quota-mailing-cassandra/src/test/java/org/apache/james/mailbox/quota/cassandra/listeners/CassandraQuotaMailingListenersIntegrationTest.java
----------------------------------------------------------------------
diff --git a/mailbox/plugin/quota-mailing-cassandra/src/test/java/org/apache/james/mailbox/quota/cassandra/listeners/CassandraQuotaMailingListenersIntegrationTest.java b/mailbox/plugin/quota-mailing-cassandra/src/test/java/org/apache/james/mailbox/quota/cassandra/listeners/CassandraQuotaMailingListenersIntegrationTest.java
new file mode 100644
index 0000000..3ea097a
--- /dev/null
+++ b/mailbox/plugin/quota-mailing-cassandra/src/test/java/org/apache/james/mailbox/quota/cassandra/listeners/CassandraQuotaMailingListenersIntegrationTest.java
@@ -0,0 +1,29 @@
+/****************************************************************
+ * 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.mailbox.quota.cassandra.listeners;
+
+import org.apache.james.eventsourcing.cassandra.CassandraEventStoreExtension;
+import org.apache.james.mailbox.quota.mailing.listeners.QuotaThresholdMailingIntegrationTest;
+import org.junit.jupiter.api.extension.ExtendWith;
+
+@ExtendWith(CassandraEventStoreExtension.class)
+public class CassandraQuotaMailingListenersIntegrationTest implements QuotaThresholdMailingIntegrationTest {
+
+}
http://git-wip-us.apache.org/repos/asf/james-project/blob/c3a1bda2/mailbox/plugin/quota-mailing-memory/src/main/java/org/apache/james/eventsource/InMemoryEventStore.java
----------------------------------------------------------------------
diff --git a/mailbox/plugin/quota-mailing-memory/src/main/java/org/apache/james/eventsource/InMemoryEventStore.java b/mailbox/plugin/quota-mailing-memory/src/main/java/org/apache/james/eventsource/InMemoryEventStore.java
index 91cdbb9..11c8e46 100644
--- a/mailbox/plugin/quota-mailing-memory/src/main/java/org/apache/james/eventsource/InMemoryEventStore.java
+++ b/mailbox/plugin/quota-mailing-memory/src/main/java/org/apache/james/eventsource/InMemoryEventStore.java
@@ -54,21 +54,14 @@ public class InMemoryEventStore implements EventStore {
private AggregateId getAggregateId(List<? extends Event> events) {
Preconditions.checkArgument(!events.isEmpty());
- Preconditions.checkArgument(belongsToSameAggregate(events));
+ Preconditions.checkArgument(Event.belongsToSameAggregate(events));
+
return events.stream()
.map(Event::getAggregateId)
.findFirst()
.get();
}
- private boolean belongsToSameAggregate(List<? extends Event> events) {
- return events.stream()
- .map(Event::getAggregateId)
- .distinct()
- .limit(2)
- .count() <= 1;
- }
-
private void appendToEmptyHistory(AggregateId aggregateId, List<Event> events) {
History newHistory = History.of(events);
http://git-wip-us.apache.org/repos/asf/james-project/blob/c3a1bda2/mailbox/plugin/quota-mailing/src/main/java/org/apache/james/eventsourcing/Event.java
----------------------------------------------------------------------
diff --git a/mailbox/plugin/quota-mailing/src/main/java/org/apache/james/eventsourcing/Event.java b/mailbox/plugin/quota-mailing/src/main/java/org/apache/james/eventsourcing/Event.java
index 7b3bc00..2b31374 100644
--- a/mailbox/plugin/quota-mailing/src/main/java/org/apache/james/eventsourcing/Event.java
+++ b/mailbox/plugin/quota-mailing/src/main/java/org/apache/james/eventsourcing/Event.java
@@ -19,8 +19,18 @@
package org.apache.james.eventsourcing;
+import java.util.List;
+
public interface Event extends Comparable<Event> {
+ static boolean belongsToSameAggregate(List<? extends Event> events) {
+ return events.stream()
+ .map(Event::getAggregateId)
+ .distinct()
+ .limit(2)
+ .count() == 1;
+ }
+
EventId eventId();
AggregateId getAggregateId();
@@ -29,4 +39,5 @@ public interface Event extends Comparable<Event> {
default int compareTo(Event o) {
return eventId().compareTo(o.eventId());
}
+
}
http://git-wip-us.apache.org/repos/asf/james-project/blob/c3a1bda2/mailbox/plugin/quota-mailing/src/main/java/org/apache/james/mailbox/quota/mailing/events/QuotaThresholdChangedEvent.java
----------------------------------------------------------------------
diff --git a/mailbox/plugin/quota-mailing/src/main/java/org/apache/james/mailbox/quota/mailing/events/QuotaThresholdChangedEvent.java b/mailbox/plugin/quota-mailing/src/main/java/org/apache/james/mailbox/quota/mailing/events/QuotaThresholdChangedEvent.java
index 3c21a3f..1c036f7 100644
--- a/mailbox/plugin/quota-mailing/src/main/java/org/apache/james/mailbox/quota/mailing/events/QuotaThresholdChangedEvent.java
+++ b/mailbox/plugin/quota-mailing/src/main/java/org/apache/james/mailbox/quota/mailing/events/QuotaThresholdChangedEvent.java
@@ -19,6 +19,8 @@
package org.apache.james.mailbox.quota.mailing.events;
+import java.util.Objects;
+
import org.apache.james.eventsourcing.Event;
import org.apache.james.eventsourcing.EventId;
import org.apache.james.mailbox.model.Quota;
@@ -71,5 +73,23 @@ public class QuotaThresholdChangedEvent implements Event {
return aggregateId;
}
+ @Override
+ public final boolean equals(Object o) {
+ if (o instanceof QuotaThresholdChangedEvent) {
+ QuotaThresholdChangedEvent that = (QuotaThresholdChangedEvent) o;
+
+ return Objects.equals(this.eventId, that.eventId)
+ && Objects.equals(this.sizeHistoryEvolution, that.sizeHistoryEvolution)
+ && Objects.equals(this.countHistoryEvolution, that.countHistoryEvolution)
+ && Objects.equals(this.sizeQuota, that.sizeQuota)
+ && Objects.equals(this.countQuota, that.countQuota)
+ && Objects.equals(this.aggregateId, that.aggregateId);
+ }
+ return false;
+ }
+ @Override
+ public final int hashCode() {
+ return Objects.hash(eventId, sizeHistoryEvolution, countHistoryEvolution, sizeQuota, countQuota, aggregateId);
+ }
}
http://git-wip-us.apache.org/repos/asf/james-project/blob/c3a1bda2/mailbox/plugin/quota-mailing/src/main/java/org/apache/james/mailbox/quota/model/HistoryEvolution.java
----------------------------------------------------------------------
diff --git a/mailbox/plugin/quota-mailing/src/main/java/org/apache/james/mailbox/quota/model/HistoryEvolution.java b/mailbox/plugin/quota-mailing/src/main/java/org/apache/james/mailbox/quota/model/HistoryEvolution.java
index e7cdf14..7f71025 100644
--- a/mailbox/plugin/quota-mailing/src/main/java/org/apache/james/mailbox/quota/model/HistoryEvolution.java
+++ b/mailbox/plugin/quota-mailing/src/main/java/org/apache/james/mailbox/quota/model/HistoryEvolution.java
@@ -22,13 +22,14 @@ package org.apache.james.mailbox.quota.model;
import java.util.Objects;
import java.util.Optional;
+import com.google.common.base.MoreObjects;
+
public class HistoryEvolution {
public static HistoryEvolution noChanges() {
return new HistoryEvolution(HistoryChangeType.NoChange,
Optional.empty(),
- Optional.empty()
- );
+ Optional.empty());
}
public static HistoryEvolution lowerThresholdReached(QuotaThresholdChange currentThreshold) {
@@ -58,7 +59,7 @@ public class HistoryEvolution {
private final Optional<HighestThresholdRecentness> recentness;
private final Optional<QuotaThresholdChange> thresholdChange;
- private HistoryEvolution(HistoryChangeType thresholdHistoryChange, Optional<HighestThresholdRecentness> recentness, Optional<QuotaThresholdChange> thresholdChange) {
+ public HistoryEvolution(HistoryChangeType thresholdHistoryChange, Optional<HighestThresholdRecentness> recentness, Optional<QuotaThresholdChange> thresholdChange) {
this.thresholdHistoryChange = thresholdHistoryChange;
this.recentness = recentness;
this.thresholdChange = thresholdChange;
@@ -82,6 +83,10 @@ public class HistoryEvolution {
return thresholdHistoryChange;
}
+ public Optional<HighestThresholdRecentness> getRecentness() {
+ return recentness;
+ }
+
@Override
public final boolean equals(Object o) {
if (o instanceof HistoryEvolution) {
@@ -99,13 +104,12 @@ public class HistoryEvolution {
return Objects.hash(thresholdHistoryChange, recentness, thresholdChange);
}
-
@Override
public String toString() {
- return "HistoryEvolution{" +
- "thresholdHistoryChange=" + thresholdHistoryChange +
- ", recentness=" + recentness +
- ", thresholdChange=" + thresholdChange +
- '}';
+ return MoreObjects.toStringHelper(this)
+ .add("thresholdHistoryChange", thresholdHistoryChange)
+ .add("recentness", recentness)
+ .add("thresholdChange", thresholdChange)
+ .toString();
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org