From 855d64dd6e8b0622f3efca83f5d2e93dbbdf315b Mon Sep 17 00:00:00 2001 From: Vatavuk Date: Wed, 8 Aug 2018 22:58:28 +0200 Subject: [PATCH] #16 implementing merge --- src/main/java/io/zold/api/Wallet.java | 68 ++++++++++++++++++----- src/test/java/io/zold/api/WalletTest.java | 59 ++++++++++++++++++-- 2 files changed, 110 insertions(+), 17 deletions(-) diff --git a/src/main/java/io/zold/api/Wallet.java b/src/main/java/io/zold/api/Wallet.java index e6e4ab9..cdb0bc9 100644 --- a/src/main/java/io/zold/api/Wallet.java +++ b/src/main/java/io/zold/api/Wallet.java @@ -27,17 +27,24 @@ import java.io.IOException; import java.io.Writer; import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Collection; +import org.cactoos.collection.Filtered; import org.cactoos.iterable.IterableOf; +import org.cactoos.iterable.Joined; import org.cactoos.iterable.Mapped; import org.cactoos.iterable.Skipped; import org.cactoos.list.ListOf; import org.cactoos.scalar.CheckedScalar; +import org.cactoos.scalar.Or; +import org.cactoos.scalar.UncheckedScalar; +import org.cactoos.text.FormattedText; import org.cactoos.text.SplitText; import org.cactoos.text.TextOf; +import org.cactoos.text.UncheckedText; /** * Wallet. - * * @since 0.1 */ @SuppressWarnings({"PMD.ShortMethodName", "PMD.TooManyMethods"}) @@ -64,7 +71,7 @@ public interface Wallet { * @param other Other wallet * @return The merged wallet */ - Wallet merge(Wallet other); + Wallet merge(Wallet other) throws IOException; /** * This wallet's ledger. @@ -74,7 +81,6 @@ public interface Wallet { /** * A Fake {@link Wallet}. - * * @since 1.0 */ final class Fake implements Wallet { @@ -84,13 +90,23 @@ final class Fake implements Wallet { */ private final long id; + private final Iterable transactions; + /** * Ctor. - * * @param id The wallet id. */ public Fake(final long id) { + this(id, new IterableOf<>()); + } + + public Fake(final long id, final Transaction... transactions) { + this(id, new IterableOf<>(transactions)); + } + + public Fake(final long id, final Iterable transactions) { this.id = id; + this.transactions = transactions; } @Override @@ -110,7 +126,7 @@ public Wallet merge(final Wallet other) { @Override public Iterable ledger() { - return new IterableOf<>(); + return this.transactions; } } @@ -158,17 +174,43 @@ public void pay(final long amt, final long bnf) throws IOException { } } - // @todo #6:30min Implement merge method. This should merge this wallet - // with a copy of the same wallet. It should throw an error if a - // wallet is provided. Also add a unit test to replace - // WalletTest.mergeIsNotYetImplemented(). @Override - public Wallet merge(final Wallet other) { - throw new UnsupportedOperationException( - "merge() not yet supported" - ); + public Wallet merge(final Wallet other) throws IOException { + if (other.id() != this.id()) { + throw new IOException( + new UncheckedText( + new FormattedText( + "Wallet ID mismatch, ours is %d, theirs is %d", + other.id(), + this.id() + ) + ).asString() + ); + } + final Iterable ledger = this.ledger(); + final Collection candidates = new ArrayList<>(); + for (final Transaction remote : other.ledger()) { + final Collection filtered = + new Filtered<>( + input -> new UncheckedScalar<>( + new Or( + () -> remote.equals(input), + () -> remote.id() == input.id() && + remote.bnf() == input.bnf(), + () -> remote.id() == input.id() && remote.amount() < 0L, + () -> remote.prefix().equals(input.prefix()) + ) + ).value(), + ledger + ); + if (filtered.isEmpty()) { + candidates.add(remote); + } + } + return new Wallet.Fake(this.id(), new Joined<>(ledger, candidates)); } + @Override public Iterable ledger() { return new Mapped<>( diff --git a/src/test/java/io/zold/api/WalletTest.java b/src/test/java/io/zold/api/WalletTest.java index 3601045..a707c5b 100644 --- a/src/test/java/io/zold/api/WalletTest.java +++ b/src/test/java/io/zold/api/WalletTest.java @@ -27,6 +27,7 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import org.cactoos.collection.CollectionOf; import org.cactoos.list.ListOf; import org.hamcrest.MatcherAssert; import org.hamcrest.Matchers; @@ -94,10 +95,60 @@ public void pay() throws IOException { ); } - @Test(expected = UnsupportedOperationException.class) - public void mergeIsNotYetImplemented() throws IOException { - new Wallet.File(this.folder.newFile().toPath()).merge( - new Wallet.File(this.folder.newFile().toPath()) + @Test + public void mergesWallets() throws IOException { + final long id = 5124095577148911L; + final Wallet wallet = new Wallet.File(this.wallet(id)); + final Wallet merged = wallet.merge( + new Wallet.Fake( + id, + new RtTransaction("abcd;2017-07-19T21:25:07Z;0000000000a72366;xxsQuJa9;98bb82c81735c4ee;") + ) + ); + MatcherAssert.assertThat( + new CollectionOf<>(merged.ledger()).size(), + new IsEqual<>(new CollectionOf<>(wallet.ledger()).size() + 1) + ); + } + + @Test + public void doesNotMergeWalletsWithDifferentId() throws IOException { + this.error.expect(IOException.class); + this.error.expectMessage("Wallet ID mismatch, ours is 123, theirs is 5124095577148911"); + final long id = 5124095577148911L; + final Wallet wallet = new Wallet.File(this.wallet(id)); + wallet.merge(new Wallet.Fake(123L)); + } + + @Test + public void doesNotMergeExistingTransactions() throws IOException { + final long id = 5124095577148911L; + final Wallet wallet = new Wallet.File(this.wallet(id)); + final Wallet merged = wallet.merge( + new Wallet.Fake( + id, + new RtTransaction("003b;2017-07-19T21:25:07Z;ffffffffffa72367;xksQuJa9;98bb82c81735c4ee;For food;QCuLuVr4...") + ) + ); + MatcherAssert.assertThat( + new CollectionOf<>(merged.ledger()).size(), + new IsEqual<>(new CollectionOf<>(wallet.ledger()).size()) + ); + } + + @Test + public void doesNotMergeTransactionsWithSameIdAndBnf() throws IOException { + final long id = 5124095577148911L; + final Wallet wallet = new Wallet.File(this.wallet(id)); + final Wallet merged = wallet.merge( + new Wallet.Fake( + id, + new RtTransaction("003b;2017-07-18T21:25:07Z;ffffffffffa72367;xxsQuJa9;98bb82c81735c4ee;For food;QCuLuVr4...") + ) + ); + MatcherAssert.assertThat( + new CollectionOf<>(merged.ledger()).size(), + new IsEqual<>(new CollectionOf<>(wallet.ledger()).size()) ); }