text:
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.  All rights reserved.
// http://code.google.com/p/protobuf/
//
// 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 <algorithm>
#include <google/protobuf/stubs/hash.h>
#include <google/protobuf/compiler/javanano/javanano_message.h>
#include <google/protobuf/compiler/javanano/javanano_enum.h>
#include <google/protobuf/compiler/javanano/javanano_extension.h>
#include <google/protobuf/compiler/javanano/javanano_helpers.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/wire_format.h>
#include <google/protobuf/descriptor.pb.h>

namespace google {
namespace protobuf {
namespace compiler {
namespace javanano {

using internal::WireFormat;
using internal::WireFormatLite;

namespace {

struct FieldOrderingByNumber {
  inline bool operator()(const FieldDescriptor* a,
                         const FieldDescriptor* b) const {
    return a->number() < b->number();
  }
};

// Sort the fields of the given Descriptor by number into a new[]'d array
// and return it.
const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor) {
  const FieldDescriptor** fields =
    new const FieldDescriptor*[descriptor->field_count()];
  for (int i = 0; i < descriptor->field_count(); i++) {
    fields[i] = descriptor->field(i);
  }
  std::sort(fields, fields + descriptor->field_count(),
       FieldOrderingByNumber());
  return fields;
}

}  // namespace

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

MessageGenerator::MessageGenerator(const Descriptor* descriptor, const Params& params)
  : params_(params),
    descriptor_(descriptor),
    field_generators_(descriptor, params) {
}

MessageGenerator::~MessageGenerator() {}

void MessageGenerator::GenerateStaticVariables(io::Printer* printer) {
  // Generate static members for all nested types.
  for (int i = 0; i < descriptor_->nested_type_count(); i++) {
    // TODO(kenton):  Reuse MessageGenerator objects?
    if (IsMapEntry(descriptor_->nested_type(i))) continue;
    MessageGenerator(descriptor_->nested_type(i), params_)
      .GenerateStaticVariables(printer);
  }
}

void MessageGenerator::GenerateStaticVariableInitializers(
    io::Printer* printer) {
  // Generate static member initializers for all nested types.
  for (int i = 0; i < descriptor_->nested_type_count(); i++) {
   // TODO(kenton):  Reuse MessageGenerator objects?
    if (IsMapEntry(descriptor_->nested_type(i))) continue;
    MessageGenerator(descriptor_->nested_type(i), params_)
      .GenerateStaticVariableInitializers(printer);
  }
}

void MessageGenerator::Generate(io::Printer* printer) {
  if (!params_.store_unknown_fields() &&
      (descriptor_->extension_count() != 0 || descriptor_->extension_range_count() != 0)) {
    GOOGLE_LOG(FATAL) << "Extensions are only supported in NANO_RUNTIME if the "
        "'store_unknown_fields' generator option is 'true'\n";
  }

  const string& file_name = descriptor_->file()->name();
  bool is_own_file =
    params_.java_multiple_files(file_name)
      && descriptor_->containing_type() == NULL;

  if (is_own_file) {
    // Note: constants (from enums and fields requiring stored defaults, emitted in the loop below)
    // may have the same names as constants in the nested classes. This causes Java warnings, but
    // is not fatal, so we suppress those warnings here in the top-most class declaration.
    printer->Print(
      "\n"
      "@SuppressWarnings(\"hiding\")\n"
      "public final class $classname$ extends\n",
      "classname", descriptor_->name());
  } else {
    printer->Print(
      "\n"
      "public static final class $classname$ extends\n",
      "classname", descriptor_->name());
  }
  if (params_.store_unknown_fields() && params_.parcelable_messages()) {
    printer->Print(
      "    com.google.protobuf.nano.android.ParcelableExtendableMessageNano<$classname$>",
      "classname", descriptor_->name());
  } else if (params_.store_unknown_fields()) {
    printer->Print(
      "    com.google.protobuf.nano.ExtendableMessageNano<$classname$>",
      "classname", descriptor_->name());
  } else if (params_.parcelable_messages()) {
    printer->Print(
      "    com.google.protobuf.nano.android.ParcelableMessageNano");
  } else {
    printer->Print(
      "    com.google.protobuf.nano.MessageNano");
  }
  if (params_.generate_clone()) {
    printer->Print(" implements java.lang.Cloneable {\n");
  } else {
    printer->Print(" {\n");
  }
  printer->Indent();

  if (params_.parcelable_messages()) {
    printer->Print(
      "\n"
      "// Used by Parcelable\n"
      "@SuppressWarnings({\"unused\"})\n"
      "public static final android.os.Parcelable.Creator<$classname$> CREATOR =\n"
      "    new com.google.protobuf.nano.android.ParcelableMessageNanoCreator<\n"
      "        $classname$>($classname$.class);\n",
      "classname", descriptor_->name());
  }

  // Nested types and extensions
  for (int i = 0; i < descriptor_->extension_count(); i++) {
    ExtensionGenerator(descriptor_->extension(i), params_).Generate(printer);
  }

  for (int i = 0; i < descriptor_->enum_type_count(); i++) {
    EnumGenerator(descriptor_->enum_type(i), params_).Generate(printer);
  }

  for (int i = 0; i < descriptor_->nested_type_count(); i++) {
    if (IsMapEntry(descriptor_->nested_type(i))) continue;
    MessageGenerator(descriptor_->nested_type(i), params_).Generate(printer);
  }

  // oneof
  std::map<string, string> vars;
  vars["message_name"] = descriptor_->name();
  for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
    const OneofDescriptor* oneof_desc = descriptor_->oneof_decl(i);
    vars["oneof_name"] = UnderscoresToCamelCase(oneof_desc);
    vars["oneof_capitalized_name"] =
        UnderscoresToCapitalizedCamelCase(oneof_desc);
    vars["oneof_index"] = SimpleItoa(oneof_desc->index());
    // Oneof Constants
    for (int j = 0; j < oneof_desc->field_count(); j++) {
      const FieldDescriptor* field = oneof_desc->field(j);
      vars["number"] = SimpleItoa(field->number());
      vars["cap_field_name"] = ToUpper(field->name());
      printer->Print(vars,
        "public static final int $cap_field_name$_FIELD_NUMBER = $number$;\n");
    }
    // oneofCase_ and oneof_
    printer->Print(vars,
      "private int $oneof_name$Case_ = 0;\n"
      "private java.lang.Object $oneof_name$_;\n");
    printer->Print(vars,
      "public int get$oneof_capitalized_name$Case() {\n"
      "  return this.$oneof_name$Case_;\n"
      "}\n");
    // Oneof clear
    printer->Print(vars,
      "public $message_name$ clear$oneof_capitalized_name$() {\n"
      "  this.$oneof_name$Case_ = 0;\n"
      "  this.$oneof_name$_ = null;\n"
      "  return this;\n"
      "}\n");
  }

  // Lazy initialization of otherwise static final fields can help prevent the
  // class initializer from being generated. We want to prevent it because it
  // stops ProGuard from inlining any methods in this class into call sites and
  // therefore reducing the method count. However, extensions are best kept as
  // public static final fields with initializers, so with their existence we
  // won't bother with lazy initialization.
  bool lazy_init = descriptor_->extension_count() == 0;

  // Empty array
  if (lazy_init) {
    printer->Print(
      "\n"
      "private static volatile $classname$[] _emptyArray;\n"
      "public static $classname$[] emptyArray() {\n"
      "  // Lazily initializes the empty array\n"
      "  if (_emptyArray == null) {\n"
      "    synchronized (\n"
      "        com.google.protobuf.nano.InternalNano.LAZY_INIT_LOCK) {\n"
      "      if (_emptyArray == null) {\n"
      "        _emptyArray = new $classname$[0];\n"
      "      }\n"
      "    }\n"
      "  }\n"
      "  return _emptyArray;\n"
      "}\n",
      "classname", descriptor_->name());
  } else {
    printer->Print(
      "\n"
      "private static final $classname$[] EMPTY_ARRAY = {};\n"
      "public static $classname$[] emptyArray() {\n"
      "  return EMPTY_ARRAY;\n"
      "}\n",
      "classname", descriptor_->name());
  }

  // Integers for bit fields
  int totalInts = (field_generators_.total_bits() + 31) / 32;
  if (totalInts > 0) {
    printer->Print("\n");
    for (int i = 0; i < totalInts; i++) {
      printer->Print("private int $bit_field_name$;\n",
        "bit_field_name", GetBitFieldName(i));
    }
  }

  // Fields and maybe their default values
  for (int i = 0; i < descriptor_->field_count(); i++) {
    printer->Print("\n");
    PrintFieldComment(printer, descriptor_->field(i));
    field_generators_.get(descriptor_->field(i)).GenerateMembers(
        printer, lazy_init);
  }

