text:
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.  All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include <google/protobuf/compiler/java/java_map_field_lite.h>

#include <google/protobuf/compiler/java/java_context.h>
#include <google/protobuf/compiler/java/java_doc_comment.h>
#include <google/protobuf/compiler/java/java_helpers.h>
#include <google/protobuf/compiler/java/java_name_resolver.h>
#include <google/protobuf/io/printer.h>

namespace google {
namespace protobuf {
namespace compiler {
namespace java {

namespace {

const FieldDescriptor* KeyField(const FieldDescriptor* descriptor) {
  GOOGLE_CHECK_EQ(FieldDescriptor::TYPE_MESSAGE, descriptor->type());
  const Descriptor* message = descriptor->message_type();
  GOOGLE_CHECK(message->options().map_entry());
  return message->FindFieldByName("key");
}

const FieldDescriptor* ValueField(const FieldDescriptor* descriptor) {
  GOOGLE_CHECK_EQ(FieldDescriptor::TYPE_MESSAGE, descriptor->type());
  const Descriptor* message = descriptor->message_type();
  GOOGLE_CHECK(message->options().map_entry());
  return message->FindFieldByName("value");
}

string TypeName(const FieldDescriptor* field,
                ClassNameResolver* name_resolver,
                bool boxed) {
  if (GetJavaType(field) == JAVATYPE_MESSAGE) {
    return name_resolver->GetImmutableClassName(field->message_type());
  } else if (GetJavaType(field) == JAVATYPE_ENUM) {
    return name_resolver->GetImmutableClassName(field->enum_type());
  } else {
    return boxed ? BoxedPrimitiveTypeName(GetJavaType(field))
                 : PrimitiveTypeName(GetJavaType(field));
  }
}

string WireType(const FieldDescriptor* field) {
  return "com.google.protobuf.WireFormat.FieldType." +
      string(FieldTypeName(field->type()));
}

void SetMessageVariables(const FieldDescriptor* descriptor,
                         int messageBitIndex,
                         int builderBitIndex,
                         const FieldGeneratorInfo* info,
                         Context* context,
                         std::map<string, string>* variables) {
  SetCommonFieldVariables(descriptor, info, variables);

  ClassNameResolver* name_resolver = context->GetNameResolver();
  (*variables)["type"] =
      name_resolver->GetImmutableClassName(descriptor->message_type());
  const FieldDescriptor* key = KeyField(descriptor);
  const FieldDescriptor* value = ValueField(descriptor);
  const JavaType keyJavaType = GetJavaType(key);
  const JavaType valueJavaType = GetJavaType(value);

  (*variables)["key_type"] = TypeName(key, name_resolver, false);
  (*variables)["boxed_key_type"] = TypeName(key, name_resolver, true);
  (*variables)["key_wire_type"] = WireType(key);
  (*variables)["key_default_value"] = DefaultValue(key, true, name_resolver);
  (*variables)["key_null_check"] = IsReferenceType(keyJavaType) ?
      "if (key == null) { throw new java.lang.NullPointerException(); }" : "";
  (*variables)["value_null_check"] = IsReferenceType(valueJavaType) ?
      "if (value == null) { throw new java.lang.NullPointerException(); }" : "";

  if (GetJavaType(value) == JAVATYPE_ENUM) {
    // We store enums as Integers internally.
    (*variables)["value_type"] = "int";
    (*variables)["boxed_value_type"] = "java.lang.Integer";
    (*variables)["value_wire_type"] = WireType(value);
    (*variables)["value_default_value"] =
        DefaultValue(value, true, name_resolver) + ".getNumber()";

    (*variables)["value_enum_type"] = TypeName(value, name_resolver, false);

    if (SupportUnknownEnumValue(descriptor->file())) {
      // Map unknown values to a special UNRECOGNIZED value if supported.
      (*variables)["unrecognized_value"] =
          (*variables)["value_enum_type"] + ".UNRECOGNIZED";
    } else {
      // Map unknown values to the default value if we don't have UNRECOGNIZED.
      (*variables)["unrecognized_value"] =
          DefaultValue(value, true, name_resolver);
    }
  } else {
    (*variables)["value_type"] = TypeName(value, name_resolver, false);
    (*variables)["boxed_value_type"] = TypeName(value, name_resolver, true);
    (*variables)["value_wire_type"] = WireType(value);
    (*variables)["value_default_value"] =
        DefaultValue(value, true, name_resolver);
  }
  (*variables)["type_parameters"] =
      (*variables)["boxed_key_type"] + ", " + (*variables)["boxed_value_type"];
  // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
  // by the proto compiler
  (*variables)["deprecation"] = descriptor->options().deprecated()
      ? "@java.lang.Deprecated " : "";

  (*variables)["default_entry"] = (*variables)["capitalized_name"] +
      "DefaultEntryHolder.defaultEntry";
}

}  // namespace

ImmutableMapFieldLiteGenerator::
ImmutableMapFieldLiteGenerator(const FieldDescriptor* descriptor,
                                       int messageBitIndex,
                                       int builderBitIndex,
                                       Context* context)
  : descriptor_(descriptor), name_resolver_(context->GetNameResolver())  {
  SetMessageVariables(descriptor, messageBitIndex, builderBitIndex,
                      context->GetFieldGeneratorInfo(descriptor),
                      context, &variables_);
}

ImmutableMapFieldLiteGenerator::
~ImmutableMapFieldLiteGenerator() {}

int ImmutableMapFieldLiteGenerator::GetNumBitsForMessage() const {
  return 0;
}

int ImmutableMapFieldLiteGenerator::GetNumBitsForBuilder() const {
  return 0;
}

void ImmutableMapFieldLiteGenerator::
GenerateInterfaceMembers(io::Printer* printer) const {
  WriteFieldDocComment(printer, descriptor_);
  printer->Print(
      variables_,
      "$deprecation$int ${$get$capitalized_name$Count$}$();\n");
  printer->Annotate("{", "}", descriptor_);
  WriteFieldDocComment(printer, descriptor_);
  printer->Print(
      variables_,
      "$deprecation$boolean ${$contains$capitalized_name$$}$(\n"
      "    $key_type$ key);\n");
  printer->Annotate("{", "}", descriptor_);
  if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
    printer->Print(
        variables_,
        "/**\n"
        " * Use {@link #get$capitalized_name$Map()} instead.\n"
        " */\n"
        "@java.lang.Deprecated\n"
        "java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
        "${$get$capitalized_name$$}$();\n");
    printer->Annotate("{", "}", descriptor_);
    WriteFieldDocComment(printer, descriptor_);
    printer->Print(
        variables_,
        "$deprecation$java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
        "${$get$capitalized_name$Map$}$();\n");
    printer->Annotate("{", "}", descriptor_);
    WriteFieldDocComment(printer, descriptor_);
    printer->Print(
        variables_,
        "$deprecation$$value_enum_type$ ${$get$capitalized_name$OrDefault$}$(\n"
        "    $key_type$ key,\n"
        "    $value_enum_type$ defaultValue);\n");
    printer->Annotate("{", "}", descriptor_);
    WriteFieldDocComment(printer, descriptor_);
    printer->Print(
        variables_,
        "$deprecation$$value_enum_type$ ${$get$capitalized_name$OrThrow$}$(\n"
        "    $key_type$ key);\n");
    printer->Annotate("{", "}", descriptor_);
    if (SupportUnknownEnumValue(descriptor_->file())) {
      printer->Print(
          variables_,
          "/**\n"
          " * Use {@link #get$capitalized_name$ValueMap()} instead.\n"
          " */\n"
          "@java.lang.Deprecated\n"
          "java.util.Map<$type_parameters$>\n"
          "${$get$capitalized_name$Value$}$();\n");
      printer->Annotate("{", "}", descriptor_);
      WriteFieldDocComment(printer, descriptor_);
      printer->Print(
          variables_,
          "$deprecation$java.util.Map<$type_parameters$>\n"
          "${$get$capitalized_name$ValueMap$}$();\n");
      printer->Annotate("{", "}", descriptor_);
      WriteFieldDocComment(printer, descriptor_);
      printer->Print(
          variables_,
          "$deprecation$\n"
          "$value_type$ ${$get$capitalized_name$ValueOrDefault$}$(\n"
          "    $key_type$ key,\n"
          "    $value_type$ defaultValue);\n");
      printer->Annotate("{", "}", descriptor_);
      WriteFieldDocComment(printer, descriptor_);
      printer->Print(
          variables_,
          "$deprecation$\n"
          "$value_type$ ${$get$capitalized_name$ValueOrThrow$}$(\n"
          "    $key_type$ key);\n");
      printer->Annotate("{", "}", descriptor_);
    }
  } else {
    printer->Print(
        variables_,
        "/**\n"
        " * Use {@link #get$capitalized_name$Map()} instead.\n"
        " */\n"
        "@java.lang.Deprecated\n"
        "java.util.Map<$type_parameters$>\n"
        "${$get$capitalized_name$$}$();\n");
    printer->Annotate("{", "}", descriptor_);
    WriteFieldDocComment(printer, descriptor_);
    printer->Print(
        variables_,
        "$deprecation$java.util.Map<$type_parameters$>\n"
        "${$get$capitalized_name$Map$}$();\n");
    printer->Annotate("{", "}", descriptor_);
    WriteFieldDocComment(printer, descriptor_);
    printer->Print(
        variables_,
        "$deprecation$\n"
        "$value_type$ ${$get$capitalized_name$OrDefault$}$(\n"
        "    $key_type$ key,\n"
        "    $value_type$ defaultValue);\n");
    printer->Annotate("{", "}", descriptor_);
    WriteFieldDocComment(printer, descriptor_);
    printer->Print(
        variables_,
        "$deprecation$\n"
        "$value_type$ ${$get$capitalized_name$OrThrow$}$(\n"
        "    $key_type$ key);\n");
    printer->Annotate("{", "}", descriptor_);
  }
}

void ImmutableMapFieldLiteGenerator::
GenerateMembers(io::Printer* printer) const {
  printer->Print(
      variables_,
      "private static final class $capitalized_name$DefaultEntryHolder {\n"
      "  static final com.google.protobuf.MapEntryLite<\n"
      "      $type_parameters$> defaultEntry =\n"
      "          com.google.protobuf.MapEntryLite\n"
      "          .<$type_parameters$>newDefaultInstance(\n"
      "              $key_wire_type$,\n"
      "              $key_default_value$,\n"
      "              $value_wire_type$,\n"
      "              $value_default_value$);\n"
      "}\n");
  printer->Print(
      variables_,
      "private com.google.protobuf.MapFieldLite<\n"
      "    $type_parameters$> $name$_ =\n"
      "        com.google.protobuf.MapFieldLite.emptyMapField();\n"
      "private com.google.protobuf.MapFieldLite<$type_parameters$>\n"
      "internalGet$capitalized_name$() {\n"
      "  return $name$_;\n"
      "}\n"
      "private com.google.protobuf.MapFieldLite<$type_parameters$>\n"
      "internalGetMutable$capitalized_name$() {\n"
      "  if (!$name$_.isMutable()) {\n"
      "    $name$_ = $name$_.mutableCopy();\n"
      "  }\n"
      "  return $name$_;\n"
      "}\n");
  printer->Print(
      variables_,
      "$deprecation$\n"
      "public int ${$get$capitalized_name$Count$}$() {\n"
      "  return internalGet$capitalized_name$().size();\n"
      "}\n");
  printer->Annotate("{", "}", descriptor_);
  WriteFieldDocComment(printer, descriptor_);
  printer->Print(
      variables_,
      "$deprecation$\n"
      "public boolean ${$contains$capitalized_name$$}$(\n"
      "    $key_type$ key) {\n"
      "  $key_null_check$\n"
      "  return internalGet$capitalized_name$().containsKey(key);\n"
      "}\n");
  printer->Annotate("{", "}", descriptor_);
  if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
    printer->Print(
        variables_,
        "private static final\n"
        "com.google.protobuf.Internal.MapAdapter.Converter<\n"
        "    java.lang.Integer, $value_enum_type$> $name$ValueConverter =\n"
        "        com.google.protobuf.Internal.MapAdapter.newEnumConverter(\n"
        "            $value_enum_type$.internalGetValueMap(),\n"
        "            $unrecognized_value$);\n");
    printer->Print(
        variables_,
        "/**\n"
        " * Use {@link #get$capitalized_name$Map()} instead.\n"
        " */\n"
        "@java.lang.Deprecated\n"
        "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
        "${$get$capitalized_name$$}$() {\n"
        "  return get$capitalized_name$Map();\n"
        "}\n");
    printer->Annotate("{", "}", descriptor_);
    WriteFieldDocComment(printer, descriptor_);
    printer->Print(
        variables_,
        "$deprecation$\n"
        "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
        "${$get$capitalized_name$Map$}$() {\n"
        "  return java.util.Collections.unmodifiableMap(\n"
        "      new com.google.protobuf.Internal.MapAdapter<\n"
        "        $boxed_key_type$, $value_enum_type$, java.lang.Integer>(\n"
        "            internalGet$capitalized_name$(),\n"
        "            $name$ValueConverter));\n"
        "}\n");
    printer->Annotate("{", "}", descriptor_);
    WriteFieldDocComment(printer, descriptor_);
    printer->Print(
        variables_,
        "$deprecation$\n"
        "public $value_enum_type$ ${$get$capitalized_name$OrDefault$}$(\n"
        "    $key_type$ key,\n"
        "    $value_enum_type$ defaultValue) {\n"
        "  $key_null_check$\n"
        "  java.util.Map<$boxed_key_type$, $boxed_value_type$> map =\n"
        "      internalGet$capitalized_name$();\n"
        "  return map.containsKey(key)\n"
        "         ? $name$ValueConverter.doForward(map.get(key))\n"
        "         : defaultValue;\n"
        "}\n");
    printer->Annotate("{", "}", descriptor_);
    WriteFieldDocComment(printer, descriptor_);
    printer->Print(
        variables_,
        "$deprecation$\n"
        "public $value_enum_type$ ${$get$capitalized_name$OrThrow$}$(\n"
        "    $key_type$ key) {\n"
        "  $key_null_check$\n"
        "  java.util.Map<$boxed_key_type$, $boxed_value_type$> map =\n"
        "      internalGet$capitalized_name$();\n"
        "  if (!map.containsKey(key)) {\n"
        "    throw new java.lang.IllegalArgumentException();\n"
        "  }\n"
        "  return $name$ValueConverter.doForward(map.get(key));\n"
        "}\n");
    printer->Annotate("{", "}", descriptor_);
    if (SupportUnknownEnumValue(descriptor_->file())) {
      printer->Print(
          variables_,
          "/**\n"
          " * Use {@link #get$capitalized_name$ValueMap()} instead.\n"
          " */\n"
          "@java.lang.Deprecated\n"
          "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
          "${$get$capitalized_name$Value$}$() {\n"
          "  return get$capitalized_name$ValueMap();\n"
          "}\n");
      printer->Annotate("{", "}", descriptor_);
      WriteFieldDocComment(printer, descriptor_);
      printer->Print(
          variables_,
          "$deprecation$\n"
          "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
          "${$get$capitalized_name$ValueMap$}$() {\n"
          "  return java.util.Collections.unmodifiableMap(\n"
          "      internalGet$capitalized_name$());\n"
          "}\n");
      printer->Annotate("{", "}", descriptor_);
      WriteFieldDocComment(printer, descriptor_);
      printer->Print(
          variables_,
          "$deprecation$\n"
          "public $value_type$ ${$get$capitalized_name$ValueOrDefault$}$(\n"
          "    $key_type$ key,\n"
          "    $value_type$ defaultValue) {\n"
          "  $key_null_check$\n"
          "  java.util.Map<$boxed_key_type$, $boxed_value_type$> map =\n"
          "      internalGet$capitalized_name$();\n"
          "  return map.containsKey(key) ? map.get(key) : defaultValue;\n"
          "}\n");
      printer->Annotate("{", "}", descriptor_);
      WriteFieldDocComment(printer, descriptor_);
      printer->Print(
          variables_,
          "$deprecation$\n"
          "public $value_type$ ${$get$capitalized_name$ValueOrThrow$}$(\n"
          "    $key_type$ key) {\n"
          "  $key_null_check$\n"
          "  java.util.Map<$boxed_key_type$, $boxed_value_type$> map =\n"
          "      internalGet$capitalized_name$();\n"
          "  if (!map.containsKey(key)) {\n"
          "    throw new java.lang.IllegalArgumentException();\n"
          "  }\n"
          "  return map.get(key);\n"
          "}\n");
      printer->Annotate("{", "}", descriptor_);
    }
  } else {
    printer->Print(
        variables_,
        "/**\n"
        " * Use {@link #get$capitalized_name$Map()} instead.\n"
        " */\n"
        "@java.lang.Deprecated\n"
        "public java.util.Map<$type_parameters$> "
        "${$get$capitalized_name$$}$() {\n"
        "  return get$capitalized_name$Map();\n"
        "}\n");
    printer->Annotate("{", "}", descriptor_);
    WriteFieldDocComment(printer, descriptor_);
    printer->Print(
        variables_,
        "$deprecation$\n"
        "public java.util.Map<$type_parameters$> "
        "${$get$capitalized_name$Map$}$() {\n"
        "  return java.util.Collections.unmodifiableMap(\n"
        "      internalGet$capitalized_name$());\n"
        "}\n");
    printer->Annotate("{", "}", descriptor_);
    WriteFieldDocComment(printer, descriptor_);
    printer->Print(
        variables_,
        "$deprecation$\n"
        "public $value_type$ ${$get$capitalized_name$OrDefault$}$(\n"
        "    $key_type$ key,\n"
        "    $value_type$ defaultValue) {\n"
        "  $key_null_check$\n"
        "  java.util.Map<$type_parameters$> map =\n"
        "      internalGet$capitalized_name$();\n"
        "  return map.containsKey(key) ? map.get(key) : defaultValue;\n"
        "}\n");
    printer->Annotate("{", "}", descriptor_);
    WriteFieldDocComment(printer, descriptor_);
    printer->Print(
        variables_,
        "$deprecation$\n"
        "public $value_type$ ${$get$capitalized_name$OrThrow$}$(\n"
        "    $key_type$ key) {\n"
        "  $key_null_check$\n"
        "  java.util.Map<$type_parameters$> map =\n"
        "      internalGet$capitalized_name$();\n"
        "  if (!map.containsKey(key)) {\n"
        "    throw new java.lang.IllegalArgumentException();\n"
        "  }\n"
        "  return map.get(key);\n"
        "}\n");
    printer->Annotate("{", "}", descriptor_);
  }

