From a54264bc749bd6007da9cb0fc6dcf3ab8cdefcd2 Mon Sep 17 00:00:00 2001 From: Stefan Larsson Date: Thu, 22 Oct 2015 11:17:43 +0200 Subject: [PATCH 1/2] Added equals(), hashCode() and toString() methods to RiakObject. Dependent classes RiakLinks, RiakUserMetadata and RiakObject also got those methods added to allow sensible comparison of any RiakObject. This allows checking parameters for equality in unit tests when mocking out RiakClient. --- .../riak/client/core/query/RiakObject.java | 72 +++++++++++++++++++ .../query/UserMetadata/RiakUserMetadata.java | 29 +++++++- .../core/query/indexes/RiakIndexes.java | 25 +++++++ .../client/core/query/links/RiakLinks.java | 26 ++++++- .../client/api/commands/StoreValueTest.java | 64 ++++++++++++----- 5 files changed, 193 insertions(+), 23 deletions(-) diff --git a/src/main/java/com/basho/riak/client/core/query/RiakObject.java b/src/main/java/com/basho/riak/client/core/query/RiakObject.java index 457ba95dd..eb6a44276 100644 --- a/src/main/java/com/basho/riak/client/core/query/RiakObject.java +++ b/src/main/java/com/basho/riak/client/core/query/RiakObject.java @@ -386,4 +386,76 @@ public boolean isDeleted() { return isDeleted; } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + RiakObject that = (RiakObject) o; + + if (isDeleted != that.isDeleted) { + return false; + } + if (isModified != that.isModified) { + return false; + } + if (lastModified != that.lastModified) { + return false; + } + if (value != null ? !value.equals(that.value) : that.value != null) { + return false; + } + if (riakIndexes != null ? !riakIndexes.equals(that.riakIndexes) : that.riakIndexes != null) { + return false; + } + if (links != null ? !links.equals(that.links) : that.links != null) { + return false; + } + if (userMeta != null ? !userMeta.equals(that.userMeta) : that.userMeta != null) { + return false; + } + if (contentType != null ? !contentType.equals(that.contentType) : that.contentType != null) { + return false; + } + if (vtag != null ? !vtag.equals(that.vtag) : that.vtag != null) { + return false; + } + return !(vclock != null ? !vclock.equals(that.vclock) : that.vclock != null); + } + + @Override + public int hashCode() { + int result = value != null ? value.hashCode() : 0; + result = 31 * result + (riakIndexes != null ? riakIndexes.hashCode() : 0); + result = 31 * result + (links != null ? links.hashCode() : 0); + result = 31 * result + (userMeta != null ? userMeta.hashCode() : 0); + result = 31 * result + (contentType != null ? contentType.hashCode() : 0); + result = 31 * result + (vtag != null ? vtag.hashCode() : 0); + result = 31 * result + (isDeleted ? 1 : 0); + result = 31 * result + (isModified ? 1 : 0); + result = 31 * result + (vclock != null ? vclock.hashCode() : 0); + result = 31 * result + (int) (lastModified ^ (lastModified >>> 32)); + return result; + } + + @Override + public String toString() { + return "RiakObject{" + + "contentType: " + contentType + + ", value: " + value + + ", riakIndexes: " + riakIndexes + + ", links: " + links + + ", userMeta: " + userMeta + + ", vtag: " + vtag + + ", isDeleted: " + isDeleted + + ", isModified: " + isModified + + ", vclock: " + vclock + + ", lastModified: " + lastModified + + '}'; + } } diff --git a/src/main/java/com/basho/riak/client/core/query/UserMetadata/RiakUserMetadata.java b/src/main/java/com/basho/riak/client/core/query/UserMetadata/RiakUserMetadata.java index de46a5a01..4ed51f953 100644 --- a/src/main/java/com/basho/riak/client/core/query/UserMetadata/RiakUserMetadata.java +++ b/src/main/java/com/basho/riak/client/core/query/UserMetadata/RiakUserMetadata.java @@ -234,7 +234,30 @@ public int size() { return meta.size(); } - - - + + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + RiakUserMetadata that = (RiakUserMetadata) o; + return meta.equals(that.meta); + } + + @Override + public int hashCode() { + return meta.hashCode(); + } + + @Override + public String toString() { + return "RiakUserMetadata{" + + "meta: " + meta + + '}'; + } } diff --git a/src/main/java/com/basho/riak/client/core/query/indexes/RiakIndexes.java b/src/main/java/com/basho/riak/client/core/query/indexes/RiakIndexes.java index e52ae4550..b445c705d 100644 --- a/src/main/java/com/basho/riak/client/core/query/indexes/RiakIndexes.java +++ b/src/main/java/com/basho/riak/client/core/query/indexes/RiakIndexes.java @@ -197,4 +197,29 @@ public Iterator> iterator() { return indexes.values().iterator(); } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + RiakIndexes that = (RiakIndexes) o; + return indexes.equals(that.indexes); + } + + @Override + public int hashCode() { + return indexes.hashCode(); + } + + @Override + public String toString() { + return "RiakIndexes{" + + "indexes: " + indexes + + '}'; + } } diff --git a/src/main/java/com/basho/riak/client/core/query/links/RiakLinks.java b/src/main/java/com/basho/riak/client/core/query/links/RiakLinks.java index 690299893..1c3df4be0 100644 --- a/src/main/java/com/basho/riak/client/core/query/links/RiakLinks.java +++ b/src/main/java/com/basho/riak/client/core/query/links/RiakLinks.java @@ -125,6 +125,28 @@ public Iterator iterator() return links.iterator(); } - - + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + RiakLinks riakLinks = (RiakLinks) o; + return links.equals(riakLinks.links); + } + + @Override + public int hashCode() { + return links.hashCode(); + } + + @Override + public String toString() { + return "RiakLinks{" + + "links: " + links + + '}'; + } } diff --git a/src/test/java/com/basho/riak/client/api/commands/StoreValueTest.java b/src/test/java/com/basho/riak/client/api/commands/StoreValueTest.java index 8e7d7a7c4..2538e86a9 100644 --- a/src/test/java/com/basho/riak/client/api/commands/StoreValueTest.java +++ b/src/test/java/com/basho/riak/client/api/commands/StoreValueTest.java @@ -28,6 +28,8 @@ import com.basho.riak.client.core.query.Location; import com.basho.riak.client.core.query.Namespace; import com.basho.riak.client.core.query.RiakObject; +import com.basho.riak.client.core.query.indexes.StringBinIndex; +import com.basho.riak.client.core.query.links.RiakLink; import com.basho.riak.client.core.util.BinaryValue; import com.basho.riak.protobuf.RiakKvPB; import org.junit.Before; @@ -76,30 +78,15 @@ public void init() throws Exception when(mockFuture.isDone()).thenReturn(true); when(mockCluster.execute(any(FutureOperation.class))).thenReturn(mockFuture); client = new RiakClient(mockCluster); - riakObject = new RiakObject(); - riakObject.setVClock(vClock); - riakObject.setValue(BinaryValue.create(new byte[]{'O', '_', 'o'})); + riakObject = createRiakObject(); } @Test public void testStore() throws ExecutionException, InterruptedException { - StoreValue.Builder store = - new StoreValue.Builder(riakObject).withLocation(key) - .withOption(Option.ASIS, true) - .withOption(Option.DW, new Quorum(1)) - .withOption(Option.IF_NONE_MATCH, true) - .withOption(Option.IF_NOT_MODIFIED, true) - .withOption(Option.PW, new Quorum(1)) - .withOption(Option.N_VAL, 1) - .withOption(Option.RETURN_BODY, true) - .withOption(Option.RETURN_HEAD, true) - .withOption(Option.SLOPPY_QUORUM, true) - .withOption(Option.TIMEOUT, 1000) - .withOption(Option.W, new Quorum(1)); - - client.execute(store.build()); + StoreValue storeValue = filledStoreValue(riakObject); + client.execute(storeValue); ArgumentCaptor captor = ArgumentCaptor.forClass(StoreOperation.class); @@ -124,5 +111,46 @@ public void testStore() throws ExecutionException, InterruptedException } + @Test + public void testEqualsWithRiakObject() + { + final RiakObject riakObject1 = createRiakObject(); + final RiakObject riakObject2 = createRiakObject(); + + + final StoreValue value1 = filledStoreValue(riakObject1); + final StoreValue value2 = filledStoreValue(riakObject2); + + assertEquals(value1, value2); + } + + private RiakObject createRiakObject() + { + final RiakObject result = new RiakObject(); + result.setValue(BinaryValue.create(new byte[]{'O', '_', 'o'})); + result.getIndexes().getIndex(StringBinIndex.named("foo")).add("bar"); + result.getLinks().addLink(new RiakLink("bucket", "linkkey", "linktag")); + result.getUserMeta().put("foo", "bar"); + result.setVTag("vtag"); + result.setVClock(vClock); + return result; + } + private StoreValue filledStoreValue(final RiakObject riakObject) + { + StoreValue.Builder store = + new StoreValue.Builder(riakObject).withLocation(key) + .withOption(Option.ASIS, true) + .withOption(Option.DW, new Quorum(1)) + .withOption(Option.IF_NONE_MATCH, true) + .withOption(Option.IF_NOT_MODIFIED, true) + .withOption(Option.PW, new Quorum(1)) + .withOption(Option.N_VAL, 1) + .withOption(Option.RETURN_BODY, true) + .withOption(Option.RETURN_HEAD, true) + .withOption(Option.SLOPPY_QUORUM, true) + .withOption(Option.TIMEOUT, 1000) + .withOption(Option.W, new Quorum(1)); + return store.build(); + } } From 907ed9ae2ab80f3b41049317ca0c8a56a28be573 Mon Sep 17 00:00:00 2001 From: Stefan Larsson Date: Thu, 22 Oct 2015 16:44:27 +0200 Subject: [PATCH 2/2] BinIndexQuery-IndexConverter and SecondaryIndex equals(), hashCode() and toString() methods implemented --- .../api/commands/indexes/BinIndexQuery.java | 79 ++++++++++++++---- .../commands/indexes/SecondaryIndexQuery.java | 82 ++++++++++++++++++- 2 files changed, 145 insertions(+), 16 deletions(-) diff --git a/src/main/java/com/basho/riak/client/api/commands/indexes/BinIndexQuery.java b/src/main/java/com/basho/riak/client/api/commands/indexes/BinIndexQuery.java index d61963c5d..5ac12987d 100644 --- a/src/main/java/com/basho/riak/client/api/commands/indexes/BinIndexQuery.java +++ b/src/main/java/com/basho/riak/client/api/commands/indexes/BinIndexQuery.java @@ -20,7 +20,6 @@ import com.basho.riak.client.core.RiakFuture; import com.basho.riak.client.core.operations.SecondaryIndexQueryOperation; import com.basho.riak.client.api.commands.CoreFutureAdapter; -import com.basho.riak.client.api.commands.indexes.SecondaryIndexQuery.IndexConverter; import com.basho.riak.client.core.query.Location; import com.basho.riak.client.core.query.Namespace; import com.basho.riak.client.core.util.BinaryValue; @@ -55,20 +54,7 @@ protected BinIndexQuery(Init builder) { super(builder); this.charset = builder.charset; - this.converter = new IndexConverter() - { - @Override - public String convert(BinaryValue input) - { - return input.toString(charset); - } - - @Override - public BinaryValue convert(String input) - { - return BinaryValue.create(input, charset); - } - }; + this.converter = new StringIndexConverter(); } @Override @@ -88,6 +74,36 @@ protected RiakFuture executeAsync(RiakCluster cluster) return future; } + @Override + public boolean equals(Object o) + { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + if (!super.equals(o)) { + return false; + } + + BinIndexQuery that = (BinIndexQuery) o; + if (!charset.equals(that.charset)) { + return false; + } + + return converter.equals(that.converter); + } + + @Override + public int hashCode() + { + int result = super.hashCode(); + result = 31 * result + charset.hashCode(); + result = 31 * result + converter.hashCode(); + return result; + } + protected final class BinQueryFuture extends CoreFutureAdapter { public BinQueryFuture(RiakFuture coreFuture) @@ -213,4 +229,37 @@ protected Entry(Location riakObjectLocation, BinaryValue indexKey, IndexConverte } } + + private class StringIndexConverter implements IndexConverter + { + @Override + public String convert(BinaryValue input) + { + return input.toString(charset); + } + + @Override + public BinaryValue convert(String input) + { + return BinaryValue.create(input, charset); + } + + @Override + public boolean equals(Object o) + { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + return true; + } + + @Override + public int hashCode() + { + return 0; + } + } } diff --git a/src/main/java/com/basho/riak/client/api/commands/indexes/SecondaryIndexQuery.java b/src/main/java/com/basho/riak/client/api/commands/indexes/SecondaryIndexQuery.java index 77a8f760f..d06bd4972 100644 --- a/src/main/java/com/basho/riak/client/api/commands/indexes/SecondaryIndexQuery.java +++ b/src/main/java/com/basho/riak/client/api/commands/indexes/SecondaryIndexQuery.java @@ -230,7 +230,87 @@ SecondaryIndexQueryOperation.Query> executeCoreAsync(RiakCluster cluster) return cluster.execute(builder.build()); } - + + @Override + public boolean equals(Object o) + { + if (this == o) { + return true; + } + if (!(o instanceof SecondaryIndexQuery)) { + return false; + } + + SecondaryIndexQuery that = (SecondaryIndexQuery) o; + + if (returnTerms != that.returnTerms) { + return false; + } + if (paginationSort != that.paginationSort) { + return false; + } + if (namespace != null ? !namespace.equals(that.namespace) : that.namespace != null) { + return false; + } + if (indexName != null ? !indexName.equals(that.indexName) : that.indexName != null) { + return false; + } + if (continuation != null ? !continuation.equals(that.continuation) : that.continuation != null) { + return false; + } + if (match != null ? !match.equals(that.match) : that.match != null) { + return false; + } + if (start != null ? !start.equals(that.start) : that.start != null) { + return false; + } + if (end != null ? !end.equals(that.end) : that.end != null) { + return false; + } + if (maxResults != null ? !maxResults.equals(that.maxResults) : that.maxResults != null) { + return false; + } + if (termFilter != null ? !termFilter.equals(that.termFilter) : that.termFilter != null) { + return false; + } + return !(timeout != null ? !timeout.equals(that.timeout) : that.timeout != null); + } + + @Override + public int hashCode() + { + int result = namespace != null ? namespace.hashCode() : 0; + result = 31 * result + (indexName != null ? indexName.hashCode() : 0); + result = 31 * result + (continuation != null ? continuation.hashCode() : 0); + result = 31 * result + (match != null ? match.hashCode() : 0); + result = 31 * result + (start != null ? start.hashCode() : 0); + result = 31 * result + (end != null ? end.hashCode() : 0); + result = 31 * result + (maxResults != null ? maxResults.hashCode() : 0); + result = 31 * result + (returnTerms ? 1 : 0); + result = 31 * result + (paginationSort ? 1 : 0); + result = 31 * result + (termFilter != null ? termFilter.hashCode() : 0); + result = 31 * result + (timeout != null ? timeout.hashCode() : 0); + return result; + } + + @Override + public String toString() + { + return "SecondaryIndexQuery{" + + ", continuation: " + continuation + + ", namespace: " + namespace + + ", indexName: " + indexName + + ", match: " + match + + ", start: " + start + + ", end: " + end + + ", maxResults: " + maxResults + + ", returnTerms: " + returnTerms + + ", paginationSort: " + paginationSort + + ", termFilter: '" + termFilter + '\'' + + ", timeout: " + timeout + + '}'; + } + protected interface IndexConverter { T convert(BinaryValue input);