  // Constructor, with lazy init code if needed
  if (lazy_init && field_generators_.saved_defaults_needed()) {
    printer->Print(
      "\n"
      "private static volatile boolean _classInitialized;\n"
      "\n"
      "public $classname$() {\n"
      "  // Lazily initializes the field defaults\n"
      "  if (!_classInitialized) {\n"
      "    synchronized (\n"
      "        com.google.protobuf.nano.InternalNano.LAZY_INIT_LOCK) {\n"
      "      if (!_classInitialized) {\n",
      "classname", descriptor_->name());
    printer->Indent();
    printer->Indent();
    printer->Indent();
    printer->Indent();
    for (int i = 0; i < descriptor_->field_count(); i++) {
      field_generators_.get(descriptor_->field(i))
          .GenerateInitSavedDefaultCode(printer);
    }
    printer->Outdent();
    printer->Outdent();
    printer->Outdent();
    printer->Outdent();
    printer->Print(
      "        _classInitialized = true;\n"
      "      }\n"
      "    }\n"
      "  }\n");
    if (params_.generate_clear()) {
      printer->Print("  clear();\n");
    }
    printer->Print("}\n");
  } else {
    printer->Print(
      "\n"
      "public $classname$() {\n",
      "classname", descriptor_->name());
    if (params_.generate_clear()) {
      printer->Print("  clear();\n");
    } else {
      printer->Indent();
      GenerateFieldInitializers(printer);
      printer->Outdent();
    }
    printer->Print("}\n");
  }

  // Other methods in this class

  GenerateClear(printer);

  if (params_.generate_clone()) {
    GenerateClone(printer);
  }

  if (params_.generate_equals()) {
    GenerateEquals(printer);
    GenerateHashCode(printer);
  }

  GenerateMessageSerializationMethods(printer);
  GenerateMergeFromMethods(printer);
  GenerateParseFromMethods(printer);

  printer->Outdent();
  printer->Print("}\n");
}

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

void MessageGenerator::
GenerateMessageSerializationMethods(io::Printer* printer) {
  // Rely on the parent implementations of writeTo() and getSerializedSize()
  // if there are no fields to serialize in this message.
  if (descriptor_->field_count() == 0) {
    return;
  }

  scoped_array<const FieldDescriptor*> sorted_fields(
    SortFieldsByNumber(descriptor_));

  printer->Print(
    "\n"
    "@Override\n"
    "public void writeTo(com.google.protobuf.nano.CodedOutputByteBufferNano output)\n"
    "    throws java.io.IOException {\n");
  printer->Indent();

  // Output the fields in sorted order
  for (int i = 0; i < descriptor_->field_count(); i++) {
    GenerateSerializeOneField(printer, sorted_fields[i]);
  }

  // The parent implementation will write any unknown fields if necessary.
  printer->Print(
    "super.writeTo(output);\n");

  printer->Outdent();
  printer->Print("}\n");

  // The parent implementation will get the serialized size for unknown
  // fields if necessary.
  printer->Print(
    "\n"
    "@Override\n"
    "protected int computeSerializedSize() {\n"
    "  int size = super.computeSerializedSize();\n");
  printer->Indent();

  for (int i = 0; i < descriptor_->field_count(); i++) {
    field_generators_.get(sorted_fields[i]).GenerateSerializedSizeCode(printer);
  }

  printer->Outdent();
  printer->Print(
    "  return size;\n"
    "}\n");
}

void MessageGenerator::GenerateMergeFromMethods(io::Printer* printer) {
  scoped_array<const FieldDescriptor*> sorted_fields(
    SortFieldsByNumber(descriptor_));

  printer->Print(
    "\n"
    "@Override\n"
    "public $classname$ mergeFrom(\n"
    "        com.google.protobuf.nano.CodedInputByteBufferNano input)\n"
    "    throws java.io.IOException {\n",
    "classname", descriptor_->name());

  printer->Indent();
  if (HasMapField(descriptor_)) {
    printer->Print(
      "com.google.protobuf.nano.MapFactories.MapFactory mapFactory =\n"
      "  com.google.protobuf.nano.MapFactories.getMapFactory();\n");
  }

  printer->Print(
    "while (true) {\n");
  printer->Indent();

  printer->Print(
    "int tag = input.readTag();\n"
    "switch (tag) {\n");
  printer->Indent();

  printer->Print(
    "case 0:\n"          // zero signals EOF / limit reached
    "  return this;\n"
    "default: {\n");

  printer->Indent();
  if (params_.store_unknown_fields()) {
    printer->Print(
        "if (!storeUnknownField(input, tag)) {\n"
        "  return this;\n"
        "}\n");
  } else {
    printer->Print(
        "if (!com.google.protobuf.nano.WireFormatNano.parseUnknownField(input, tag)) {\n"
        "  return this;\n"   // it's an endgroup tag
        "}\n");
  }
  printer->Print("break;\n");
  printer->Outdent();
  printer->Print("}\n");

  for (int i = 0; i < descriptor_->field_count(); i++) {
    const FieldDescriptor* field = sorted_fields[i];
    uint32 tag = WireFormatLite::MakeTag(field->number(),
      WireFormat::WireTypeForFieldType(field->type()));

    printer->Print(
      "case $tag$: {\n",
      "tag", SimpleItoa(tag));
    printer->Indent();

    field_generators_.get(field).GenerateMergingCode(printer);

    printer->Outdent();
    printer->Print(
      "  break;\n"
      "}\n");

    if (field->is_packable()) {
      // To make packed = true wire compatible, we generate parsing code from a
      // packed version of this field regardless of field->options().packed().
      uint32 packed_tag = WireFormatLite::MakeTag(field->number(),
        WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
      printer->Print(
        "case $tag$: {\n",
        "tag", SimpleItoa(packed_tag));
      printer->Indent();

      field_generators_.get(field).GenerateMergingCodeFromPacked(printer);

      printer->Outdent();
      printer->Print(
        "  break;\n"
        "}\n");
    }
  }

  printer->Outdent();
  printer->Outdent();
  printer->Outdent();
  printer->Print(
    "    }\n"     // switch (tag)
    "  }\n"       // while (true)
    "}\n");
}

void MessageGenerator::
GenerateParseFromMethods(io::Printer* printer) {
  // Note:  These are separate from GenerateMessageSerializationMethods()
  //   because they need to be generated even for messages that are optimized
  //   for code size.
  printer->Print(
    "\n"
    "public static $classname$ parseFrom(byte[] data)\n"
    "    throws com.google.protobuf.nano.InvalidProtocolBufferNanoException {\n"
    "  return com.google.protobuf.nano.MessageNano.mergeFrom(new $classname$(), data);\n"
    "}\n"
    "\n"
    "public static $classname$ parseFrom(\n"
    "        com.google.protobuf.nano.CodedInputByteBufferNano input)\n"
    "    throws java.io.IOException {\n"
    "  return new $classname$().mergeFrom(input);\n"
    "}\n",
    "classname", descriptor_->name());
}

void MessageGenerator::GenerateSerializeOneField(
    io::Printer* printer, const FieldDescriptor* field) {
  field_generators_.get(field).GenerateSerializationCode(printer);
}

void MessageGenerator::GenerateClear(io::Printer* printer) {
  if (!params_.generate_clear()) {
    return;
  }
  printer->Print(
    "\n"
    "public $classname$ clear() {\n",
    "classname", descriptor_->name());
  printer->Indent();

  GenerateFieldInitializers(printer);

  printer->Outdent();
  printer->Print(
    "  return this;\n"
    "}\n");
}

void MessageGenerator::GenerateFieldInitializers(io::Printer* printer) {
  // Clear bit fields.
  int totalInts = (field_generators_.total_bits() + 31) / 32;
  for (int i = 0; i < totalInts; i++) {
    printer->Print("$bit_field_name$ = 0;\n",
      "bit_field_name", GetBitFieldName(i));
  }

  // Call clear for all of the fields.
  for (int i = 0; i < descriptor_->field_count(); i++) {
    const FieldDescriptor* field = descriptor_->field(i);
    field_generators_.get(field).GenerateClearCode(printer);
  }

  // Clear oneofs.
  for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
    printer->Print(
      "clear$oneof_capitalized_name$();\n",
      "oneof_capitalized_name", UnderscoresToCapitalizedCamelCase(
          descriptor_->oneof_decl(i)));
  }

  // Clear unknown fields.
  if (params_.store_unknown_fields()) {
    printer->Print("unknownFieldData = null;\n");
  }
  printer->Print("cachedSize = -1;\n");
}

void MessageGenerator::GenerateClone(io::Printer* printer) {
  printer->Print(
    "@Override\n"
    "public $classname$ clone() {\n",
    "classname", descriptor_->name());
  printer->Indent();

  printer->Print(
    "$classname$ cloned;\n"
    "try {\n"
    "  cloned = ($classname$) super.clone();\n"
    "} catch (java.lang.CloneNotSupportedException e) {\n"
    "  throw new java.lang.AssertionError(e);\n"
    "}\n",
    "classname", descriptor_->name());

  for (int i = 0; i < descriptor_->field_count(); i++) {
    field_generators_.get(descriptor_->field(i)).GenerateFixClonedCode(printer);
  }

  printer->Outdent();
  printer->Print(
    "  return cloned;\n"
    "}\n"
    "\n");
}

void MessageGenerator::GenerateEquals(io::Printer* printer) {
  // Don't override if there are no fields. We could generate an
  // equals method that compares types, but often empty messages
  // are used as namespaces.
  if (descriptor_->field_count() == 0 && !params_.store_unknown_fields()) {
    return;
  }

  printer->Print(
    "\n"
    "@Override\n"
    "public boolean equals(Object o) {\n");
  printer->Indent();
  printer->Print(
    "if (o == this) {\n"
    "  return true;\n"
    "}\n"
    "if (!(o instanceof $classname$)) {\n"
    "  return false;\n"
    "}\n"
    "$classname$ other = ($classname$) o;\n",
    "classname", descriptor_->name());

  // Checking oneof case before checking each oneof field.
  for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
    const OneofDescriptor* oneof_desc = descriptor_->oneof_decl(i);
    printer->Print(
      "if (this.$oneof_name$Case_ != other.$oneof_name$Case_) {\n"
      "  return false;\n"
      "}\n",
      "oneof_name", UnderscoresToCamelCase(oneof_desc));
  }

