164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci// Protocol Buffers - Google's data interchange format
264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci// Copyright 2008 Google Inc.  All rights reserved.
364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci// http://code.google.com/p/protobuf/
464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci//
564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci// Redistribution and use in source and binary forms, with or without
664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci// modification, are permitted provided that the following conditions are
764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci// met:
864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci//
964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci//     * Redistributions of source code must retain the above copyright
1064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci// notice, this list of conditions and the following disclaimer.
1164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci//     * Redistributions in binary form must reproduce the above
1264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci// copyright notice, this list of conditions and the following disclaimer
1364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci// in the documentation and/or other materials provided with the
1464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci// distribution.
1564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci//     * Neither the name of Google Inc. nor the names of its
1664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci// contributors may be used to endorse or promote products derived from
1764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci// this software without specific prior written permission.
1864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci//
1964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci
3164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci// Author: kenton@google.com (Kenton Varda)
3264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci//  Based on original Protocol Buffers design by
3364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci//  Sanjay Ghemawat, Jeff Dean, and others.
3464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci
3564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci#include <google/protobuf/compiler/javanano/javanano_params.h>
3664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci#include <google/protobuf/compiler/javanano/javanano_generator.h>
3764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci#include <google/protobuf/compiler/javanano/javanano_file.h>
3864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci#include <google/protobuf/compiler/javanano/javanano_helpers.h>
3964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci#include <google/protobuf/io/printer.h>
4064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci#include <google/protobuf/io/zero_copy_stream.h>
4164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci#include <google/protobuf/descriptor.pb.h>
4264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci#include <google/protobuf/stubs/strutil.h>
4364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci
4464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazcinamespace google {
4564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazcinamespace protobuf {
4664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazcinamespace compiler {
4764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazcinamespace javanano {
4864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci
4964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazcivoid UpdateParamsRecursively(Params& params,
5064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    const FileDescriptor* file) {
5164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  // Add any parameters for this file
5264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  if (file->options().has_java_outer_classname()) {
5364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    params.set_java_outer_classname(
5464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci      file->name(), file->options().java_outer_classname());
5564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  }
5664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  if (file->options().has_java_package()) {
5764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    params.set_java_package(
5864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci      file->name(), file->options().java_package());
5964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  }
608170787391efcb6cc6a8babc1cce35d5b1aff420Max Cai  if (file->options().has_java_multiple_files()) {
618170787391efcb6cc6a8babc1cce35d5b1aff420Max Cai    params.set_java_multiple_files(
628170787391efcb6cc6a8babc1cce35d5b1aff420Max Cai      file->name(), file->options().java_multiple_files());
638170787391efcb6cc6a8babc1cce35d5b1aff420Max Cai  }
6464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci
6564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  // Loop through all dependent files recursively
6664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  // adding dep
6764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  for (int i = 0; i < file->dependency_count(); i++) {
6864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    UpdateParamsRecursively(params, file->dependency(i));
6964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  }
7064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci}
7164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci
7264d8d8f89050c5ada85341f967af391f4716a7cbUlas KirazciJavaNanoGenerator::JavaNanoGenerator() {}
7364d8d8f89050c5ada85341f967af391f4716a7cbUlas KirazciJavaNanoGenerator::~JavaNanoGenerator() {}
7464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci
7564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazcibool JavaNanoGenerator::Generate(const FileDescriptor* file,
7664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci                             const string& parameter,
7764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci                             OutputDirectory* output_directory,
7864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci                             string* error) const {
7964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  vector<pair<string, string> > options;
8064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci
8164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  ParseGeneratorParameter(parameter, &options);
8264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci
8364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  // -----------------------------------------------------------------
8464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  // parse generator options
8564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci
8664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  // Name a file where we will write a list of generated file names, one
8764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  // per line.
8864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  string output_list_file;
8964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  Params params(file->name());
9064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci
9164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  // Update per file params
9264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  UpdateParamsRecursively(params, file);
9364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci
9464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  // Replace any existing options with ones from command line
9564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  for (int i = 0; i < options.size(); i++) {
9664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    if (options[i].first == "output_list_file") {
9764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci      output_list_file = options[i].second;
9864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    } else if (options[i].first == "java_package") {
9964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci        vector<string> parts;
10064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci        SplitStringUsing(options[i].second, "|", &parts);
10164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci        if (parts.size() != 2) {
10264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci          *error = "Bad java_package, expecting filename|PackageName found '"
10364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci            + options[i].second + "'";
10464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci          return false;
10564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci        }
10664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci        params.set_java_package(parts[0], parts[1]);
10764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    } else if (options[i].first == "java_outer_classname") {
10864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci        vector<string> parts;
10964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci        SplitStringUsing(options[i].second, "|", &parts);
11064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci        if (parts.size() != 2) {
11164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci          *error = "Bad java_outer_classname, "
11264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci                   "expecting filename|ClassName found '"
11364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci                   + options[i].second + "'";
11464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci          return false;
11564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci        }
11664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci        params.set_java_outer_classname(parts[0], parts[1]);
1170e055f079f53b07de3705838a7b4742ce56839f8Brian Duff    } else if (options[i].first == "store_unknown_fields") {
1180e055f079f53b07de3705838a7b4742ce56839f8Brian Duff      params.set_store_unknown_fields(options[i].second == "true");
11964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    } else if (options[i].first == "java_multiple_files") {
1208170787391efcb6cc6a8babc1cce35d5b1aff420Max Cai      params.set_override_java_multiple_files(options[i].second == "true");
12135d9fd84ff1d9ecdb91156b757cc9fdcc3f25249Ulas Kirazci    } else if (options[i].first == "java_nano_generate_has") {
12235d9fd84ff1d9ecdb91156b757cc9fdcc3f25249Ulas Kirazci        params.set_generate_has(options[i].second == "true");
12364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    } else {
12464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci      *error = "Ignore unknown javanano generator option: " + options[i].first;
12564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    }
12664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  }
12764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci
12864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  // -----------------------------------------------------------------
12964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci
13064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  FileGenerator file_generator(file, params);
13164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  if (!file_generator.Validate(error)) {
13264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    return false;
13364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  }
13464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci
13564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  string package_dir =
13664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    StringReplace(file_generator.java_package(), ".", "/", true);
13764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  if (!package_dir.empty()) package_dir += "/";
13864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci
13964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  vector<string> all_files;
14064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci
141624c448fbef20a1a2fad2289f622b468c25763d1Max Cai  if (IsOuterClassNeeded(params, file)) {
142624c448fbef20a1a2fad2289f622b468c25763d1Max Cai    string java_filename = package_dir;
143624c448fbef20a1a2fad2289f622b468c25763d1Max Cai    java_filename += file_generator.classname();
144624c448fbef20a1a2fad2289f622b468c25763d1Max Cai    java_filename += ".java";
145624c448fbef20a1a2fad2289f622b468c25763d1Max Cai    all_files.push_back(java_filename);
146624c448fbef20a1a2fad2289f622b468c25763d1Max Cai
147624c448fbef20a1a2fad2289f622b468c25763d1Max Cai    // Generate main java file.
148624c448fbef20a1a2fad2289f622b468c25763d1Max Cai    scoped_ptr<io::ZeroCopyOutputStream> output(
149624c448fbef20a1a2fad2289f622b468c25763d1Max Cai      output_directory->Open(java_filename));
150624c448fbef20a1a2fad2289f622b468c25763d1Max Cai    io::Printer printer(output.get(), '$');
151624c448fbef20a1a2fad2289f622b468c25763d1Max Cai    file_generator.Generate(&printer);
152624c448fbef20a1a2fad2289f622b468c25763d1Max Cai  }
15364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci
15464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  // Generate sibling files.
15564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  file_generator.GenerateSiblings(package_dir, output_directory, &all_files);
15664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci
15764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  // Generate output list if requested.
15864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  if (!output_list_file.empty()) {
15964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    // Generate output list.  This is just a simple text file placed in a
16064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    // deterministic location which lists the .java files being generated.
16164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    scoped_ptr<io::ZeroCopyOutputStream> srclist_raw_output(
16264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci      output_directory->Open(output_list_file));
16364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    io::Printer srclist_printer(srclist_raw_output.get(), '$');
16464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    for (int i = 0; i < all_files.size(); i++) {
16564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci      srclist_printer.Print("$filename$\n", "filename", all_files[i]);
16664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    }
16764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  }
16864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci
16964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  return true;
17064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci}
17164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci
17264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci}  // namespace java
17364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci}  // namespace compiler
17464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci}  // namespace protobuf
17564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci}  // namespace google
176