Skip to content

Commit 1418a77

Browse files
authored
[LANG-1452] RecursiveToStringStyle and MultilineRecursiveToStringStyle shouldn't recurse into a java.math.BigDecimal (#1584)
* Add testLang1641() * Rename some test methods * [LANG-1452] RecursiveToStringStyle and MultilineRecursiveToStringStyle shouldn't recurse into a java.math.BigDecimal - We already don't recurse into a Decimal and other boxed primitive. - Don't recurse into Number subclasses. - Don't recurse into AtomicBoolean.
1 parent 3f803b8 commit 1418a77

2 files changed

Lines changed: 77 additions & 12 deletions

File tree

src/main/java/org/apache/commons/lang3/builder/RecursiveToStringStyle.java

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,10 @@
1717
package org.apache.commons.lang3.builder;
1818

1919
import java.util.Collection;
20+
import java.util.concurrent.atomic.AtomicBoolean;
2021

2122
import org.apache.commons.lang3.ClassUtils;
23+
import org.apache.commons.lang3.mutable.MutableBoolean;
2224

2325
/**
2426
* Works with {@link ToStringBuilder} to create a "deep" {@code toString}.
@@ -66,16 +68,29 @@ public RecursiveToStringStyle() {
6668
}
6769

6870
/**
69-
* Returns whether or not to recursively format the given {@link Class}.
70-
* By default, this method always returns {@code true}, but may be overwritten by
71-
* subclasses to filter specific classes.
71+
* Tests whether or not to recursively format the given {@link Class}.
72+
* <p>
73+
* By default, this method always filters out the following:
74+
* </p>
75+
* <ul>
76+
* <li><a href="https://docs.oracle.com/javase/specs/jls/se25/html/jls-5.html#jls-5.1.7">Boxed primitives</a>, see {@link ClassUtils#isPrimitiveWrapper(Class)}
77+
* <li>{@link String}</li>
78+
* <li>{@link Number} subclasses</li>
79+
* <li>{@link AtomicBoolean}</li>
80+
* <li>{@link MutableBoolean}</li>
81+
* </ul>
7282
*
73-
* @param clazz
74-
* The class to test.
75-
* @return Whether or not to recursively format the given {@link Class}.
83+
* @param clazz The class to test.
84+
* @return Whether or not to recursively format instances of the given {@link Class}.
7685
*/
7786
protected boolean accept(final Class<?> clazz) {
78-
return true;
87+
// @formatter:off
88+
return !ClassUtils.isPrimitiveWrapper(clazz) &&
89+
!String.class.equals(clazz) &&
90+
!Number.class.isAssignableFrom(clazz) &&
91+
!AtomicBoolean.class.equals(clazz) &&
92+
!MutableBoolean.class.equals(clazz);
93+
// @formatter:on
7994
}
8095