  for (int i = 0; i < descriptor_->field_count(); i++) {
    const FieldDescriptor* field = descriptor_->field(i);
    field_generators_.get(field).GenerateEqualsCode(printer);
  }

  if (params_.store_unknown_fields()) {
    printer->Print(
      "if (unknownFieldData == null || unknownFieldData.isEmpty()) {\n"
      "  return other.unknownFieldData == null || other.unknownFieldData.isEmpty();\n"
      "} else {\n"
      "  return unknownFieldData.equals(other.unknownFieldData);\n"
      "}");
  } else {
    printer->Print(
      "return true;\n");
  }

  printer->Outdent();
  printer->Print("}\n");
}

void MessageGenerator::GenerateHashCode(io::Printer* printer) {
  if (descriptor_->field_count() == 0 && !params_.store_unknown_fields()) {
    return;
  }

  printer->Print(
    "\n"
    "@Override\n"
    "public int hashCode() {\n");
  printer->Indent();

  printer->Print("int result = 17;\n");
  printer->Print("result = 31 * result + getClass().getName().hashCode();\n");
  for (int i = 0; i < descriptor_->field_count(); i++) {
    const FieldDescriptor* field = descriptor_->field(i);
    field_generators_.get(field).GenerateHashCodeCode(printer);
  }

  if (params_.store_unknown_fields()) {
    printer->Print(
      "result = 31 * result + \n"
      "  (unknownFieldData == null || unknownFieldData.isEmpty() ? 0 : \n"
      "  unknownFieldData.hashCode());\n");
  }

  printer->Print("return result;\n");

  printer->Outdent();
  printer->Print("}\n");
}

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

}  // namespace javanano
}  // namespace compiler
}  // namespace protobuf
}  // namespace google


text:
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.  All rights reserved.
// http://code.google.com/p/protobuf/
//
// 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/javanano/javanano_map_field.h>
#include <google/protobuf/compiler/javanano/javanano_helpers.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/wire_format.h>
#include <google/protobuf/stubs/strutil.h>

namespace google {
namespace protobuf {
namespace compiler {
namespace javanano {

namespace {

string TypeName(const Params& params, const FieldDescriptor* field,
                bool boxed) {
  JavaType java_type = GetJavaType(field);
  switch (java_type) {
    case JAVATYPE_MESSAGE:
      return ClassName(params, field->message_type());
    case JAVATYPE_INT:
    case JAVATYPE_LONG:
    case JAVATYPE_FLOAT:
    case JAVATYPE_DOUBLE:
    case JAVATYPE_BOOLEAN:
    case JAVATYPE_STRING:
    case JAVATYPE_BYTES:
    case JAVATYPE_ENUM:
      if (boxed) {
        return BoxedPrimitiveTypeName(java_type);
      } else {
        return PrimitiveTypeName(java_type);
      }
    // No default because we want the compiler to complain if any new JavaTypes
    // are added..
  }

  GOOGLE_LOG(FATAL) << "should not reach here.";
  return "";
}

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");
}

void SetMapVariables(const Params& params,
    const FieldDescriptor* descriptor, std::map<string, string>* variables) {
  const FieldDescriptor* key = KeyField(descriptor);
  const FieldDescriptor* value = ValueField(descriptor);
  (*variables)["name"] =
    RenameJavaKeywords(UnderscoresToCamelCase(descriptor));
  (*variables)["number"] = SimpleItoa(descriptor->number());
  (*variables)["key_type"] = TypeName(params, key, false);
  (*variables)["boxed_key_type"] = TypeName(params,key, true);
  (*variables)["key_desc_type"] =
      "TYPE_" + ToUpper(FieldDescriptor::TypeName(key->type()));
  (*variables)["key_tag"] = SimpleItoa(internal::WireFormat::MakeTag(key));
  (*variables)["value_type"] = TypeName(params, value, false);
  (*variables)["boxed_value_type"] = TypeName(params, value, true);
  (*variables)["value_desc_type"] =
      "TYPE_" + ToUpper(FieldDescriptor::TypeName(value->type()));
  (*variables)["value_tag"] = SimpleItoa(internal::WireFormat::MakeTag(value));
  (*variables)["type_parameters"] =
      (*variables)["boxed_key_type"] + ", " + (*variables)["boxed_value_type"];
  (*variables)["value_default"] =
      value->type() == FieldDescriptor::TYPE_MESSAGE
          ? "new " + (*variables)["value_type"] + "()"
          : "null";
}
}  // namespace

// ===================================================================
MapFieldGenerator::MapFieldGenerator(const FieldDescriptor* descriptor,
                                     const Params& params)
    : FieldGenerator(params), descriptor_(descriptor) {
  SetMapVariables(params, descriptor, &variables_);
}

MapFieldGenerator::~MapFieldGenerator() {}

void MapFieldGenerator::
GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const {
  printer->Print(variables_,
    "public java.util.Map<$type_parameters$> $name$;\n");
}

void MapFieldGenerator::
GenerateClearCode(io::Printer* printer) const {
  printer->Print(variables_,
    "$name$ = null;\n");
}

void MapFieldGenerator::
GenerateMergingCode(io::Printer* printer) const {
  printer->Print(variables_,
    "this.$name$ = com.google.protobuf.nano.InternalNano.mergeMapEntry(\n"
    "  input, this.$name$, mapFactory,\n"
    "  com.google.protobuf.nano.InternalNano.$key_desc_type$,\n"
    "  com.google.protobuf.nano.InternalNano.$value_desc_type$,\n"
    "  $value_default$,\n"
    "  $key_tag$, $value_tag$);\n"
    "\n");
}

void MapFieldGenerator::
GenerateSerializationCode(io::Printer* printer) const {
  printer->Print(variables_,
    "if (this.$name$ != null) {\n"
    "  com.google.protobuf.nano.InternalNano.serializeMapField(\n"
    "    output, this.$name$, $number$,\n"
    "  com.google.protobuf.nano.InternalNano.$key_desc_type$,\n"
    "  com.google.protobuf.nano.InternalNano.$value_desc_type$);\n"
    "}\n");
}

void MapFieldGenerator::
GenerateSerializedSizeCode(io::Printer* printer) const {
  printer->Print(variables_,
    "if (this.$name$ != null) {\n"
    "  size += com.google.protobuf.nano.InternalNano.computeMapFieldSize(\n"
    "    this.$name$, $number$,\n"
    "  com.google.protobuf.nano.InternalNano.$key_desc_type$,\n"
    "  com.google.protobuf.nano.InternalNano.$value_desc_type$);\n"
    "}\n");
}

void MapFieldGenerator::
GenerateEqualsCode(io::Printer* printer) const {
  printer->Print(variables_,
    "if (!com.google.protobuf.nano.InternalNano.equals(\n"
    "  this.$name$, other.$name$)) {\n"
    "  return false;\n"
    "}\n");
}

void MapFieldGenerator::
GenerateHashCodeCode(io::Printer* printer) const {
  printer->Print(variables_,
    "result = 31 * result +\n"
    "    com.google.protobuf.nano.InternalNano.hashCode(this.$name$);\n");
}

}  // namespace javanano
}  // namespace compiler
}  // namespace protobuf
}  // namespace google