  // Generate private setters for the builder to proxy into.
  if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
    WriteFieldDocComment(printer, descriptor_);
    printer->Print(
        variables_,
        "private java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
        "getMutable$capitalized_name$Map() {\n"
        "  return new com.google.protobuf.Internal.MapAdapter<\n"
        "      $boxed_key_type$, $value_enum_type$, java.lang.Integer>(\n"
        "          internalGetMutable$capitalized_name$(),\n"
        "          $name$ValueConverter);\n"
        "}\n");
    if (SupportUnknownEnumValue(descriptor_->file())) {
      WriteFieldDocComment(printer, descriptor_);
      printer->Print(
          variables_,
          "private java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
          "getMutable$capitalized_name$ValueMap() {\n"
          "  return internalGetMutable$capitalized_name$();\n"
          "}\n");
    }
  } else {
    WriteFieldDocComment(printer, descriptor_);
    printer->Print(
        variables_,
        "private java.util.Map<$type_parameters$>\n"
        "getMutable$capitalized_name$Map() {\n"
        "  return internalGetMutable$capitalized_name$();\n"
        "}\n");
  }
}

void ImmutableMapFieldLiteGenerator::
GenerateBuilderMembers(io::Printer* printer) const {
  printer->Print(
      variables_,
      "$deprecation$\n"
      "public int ${$get$capitalized_name$Count$}$() {\n"
      "  return instance.get$capitalized_name$Map().size();\n"
      "}\n");
  printer->Annotate("{", "}", descriptor_);
  WriteFieldDocComment(printer, descriptor_);
  printer->Print(
      variables_,
      "$deprecation$\n"
      "public boolean ${$contains$capitalized_name$$}$(\n"
      "    $key_type$ key) {\n"
      "  $key_null_check$\n"
      "  return instance.get$capitalized_name$Map().containsKey(key);\n"
      "}\n");
  printer->Annotate("{", "}", descriptor_);
  printer->Print(
      variables_,
      "$deprecation$\n"
      "public Builder ${$clear$capitalized_name$$}$() {\n"
      "  copyOnWrite();\n"
      "  instance.getMutable$capitalized_name$Map().clear();\n"
      "  return this;\n"
      "}\n");
  printer->Annotate("{", "}", descriptor_);
  WriteFieldDocComment(printer, descriptor_);
  printer->Print(
      variables_,
      "$deprecation$\n"
      "public Builder ${$remove$capitalized_name$$}$(\n"
      "    $key_type$ key) {\n"
      "  $key_null_check$\n"
      "  copyOnWrite();\n"
      "  instance.getMutable$capitalized_name$Map().remove(key);\n"
      "  return this;\n"
      "}\n");
  printer->Annotate("{", "}", descriptor_);
  if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
    printer->Print(
        variables_,
        "/**\n"
        " * Use {@link #get$capitalized_name$Map()} instead.\n"
        " */\n"
        "@java.lang.Deprecated\n"
        "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
        "${$get$capitalized_name$$}$() {\n"
        "  return get$capitalized_name$Map();\n"
        "}\n");
    printer->Annotate("{", "}", descriptor_);
    WriteFieldDocComment(printer, descriptor_);
    printer->Print(
        variables_,
        "$deprecation$\n"
        "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
        "${$get$capitalized_name$Map$}$() {\n"
        "  return java.util.Collections.unmodifiableMap(\n"
        "      instance.get$capitalized_name$Map());\n"
        "}\n");
    printer->Annotate("{", "}", descriptor_);
    WriteFieldDocComment(printer, descriptor_);
    printer->Print(
        variables_,
        "$deprecation$\n"
        "public $value_enum_type$ ${$get$capitalized_name$OrDefault$}$(\n"
        "    $key_type$ key,\n"
        "    $value_enum_type$ defaultValue) {\n"
        "  $key_null_check$\n"
        "  java.util.Map<$boxed_key_type$, $value_enum_type$> map =\n"
        "      instance.get$capitalized_name$Map();\n"
        "  return map.containsKey(key)\n"
        "         ? map.get(key)\n"
        "         : defaultValue;\n"
        "}\n");
    printer->Annotate("{", "}", descriptor_);
    WriteFieldDocComment(printer, descriptor_);
    printer->Print(
        variables_,
        "$deprecation$\n"
        "public $value_enum_type$ ${$get$capitalized_name$OrThrow$}$(\n"
        "    $key_type$ key) {\n"
        "  $key_null_check$\n"
        "  java.util.Map<$boxed_key_type$, $value_enum_type$> map =\n"
        "      instance.get$capitalized_name$Map();\n"
        "  if (!map.containsKey(key)) {\n"
        "    throw new java.lang.IllegalArgumentException();\n"
        "  }\n"
        "  return map.get(key);\n"
        "}\n");
    printer->Annotate("{", "}", descriptor_);
    WriteFieldDocComment(printer, descriptor_);
    printer->Print(
        variables_,
        "$deprecation$public Builder ${$put$capitalized_name$$}$(\n"
        "    $key_type$ key,\n"
        "    $value_enum_type$ value) {\n"
        "  $key_null_check$\n"
        "  $value_null_check$\n"
        "  copyOnWrite();\n"
        "  instance.getMutable$capitalized_name$Map().put(key, value);\n"
        "  return this;\n"
        "}\n");
    printer->Annotate("{", "}", descriptor_);
    WriteFieldDocComment(printer, descriptor_);
    printer->Print(
        variables_,
        "$deprecation$public Builder ${$putAll$capitalized_name$$}$(\n"
        "    java.util.Map<$boxed_key_type$, $value_enum_type$> values) {\n"
        "  copyOnWrite();\n"
        "  instance.getMutable$capitalized_name$Map().putAll(values);\n"
        "  return this;\n"
        "}\n");
    printer->Annotate("{", "}", descriptor_);
    if (SupportUnknownEnumValue(descriptor_->file())) {
      printer->Print(
          variables_,
          "/**\n"
          " * Use {@link #get$capitalized_name$ValueMap()} instead.\n"
          " */\n"
          "@java.lang.Deprecated\n"
          "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
          "${$get$capitalized_name$Value$}$() {\n"
          "  return get$capitalized_name$ValueMap();\n"
          "}\n");
      printer->Annotate("{", "}", descriptor_);
      WriteFieldDocComment(printer, descriptor_);
      printer->Print(
          variables_,
          "$deprecation$\n"
          "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
          "${$get$capitalized_name$ValueMap$}$() {\n"
          "  return java.util.Collections.unmodifiableMap(\n"
          "      instance.get$capitalized_name$ValueMap());\n"
          "}\n");
      printer->Annotate("{", "}", descriptor_);
      WriteFieldDocComment(printer, descriptor_);
      printer->Print(
          variables_,
          "$deprecation$\n"
          "public $value_type$ ${$get$capitalized_name$ValueOrDefault$}$(\n"
          "    $key_type$ key,\n"
          "    $value_type$ defaultValue) {\n"
          "  $key_null_check$\n"
          "  java.util.Map<$boxed_key_type$, $boxed_value_type$> map =\n"
          "      instance.get$capitalized_name$ValueMap();\n"
          "  return map.containsKey(key) ? map.get(key) : defaultValue;\n"
          "}\n");
      printer->Annotate("{", "}", descriptor_);
      WriteFieldDocComment(printer, descriptor_);
      printer->Print(
          variables_,
          "$deprecation$\n"
          "public $value_type$ ${$get$capitalized_name$ValueOrThrow$}$(\n"
          "    $key_type$ key) {\n"
          "  $key_null_check$\n"
          "  java.util.Map<$boxed_key_type$, $boxed_value_type$> map =\n"
          "      instance.get$capitalized_name$ValueMap();\n"
          "  if (!map.containsKey(key)) {\n"
          "    throw new java.lang.IllegalArgumentException();\n"
          "  }\n"
          "  return map.get(key);\n"
          "}\n");
      printer->Annotate("{", "}", descriptor_);
      WriteFieldDocComment(printer, descriptor_);
      printer->Print(
          variables_,
          "$deprecation$public Builder ${$put$capitalized_name$Value$}$(\n"
          "    $key_type$ key,\n"
          "    $value_type$ value) {\n"
          "  $key_null_check$\n"
          "  copyOnWrite();\n"
          "  instance.getMutable$capitalized_name$ValueMap().put(key, value);\n"
          "  return this;\n"
          "}\n");
      printer->Annotate("{", "}", descriptor_);
      WriteFieldDocComment(printer, descriptor_);
      printer->Print(
          variables_,
          "$deprecation$public Builder ${$putAll$capitalized_name$Value$}$(\n"
          "    java.util.Map<$boxed_key_type$, $boxed_value_type$> values) {\n"
          "  copyOnWrite();\n"
          "  instance.getMutable$capitalized_name$ValueMap().putAll(values);\n"
          "  return this;\n"
          "}\n");
      printer->Annotate("{", "}", descriptor_);
    }
  } else {
    printer->Print(
        variables_,
        "/**\n"
        " * Use {@link #get$capitalized_name$Map()} instead.\n"
        " */\n"
        "@java.lang.Deprecated\n"
        "public java.util.Map<$type_parameters$> "
        "${$get$capitalized_name$$}$() {\n"
        "  return get$capitalized_name$Map();\n"
        "}\n");
    printer->Annotate("{", "}", descriptor_);
    WriteFieldDocComment(printer, descriptor_);
    printer->Print(
        variables_,
        "$deprecation$"
        "public java.util.Map<$type_parameters$> "
        "${$get$capitalized_name$Map$}$() {\n"
        "  return java.util.Collections.unmodifiableMap(\n"
        "      instance.get$capitalized_name$Map());\n"
        "}\n");
    printer->Annotate("{", "}", descriptor_);
    WriteFieldDocComment(printer, descriptor_);
    printer->Print(
        variables_,
        "$deprecation$\n"
        "public $value_type$ ${$get$capitalized_name$OrDefault$}$(\n"
        "    $key_type$ key,\n"
        "    $value_type$ defaultValue) {\n"
        "  $key_null_check$\n"
        "  java.util.Map<$type_parameters$> map =\n"
        "      instance.get$capitalized_name$Map();\n"
        "  return map.containsKey(key) ? map.get(key) : defaultValue;\n"
        "}\n");
    printer->Annotate("{", "}", descriptor_);
    WriteFieldDocComment(printer, descriptor_);
    printer->Print(
        variables_,
        "$deprecation$\n"
        "public $value_type$ ${$get$capitalized_name$OrThrow$}$(\n"
        "    $key_type$ key) {\n"
        "  $key_null_check$\n"
        "  java.util.Map<$type_parameters$> map =\n"
        "      instance.get$capitalized_name$Map();\n"
        "  if (!map.containsKey(key)) {\n"
        "    throw new java.lang.IllegalArgumentException();\n"
        "  }\n"
        "  return map.get(key);\n"
        "}\n");
    printer->Annotate("{", "}", descriptor_);
    WriteFieldDocComment(printer, descriptor_);
    printer->Print(
        variables_,
        "$deprecation$"
        "public Builder ${$put$capitalized_name$$}$(\n"
        "    $key_type$ key,\n"
        "    $value_type$ value) {\n"
        "  $key_null_check$\n"
        "  $value_null_check$\n"
        "  copyOnWrite();\n"
        "  instance.getMutable$capitalized_name$Map().put(key, value);\n"
        "  return this;\n"
        "}\n");
    printer->Annotate("{", "}", descriptor_);
    WriteFieldDocComment(printer, descriptor_);
    printer->Print(
        variables_,
        "$deprecation$"
        "public Builder ${$putAll$capitalized_name$$}$(\n"
        "    java.util.Map<$type_parameters$> values) {\n"
        "  copyOnWrite();\n"
        "  instance.getMutable$capitalized_name$Map().putAll(values);\n"
        "  return this;\n"
        "}\n");
    printer->Annotate("{", "}", descriptor_);
  }
}

