package com.fasterxml.jackson.dataformat.protobuf.schema;
import java.util.EnumMap;
import java.util.Map;
import com.squareup.protoparser.DataType;
import com.squareup.protoparser.EnumConstantElement;
import com.squareup.protoparser.EnumElement;
import com.squareup.protoparser.FieldElement;
import com.squareup.protoparser.MessageElement;
import com.squareup.protoparser.OptionElement;
import com.squareup.protoparser.ProtoFile;
public class FileDescriptorSet
{
protected FileDescriptorProto[] file;
protected FileDescriptorSet() { }
public FileDescriptorSet(FileDescriptorProto[] f) {
file = f;
}
public FileDescriptorProto[] getFile() { return file; }
public FileDescriptorProto findDescriptor(String fileName)
{
for (FileDescriptorProto fdp : file) {
if (fdp.name.equals(fileName)) {
return fdp;
}
}
return null;
}
public FileDescriptorProto getDescriptor(String fileName)
{
FileDescriptorProto p = findDescriptor(fileName);
if (p == null) {
throw new IllegalArgumentException(fileName + " not found");
}
return p;
}
public ProtobufSchema schemaForFirstType()
{
ProtoFile protoFile = buildProtoFile(file[0].name);
return NativeProtobufSchema.construct(protoFile).forFirstType();
}
public ProtobufSchema schemaFor(String rootTypeName)
{
for (FileDescriptorProto fdp : file) {
for (DescriptorProto dp : fdp.message_type) {
if (dp.name.equals(rootTypeName)) {
ProtoFile protoFile = buildProtoFile(fdp.name);
NativeProtobufSchema nps = NativeProtobufSchema.construct(protoFile);
return nps.forType(rootTypeName);
}
}
}
throw new IllegalArgumentException(rootTypeName + " not found");
}
private ProtoFile buildProtoFile(String fileName)
{
FileDescriptorProto fdp = getDescriptor(fileName);
ProtoFile.Builder builder = ProtoFile.builder(fdp.name);
builder.syntax(fdp.getSyntax());
builder.packageName(fdp.getPackage());
if (fdp.dependency != null) {
for (String dependency : fdp.dependency) {
FileDescriptorProto dep = getDescriptor(dependency);
for (DescriptorProto dp : dep.message_type) {
MessageElement me = dp.buildMessageElement();
builder.addType(me);
}
}
}
for (DescriptorProto dp : fdp.message_type) {
MessageElement me = dp.buildMessageElement();
builder.addType(me);
}
return builder.build();
}
public static class FileDescriptorProto
{
public String name;
protected String _package;
public String[] dependency;
public int[] public_dependency;
public int[] weak_dependency;
public DescriptorProto[] message_type;
public EnumDescriptorProto[] enum_type;
public ServiceDescriptorProto[] service;
public FieldDescriptorProto[] extension;
public FileOptions options;
public SourceCodeInfo source_code_info;
public String syntax;
public ProtoFile.Syntax getSyntax()
{
if (syntax == null) {
return ProtoFile.Syntax.PROTO_2;
}
return ProtoFile.Syntax.valueOf(syntax);
}
public void setPackage(String p) { _package = p; }
public String getPackage() { return _package; }
}
public static class DescriptorProto
{
public String name;
public FieldDescriptorProto[] field;
public FieldDescriptorProto[] extension;
public DescriptorProto[] nested_type;
public EnumDescriptorProto[] enum_type;
static class ExtensionRange
{
public int start;
public int end;
}
public ExtensionRange[] extension_range;
public OneofDescriptorProto[] oneof_decl;
public MessageOptions options;
static class ReservedRange
{
public int start;
public int end;
}
public ReservedRange[] reserved_range;
public String[] reserved_name;
public MessageElement buildMessageElement()
{
MessageElement.Builder messageElementBuilder = MessageElement.builder();
messageElementBuilder.name(name);
if (field != null) {
for (FieldDescriptorProto f : field) {
DataType dataType;
String fieldName = f.name;
FieldDescriptorProto.Type type = f.type;
FieldElement.Label label = f.getLabel();
if (type.equals(FieldDescriptorProto.Type.TYPE_MESSAGE)
|| type.equals(FieldDescriptorProto.Type.TYPE_ENUM)) {
String fullyQualifiedtypeName = f.type_name;
String typeName = fullyQualifiedtypeName.substring(fullyQualifiedtypeName.indexOf(".", 2) + 1);
dataType = DataType.NamedType.create(typeName);
} else {
dataType = f.getDataType();
}
FieldElement.Builder fieldBuilder = FieldElement
.builder()
.name(fieldName)
.type(dataType)
.label(label)
.tag(f.number);
if (f.json_name != null) {
OptionElement.Kind kind = OptionElement.Kind.STRING;
OptionElement option = OptionElement.create("json_name", kind, f.json_name);
fieldBuilder.addOption(option);
}
if (f.options != null) {
if (f.options.packed) {
OptionElement.Kind kind = OptionElement.Kind.STRING;
OptionElement option = OptionElement.create("packed", kind, "true");
fieldBuilder.addOption(option);
}
}
messageElementBuilder.addField(fieldBuilder.build());
}
}
if (nested_type != null) {
for (DescriptorProto n : nested_type) {
messageElementBuilder.addType(n.buildMessageElement());
}
}
if (enum_type != null) {
for (EnumDescriptorProto e : enum_type) {
EnumElement.Builder nestedEnumElement = EnumElement
.builder()
.name(e.name);
for (EnumValueDescriptorProto v : e.value) {
EnumConstantElement.Builder c = EnumConstantElement.builder()
.name(v.name)
.tag(v.number);
nestedEnumElement.addConstant(c.build());
}
messageElementBuilder.addType(nestedEnumElement.build());
}
}
return messageElementBuilder.build();
}
}
public static class FieldDescriptorProto
{
public enum Type
{
TYPE_DOUBLE,
TYPE_FLOAT,
TYPE_INT64,
TYPE_UINT64,
TYPE_INT32,
TYPE_FIXED64,
TYPE_FIXED32,
TYPE_BOOL,
TYPE_STRING,
TYPE_GROUP,
TYPE_MESSAGE,
TYPE_BYTES,
TYPE_UINT32,
TYPE_ENUM,
TYPE_SFIXED32,
TYPE_SFIXED64,
TYPE_SINT32,
TYPE_SINT64
}
public enum Label
{
LABEL_OPTIONAL,
LABEL_REQUIRED,
LABEL_REPEATED
}
public String name;
public int number;
public Label label;
public Type type;
public String type_name;
public String extendee;
public String default_value;
public int oneof_index;
public String json_name;
public FieldOptions options;
static private Map<Type, DataType> scalarTypeMap = new EnumMap<>(Type.class);
static private Map<Label, FieldElement.Label> labelMap = new EnumMap<>(Label.class);
static {
scalarTypeMap.put(Type.TYPE_DOUBLE, DataType.ScalarType.DOUBLE);
scalarTypeMap.put(Type.TYPE_FLOAT, DataType.ScalarType.FLOAT);
scalarTypeMap.put(Type.TYPE_INT64, DataType.ScalarType.INT64);
scalarTypeMap.put(Type.TYPE_UINT64, DataType.ScalarType.UINT64);
scalarTypeMap.put(Type.TYPE_INT32, DataType.ScalarType.INT32);
scalarTypeMap.put(Type.TYPE_FIXED64, DataType.ScalarType.FIXED64);
scalarTypeMap.put(Type.TYPE_FIXED32, DataType.ScalarType.FIXED32);
scalarTypeMap.put(Type.TYPE_BOOL, DataType.ScalarType.BOOL);
scalarTypeMap.put(Type.TYPE_STRING, DataType.ScalarType.STRING);
scalarTypeMap.put(Type.TYPE_BYTES, DataType.ScalarType.BYTES);
scalarTypeMap.put(Type.TYPE_UINT32, DataType.ScalarType.UINT32);
scalarTypeMap.put(Type.TYPE_SFIXED32, DataType.ScalarType.SFIXED32);
scalarTypeMap.put(Type.TYPE_SFIXED64, DataType.ScalarType.SFIXED64);
scalarTypeMap.put(Type.TYPE_SINT32, DataType.ScalarType.SINT32);
scalarTypeMap.put(Type.TYPE_SINT64, DataType.ScalarType.SINT64);
labelMap.put(Label.LABEL_OPTIONAL, FieldElement.Label.OPTIONAL);
labelMap.put(Label.LABEL_REQUIRED, FieldElement.Label.REQUIRED);
labelMap.put(Label.LABEL_REPEATED, FieldElement.Label.REPEATED);
}
public DataType getDataType()
{
return scalarTypeMap.get(type);
}
public FieldElement.Label getLabel()
{
return labelMap.get(label);
}
}
public static class OneofDescriptorProto
{
public String name;
public OneofOptions options;
}
public static class EnumDescriptorProto
{
public String name;
public EnumValueDescriptorProto[] value;
public EnumOptions options;
}
public static class EnumValueDescriptorProto
{
public String name;
public int number;
public EnumValueOptions options;
}
public static class ServiceDescriptorProto
{
public String name;
public MethodDescriptorProto[] method;
public ServiceOptions options;
}
public static class MethodDescriptorProto
{
public String name;
public String input_type;
public String output_type;
public MethodOptions options;
public boolean client_streaming;
public boolean server_streaming;
}
public static class FileOptions
{
public String java_package;
public String java_outer_classname;
public boolean java_multiple_files;
public boolean java_generate_equals_and_hash;
public boolean java_String_check_utf8;
enum OptimizeMode
{
SPEED,
CODE_SIZE,
LITE_RUNTIME
}
public OptimizeMode optimize_for;
public String go_package;
public boolean cc_generic_services;
public boolean java_generic_services;
public boolean py_generic_services;
public boolean deprecated;
public boolean cc_enable_arenas;
public String objc_class_prefix;
public String csharp_namespace;
public String swift_prefix;
public String php_class_prefix;
public UninterpretedOption[] uninterpreted_option;
}
public static class MessageOptions
{
public boolean message_set_wire_format;
public boolean no_standard_descriptor_accessor;
public boolean deprecated;
public boolean map_entry;
public UninterpretedOption[] uninterpreted_option;
}
public static class FieldOptions
{
public CType ctype;
enum CType
{
STRING,
CORD,
STRING_PIECE
}
public boolean packed;
public JSType jstype;
enum JSType
{
JS_NORMAL,
JS_STRING,
JS_NUMBER
}
public boolean lazy;
public boolean deprecated;
public boolean weak;
public UninterpretedOption[] uninterpreted_option;
}
public static class OneofOptions
{
public UninterpretedOption[] uninterpreted_option;
}
public static class EnumOptions
{
public boolean allow_alias;
public boolean deprecated;
public UninterpretedOption[] uninterpreted_option;
}
public static class EnumValueOptions
{
public boolean deprecated;
public UninterpretedOption[] uninterpreted_option;
}
public static class ServiceOptions
{
public boolean deprecated;
public UninterpretedOption[] uninterpreted_option;
}
public static class MethodOptions
{
public boolean deprecated;
enum IdempotencyLevel
{
IDEMPOTENCY_UNKNOWN,
NO_SIDE_EFFECTS,
IDEMPOTENT
}
public IdempotencyLevel idempotency_level;
public UninterpretedOption[] uninterpreted_option;
}
public static class UninterpretedOption
{
static class NamePart
{
public String name_part;
public boolean is_extension;
}
public NamePart[] name;
public String identifier_value;
public long positive_int_value;
public long negative_int_value;
public double double_value;
public byte[] string_value;
public String aggregate_value;
}
public static class SourceCodeInfo
{
public Location[] location;
public static class Location
{
public int[] path;
public int[] span;
public String ;
public String ;
public String[] ;
}
}
}