mime_type: text/plain


text:
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.  All rights reserved.
// http://code.google.com/p/protobuf/
//
// 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 <map>
#include <string>

#include <google/protobuf/compiler/javanano/javanano_params.h>
#include <google/protobuf/compiler/javanano/javanano_enum.h>
#include <google/protobuf/compiler/javanano/javanano_helpers.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/stubs/strutil.h>

namespace google {
namespace protobuf {
namespace compiler {
namespace javanano {

EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor, const Params& params)
  : params_(params), descriptor_(descriptor) {
  for (int i = 0; i < descriptor_->value_count(); i++) {
    const EnumValueDescriptor* value = descriptor_->value(i);
    const EnumValueDescriptor* canonical_value =
      descriptor_->FindValueByNumber(value->number());

    if (value == canonical_value) {
      canonical_values_.push_back(value);
    } else {
      Alias alias;
      alias.value = value;
      alias.canonical_value = canonical_value;
      aliases_.push_back(alias);
    }
  }
}

EnumGenerator::~EnumGenerator() {}

void EnumGenerator::Generate(io::Printer* printer) {
  printer->Print(
      "\n"
      "// enum $classname$\n",
      "classname", descriptor_->name());

  const string classname = RenameJavaKeywords(descriptor_->name());

  // Start of container interface
  // If generating intdefs, we use the container interface as the intdef if
  // present. Otherwise, we just make an empty @interface parallel to the
  // constants.
  bool use_intdef = params_.generate_intdefs();
  bool use_shell_class = params_.java_enum_style();
  if (use_intdef) {
    // @IntDef annotation so tools can enforce correctness
    // Annotations will be discarded by the compiler
    printer->Print("@java.lang.annotation.Retention("
      "java.lang.annotation.RetentionPolicy.SOURCE)\n"
      "@android.support.annotation.IntDef({\n");
    printer->Indent();
    for (int i = 0; i < canonical_values_.size(); i++) {
      const string constant_name =
          RenameJavaKeywords(canonical_values_[i]->name());
      if (use_shell_class) {
        printer->Print("$classname$.$name$,\n",
          "classname", classname,
          "name", constant_name);
      } else {
        printer->Print("$name$,\n", "name", constant_name);
      }
    }
    printer->Outdent();
    printer->Print("})\n");
  }
  if (use_shell_class || use_intdef) {
    printer->Print(
      "public $at_for_intdef$interface $classname$ {\n",
      "classname", classname,
      "at_for_intdef", use_intdef ? "@" : "");
    if (use_shell_class) {
        printer->Indent();
    } else {
        printer->Print("}\n\n");
    }
  }

  // Canonical values
  for (int i = 0; i < canonical_values_.size(); i++) {
    printer->Print(
      "public static final int $name$ = $canonical_value$;\n",
      "name", RenameJavaKeywords(canonical_values_[i]->name()),
      "canonical_value", SimpleItoa(canonical_values_[i]->number()));
  }

  // Aliases
  for (int i = 0; i < aliases_.size(); i++) {
    printer->Print(
      "public static final int $name$ = $canonical_name$;\n",
      "name", RenameJavaKeywords(aliases_[i].value->name()),
      "canonical_name", RenameJavaKeywords(aliases_[i].canonical_value->name()));
  }

  // End of container interface
  if (use_shell_class) {
    printer->Outdent();
    printer->Print("}\n");
  }
}

}  // namespace javanano
}  // namespace compiler
}  // namespace protobuf
}  // namespace google


text:
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.  All rights reserved.
// http://code.google.com/p/protobuf/
//
// 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/javanano/javanano_params.h>
#include <google/protobuf/compiler/javanano/javanano_generator.h>
#include <google/protobuf/compiler/javanano/javanano_file.h>
#include <google/protobuf/compiler/javanano/javanano_helpers.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/io/zero_copy_stream.h>
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/stubs/strutil.h>