void ImmutableMapFieldLiteGenerator::
GenerateFieldBuilderInitializationCode(io::Printer* printer)  const {
  // Nothing to initialize.
}

void ImmutableMapFieldLiteGenerator::
GenerateInitializationCode(io::Printer* printer) const {
  // Nothing to initialize.
}

void ImmutableMapFieldLiteGenerator::
GenerateVisitCode(io::Printer* printer) const {
  printer->Print(
      variables_,
      "$name$_ = visitor.visitMap(\n"
      "    $name$_, other.internalGet$capitalized_name$());\n");
}

void ImmutableMapFieldLiteGenerator::
GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const {
  printer->Print(variables_,
    "$name$_.makeImmutable();\n");
}

void ImmutableMapFieldLiteGenerator::
GenerateParsingCode(io::Printer* printer) const {
  printer->Print(
      variables_,
      "if (!$name$_.isMutable()) {\n"
      "  $name$_ = $name$_.mutableCopy();\n"
      "}\n");
  if (!SupportUnknownEnumValue(descriptor_->file()) &&
      GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
    printer->Print(
        variables_,
        "com.google.protobuf.ByteString bytes = input.readBytes();\n"
        "java.util.Map.Entry<$type_parameters$> $name$__ =\n"
        "    $default_entry$.parseEntry(bytes, extensionRegistry);\n");
    printer->Print(
        variables_,
        "if ($value_enum_type$.forNumber($name$__.getValue()) == null) {\n"
        "  super.mergeLengthDelimitedField($number$, bytes);\n"
        "} else {\n"
        "  $name$_.put($name$__);\n"
        "}\n");
  } else {
    printer->Print(
        variables_,
        "$default_entry$.parseInto($name$_, input, extensionRegistry);");
  }
}

void ImmutableMapFieldLiteGenerator::
GenerateParsingDoneCode(io::Printer* printer) const {
  // Nothing to do here.
}

void ImmutableMapFieldLiteGenerator::
GenerateSerializationCode(io::Printer* printer) const {
  printer->Print(
      variables_,
      "for (java.util.Map.Entry<$type_parameters$> entry\n"
      "     : internalGet$capitalized_name$().entrySet()) {\n"
      "  $default_entry$.serializeTo(\n"
      "      output, $number$, entry.getKey(), entry.getValue());\n"
      "}\n");
}

void ImmutableMapFieldLiteGenerator::
GenerateSerializedSizeCode(io::Printer* printer) const {
  printer->Print(
      variables_,
      "for (java.util.Map.Entry<$type_parameters$> entry\n"
      "     : internalGet$capitalized_name$().entrySet()) {\n"
      "  size += $default_entry$.computeMessageSize(\n"
      "    $number$, entry.getKey(), entry.getValue());\n"
      "}\n");
}

void ImmutableMapFieldLiteGenerator::
GenerateEqualsCode(io::Printer* printer) const {
  printer->Print(
      variables_,
      "result = result && internalGet$capitalized_name$().equals(\n"
      "    other.internalGet$capitalized_name$());\n");
}