8196
@Override
@@ -87,10 +102,7 @@ protected void appendDetail(final StringBuffer buffer, final String fieldName, f
87102

88103
@Override
89104
public void appendDetail(final StringBuffer buffer, final String fieldName, final Object value) {
90-
final Class<? extends Object> clazz = value.getClass();
91-
if (!ClassUtils.isPrimitiveWrapper(clazz) &&
92-
!String.class.equals(clazz) &&
93-
accept(clazz)) {
105+
if (value != null && accept(value.getClass())) {
94106
buffer.append(ReflectionToStringBuilder.toString(value, this));
95107
} else {
96108
super.appendDetail(buffer, fieldName, value);

src/test/java/org/apache/commons/lang3/builder/RecursiveToStringStyleTest.java

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,22 @@
1818

1919
import static org.junit.jupiter.api.Assertions.assertEquals;
2020

21+
import java.math.BigDecimal;
22+
import java.math.BigInteger;
2123
import java.util.ArrayList;
2224
import java.util.HashMap;
25+
import java.util.concurrent.atomic.AtomicBoolean;
26+
import java.util.concurrent.atomic.AtomicInteger;
27+
import java.util.concurrent.atomic.AtomicLong;
2328

2429
import org.apache.commons.lang3.AbstractLangTest;
30+
import org.apache.commons.lang3.mutable.MutableBoolean;
31+
import org.apache.commons.lang3.mutable.MutableByte;
32+
import org.apache.commons.lang3.mutable.MutableDouble;
33+
import org.apache.commons.lang3.mutable.MutableFloat;
34+
import org.apache.commons.lang3.mutable.MutableInt;
35+
import org.apache.commons.lang3.mutable.MutableLong;
36+
import org.apache.commons.lang3.mutable.MutableShort;
2537
import org.junit.jupiter.api.AfterEach;
2638
import org.junit.jupiter.api.BeforeEach;
2739
import org.junit.jupiter.api.Test;
@@ -85,6 +97,30 @@ void testAppendSuper() {
8597
assertEquals(baseStr + "[a=hello]", new ToStringBuilder(base).appendSuper(null).append("a", "hello").toString());
8698
}
8799

100+
@Test
101+
void testAtomicsArray() {
102+
assertEquals(baseStr + "[{<null>,5,{3,6}}]",
103+
new ToStringBuilder(base).append(new Object[] { null, base, new AtomicLong[] { new AtomicLong(3), new AtomicLong(6) } }).toString());
104+
assertEquals(baseStr + "[{<null>,5,{3,6}}]",
105+
new ToStringBuilder(base).append(new Object[] { null, base, new AtomicInteger[] { new AtomicInteger(3), new AtomicInteger(6) } }).toString());
106+
assertEquals(baseStr + "[{<null>,5,{true,false}}]",
107+
new ToStringBuilder(base).append(new Object[] { null, base, new AtomicBoolean[] { new AtomicBoolean(true), new AtomicBoolean(false) } }).toString());
108+
}
109+
110+
@Test
111+
void testBigDecimal() {
112+
assertEquals(baseStr + "[{<null>,5,{3,6}}]",
113+
new ToStringBuilder(base).append(new Object[] { null, base, new BigDecimal[] { BigDecimal.valueOf(3), BigDecimal.valueOf(6) } }).toString());
114+
assertEquals(baseStr + "[{<null>,5,{3.0,6.0}}]",
115+
new ToStringBuilder(base).append(new Object[] { null, base, new BigDecimal[] { BigDecimal.valueOf(3.0), BigDecimal.valueOf(6.0) } }).toString());
116+
}
117+
118+
@Test
119+
void testBigInteger() {
120+
assertEquals(baseStr + "[{<null>,5,{3,6}}]",
121+
new ToStringBuilder(base).append(new Object[] { null, base, new BigInteger[] { BigInteger.valueOf(3), BigInteger.valueOf(6) } }).toString());
122+
}
123+
88124
@Test
89125
void testBlank() {
90126
assertEquals(baseStr + "[]", new ToStringBuilder(base).toString());
@@ -117,6 +153,24 @@ void testLongArrayArray() {
117153
assertEquals(baseStr + "[<null>]", new ToStringBuilder(base).append((Object) array).toString());
118154
}
119155

156+
@Test
157+
void testMutableWrapperArray() {
158+
assertEquals(baseStr + "[{<null>,5,{3,6}}]",
159+
new ToStringBuilder(base).append(new Object[] { null, base, new MutableLong[] { new MutableLong(3), new MutableLong(6) } }).toString());
160+
assertEquals(baseStr + "[{<null>,5,{3,6}}]",
161+
new ToStringBuilder(base).append(new Object[] { null, base, new MutableInt[] { new MutableInt(3), new MutableInt(6) } }).toString());
162+
assertEquals(baseStr + "[{<null>,5,{3,6}}]",
163+
new ToStringBuilder(base).append(new Object[] { null, base, new MutableShort[] { new MutableShort(3), new MutableShort(6) } }).toString());
164+
assertEquals(baseStr + "[{<null>,5,{3,6}}]",
165+
new ToStringBuilder(base).append(new Object[] { null, base, new MutableByte[] { new MutableByte((byte) 3), new MutableByte((byte) 6) } }).toString());
166+
assertEquals(baseStr + "[{<null>,5,{3.0,6.0}}]",
167+
new ToStringBuilder(base).append(new Object[] { null, base, new MutableFloat[] { new MutableFloat(3f), new MutableFloat(6f) } }).toString());
168+
assertEquals(baseStr + "[{<null>,5,{3.0,6.0}}]",
169+
new ToStringBuilder(base).append(new Object[] { null, base, new MutableDouble[] { new MutableDouble(3d), new MutableDouble(6d) } }).toString());
170+
assertEquals(baseStr + "[{<null>,5,{true,false}}]",
171+
new ToStringBuilder(base).append(new Object[] { null, base, new MutableBoolean[] { new MutableBoolean(true), new MutableBoolean(false) } }).toString());
172+
}
173+
120174
@Test
121175
void testObject() {
122176
final Integer i3 = Integer.valueOf(3);
@@ -174,5 +228,4 @@ void testPrimitiveWrapperArray() {
174228
assertEquals(baseStr + "[{<null>,5,{true,false}}]",
175229
new ToStringBuilder(base).append(new Object[] { null, base, new Boolean[] { true, false } }).toString());
176230
}
177-
178231
}

0 commit comments

Comments
 (0)