1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32 package org.spf4j.io;
33
34 import java.io.IOException;
35 import java.io.UncheckedIOException;
36 import java.util.ConcurrentModificationException;
37 import java.util.function.BiConsumer;
38 import javax.annotation.Nullable;
39 import javax.annotation.ParametersAreNonnullByDefault;
40 import org.spf4j.base.CoreTextMediaType;
41 import org.spf4j.base.EscapeJsonStringAppendableWrapper;
42
43
44
45
46
47 @ParametersAreNonnullByDefault
48 @FunctionalInterface
49 public interface ObjectAppender<T> extends BiConsumer<T, Appendable> {
50
51
52
53
54
55 default CoreTextMediaType getAppendedType() {
56 return CoreTextMediaType.TEXT_PLAIN;
57 }
58
59
60
61
62
63
64
65 void append(T object, Appendable appendTo) throws IOException;
66
67
68 static void appendNullable(@Nullable final Object o, final Appendable appendTo,
69 final ObjectAppenderSupplier appenderSupplier)
70 throws IOException {
71 if (o == null) {
72 appendTo.append("null");
73 } else {
74 appenderSupplier.get(o.getClass()).append(o, appendTo, appenderSupplier);
75 }
76 }
77
78 static void appendNullableJson(@Nullable final Object o, final Appendable appendTo,
79 final ObjectAppenderSupplier appenderSupplier)
80 throws IOException {
81 if (o == null) {
82 appendTo.append("null");
83 } else {
84 ObjectAppender app = appenderSupplier.get(CoreTextMediaType.APPLICATION_JSON, o.getClass());
85 if (app != null) {
86 app.append(o, appendTo, appenderSupplier);
87 } else {
88 app = appenderSupplier.get(CoreTextMediaType.TEXT_PLAIN, o.getClass());
89 EscapeJsonStringAppendableWrapper sEsc = new EscapeJsonStringAppendableWrapper(appendTo);
90 appendTo.append('"');
91 app.append(o, sEsc, appenderSupplier);
92 appendTo.append('"');
93 }
94 }
95 }
96
97
98
99
100
101 default void append(T object, Appendable appendTo, ObjectAppenderSupplier appenderSupplier) throws IOException {
102 append(object, appendTo);
103 }
104
105 default void accept(final T object, final Appendable appendTo) {
106 try {
107 append(object, appendTo);
108 } catch (IOException ex) {
109 throw new UncheckedIOException(ex);
110 }
111 }
112
113 default String toString(final T object) {
114 StringBuilder sb = new StringBuilder();
115 this.accept(object, sb);
116 return sb.toString();
117 }
118
119
120
121
122 ObjectAppender<Object> TOSTRING_APPENDER = new ObjectAppender<Object>() {
123 @Override
124 public void append(final Object object, final Appendable appendTo) throws IOException {
125
126 String toString = null;
127 int i = 10;
128 do {
129 try {
130 toString = object.toString();
131 } catch (ConcurrentModificationException ex) {
132 i--;
133 }
134 } while (toString == null && i > 0);
135 if (i != 10) {
136 appendTo.append("ConcurrentlyModifiedDuringToString:");
137 }
138 if (toString == null) {
139 appendTo.append(object.getClass().getName()).append('@')
140 .append(Integer.toHexString(System.identityHashCode(object)));
141 } else {
142 appendTo.append(toString);
143 }
144 }
145
146 };
147
148 }