void ImmutableMapFieldLiteGenerator::
GenerateHashCode(io::Printer* printer) const {
  printer->Print(
      variables_,
      "if (!internalGet$capitalized_name$().isEmpty()) {\n"
      "  hash = (37 * hash) + $constant_name$;\n"
      "  hash = (53 * hash) + internalGet$capitalized_name$().hashCode();\n"
      "}\n");
}

string ImmutableMapFieldLiteGenerator::GetBoxedType() const {
  return name_resolver_->GetImmutableClassName(descriptor_->message_type());
}

}  // namespace java
}  // namespace compiler
}  // namespace protobuf
}  // namespace google


text:
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.  All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

// Author: kenton@google.com (Kenton Varda)
//  Based on original Protocol Buffers design by
//  Sanjay Ghemawat, Jeff Dean, and others.

#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_FILE_H__
#define GOOGLE_PROTOBUF_COMPILER_JAVA_FILE_H__

#include <memory>
#ifndef _SHARED_PTR_H
#include <google/protobuf/stubs/shared_ptr.h>
#endif
#include <string>
#include <vector>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/compiler/java/java_options.h>

namespace google {
namespace protobuf {
  class FileDescriptor;          // descriptor.h
  namespace io {
    class Printer;               // printer.h
  }
  namespace compiler {
    class GeneratorContext;      // code_generator.h
    namespace java {
      class Context;             // context.h
      class MessageGenerator;    // message.h
      class GeneratorFactory;    // generator_factory.h
      class ExtensionGenerator;  // extension.h
      class ClassNameResolver;   // name_resolver.h
    }
  }
}

namespace protobuf {
namespace compiler {
namespace java {

class FileGenerator {
 public:
  FileGenerator(const FileDescriptor* file, const Options& options,
                bool immutable_api = true);
  ~FileGenerator();

  // Checks for problems that would otherwise lead to cryptic compile errors.
  // Returns true if there are no problems, or writes an error description to
  // the given string and returns false otherwise.
  bool Validate(string* error);

  void Generate(io::Printer* printer);

  // If we aren't putting everything into one file, this will write all the
  // files other than the outer file (i.e. one for each message, enum, and
  // service type).
  void GenerateSiblings(const string& package_dir,
                        GeneratorContext* generator_context,
                        std::vector<string>* file_list,
                        std::vector<string>* annotation_list);

  const string& java_package() { return java_package_; }
  const string& classname()    { return classname_;    }

 private:
  void GenerateDescriptorInitializationCodeForImmutable(io::Printer* printer);
  void GenerateDescriptorInitializationCodeForMutable(io::Printer* printer);

  bool ShouldIncludeDependency(const FileDescriptor* descriptor,
                               bool immutable_api_);

  const FileDescriptor* file_;
  string java_package_;
  string classname_;

  google::protobuf::scoped_array<google::protobuf::scoped_ptr<MessageGenerator> > message_generators_;
  google::protobuf::scoped_array<google::protobuf::scoped_ptr<ExtensionGenerator> > extension_generators_;
  google::protobuf::scoped_ptr<GeneratorFactory> generator_factory_;
  google::protobuf::scoped_ptr<Context> context_;
  ClassNameResolver* name_resolver_;
  const Options options_;
  bool immutable_api_;

  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileGenerator);
};

}  // namespace java
}  // namespace compiler
}  // namespace protobuf

}  // namespace google
#endif  // GOOGLE_PROTOBUF_COMPILER_JAVA_FILE_H__

mime_type: text/plain


text:
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.  All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

// Author: kenton@google.com (Kenton Varda)
//  Based on original Protocol Buffers design by
//  Sanjay Ghemawat, Jeff Dean, and others.

#include <google/protobuf/compiler/java/java_doc_comment.h>

#include <vector>

#include <google/protobuf/io/printer.h>
#include <google/protobuf/stubs/strutil.h>

