Skip to content

Commit b76ee48

Browse files
committed
Add BigDecimal converter.
Add BigDecimal converter, add converter tests for BigDecimal and BigInteger. Since BigDecimail is not support, it cannot be used in the CustomerConverter tests. So instead use ChoiceFormat for CustomConverter tests. Closes #1439.
1 parent 6eb338b commit b76ee48

File tree

2 files changed

+173
-50
lines changed

2 files changed

+173
-50
lines changed

src/main/java/org/springframework/data/couchbase/core/convert/OtherConverters.java

+24-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2021 the original author or authors
2+
* Copyright 2021-2022 the original author or authors
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -16,6 +16,7 @@
1616

1717
package org.springframework.data.couchbase.core.convert;
1818

19+
import java.math.BigDecimal;
1920
import java.math.BigInteger;
2021
import java.util.ArrayList;
2122
import java.util.Collection;
@@ -47,6 +48,8 @@ private OtherConverters() {}
4748
converters.add(StringToUuid.INSTANCE);
4849
converters.add(BigIntegerToString.INSTANCE);
4950
converters.add(StringToBigInteger.INSTANCE);
51+
converters.add(BigDecimalToString.INSTANCE);
52+
converters.add(StringToBigDecimal.INSTANCE);
5053

5154
return converters;
5255
}
@@ -90,4 +93,24 @@ public BigInteger convert(String source) {
9093
return source == null ? null : new BigInteger(source);
9194
}
9295
}
96+
97+
@WritingConverter
98+
public enum BigDecimalToString implements Converter<BigDecimal, String> {
99+
INSTANCE;
100+
101+
@Override
102+
public String convert(BigDecimal source) {
103+
return source == null ? null : source.toPlainString();
104+
}
105+
}
106+
107+
@ReadingConverter
108+
public enum StringToBigDecimal implements Converter<String, BigDecimal> {
109+
INSTANCE;
110+
111+
@Override
112+
public BigDecimal convert(String source) {
113+
return source == null ? null : new BigDecimal(source);
114+
}
115+
}
93116
}

src/test/java/org/springframework/data/couchbase/core/mapping/MappingCouchbaseConverterTests.java

+149-49
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,32 @@
1616

1717
package org.springframework.data.couchbase.core.mapping;
1818

19-
import static org.assertj.core.api.Assertions.*;
19+
import static org.assertj.core.api.Assertions.assertThat;
20+
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
2021
import static org.assertj.core.data.Offset.offset;
21-
import static org.junit.jupiter.api.Assertions.*;
22+
import static org.junit.jupiter.api.Assertions.assertThrows;
2223

2324
import java.math.BigDecimal;
25+
import java.math.BigInteger;
26+
import java.text.ChoiceFormat;
2427
import java.time.LocalDateTime;
2528
import java.time.temporal.ChronoUnit;
26-
import java.util.*;
29+
import java.util.ArrayList;
30+
import java.util.Arrays;
31+
import java.util.Calendar;
32+
import java.util.Collection;
33+
import java.util.Date;
34+
import java.util.HashMap;
35+
import java.util.HashSet;
36+
import java.util.LinkedHashMap;
37+
import java.util.LinkedList;
38+
import java.util.List;
39+
import java.util.Map;
40+
import java.util.Set;
41+
import java.util.TreeMap;
42+
import java.util.TreeSet;
43+
import java.util.UUID;
44+
import java.util.stream.Collectors;
2745

