DATACMNS-378 - Fixed ClassCastException in MapReduceResults.

The parseCount(…) method now safely converts both integer and long values from the source DBObject.
This commit is contained in:
Oliver Gierke
2012-11-29 13:22:30 +01:00
parent 04a87b373d
commit 4e16f7ebe2
4 changed files with 100 additions and 15 deletions

View File

@@ -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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with 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; package org.springframework.data.mongodb.core.mapreduce;
/** /**
* Value object to encapsulate results of a map-reduce count.
*
* @author Mark Pollack * @author Mark Pollack
* @author Oliver Gierke
*/ */
public class MapReduceCounts { public class MapReduceCounts {
private final int inputCount; public static MapReduceCounts NONE = new MapReduceCounts(-1, -1, -1);
private final int emitCount;
private final int outputCount; 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.inputCount = inputCount;
this.emitCount = emitCount; this.emitCount = emitCount;
this.outputCount = outputCount; this.outputCount = outputCount;
} }
public int getInputCount() { public long getInputCount() {
return inputCount; return inputCount;
} }
public int getEmitCount() { public long getEmitCount() {
return emitCount; return emitCount;
} }
public int getOutputCount() { public long getOutputCount() {
return outputCount; return outputCount;
} }
@@ -59,12 +71,15 @@ public class MapReduceCounts {
*/ */
@Override @Override
public int hashCode() { public int hashCode() {
final int prime = 31; final int prime = 31;
int result = 1; long result = 1;
result = prime * result + emitCount; result = prime * result + emitCount;
result = prime * result + inputCount; result = prime * result + inputCount;
result = prime * result + outputCount; result = prime * result + outputCount;
return result;
return Long.valueOf(result).intValue();
} }
/* /*

View File

@@ -118,15 +118,14 @@ public class MapReduceResults<T> implements Iterable<T> {
DBObject counts = (DBObject) rawResults.get("counts"); DBObject counts = (DBObject) rawResults.get("counts");
if (counts == null) { 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) { if (counts.get("input") != null && counts.get("emit") != null && counts.get("output") != null) {
return new MapReduceCounts((Integer) counts.get("input"), (Integer) counts.get("emit"), return new MapReduceCounts(getAsLong(counts, "input"), getAsLong(counts, "emit"), getAsLong(counts, "output"));
(Integer) counts.get("output"));
} }
return new MapReduceCounts(-1, -1, -1); return MapReduceCounts.NONE;
} }
/** /**

View File

@@ -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())));
}
}

View File

@@ -69,4 +69,18 @@ public class MapReduceResultsUnitTests {
DBObject source = new BasicDBObject("timing", inner); DBObject source = new BasicDBObject("timing", inner);
new MapReduceResults<Object>(Collections.emptyList(), source); new MapReduceResults<Object>(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<Object>(Collections.emptyList(), source);
}
} }