namespace google {
namespace protobuf {
namespace compiler {
namespace java {

string EscapeJavadoc(const string& input) {
  string result;
  result.reserve(input.size() * 2);

  char prev = '*';

  for (string::size_type i = 0; i < input.size(); i++) {
    char c = input[i];
    switch (c) {
      case '*':
        // Avoid "/*".
        if (prev == '/') {
          result.append("*");
        } else {
          result.push_back(c);
        }
        break;
      case '/':
        // Avoid "*/".
        if (prev == '*') {
          result.append("/");
        } else {
          result.push_back(c);
        }
        break;
      case '@':
        // '@' starts javadoc tags including the @deprecated tag, which will
        // cause a compile-time error if inserted before a declaration that
        // does not have a corresponding @Deprecated annotation.
        result.append("@");
        break;
      case '<':
        // Avoid interpretation as HTML.
        result.append("<");
        break;
      case '>':
        // Avoid interpretation as HTML.
        result.append(">");
        break;
      case '&':
        // Avoid interpretation as HTML.
        result.append("&");
        break;
      case '\\':
        // Java interprets Unicode escape sequences anywhere!
        result.append("\");
        break;
      default:
        result.push_back(c);
        break;
    }

    prev = c;
  }

  return result;
}

static void WriteDocCommentBodyForLocation(
    io::Printer* printer, const SourceLocation& location) {
  string comments = location.leading_comments.empty() ?
      location.trailing_comments : location.leading_comments;
  if (!comments.empty()) {
    // TODO(kenton):  Ideally we should parse the comment text as Markdown and
    //   write it back as HTML, but this requires a Markdown parser.  For now
    //   we just use
 to get fixed-width text formatting.

    // If the comment itself contains block comment start or end markers,
    // HTML-escape them so that they don't accidentally close the doc comment.
    comments = EscapeJavadoc(comments);

    std::vector<string> lines = Split(comments, "\n");
    while (!lines.empty() && lines.back().empty()) {
      lines.pop_back();
    }

    printer->Print(" *
\n");
    for (int i = 0; i < lines.size(); i++) {
      // Most lines should start with a space.  Watch out for lines that start
      // with a /, since putting that right after the leading asterisk will
      // close the comment.
      if (!lines[i].empty() && lines[i][0] == '/') {
        printer->Print(" * $line$\n", "line", lines[i]);
      } else {
        printer->Print(" *$line$\n", "line", lines[i]);
      }
    }
    printer->Print(
        " *
\n"
        " *\n");
  }
}

template <typename DescriptorType>
static void WriteDocCommentBody(
    io::Printer* printer, const DescriptorType* descriptor) {
  SourceLocation location;
  if (descriptor->GetSourceLocation(&location)) {
    WriteDocCommentBodyForLocation(printer, location);
  }
}

static string FirstLineOf(const string& value) {
  string result = value;

  string::size_type pos = result.find_first_of('\n');
  if (pos != string::npos) {
    result.erase(pos);
  }

  // If line ends in an opening brace, make it "{ ... }" so it looks nice.
  if (!result.empty() && result[result.size() - 1] == '{') {
    result.append(" ... }");
  }

  return result;
}

void WriteMessageDocComment(io::Printer* printer, const Descriptor* message) {
  printer->Print("/**\n");
  WriteDocCommentBody(printer, message);
  printer->Print(
    " * Protobuf type {@code $fullname$}\n"
    " */\n",
    "fullname", EscapeJavadoc(message->full_name()));
}

void WriteFieldDocComment(io::Printer* printer, const FieldDescriptor* field) {
  // In theory we should have slightly different comments for setters, getters,
  // etc., but in practice everyone already knows the difference between these
  // so it's redundant information.

  // We start the comment with the main body based on the comments from the
  // .proto file (if present). We then end with the field declaration, e.g.:
  //   optional string foo = 5;
  // If the field is a group, the debug string might end with {.
  printer->Print("/**\n");
  WriteDocCommentBody(printer, field);
  printer->Print(
    " * $def$\n",
    "def", EscapeJavadoc(FirstLineOf(field->DebugString())));
  printer->Print(" */\n");
}

void WriteEnumDocComment(io::Printer* printer, const EnumDescriptor* enum_) {
  printer->Print("/**\n");
  WriteDocCommentBody(printer, enum_);
  printer->Print(
    " * Protobuf enum {@code $fullname$}\n"
    " */\n",
    "fullname", EscapeJavadoc(enum_->full_name()));
}

void WriteEnumValueDocComment(io::Printer* printer,
                              const EnumValueDescriptor* value) {
  printer->Print("/**\n");
  WriteDocCommentBody(printer, value);
  printer->Print(
    " * $def$\n"
    " */\n",
    "def", EscapeJavadoc(FirstLineOf(value->DebugString())));
}

void WriteServiceDocComment(io::Printer* printer,
                            const ServiceDescriptor* service) {
  printer->Print("/**\n");
  WriteDocCommentBody(printer, service);
  printer->Print(
    " * Protobuf service {@code $fullname$}\n"
    " */\n",
    "fullname", EscapeJavadoc(service->full_name()));
}

void WriteMethodDocComment(io::Printer* printer,
                           const MethodDescriptor* method) {
  printer->Print("/**\n");
  WriteDocCommentBody(printer, method);
  printer->Print(
    " * $def$\n"
    " */\n",
    "def", EscapeJavadoc(FirstLineOf(method->DebugString())));
}

}  // namespace java
}  // namespace compiler
}  // namespace protobuf
}  // namespace google


text:
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.  All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

// Author: niwasaki@google.com (Naoki Iwasaki)
//  Based on original Protocol Buffers design by
//  Sanjay Ghemawat, Jeff Dean, and others.

#include <google/protobuf/compiler/java/java_context.h>
#include <google/protobuf/compiler/java/java_lazy_message_field.h>
#include <google/protobuf/compiler/java/java_doc_comment.h>
#include <google/protobuf/compiler/java/java_helpers.h>
#include <google/protobuf/io/printer.h>

namespace google {
namespace protobuf {
namespace compiler {
namespace java {

ImmutableLazyMessageFieldGenerator::
ImmutableLazyMessageFieldGenerator(
    const FieldDescriptor* descriptor,
    int messageBitIndex,
    int builderBitIndex,
    Context* context)
    : ImmutableMessageFieldGenerator(
          descriptor, messageBitIndex, builderBitIndex, context) {
}

ImmutableLazyMessageFieldGenerator::~ImmutableLazyMessageFieldGenerator() {}

void ImmutableLazyMessageFieldGenerator::
GenerateMembers(io::Printer* printer) const {
  printer->Print(variables_,
    "private com.google.protobuf.LazyFieldLite $name$_ =\n"
    "    new com.google.protobuf.LazyFieldLite();\n");

  PrintExtraFieldInfo(variables_, printer);
  WriteFieldDocComment(printer, descriptor_);
  printer->Print(variables_,
    "$deprecation$public boolean has$capitalized_name$() {\n"
    "  return $get_has_field_bit_message$;\n"
    "}\n");
  WriteFieldDocComment(printer, descriptor_);

  printer->Print(variables_,
    "$deprecation$public $type$ get$capitalized_name$() {\n"
    "  return ($type$) $name$_.getValue($type$.getDefaultInstance());\n"
    "}\n");
  WriteFieldDocComment(printer, descriptor_);
  printer->Print(variables_,
    "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n"
    "  return $name$_;\n"
    "}\n");
}

void ImmutableLazyMessageFieldGenerator::
GenerateBuilderMembers(io::Printer* printer) const {
  // When using nested-builders, the code initially works just like the
  // non-nested builder case. It only creates a nested builder lazily on
  // demand and then forever delegates to it after creation.

  printer->Print(variables_,
    "private com.google.protobuf.LazyFieldLite $name$_ =\n"
    "    new com.google.protobuf.LazyFieldLite();\n");

  printer->Print(variables_,
    // If this builder is non-null, it is used and the other fields are
    // ignored.
    "private com.google.protobuf.SingleFieldBuilder$ver$<\n"
    "    $type$, $type$.Builder, $type$OrBuilder> $name$Builder_;"
    "\n");

  // The comments above the methods below are based on a hypothetical
  // field of type "Field" called "Field".

  // boolean hasField()
  WriteFieldDocComment(printer, descriptor_);
  printer->Print(variables_,
    "$deprecation$public boolean has$capitalized_name$() {\n"
    "  return $get_has_field_bit_builder$;\n"
    "}\n");

    printer->Print(variables_,
      "$deprecation$public $type$ get$capitalized_name$() {\n"
      "  return ($type$) $name$_.getValue($type$.getDefaultInstance());\n"
      "}\n");

  // Field.Builder setField(Field value)
  WriteFieldDocComment(printer, descriptor_);
  PrintNestedBuilderFunction(printer,
    "$deprecation$public Builder set$capitalized_name$($type$ value)",

    "if (value == null) {\n"
    "  throw new NullPointerException();\n"
    "}\n"
    "$name$_.setValue(value);\n"
    "$on_changed$\n",

     NULL,  // Lazy fields are supported only for lite-runtime.

    "$set_has_field_bit_builder$;\n"
    "return this;\n");

  // Field.Builder setField(Field.Builder builderForValue)
  WriteFieldDocComment(printer, descriptor_);
  PrintNestedBuilderFunction(printer,
    "$deprecation$public Builder set$capitalized_name$(\n"
    "    $type$.Builder builderForValue)",

    "$name$_.setValue(builderForValue.build());\n"
    "$on_changed$\n",

    NULL,

    "$set_has_field_bit_builder$;\n"
    "return this;\n");

  // Field.Builder mergeField(Field value)
  WriteFieldDocComment(printer, descriptor_);
  PrintNestedBuilderFunction(printer,
    "$deprecation$public Builder merge$capitalized_name$($type$ value)",

    "if ($get_has_field_bit_builder$ &&\n"
    "    !$name$_.containsDefaultInstance()) {\n"
    "  $name$_.setValue(\n"
    "    $type$.newBuilder(\n"
    "        get$capitalized_name$()).mergeFrom(value).buildPartial());\n"
    "} else {\n"
    "  $name$_.setValue(value);\n"
    "}\n"
    "$on_changed$\n",

    NULL,

    "$set_has_field_bit_builder$;\n"
    "return this;\n");

  // Field.Builder clearField()
  WriteFieldDocComment(printer, descriptor_);
  PrintNestedBuilderFunction(printer,
    "$deprecation$public Builder clear$capitalized_name$()",

    "$name$_.clear();\n"
    "$on_changed$\n",

    NULL,

    "$clear_has_field_bit_builder$;\n"
    "return this;\n");

  WriteFieldDocComment(printer, descriptor_);
  printer->Print(variables_,
    "$deprecation$public $type$.Builder get$capitalized_name$Builder() {\n"
    "  $set_has_field_bit_builder$;\n"
    "  $on_changed$\n"
    "  return get$capitalized_name$FieldBuilder().getBuilder();\n"
    "}\n");
  WriteFieldDocComment(printer, descriptor_);
  printer->Print(variables_,
    "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n"
    "  if ($name$Builder_ != null) {\n"
    "    return $name$Builder_.getMessageOrBuilder();\n"
    "  } else {\n"
    "    return $name$_;\n"
    "  }\n"
    "}\n");
  WriteFieldDocComment(printer, descriptor_);
  printer->Print(variables_,
    "private com.google.protobuf.SingleFieldBuilder$ver$<\n"
    "    $type$, $type$.Builder, $type$OrBuilder> \n"
    "    get$capitalized_name$FieldBuilder() {\n"
    "  if ($name$Builder_ == null) {\n"
    "    $name$Builder_ = new com.google.protobuf.SingleFieldBuilder$ver$<\n"
    "        $type$, $type$.Builder, $type$OrBuilder>(\n"
    "            $name$_,\n"
    "            getParentForChildren(),\n"
    "            isClean());\n"
    "    $name$_ = null;\n"
    "  }\n"
    "  return $name$Builder_;\n"
    "}\n");
}

void ImmutableLazyMessageFieldGenerator::
GenerateInitializationCode(io::Printer* printer) const {
  printer->Print(variables_, "$name$_.clear();\n");
}

void ImmutableLazyMessageFieldGenerator::
GenerateBuilderClearCode(io::Printer* printer) const {
  printer->Print(variables_, "$name$_.clear();\n");
  printer->Print(variables_, "$clear_has_field_bit_builder$;\n");
}

void ImmutableLazyMessageFieldGenerator::
GenerateMergingCode(io::Printer* printer) const {
  printer->Print(variables_,
    "if (other.has$capitalized_name$()) {\n"
    "  $name$_.merge(other.$name$_);\n"
    "  $set_has_field_bit_builder$;\n"
    "}\n");
}

void ImmutableLazyMessageFieldGenerator::
GenerateBuildingCode(io::Printer* printer) const {
  printer->Print(variables_,
      "if ($get_has_field_bit_from_local$) {\n"
      "  $set_has_field_bit_to_local$;\n"
      "}\n");

  printer->Print(variables_,
      "result.$name$_.set(\n"
      "    $name$_);\n");
}

void ImmutableLazyMessageFieldGenerator::
GenerateParsingCode(io::Printer* printer) const {
  printer->Print(variables_,
    "$name$_.setByteString(input.readBytes(), extensionRegistry);\n");
  printer->Print(variables_,
    "$set_has_field_bit_message$;\n");
}

void ImmutableLazyMessageFieldGenerator::
GenerateSerializationCode(io::Printer* printer) const {
  // Do not de-serialize lazy fields.
  printer->Print(variables_,
    "if ($get_has_field_bit_message$) {\n"
    "  output.writeBytes($number$, $name$_.toByteString());\n"
    "}\n");
}

void ImmutableLazyMessageFieldGenerator::
GenerateSerializedSizeCode(io::Printer* printer) const {
  printer->Print(variables_,
    "if ($get_has_field_bit_message$) {\n"
    "  size += com.google.protobuf.CodedOutputStream\n"
    "    .computeLazyFieldSize($number$, $name$_);\n"
    "}\n");
}

// ===================================================================

ImmutableLazyMessageOneofFieldGenerator::
ImmutableLazyMessageOneofFieldGenerator(const FieldDescriptor* descriptor,
                                        int messageBitIndex,
                                        int builderBitIndex,
                                        Context* context)
    : ImmutableLazyMessageFieldGenerator(
          descriptor, messageBitIndex, builderBitIndex, context) {
  const OneofGeneratorInfo* info =
      context->GetOneofGeneratorInfo(descriptor->containing_oneof());
  SetCommonOneofVariables(descriptor, info, &variables_);
  variables_["lazy_type"] = "com.google.protobuf.LazyFieldLite";
}

ImmutableLazyMessageOneofFieldGenerator::
~ImmutableLazyMessageOneofFieldGenerator() {}

void ImmutableLazyMessageOneofFieldGenerator::
GenerateMembers(io::Printer* printer) const {
  PrintExtraFieldInfo(variables_, printer);
  WriteFieldDocComment(printer, descriptor_);

  printer->Print(variables_,
    "$deprecation$public boolean has$capitalized_name$() {\n"
    "  return $has_oneof_case_message$;\n"
    "}\n");
  WriteFieldDocComment(printer, descriptor_);

  printer->Print(variables_,
    "$deprecation$public $type$ get$capitalized_name$() {\n"
    "  if ($has_oneof_case_message$) {\n"
    "    return ($type$) (($lazy_type$) $oneof_name$_).getValue(\n"
    "        $type$.getDefaultInstance());\n"
    "  }\n"
    "  return $type$.getDefaultInstance();\n"
    "}\n");
}

void ImmutableLazyMessageOneofFieldGenerator::
GenerateBuilderMembers(io::Printer* printer) const {
  // boolean hasField()
  WriteFieldDocComment(printer, descriptor_);
  printer->Print(variables_,
    "$deprecation$public boolean has$capitalized_name$() {\n"
    "  return $has_oneof_case_message$;\n"
    "}\n");

  printer->Print(variables_,
    "$deprecation$public $type$ get$capitalized_name$() {\n"
    "  if ($has_oneof_case_message$) {\n"
    "    return ($type$) (($lazy_type$) $oneof_name$_).getValue(\n"
    "        $type$.getDefaultInstance());\n"
    "  }\n"
    "  return $type$.getDefaultInstance();\n"
    "}\n");

  // Field.Builder setField(Field value)
  WriteFieldDocComment(printer, descriptor_);
  PrintNestedBuilderFunction(printer,
    "$deprecation$public Builder set$capitalized_name$($type$ value)",

    "if (value == null) {\n"
    "  throw new NullPointerException();\n"
    "}\n"
    "if (!($has_oneof_case_message$)) {\n"
    "  $oneof_name$_ = new $lazy_type$();\n"
    "  $set_oneof_case_message$;\n"
    "}\n"
    "(($lazy_type$) $oneof_name$_).setValue(value);\n"
    "$on_changed$\n",

     NULL,  // Lazy fields are supported only for lite-runtime.

    "return this;\n");

  // Field.Builder setField(Field.Builder builderForValue)
  WriteFieldDocComment(printer, descriptor_);
  PrintNestedBuilderFunction(printer,
    "$deprecation$public Builder set$capitalized_name$(\n"
    "    $type$.Builder builderForValue)",

    "if (!($has_oneof_case_message$)) {\n"
    "  $oneof_name$_ = new $lazy_type$();\n"
    "  $set_oneof_case_message$;\n"
    "}\n"
    "(($lazy_type$) $oneof_name$_).setValue(builderForValue.build());\n"
    "$on_changed$\n",

    NULL,

    "return this;\n");

  // Field.Builder mergeField(Field value)
  WriteFieldDocComment(printer, descriptor_);
  PrintNestedBuilderFunction(printer,
    "$deprecation$public Builder merge$capitalized_name$($type$ value)",

    "if ($has_oneof_case_message$ &&\n"
    "    !(($lazy_type$) $oneof_name$_).containsDefaultInstance()) {\n"
    "  (($lazy_type$) $oneof_name$_).setValue(\n"
    "    $type$.newBuilder(\n"
    "        get$capitalized_name$()).mergeFrom(value).buildPartial());\n"
    "} else {\n"
    "  if (!($has_oneof_case_message$)) {\n"
    "    $oneof_name$_ = new $lazy_type$();\n"
    "    $set_oneof_case_message$;\n"
    "  }\n"
    "  (($lazy_type$) $oneof_name$_).setValue(value);\n"
    "}\n"
    "$on_changed$\n",

    NULL,

    "return this;\n");

  // Field.Builder clearField()
  WriteFieldDocComment(printer, descriptor_);
  PrintNestedBuilderFunction(printer,
    "$deprecation$public Builder clear$capitalized_name$()",

    "if ($has_oneof_case_message$) {\n"
    "  $clear_oneof_case_message$;\n"
    "  $oneof_name$_ = null;\n"
    "  $on_changed$\n"
    "}\n",

    NULL,

    "return this;\n");
}

void ImmutableLazyMessageOneofFieldGenerator::
GenerateMergingCode(io::Printer* printer) const {
  printer->Print(variables_,
    "if (!($has_oneof_case_message$)) {\n"
    "  $oneof_name$_ = new $lazy_type$();\n"
    "}\n"
    "(($lazy_type$) $oneof_name$_).merge(\n"
    "    ($lazy_type$) other.$oneof_name$_);\n"
    "$set_oneof_case_message$;\n");
}

void ImmutableLazyMessageOneofFieldGenerator::
GenerateBuildingCode(io::Printer* printer) const {
  printer->Print(variables_,
                 "if ($has_oneof_case_message$) {\n");
  printer->Indent();

  printer->Print(variables_,
      "result.$oneof_name$_ = new $lazy_type$();\n"
      "(($lazy_type$) result.$oneof_name$_).set(\n"
      "    (($lazy_type$) $oneof_name$_));\n");
  printer->Outdent();
  printer->Print("}\n");
}

void ImmutableLazyMessageOneofFieldGenerator::
GenerateParsingCode(io::Printer* printer) const {
  printer->Print(variables_,
    "if (!($has_oneof_case_message$)) {\n"
    "  $oneof_name$_ = new $lazy_type$();\n"
    "}\n"
    "(($lazy_type$) $oneof_name$_).setByteString(\n"
    "    input.readBytes(), extensionRegistry);\n"
    "$set_oneof_case_message$;\n");
}

void ImmutableLazyMessageOneofFieldGenerator::
GenerateSerializationCode(io::Printer* printer) const {
  // Do not de-serialize lazy fields.
  printer->Print(variables_,
    "if ($has_oneof_case_message$) {\n"
    "  output.writeBytes(\n"
    "      $number$, (($lazy_type$) $oneof_name$_).toByteString());\n"
    "}\n");
}

void ImmutableLazyMessageOneofFieldGenerator::
GenerateSerializedSizeCode(io::Printer* printer) const {
  printer->Print(variables_,
    "if ($has_oneof_case_message$) {\n"
    "  size += com.google.protobuf.CodedOutputStream\n"
    "    .computeLazyFieldSize($number$, ($lazy_type$) $oneof_name$_);\n"
    "}\n");
}

// ===================================================================

RepeatedImmutableLazyMessageFieldGenerator::
RepeatedImmutableLazyMessageFieldGenerator(
    const FieldDescriptor* descriptor,
    int messageBitIndex,
    int builderBitIndex,
    Context* context)
    : RepeatedImmutableMessageFieldGenerator(
          descriptor, messageBitIndex, builderBitIndex, context) {
}

RepeatedImmutableLazyMessageFieldGenerator::
~RepeatedImmutableLazyMessageFieldGenerator() {}

void RepeatedImmutableLazyMessageFieldGenerator::
GenerateMembers(io::Printer* printer) const {
  printer->Print(variables_,
    "private java.util.List<com.google.protobuf.LazyFieldLite> $name$_;\n");
  PrintExtraFieldInfo(variables_, printer);
  WriteFieldDocComment(printer, descriptor_);
  printer->Print(variables_,
    "$deprecation$public java.util.List<$type$>\n"
    "    get$capitalized_name$List() {\n"
    "  java.util.List<$type$> list =\n"
    "      new java.util.ArrayList<$type$>($name$_.size());\n"
    "  for (com.google.protobuf.LazyFieldLite lf : $name$_) {\n"
    "    list.add(($type$) lf.getValue($type$.getDefaultInstance()));\n"
    "  }\n"
    "  return list;\n"
    "}\n");
  WriteFieldDocComment(printer, descriptor_);
  printer->Print(variables_,
    "$deprecation$public java.util.List<? extends $type$OrBuilder>\n"
    "    get$capitalized_name$OrBuilderList() {\n"
    "  return get$capitalized_name$List();\n"
    "}\n");
  WriteFieldDocComment(printer, descriptor_);
  printer->Print(variables_,
    "$deprecation$public int get$capitalized_name$Count() {\n"
    "  return $name$_.size();\n"
    "}\n");
  WriteFieldDocComment(printer, descriptor_);
  printer->Print(variables_,
    "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
    "  return ($type$)\n"
    "      $name$_.get(index).getValue($type$.getDefaultInstance());\n"
    "}\n");
  WriteFieldDocComment(printer, descriptor_);
  printer->Print(variables_,
    "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder(\n"
    "    int index) {\n"
    "  return ($type$OrBuilder)\n"
    "      $name$_.get(index).getValue($type$.getDefaultInstance());\n"
    "}\n");
}

void RepeatedImmutableLazyMessageFieldGenerator::
GenerateBuilderMembers(io::Printer* printer) const {
  // When using nested-builders, the code initially works just like the
  // non-nested builder case. It only creates a nested builder lazily on
  // demand and then forever delegates to it after creation.

  printer->Print(variables_,
    "private java.util.List<com.google.protobuf.LazyFieldLite> $name$_ =\n"
    "  java.util.Collections.emptyList();\n"

    "private void ensure$capitalized_name$IsMutable() {\n"
    "  if (!$get_mutable_bit_builder$) {\n"
    "    $name$_ =\n"
    "        new java.util.ArrayList<com.google.protobuf.LazyFieldLite>(\n"
    "            $name$_);\n"
    "    $set_mutable_bit_builder$;\n"
    "   }\n"
    "}\n"
    "\n");

  printer->Print(variables_,
    // If this builder is non-null, it is used and the other fields are
    // ignored.
    "private com.google.protobuf.RepeatedFieldBuilder$ver$<\n"
    "    $type$, $type$.Builder, $type$OrBuilder> $name$Builder_;\n"
    "\n");

  // The comments above the methods below are based on a hypothetical
  // repeated field of type "Field" called "RepeatedField".

  // List<Field> getRepeatedFieldList()
  WriteFieldDocComment(printer, descriptor_);
  PrintNestedBuilderFunction(printer,
    "$deprecation$public java.util.List<$type$> get$capitalized_name$List()",

    "java.util.List<$type$> list =\n"
    "    new java.util.ArrayList<$type$>($name$_.size());\n"
    "for (com.google.protobuf.LazyFieldLite lf : $name$_) {\n"
    "  list.add(($type$) lf.getValue($type$.getDefaultInstance()));\n"
    "}\n"
    "return java.util.Collections.unmodifiableList(list);\n",

    "return $name$Builder_.getMessageList();\n",

    NULL);

  // int getRepeatedFieldCount()
  WriteFieldDocComment(printer, descriptor_);
  PrintNestedBuilderFunction(printer,
    "$deprecation$public int get$capitalized_name$Count()",

    "return $name$_.size();\n",
    "return $name$Builder_.getCount();\n",

    NULL);

  // Field getRepeatedField(int index)
  WriteFieldDocComment(printer, descriptor_);
  PrintNestedBuilderFunction(printer,
    "$deprecation$public $type$ get$capitalized_name$(int index)",

    "return ($type$) $name$_.get(index).getValue(\n"
    "    $type$.getDefaultInstance());\n",

    "return $name$Builder_.getMessage(index);\n",

    NULL);

  // Builder setRepeatedField(int index, Field value)
  WriteFieldDocComment(printer, descriptor_);
  PrintNestedBuilderFunction(printer,
    "$deprecation$public Builder set$capitalized_name$(\n"
    "    int index, $type$ value)",
    "if (value == null) {\n"
    "  throw new NullPointerException();\n"
    "}\n"
    "ensure$capitalized_name$IsMutable();\n"
    "$name$_.set(index, com.google.protobuf.LazyFieldLite.fromValue(value));\n"
    "$on_changed$\n",
    "$name$Builder_.setMessage(index, value);\n",
    "return this;\n");

  // Builder setRepeatedField(int index, Field.Builder builderForValue)
  WriteFieldDocComment(printer, descriptor_);
  PrintNestedBuilderFunction(printer,
    "$deprecation$public Builder set$capitalized_name$(\n"
    "    int index, $type$.Builder builderForValue)",

    "ensure$capitalized_name$IsMutable();\n"
    "$name$_.set(index, com.google.protobuf.LazyFieldLite.fromValue(\n"
    "    builderForValue.build()));\n"
    "$on_changed$\n",

    "$name$Builder_.setMessage(index, builderForValue.build());\n",

    "return this;\n");

  // Builder addRepeatedField(Field value)
  WriteFieldDocComment(printer, descriptor_);
  PrintNestedBuilderFunction(printer,
    "$deprecation$public Builder add$capitalized_name$($type$ value)",

    "if (value == null) {\n"
    "  throw new NullPointerException();\n"
    "}\n"
    "ensure$capitalized_name$IsMutable();\n"
    "$name$_.add(com.google.protobuf.LazyFieldLite.fromValue(value));\n"

    "$on_changed$\n",

    "$name$Builder_.addMessage(value);\n",

    "return this;\n");

  // Builder addRepeatedField(int index, Field value)
  WriteFieldDocComment(printer, descriptor_);
  PrintNestedBuilderFunction(printer,
    "$deprecation$public Builder add$capitalized_name$(\n"
    "    int index, $type$ value)",

    "if (value == null) {\n"
    "  throw new NullPointerException();\n"
    "}\n"
    "ensure$capitalized_name$IsMutable();\n"
    "$name$_.add(index, com.google.protobuf.LazyFieldLite.fromValue(value));\n"
    "$on_changed$\n",

    "$name$Builder_.addMessage(index, value);\n",

    "return this;\n");

  // Builder addRepeatedField(Field.Builder builderForValue)
  WriteFieldDocComment(printer, descriptor_);
  PrintNestedBuilderFunction(printer,
    "$deprecation$public Builder add$capitalized_name$(\n"
    "    $type$.Builder builderForValue)",

    "ensure$capitalized_name$IsMutable();\n"
    "$name$_.add(com.google.protobuf.LazyFieldLite.fromValue(\n"
    "    builderForValue.build()));\n"
    "$on_changed$\n",

    "$name$Builder_.addMessage(builderForValue.build());\n",

    "return this;\n");

  // Builder addRepeatedField(int index, Field.Builder builderForValue)
  WriteFieldDocComment(printer, descriptor_);
  PrintNestedBuilderFunction(printer,
    "$deprecation$public Builder add$capitalized_name$(\n"
    "    int index, $type$.Builder builderForValue)",

    "ensure$capitalized_name$IsMutable();\n"
    "$name$_.add(index, com.google.protobuf.LazyFieldLite.fromValue(\n"
    "    builderForValue.build()));\n"
    "$on_changed$\n",

    "$name$Builder_.addMessage(index, builderForValue.build());\n",

    "return this;\n");

  // Builder addAllRepeatedField(Iterable<Field> values)
  WriteFieldDocComment(printer, descriptor_);
  PrintNestedBuilderFunction(printer,
    "$deprecation$public Builder addAll$capitalized_name$(\n"
    "    java.lang.Iterable<? extends $type$> values)",

    "ensure$capitalized_name$IsMutable();\n"
    "for (com.google.protobuf.MessageLite v : values) {\n"
    "  $name$_.add(com.google.protobuf.LazyFieldLite.fromValue(v));\n"
    "}\n"
    "$on_changed$\n",

    "$name$Builder_.addAllMessages(values);\n",

    "return this;\n");

  // Builder clearAllRepeatedField()
  WriteFieldDocComment(printer, descriptor_);
  PrintNestedBuilderFunction(printer,
    "$deprecation$public Builder clear$capitalized_name$()",

    "$name$_ = java.util.Collections.emptyList();\n"
    "$clear_mutable_bit_builder$;\n"
    "$on_changed$\n",

    "$name$Builder_.clear();\n",

    "return this;\n");

  // Builder removeRepeatedField(int index)
  WriteFieldDocComment(printer, descriptor_);
  PrintNestedBuilderFunction(printer,
    "$deprecation$public Builder remove$capitalized_name$(int index)",

    "ensure$capitalized_name$IsMutable();\n"
    "$name$_.remove(index);\n"
    "$on_changed$\n",

    "$name$Builder_.remove(index);\n",

    "return this;\n");

  WriteFieldDocComment(printer, descriptor_);
  printer->Print(variables_,
    "$deprecation$public $type$.Builder get$capitalized_name$Builder(\n"
    "    int index) {\n"
    "  return get$capitalized_name$FieldBuilder().getBuilder(index);\n"
    "}\n");

  WriteFieldDocComment(printer, descriptor_);
      printer->Print(variables_,
    "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder(\n"
    "    int index) {\n"
    "  if ($name$Builder_ == null) {\n"
    "    return $name$_.get(index);"
    "  } else {\n"
    "    return $name$Builder_.getMessageOrBuilder(index);\n"
    "  }\n"
    "}\n");

  WriteFieldDocComment(printer, descriptor_);
      printer->Print(variables_,
    "$deprecation$public java.util.List<? extends $type$OrBuilder> \n"
    "     get$capitalized_name$OrBuilderList() {\n"
    "  if ($name$Builder_ != null) {\n"
    "    return $name$Builder_.getMessageOrBuilderList();\n"
    "  } else {\n"
    "    return java.util.Collections.unmodifiableList($name$_);\n"
    "  }\n"
    "}\n");

  WriteFieldDocComment(printer, descriptor_);
      printer->Print(variables_,
    "$deprecation$public $type$.Builder add$capitalized_name$Builder() {\n"
    "  return get$capitalized_name$FieldBuilder().addBuilder(\n"
    "      $type$.getDefaultInstance());\n"
    "}\n");
  WriteFieldDocComment(printer, descriptor_);
      printer->Print(variables_,
    "$deprecation$public $type$.Builder add$capitalized_name$Builder(\n"
    "    int index) {\n"
    "  return get$capitalized_name$FieldBuilder().addBuilder(\n"
    "      index, $type$.getDefaultInstance());\n"
    "}\n");
  WriteFieldDocComment(printer, descriptor_);
      printer->Print(variables_,
    "$deprecation$public java.util.List<$type$.Builder> \n"
    "     get$capitalized_name$BuilderList() {\n"
    "  return get$capitalized_name$FieldBuilder().getBuilderList();\n"
    "}\n"
    "private com.google.protobuf.RepeatedFieldBuilder$ver$<\n"
    "    $type$, $type$.Builder, $type$OrBuilder> \n"
    "    get$capitalized_name$FieldBuilder() {\n"
    "  if ($name$Builder_ == null) {\n"
    "    $name$Builder_ = new com.google.protobuf.RepeatedFieldBuilder$ver$<\n"
    "        $type$, $type$.Builder, $type$OrBuilder>(\n"
    "            $name$_,\n"
    "            $get_mutable_bit_builder$,\n"
    "            getParentForChildren(),\n"
    "            isClean());\n"
    "    $name$_ = null;\n"
    "  }\n"
    "  return $name$Builder_;\n"
    "}\n");
}

void RepeatedImmutableLazyMessageFieldGenerator::
GenerateParsingCode(io::Printer* printer) const {
  printer->Print(variables_,
    "if (!$get_mutable_bit_parser$) {\n"
    "  $name$_ =\n"
    "      new java.util.ArrayList<com.google.protobuf.LazyFieldLite>();\n"
    "  $set_mutable_bit_parser$;\n"
    "}\n"
    "$name$_.add(new com.google.protobuf.LazyFieldLite(\n"
    "    extensionRegistry, input.readBytes()));\n");
}

void RepeatedImmutableLazyMessageFieldGenerator::
GenerateSerializationCode(io::Printer* printer) const {
  printer->Print(variables_,
    "for (int i = 0; i < $name$_.size(); i++) {\n"
    "  output.writeBytes($number$, $name$_.get(i).toByteString());\n"
    "}\n");
}

void RepeatedImmutableLazyMessageFieldGenerator::
GenerateSerializedSizeCode(io::Printer* printer) const {
  printer->Print(variables_,
    "for (int i = 0; i < $name$_.size(); i++) {\n"
    "  size += com.google.protobuf.CodedOutputStream\n"
    "    .computeLazyFieldSize($number$, $name$_.get(i));\n"
    "}\n");
}

}  // namespace java
}  // namespace compiler
}  // namespace protobuf
}  // namespace google


text:
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.  All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

// Author: kenton@google.com (Kenton Varda)
//  Based on original Protocol Buffers design by
//  Sanjay Ghemawat, Jeff Dean, and others.

#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_FIELD_LITE_H__
#define GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_FIELD_LITE_H__

#include <map>
#include <string>
#include <google/protobuf/compiler/java/java_field.h>

namespace google {
namespace protobuf {
  namespace compiler {
    namespace java {
      class Context;            // context.h
      class ClassNameResolver;  // name_resolver.h
    }
  }
}

namespace protobuf {
namespace compiler {
namespace java {

class ImmutableEnumFieldLiteGenerator : public ImmutableFieldLiteGenerator {
 public:
  explicit ImmutableEnumFieldLiteGenerator(
      const FieldDescriptor* descriptor, int messageBitIndex,
      int builderBitIndex, Context* context);
  ~ImmutableEnumFieldLiteGenerator();