2846
import org.junit.jupiter.api.Test;
2947
import org.springframework.core.convert.converter.Converter;
@@ -35,7 +53,11 @@
3553
import org.springframework.data.couchbase.core.convert.CouchbaseCustomConversions;
3654
import org.springframework.data.couchbase.core.convert.CouchbaseJsr310Converters.LocalDateTimeToLongConverter;
3755
import org.springframework.data.couchbase.core.convert.MappingCouchbaseConverter;
38-
import org.springframework.data.couchbase.core.mapping.id.*;
56+
import org.springframework.data.couchbase.core.mapping.id.GeneratedValue;
57+
import org.springframework.data.couchbase.core.mapping.id.GenerationStrategy;
58+
import org.springframework.data.couchbase.core.mapping.id.IdAttribute;
59+
import org.springframework.data.couchbase.core.mapping.id.IdPrefix;
60+
import org.springframework.data.couchbase.core.mapping.id.IdSuffix;
3961
import org.springframework.data.couchbase.domain.Address;
4062
import org.springframework.data.couchbase.domain.Config;
4163
import org.springframework.data.couchbase.domain.Person;
@@ -70,8 +92,9 @@ void shouldNotThrowNPE() {
7092
void doesNotAllowSimpleType1() {
7193
try {
7294
converter.write("hello", new CouchbaseDocument());
73-
} catch(Exception e){
74-
if(!(e instanceof MappingException) && !e.getClass().getName().equals("java.lang.reflect.InaccessibleObjectException")){
95+
} catch (Exception e) {
96+
if (!(e instanceof MappingException)
97+
&& !e.getClass().getName().equals("java.lang.reflect.InaccessibleObjectException")) {
7598
throw new RuntimeException("Should have thrown MappingException or InaccessibleObjectException", e);
7699
}
77100
}
@@ -81,8 +104,9 @@ void doesNotAllowSimpleType1() {
81104
void doesNotAllowSimpleType2() {
82105
try {
83106
converter.write(true, new CouchbaseDocument());
84-
} catch(Exception e){
85-
if(!(e instanceof MappingException) && !e.getClass().getName().equals("java.lang.reflect.InaccessibleObjectException")){
107+
} catch (Exception e) {
108+
if (!(e instanceof MappingException)
109+
&& !e.getClass().getName().equals("java.lang.reflect.InaccessibleObjectException")) {
86110
throw new RuntimeException("Should have thrown MappingException or InaccessibleObjectException", e);
87111
}
88112
}
@@ -92,8 +116,9 @@ void doesNotAllowSimpleType2() {
92116
void doesNotAllowSimpleType3() {
93117
try {
94118
converter.write(42, new CouchbaseDocument());
95-
} catch(Exception e){
96-
if(!(e instanceof MappingException) && !e.getClass().getName().equals("java.lang.reflect.InaccessibleObjectException")){
119+
} catch (Exception e) {
120+
if (!(e instanceof MappingException)
121+
&& !e.getClass().getName().equals("java.lang.reflect.InaccessibleObjectException")) {
97122
throw new RuntimeException("Should have thrown MappingException or InaccessibleObjectException", e);
98123
}
99124
}
@@ -112,7 +137,7 @@ void writesString() {
112137
converter.write(entity, converted);
113138
Map<String, Object> result = converted.export();
114139
assertThat(result.get("_class")).isEqualTo(entity.getClass().getName());
115-
assertThat(result.get("attr0")).isEqualTo("foobar");
140+
assertThat(result.get("attr0")).isEqualTo(entity.attr0);
116141
assertThat(converted.getId()).isEqualTo(BaseEntity.ID);
117142
}
118143

@@ -123,7 +148,51 @@ void readsString() {
123148
source.put("attr0", "foobar");
124149

125150
StringEntity converted = converter.read(StringEntity.class, source);
126-
assertThat(converted.attr0).isEqualTo("foobar");
151+
assertThat(converted.attr0).isEqualTo(source.get("attr0"));
152+
}
153+
154+
@Test
155+
void writesBigInteger() {
156+
CouchbaseDocument converted = new CouchbaseDocument();
157+
BigIntegerEntity entity = new BigIntegerEntity(new BigInteger("12345"));
158+
159+
converter.write(entity, converted);
160+
Map<String, Object> result = converted.export();
161+
assertThat(result.get("_class")).isEqualTo(entity.getClass().getName());
162+
assertThat(result.get("attr0")).isEqualTo(entity.attr0.toString());
163+
assertThat(converted.getId()).isEqualTo(BaseEntity.ID);
164+
}
165+
166+
@Test
167+
void readsBigInteger() {
168+
CouchbaseDocument source = new CouchbaseDocument();
169+
source.put("_class", BigIntegerEntity.class.getName());
170+
source.put("attr0", "12345");
171+
172+
BigIntegerEntity converted = converter.read(BigIntegerEntity.class, source);
173+
assertThat(converted.attr0).isEqualTo(new BigInteger((String) source.get("attr0")));
174+
}
175+
176+
@Test
177+
void writesBigDecimal() {
178+
CouchbaseDocument converted = new CouchbaseDocument();
179+
BigDecimalEntity entity = new BigDecimalEntity(new BigDecimal("123.45"));
180+
181+
converter.write(entity, converted);
182+
Map<String, Object> result = converted.export();
183+
assertThat(result.get("_class")).isEqualTo(entity.getClass().getName());
184+
assertThat(result.get("attr0")).isEqualTo(entity.attr0.toString());
185+
assertThat(converted.getId()).isEqualTo(BaseEntity.ID);
186+
}
187+
188+
@Test
189+
void readsBigDecimal() {
190+
CouchbaseDocument source = new CouchbaseDocument();
191+
source.put("_class", BigDecimalEntity.class.getName());
192+
source.put("attr0", "123.45");
193+
194+
BigDecimalEntity converted = converter.read(BigDecimalEntity.class, source);
195+
assertThat(converted.attr0).isEqualTo(new BigDecimal((String) source.get("attr0")));
127196
}
128197

129198
@Test
@@ -438,8 +507,8 @@ void writesAndReadsValueClassCustomType() {
438507
@Test
439508
void writesAndReadsCustomConvertedClass() {
440509
List<Object> converters = new ArrayList<>();
441-
converters.add(BigDecimalToStringConverter.INSTANCE);
442-
converters.add(StringToBigDecimalConverter.INSTANCE);
510+
converters.add(ChoiceFormatToStringConverter.INSTANCE);
511+
converters.add(StringToChoiceFormatConverter.INSTANCE);
443512
CustomConversions customConversions = new CouchbaseCustomConversions(converters);
444513
converter.setCustomConversions(customConversions);
445514
converter.afterPropertiesSet();
@@ -448,14 +517,14 @@ void writesAndReadsCustomConvertedClass() {
448517

449518
CouchbaseDocument converted = new CouchbaseDocument();
450519

451-
final String valueStr = "12.345";
452-
final BigDecimal value = new BigDecimal(valueStr);
453-
final String value2Str = "0.6789";
454-
final BigDecimal value2 = new BigDecimal(value2Str);
455-
List<BigDecimal> listOfValues = new ArrayList<>();
520+
final String valueStr = "1.0,2.0,3.0,4.0,5.0,6.0,7.0|Sun,Mon,Tue,Wed,Thur,Fri,Sat";
521+
final ChoiceFormat value = fromString(valueStr);
522+
final String value2Str = "1.0,2.0,3.0|Jan,Feb,Mar";
523+
final ChoiceFormat value2 = fromString(value2Str);
524+
List<ChoiceFormat> listOfValues = new ArrayList<>();
456525
listOfValues.add(value);
457526
listOfValues.add(value2);
458-
Map<String, BigDecimal> mapOfValues = new TreeMap<>();
527+
Map<String, ChoiceFormat> mapOfValues = new TreeMap<>();
459528
mapOfValues.put("val1", value);
460529
mapOfValues.put("val2", value2);
461530

@@ -486,11 +555,25 @@ void writesAndReadsCustomConvertedClass() {
486555
assertThat(readConverted.mapOfValues.get("val2")).isEqualTo(mapOfValues.get("val2"));
487556
}
488557

558+
static private String toString(ChoiceFormat choiceFormat) {
559+
String limits = Arrays.stream(choiceFormat.getLimits()).mapToObj(String::valueOf).collect(Collectors.joining(","));
560+
String formats = Arrays.stream(choiceFormat.getFormats()).map((o) -> String.valueOf(o))
561+
.collect(Collectors.joining(","));
562+
return limits + "|" + formats;
563+
}
564+
565+
static private ChoiceFormat fromString(String source) {
566+
String[] split = source.split("\\|");
567+
double[] limits = Arrays.stream(split[0].split(",")).mapToDouble(Double::parseDouble).toArray();
568+
String[] formats = split[1].split(",");
569+
return new ChoiceFormat(limits, formats);
570+
}
571+
489572
@Test
490573
void writesAndReadsCustomFieldsConvertedClass() {
491574
List<Object> converters = new ArrayList<>();
492-
converters.add(BigDecimalToStringConverter.INSTANCE);
493-
converters.add(StringToBigDecimalConverter.INSTANCE);
575+
converters.add(ChoiceFormatToStringConverter.INSTANCE);
576+
converters.add(StringToChoiceFormatConverter.INSTANCE);
494577
CustomConversions customConversions = new CouchbaseCustomConversions(converters);
495578
converter.setCustomConversions(customConversions);
496579
converter.afterPropertiesSet();
@@ -499,14 +582,14 @@ void writesAndReadsCustomFieldsConvertedClass() {
499582

500583
CouchbaseDocument converted = new CouchbaseDocument();
501584

502-
final String valueStr = "12.345";
503-
final BigDecimal value = new BigDecimal(valueStr);
504-
final String value2Str = "0.6789";
505-
final BigDecimal value2 = new BigDecimal(value2Str);
506-
List<BigDecimal> listOfValues = new ArrayList<>();
585+
final String valueStr = "1.0,2.0,3.0,4.0,5.0,6.0,7.0|Sun,Mon,Tue,Wed,Thur,Fri,Sat";
586+
final ChoiceFormat value = fromString(valueStr);
587+
final String value2Str = "1.0,2.0,3.0|Jan,Feb,Mar";
588+
final ChoiceFormat value2 = fromString(value2Str);
589+
List<ChoiceFormat> listOfValues = new ArrayList<>();
507590
listOfValues.add(value);
508591
listOfValues.add(value2);
509-
Map<String, BigDecimal> mapOfValues = new HashMap<>();
592+
Map<String, ChoiceFormat> mapOfValues = new TreeMap<>();
510593
mapOfValues.put("val1", value);
511594
mapOfValues.put("val2", value2);
512595

@@ -515,18 +598,18 @@ void writesAndReadsCustomFieldsConvertedClass() {
515598

516599
CouchbaseDocument source = new CouchbaseDocument();
517600
source.put("_class", CustomFieldsEntity.class.getName());
518-
source.put("decimalValue", valueStr);
601+
source.put("choiceFormatValue", valueStr);
519602
CouchbaseList listOfValuesDoc = new CouchbaseList();
520603
listOfValuesDoc.put(valueStr);
521604
listOfValuesDoc.put(value2Str);
522-
source.put("listOfDecimalValues", listOfValuesDoc);
605+
source.put("listOfChoiceFormatValues", listOfValuesDoc);
523606
CouchbaseDocument mapOfValuesDoc = new CouchbaseDocument();
524607
mapOfValuesDoc.put("val1", valueStr);
525608
mapOfValuesDoc.put("val2", value2Str);
526-
source.put("mapOfDecimalValues", mapOfValuesDoc);
609+
source.put("mapOfChoiceFormatValues", mapOfValuesDoc);
527610

528-
assertThat(valueStr).isEqualTo(((CouchbaseList) converted.getContent().get("listOfDecimalValues")).get(0));
529-
assertThat(value2Str).isEqualTo(((CouchbaseList) converted.getContent().get("listOfDecimalValues")).get(1));
611+
assertThat(valueStr).isEqualTo(((CouchbaseList) converted.getContent().get("listOfChoiceFormatValues")).get(0));
612+
assertThat(value2Str).isEqualTo(((CouchbaseList) converted.getContent().get("listOfChoiceFormatValues")).get(1));
530613
assertThat(converted.export().toString()).isEqualTo(source.export().toString());
531614

532615
CustomFieldsEntity readConverted = converter.read(CustomFieldsEntity.class, source);
@@ -540,8 +623,8 @@ void writesAndReadsCustomFieldsConvertedClass() {
540623
@Test
541624
void writesAndReadsClassContainingCustomConvertedObjects() {
542625
List<Object> converters = new ArrayList<>();
543-
converters.add(BigDecimalToStringConverter.INSTANCE);
544-
converters.add(StringToBigDecimalConverter.INSTANCE);
626+
converters.add(ChoiceFormatToStringConverter.INSTANCE);
627+
converters.add(StringToChoiceFormatConverter.INSTANCE);
545628
CustomConversions customConversions = new CouchbaseCustomConversions(converters);
546629
converter.setCustomConversions(customConversions);
547630
converter.afterPropertiesSet();
@@ -635,22 +718,22 @@ void writesAndReadsNestedClass() {
635718
}
636719

637720
@WritingConverter
638-
public enum BigDecimalToStringConverter implements Converter<BigDecimal, String> {
721+
public enum ChoiceFormatToStringConverter implements Converter<ChoiceFormat, String> {
639722
INSTANCE;
640723

641724
@Override
642-
public String convert(BigDecimal source) {
643-
return source.toPlainString();
725+
public String convert(ChoiceFormat source) {
726+
return MappingCouchbaseConverterTests.toString(source);
644727
}
645728
}
646729

647730
@ReadingConverter
648-
public enum StringToBigDecimalConverter implements Converter<String, BigDecimal> {
731+
public enum StringToChoiceFormatConverter implements Converter<String, ChoiceFormat> {
649732
INSTANCE;
650733

651734
@Override
652-
public BigDecimal convert(String source) {
653-
return new BigDecimal(source);
735+
public ChoiceFormat convert(String source) {
736+
return MappingCouchbaseConverterTests.fromString(source);
654737
}
655738
}
656739

@@ -676,6 +759,22 @@ public StringEntity(String attr0) {
676759
}
677760
}
678761

762+
static class BigIntegerEntity extends BaseEntity {
763+
private BigInteger attr0;
764+
765+
public BigIntegerEntity(BigInteger attr0) {
766+
this.attr0 = attr0;
767+
}
768+
}
769+
770+
static class BigDecimalEntity extends BaseEntity {
771+
private BigDecimal attr0;
772+
773+
public BigDecimalEntity(BigDecimal attr0) {
774+
this.attr0 = attr0;
775+
}
776+
}
777+
679778
static class NumberEntity extends BaseEntity {
680779
private long attr0;
681780

@@ -770,23 +869,24 @@ public Email(String emailAddr) {
770869
}
771870

772871
static class CustomEntity extends BaseEntity {
773-
private BigDecimal value;
774-
private List<BigDecimal> listOfValues;
775-
private Map<String, BigDecimal> mapOfValues;
872+
private ChoiceFormat value;
873+
private List<ChoiceFormat> listOfValues;
874+
private Map<String, ChoiceFormat> mapOfValues;
776875

777-
public CustomEntity(BigDecimal value, List<BigDecimal> listOfValues, Map<String, BigDecimal> mapOfValues) {
876+
public CustomEntity(ChoiceFormat value, List<ChoiceFormat> listOfValues, Map<String, ChoiceFormat> mapOfValues) {
778877
this.value = value;
779878
this.listOfValues = listOfValues;
780879
this.mapOfValues = mapOfValues;
781880
}
782881
}
783882

784883
static class CustomFieldsEntity extends BaseEntity {
785-
@Field("decimalValue") private BigDecimal value;
786-
@Field("listOfDecimalValues") private List<BigDecimal> listOfValues;
787-
@Field("mapOfDecimalValues") private Map<String, BigDecimal> mapOfValues;
884+
@Field("choiceFormatValue") private ChoiceFormat value;
885+
@Field("listOfChoiceFormatValues") private List<ChoiceFormat> listOfValues;
886+
@Field("mapOfChoiceFormatValues") private Map<String, ChoiceFormat> mapOfValues;
788887

789-
public CustomFieldsEntity(BigDecimal value, List<BigDecimal> listOfValues, Map<String, BigDecimal> mapOfValues) {
888+
public CustomFieldsEntity(ChoiceFormat value, List<ChoiceFormat> listOfValues,
889+
Map<String, ChoiceFormat> mapOfValues) {
790890
this.value = value;
791891
this.listOfValues = listOfValues;
792892
this.mapOfValues = mapOfValues;

0 commit comments

Comments
 (0)