namespace google {
namespace protobuf {
namespace compiler {
namespace javanano {

namespace {

string TrimString(const string& s) {
  string::size_type start = s.find_first_not_of(" \n\r\t");
  if (start == string::npos) {
    return "";
  }
  string::size_type end = s.find_last_not_of(" \n\r\t") + 1;
  return s.substr(start, end - start);
}

} // namespace

void UpdateParamsRecursively(Params& params,
    const FileDescriptor* file) {
  // Add any parameters for this file
  if (file->options().has_java_outer_classname()) {
    params.set_java_outer_classname(
      file->name(), file->options().java_outer_classname());
  }
  if (file->options().has_java_package()) {
    string result = file->options().java_package();
    if (!result.empty()) {
      result += ".";
    }
    result += "nano";
    params.set_java_package(
      file->name(), result);
  }
  if (file->options().has_java_multiple_files()) {
    params.set_java_multiple_files(
      file->name(), file->options().java_multiple_files());
  }

  // Loop through all dependent files recursively
  // adding dep
  for (int i = 0; i < file->dependency_count(); i++) {
    UpdateParamsRecursively(params, file->dependency(i));
  }
}

JavaNanoGenerator::JavaNanoGenerator() {}
JavaNanoGenerator::~JavaNanoGenerator() {}

bool JavaNanoGenerator::Generate(const FileDescriptor* file,
                             const string& parameter,
                             GeneratorContext* output_directory,
                             string* error) const {
  vector<pair<string, string> > options;

  ParseGeneratorParameter(parameter, &options);

  // -----------------------------------------------------------------
  // parse generator options

  // Name a file where we will write a list of generated file names, one
  // per line.
  string output_list_file;
  Params params(file->name());

  // Update per file params
  UpdateParamsRecursively(params, file);

  // Replace any existing options with ones from command line
  for (int i = 0; i < options.size(); i++) {
    string option_name = TrimString(options[i].first);
    string option_value = TrimString(options[i].second);
    if (option_name == "output_list_file") {
      output_list_file = option_value;
    } else if (option_name == "java_package") {
        vector<string> parts;
        SplitStringUsing(option_value, "|", &parts);
        if (parts.size() != 2) {
          *error = "Bad java_package, expecting filename|PackageName found '"
            + option_value + "'";
          return false;
        }
        params.set_java_package(parts[0], parts[1]);
    } else if (option_name == "java_outer_classname") {
        vector<string> parts;
        SplitStringUsing(option_value, "|", &parts);
        if (parts.size() != 2) {
          *error = "Bad java_outer_classname, "
                   "expecting filename|ClassName found '"
                   + option_value + "'";
          return false;
        }
        params.set_java_outer_classname(parts[0], parts[1]);
    } else if (option_name == "store_unknown_fields") {
      params.set_store_unknown_fields(option_value == "true");
    } else if (option_name == "java_multiple_files") {
      params.set_override_java_multiple_files(option_value == "true");
    } else if (option_name == "java_nano_generate_has") {
      params.set_generate_has(option_value == "true");
    } else if (option_name == "enum_style") {
      params.set_java_enum_style(option_value == "java");
    } else if (option_name == "optional_field_style") {
      params.set_optional_field_accessors(option_value == "accessors");
      params.set_use_reference_types_for_primitives(option_value == "reftypes"
          || option_value == "reftypes_compat_mode");
      params.set_reftypes_primitive_enums(
          option_value == "reftypes_compat_mode");
      if (option_value == "reftypes_compat_mode") {
        params.set_generate_clear(false);
      }
    } else if (option_name == "generate_equals") {
      params.set_generate_equals(option_value == "true");
    } else if (option_name == "ignore_services") {
      params.set_ignore_services(option_value == "true");
    } else if (option_name == "parcelable_messages") {
      params.set_parcelable_messages(option_value == "true");
    } else if (option_name == "generate_clone") {
      params.set_generate_clone(option_value == "true");
    } else if (option_name == "generate_intdefs") {
      params.set_generate_intdefs(option_value == "true");
    } else if (option_name == "generate_clear") {
      params.set_generate_clear(option_value == "true");
    } else {
      *error = "Ignore unknown javanano generator option: " + option_name;
    }
  }

  // Check illegal parameter combinations
  // Note: the enum-like optional_field_style generator param ensures
  // that we can never have illegal combinations of field styles
  // (e.g. reftypes and accessors can't be on at the same time).
  if (params.generate_has()
      && (params.optional_field_accessors()
          || params.use_reference_types_for_primitives())) {
    error->assign("java_nano_generate_has=true cannot be used in conjunction"
        " with optional_field_style=accessors or optional_field_style=reftypes");
    return false;
  }

  // -----------------------------------------------------------------

  FileGenerator file_generator(file, params);
  if (!file_generator.Validate(error)) {
    return false;
  }

  string package_dir =
    StringReplace(file_generator.java_package(), ".", "/", true);
  if (!package_dir.empty()) package_dir += "/";

  vector<string> all_files;

  if (IsOuterClassNeeded(params, file)) {
    string java_filename = package_dir;
    java_filename += file_generator.classname();
    java_filename += ".java";
    all_files.push_back(java_filename);

    // Generate main java file.
    scoped_ptr<io::ZeroCopyOutputStream> output(
      output_directory->Open(java_filename));
    io::Printer printer(output.get(), '$');
    file_generator.Generate(&printer);
  }

  // Generate sibling files.
  file_generator.GenerateSiblings(package_dir, output_directory, &all_files);

  // Generate output list if requested.
  if (!output_list_file.empty()) {
    // Generate output list.  This is just a simple text file placed in a
    // deterministic location which lists the .java files being generated.
    scoped_ptr<io::ZeroCopyOutputStream> srclist_raw_output(
      output_directory->Open(output_list_file));
    io::Printer srclist_printer(srclist_raw_output.get(), '$');
    for (int i = 0; i < all_files.size(); i++) {
      srclist_printer.Print("$filename$\n", "filename", all_files[i]);
    }
  }

  return true;
}

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


text:
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.  All rights reserved.
// http://code.google.com/p/protobuf/
//
// 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 <map>
#include <string>

#include <google/protobuf/compiler/javanano/javanano_message_field.h>
#include <google/protobuf/compiler/javanano/javanano_helpers.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/wire_format.h>
#include <google/protobuf/stubs/strutil.h>

namespace google {
namespace protobuf {
namespace compiler {
namespace javanano {

using internal::WireFormat;
using internal::WireFormatLite;

namespace {

// TODO(kenton):  Factor out a "SetCommonFieldVariables()" to get rid of
//   repeat code between this and the other field types.
void SetMessageVariables(const Params& params,
    const FieldDescriptor* descriptor, std::map<string, string>* variables) {
  (*variables)["name"] =
    RenameJavaKeywords(UnderscoresToCamelCase(descriptor));
  (*variables)["capitalized_name"] =
    RenameJavaKeywords(UnderscoresToCapitalizedCamelCase(descriptor));
  (*variables)["number"] = SimpleItoa(descriptor->number());
  (*variables)["type"] = ClassName(params, descriptor->message_type());
  (*variables)["group_or_message"] =
    (descriptor->type() == FieldDescriptor::TYPE_GROUP) ?
    "Group" : "Message";
  (*variables)["message_name"] = descriptor->containing_type()->name();
  //(*variables)["message_type"] = descriptor->message_type()->name();
  (*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor));
}

}  // namespace

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

MessageFieldGenerator::
MessageFieldGenerator(const FieldDescriptor* descriptor, const Params& params)
  : FieldGenerator(params), descriptor_(descriptor) {
  SetMessageVariables(params, descriptor, &variables_);
}

MessageFieldGenerator::~MessageFieldGenerator() {}

void MessageFieldGenerator::
GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const {
  printer->Print(variables_,
    "public $type$ $name$;\n");
}

void MessageFieldGenerator::
GenerateClearCode(io::Printer* printer) const {
  printer->Print(variables_,
    "$name$ = null;\n");
}

void MessageFieldGenerator::
GenerateMergingCode(io::Printer* printer) const {
  printer->Print(variables_,
    "if (this.$name$ == null) {\n"
    "  this.$name$ = new $type$();\n"
    "}\n");

  if (descriptor_->type() == FieldDescriptor::TYPE_GROUP) {
    printer->Print(variables_,
      "input.readGroup(this.$name$, $number$);\n");
  } else {
    printer->Print(variables_,
      "input.readMessage(this.$name$);\n");
  }
}

void MessageFieldGenerator::
GenerateSerializationCode(io::Printer* printer) const {
  printer->Print(variables_,
    "if (this.$name$ != null) {\n"
    "  output.write$group_or_message$($number$, this.$name$);\n"
    "}\n");
}

void MessageFieldGenerator::
GenerateSerializedSizeCode(io::Printer* printer) const {
  printer->Print(variables_,
    "if (this.$name$ != null) {\n"
    "  size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
    "    .compute$group_or_message$Size($number$, this.$name$);\n"
    "}\n");
}

void MessageFieldGenerator::
GenerateFixClonedCode(io::Printer* printer) const {
  printer->Print(variables_,
    "if (this.$name$ != null) {\n"
    "  cloned.$name$ = this.$name$.clone();\n"
    "}\n");
}

void MessageFieldGenerator::
GenerateEqualsCode(io::Printer* printer) const {
  printer->Print(variables_,
    "if (this.$name$ == null) { \n"
    "  if (other.$name$ != null) {\n"
    "    return false;\n"
    "  }\n"
    "} else {\n"
    "  if (!this.$name$.equals(other.$name$)) {\n"
    "    return false;\n"
    "  }\n"
    "}\n");
}

void MessageFieldGenerator::
GenerateHashCodeCode(io::Printer* printer) const {
  printer->Print(variables_,
    "result = 31 * result +\n"
    "    (this.$name$ == null ? 0 : this.$name$.hashCode());\n");
}
// ===================================================================

MessageOneofFieldGenerator::MessageOneofFieldGenerator(
    const FieldDescriptor* descriptor, const Params& params)
    : FieldGenerator(params), descriptor_(descriptor) {
    SetMessageVariables(params, descriptor, &variables_);
    SetCommonOneofVariables(descriptor, &variables_);
}

MessageOneofFieldGenerator::~MessageOneofFieldGenerator() {}

void MessageOneofFieldGenerator::
GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const {
  printer->Print(variables_,
    "public boolean has$capitalized_name$() {\n"
    "  return $has_oneof_case$;\n"
    "}\n"
    "public $type$ get$capitalized_name$() {\n"
    "  if ($has_oneof_case$) {\n"
    "    return ($type$) this.$oneof_name$_;\n"
    "  }\n"
    "  return null;\n"
    "}\n"
    "public $message_name$ set$capitalized_name$($type$ value) {\n"
    "  if (value == null) { throw new java.lang.NullPointerException(); }\n"
    "  $set_oneof_case$;\n"
    "  this.$oneof_name$_ = value;\n"
    "  return this;\n"
    "}\n");
}

void MessageOneofFieldGenerator::
GenerateClearCode(io::Printer* printer) const {
  // No clear method for oneof fields.
}

void MessageOneofFieldGenerator::
GenerateMergingCode(io::Printer* printer) const {
  printer->Print(variables_,
    "if (!($has_oneof_case$)) {\n"
    "  this.$oneof_name$_ = new $type$();\n"
    "}\n"
    "input.readMessage(\n"
    "    (com.google.protobuf.nano.MessageNano) this.$oneof_name$_);\n"
    "$set_oneof_case$;\n");
}

void MessageOneofFieldGenerator::
GenerateSerializationCode(io::Printer* printer) const {
  printer->Print(variables_,
    "if ($has_oneof_case$) {\n"
    "  output.writeMessage($number$,\n"
    "      (com.google.protobuf.nano.MessageNano) this.$oneof_name$_);\n"
    "}\n");
}

void MessageOneofFieldGenerator::
GenerateSerializedSizeCode(io::Printer* printer) const {
  printer->Print(variables_,
    "if ($has_oneof_case$) {\n"
    "  size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
    "    .computeMessageSize($number$,\n"
    "        (com.google.protobuf.nano.MessageNano) this.$oneof_name$_);\n"
    "}\n");
}

void MessageOneofFieldGenerator::
GenerateFixClonedCode(io::Printer* printer) const {
  printer->Print(variables_,
    "if (this.$oneof_name$ != null) {\n"
    "  cloned.$oneof_name$ = this.$oneof_name$.clone();\n"
    "}\n");
}

void MessageOneofFieldGenerator::
GenerateEqualsCode(io::Printer* printer) const {
  GenerateOneofFieldEquals(descriptor_, variables_, printer);
}

void MessageOneofFieldGenerator::
GenerateHashCodeCode(io::Printer* printer) const {
  GenerateOneofFieldHashCode(descriptor_, variables_, printer);
}

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

RepeatedMessageFieldGenerator::RepeatedMessageFieldGenerator(
    const FieldDescriptor* descriptor, const Params& params)
    : FieldGenerator(params), descriptor_(descriptor) {
  SetMessageVariables(params, descriptor, &variables_);
}

RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {}

void RepeatedMessageFieldGenerator::
GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const {
  printer->Print(variables_,
    "public $type$[] $name$;\n");
}

void RepeatedMessageFieldGenerator::
GenerateClearCode(io::Printer* printer) const {
  printer->Print(variables_,
    "$name$ = $type$.emptyArray();\n");
}

void RepeatedMessageFieldGenerator::
GenerateMergingCode(io::Printer* printer) const {
  // First, figure out the length of the array, then parse.
  printer->Print(variables_,
    "int arrayLength = com.google.protobuf.nano.WireFormatNano\n"
    "    .getRepeatedFieldArrayLength(input, $tag$);\n"
    "int i = this.$name$ == null ? 0 : this.$name$.length;\n"
    "$type$[] newArray =\n"
    "    new $type$[i + arrayLength];\n"
    "if (i != 0) {\n"
    "  java.lang.System.arraycopy(this.$name$, 0, newArray, 0, i);\n"
    "}\n"
    "for (; i < newArray.length - 1; i++) {\n"
    "  newArray[i] = new $type$();\n");

  if (descriptor_->type() == FieldDescriptor::TYPE_GROUP) {
    printer->Print(variables_,
      "  input.readGroup(newArray[i], $number$);\n");
  } else {
    printer->Print(variables_,
      "  input.readMessage(newArray[i]);\n");
  }

  printer->Print(variables_,
    "  input.readTag();\n"
    "}\n"
    "// Last one without readTag.\n"
    "newArray[i] = new $type$();\n");

  if (descriptor_->type() == FieldDescriptor::TYPE_GROUP) {
    printer->Print(variables_,
      "input.readGroup(newArray[i], $number$);\n");
  } else {
    printer->Print(variables_,
      "input.readMessage(newArray[i]);\n");
  }

  printer->Print(variables_,
    "this.$name$ = newArray;\n");
}

void RepeatedMessageFieldGenerator::
GenerateSerializationCode(io::Printer* printer) const {
  printer->Print(variables_,
    "if (this.$name$ != null && this.$name$.length > 0) {\n"
    "  for (int i = 0; i < this.$name$.length; i++) {\n"
    "    $type$ element = this.$name$[i];\n"
    "    if (element != null) {\n"
    "      output.write$group_or_message$($number$, element);\n"
    "    }\n"
    "  }\n"
    "}\n");
}

void RepeatedMessageFieldGenerator::
GenerateSerializedSizeCode(io::Printer* printer) const {
  printer->Print(variables_,
    "if (this.$name$ != null && this.$name$.length > 0) {\n"
    "  for (int i = 0; i < this.$name$.length; i++) {\n"
    "    $type$ element = this.$name$[i];\n"
    "    if (element != null) {\n"
    "      size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
    "        .compute$group_or_message$Size($number$, element);\n"
    "    }\n"
    "  }\n"
    "}\n");
}

void RepeatedMessageFieldGenerator::
GenerateFixClonedCode(io::Printer* printer) const {
  printer->Print(variables_,
    "if (this.$name$ != null && this.$name$.length > 0) {\n"
    "  cloned.$name$ = new $type$[this.$name$.length];\n"
    "  for (int i = 0; i < this.$name$.length; i++) {\n"
    "    if (this.$name$[i] != null) {\n"
    "      cloned.$name$[i] = this.$name$[i].clone();\n"
    "    }\n"
    "  }\n"
    "}\n");
}

void RepeatedMessageFieldGenerator::
GenerateEqualsCode(io::Printer* printer) const {
  printer->Print(variables_,
    "if (!com.google.protobuf.nano.InternalNano.equals(\n"
    "    this.$name$, other.$name$)) {\n"
    "  return false;\n"
    "}\n");
}

void RepeatedMessageFieldGenerator::
GenerateHashCodeCode(io::Printer* printer) const {
  printer->Print(variables_,
    "result = 31 * result\n"
    "    + com.google.protobuf.nano.InternalNano.hashCode(this.$name$);\n");
}

}  // namespace javanano
}  // namespace compiler
}  // namespace protobuf
}  // namespace google


text:
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.  All rights reserved.
// http://code.google.com/p/protobuf/
//
// 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: bduff@google.com (Brian Duff)
//  Based on original Protocol Buffers design by
//  Sanjay Ghemawat, Jeff Dean, and others.

#ifndef GOOGLE_PROTOBUF_COMPILER_JAVANANO_EXTENSION_H_
#define GOOGLE_PROTOBUF_COMPILER_JAVANANO_EXTENSION_H_

#include <google/protobuf/stubs/common.h>
#include <google/protobuf/compiler/javanano/javanano_params.h>
#include <google/protobuf/descriptor.pb.h>

namespace google {
namespace protobuf {
  namespace io {
    class Printer;             // printer.h
  }
}

namespace protobuf {
namespace compiler {
namespace javanano {

class ExtensionGenerator {
 public:
  explicit ExtensionGenerator(const FieldDescriptor* descriptor, const Params& params);
  ~ExtensionGenerator();

