31 package com.google.protobuf;
35 import java.util.HashMap;
36 import java.util.Iterator;
37 import java.util.List;
40 import java.util.TreeSet;
43 final class MessageLiteToString {
45 private static final String LIST_SUFFIX =
"List";
46 private static final String BUILDER_LIST_SUFFIX =
"OrBuilderList";
47 private static final String MAP_SUFFIX =
"Map";
48 private static final String BYTES_SUFFIX =
"Bytes";
58 static String toString(MessageLite messageLite, String commentString) {
59 StringBuilder
buffer =
new StringBuilder();
60 buffer.append(
"# ").append(commentString);
61 reflectivePrintWithIndent(messageLite,
buffer, 0);
71 private static void reflectivePrintWithIndent(
72 MessageLite messageLite, StringBuilder
buffer,
int indent) {
78 Set<String> getters =
new TreeSet<String>();
79 for (
Method method : messageLite.getClass().getDeclaredMethods()) {
81 if (
method.getParameterTypes().length == 0) {
84 if (
method.getName().startsWith(
"get")) {
85 getters.add(
method.getName());
90 for (String getter : getters) {
91 String suffix = getter.replaceFirst(
"get",
"");
92 if (suffix.endsWith(LIST_SUFFIX)
93 && !suffix.endsWith(BUILDER_LIST_SUFFIX)
95 && !suffix.equals(LIST_SUFFIX)) {
97 suffix.substring(0, 1).toLowerCase()
98 + suffix.substring(1, suffix.length() - LIST_SUFFIX.length());
101 Method listMethod = nameToNoArgMethod.get(getter);
102 if (listMethod !=
null && listMethod.getReturnType().equals(List.class)) {
106 camelCaseToSnakeCase(camelCase),
107 GeneratedMessageLite.invokeOrDie(listMethod, messageLite));
111 if (suffix.endsWith(MAP_SUFFIX)
113 && !suffix.equals(MAP_SUFFIX)) {
115 suffix.substring(0, 1).toLowerCase()
116 + suffix.substring(1, suffix.length() - MAP_SUFFIX.length());
119 Method mapMethod = nameToNoArgMethod.get(getter);
120 if (mapMethod !=
null
121 && mapMethod.getReturnType().equals(
Map.class)
124 && !mapMethod.isAnnotationPresent(Deprecated.class)
126 && Modifier.isPublic(mapMethod.getModifiers())) {
130 camelCaseToSnakeCase(camelCase),
131 GeneratedMessageLite.invokeOrDie(mapMethod, messageLite));
136 Method setter = nameToMethod.get(
"set" + suffix);
137 if (setter ==
null) {
140 if (suffix.endsWith(BYTES_SUFFIX)
141 && nameToNoArgMethod.containsKey(
142 "get" + suffix.substring(0, suffix.length() -
"Bytes".length()))) {
147 String camelCase = suffix.substring(0, 1).toLowerCase() + suffix.substring(1);
151 Method getMethod = nameToNoArgMethod.get(
"get" + suffix);
152 Method hasMethod = nameToNoArgMethod.get(
"has" + suffix);
154 if (getMethod !=
null) {
155 Object
value = GeneratedMessageLite.invokeOrDie(getMethod, messageLite);
156 final boolean hasValue =
158 ? !isDefaultValue(
value)
159 : (Boolean) GeneratedMessageLite.invokeOrDie(hasMethod, messageLite);
168 if (messageLite instanceof GeneratedMessageLite.ExtendableMessage) {
169 Iterator<
Map.Entry<GeneratedMessageLite.ExtensionDescriptor, Object>> iter =
170 ((GeneratedMessageLite.ExtendableMessage<?, ?>) messageLite).extensions.iterator();
171 while (iter.hasNext()) {
172 Map.Entry<GeneratedMessageLite.ExtensionDescriptor, Object> entry = iter.next();
173 printField(
buffer,
indent,
"[" + entry.getKey().getNumber() +
"]", entry.getValue());
177 if (((GeneratedMessageLite<?, ?>) messageLite).unknownFields !=
null) {
178 ((GeneratedMessageLite<?, ?>) messageLite).unknownFields.printWithIndent(
buffer,
indent);
182 private static boolean isDefaultValue(Object o) {
183 if (o instanceof Boolean) {
184 return !((Boolean) o);
186 if (o instanceof Integer) {
187 return ((Integer) o) == 0;
189 if (o instanceof
Float) {
192 if (o instanceof
Double) {
193 return ((
Double) o) == 0d;
195 if (o instanceof String) {
198 if (o instanceof ByteString) {
199 return o.equals(ByteString.EMPTY);
201 if (o instanceof MessageLite) {
202 return o == ((MessageLite) o).getDefaultInstanceForType();
204 if (o instanceof
java.
lang.Enum<?>) {
205 return ((
java.
lang.Enum<?>) o).ordinal() == 0;
221 static final void printField(StringBuilder
buffer,
int indent, String
name, Object
object) {
222 if (
object instanceof List<?>) {
223 List<?> list = (List<?>)
object;
224 for (Object entry : list) {
231 for (
Map.Entry<?, ?> entry :
map.entrySet()) {
243 if (
object instanceof String) {
244 buffer.append(
": \"").append(TextFormatEscaper.escapeText((String)
object)).append(
'"');
245 }
else if (
object instanceof ByteString) {
246 buffer.append(
": \"").append(TextFormatEscaper.escapeBytes((ByteString)
object)).append(
'"');
247 }
else if (
object instanceof GeneratedMessageLite) {
249 reflectivePrintWithIndent((GeneratedMessageLite<?, ?>)
object,
buffer,
indent + 2);
255 }
else if (
object instanceof
Map.Entry<?, ?>) {
257 Map.Entry<?, ?> entry = (
Map.Entry<?, ?>)
object;
259 printField(
buffer,
indent + 2,
"value", entry.getValue());
266 buffer.append(
": ").append(
object.toString());
270 private static final String camelCaseToSnakeCase(String camelCase) {
271 StringBuilder builder =
new StringBuilder();
272 for (
int i = 0;
i < camelCase.length();
i++) {
273 char ch = camelCase.charAt(
i);
274 if (Character.isUpperCase(
ch)) {
277 builder.append(Character.toLowerCase(
ch));
279 return builder.toString();