From 4e16f7ebe28745d9429a777b0c7b5a60ebdbf2e8 Mon Sep 17 00:00:00 2001 From: Oliver Gierke Date: Thu, 29 Nov 2012 13:22:30 +0100 Subject: [PATCH] DATACMNS-378 - Fixed ClassCastException in MapReduceResults. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The parseCount(…) method now safely converts both integer and long values from the source DBObject. --- .../core/mapreduce/MapReduceCounts.java | 37 ++++++++---- .../core/mapreduce/MapReduceResults.java | 7 +-- .../mapreduce/MapReduceCountsUnitTests.java | 57 +++++++++++++++++++ .../mapreduce/MapReduceResultsUnitTests.java | 14 +++++ 4 files changed, 100 insertions(+), 15 deletions(-) create mode 100644 spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/MapReduceCountsUnitTests.java diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapreduce/MapReduceCounts.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapreduce/MapReduceCounts.java index 5386ce1bf..befcbf873 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapreduce/MapReduceCounts.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapreduce/MapReduceCounts.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2011 the original author or authors. + * Copyright 2010-2012 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,30 +16,42 @@ package org.springframework.data.mongodb.core.mapreduce; /** + * Value object to encapsulate results of a map-reduce count. + * * @author Mark Pollack + * @author Oliver Gierke */ public class MapReduceCounts { - private final int inputCount; - private final int emitCount; - private final int outputCount; + public static MapReduceCounts NONE = new MapReduceCounts(-1, -1, -1); + + private final long inputCount; + private final long emitCount; + private final long outputCount; + + /** + * Creates a new {@link MapReduceCounts} using the given input count, emit count, and output count. + * + * @param inputCount + * @param emitCount + * @param outputCount + */ + public MapReduceCounts(long inputCount, long emitCount, long outputCount) { - public MapReduceCounts(int inputCount, int emitCount, int outputCount) { - super(); this.inputCount = inputCount; this.emitCount = emitCount; this.outputCount = outputCount; } - public int getInputCount() { + public long getInputCount() { return inputCount; } - public int getEmitCount() { + public long getEmitCount() { return emitCount; } - public int getOutputCount() { + public long getOutputCount() { return outputCount; } @@ -59,12 +71,15 @@ public class MapReduceCounts { */ @Override public int hashCode() { + final int prime = 31; - int result = 1; + long result = 1; + result = prime * result + emitCount; result = prime * result + inputCount; result = prime * result + outputCount; - return result; + + return Long.valueOf(result).intValue(); } /* diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapreduce/MapReduceResults.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapreduce/MapReduceResults.java index 34769d7ea..981ca1a3f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapreduce/MapReduceResults.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapreduce/MapReduceResults.java @@ -118,15 +118,14 @@ public class MapReduceResults implements Iterable { DBObject counts = (DBObject) rawResults.get("counts"); if (counts == null) { - return new MapReduceCounts(-1, -1, -1); + return MapReduceCounts.NONE; } if (counts.get("input") != null && counts.get("emit") != null && counts.get("output") != null) { - return new MapReduceCounts((Integer) counts.get("input"), (Integer) counts.get("emit"), - (Integer) counts.get("output")); + return new MapReduceCounts(getAsLong(counts, "input"), getAsLong(counts, "emit"), getAsLong(counts, "output")); } - return new MapReduceCounts(-1, -1, -1); + return MapReduceCounts.NONE; } /** diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/MapReduceCountsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/MapReduceCountsUnitTests.java new file mode 100644 index 000000000..a0da06bc0 --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/MapReduceCountsUnitTests.java @@ -0,0 +1,57 @@ +/* + * Copyright 2012 the original author or authors. + * + * Licensed 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.springframework.data.mongodb.core.mapreduce; + +import static org.hamcrest.CoreMatchers.*; +import static org.junit.Assert.*; + +import org.junit.Test; + +/** + * Unit tests for {@link MapReduceCounts}. + * + * @author Oliver Gierke + */ +public class MapReduceCountsUnitTests { + + /** + * @see DATACMNS-378 + */ + @Test + public void equalsForSameNumberValues() { + + MapReduceCounts left = new MapReduceCounts(1L, 1L, 1L); + MapReduceCounts right = new MapReduceCounts(1L, 1L, 1L); + + assertThat(left, is(right)); + assertThat(right, is(left)); + assertThat(left.hashCode(), is(right.hashCode())); + } + + /** + * @see DATACMNS-378 + */ + @Test + public void notEqualForDifferentNumberValues() { + + MapReduceCounts left = new MapReduceCounts(1L, 1L, 1L); + MapReduceCounts right = new MapReduceCounts(1L, 2L, 1L); + + assertThat(left, is(not(right))); + assertThat(right, is(not(left))); + assertThat(left.hashCode(), is(not(right.hashCode()))); + } +} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/MapReduceResultsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/MapReduceResultsUnitTests.java index ac7b29d61..087ee786e 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/MapReduceResultsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/MapReduceResultsUnitTests.java @@ -69,4 +69,18 @@ public class MapReduceResultsUnitTests { DBObject source = new BasicDBObject("timing", inner); new MapReduceResults(Collections.emptyList(), source); } + + /** + * @see DATAMONGO-378 + */ + @Test + public void handlesLongResultsForCounts() { + + DBObject inner = new BasicDBObject("input", 1L); + inner.put("emit", 1L); + inner.put("output", 1); + + DBObject source = new BasicDBObject("counts", inner); + new MapReduceResults(Collections.emptyList(), source); + } }