2 * Copyright 2011 Google Inc.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package com
.google
.ipc
.invalidation
.util
;
19 import java
.lang
.reflect
.Field
;
20 import java
.lang
.reflect
.Modifier
;
23 * A {@link TextBuilder} is an abstraction that allows classes to efficiently append their string
24 * representations and then use them later for human consumption, e.g., for debugging or logging. It
25 * is currently a wrapper around {@link StringBuilder} and {@link Formatter} to give us format and
26 * append capabilities together. All append methods return this TextBuilder so that the method calls
30 public class TextBuilder
{
32 private final StringBuilder builder
;
33 private final UtilFormatter formatter
;
36 * Given an {@code object} that is an instance of {@code clazz}, outputs names and values of all
37 * member fields declared on {@code clazz}. This method should be used carefully:
39 * <li>This method is expensive. For frequently logged types, an ad hoc
40 * {@link InternalBase#toCompactString} implementation is preferred.</li>
41 * <li>May overflow the stack if there is a cycle in an object graph.</li>
42 * <li>Custom formatters have been implemented for many protos. They will not be used by this
46 public static void outputFieldsToBuilder(TextBuilder builder
, Object object
, Class
<?
> clazz
) {
47 Preconditions
.checkArgument(clazz
.isAssignableFrom(object
.getClass()));
49 // Get all the fields and print them using toCompactString if possible;
50 // otherwise, via toString
51 Field
[] fields
= clazz
.getDeclaredFields();
52 for (Field field
: fields
) {
54 // Ignore static final fields, as they're uninteresting.
55 int modifiers
= field
.getModifiers();
56 if (Modifier
.isStatic(modifiers
) && Modifier
.isFinal(modifiers
)) {
60 field
.setAccessible(true);
61 builder
.append(field
.getName() + " = ");
62 Object fieldValue
= field
.get(object
);
63 if (fieldValue
instanceof InternalBase
) {
64 ((InternalBase
) fieldValue
).toCompactString(builder
);
66 builder
.append(fieldValue
);
69 } catch (IllegalArgumentException e
) {
71 } catch (IllegalAccessException e
) {
78 * Returns an empty TextBuilder to which various objects' string
79 * representations can be added later.
81 public TextBuilder() {
82 builder
= new StringBuilder();
83 formatter
= new UtilFormatter(builder
);
87 * Appends the string representation of {@code c} to this builder.
89 * @param c the character being appended
91 public TextBuilder
append(char c
) {
97 * Appends the string representation of {@code i} to this builder.
99 * @param i the integer being appended
101 public TextBuilder
append(int i
) {
107 * Appends the toString representation of {@code object} to this builder.
109 public TextBuilder
append(Object object
) {
110 if (object
instanceof InternalBase
) {
111 return append((InternalBase
) object
);
113 builder
.append(object
);
119 * Appends the {@code InternalBase#toCompactString} representation of {@code object} to this
122 public TextBuilder
append(InternalBase object
) {
123 if (object
== null) {
124 return append("null");
126 object
.toCompactString(this);
131 * Appends the comma-separated {@code InternalBase#toCompactString} representations of
132 * {@code objects} to this builder.
134 public TextBuilder
append(Iterable
<?
extends InternalBase
> objects
) {
135 if (objects
== null) {
138 boolean first
= true;
139 for (InternalBase object
: objects
) {
143 builder
.append(", ");
150 /** Appends the {@link Bytes#toString} representation of {@code bytes} to this builder. */
151 public TextBuilder
append(byte[] bytes
) {
153 return append("null");
155 Bytes
.toCompactString(this, bytes
);
160 * Appends the string representation of {@code l} to this builder.
162 * @param l the long being appended
164 public TextBuilder
append(long l
) {
170 * Appends the string representation of {@code b} to this builder.
172 * @param b the boolean being appended
174 public TextBuilder
append(boolean b
) {
180 * Appends {@code s} to this builder.
182 * @param s the string being appended
184 public TextBuilder
append(String s
) {
190 * Writes a formatted string to this using the specified format string and
193 * @param format the format as used in {@link java.util.Formatter}
194 * @param args the arguments that are converted to their string form using
197 public TextBuilder
appendFormat(String format
, Object
... args
) {
198 formatter
.format(format
, args
);
203 public String
toString() {
204 return builder
.toString();