JAMES-2541 Design encoder/decoder layer to allow arbitrary java object storage in the blob store
Note that these object can be saved in several blobs Project: http://git-wip-us.apache.org/repos/asf/james-project/repo Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/0f7bd354 Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/0f7bd354 Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/0f7bd354 Branch: refs/heads/master Commit: 0f7bd3546b7e670916e4de19a601603fbb63f709 Parents: a207098 Author: Benoit Tellier <[email protected]> Authored: Thu Sep 6 11:58:35 2018 +0700 Committer: Benoit Tellier <[email protected]> Committed: Mon Sep 10 17:17:41 2018 +0700 ---------------------------------------------------------------------- server/blob/blob-api/pom.xml | 2 - .../java/org/apache/james/blob/api/Store.java | 108 +++++++++++++++++++ 2 files changed, 108 insertions(+), 2 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/james-project/blob/0f7bd354/server/blob/blob-api/pom.xml ---------------------------------------------------------------------- diff --git a/server/blob/blob-api/pom.xml b/server/blob/blob-api/pom.xml index 8f327e6..bb4941c 100644 --- a/server/blob/blob-api/pom.xml +++ b/server/blob/blob-api/pom.xml @@ -36,7 +36,6 @@ <dependency> <groupId>${james.groupId}</groupId> <artifactId>james-server-util</artifactId> - <scope>test</scope> </dependency> <dependency> <groupId>commons-io</groupId> @@ -60,7 +59,6 @@ <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> - <scope>test</scope> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> http://git-wip-us.apache.org/repos/asf/james-project/blob/0f7bd354/server/blob/blob-api/src/main/java/org/apache/james/blob/api/Store.java ---------------------------------------------------------------------- diff --git a/server/blob/blob-api/src/main/java/org/apache/james/blob/api/Store.java b/server/blob/blob-api/src/main/java/org/apache/james/blob/api/Store.java new file mode 100644 index 0000000..4665c6b --- /dev/null +++ b/server/blob/blob-api/src/main/java/org/apache/james/blob/api/Store.java @@ -0,0 +1,108 @@ +/**************************************************************** + * 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.blob.api; + +import java.io.InputStream; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.CompletableFuture; + +import org.apache.commons.lang3.tuple.Pair; +import org.apache.james.util.FluentFutureStream; + +import com.google.common.collect.ImmutableMap; + +public interface Store<T> { + class BlobType { + private final String name; + + public BlobType(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + @Override + public final boolean equals(Object o) { + if (o instanceof BlobType) { + BlobType blobType = (BlobType) o; + + return Objects.equals(this.name, blobType.name); + } + return false; + } + + @Override + public final int hashCode() { + return Objects.hash(name); + } + } + + interface Encoder<T> { + Map<BlobType, InputStream> encode(T t); + } + + interface Decoder<T> { + T decode(Map<BlobType, InputStream> streams); + } + + Map<BlobType, BlobId> save(T t); + + T read(Map<BlobType, BlobId> blobIds); + + class Impl<T> implements Store<T> { + private final Encoder<T> encoder; + private final Decoder<T> decoder; + private final BlobStore blobStore; + + public Impl(Encoder<T> encoder, Decoder<T> decoder, BlobStore blobStore) { + this.encoder = encoder; + this.decoder = decoder; + this.blobStore = blobStore; + } + + @Override + public Map<BlobType, BlobId> save(T t) { + return FluentFutureStream.of( + encoder.encode(t) + .entrySet() + .stream() + .map(this::saveEntry)) + .join() + .collect(ImmutableMap.toImmutableMap(Pair::getKey, Pair::getValue)); + } + + private CompletableFuture<Pair<BlobType, BlobId>> saveEntry(Map.Entry<BlobType, InputStream> entry) { + return blobStore.save(entry.getValue()) + .thenApply(blobId -> Pair.of(entry.getKey(), blobId)); + } + + @Override + public T read(Map<BlobType, BlobId> blobIds) { + ImmutableMap<BlobType, InputStream> binaries = blobIds.entrySet() + .stream() + .map(entry -> Pair.of(entry.getKey(), blobStore.read(entry.getValue()))) + .collect(ImmutableMap.toImmutableMap(Pair::getKey, Pair::getValue)); + return decoder.decode(binaries); + } + } +} --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
