/src/org/matmexrhino/protobuf/scala/scala_message.cc

http://protobuf-scala.googlecode.com/ · C++ · 137 lines · 105 code · 18 blank · 14 comment · 11 complexity · 0ddb15a2c5bdebb47bfce26c0ff83122 MD5 · raw file

  1. /*
  2. * Copyright 2010 Eugene Vigdorchik.
  3. * Licensed under the Apache License, Version 2.0 (the "License");
  4. * you may not use this file except in compliance with the License.
  5. * You may obtain a copy of the License at
  6. *
  7. * http://www.apache.org/licenses/LICENSE-2.0
  8. *
  9. * Unless required by applicable law or agreed to in writing, software
  10. * distributed under the License is distributed on an "AS IS" BASIS,
  11. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. * See the License for the specific language governing permissions and
  13. * limitations under the License.
  14. */
  15. #include <map>
  16. #include <string>
  17. #include <google/protobuf/compiler/java/java_helpers.h>
  18. #include <org/matmexrhino/protobuf/scala/scala_message.h>
  19. using std::map;
  20. using std::string;
  21. using namespace google::protobuf::compiler::java;
  22. using google::protobuf::FieldDescriptor;
  23. namespace {
  24. string GetScalaType(const FieldDescriptor* descriptor, bool box) {
  25. switch (GetJavaType(descriptor)) {
  26. case JAVATYPE_INT: return box ? "java.lang.Integer" : "scala.Int";
  27. case JAVATYPE_LONG: return box ? "java.lang.Long" : "scala.Long";
  28. case JAVATYPE_FLOAT: return box ? "java.lang.Float" : "scala.Float";
  29. case JAVATYPE_DOUBLE: return box ? "java.lang.Double" : "scala.Double";
  30. case JAVATYPE_BOOLEAN: return box ? "java.lang.Boolean" : "scala.Boolean";
  31. case JAVATYPE_STRING: return "java.lang.String";
  32. case JAVATYPE_BYTES: return "com.google.protobuf.ByteString";
  33. case JAVATYPE_ENUM: return ClassName(descriptor->enum_type());
  34. case JAVATYPE_MESSAGE: return ClassName(descriptor->message_type()) + ".Builder";
  35. default: GOOGLE_LOG(FATAL) << "Unknown java type for a field";
  36. }
  37. }
  38. string ObjectName(const Descriptor* descriptor) {
  39. const Descriptor* container = descriptor->containing_type();
  40. if (container) return ObjectName(container) + "." + descriptor->name();
  41. return FileJavaPackage(descriptor->file()) + ".scala." +
  42. FileClassName(descriptor->file()) + "." + descriptor->name();
  43. }
  44. } // namespace
  45. namespace org {
  46. namespace matmexrhino {
  47. namespace protobuf {
  48. namespace scala {
  49. ScalaMessageGenerator::ScalaMessageGenerator() {}
  50. ScalaMessageGenerator::~ScalaMessageGenerator() {}
  51. void ScalaMessageGenerator::PrintField(const FieldDescriptor* field,
  52. const string& classname,
  53. const string& constr_value_part,
  54. bool box_field_type,
  55. Printer* printer) const {
  56. map<string, string> vars;
  57. vars["name"] = field->name();
  58. vars["classname"] = classname + ".Builder";
  59. vars["opttype"] = GetScalaType(field, box_field_type);
  60. if (field->is_repeated()) {
  61. vars["sort"] = "Seq";
  62. vars["constr"] = "(_ add" + constr_value_part + ")";
  63. } else if (field->type() == FieldDescriptor::TYPE_MESSAGE ||
  64. field->type() == FieldDescriptor::TYPE_GROUP) {
  65. vars["sort"] = "Message";
  66. vars["constr"] = "(_ set" + constr_value_part + ")"
  67. "(" + ObjectName(field->message_type()) + ")";
  68. } else {
  69. vars["sort"] = "";
  70. vars["constr"] = "(_ set" + constr_value_part + ")";
  71. }
  72. printer->Print(vars,
  73. "val $name$ = new org.matmexrhino.protobuf.scala.$sort$Opt"
  74. "[$classname$, $opttype$]$constr$\n");
  75. }
  76. void ScalaMessageGenerator::GenerateField(const FieldDescriptor* field,
  77. const string& classname,
  78. Printer* printer) const {
  79. PrintField(field, classname,
  80. UnderscoresToCapitalizedCamelCase(field) + " _", false, printer);
  81. }
  82. void ScalaMessageGenerator::GenerateExtension(const FieldDescriptor* field,
  83. const string& classname,
  84. Printer* printer) const {
  85. const string generated_extension = classname + "." + field->name();
  86. PrintField(field, ClassName(field->containing_type()),
  87. "Extension(" + generated_extension + ", _)", true, printer);
  88. }
  89. void ScalaMessageGenerator::Generate(const Descriptor* descriptor,
  90. Printer* printer) const {
  91. string classname = ClassName(descriptor);
  92. map<string, string> objvars;
  93. objvars["name"] = descriptor->name();
  94. objvars["classname"] = classname;
  95. printer->Print(objvars,
  96. "object $name$ extends "
  97. "org.matmexrhino.protobuf.scala.MessageObject[$classname$.Builder] {\n");
  98. printer->Indent();
  99. printer->Print(objvars, "def newInstance = $classname$.newBuilder\n");
  100. printer->Print(objvars, "def clone(b : $classname$.Builder) = b.clone\n");
  101. for(int i = 0; i < descriptor->field_count(); ++i) {
  102. GenerateField(descriptor->field(i), classname, printer);
  103. }
  104. for(int i = 0; i < descriptor->extension_count(); ++i) {
  105. GenerateExtension(descriptor->extension(i), classname, printer);
  106. }
  107. printer->Print("\n");
  108. printer->Print("implicit def buildProto(b : $classname$.Builder) = b.build()\n",
  109. "classname", classname);
  110. for(int i = 0; i < descriptor->nested_type_count(); ++i) {
  111. Generate(descriptor->nested_type(i), printer);
  112. }
  113. printer->Outdent();
  114. printer->Print("}\n");
  115. }
  116. } // namespace scala
  117. } // namespace protobuf
  118. } // namespace matmexrhino
  119. } // namespace org