1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * https://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 package org.apache.commons.lang3.builder;
18
19 import java.util.Collection;
20
21 import org.apache.commons.lang3.ClassUtils;
22
23 /**
24 * Works with {@link ToStringBuilder} to create a "deep" {@code toString}.
25 *
26 * <p>To use this class write code as follows:</p>
27 *
28 * <pre>
29 * public class Job {
30 * String title;
31 * ...
32 * }
33 *
34 * public class Person {
35 * String name;
36 * int age;
37 * boolean smoker;
38 * Job job;
39 *
40 * ...
41 *
42 * public String toString() {
43 * return new ReflectionToStringBuilder(this, new RecursiveToStringStyle()).toString();
44 * }
45 * }
46 * </pre>
47 *
48 * <p>This will produce a toString of the format:
49 * {@code Person@7f54[name=Stephen,age=29,smoker=false,job=Job@43cd2[title=Manager]]}</p>
50 *
51 * @since 3.2
52 */
53 public class RecursiveToStringStyle extends ToStringStyle {
54
55 /**
56 * Required for serialization support.
57 *
58 * @see java.io.Serializable
59 */
60 private static final long serialVersionUID = 1L;
61
62 /**
63 * Constructs a new instance.
64 */
65 public RecursiveToStringStyle() {
66 }
67
68 /**
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.
72 *
73 * @param clazz
74 * The class to test.
75 * @return Whether or not to recursively format the given {@link Class}.
76 */
77 protected boolean accept(final Class<?> clazz) {
78 return true;
79 }
80
81 @Override
82 protected void appendDetail(final StringBuffer buffer, final String fieldName, final Collection<?> coll) {
83 appendClassName(buffer, coll);
84 appendIdentityHashCode(buffer, coll);
85 appendDetail(buffer, fieldName, coll.toArray());
86 }
87
88 @Override
89 public void appendDetail(final StringBuffer buffer, final String fieldName, final Object value) {
90 if (!ClassUtils.isPrimitiveWrapper(value.getClass()) &&
91 !String.class.equals(value.getClass()) &&
92 accept(value.getClass())) {
93 buffer.append(ReflectionToStringBuilder.toString(value, this));
94 } else {
95 super.appendDetail(buffer, fieldName, value);
96 }
97 }
98 }