  // implements ImmutableFieldLiteGenerator ------------------------------------
  int GetNumBitsForMessage() const;
  int GetNumBitsForBuilder() const;
  void GenerateInterfaceMembers(io::Printer* printer) const;
  void GenerateMembers(io::Printer* printer) const;
  void GenerateBuilderMembers(io::Printer* printer) const;
  void GenerateInitializationCode(io::Printer* printer) const;
  void GenerateVisitCode(io::Printer* printer) const;
  void GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const;
  void GenerateParsingCode(io::Printer* printer) const;
  void GenerateParsingDoneCode(io::Printer* printer) const;
  void GenerateSerializationCode(io::Printer* printer) const;
  void GenerateSerializedSizeCode(io::Printer* printer) const;
  void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
  void GenerateEqualsCode(io::Printer* printer) const;
  void GenerateHashCode(io::Printer* printer) const;

  string GetBoxedType() const;

 protected:
  const FieldDescriptor* descriptor_;
  std::map<string, string> variables_;
  const int messageBitIndex_;
  const int builderBitIndex_;
  Context* context_;
  ClassNameResolver* name_resolver_;

 private:
  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableEnumFieldLiteGenerator);
};

class ImmutableEnumOneofFieldLiteGenerator
    : public ImmutableEnumFieldLiteGenerator {
 public:
  ImmutableEnumOneofFieldLiteGenerator(
      const FieldDescriptor* descriptor, int messageBitIndex,
      int builderBitIndex, Context* context);
  ~ImmutableEnumOneofFieldLiteGenerator();

  void GenerateMembers(io::Printer* printer) const;
  void GenerateBuilderMembers(io::Printer* printer) const;
  void GenerateVisitCode(io::Printer* printer) const;
  void GenerateParsingCode(io::Printer* printer) const;
  void GenerateSerializationCode(io::Printer* printer) const;
  void GenerateSerializedSizeCode(io::Printer* printer) const;
  void GenerateEqualsCode(io::Printer* printer) const;
  void GenerateHashCode(io::Printer* printer) const;

 private:
  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableEnumOneofFieldLiteGenerator);
};

class RepeatedImmutableEnumFieldLiteGenerator
    : public ImmutableFieldLiteGenerator {
 public:
  explicit RepeatedImmutableEnumFieldLiteGenerator(
      const FieldDescriptor* descriptor, int messageBitIndex,
      int builderBitIndex, Context* context);
  ~RepeatedImmutableEnumFieldLiteGenerator();

  // implements ImmutableFieldLiteGenerator ------------------------------------
  int GetNumBitsForMessage() const;
  int GetNumBitsForBuilder() const;
  void GenerateInterfaceMembers(io::Printer* printer) const;
  void GenerateMembers(io::Printer* printer) const;
  void GenerateBuilderMembers(io::Printer* printer) const;
  void GenerateInitializationCode(io::Printer* printer) const;
  void GenerateVisitCode(io::Printer* printer) const;
  void GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const;
  void GenerateParsingCode(io::Printer* printer) const;
  void GenerateParsingCodeFromPacked(io::Printer* printer) const;
  void GenerateParsingDoneCode(io::Printer* printer) const;
  void GenerateSerializationCode(io::Printer* printer) const;
  void GenerateSerializedSizeCode(io::Printer* printer) const;
  void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
  void GenerateEqualsCode(io::Printer* printer) const;
  void GenerateHashCode(io::Printer* printer) const;

  string GetBoxedType() const;

 private:
  const FieldDescriptor* descriptor_;
  std::map<string, string> variables_;
  const int messageBitIndex_;
  const int builderBitIndex_;
  Context* context_;
  ClassNameResolver* name_resolver_;

  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutableEnumFieldLiteGenerator);
};

}  // namespace java
}  // namespace compiler
}  // namespace protobuf

}  // namespace google
#endif  // GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_FIELD_LITE_H__


