1e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville// Protocol Buffers - Google's data interchange format
2e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville// Copyright 2008 Google Inc.  All rights reserved.
3e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville// http://code.google.com/p/protobuf/
4e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville//
5e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville// Redistribution and use in source and binary forms, with or without
6e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville// modification, are permitted provided that the following conditions are
7e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville// met:
8e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville//
9e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville//     * Redistributions of source code must retain the above copyright
10e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville// notice, this list of conditions and the following disclaimer.
11e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville//     * Redistributions in binary form must reproduce the above
12e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville// copyright notice, this list of conditions and the following disclaimer
13e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville// in the documentation and/or other materials provided with the
14e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville// distribution.
15e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville//     * Neither the name of Google Inc. nor the names of its
16e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville// contributors may be used to endorse or promote products derived from
17e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville// this software without specific prior written permission.
18e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville//
19e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
31e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville// Author: kenton@google.com (Kenton Varda)
32e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville//  Based on original Protocol Buffers design by
33e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville//  Sanjay Ghemawat, Jeff Dean, and others.
34e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
35e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville#include <vector>
36e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
37e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville#include <google/protobuf/compiler/javamicro/javamicro_helpers.h>
38e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville#include <google/protobuf/compiler/javamicro/javamicro_params.h>
39e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville#include <google/protobuf/descriptor.pb.h>
40e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville#include <google/protobuf/stubs/strutil.h>
41e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville#include <google/protobuf/stubs/substitute.h>
42e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
43e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Savillenamespace google {
44e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Savillenamespace protobuf {
45e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Savillenamespace compiler {
46e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Savillenamespace javamicro {
47e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
48e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Savilleconst char kThickSeparator[] =
49e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  "// ===================================================================\n";
50e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Savilleconst char kThinSeparator[] =
51e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  "// -------------------------------------------------------------------\n";
52e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
53e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Savillenamespace {
54e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
55e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Savilleconst char* kDefaultPackage = "";
56e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
57e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Savilleconst string& FieldName(const FieldDescriptor* field) {
58e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  // Groups are hacky:  The name of the field is just the lower-cased name
59e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  // of the group type.  In Java, though, we would like to retain the original
60e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  // capitalization of the type name.
61e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  if (field->type() == FieldDescriptor::TYPE_GROUP) {
62e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    return field->message_type()->name();
63e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  } else {
64e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    return field->name();
65e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  }
66e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville}
67e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
68e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Savillestring UnderscoresToCamelCaseImpl(const string& input, bool cap_next_letter) {
69e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  string result;
70e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  // Note:  I distrust ctype.h due to locales.
71e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  for (int i = 0; i < input.size(); i++) {
72e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    if ('a' <= input[i] && input[i] <= 'z') {
73e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      if (cap_next_letter) {
74e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville        result += input[i] + ('A' - 'a');
75e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      } else {
76e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville        result += input[i];
77e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      }
78e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      cap_next_letter = false;
79e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    } else if ('A' <= input[i] && input[i] <= 'Z') {
80e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      if (i == 0 && !cap_next_letter) {
81e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville        // Force first letter to lower-case unless explicitly told to
82e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville        // capitalize it.
83e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville        result += input[i] + ('a' - 'A');
84e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      } else {
85e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville        // Capital letters after the first are left as-is.
86e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville        result += input[i];
87e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      }
88e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      cap_next_letter = false;
89e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    } else if ('0' <= input[i] && input[i] <= '9') {
90e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      result += input[i];
91e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      cap_next_letter = true;
92e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    } else {
93e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      cap_next_letter = true;
94e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    }
95e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  }
96e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  return result;
97e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville}
98e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
99e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville}  // namespace
100e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
101e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Savillestring UnderscoresToCamelCase(const FieldDescriptor* field) {
102e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  return UnderscoresToCamelCaseImpl(FieldName(field), false);
103e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville}
104e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
105e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Savillestring UnderscoresToCapitalizedCamelCase(const FieldDescriptor* field) {
106e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  return UnderscoresToCamelCaseImpl(FieldName(field), true);
107e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville}
108e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
109e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Savillestring UnderscoresToCamelCase(const MethodDescriptor* method) {
110e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  return UnderscoresToCamelCaseImpl(method->name(), false);
111e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville}
112e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
113e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Savillestring StripProto(const string& filename) {
114e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  if (HasSuffixString(filename, ".protodevel")) {
115e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    return StripSuffixString(filename, ".protodevel");
116e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  } else {
117e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    return StripSuffixString(filename, ".proto");
118e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  }
119e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville}
120e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
121e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Savillestring FileClassName(const Params& params, const FileDescriptor* file) {
122e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  string name;
123e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
124e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  if (params.has_java_outer_classname(file->name())) {
125e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      name = params.java_outer_classname(file->name());
126e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  } else {
127e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    if ((file->message_type_count() == 1)
128e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville        || (file->enum_type_count() == 0)) {
129e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      // If no outer calls and only one message then
130e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      // use the message name as the file name
131e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      name = file->message_type(0)->name();
132e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    } else {
133e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      // Use the filename it self with underscores removed
134e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      // and a CamelCase style name.
135e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      string basename;
136e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      string::size_type last_slash = file->name().find_last_of('/');
137e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      if (last_slash == string::npos) {
138e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville        basename = file->name();
139e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      } else {
140e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville        basename = file->name().substr(last_slash + 1);
141e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      }
142e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      name = UnderscoresToCamelCaseImpl(StripProto(basename), true);
143e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    }
144e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  }
145e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
146e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  return name;
147e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville}
148e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
149e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Savillestring FileJavaPackage(const Params& params, const FileDescriptor* file) {
150e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  if (params.has_java_package(file->name())) {
151e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    return params.java_package(file->name());
152e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  } else {
153e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    string result = kDefaultPackage;
154e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    if (!file->package().empty()) {
155e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      if (!result.empty()) result += '.';
156e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      result += file->package();
157e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    }
158e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    return result;
159e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  }
160e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville}
161e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
162e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Savillestring ToJavaName(const Params& params, const string& full_name,
163e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    const FileDescriptor* file) {
164e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  string result;
165e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  if (params.java_multiple_files()) {
166e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    result = FileJavaPackage(params, file);
167e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  } else {
168e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    result = ClassName(params, file);
169e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  }
170e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  if (file->package().empty()) {
171e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    result += '.';
172e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    result += full_name;
173e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  } else {
174e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    // Strip the proto package from full_name since we've replaced it with
175e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    // the Java package. If there isn't an outer classname then strip it too.
176e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    int sizeToSkipPackageName = file->package().size();
177e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    int sizeToSkipOutClassName;
178e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    if (params.has_java_outer_classname(file->name())) {
179e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      sizeToSkipOutClassName = 0;
180e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    } else {
181e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      sizeToSkipOutClassName =
182e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville                full_name.find_first_of('.', sizeToSkipPackageName + 1);
183e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    }
184e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    int sizeToSkip = sizeToSkipOutClassName > 0 ?
185e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville            sizeToSkipOutClassName : sizeToSkipPackageName;
186e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    string class_name = full_name.substr(sizeToSkip + 1);
187e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    if (class_name == FileClassName(params, file)) {
188e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      // Done class_name is already present.
189e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    } else {
190e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      result += '.';
191e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      result += class_name;
192e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    }
193e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  }
194e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  return result;
195e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville}
196e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
197e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Savillestring ClassName(const Params& params, const FileDescriptor* descriptor) {
198e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  string result = FileJavaPackage(params, descriptor);
199e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  if (!result.empty()) result += '.';
200e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  result += FileClassName(params, descriptor);
201e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  return result;
202e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville}
203e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
204e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Savillestring ClassName(const Params& params, const EnumDescriptor* descriptor) {
205e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  string result;
206e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  const FileDescriptor* file = descriptor->file();
207e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  const string file_name = file->name();
208e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  const string full_name = descriptor->full_name();
209e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
21066663e974c1d66250e51f5008bce5590464bbe9aWink Saville  // Remove enum class name as we use int's for enums
211e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  string base_name = full_name.substr(0, full_name.find_last_of('.'));
212e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
213e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  if (!file->package().empty()) {
21466663e974c1d66250e51f5008bce5590464bbe9aWink Saville    if (file->package() == base_name.substr(0, file->package().size())) {
21566663e974c1d66250e51f5008bce5590464bbe9aWink Saville      // Remove package name leaving just the parent class of the enum
21666663e974c1d66250e51f5008bce5590464bbe9aWink Saville      int offset = file->package().size();
21766663e974c1d66250e51f5008bce5590464bbe9aWink Saville      if (base_name.size() > offset) {
21866663e974c1d66250e51f5008bce5590464bbe9aWink Saville        // Remove period between package and class name if there is a classname
21966663e974c1d66250e51f5008bce5590464bbe9aWink Saville        offset += 1;
22066663e974c1d66250e51f5008bce5590464bbe9aWink Saville      }
22166663e974c1d66250e51f5008bce5590464bbe9aWink Saville      base_name = base_name.substr(offset);
22266663e974c1d66250e51f5008bce5590464bbe9aWink Saville    } else {
22366663e974c1d66250e51f5008bce5590464bbe9aWink Saville      GOOGLE_LOG(FATAL) << "Expected package name to start an enum";
224e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    }
225e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  }
226e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
22766663e974c1d66250e51f5008bce5590464bbe9aWink Saville  // Construct the path name from the package and outer class
22866663e974c1d66250e51f5008bce5590464bbe9aWink Saville
22966663e974c1d66250e51f5008bce5590464bbe9aWink Saville  // Add the java package name if it exsits
230e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  if (params.has_java_package(file_name)) {
231e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    result += params.java_package(file_name);
232e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  }
23366663e974c1d66250e51f5008bce5590464bbe9aWink Saville
23466663e974c1d66250e51f5008bce5590464bbe9aWink Saville  // Add the outer classname if it exists
235e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  if (params.has_java_outer_classname(file_name)) {
23666663e974c1d66250e51f5008bce5590464bbe9aWink Saville    if (!result.empty()) {
23766663e974c1d66250e51f5008bce5590464bbe9aWink Saville      result += ".";
23866663e974c1d66250e51f5008bce5590464bbe9aWink Saville    }
239e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    result += params.java_outer_classname(file_name);
240e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  }
24166663e974c1d66250e51f5008bce5590464bbe9aWink Saville
24266663e974c1d66250e51f5008bce5590464bbe9aWink Saville  // Create the full class name from the base and path
243e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  if (!base_name.empty()) {
24466663e974c1d66250e51f5008bce5590464bbe9aWink Saville    if (!result.empty()) {
24566663e974c1d66250e51f5008bce5590464bbe9aWink Saville      result += ".";
24666663e974c1d66250e51f5008bce5590464bbe9aWink Saville    }
247e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    result += base_name;
248e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  }
249e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  return result;
250e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville}
251e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
252e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Savillestring FieldConstantName(const FieldDescriptor *field) {
253e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  string name = field->name() + "_FIELD_NUMBER";
254e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  UpperString(&name);
255e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  return name;
256e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville}
257e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
258e2d542951c059563a3b7f74c257dac4f222d9dc5Wink SavilleJavaType GetJavaType(FieldDescriptor::Type field_type) {
259e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  switch (field_type) {
260e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    case FieldDescriptor::TYPE_INT32:
261e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    case FieldDescriptor::TYPE_UINT32:
262e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    case FieldDescriptor::TYPE_SINT32:
263e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    case FieldDescriptor::TYPE_FIXED32:
264e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    case FieldDescriptor::TYPE_SFIXED32:
265e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      return JAVATYPE_INT;
266e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
267e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    case FieldDescriptor::TYPE_INT64:
268e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    case FieldDescriptor::TYPE_UINT64:
269e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    case FieldDescriptor::TYPE_SINT64:
270e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    case FieldDescriptor::TYPE_FIXED64:
271e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    case FieldDescriptor::TYPE_SFIXED64:
272e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      return JAVATYPE_LONG;
273e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
274e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    case FieldDescriptor::TYPE_FLOAT:
275e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      return JAVATYPE_FLOAT;
276e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
277e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    case FieldDescriptor::TYPE_DOUBLE:
278e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      return JAVATYPE_DOUBLE;
279e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
280e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    case FieldDescriptor::TYPE_BOOL:
281e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      return JAVATYPE_BOOLEAN;
282e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
283e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    case FieldDescriptor::TYPE_STRING:
284e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      return JAVATYPE_STRING;
285e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
286e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    case FieldDescriptor::TYPE_BYTES:
287e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      return JAVATYPE_BYTES;
288e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
289e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    case FieldDescriptor::TYPE_ENUM:
290e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      return JAVATYPE_ENUM;
291e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
292e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    case FieldDescriptor::TYPE_GROUP:
293e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    case FieldDescriptor::TYPE_MESSAGE:
294e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      return JAVATYPE_MESSAGE;
295e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
296e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    // No default because we want the compiler to complain if any new
297e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    // types are added.
298e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  }
299e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
300e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  GOOGLE_LOG(FATAL) << "Can't get here.";
301e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  return JAVATYPE_INT;
302e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville}
303e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
304e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Savilleconst char* BoxedPrimitiveTypeName(JavaType type) {
305e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  switch (type) {
306e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    case JAVATYPE_INT    : return "java.lang.Integer";
307e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    case JAVATYPE_LONG   : return "java.lang.Long";
308e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    case JAVATYPE_FLOAT  : return "java.lang.Float";
309e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    case JAVATYPE_DOUBLE : return "java.lang.Double";
310e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    case JAVATYPE_BOOLEAN: return "java.lang.Boolean";
311e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    case JAVATYPE_STRING : return "java.lang.String";
312e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    case JAVATYPE_BYTES  : return "com.google.protobuf.micro.ByteStringMicro";
313e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    case JAVATYPE_ENUM   : return "java.lang.Integer";
314e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    case JAVATYPE_MESSAGE: return NULL;
315e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
316e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    // No default because we want the compiler to complain if any new
317e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    // JavaTypes are added.
318e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  }
319e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
320e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  GOOGLE_LOG(FATAL) << "Can't get here.";
321e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  return NULL;
322e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville}
323e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
324e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Savillebool AllAscii(const string& text) {
325e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  for (int i = 0; i < text.size(); i++) {
326e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    if ((text[i] & 0x80) != 0) {
327e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      return false;
328e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    }
329e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  }
330e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  return true;
331e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville}
332e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
333e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Savillestring DefaultValue(const Params& params, const FieldDescriptor* field) {
334e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  // Switch on cpp_type since we need to know which default_value_* method
335e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  // of FieldDescriptor to call.
336e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  switch (field->cpp_type()) {
337e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    case FieldDescriptor::CPPTYPE_INT32:
338e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      return SimpleItoa(field->default_value_int32());
339e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    case FieldDescriptor::CPPTYPE_UINT32:
340e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      // Need to print as a signed int since Java has no unsigned.
341e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      return SimpleItoa(static_cast<int32>(field->default_value_uint32()));
342e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    case FieldDescriptor::CPPTYPE_INT64:
343e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      return SimpleItoa(field->default_value_int64()) + "L";
344e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    case FieldDescriptor::CPPTYPE_UINT64:
345e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      return SimpleItoa(static_cast<int64>(field->default_value_uint64())) +
346e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville             "L";
347e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    case FieldDescriptor::CPPTYPE_DOUBLE:
348e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      return SimpleDtoa(field->default_value_double()) + "D";
349e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    case FieldDescriptor::CPPTYPE_FLOAT:
350e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      return SimpleFtoa(field->default_value_float()) + "F";
351e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    case FieldDescriptor::CPPTYPE_BOOL:
352e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      return field->default_value_bool() ? "true" : "false";
353e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    case FieldDescriptor::CPPTYPE_STRING:
354e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      if (field->type() == FieldDescriptor::TYPE_BYTES) {
355e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville        if (field->has_default_value()) {
356e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville          // See comments in Internal.java for gory details.
357e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville          return strings::Substitute(
358e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville            "com.google.protobuf.micro.ByteStringMicro.copyFromUtf8(\"$0\")",
359e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville            CEscape(field->default_value_string()));
360e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville        } else {
361e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville          return "com.google.protobuf.micro.ByteStringMicro.EMPTY";
362e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville        }
363e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      } else {
364e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville        if (AllAscii(field->default_value_string())) {
365e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville          // All chars are ASCII.  In this case CEscape() works fine.
366e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville          return "\"" + CEscape(field->default_value_string()) + "\"";
367e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville        } else {
368e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville          // See comments in Internal.java for gory details.
369e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville          // BUG: Internal NOT SUPPORTED need to fix!!
370e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville          return strings::Substitute(
371e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville            "com.google.protobuf.micro.Internal.stringDefaultValue(\"$0\")",
372e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville            CEscape(field->default_value_string()));
373e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville        }
374e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      }
375e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
376e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    case FieldDescriptor::CPPTYPE_ENUM:
377e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      return ClassName(params, field->enum_type()) + "." +
378e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville             field->default_value_enum()->name();
379e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
380e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    case FieldDescriptor::CPPTYPE_MESSAGE:
381e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      return ClassName(params, field->message_type()) + ".getDefaultInstance()";
382e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
383e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    // No default because we want the compiler to complain if any new
384e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    // types are added.
385e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  }
386e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
387e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  GOOGLE_LOG(FATAL) << "Can't get here.";
388e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  return "";
389e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville}
390e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
391e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville}  // namespace javamicro
392e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville}  // namespace compiler
393e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville}  // namespace protobuf
394e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville}  // namespace google
395