  void Generate(io::Printer* printer) const;

 private:
  const Params& params_;
  const FieldDescriptor* descriptor_;
  std::map<string, string> variables_;

  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ExtensionGenerator);
};

}  // namespace javanano
}  // namespace compiler
}  // namespace protobuf
}  // namespace google

#endif  // GOOGLE_PROTOBUF_COMPILER_JAVANANO_EXTENSION_H_


text:
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.  All rights reserved.
// http://code.google.com/p/protobuf/
//
// 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_JAVANANO_ENUM_H__
#define GOOGLE_PROTOBUF_COMPILER_JAVANANO_ENUM_H__

#include <string>
#include <vector>

#include <google/protobuf/compiler/javanano/javanano_params.h>
#include <google/protobuf/descriptor.h>

namespace google {
namespace protobuf {
  namespace io {
    class Printer;             // printer.h
  }
}

namespace protobuf {
namespace compiler {
namespace javanano {

class EnumGenerator {
 public:
  explicit EnumGenerator(const EnumDescriptor* descriptor, const Params& params);
  ~EnumGenerator();

  void Generate(io::Printer* printer);

 private:
  const Params& params_;
  const EnumDescriptor* descriptor_;

  // The proto language allows multiple enum constants to have the same numeric
  // value.  Java, however, does not allow multiple enum constants to be
  // considered equivalent.  We treat the first defined constant for any
  // given numeric value as "canonical" and the rest as aliases of that
  // canonical value.
  vector<const EnumValueDescriptor*> canonical_values_;

