Skip to content

Commit 06e985e

Browse files
DATAMONGO-1288 - Add conversion for AtomicInteger & AtomicLong.
We now convert AtomicInteger and AtomicLong to the required Number target type by calling get() followed by the actual conversion. This allows to directly use these types eg. as part of an Update. new Update().set("intValue", new AtomicInteger(10));
1 parent 059de55 commit 06e985e

File tree

4 files changed

+155
-4
lines changed

4 files changed

+155
-4
lines changed

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/CustomConversions.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
import org.springframework.data.mongodb.core.convert.MongoConverters.DBObjectToNamedMongoScriptCoverter;
4848
import org.springframework.data.mongodb.core.convert.MongoConverters.DBObjectToStringConverter;
4949
import org.springframework.data.mongodb.core.convert.MongoConverters.NamedMongoScriptToDBObjectConverter;
50+
import org.springframework.data.mongodb.core.convert.MongoConverters.NumberToNumberConverterFactory;
5051
import org.springframework.data.mongodb.core.convert.MongoConverters.StringToBigDecimalConverter;
5152
import org.springframework.data.mongodb.core.convert.MongoConverters.StringToBigIntegerConverter;
5253
import org.springframework.data.mongodb.core.convert.MongoConverters.StringToURLConverter;
@@ -122,6 +123,7 @@ public CustomConversions(List<?> converters) {
122123
toRegister.add(TermToStringConverter.INSTANCE);
123124
toRegister.add(NamedMongoScriptToDBObjectConverter.INSTANCE);
124125
toRegister.add(DBObjectToNamedMongoScriptCoverter.INSTANCE);
126+
toRegister.add(NumberToNumberConverterFactory.INSTANCE);
125127

126128
toRegister.addAll(JodaTimeConverters.getConvertersToRegister());
127129
toRegister.addAll(GeoConverters.getConvertersToRegister());

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoConverters.java

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,21 @@
1919
import java.math.BigInteger;
2020
import java.net.MalformedURLException;
2121
import java.net.URL;
22+
import java.util.concurrent.atomic.AtomicInteger;
23+
import java.util.concurrent.atomic.AtomicLong;
2224

2325
import org.bson.types.Code;
2426
import org.bson.types.ObjectId;
2527
import org.springframework.core.convert.ConversionFailedException;
2628
import org.springframework.core.convert.TypeDescriptor;
29+
import org.springframework.core.convert.converter.ConditionalConverter;
2730
import org.springframework.core.convert.converter.Converter;
31+
import org.springframework.core.convert.converter.ConverterFactory;
2832
import org.springframework.data.convert.ReadingConverter;
2933
import org.springframework.data.convert.WritingConverter;
3034
import org.springframework.data.mongodb.core.query.Term;
3135
import org.springframework.data.mongodb.core.script.NamedMongoScript;
36+
import org.springframework.util.NumberUtils;
3237
import org.springframework.util.StringUtils;
3338

3439
import com.mongodb.BasicDBObject;
@@ -228,4 +233,50 @@ public DBObject convert(NamedMongoScript source) {
228233
return builder.get();
229234
}
230235
}
236+
237+
/**
238+
* {@link ConverterFactory} implementation using {@link NumberUtils} for number conversion and parsing. Additionally
239+
* deals with {@link AtomicInteger} and {@link AtomicLong} by calling {@code get()} before performing the actual
240+
* conversion.
241+
*
242+
* @author Christoph Strobl
243+
* @since 1.9
244+
*/
245+
@WritingConverter
246+
public static enum NumberToNumberConverterFactory implements ConverterFactory<Number, Number>, ConditionalConverter {
247+
248+
INSTANCE;
249+
250+
@Override
251+
public <T extends Number> Converter<Number, T> getConverter(Class<T> targetType) {
252+
return new NumberToNumber<T>(targetType);
253+
}
254+
255+
@Override
256+
public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
257+
return !sourceType.equals(targetType);
258+
}
259+
260+
private final static class NumberToNumber<T extends Number> implements Converter<Number, T> {
261+
262+
private final Class<T> targetType;
263+
264+
public NumberToNumber(Class<T> targetType) {
265+
this.targetType = targetType;
266+
}
267+
268+
@Override
269+
public T convert(Number source) {
270+
271+
if (source instanceof AtomicInteger) {
272+
return NumberUtils.convertNumberToTargetClass(((AtomicInteger) source).get(), this.targetType);
273+
}
274+
if (source instanceof AtomicLong) {
275+
return NumberUtils.convertNumberToTargetClass(((AtomicLong) source).get(), this.targetType);
276+
}
277+
278+
return NumberUtils.convertNumberToTargetClass(source, this.targetType);
279+
}
280+
}
281+
}
231282
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/*
2+
* Copyright 2015 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.data.mongodb.core.convert;
17+
18+
import static org.hamcrest.core.Is.*;
19+
import static org.junit.Assert.*;
20+
21+
import java.util.Arrays;
22+
import java.util.Collection;
23+
import java.util.concurrent.atomic.AtomicInteger;
24+
import java.util.concurrent.atomic.AtomicLong;
25+
26+
import org.junit.Test;
27+
import org.junit.runner.RunWith;
28+
import org.junit.runners.Parameterized;
29+
import org.junit.runners.Parameterized.Parameter;
30+
import org.junit.runners.Parameterized.Parameters;
31+
import org.springframework.data.mongodb.core.convert.MongoConverters.NumberToNumberConverterFactory;
32+
33+
/**
34+
* @author Christoph Strobl
35+
*/
36+
@RunWith(Parameterized.class)
37+
public class NumberToNumberConverterFactoryUnitTests {
38+
39+
public @Parameter(0) Number source;
40+
41+
public @Parameter(1) Number expected;
42+
43+
@Parameters
44+
public static Collection<Number[]> parameters() {
45+
46+
Number[] longToInt = new Number[] { new Long(10), new Integer(10) };
47+
Number[] atomicIntToInt = new Number[] { new AtomicInteger(10), new Integer(10) };
48+
Number[] atomicIntToDouble = new Number[] { new AtomicInteger(10), new Double(10) };
49+
Number[] atomicLongToInt = new Number[] { new AtomicLong(10), new Integer(10) };
50+
Number[] atomicLongToLong = new Number[] { new AtomicLong(10), new Long(10) };
51+
52+
return Arrays.<Number[]> asList(longToInt, atomicIntToInt, atomicIntToDouble, atomicLongToInt, atomicLongToLong);
53+
}
54+
55+
/**
56+
* @see DATAMONGO-1288
57+
*/
58+
@Test
59+
public void convertsToTargetTypeCorrectly() {
60+
assertThat(NumberToNumberConverterFactory.INSTANCE.getConverter(expected.getClass()).convert(source), is(expected));
61+
}
62+
}

spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/UpdateMapperUnitTests.java

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,11 @@
2727
import java.util.Collections;
2828
import java.util.List;
2929
import java.util.Map;
30+
import java.util.concurrent.atomic.AtomicInteger;
3031

3132
import org.hamcrest.Matcher;
3233
import org.hamcrest.collection.IsIterableContainingInOrder;
34+
import org.hamcrest.core.Is;
3335
import org.hamcrest.core.IsEqual;
3436
import org.junit.Before;
3537
import org.junit.Test;
@@ -794,7 +796,7 @@ public void mapsUpdateWithBothReadingAndWritingConverterRegistered() {
794796
}
795797

796798
/**
797-
* see DATAMONGO-1251
799+
* @see DATAMONGO-1251
798800
*/
799801
@Test
800802
public void mapsNullValueCorrectlyForSimpleTypes() {
@@ -810,7 +812,7 @@ public void mapsNullValueCorrectlyForSimpleTypes() {
810812
}
811813

812814
/**
813-
* see DATAMONGO-1251
815+
* @see DATAMONGO-1251
814816
*/
815817
@Test
816818
public void mapsNullValueCorrectlyForJava8Date() {
@@ -826,7 +828,7 @@ public void mapsNullValueCorrectlyForJava8Date() {
826828
}
827829

828830
/**
829-
* see DATAMONGO-1251
831+
* @see DATAMONGO-1251
830832
*/
831833
@Test
832834
public void mapsNullValueCorrectlyForCollectionTypes() {
@@ -842,7 +844,7 @@ public void mapsNullValueCorrectlyForCollectionTypes() {
842844
}
843845

844846
/**
845-
* see DATAMONGO-1251
847+
* @see DATAMONGO-1251
846848
*/
847849
@Test
848850
public void mapsNullValueCorrectlyForPropertyOfNestedDocument() {
@@ -857,6 +859,34 @@ public void mapsNullValueCorrectlyForPropertyOfNestedDocument() {
857859
assertThat($set.get("concreteValue.name"), nullValue());
858860
}
859861

862+
/**
863+
* @see DATAMONGO-1288
864+
*/
865+
@Test
866+
public void mapsAtomicIntegerToIntegerCorrectly() {
867+
868+
Update update = new Update().set("intValue", new AtomicInteger(10));
869+
DBObject mappedUpdate = mapper.getMappedObject(update.getUpdateObject(),
870+
context.getPersistentEntity(SimpleValueHolder.class));
871+
872+
DBObject $set = DBObjectTestUtils.getAsDBObject(mappedUpdate, "$set");
873+
assertThat($set.get("intValue"), Is.<Object> is(10));
874+
}
875+
876+
/**
877+
* @see DATAMONGO-1288
878+
*/
879+
@Test
880+
public void mapsAtomicIntegerToPrimitiveIntegerCorrectly() {
881+
882+
Update update = new Update().set("primIntValue", new AtomicInteger(10));
883+
DBObject mappedUpdate = mapper.getMappedObject(update.getUpdateObject(),
884+
context.getPersistentEntity(SimpleValueHolder.class));
885+
886+
DBObject $set = DBObjectTestUtils.getAsDBObject(mappedUpdate, "$set");
887+
assertThat($set.get("primIntValue"), Is.<Object> is(10));
888+
}
889+
860890
static class DomainTypeWrappingConcreteyTypeHavingListOfInterfaceTypeAttributes {
861891
ListModelWrapper concreteTypeWithListAttributeOfInterfaceType;
862892
}
@@ -1131,4 +1161,10 @@ static class ClassWithJava8Date {
11311161

11321162
LocalDate date;
11331163
}
1164+
1165+
static class SimpleValueHolder {
1166+
1167+
Integer intValue;
1168+
int primIntValue;
1169+
}
11341170
}

0 commit comments

Comments
 (0)