// 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: xiaofeng@google.com (Feng Xiao)

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

#include <memory>

#include <google/protobuf/compiler/code_generator.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/io/zero_copy_stream.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/compiler/java/helpers.h>
#include <google/protobuf/compiler/java/name_resolver.h>
#include <google/protobuf/compiler/java/names.h>
#include <google/protobuf/descriptor.pb.h>

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

SharedCodeGenerator::SharedCodeGenerator(const FileDescriptor* file,
                                         const Options& options)
    : name_resolver_(new ClassNameResolver), file_(file), options_(options) {}

SharedCodeGenerator::~SharedCodeGenerator() {}

void SharedCodeGenerator::Generate(
    GeneratorContext* context, std::vector<std::string>* file_list,
    std::vector<std::string>* annotation_file_list) {
  std::string java_package = FileJavaPackage(file_);
  std::string package_dir = JavaPackageToDir(java_package);

  if (HasDescriptorMethods(file_, options_.enforce_lite)) {
    // Generate descriptors.
    std::string classname = name_resolver_->GetDescriptorClassName(file_);
    std::string filename = package_dir + classname + ".java";
    file_list->push_back(filename);
    std::unique_ptr<io::ZeroCopyOutputStream> output(context->Open(filename));
    GeneratedCodeInfo annotations;
    io::AnnotationProtoCollector<GeneratedCodeInfo> annotation_collector(
        &annotations);
    std::unique_ptr<io::Printer> printer(
        new io::Printer(output.get(), '$',
                        options_.annotate_code ? &annotation_collector : NULL));
    std::string info_relative_path = classname + ".java.pb.meta";
    std::string info_full_path = filename + ".pb.meta";
    printer->Print(
        "// Generated by the protocol buffer compiler.  DO NOT EDIT!\n"
        "// source: $filename$\n"
        "\n",
        "filename", file_->name());
    if (!java_package.empty()) {
      printer->Print(
          "package $package$;\n"
          "\n",
          "package", java_package);
    }
    PrintGeneratedAnnotation(printer.get(), '$',
                             options_.annotate_code ? info_relative_path : "");
    printer->Print(
        "public final class $classname$ {\n"
        "  public static com.google.protobuf.Descriptors.FileDescriptor\n"
        "      descriptor;\n"
        "  static {\n",
        "classname", classname);
    printer->Annotate("classname", file_->name());
    printer->Indent();
    printer->Indent();
    GenerateDescriptors(printer.get());
    printer->Outdent();
    printer->Outdent();
    printer->Print(
        "  }\n"
        "}\n");

    if (options_.annotate_code) {
      std::unique_ptr<io::ZeroCopyOutputStream> info_output(
          context->Open(info_full_path));
      annotations.SerializeToZeroCopyStream(info_output.get());
      annotation_file_list->push_back(info_full_path);
    }

    printer.reset();
    output.reset();
  }
}

void SharedCodeGenerator::GenerateDescriptors(io::Printer* printer) {
  // Embed the descriptor.  We simply serialize the entire FileDescriptorProto
  // and embed it as a string literal, which is parsed and built into real
  // descriptors at initialization time.  We unfortunately have to put it in
  // a string literal, not a byte array, because apparently using a literal
  // byte array causes the Java compiler to generate *instructions* to
  // initialize each and every byte of the array, e.g. as if you typed:
  //   b[0] = 123; b[1] = 456; b[2] = 789;
  // This makes huge bytecode files and can easily hit the compiler's internal
  // code size limits (error "code to large").  String literals are apparently
  // embedded raw, which is what we want.
  FileDescriptorProto file_proto;
  file_->CopyTo(&file_proto);

  std::string file_data;
  file_proto.SerializeToString(&file_data);

  printer->Print("java.lang.String[] descriptorData = {\n");
  printer->Indent();

  // Limit the number of bytes per line.
  static const int kBytesPerLine = 40;
  // Limit the number of lines per string part.
  static const int kLinesPerPart = 400;
  // Every block of bytes, start a new string literal, in order to avoid the
  // 64k length limit. Note that this value needs to be <64k.
  static const int kBytesPerPart = kBytesPerLine * kLinesPerPart;
  for (int i = 0; i < file_data.size(); i += kBytesPerLine) {
    if (i > 0) {
      if (i % kBytesPerPart == 0) {
        printer->Print(",\n");
      } else {
        printer->Print(" +\n");
      }
    }
    printer->Print("\"$data$\"", "data",
                   CEscape(file_data.substr(i, kBytesPerLine)));
  }

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

  // -----------------------------------------------------------------
  // Find out all dependencies.
  std::vector<std::pair<std::string, std::string> > dependencies;
  for (int i = 0; i < file_->dependency_count(); i++) {
    std::string filename = file_->dependency(i)->name();
    std::string package = FileJavaPackage(file_->dependency(i));
    std::string classname =
        name_resolver_->GetDescriptorClassName(file_->dependency(i));
    std::string full_name;
    if (package.empty()) {
      full_name = classname;
    } else {
      full_name = package + "." + classname;
    }
    dependencies.push_back(std::make_pair(filename, full_name));
  }

  // -----------------------------------------------------------------
  // Invoke internalBuildGeneratedFileFrom() to build the file.
  printer->Print(
      "descriptor = com.google.protobuf.Descriptors.FileDescriptor\n"
      "  .internalBuildGeneratedFileFrom(descriptorData,\n");
  printer->Print(
      "    new com.google.protobuf.Descriptors.FileDescriptor[] {\n");

  for (int i = 0; i < dependencies.size(); i++) {
    const std::string& dependency = dependencies[i].second;
    printer->Print("      $dependency$.getDescriptor(),\n", "dependency",
                   dependency);
  }

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

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