  struct Alias {
    const EnumValueDescriptor* value;
    const EnumValueDescriptor* canonical_value;
  };
  vector<Alias> aliases_;

  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumGenerator);
};

}  // namespace javanano
}  // namespace compiler
}  // namespace protobuf

}  // namespace google
#endif  // GOOGLE_PROTOBUF_COMPILER_JAVANANO_ENUM_H__


text:
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.  All rights reserved.
// http://code.google.com/p/protobuf/
//
// 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: bduff@google.com (Brian Duff)

#include <google/protobuf/compiler/javanano/javanano_extension.h>
#include <google/protobuf/compiler/javanano/javanano_helpers.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/wire_format.h>

namespace google {
namespace protobuf {
namespace compiler {
namespace javanano {

using internal::WireFormat;
using internal::WireFormatLite;

namespace {

const char* GetTypeConstantName(const FieldDescriptor::Type type) {
  switch (type) {
    case FieldDescriptor::TYPE_INT32   : return "TYPE_INT32"   ;
    case FieldDescriptor::TYPE_UINT32  : return "TYPE_UINT32"  ;
    case FieldDescriptor::TYPE_SINT32  : return "TYPE_SINT32"  ;
    case FieldDescriptor::TYPE_FIXED32 : return "TYPE_FIXED32" ;
    case FieldDescriptor::TYPE_SFIXED32: return "TYPE_SFIXED32";
    case FieldDescriptor::TYPE_INT64   : return "TYPE_INT64"   ;
    case FieldDescriptor::TYPE_UINT64  : return "TYPE_UINT64"  ;
    case FieldDescriptor::TYPE_SINT64  : return "TYPE_SINT64"  ;
    case FieldDescriptor::TYPE_FIXED64 : return "TYPE_FIXED64" ;
    case FieldDescriptor::TYPE_SFIXED64: return "TYPE_SFIXED64";
    case FieldDescriptor::TYPE_FLOAT   : return "TYPE_FLOAT"   ;
    case FieldDescriptor::TYPE_DOUBLE  : return "TYPE_DOUBLE"  ;
    case FieldDescriptor::TYPE_BOOL    : return "TYPE_BOOL"    ;
    case FieldDescriptor::TYPE_STRING  : return "TYPE_STRING"  ;
    case FieldDescriptor::TYPE_BYTES   : return "TYPE_BYTES"   ;
    case FieldDescriptor::TYPE_ENUM    : return "TYPE_ENUM"    ;
    case FieldDescriptor::TYPE_GROUP   : return "TYPE_GROUP"   ;
    case FieldDescriptor::TYPE_MESSAGE : return "TYPE_MESSAGE" ;

    // No default because we want the compiler to complain if any new
    // types are added.
  }

  GOOGLE_LOG(FATAL) << "Can't get here.";
  return NULL;
}

}  // namespace

void SetVariables(const FieldDescriptor* descriptor, const Params params,
                  std::map<string, string>* variables) {
  (*variables)["extends"] = ClassName(params, descriptor->containing_type());
  (*variables)["name"] = RenameJavaKeywords(UnderscoresToCamelCase(descriptor));
  bool repeated = descriptor->is_repeated();
  (*variables)["repeated"] = repeated ? "Repeated" : "";
  (*variables)["type"] = GetTypeConstantName(descriptor->type());
  JavaType java_type = GetJavaType(descriptor->type());
  string tag = SimpleItoa(WireFormat::MakeTag(descriptor));
  if (java_type == JAVATYPE_MESSAGE) {
    (*variables)["ext_type"] = "MessageTyped";
    string message_type = ClassName(params, descriptor->message_type());
    if (repeated) {
      message_type += "[]";
    }
    (*variables)["class"] = message_type;
    // For message typed extensions, tags_params contains a single tag
    // for both singular and repeated cases.
    (*variables)["tag_params"] = tag;
  } else {
    (*variables)["ext_type"] = "PrimitiveTyped";
    if (!repeated) {
      (*variables)["class"] = BoxedPrimitiveTypeName(java_type);
      (*variables)["tag_params"] = tag;
    } else {
      (*variables)["class"] = PrimitiveTypeName(java_type) + "[]";
      if (!descriptor->is_packable()) {
        // Non-packable: nonPackedTag == tag, packedTag == 0
        (*variables)["tag_params"] = tag + ", " + tag + ", 0";
      } else if (descriptor->options().packed()) {
        // Packable and packed: tag == packedTag
        string non_packed_tag = SimpleItoa(WireFormatLite::MakeTag(
            descriptor->number(),
            WireFormat::WireTypeForFieldType(descriptor->type())));
        (*variables)["tag_params"] = tag + ", " + non_packed_tag + ", " + tag;
      } else {
        // Packable and not packed: tag == nonPackedTag
        string packed_tag = SimpleItoa(WireFormatLite::MakeTag(
            descriptor->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED));
        (*variables)["tag_params"] = tag + ", " + tag + ", " + packed_tag;
      }
    }
  }
}

ExtensionGenerator::
ExtensionGenerator(const FieldDescriptor* descriptor, const Params& params)
  : params_(params), descriptor_(descriptor) {
  SetVariables(descriptor, params, &variables_);
}

ExtensionGenerator::~ExtensionGenerator() {}

void ExtensionGenerator::Generate(io::Printer* printer) const {
  printer->Print("\n");
  PrintFieldComment(printer, descriptor_);
  printer->Print(variables_,
    "public static final com.google.protobuf.nano.Extension<\n"
    "    $extends$,\n"
    "    $class$> $name$ =\n"
    "        com.google.protobuf.nano.Extension.create$repeated$$ext_type$(\n"
    "            com.google.protobuf.nano.Extension.$type$,\n"
    "            $class$.class,\n"
    "            $tag_params$L);\n");
}

}  // namespace javanano
}  // namespace compiler
}  // namespace protobuf
}  // namespace google


text:
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.  All rights reserved.
// http://code.google.com/p/protobuf/
//
// 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_JAVANANO_MESSAGE_FIELD_H__
#define GOOGLE_PROTOBUF_COMPILER_JAVANANO_MESSAGE_FIELD_H__

#include <map>
#include <string>
#include <google/protobuf/compiler/javanano/javanano_field.h>

namespace google {
namespace protobuf {
namespace compiler {
namespace javanano {

class MessageFieldGenerator : public FieldGenerator {
 public:
  explicit MessageFieldGenerator(
      const FieldDescriptor* descriptor, const Params& params);
  ~MessageFieldGenerator();

  // implements FieldGenerator ---------------------------------------
  void GenerateMembers(io::Printer* printer, bool lazy_init) const;
  void GenerateClearCode(io::Printer* printer) const;
  void GenerateMergingCode(io::Printer* printer) const;
  void GenerateSerializationCode(io::Printer* printer) const;
  void GenerateSerializedSizeCode(io::Printer* printer) const;
  void GenerateEqualsCode(io::Printer* printer) const;
  void GenerateHashCodeCode(io::Printer* printer) const;
  void GenerateFixClonedCode(io::Printer* printer) const;

 private:
  const FieldDescriptor* descriptor_;
  std::map<string, string> variables_;

  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageFieldGenerator);
};

class MessageOneofFieldGenerator : public FieldGenerator {
 public:
  explicit MessageOneofFieldGenerator(const FieldDescriptor* descriptor,
                                      const Params& params);
  ~MessageOneofFieldGenerator();

  // implements FieldGenerator ---------------------------------------
  void GenerateMembers(io::Printer* printer, bool lazy_init) const;
  void GenerateClearCode(io::Printer* printer) const;
  void GenerateMergingCode(io::Printer* printer) const;
  void GenerateSerializationCode(io::Printer* printer) const;
  void GenerateSerializedSizeCode(io::Printer* printer) const;
  void GenerateEqualsCode(io::Printer* printer) const;
  void GenerateHashCodeCode(io::Printer* printer) const;
  void GenerateFixClonedCode(io::Printer* printer) const;

 private:
  const FieldDescriptor* descriptor_;
  std::map<string, string> variables_;

  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageOneofFieldGenerator);
};

class RepeatedMessageFieldGenerator : public FieldGenerator {
 public:
  explicit RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor,
        const Params& params);
  ~RepeatedMessageFieldGenerator();

  // implements FieldGenerator ---------------------------------------
  void GenerateMembers(io::Printer* printer, bool lazy_init) const;
  void GenerateClearCode(io::Printer* printer) const;
  void GenerateMergingCode(io::Printer* printer) const;
  void GenerateSerializationCode(io::Printer* printer) const;
  void GenerateSerializedSizeCode(io::Printer* printer) const;
  void GenerateEqualsCode(io::Printer* printer) const;
  void GenerateHashCodeCode(io::Printer* printer) const;
  void GenerateFixClonedCode(io::Printer* printer) const;

 private:
  const FieldDescriptor* descriptor_;
  std::map<string, string> variables_;

  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedMessageFieldGenerator);
};

}  // namespace javanano
}  // namespace compiler
}  // namespace protobuf

}  // namespace google
#endif  // GOOGLE_PROTOBUF_COMPILER_JAVANANO_MESSAGE_FIELD_H__


text:
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.  All rights reserved.
// http://code.google.com/p/protobuf/
//
// 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.
//
// Generates Java nano code for a given .proto file.

#ifndef GOOGLE_PROTOBUF_COMPILER_JAVANANO_NANO_GENERATOR_H__
#define GOOGLE_PROTOBUF_COMPILER_JAVANANO_NANO_GENERATOR_H__

#include <string>
#include <google/protobuf/compiler/code_generator.h>

namespace google {
namespace protobuf {
namespace compiler {
namespace javanano {

// CodeGenerator implementation which generates Java nano code.  If you create your
// own protocol compiler binary and you want it to support Java output for the
// nano runtime, you can do so by registering an instance of this CodeGenerator with
// the CommandLineInterface in your main() function.
class LIBPROTOC_EXPORT JavaNanoGenerator : public CodeGenerator {
 public:
  JavaNanoGenerator();
  ~JavaNanoGenerator();

  // implements CodeGenerator ----------------------------------------
  bool Generate(const FileDescriptor* file,
                const string& parameter,
                GeneratorContext* output_directory,
                string* error) const;

 private:
  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(JavaNanoGenerator);
};

}  // namespace javanano
}  // namespace compiler
}  // namespace protobuf

}  // namespace google
#endif  // GOOGLE_PROTOBUF_COMPILER_JAVANANO_NANO_GENERATOR_H__


text:
// Protocol Buffers - Google's data interchange format
// Copyright 2010 Google Inc.  All rights reserved.
// http://code.google.com/p/protobuf/
//
// 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: wink@google.com (Wink Saville)

#ifndef PROTOBUF_COMPILER_JAVANANO_JAVANANO_PARAMS_H_
#define PROTOBUF_COMPILER_JAVANANO_JAVANANO_PARAMS_H_

#include <map>
#include <set>
#include <google/protobuf/stubs/strutil.h>

namespace google {
namespace protobuf {
namespace compiler {
namespace javanano {

enum eMultipleFiles { JAVANANO_MUL_UNSET, JAVANANO_MUL_FALSE, JAVANANO_MUL_TRUE };

// Parameters for used by the generators
class Params {
 public:
  typedef std::map<string, string> NameMap;
  typedef std::set<string> NameSet;
 private:
  string empty_;
  string base_name_;
  eMultipleFiles override_java_multiple_files_;
  bool store_unknown_fields_;
  NameMap java_packages_;
  NameMap java_outer_classnames_;
  NameSet java_multiple_files_;
  bool generate_has_;
  bool java_enum_style_;
  bool optional_field_accessors_;
  bool use_reference_types_for_primitives_;
  bool generate_equals_;
  bool ignore_services_;
  bool parcelable_messages_;
  bool reftypes_primitive_enums_;
  bool generate_clear_;
  bool generate_clone_;
  bool generate_intdefs_;

