001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 018package org.apache.commons.lang3.builder; 019 020import org.apache.commons.lang3.ClassUtils; 021import org.apache.commons.lang3.SystemUtils; 022 023/** 024 * <p>Works with {@link ToStringBuilder} to create a "deep" <code>toString</code>. 025 * But instead a single line like the {@link RecursiveToStringStyle} this creates a multiline String 026 * similar to the {@link ToStringStyle#MULTI_LINE_STYLE}.</p> 027 * 028 * <p>To use this class write code as follows:</p> 029 * 030 * <pre> 031 * public class Job { 032 * String title; 033 * ... 034 * } 035 * 036 * public class Person { 037 * String name; 038 * int age; 039 * boolean smoker; 040 * Job job; 041 * 042 * ... 043 * 044 * public String toString() { 045 * return new ReflectionToStringBuilder(this, new MultilineRecursiveToStringStyle()).toString(); 046 * } 047 * } 048 * </pre> 049 * 050 * <p> 051 * This will produce a toString of the format:<br> 052 * <code>Person@7f54[ <br> 053 * name=Stephen, <br> 054 * age=29, <br> 055 * smoker=false, <br> 056 * job=Job@43cd2[ <br> 057 * title=Manager <br> 058 * ] <br> 059 * ] 060 * </code> 061 * </p> 062 * 063 * @since 3.4 064 */ 065public class MultilineRecursiveToStringStyle extends RecursiveToStringStyle { 066 067 /** 068 * Required for serialization support. 069 * @see java.io.Serializable 070 */ 071 private static final long serialVersionUID = 1L; 072 073 /** Indenting of inner lines. */ 074 private int indent = 2; 075 076 /** Current indenting. */ 077 private int spaces = 2; 078 079 /** 080 * Constructor. 081 */ 082 public MultilineRecursiveToStringStyle() { 083 super(); 084 resetIndent(); 085 } 086 087 /** 088 * Resets the fields responsible for the line breaks and indenting. 089 * Must be invoked after changing the {@link #spaces} value. 090 */ 091 private void resetIndent() { 092 setArrayStart("{" + SystemUtils.LINE_SEPARATOR + spacer(spaces)); 093 setArraySeparator("," + SystemUtils.LINE_SEPARATOR + spacer(spaces)); 094 setArrayEnd(SystemUtils.LINE_SEPARATOR + spacer(spaces - indent) + "}"); 095 096 setContentStart("[" + SystemUtils.LINE_SEPARATOR + spacer(spaces)); 097 setFieldSeparator("," + SystemUtils.LINE_SEPARATOR + spacer(spaces)); 098 setContentEnd(SystemUtils.LINE_SEPARATOR + spacer(spaces - indent) + "]"); 099 } 100 101 /** 102 * Creates a StringBuilder responsible for the indenting. 103 * 104 * @param spaces how far to indent 105 * @return a StringBuilder with {spaces} leading space characters. 106 */ 107 private StringBuilder spacer(int spaces) { 108 StringBuilder sb = new StringBuilder(); 109 for (int i = 0; i < spaces; i++) { 110 sb.append(" "); 111 } 112 return sb; 113 } 114 115 @Override 116 public void appendDetail(StringBuffer buffer, String fieldName, Object value) { 117 if (!ClassUtils.isPrimitiveWrapper(value.getClass()) && !String.class.equals(value.getClass()) 118 && accept(value.getClass())) { 119 spaces += indent; 120 resetIndent(); 121 buffer.append(ReflectionToStringBuilder.toString(value, this)); 122 spaces -= indent; 123 resetIndent(); 124 } else { 125 super.appendDetail(buffer, fieldName, value); 126 } 127 } 128 129 @Override 130 protected void appendDetail(final StringBuffer buffer, final String fieldName, final Object[] array) { 131 spaces += indent; 132 resetIndent(); 133 super.appendDetail(buffer, fieldName, array); 134 spaces -= indent; 135 resetIndent(); 136 } 137 138 @Override 139 protected void reflectionAppendArrayDetail(final StringBuffer buffer, final String fieldName, final Object array) { 140 spaces += indent; 141 resetIndent(); 142 super.appendDetail(buffer, fieldName, array); 143 spaces -= indent; 144 resetIndent(); 145 } 146 147 @Override 148 protected void appendDetail(final StringBuffer buffer, final String fieldName, final long[] array) { 149 spaces += indent; 150 resetIndent(); 151 super.appendDetail(buffer, fieldName, array); 152 spaces -= indent; 153 resetIndent(); 154 } 155 156 @Override 157 protected void appendDetail(final StringBuffer buffer, final String fieldName, final int[] array) { 158 spaces += indent; 159 resetIndent(); 160 super.appendDetail(buffer, fieldName, array); 161 spaces -= indent; 162 resetIndent(); 163 } 164 165 @Override 166 protected void appendDetail(final StringBuffer buffer, final String fieldName, final short[] array) { 167 spaces += indent; 168 resetIndent(); 169 super.appendDetail(buffer, fieldName, array); 170 spaces -= indent; 171 resetIndent(); 172 } 173 174 @Override 175 protected void appendDetail(final StringBuffer buffer, final String fieldName, final byte[] array) { 176 spaces += indent; 177 resetIndent(); 178 super.appendDetail(buffer, fieldName, array); 179 spaces -= indent; 180 resetIndent(); 181 } 182 183 @Override 184 protected void appendDetail(final StringBuffer buffer, final String fieldName, final char[] array) { 185 spaces += indent; 186 resetIndent(); 187 super.appendDetail(buffer, fieldName, array); 188 spaces -= indent; 189 resetIndent(); 190 } 191 192 @Override 193 protected void appendDetail(final StringBuffer buffer, final String fieldName, final double[] array) { 194 spaces += indent; 195 resetIndent(); 196 super.appendDetail(buffer, fieldName, array); 197 spaces -= indent; 198 resetIndent(); 199 } 200 201 @Override 202 protected void appendDetail(final StringBuffer buffer, final String fieldName, final float[] array) { 203 spaces += indent; 204 resetIndent(); 205 super.appendDetail(buffer, fieldName, array); 206 spaces -= indent; 207 resetIndent(); 208 } 209 210 @Override 211 protected void appendDetail(final StringBuffer buffer, final String fieldName, final boolean[] array) { 212 spaces += indent; 213 resetIndent(); 214 super.appendDetail(buffer, fieldName, array); 215 spaces -= indent; 216 resetIndent(); 217 } 218 219}