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; 021 022/** 023 * <p>Works with {@link ToStringBuilder} to create a "deep" <code>toString</code>. 024 * But instead a single line like the {@link RecursiveToStringStyle} this creates a multiline String 025 * similar to the {@link ToStringStyle#MULTI_LINE_STYLE}.</p> 026 * 027 * <p>To use this class write code as follows:</p> 028 * 029 * <pre> 030 * public class Job { 031 * String title; 032 * ... 033 * } 034 * 035 * public class Person { 036 * String name; 037 * int age; 038 * boolean smoker; 039 * Job job; 040 * 041 * ... 042 * 043 * public String toString() { 044 * return new ReflectionToStringBuilder(this, new MultilineRecursiveToStringStyle()).toString(); 045 * } 046 * } 047 * </pre> 048 * 049 * <p> 050 * This will produce a toString of the format:<br> 051 * <code>Person@7f54[ <br> 052 * name=Stephen, <br> 053 * age=29, <br> 054 * smoker=false, <br> 055 * job=Job@43cd2[ <br> 056 * title=Manager <br> 057 * ] <br> 058 * ] 059 * </code> 060 * </p> 061 * 062 * @since 3.4 063 */ 064public class MultilineRecursiveToStringStyle extends RecursiveToStringStyle { 065 066 /** 067 * Required for serialization support. 068 * @see java.io.Serializable 069 */ 070 private static final long serialVersionUID = 1L; 071 072 /** Indenting of inner lines. */ 073 private static final int INDENT = 2; 074 075 /** Current indenting. */ 076 private int spaces = 2; 077 078 /** 079 * Constructor. 080 */ 081 public MultilineRecursiveToStringStyle() { 082 super(); 083 resetIndent(); 084 } 085 086 /** 087 * Resets the fields responsible for the line breaks and indenting. 088 * Must be invoked after changing the {@link #spaces} value. 089 */ 090 private void resetIndent() { 091 setArrayStart("{" + System.lineSeparator() + spacer(spaces)); 092 setArraySeparator("," + System.lineSeparator() + spacer(spaces)); 093 setArrayEnd(System.lineSeparator() + spacer(spaces - INDENT) + "}"); 094 095 setContentStart("[" + System.lineSeparator() + spacer(spaces)); 096 setFieldSeparator("," + System.lineSeparator() + spacer(spaces)); 097 setContentEnd(System.lineSeparator() + spacer(spaces - INDENT) + "]"); 098 } 099 100 /** 101 * Creates a StringBuilder responsible for the indenting. 102 * 103 * @param spaces how far to indent 104 * @return a StringBuilder with {spaces} leading space characters. 105 */ 106 private StringBuilder spacer(final int spaces) { 107 final StringBuilder sb = new StringBuilder(); 108 for (int i = 0; i < spaces; i++) { 109 sb.append(" "); 110 } 111 return sb; 112 } 113 114 @Override 115 public void appendDetail(final StringBuffer buffer, final String fieldName, final Object value) { 116 if (!ClassUtils.isPrimitiveWrapper(value.getClass()) && !String.class.equals(value.getClass()) 117 && accept(value.getClass())) { 118 spaces += INDENT; 119 resetIndent(); 120 buffer.append(ReflectionToStringBuilder.toString(value, this)); 121 spaces -= INDENT; 122 resetIndent(); 123 } else { 124 super.appendDetail(buffer, fieldName, value); 125 } 126 } 127 128 @Override 129 protected void appendDetail(final StringBuffer buffer, final String fieldName, final Object[] array) { 130 spaces += INDENT; 131 resetIndent(); 132 super.appendDetail(buffer, fieldName, array); 133 spaces -= INDENT; 134 resetIndent(); 135 } 136 137 @Override 138 protected void reflectionAppendArrayDetail(final StringBuffer buffer, final String fieldName, final Object array) { 139 spaces += INDENT; 140 resetIndent(); 141 super.reflectionAppendArrayDetail(buffer, fieldName, array); 142 spaces -= INDENT; 143 resetIndent(); 144 } 145 146 @Override 147 protected void appendDetail(final StringBuffer buffer, final String fieldName, final long[] array) { 148 spaces += INDENT; 149 resetIndent(); 150 super.appendDetail(buffer, fieldName, array); 151 spaces -= INDENT; 152 resetIndent(); 153 } 154 155 @Override 156 protected void appendDetail(final StringBuffer buffer, final String fieldName, final int[] array) { 157 spaces += INDENT; 158 resetIndent(); 159 super.appendDetail(buffer, fieldName, array); 160 spaces -= INDENT; 161 resetIndent(); 162 } 163 164 @Override 165 protected void appendDetail(final StringBuffer buffer, final String fieldName, final short[] array) { 166 spaces += INDENT; 167 resetIndent(); 168 super.appendDetail(buffer, fieldName, array); 169 spaces -= INDENT; 170 resetIndent(); 171 } 172 173 @Override 174 protected void appendDetail(final StringBuffer buffer, final String fieldName, final byte[] array) { 175 spaces += INDENT; 176 resetIndent(); 177 super.appendDetail(buffer, fieldName, array); 178 spaces -= INDENT; 179 resetIndent(); 180 } 181 182 @Override 183 protected void appendDetail(final StringBuffer buffer, final String fieldName, final char[] array) { 184 spaces += INDENT; 185 resetIndent(); 186 super.appendDetail(buffer, fieldName, array); 187 spaces -= INDENT; 188 resetIndent(); 189 } 190 191 @Override 192 protected void appendDetail(final StringBuffer buffer, final String fieldName, final double[] array) { 193 spaces += INDENT; 194 resetIndent(); 195 super.appendDetail(buffer, fieldName, array); 196 spaces -= INDENT; 197 resetIndent(); 198 } 199 200 @Override 201 protected void appendDetail(final StringBuffer buffer, final String fieldName, final float[] array) { 202 spaces += INDENT; 203 resetIndent(); 204 super.appendDetail(buffer, fieldName, array); 205 spaces -= INDENT; 206 resetIndent(); 207 } 208 209 @Override 210 protected void appendDetail(final StringBuffer buffer, final String fieldName, final boolean[] array) { 211 spaces += INDENT; 212 resetIndent(); 213 super.appendDetail(buffer, fieldName, array); 214 spaces -= INDENT; 215 resetIndent(); 216 } 217 218}