text:
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.  All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

// Author: kenton@google.com (Kenton Varda)

#include <google/protobuf/compiler/java/java_doc_comment.h>

#include <gtest/gtest.h>

namespace google {
namespace protobuf {
namespace compiler {
namespace java {
namespace {

TEST(JavaDocCommentTest, Escaping) {
  EXPECT_EQ("foo /* bar */ baz", EscapeJavadoc("foo /* bar */ baz"));
  EXPECT_EQ("foo /*/ baz", EscapeJavadoc("foo /*/ baz"));
  EXPECT_EQ("{@foo}", EscapeJavadoc("{@foo}"));
  EXPECT_EQ("&", EscapeJavadoc("&"));
  EXPECT_EQ("foo\u1234bar", EscapeJavadoc("foo\\u1234bar"));
  EXPECT_EQ("@deprecated", EscapeJavadoc("@deprecated"));
}

// TODO(kenton):  It's hard to write a robust test of the doc comments -- we
//   can only really compare the output against a golden value, which is a
//   fairly tedious and fragile testing strategy.  If we want to go that route,
//   it probably makes sense to bite the bullet and write a test that compares
//   the whole generated output for unittest.proto against a golden value, with
//   a very simple script that can be run to regenerate it with the latest code.
//   This would mean that updates to the golden file would have to be included
//   in any change to the code generator, which would actually be fairly useful
//   as it allows the reviewer to see clearly how the generated code is
//   changing.

}  // namespace
}  // namespace java
}  // namespace compiler
}  // namespace protobuf
}  // namespace google