 public:
  Params(const string & base_name) :
    empty_(""),
    base_name_(base_name),
    override_java_multiple_files_(JAVANANO_MUL_UNSET),
    store_unknown_fields_(false),
    generate_has_(false),
    java_enum_style_(false),
    optional_field_accessors_(false),
    use_reference_types_for_primitives_(false),
    generate_equals_(false),
    ignore_services_(false),
    parcelable_messages_(false),
    reftypes_primitive_enums_(false),
    generate_clear_(true),
    generate_clone_(false),
    generate_intdefs_(false) {
  }

  const string& base_name() const {
    return base_name_;
  }

  bool has_java_package(const string& file_name) const {
    return java_packages_.find(file_name)
                        != java_packages_.end();
  }
  void set_java_package(const string& file_name,
      const string& java_package) {
    java_packages_[file_name] = java_package;
  }
  const string& java_package(const string& file_name) const {
    NameMap::const_iterator itr;

    itr = java_packages_.find(file_name);
    if  (itr == java_packages_.end()) {
      return empty_;
    } else {
      return itr->second;
    }
  }
  const NameMap& java_packages() {
    return java_packages_;
  }

  bool has_java_outer_classname(const string& file_name) const {
    return java_outer_classnames_.find(file_name)
                        != java_outer_classnames_.end();
  }
  void set_java_outer_classname(const string& file_name,
      const string& java_outer_classname) {
    java_outer_classnames_[file_name] = java_outer_classname;
  }
  const string& java_outer_classname(const string& file_name) const {
    NameMap::const_iterator itr;

    itr = java_outer_classnames_.find(file_name);
    if  (itr == java_outer_classnames_.end()) {
      return empty_;
    } else {
      return itr->second;
    }
  }
  const NameMap& java_outer_classnames() {
    return java_outer_classnames_;
  }

  void set_override_java_multiple_files(bool java_multiple_files) {
    if (java_multiple_files) {
      override_java_multiple_files_ = JAVANANO_MUL_TRUE;
    } else {
      override_java_multiple_files_ = JAVANANO_MUL_FALSE;
    }
  }
  void clear_override_java_multiple_files() {
    override_java_multiple_files_ = JAVANANO_MUL_UNSET;
  }

  void set_java_multiple_files(const string& file_name, bool value) {
    if (value) {
      java_multiple_files_.insert(file_name);
    } else {
      java_multiple_files_.erase(file_name);
    }
  }
  bool java_multiple_files(const string& file_name) const {
    switch (override_java_multiple_files_) {
      case JAVANANO_MUL_FALSE:
        return false;
      case JAVANANO_MUL_TRUE:
        return true;
      default:
        return java_multiple_files_.find(file_name)
                != java_multiple_files_.end();
    }
  }

  void set_store_unknown_fields(bool value) {
    store_unknown_fields_ = value;
  }
  bool store_unknown_fields() const {
    return store_unknown_fields_;
  }

  void set_generate_has(bool value) {
    generate_has_ = value;
  }
  bool generate_has() const {
    return generate_has_;
  }

  void set_java_enum_style(bool value) {
    java_enum_style_ = value;
  }
  bool java_enum_style() const {
    return java_enum_style_;
  }

  void set_optional_field_accessors(bool value) {
    optional_field_accessors_ = value;
  }
  bool optional_field_accessors() const {
    return optional_field_accessors_;
  }

  void set_use_reference_types_for_primitives(bool value) {
    use_reference_types_for_primitives_ = value;
  }
  bool use_reference_types_for_primitives() const {
    return use_reference_types_for_primitives_;
  }

  void set_generate_equals(bool value) {
    generate_equals_ = value;
  }
  bool generate_equals() const {
    return generate_equals_;
  }

  void set_ignore_services(bool value) {
    ignore_services_ = value;
  }
  bool ignore_services() const {
    return ignore_services_;
  }

  void set_parcelable_messages(bool value) {
    parcelable_messages_ = value;
  }
  bool parcelable_messages() const {
    return parcelable_messages_;
  }

  void set_reftypes_primitive_enums(bool value) {
    reftypes_primitive_enums_ = value;
  }
  bool reftypes_primitive_enums() const {
    return reftypes_primitive_enums_;
  }

  void set_generate_clear(bool value) {
    generate_clear_ = value;
  }
  bool generate_clear() const {
    return generate_clear_;
  }

  void set_generate_clone(bool value) {
    generate_clone_ = value;
  }
  bool generate_clone() const {
    return generate_clone_;
  }

  void set_generate_intdefs(bool value) {
    generate_intdefs_ = value;
  }
  bool generate_intdefs() const {
    return generate_intdefs_;
  }
};

}  // namespace javanano
}  // namespace compiler
}  // namespace protobuf
}  // namespace google
#endif  // PROTOBUF_COMPILER_JAVANANO_JAVANANO_PARAMS_H_


text:
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.  All rights reserved.
// http://code.google.com/p/protobuf/
//
// 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_JAVANANO_FIELD_H__
#define GOOGLE_PROTOBUF_COMPILER_JAVANANO_FIELD_H__

#include <map>
#include <string>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/compiler/javanano/javanano_params.h>

namespace google {
namespace protobuf {
  namespace io {
    class Printer;             // printer.h
  }
}

namespace protobuf {
namespace compiler {
namespace javanano {

class FieldGenerator {
 public:
  FieldGenerator(const Params& params) : params_(params) {}
  virtual ~FieldGenerator();

  virtual bool SavedDefaultNeeded() const;
  virtual void GenerateInitSavedDefaultCode(io::Printer* printer) const;

  // Generates code for Java fields and methods supporting this field.
  // If this field needs a saved default (SavedDefaultNeeded() is true),
  // then @lazy_init controls how the static field for that default value
  // and its initialization code should be generated. If @lazy_init is
  // true, the static field is not declared final and the initialization
  // code is generated only when GenerateInitSavedDefaultCode is called;
  // otherwise, the static field is declared final and initialized inline.
  // GenerateInitSavedDefaultCode will not be called in the latter case.
  virtual void GenerateMembers(
      io::Printer* printer, bool lazy_init) const = 0;

  virtual void GenerateClearCode(io::Printer* printer) const = 0;
  virtual void GenerateMergingCode(io::Printer* printer) const = 0;

  // Generates code to merge from packed serialized form. The default
  // implementation will fail; subclasses which can handle packed serialized
  // forms will override this and print appropriate code to the printer.
  virtual void GenerateMergingCodeFromPacked(io::Printer* printer) const;

  virtual void GenerateSerializationCode(io::Printer* printer) const = 0;
  virtual void GenerateSerializedSizeCode(io::Printer* printer) const = 0;
  virtual void GenerateEqualsCode(io::Printer* printer) const = 0;
  virtual void GenerateHashCodeCode(io::Printer* printer) const = 0;
  virtual void GenerateFixClonedCode(io::Printer* printer) const {}

 protected:
  const Params& params_;
 private:
  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGenerator);
};

// Convenience class which constructs FieldGenerators for a Descriptor.
class FieldGeneratorMap {
 public:
  explicit FieldGeneratorMap(const Descriptor* descriptor, const Params &params);
  ~FieldGeneratorMap();

  const FieldGenerator& get(const FieldDescriptor* field) const;
  int total_bits() const { return total_bits_; }
  bool saved_defaults_needed() const { return saved_defaults_needed_; }

 private:
  const Descriptor* descriptor_;
  scoped_array<scoped_ptr<FieldGenerator> > field_generators_;
  int total_bits_;
  bool saved_defaults_needed_;

  static FieldGenerator* MakeGenerator(const FieldDescriptor* field,
      const Params &params, int* next_has_bit_index);

  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGeneratorMap);
};

void SetCommonOneofVariables(const FieldDescriptor* descriptor,
                             std::map<string, string>* variables);
void GenerateOneofFieldEquals(const FieldDescriptor* descriptor,
                              const std::map<string, string>& variables,
                              io::Printer* printer);
void GenerateOneofFieldHashCode(const FieldDescriptor* descriptor,
                                const std::map<string, string>& variables,
                                io::Printer* printer);

}  // namespace javanano
}  // namespace compiler
}  // namespace protobuf

}  // namespace google
#endif  // GOOGLE_PROTOBUF_COMPILER_JAVANANO_FIELD_H__