com.baidu.bjf.remoting.protobuf.code.CodedConstant Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jprotobuf Show documentation
Show all versions of jprotobuf Show documentation
A useful utility library for java programmer using google protobuf.
/*
* Copyright (c) Baidu Inc. All rights reserved.
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.baidu.bjf.remoting.protobuf.code;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.baidu.bjf.remoting.protobuf.Codec;
import com.baidu.bjf.remoting.protobuf.EnumHandler;
import com.baidu.bjf.remoting.protobuf.EnumReadable;
import com.baidu.bjf.remoting.protobuf.FieldType;
import com.baidu.bjf.remoting.protobuf.ProtobufIDLGenerator;
import com.baidu.bjf.remoting.protobuf.ProtobufIDLProxy;
import com.baidu.bjf.remoting.protobuf.ProtobufProxy;
import com.baidu.bjf.remoting.protobuf.descriptor.DescriptorProtoPOJO;
import com.baidu.bjf.remoting.protobuf.descriptor.EnumDescriptorProtoPOJO;
import com.baidu.bjf.remoting.protobuf.descriptor.EnumOptionsPOJO;
import com.baidu.bjf.remoting.protobuf.descriptor.EnumValueDescriptorProtoPOJO;
import com.baidu.bjf.remoting.protobuf.descriptor.ExtensionRangePOJO;
import com.baidu.bjf.remoting.protobuf.descriptor.FieldDescriptorProtoPOJO;
import com.baidu.bjf.remoting.protobuf.descriptor.FileDescriptorProtoPOJO;
import com.baidu.bjf.remoting.protobuf.descriptor.Label;
import com.baidu.bjf.remoting.protobuf.descriptor.MessageOptionsPOJO;
import com.baidu.bjf.remoting.protobuf.descriptor.OneofDescriptorProtoPOJO;
import com.baidu.bjf.remoting.protobuf.descriptor.ServiceDescriptorProtoPOJO;
import com.baidu.bjf.remoting.protobuf.descriptor.Type;
import com.baidu.bjf.remoting.protobuf.utils.ClassHelper;
import com.baidu.bjf.remoting.protobuf.utils.FieldInfo;
import com.baidu.bjf.remoting.protobuf.utils.ProtobufProxyUtils;
import com.baidu.bjf.remoting.protobuf.utils.StringUtils;
import com.baidu.jprotobuf.com.squareup.protoparser.DataType;
import com.baidu.jprotobuf.com.squareup.protoparser.DataType.Kind;
import com.baidu.jprotobuf.com.squareup.protoparser.DataType.MapType;
import com.baidu.jprotobuf.com.squareup.protoparser.EnumConstantElement;
import com.baidu.jprotobuf.com.squareup.protoparser.EnumElement;
import com.baidu.jprotobuf.com.squareup.protoparser.FieldElement;
import com.baidu.jprotobuf.com.squareup.protoparser.FieldElement.Builder;
import com.baidu.jprotobuf.com.squareup.protoparser.MessageElement;
import com.baidu.jprotobuf.com.squareup.protoparser.OptionElement;
import com.baidu.jprotobuf.com.squareup.protoparser.ProtoFile;
import com.baidu.jprotobuf.com.squareup.protoparser.ProtoParser;
import com.baidu.jprotobuf.com.squareup.protoparser.TypeElement;
import com.google.protobuf.ByteString;
import com.google.protobuf.CodedInputStream;
import com.google.protobuf.CodedOutputStream;
import com.google.protobuf.DescriptorProtos.FileDescriptorProto;
import com.google.protobuf.Descriptors;
import com.google.protobuf.Descriptors.Descriptor;
import com.google.protobuf.Descriptors.DescriptorValidationException;
import com.google.protobuf.Descriptors.FileDescriptor;
import com.google.protobuf.Internal;
import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.LazyField;
import com.google.protobuf.Message;
import com.google.protobuf.MessageLite;
import com.google.protobuf.WireFormat;
/**
* Utility class for codec.
*
* @author xiemalin
* @since 1.0.0
*/
public class CodedConstant {
private static final String FIELD_PREFIX = "f_";
/** The Constant MAP_ENTRY_SUFFIX. */
private static final String MAP_ENTRY_SUFFIX = "Entry";
/** The Constant WIREFORMAT_CLSNAME. */
private static final String WIREFORMAT_CLSNAME =
ClassHelper.getInternalName(com.google.protobuf.WireFormat.FieldType.class.getCanonicalName());
/**
* get field name.
*
* @param order field order
* @return field name
*/
public static String getFieldName(int order) {
String fieldName = FIELD_PREFIX + order;
return fieldName;
}
/**
* Compute the number of bytes that would be needed to encode a single tag/value pair of arbitrary type.
*
* @param type The field's type.
* @param number The field's number.
* @param value Object representing the field's value. Must be of the exact type which would be returned by
* {@link Message#getField(Descriptors.FieldDescriptor)} for this field.
* @return the int
*/
public static int computeElementSize(final WireFormat.FieldType type, final int number, final Object value) {
int tagSize = CodedOutputStream.computeTagSize(number);
if (type == WireFormat.FieldType.GROUP) {
// Only count the end group tag for proto2 messages as for proto1 the end
// group tag will be counted as a part of getSerializedSize().
tagSize *= 2;
}
return tagSize + computeElementSizeNoTag(type, value);
}
/**
* get mapped type defined java expression.
*
* @param order field order
* @param type field type
* @param express java expression
* @param isList is field type is a {@link List}
* @param isMap is field type is a {@link Map}
* @return full java expression
*/
public static String getMappedTypeDefined(int order, FieldType type, String express, boolean isList,
boolean isMap) {
StringBuilder code = new StringBuilder();
String fieldName = getFieldName(order);
if ((type == FieldType.STRING || type == FieldType.BYTES) && !isList) {
// add null check
code.append("com.google.protobuf.ByteString ").append(fieldName).append(" = null")
.append(ICodeGenerator.JAVA_LINE_BREAK);
code.append("if (!CodedConstant.isNull(").append(express).append(")) {").append(ICodeGenerator.LINE_BREAK);
String method = "copyFromUtf8";
if (type == FieldType.BYTES) {
method = "copyFrom";
}
code.append(fieldName).append(" = com.google.protobuf.ByteString.").append(method).append("(")
.append(express).append(")").append(ICodeGenerator.JAVA_LINE_BREAK);
code.append("}").append(ICodeGenerator.LINE_BREAK);
return code.toString();
}
// add null check
String defineType = type.getJavaType();
if (isList) {
defineType = "List";
} else if (isMap) {
defineType = "Map";
}
code.setLength(0);
code.append(defineType).append(" ").append(fieldName).append(" = null").append(ICodeGenerator.JAVA_LINE_BREAK);
code.append("if (!CodedConstant.isNull(").append(express).append(")) {").append(ICodeGenerator.LINE_BREAK);
code.append(fieldName).append(" = ").append(express).append(ICodeGenerator.JAVA_LINE_BREAK);
code.append("}").append(ICodeGenerator.LINE_BREAK);
return code.toString();
}
/**
* Gets the filed type.
*
* @param type the type
* @param isList the is list
* @return the filed type
*/
public static String getFiledType(FieldType type, boolean isList) {
// add null check
String defineType = type.getJavaType();
if (isList) {
defineType = "Collection";
}
return defineType;
}
/**
* Gets the write value to field.
*
* @param type the type
* @param express the express
* @param isList the is list
* @return the write value to field
*/
public static String getWriteValueToField(FieldType type, String express, boolean isList) {
return express;
}
/**
* Gets the mapped type size.
*
* @param field field
* @param order field order
* @param type field type
* @param isList is field type is a {@link List}
* @param isMap the is map
* @param debug debug mode if true enable debug.
* @param path the path
* @return full java expression
*/
public static String getMappedTypeSize(FieldInfo field, int order, FieldType type, boolean isList, boolean isMap,
boolean debug, File path) {
String fieldName = getFieldName(order);
String spath = "null";
if (path != null) {
spath = "ProtobufProxy.OUTPUT_PATH.get()";
}
String typeString = type.getType().toUpperCase();
if (isList) {
return "CodedConstant.computeListSize(" + order + ", " + fieldName + ", " + FieldType.class.getName() + "."
+ typeString + ", " + Boolean.valueOf(debug) + ", " + spath + ","
+ Boolean.valueOf(field.isPacked()) + ")" + ICodeGenerator.JAVA_LINE_BREAK;
} else if (isMap) {
String joinedSentence = getMapFieldGenericParameterString(field);
return "CodedConstant.computeMapSize(" + order + ", " + fieldName + ", " + joinedSentence + ")"
+ ICodeGenerator.JAVA_LINE_BREAK;
}
if (type == FieldType.OBJECT) {
return "CodedConstant.computeSize(" + order + "," + fieldName + ", " + FieldType.class.getName() + "."
+ typeString + "," + Boolean.valueOf(debug) + "," + spath + ")" + ICodeGenerator.JAVA_LINE_BREAK;
}
String t = type.getType();
if (type == FieldType.STRING) {
t = "String";
}
if (type == FieldType.BYTES) {
t = "ByteArray";
}
t = capitalize(t);
boolean enumSpecial = false;
if (type == FieldType.ENUM) {
if (EnumReadable.class.isAssignableFrom(field.getField().getType())) {
String clsName = ClassHelper.getInternalName(field.getField().getType().getCanonicalName());
fieldName = "((" + clsName + ") " + fieldName + ").value()";
enumSpecial = true;
}
}
if (!enumSpecial) {
fieldName = fieldName + type.getToPrimitiveType();
}
return "com.google.protobuf.CodedOutputStream.compute" + t + "Size(" + order + "," + fieldName + ")"
+ ICodeGenerator.JAVA_LINE_BREAK;
}
/**
* Gets the map field generic parameter string.
*
* @param field the field
* @return the map field generic parameter string
*/
public static String getMapFieldGenericParameterString(FieldInfo field) {
FieldType fieldType = ProtobufProxyUtils.TYPE_MAPPING.get(field.getGenericKeyType());
String keyClass;
String defaultKeyValue;
if (fieldType == null) {
// may be object or enum
if (Enum.class.isAssignableFrom(field.getGenericKeyType())) {
keyClass = WIREFORMAT_CLSNAME + ".ENUM";
Class> declaringClass = field.getGenericKeyType();
Field[] fields = declaringClass.getFields();
if (fields != null && fields.length > 0) {
defaultKeyValue = ClassHelper.getInternalName(field.getGenericKeyType().getCanonicalName()) + "."
+ fields[0].getName();
} else {
defaultKeyValue = "0";
}
} else {
keyClass = WIREFORMAT_CLSNAME + ".MESSAGE";
// check constructor
boolean hasDefaultConstructor = ClassHelper.hasDefaultConstructor(field.getGenericKeyType());
if (!hasDefaultConstructor) {
throw new IllegalArgumentException("Class '" + field.getGenericKeyType().getCanonicalName()
+ "' must has default constructor method with no parameters.");
}
defaultKeyValue =
"new " + ClassHelper.getInternalName(field.getGenericKeyType().getCanonicalName()) + "()";
}
} else {
keyClass = WIREFORMAT_CLSNAME + "." + fieldType.toString();
// check type
defaultKeyValue = fieldType.getDefaultValue();
}
fieldType = ProtobufProxyUtils.TYPE_MAPPING.get(field.getGenericeValueType());
String valueClass;
String defaultValueValue;
if (fieldType == null) {
// may be object or enum
if (Enum.class.isAssignableFrom(field.getGenericeValueType())) {
valueClass = WIREFORMAT_CLSNAME + ".ENUM";
Class> declaringClass = field.getGenericeValueType();
Field[] fields = declaringClass.getFields();
if (fields != null && fields.length > 0) {
defaultValueValue = ClassHelper.getInternalName(field.getGenericeValueType().getCanonicalName())
+ "." + fields[0].getName();
} else {
defaultValueValue = "0";
}
} else {
valueClass = WIREFORMAT_CLSNAME + ".MESSAGE";
// check constructor
boolean hasDefaultConstructor = ClassHelper.hasDefaultConstructor(field.getGenericeValueType());
if (!hasDefaultConstructor) {
throw new IllegalArgumentException("Class '" + field.getGenericeValueType().getCanonicalName()
+ "' must has default constructor method with no parameters.");
}
defaultValueValue =
"new " + ClassHelper.getInternalName(field.getGenericeValueType().getCanonicalName()) + "()";
}
} else {
valueClass = WIREFORMAT_CLSNAME + "." + fieldType.toString();
defaultValueValue = fieldType.getDefaultValue();
}
String joinedSentence = keyClass + "," + defaultKeyValue + "," + valueClass + "," + defaultValueValue;
return joinedSentence;
}
/**
* Compute list size.
*
* @param order field order
* @param list field value
* @param type field type of list obj
* @param debug the debug
* @param path the path
* @return full java expression
*/
public static int computeListSize(int order, Collection> list, FieldType type, boolean debug, File path) {
return computeListSize(order, list, type, debug, path, false, false);
}
/**
* Compute list size.
*
* @param order the order
* @param list the list
* @param type the type
* @param debug the debug
* @param path the path
* @param packed the packed
* @return the int
*/
public static int computeListSize(int order, Collection list, FieldType type, boolean debug, File path,
boolean packed) {
return computeListSize(order, list, type, debug, path, packed, false);
}
/**
* Compute list size.
*
* @param order the order
* @param list the list
* @param type the type
* @param debug the debug
* @param path the path
* @param packed the packed
* @param sizeOnly the size only if true will not include order size and tag size
* @return the int
*/
public static int computeListSize(int order, Collection list, FieldType type, boolean debug, File path,
boolean packed, boolean sizeOnly) {
int size = 0;
if (list == null || list.isEmpty()) {
return size;
}
int dataSize = 0;
for (Object object : list) {
dataSize += computeSize(order, object, type, debug, path);
}
size += dataSize;
if (type != FieldType.OBJECT) {
if (packed) {
if (!sizeOnly) {
size += com.google.protobuf.CodedOutputStream.computeInt32SizeNoTag(dataSize);
int tag = CodedConstant.makeTag(order, WireFormat.WIRETYPE_LENGTH_DELIMITED);
size += com.google.protobuf.CodedOutputStream.computeUInt32SizeNoTag(tag);
}
} else {
size += list.size() * CodedOutputStream.computeTagSize(order);
}
}
return size;
}
/**
* Compute map size.
*
* @param the key type
* @param the value type
* @param order the order
* @param map the map
* @param keyType the key type
* @param defaultKey the default key
* @param valueType the value type
* @param defalutValue the defalut value
* @return the int
*/
public static int computeMapSize(int order, Map map, com.google.protobuf.WireFormat.FieldType keyType,
K defaultKey, com.google.protobuf.WireFormat.FieldType valueType, V defalutValue) {
int size = 0;
for (java.util.Map.Entry entry : map.entrySet()) {
com.baidu.bjf.remoting.protobuf.MapEntry valuesDefaultEntry = com.baidu.bjf.remoting.protobuf.MapEntry
. newDefaultInstance(null, keyType, defaultKey, valueType, defalutValue);
com.baidu.bjf.remoting.protobuf.MapEntry values =
valuesDefaultEntry.newBuilderForType().setKey(entry.getKey()).setValue(entry.getValue()).build();
size += com.google.protobuf.CodedOutputStream.computeMessageSize(order, values);
}
return size;
}
/**
* Put map value.
*
* @param the key type
* @param the value type
* @param input the input
* @param map the map
* @param keyType the key type
* @param defaultKey the default key
* @param valueType the value type
* @param defalutValue the defalut value
* @throws IOException Signals that an I/O exception has occurred.
*/
public static void putMapValue(CodedInputStream input, Map map,
com.google.protobuf.WireFormat.FieldType keyType, K defaultKey,
com.google.protobuf.WireFormat.FieldType valueType, V defalutValue) throws IOException {
putMapValue(input, map, keyType, defaultKey, valueType, defalutValue, null);
}
public static void putMapValue(CodedInputStream input, Map map,
com.google.protobuf.WireFormat.FieldType keyType, K defaultKey,
com.google.protobuf.WireFormat.FieldType valueType, V defalutValue, EnumHandler handler)
throws IOException {
putMapValue(input, map, keyType, defaultKey, valueType, defalutValue, null, handler);
}
public static void putMapValue(CodedInputStream input, Map map,
com.google.protobuf.WireFormat.FieldType keyType, K defaultKey,
com.google.protobuf.WireFormat.FieldType valueType, V defalutValue, EnumHandler keyHandler, EnumHandler valHandler)
throws IOException {
com.baidu.bjf.remoting.protobuf.MapEntry valuesDefaultEntry = com.baidu.bjf.remoting.protobuf.MapEntry
. newDefaultInstance(null, keyType, defaultKey, valueType, defalutValue);
com.baidu.bjf.remoting.protobuf.MapEntry values =
input.readMessage(valuesDefaultEntry.getParserForType(), null);
Object value = values.getValue();
Object key = values.getKey();
if (keyHandler != null) {
key = keyHandler.handle((int) key);
}
if (valHandler != null) {
value = valHandler.handle((int) value);
}
map.put((K) key, (V) value);
}
/**
* Write to map.
*
* @param the key type
* @param the value type
* @param output the output
* @param order the order
* @param map the map
* @param keyType the key type
* @param defaultKey the default key
* @param valueType the value type
* @param defalutValue the defalut value
* @throws IOException Signals that an I/O exception has occurred.
*/
public static void writeToMap(CodedOutputStream output, int order, Map map,
com.google.protobuf.WireFormat.FieldType keyType, K defaultKey,
com.google.protobuf.WireFormat.FieldType valueType, V defalutValue) throws IOException {
com.baidu.bjf.remoting.protobuf.MapEntry valuesDefaultEntry = com.baidu.bjf.remoting.protobuf.MapEntry
. newDefaultInstance(null, keyType, defaultKey, valueType, defalutValue);
for (java.util.Map.Entry entry : map.entrySet()) {
com.baidu.bjf.remoting.protobuf.MapEntry values =
valuesDefaultEntry.newBuilderForType().setKey(entry.getKey()).setValue(entry.getValue()).build();
output.writeMessage(order, values);
}
}
/**
* get object size by {@link FieldType}.
*
* @param order the order
* @param o the o
* @param type the type
* @param debug the debug
* @param path the path
* @return the int
*/
public static int computeSize(int order, Object o, FieldType type, boolean debug, File path) {
return computeSize(order, o, type, false, debug, path);
}
/**
* Compute object size no tag.
*
* @param o the o
* @return the int
*/
public static int computeObjectSizeNoTag(Object o) {
int size = 0;
if (o == null) {
return size;
}
Class cls = o.getClass();
Codec target = ProtobufProxy.create(cls, ProtobufProxy.isDebugEnabled());
try {
size = target.size(o);
size = size + CodedOutputStream.computeRawVarint32Size(size);
return size;
} catch (IOException e) {
throw new RuntimeException(e.getMessage(), e);
}
}
/**
* get object size by {@link FieldType}.
*
* @param order the order
* @param o the o
* @param type the type
* @param list the list
* @param debug the debug
* @param path the path
* @return the int
*/
public static int computeSize(int order, Object o, FieldType type, boolean list, boolean debug, File path) {
int size = 0;
if (o == null) {
return size;
}
if (type == FieldType.OBJECT) {
Class cls = o.getClass();
Codec target = ProtobufProxy.create(cls, debug, path);
try {
size = target.size(o);
size = size + CodedOutputStream.computeRawVarint32Size(size);
return size + CodedOutputStream.computeTagSize(order);
} catch (IOException e) {
throw new RuntimeException(e.getMessage(), e);
}
}
if (type == FieldType.STRING) {
size = CodedOutputStream.computeStringSizeNoTag(String.valueOf(o));
} else if (type == FieldType.BOOL) {
size = CodedOutputStream.computeBoolSizeNoTag(Boolean.valueOf(String.valueOf(o)));
} else if (type == FieldType.BYTES) {
byte[] bb = (byte[]) o;
size = CodedOutputStream.computeBytesSizeNoTag(ByteString.copyFrom(bb));
} else if (type == FieldType.DOUBLE) {
size = CodedOutputStream.computeDoubleSizeNoTag(Double.valueOf(o.toString()));
} else if (type == FieldType.FIXED32 || type == FieldType.SFIXED32) {
size = CodedOutputStream.computeFixed32SizeNoTag(Integer.valueOf(o.toString()));
} else if (type == FieldType.INT32 || type == FieldType.SINT32 || type == FieldType.UINT32) {
size = CodedOutputStream.computeInt32SizeNoTag(Integer.valueOf(o.toString()));
}else if (type == FieldType.FIXED64|| type == FieldType.SFIXED64) {
size = CodedOutputStream.computeSFixed64SizeNoTag(Long.valueOf(o.toString()));
} else if (type == FieldType.INT64 || type == FieldType.SINT64 || type == FieldType.UINT64) {
size = CodedOutputStream.computeInt64SizeNoTag(Long.valueOf(o.toString()));
} else if (type == FieldType.FLOAT) {
size = CodedOutputStream.computeFloatSizeNoTag(Float.valueOf(o.toString()));
} else if (type == FieldType.ENUM) {
if (o instanceof EnumReadable) {
size = CodedOutputStream.computeInt32SizeNoTag(((EnumReadable) o).value());
} else if (o instanceof Enum) {
size = CodedOutputStream.computeInt32SizeNoTag(((Enum) o).ordinal());
}
}
return size;
}
/**
* get mapped object byte write java expression.
*
* @param field the field
* @param prefix the prefix
* @param order field order
* @param type field type
* @param isList the is list
* @param isMap the is map
* @return full java expression
*/
public static String getMappedWriteCode(FieldInfo field, String prefix, int order, FieldType type, boolean isList,
boolean isMap) {
String fieldName = getFieldName(order);
StringBuilder ret = new StringBuilder();
ret.append("if (").append(fieldName).append(" != null){").append(ICodeGenerator.LINE_BREAK);
if (isList) {
String typeString = type.getType().toUpperCase();
ret.append("CodedConstant.writeToList(").append(prefix).append(",");
ret.append(order).append(",").append(FieldType.class.getName()).append(".").append(typeString);
ret.append(",").append(fieldName).append(",").append(Boolean.valueOf(field.isPacked())).append(")")
.append(ICodeGenerator.JAVA_LINE_BREAK).append("}").append(ICodeGenerator.LINE_BREAK);
return ret.toString();
} else if (isMap) {
ret.append("CodedConstant.writeToMap(").append(prefix).append(",");
ret.append(order).append(",").append(fieldName);
String joinedSentence = getMapFieldGenericParameterString(field);
ret.append(",").append(joinedSentence);
ret.append(")").append(ICodeGenerator.JAVA_LINE_BREAK).append("}").append(ICodeGenerator.LINE_BREAK);
return ret.toString();
} else {
// not list so should add convert to primitive type
boolean enumSpecial = false;
if (type == FieldType.ENUM) {
if (EnumReadable.class.isAssignableFrom(field.getField().getType())) {
String clsName = ClassHelper.getInternalName(field.getField().getType().getCanonicalName());
fieldName = "((" + clsName + ") " + fieldName + ").value()";
enumSpecial = true;
}
}
if (!enumSpecial) {
fieldName = fieldName + type.getToPrimitiveType();
}
}
if (type == FieldType.OBJECT) {
String typeString = type.getType().toUpperCase();
ret.append("CodedConstant.writeObject(").append(prefix).append(",");
ret.append(order).append(",").append(FieldType.class.getName()).append(".").append(typeString);
ret.append(",").append(fieldName).append(", false)").append(ICodeGenerator.JAVA_LINE_BREAK).append("}")
.append(ICodeGenerator.LINE_BREAK);
return ret.toString();
}
if (type == FieldType.STRING) {
ret.append(prefix).append(".writeString(").append(order);
ret.append(", ").append(fieldName).append(")").append(ICodeGenerator.JAVA_LINE_BREAK).append("}")
.append(ICodeGenerator.LINE_BREAK);
return ret.toString();
}
if (type == FieldType.BYTES) {
ret.append(prefix).append(".writeByteArray(").append(order);
ret.append(", ").append(fieldName).append(")").append(ICodeGenerator.JAVA_LINE_BREAK).append("}")
.append(ICodeGenerator.LINE_BREAK);
return ret.toString();
}
String t = type.getType();
t = capitalize(t);
ret.append(prefix).append(".write").append(t).append("(").append(order);
ret.append(", ").append(fieldName).append(")").append(ICodeGenerator.JAVA_LINE_BREAK).append("}")
.append(ICodeGenerator.LINE_BREAK);
return ret.toString();
}
/**
* Write to list.
*
* @param out the out
* @param order the order
* @param type the type
* @param list the list
* @throws IOException Signals that an I/O exception has occurred.
*/
public static void writeToList(CodedOutputStream out, int order, FieldType type, Collection list)
throws IOException {
writeToList(out, order, type, list, false);
}
/**
* write list to {@link CodedOutputStream} object.
*
* @param out target output stream to write
* @param order field order
* @param type field type
* @param list target list object to be serialized
* @param packed the packed
* @throws IOException Signals that an I/O exception has occurred.
*/
public static void writeToList(CodedOutputStream out, int order, FieldType type, Collection list, boolean packed)
throws IOException {
if (list == null || list.isEmpty()) {
return;
}
CodecOutputByteArray output = CodecOutputByteArray.get();
for (Object object : list) {
if (object == null) {
throw new NullPointerException("List can not include Null value.");
}
writeObject(output.getCodedOutputStream(), order, type, object, true, !packed);
}
byte[] byteArray = output.getData();
if (packed) {
out.writeUInt32NoTag(makeTag(order, WireFormat.WIRETYPE_LENGTH_DELIMITED));
out.writeUInt32NoTag(byteArray.length);
}
out.write(byteArray, 0, byteArray.length);
}
/**
* Write object.
*
* @param out the out
* @param order the order
* @param type the type
* @param o the o
* @param list the list
* @throws IOException Signals that an I/O exception has occurred.
*/
public static void writeObject(CodedOutputStream out, int order, FieldType type, Object o, boolean list)
throws IOException {
writeObject(out, order, type, o, list, true);
}
/**
* Write object to byte array by {@link FieldType}.
*
* @param out the out
* @param order the order
* @param type the type
* @param o the o
* @param list the list
* @param withTag the with tag
* @throws IOException Signals that an I/O exception has occurred.
*/
public static void writeObject(CodedOutputStream out, int order, FieldType type, Object o, boolean list,
boolean withTag) throws IOException {
if (o == null) {
return;
}
if (type == FieldType.OBJECT) {
Class cls = o.getClass();
Codec target = ProtobufProxy.create(cls, ProtobufProxy.isDebugEnabled());
if (withTag) {
out.writeUInt32NoTag(makeTag(order, WireFormat.WIRETYPE_LENGTH_DELIMITED));
}
byte[] byteArray = CodecOutputByteArray.getData(target, o);
out.writeUInt32NoTag(byteArray.length);
out.write(byteArray, 0, byteArray.length);
return;
}
if (type == FieldType.BOOL) {
if (withTag) {
out.writeBool(order, (Boolean) o);
} else {
out.writeBoolNoTag((Boolean) o);
}
} else if (type == FieldType.BYTES) {
byte[] bb = (byte[]) o;
if (withTag) {
out.writeBytes(order, ByteString.copyFrom(bb));
} else {
out.writeBytesNoTag(ByteString.copyFrom(bb));
}
} else if (type == FieldType.DOUBLE) {
if (withTag) {
out.writeDouble(order, (Double) o);
} else {
out.writeDoubleNoTag((Double) o);
}
} else if (type == FieldType.FIXED32) {
if (withTag) {
out.writeFixed32(order, (Integer) o);
} else {
out.writeFixed32NoTag((Integer) o);
}
} else if (type == FieldType.FIXED64) {
if (withTag) {
out.writeFixed64(order, (Long) o);
} else {
out.writeFixed64NoTag((Long) o);
}
} else if (type == FieldType.FLOAT) {
if (withTag) {
out.writeFloat(order, (Float) o);
} else {
out.writeFloatNoTag((Float) o);
}
} else if (type == FieldType.INT32) {
if (withTag) {
out.writeInt32(order, (Integer) o);
} else {
out.writeInt32NoTag((Integer) o);
}
} else if (type == FieldType.INT64) {
if (withTag) {
out.writeInt64(order, (Long) o);
} else {
out.writeInt64NoTag((Long) o);
}
} else if (type == FieldType.SFIXED32) {
if (withTag) {
out.writeSFixed32(order, (Integer) o);
} else {
out.writeSFixed32NoTag((Integer) o);
}
} else if (type == FieldType.SFIXED64) {
if (withTag) {
out.writeSFixed64(order, (Long) o);
} else {
out.writeSFixed64NoTag((Long) o);
}
} else if (type == FieldType.SINT32) {
if (withTag) {
out.writeSInt32(order, (Integer) o);
} else {
out.writeSInt32NoTag((Integer) o);
}
} else if (type == FieldType.SINT64) {
if (withTag) {
out.writeSInt64(order, (Long) o);
} else {
out.writeSInt64NoTag((Long) o);
}
} else if (type == FieldType.STRING) {
if (withTag) {
out.writeBytes(order, ByteString.copyFromUtf8(String.valueOf(o)));
} else {
out.writeBytesNoTag(ByteString.copyFromUtf8(String.valueOf(o)));
}
} else if (type == FieldType.UINT32) {
if (withTag) {
out.writeUInt32(order, (Integer) o);
} else {
out.writeUInt32NoTag((Integer) o);
}
} else if (type == FieldType.UINT64) {
if (withTag) {
out.writeUInt64(order, (Long) o);
} else {
out.writeUInt64NoTag((Long) o);
}
} else if (type == FieldType.ENUM) {
int value = 0;
if (o instanceof EnumReadable) {
value = ((EnumReadable) o).value();
} else if (o instanceof Enum) {
value = ((Enum) o).ordinal();
}
if (withTag) {
out.writeEnum(order, value);
} else {
out.writeEnumNoTag(value);
}
}
}
/**
* get required field check java expression.
*
* @param order field order
* @param field java field
* @return full java expression
*/
public static String getRequiredCheck(int order, Field field) {
String fieldName = getFieldName(order);
String code = "if (" + fieldName + "== null) {\n";
code += "throw new UninitializedMessageException(CodedConstant.asList(\"" + field.getName() + "\"));\n";
code += "}\n";
return code;
}
/**
* get return required field check java expression.
*
* @param express java expression
* @param field java field
* @return full java expression
*/
public static String getRetRequiredCheck(String express, Field field) {
String code = "if (CodedConstant.isNull(" + express + ")) {\n";
code += "throw new UninitializedMessageException(CodedConstant.asList(\"" + field.getName() + "\"));\n";
code += "}\n";
return code;
}
/**
* check object is null.
*
* @param o to check
* @return true if is null
*/
public static boolean isNull(Object o) {
return o == null;
}
/**
* check double is null.
*
* @param o to check
* @return true if is null
*/
public static boolean isNull(double o) {
return false;
}
/**
* check int is null.
*
* @param o to check
* @return true if is null
*/
public static boolean isNull(int o) {
return false;
}
/**
* check byte is null.
*
* @param o to check
* @return true if is null
*/
public static boolean isNull(byte o) {
return false;
}
/**
* check short is null.
*
* @param o to check
* @return true if is null
*/
public static boolean isNull(short o) {
return false;
}
/**
* check long is null.
*
* @param o to check
* @return true if is null
*/
public static boolean isNull(long o) {
return false;
}
/**
* check float is null.
*
* @param o to check
* @return true if is null
*/
public static boolean isNull(float o) {
return false;
}
/**
* check char is null.
*
* @param o to check
* @return true if is null
*/
public static boolean isNull(char o) {
return false;
}
/**
* As list.
*
* @param value the value
* @return the list
*/
public static List asList(String value) {
return Arrays.asList(value);
}
/**
*
* Capitalizes a String changing the first letter to title case as per {@link Character#toTitleCase(char)}. No other
* letters are changed.
*
*
* @param str the String to capitalize, may be null
* @return the capitalized String, null
if null String input
*/
public static String capitalize(String str) {
int strLen;
if (str == null || (strLen = str.length()) == 0) {
return str;
}
return new StringBuilder(strLen).append(Character.toTitleCase(str.charAt(0))).append(str.substring(1))
.toString();
}
/** bit type tag value. */
static final int TAG_TYPE_BITS = 3;
/**
* make protobuf tag.
*
* @param fieldNumber field number order
* @param wireType wireformat type
* @return tag id
*/
public static int makeTag(final int fieldNumber, final int wireType) {
return (fieldNumber << TAG_TYPE_BITS) | wireType;
}
/**
* Gets the enum name.
*
* @param e the e
* @param value the value
* @return the enum name
*/
public static String getEnumName(Enum[] e, int value) {
if (e != null) {
int toCompareValue;
for (Enum en : e) {
if (en instanceof EnumReadable) {
toCompareValue = ((EnumReadable) en).value();
} else {
toCompareValue = en.ordinal();
}
if (value == toCompareValue) {
return en.name();
}
}
}
return "";
}
/**
* Gets the enum value.
*
* @param en the en
* @return the enum value
*/
public static int getEnumValue(Enum en) {
if (en != null) {
int toCompareValue;
if (en instanceof EnumReadable) {
toCompareValue = ((EnumReadable) en).value();
} else {
toCompareValue = en.ordinal();
}
return toCompareValue;
}
return -1;
}
/**
* Gets the enumeration value.
*
* @param the generic type
* @param enumType the enum type
* @param name the name
* @return the enum value
*/
public static > T getEnumValue(Class enumType, String name) {
if (StringUtils.isEmpty(name)) {
return null;
}
try {
T v = Enum.valueOf(enumType, name);
return v;
} catch (IllegalArgumentException e) {
return null;
}
}
/**
* Read a field of any primitive type for immutable messages from a CodedInputStream. Enums, groups, and embedded
* messages are not handled by this method.
*
* @param input The stream from which to read.
* @param type Declared type of the field.
* @param checkUtf8 When true, check that the input is valid utf8.
* @return An object representing the field's value, of the exact type which would be returned by
* {@link Message#getField(Descriptors.FieldDescriptor)} for this field.
* @throws IOException Signals that an I/O exception has occurred.
*/
public static Object readPrimitiveField(CodedInputStream input, final WireFormat.FieldType type, boolean checkUtf8)
throws IOException {
switch (type) {
case DOUBLE:
return input.readDouble();
case FLOAT:
return input.readFloat();
case INT64:
return input.readInt64();
case UINT64:
return input.readUInt64();
case INT32:
return input.readInt32();
case FIXED64:
return input.readFixed64();
case FIXED32:
return input.readFixed32();
case BOOL:
return input.readBool();
case STRING:
if (checkUtf8) {
return input.readStringRequireUtf8();
} else {
return input.readString();
}
case BYTES:
return input.readByteArray();
case UINT32:
return input.readUInt32();
case SFIXED32:
return input.readSFixed32();
case SFIXED64:
return input.readSFixed64();
case SINT32:
return input.readSInt32();
case SINT64:
return input.readSInt64();
case GROUP:
throw new IllegalArgumentException("readPrimitiveField() cannot handle nested groups.");
case MESSAGE:
throw new IllegalArgumentException("readPrimitiveField() cannot handle embedded messages.");
case ENUM:
// We don't handle enums because we don't know what to do if the
// value is not recognized.
throw new IllegalArgumentException("readPrimitiveField() cannot handle enums.");
}
throw new RuntimeException("There is no way to get here, but the compiler thinks otherwise.");
}
/**
* Write a single tag-value pair to the stream.
*
* @param output The output stream.
* @param type The field's type.
* @param number The field's number.
* @param value Object representing the field's value. Must be of the exact type which would be returned by
* {@link Message#getField(Descriptors.FieldDescriptor)} for this field.
* @throws IOException Signals that an I/O exception has occurred.
*/
public static void writeElement(final CodedOutputStream output, final WireFormat.FieldType type, final int number,
final Object value) throws IOException {
// Special case for groups, which need a start and end tag; other fields
// can just use writeTag() and writeFieldNoTag().
if (type == WireFormat.FieldType.GROUP) {
output.writeGroup(number, (MessageLite) value);
} else {
output.writeTag(number, getWireFormatForFieldType(type, false));
writeElementNoTag(output, type, value);
}
}
/**
* Given a field type, return the wire type.
*
* @param type the type
* @param isPacked the is packed
* @return the wire format for field type
* @returns One of the {@code WIRETYPE_} constants defined in {@link WireFormat}.
*/
static int getWireFormatForFieldType(final WireFormat.FieldType type, boolean isPacked) {
if (isPacked) {
return WireFormat.WIRETYPE_LENGTH_DELIMITED;
} else {
return type.getWireType();
}
}
static byte[] toByteArray(Byte[] bb) {
byte[] ret = new byte[bb.length];
int i = 0;
for (Byte b : bb) {
ret[i++] = b.byteValue();
}
return ret;
}
/**
* Write a field of arbitrary type, without its tag, to the stream.
*
* @param output The output stream.
* @param type The field's type.
* @param value Object representing the field's value. Must be of the exact type which would be returned by
* {@link Message#getField(Descriptors.FieldDescriptor)} for this field.
* @throws IOException Signals that an I/O exception has occurred.
*/
public static void writeElementNoTag(final CodedOutputStream output, final WireFormat.FieldType type,
final Object value) throws IOException {
switch (type) {
case DOUBLE:
output.writeDoubleNoTag((Double) value);
break;
case FLOAT:
output.writeFloatNoTag((Float) value);
break;
case INT64:
output.writeInt64NoTag((Long) value);
break;
case UINT64:
output.writeUInt64NoTag((Long) value);
break;
case INT32:
output.writeInt32NoTag((Integer) value);
break;
case FIXED64:
output.writeFixed64NoTag((Long) value);
break;
case FIXED32:
output.writeFixed32NoTag((Integer) value);
break;
case BOOL:
output.writeBoolNoTag((Boolean) value);
break;
case STRING:
output.writeStringNoTag((String) value);
break;
// group not support yet
// case GROUP : output.writeGroupNoTag ((MessageLite) value); break;
case MESSAGE:
writeObject(output, 0, FieldType.OBJECT, value, false, false);
break;
case BYTES:
if (value instanceof ByteString) {
output.writeBytesNoTag((ByteString) value);
} else {
byte[] v;
if (value instanceof Byte[]) {
v = toByteArray((Byte[]) value);
} else {
v = (byte[]) value;
}
output.writeByteArrayNoTag(v);
}
break;
case UINT32:
output.writeUInt32NoTag((Integer) value);
break;
case SFIXED32:
output.writeSFixed32NoTag((Integer) value);
break;
case SFIXED64:
output.writeSFixed64NoTag((Long) value);
break;
case SINT32:
output.writeSInt32NoTag((Integer) value);
break;
case SINT64:
output.writeSInt64NoTag((Long) value);
break;
case ENUM:
if (value instanceof Internal.EnumLite) {
output.writeEnumNoTag(((Internal.EnumLite) value).getNumber());
} else {
if (value instanceof EnumReadable) {
output.writeEnumNoTag(((EnumReadable) value).value());
} else if (value instanceof Enum) {
output.writeEnumNoTag(((Enum) value).ordinal());
} else {
output.writeEnumNoTag(((Integer) value).intValue());
}
}
break;
}
}
/**
* Compute length delimited field size.
*
* @param fieldLength the field length
* @return the int
*/
public static int computeLengthDelimitedFieldSize(int fieldLength) {
return CodedOutputStream.computeUInt32SizeNoTag(fieldLength) + fieldLength;
}
/**
* Compute the number of bytes that would be needed to encode a particular value of arbitrary type, excluding tag.
*
* @param type The field's type.
* @param value Object representing the field's value. Must be of the exact type which would be returned by
* {@link Message#getField(Descriptors.FieldDescriptor)} for this field.
* @return the int
*/
public static int computeElementSizeNoTag(final WireFormat.FieldType type, final Object value) {
switch (type) {
// Note: Minor violation of 80-char limit rule here because this would
// actually be harder to read if we wrapped the lines.
case DOUBLE:
return CodedOutputStream.computeDoubleSizeNoTag((Double) value);
case FLOAT:
return CodedOutputStream.computeFloatSizeNoTag((Float) value);
case INT64:
return CodedOutputStream.computeInt64SizeNoTag((Long) value);
case UINT64:
return CodedOutputStream.computeUInt64SizeNoTag((Long) value);
case INT32:
return CodedOutputStream.computeInt32SizeNoTag((Integer) value);
case FIXED64:
return CodedOutputStream.computeFixed64SizeNoTag((Long) value);
case FIXED32:
return CodedOutputStream.computeFixed32SizeNoTag((Integer) value);
case BOOL:
return CodedOutputStream.computeBoolSizeNoTag((Boolean) value);
case STRING:
return CodedOutputStream.computeStringSizeNoTag((String) value);
case GROUP:
return CodedOutputStream.computeGroupSizeNoTag((MessageLite) value);
case BYTES:
if (value instanceof ByteString) {
return CodedOutputStream.computeBytesSizeNoTag((ByteString) value);
} else {
if (value instanceof Byte[]) {
return computeLengthDelimitedFieldSize(((Byte[]) value).length);
}
return CodedOutputStream.computeByteArraySizeNoTag((byte[]) value);
}
case UINT32:
return CodedOutputStream.computeUInt32SizeNoTag((Integer) value);
case SFIXED32:
return CodedOutputStream.computeSFixed32SizeNoTag((Integer) value);
case SFIXED64:
return CodedOutputStream.computeSFixed64SizeNoTag((Long) value);
case SINT32:
return CodedOutputStream.computeSInt32SizeNoTag((Integer) value);
case SINT64:
return CodedOutputStream.computeSInt64SizeNoTag((Long) value);
case MESSAGE:
if (value instanceof LazyField) {
return CodedOutputStream.computeLazyFieldSizeNoTag((LazyField) value);
} else {
return computeObjectSizeNoTag(value);
}
case ENUM:
if (value instanceof Internal.EnumLite) {
return CodedOutputStream.computeEnumSizeNoTag(((Internal.EnumLite) value).getNumber());
} else {
if (value instanceof EnumReadable) {
return CodedOutputStream.computeEnumSizeNoTag(((EnumReadable) value).value());
} else if (value instanceof Enum) {
return CodedOutputStream.computeEnumSizeNoTag(((Enum) value).ordinal());
}
return CodedOutputStream.computeEnumSizeNoTag((Integer) value);
}
}
throw new RuntimeException("There is no way to get here, but the compiler thinks otherwise.");
}
/**
* Gets the descriptor.
*
* @param cls the cls
* @return the descriptor
* @throws IOException Signals that an I/O exception has occurred.
*/
public static Descriptor getDescriptor(Class> cls) throws IOException {
String idl = ProtobufIDLGenerator.getIDL(cls);
ProtoFile file = ProtoParser.parse(ProtobufIDLProxy.DEFAULT_FILE_NAME, idl);
FileDescriptorProtoPOJO fileDescriptorProto = new FileDescriptorProtoPOJO();
fileDescriptorProto.name = ProtobufIDLProxy.DEFAULT_FILE_NAME;
fileDescriptorProto.pkg = file.packageName();
fileDescriptorProto.dependencies = file.dependencies();
fileDescriptorProto.publicDependency = convertList(file.publicDependencies());
fileDescriptorProto.weakDependency = null; // XXX
fileDescriptorProto.messageTypes = new ArrayList();
fileDescriptorProto.enumTypes = new ArrayList();
fileDescriptorProto.services = new ArrayList();
Set messageSet = new HashSet();
Set enumSet = new HashSet();
List typeElements = file.typeElements();
if (typeElements != null) {
for (TypeElement typeElement : typeElements) {
if (typeElement instanceof MessageElement) {
messageSet.add(typeElement.name());
} else if (typeElement instanceof EnumElement) {
enumSet.add(typeElement.name());
}
}
for (TypeElement typeElement : typeElements) {
if (typeElement instanceof MessageElement) {
fileDescriptorProto.messageTypes.add(getDescritorProtoPOJO(fileDescriptorProto,
(MessageElement) typeElement, messageSet, enumSet));
} else if (typeElement instanceof EnumElement) {
fileDescriptorProto.enumTypes.add(
getDescritorProtoPOJO(fileDescriptorProto, (EnumElement) typeElement, messageSet, enumSet));
}
}
}
FileDescriptorProto fileproto;
try {
Codec descriptorCodec = ProtobufProxy.create(FileDescriptorProtoPOJO.class,
ProtobufProxy.isCacheEnabled(), ProtobufProxy.OUTPUT_PATH.get());
byte[] bs = descriptorCodec.encode(fileDescriptorProto);
fileproto = FileDescriptorProto.parseFrom(bs);
} catch (InvalidProtocolBufferException e) {
throw new IOException("Failed to parse protocol buffer descriptor for generated code.", e);
}
FileDescriptor fileDescriptor;
try {
fileDescriptor =
FileDescriptor.buildFrom(fileproto, new com.google.protobuf.Descriptors.FileDescriptor[] {});
} catch (DescriptorValidationException e) {
throw new IOException(e.getMessage(), e);
}
return fileDescriptor.getMessageTypes().get(0);
}
/**
* Gets the descritor proto pojo.
*
* @param fileDescriptorProto the file descriptor proto
* @param typeElement the type element
* @param messageSet the message set
* @param enumSet the enum set
* @return the descritor proto pojo
*/
private static EnumDescriptorProtoPOJO getDescritorProtoPOJO(FileDescriptorProtoPOJO fileDescriptorProto,
EnumElement typeElement, Set messageSet, Set enumSet) {
EnumDescriptorProtoPOJO ret = new EnumDescriptorProtoPOJO();
ret.name = typeElement.name();
ret.values = new ArrayList();
ret.options = new ArrayList();
List values = typeElement.constants();
if (values != null) {
EnumValueDescriptorProtoPOJO fieldDescriptorProto;
for (EnumConstantElement fieldElement : values) {
fieldDescriptorProto = new EnumValueDescriptorProtoPOJO();
fieldDescriptorProto.name = fieldElement.name();
fieldDescriptorProto.number = fieldElement.tag();
ret.values.add(fieldDescriptorProto);
}
}
List options = typeElement.options();
if (options != null) {
EnumOptionsPOJO fieldDescriptorProto;
for (OptionElement option : options) {
fieldDescriptorProto = new EnumOptionsPOJO();
ret.options.add(fieldDescriptorProto);
}
}
return ret;
}
/**
* Gets the descritor proto pojo.
*
* @param fileDescriptorProto the file descriptor proto
* @param typeElement the type element
* @param messageSet the message set
* @param enumSet the enum set
* @return the descritor proto pojo
*/
private static DescriptorProtoPOJO getDescritorProtoPOJO(FileDescriptorProtoPOJO fileDescriptorProto,
MessageElement typeElement, Set messageSet, Set enumSet) {
DescriptorProtoPOJO ret = new DescriptorProtoPOJO();
ret.name = typeElement.name();
ret.fields = new ArrayList();
ret.nestedTypes = new ArrayList();
ret.enumTypes = new ArrayList();
ret.extensionRanges = new ArrayList();
ret.extensions = new ArrayList();
ret.options = new ArrayList();
ret.oneofDecls = new ArrayList();
List fields = typeElement.fields();
if (fields != null) {
FieldDescriptorProtoPOJO fieldDescriptorProto;
for (FieldElement fieldElement : fields) {
fieldDescriptorProto = new FieldDescriptorProtoPOJO();
fieldDescriptorProto.name = fieldElement.name();
fieldDescriptorProto.extendee = null; // XXX
fieldDescriptorProto.number = fieldElement.tag();
FieldElement.Label label = fieldElement.label();
if (label == FieldElement.Label.OPTIONAL) {
fieldDescriptorProto.label = Label.LABEL_OPTIONAL;
} else if (label == FieldElement.Label.REQUIRED) {
fieldDescriptorProto.label = Label.LABEL_REQUIRED;
} else if (label == FieldElement.Label.REPEATED) {
fieldDescriptorProto.label = Label.LABEL_REPEATED;
}
DataType type = fieldElement.type();
if (type.kind() == Kind.MAP) {
String messageName = StringUtils.capitalize(fieldDescriptorProto.name) + MAP_ENTRY_SUFFIX;
fieldDescriptorProto.type = Type.TYPE_MESSAGE;
fieldDescriptorProto.typeName = ICodeGenerator.PACKAGE_SPLIT + fileDescriptorProto.pkg
+ ICodeGenerator.PACKAGE_SPLIT + ret.name + ICodeGenerator.PACKAGE_SPLIT + messageName;
// refix label type
fieldDescriptorProto.label = Label.LABEL_REPEATED;
// here should add key and value type message type
DataType.MapType mapType = (DataType.MapType) type;
MessageElement messageElement = getMapKVMessageElements(messageName, mapType);
ret.nestedTypes
.add(getDescritorProtoPOJO(fileDescriptorProto, messageElement, messageSet, enumSet));
} else if (type.kind() == Kind.MAP || type.kind() == Kind.NAMED) {
fieldDescriptorProto.typeName = ((DataType.NamedType) type).name();
if (messageSet.contains(fieldDescriptorProto.typeName)) {
fieldDescriptorProto.type = Type.TYPE_MESSAGE;
} else {
fieldDescriptorProto.type = Type.TYPE_ENUM;
}
} else {
fieldDescriptorProto.type = Type.valueOf("TYPE_" + ((DataType.ScalarType) type).name());
}
ret.fields.add(fieldDescriptorProto);
}
}
List nestedElements = typeElement.nestedElements();
if (nestedElements != null) {
for (TypeElement nestedTypeElement : nestedElements) {
if (nestedTypeElement instanceof MessageElement) {
ret.nestedTypes.add(getDescritorProtoPOJO(fileDescriptorProto, (MessageElement) nestedTypeElement,
messageSet, enumSet));
} else if (nestedTypeElement instanceof EnumElement) {
ret.enumTypes.add(getDescritorProtoPOJO(fileDescriptorProto, (EnumElement) nestedTypeElement,
messageSet, enumSet));
}
}
}
return ret;
}
/**
* Gets the map kv message elements.
*
* @param name the name
* @param mapType the map type
* @return the map kv message elements
*/
private static MessageElement getMapKVMessageElements(String name, MapType mapType) {
MessageElement.Builder ret = MessageElement.builder();
ret.name(name);
DataType keyType = mapType.keyType();
Builder fieldBuilder = FieldElement.builder().name("key").tag(1);
fieldBuilder.type(keyType).label(FieldElement.Label.OPTIONAL);
ret.addField(fieldBuilder.build());
DataType valueType = mapType.valueType();
fieldBuilder = FieldElement.builder().name("value").tag(2);
fieldBuilder.type(valueType).label(FieldElement.Label.OPTIONAL);
ret.addField(fieldBuilder.build());
return ret.build();
}
/**
* Convert list.
*
* @param list the list
* @return the list
*/
private static List convertList(List list) {
if (list == null) {
return null;
}
List ret = new ArrayList(list.size());
for (String v : list) {
ret.add(StringUtils.toInt(v));
}
return ret;
}
}