text:
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.  All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

// Author: kenton@google.com (Kenton Varda)
//  Based on original Protocol Buffers design by
//  Sanjay Ghemawat, Jeff Dean, and others.

#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_PRIMITIVE_FIELD_LITE_H__
#define GOOGLE_PROTOBUF_COMPILER_JAVA_PRIMITIVE_FIELD_LITE_H__

#include <map>
#include <string>
#include <google/protobuf/compiler/java/java_field.h>

namespace google {
namespace protobuf {
  namespace compiler {
    namespace java {
      class Context;           // context.h
      class ClassNameResolver; // name_resolver.h
    }
  }
}

namespace protobuf {
namespace compiler {
namespace java {

class ImmutablePrimitiveFieldLiteGenerator
    : public ImmutableFieldLiteGenerator {
 public:
  explicit ImmutablePrimitiveFieldLiteGenerator(
      const FieldDescriptor* descriptor, int messageBitIndex,
      int builderBitIndex, Context* context);
  ~ImmutablePrimitiveFieldLiteGenerator();

  // implements ImmutableFieldLiteGenerator ------------------------------------
  int GetNumBitsForMessage() const;
  int GetNumBitsForBuilder() const;
  void GenerateInterfaceMembers(io::Printer* printer) const;
  void GenerateMembers(io::Printer* printer) const;
  void GenerateBuilderMembers(io::Printer* printer) const;
  void GenerateInitializationCode(io::Printer* printer) const;
  void GenerateBuilderClearCode(io::Printer* printer) const;
  void GenerateVisitCode(io::Printer* printer) const;
  void GenerateBuildingCode(io::Printer* printer) const;
  void GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const;
  void GenerateParsingCode(io::Printer* printer) const;
  void GenerateParsingDoneCode(io::Printer* printer) const;
  void GenerateSerializationCode(io::Printer* printer) const;
  void GenerateSerializedSizeCode(io::Printer* printer) const;
  void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
  void GenerateEqualsCode(io::Printer* printer) const;
  void GenerateHashCode(io::Printer* printer) const;

  string GetBoxedType() const;

 protected:
  const FieldDescriptor* descriptor_;
  std::map<string, string> variables_;
  const int messageBitIndex_;
  const int builderBitIndex_;
  Context* context_;
  ClassNameResolver* name_resolver_;

 private:
  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutablePrimitiveFieldLiteGenerator);
};

class ImmutablePrimitiveOneofFieldLiteGenerator
    : public ImmutablePrimitiveFieldLiteGenerator {
 public:
  ImmutablePrimitiveOneofFieldLiteGenerator(
      const FieldDescriptor* descriptor, int messageBitIndex,
      int builderBitIndex, Context* context);
  ~ImmutablePrimitiveOneofFieldLiteGenerator();

  void GenerateMembers(io::Printer* printer) const;
  void GenerateBuilderMembers(io::Printer* printer) const;
  void GenerateBuildingCode(io::Printer* printer) const;
  void GenerateVisitCode(io::Printer* printer) const;
  void GenerateParsingCode(io::Printer* printer) const;
  void GenerateSerializationCode(io::Printer* printer) const;
  void GenerateSerializedSizeCode(io::Printer* printer) const;

 private:
  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutablePrimitiveOneofFieldLiteGenerator);
};

class RepeatedImmutablePrimitiveFieldLiteGenerator
    : public ImmutableFieldLiteGenerator {
 public:
  explicit RepeatedImmutablePrimitiveFieldLiteGenerator(
      const FieldDescriptor* descriptor, int messageBitIndex,
      int builderBitIndex, Context* context);
  virtual ~RepeatedImmutablePrimitiveFieldLiteGenerator();

  // implements ImmutableFieldLiteGenerator ------------------------------------
  int GetNumBitsForMessage() const;
  int GetNumBitsForBuilder() const;
  void GenerateInterfaceMembers(io::Printer* printer) const;
  void GenerateMembers(io::Printer* printer) const;
  void GenerateBuilderMembers(io::Printer* printer) const;
  void GenerateInitializationCode(io::Printer* printer) const;
  void GenerateBuilderClearCode(io::Printer* printer) const;
  void GenerateVisitCode(io::Printer* printer) const;
  void GenerateBuildingCode(io::Printer* printer) const;
  void GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const;
  void GenerateParsingCode(io::Printer* printer) const;
  void GenerateParsingCodeFromPacked(io::Printer* printer) const;
  void GenerateParsingDoneCode(io::Printer* printer) const;
  void GenerateSerializationCode(io::Printer* printer) const;
  void GenerateSerializedSizeCode(io::Printer* printer) const;
  void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
  void GenerateEqualsCode(io::Printer* printer) const;
  void GenerateHashCode(io::Printer* printer) const;

  string GetBoxedType() const;

 private:
  const FieldDescriptor* descriptor_;
  std::map<string, string> variables_;
  const int messageBitIndex_;
  const int builderBitIndex_;
  Context* context_;
  ClassNameResolver* name_resolver_;

  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutablePrimitiveFieldLiteGenerator);
};

}  // namespace java
}  // namespace compiler
}  // namespace protobuf

}  // namespace google
#endif  // GOOGLE_PROTOBUF_COMPILER_JAVA_PRIMITIVE_FIELD_LITE_H__


text:
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.  All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

// Author: kenton@google.com (Kenton Varda)
//  Based on original Protocol Buffers design by
//  Sanjay Ghemawat, Jeff Dean, and others.

#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_FIELD_H__
#define GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_FIELD_H__

#include <map>
#include <string>
#include <google/protobuf/compiler/java/java_field.h>

namespace google {
namespace protobuf {
  namespace compiler {
    namespace java {
      class Context;           // context.h
      class ClassNameResolver; // name_resolver.h
    }
  }
}

namespace protobuf {
namespace compiler {
namespace java {

class ImmutableMessageFieldGenerator : public ImmutableFieldGenerator {
 public:
  explicit ImmutableMessageFieldGenerator(
      const FieldDescriptor* descriptor, int messageBitIndex,
      int builderBitIndex, Context* context);
  ~ImmutableMessageFieldGenerator();

  // implements ImmutableFieldGenerator ---------------------------------------
  int GetNumBitsForMessage() const;
  int GetNumBitsForBuilder() const;
  void GenerateInterfaceMembers(io::Printer* printer) const;
  void GenerateMembers(io::Printer* printer) const;
  void GenerateBuilderMembers(io::Printer* printer) const;
  void GenerateInitializationCode(io::Printer* printer) const;
  void GenerateBuilderClearCode(io::Printer* printer) const;
  void GenerateMergingCode(io::Printer* printer) const;
  void GenerateBuildingCode(io::Printer* printer) const;
  void GenerateParsingCode(io::Printer* printer) const;
  void GenerateParsingDoneCode(io::Printer* printer) const;
  void GenerateSerializationCode(io::Printer* printer) const;
  void GenerateSerializedSizeCode(io::Printer* printer) const;
  void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
  void GenerateEqualsCode(io::Printer* printer) const;
  void GenerateHashCode(io::Printer* printer) const;

  string GetBoxedType() const;

 protected:
  const FieldDescriptor* descriptor_;
  std::map<string, string> variables_;
  const int messageBitIndex_;
  const int builderBitIndex_;
  Context* context_;
  ClassNameResolver* name_resolver_;

  void PrintNestedBuilderCondition(io::Printer* printer,
      const char* regular_case, const char* nested_builder_case) const;
  void PrintNestedBuilderFunction(io::Printer* printer,
      const char* method_prototype, const char* regular_case,
      const char* nested_builder_case,
      const char* trailing_code) const;

 private:
  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableMessageFieldGenerator);
};

class ImmutableMessageOneofFieldGenerator
    : public ImmutableMessageFieldGenerator {
 public:
  ImmutableMessageOneofFieldGenerator(
      const FieldDescriptor* descriptor, int messageBitIndex,
      int builderBitIndex, Context* context);
  ~ImmutableMessageOneofFieldGenerator();

  void GenerateMembers(io::Printer* printer) const;
  void GenerateBuilderMembers(io::Printer* printer) const;
  void GenerateBuildingCode(io::Printer* printer) const;
  void GenerateMergingCode(io::Printer* printer) const;
  void GenerateParsingCode(io::Printer* printer) const;
  void GenerateSerializationCode(io::Printer* printer) const;
  void GenerateSerializedSizeCode(io::Printer* printer) const;

 private:
  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableMessageOneofFieldGenerator);
};

class RepeatedImmutableMessageFieldGenerator : public ImmutableFieldGenerator {
 public:
  explicit RepeatedImmutableMessageFieldGenerator(
      const FieldDescriptor* descriptor, int messageBitIndex,
      int builderBitIndex, Context* context);
  ~RepeatedImmutableMessageFieldGenerator();

  // implements ImmutableFieldGenerator ---------------------------------------
  int GetNumBitsForMessage() const;
  int GetNumBitsForBuilder() const;
  void GenerateInterfaceMembers(io::Printer* printer) const;
  void GenerateMembers(io::Printer* printer) const;
  void GenerateBuilderMembers(io::Printer* printer) const;
  void GenerateInitializationCode(io::Printer* printer) const;
  void GenerateBuilderClearCode(io::Printer* printer) const;
  void GenerateMergingCode(io::Printer* printer) const;
  void GenerateBuildingCode(io::Printer* printer) const;
  void GenerateParsingCode(io::Printer* printer) const;
  void GenerateParsingDoneCode(io::Printer* printer) const;
  void GenerateSerializationCode(io::Printer* printer) const;
  void GenerateSerializedSizeCode(io::Printer* printer) const;
  void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
  void GenerateEqualsCode(io::Printer* printer) const;
  void GenerateHashCode(io::Printer* printer) const;

  string GetBoxedType() const;

 protected:
  const FieldDescriptor* descriptor_;
  std::map<string, string> variables_;
  const int messageBitIndex_;
  const int builderBitIndex_;
  Context* context_;
  ClassNameResolver* name_resolver_;

  void PrintNestedBuilderCondition(io::Printer* printer,
      const char* regular_case, const char* nested_builder_case) const;
  void PrintNestedBuilderFunction(io::Printer* printer,
      const char* method_prototype, const char* regular_case,
      const char* nested_builder_case,
      const char* trailing_code) const;

 private:
  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutableMessageFieldGenerator);
};

}  // namespace java
}  // namespace compiler
}  // namespace protobuf

}  // namespace google
#endif  // GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_FIELD_H__