Squashed 'third_party/flatbuffers/' changes from e5f331db9..bc44fad35

bc44fad35 UnPackTo disable merge by default (#7527)
4fca4dc60 [TS/JS] Move TS tests to dedicated folder and deps upgrade (#7508)
036032373 Bump junit from 4.13 to 4.13.1 in /java (#7526)
89dfb43f3 Replace `bash JavaTest.sh` with `mvn test` (#7500)
c49aff4b6 enabled cpp17 tests in CI (#7524)
56e60223c prevent force_align attribute on enums (#7523)
89b1f5aa1 remove travis config (#7522)
b90159823 [Java][Flexbuffers] Add API to add nullables into the buffer. (#7521)
8cdc6a288 Install BuildFlatBuffers.cmake (#7519)
a67e35aff Moves all of the swift test code into tests/swift (#7509)
f124e41ae Updated Readme
4c954181c [Java][FlexBuffers] throwing exception for untyped fixed vectors (#7507)
7f7547737 [Android] Remove maven dependency of flatbuffers and use source folder (#7503)
a79d61ea8 Fixes issue with cocoapods failing to be published because of docc (#7505)
d465b39c3 [CMake]: fix breaking find_package change (#7499) (#7502)
c5a609dc2 [C#] Prepares for official Nuget release (#7496)
5634dc3d0 [ISSUE-6268] returns NaN insteadof nan (#7498)
37e37b8ca Updates cocoapods version (#7497)
8fd4534fb update android multidex setting (#7495)
d5427da52 Disable Android Build (#7494)
06c5c7ed0 FlatBuffers Version 2.0.8 (#7492)
b190ce11b Verifier Refinements (#7490)
bf5d23230 Namer applied to Typescript generator (#7488)
ce382d6dd [TS/JS] Add rollup and config to generate iife flatbuffers bundle (#7449)
41d9add7e C++: Add option to skip verifying nested flatbuffers (#7489)
6a8742754 [C++] support native_inline attribute for vector of tables (#7479)
694add668 Refactor test.cpp (#7487)
7edf8c908 Update scorecard to 1.1.2
b86387442 Fix typos (#7483)
e2eb5ee67 Include <array> head in stl_emulation.h (#7480)
994502b6d Version number in file package.json updated to 2.0.7 (#7476)
fa41e8367 [C++] Fixed crash when copying table with empty shared strings (#7477)
799cc8f7b Use type traits for specialization (#7475)
b7eb44147 Disable RTTI and rework use in idl_gen_ts.cpp (#7474)
8d01c5859 CMake project version detection made more robust (#7473)
237e8b71f Moved compiler warnings around (#7471)
eeb8fd60d Include builder.addOffset for vector of structs (#7470)
fef2ffc4d Use schema include name for keep-prefix (#7469)
8367664f1 Flatbuffers Version 2.0.7 (#7462)
d6f06c33f Reworked keep prefix (#7456)
627e8bf36 update grpc version (#7457)
883c42b7d disabling unpackto optimization (#7459)
7aae0af30 Remove old GRPC bash script and convert to python3 (#7454)
b057aa917 Grouped anonymous namespaces together, (#7455)
f1b26ff7f Change to GetTypeName (#7453)
9610a666b Generate SLSA signatures for Released zip files (#7450)
1e0f75a64 [WIP] speedup (#7452)
82b75407a Wrap types in namespace for --ts-flat-files and --gen-all (#7451)
f7c511957 Audit and fixups for GCC and Clang (#7212)
a66de58af Partial support for --ts-flat-files and --gen-all (#7446)
a3508f36d [Kotlin] Make sure namespace path exist for code generation (#7357)
137fec716 Stop using __has_trivial_copy on recent clang versions. (#7443)
214125e41 [C#] Rework how sorted vectors are looked up (#7441)
44a7dc999 Define minimum buffer size (#7440)
3cc2daa78 make_span overloads for pointer to vector (#7374) (#7435)
fa1174aa7 [TypeScript] Fix namespaceless schema generation (#7432)
83d4e2a10 Add checks to verifier (#7438)
8a09f3fb0 Fix FlexBuffers JS/TS bug https://github.com/google/flatbuffers/issues/6934 (#7434)
9dbe819ef Add flatc python tests to CI (#7437)
67c414958 Update TypeScriptTest.py to work better cross platform (#7436)
8b8c7dbdf Update gitingore to reflect name change (#7431)
2ee20a5f3 Remove auto including locale functions (#7430)
4be605604 [C++] Set StructDef::has_key property when deserializing from binary schema (#7386) (#7428)
fc5d86f1e [C++] Make template parameter in stl_emulation.h more explicit to avoid conflicts with cpprestsdk U macro (#7424)
9dce287ad Issue#6959 :Updated Automatically generated rust files. (#7425)
7798be3bb avoid zero-as-null-pointer warning (#7423)
966362e07 [C++] Vector of Tables equality (#7415)
a89c279ed [golang] Perform keyword escaping after case conversion (#7421)
a212b3c03 Turn of fail fast for C++ CI
9230f600d Remove stringop-overflow from error (#7422)
c79362156 [golang] Add support for text parsing with json struct tags (#7353)
ee2ced236 Moved TypeScriptTests to python script (#7411)
468c00a3f Rebased: grpc/compiler: Respect filename suffix and extension during code generation (#7414)
47c757f71 Add tests for flatc (#7405)
9a5ff8900 Add FLATBUFFERS_STRICT_MODE (#7408)
950444a34 [TS] Use TextEncoder and TextDecoder (#7400)
30d76198c Compilation issue msys2 #7399 (#7409)
cce3a66f0 Delete .travis directory
8d1cc6ac7 Revert "Compilation issue msys2 (#7403)" (#7407)
5b207639a Update readme.md
359e0f9d6 Revert "grpc/compiler: Respect filename suffix and extension during code generation (#7343)" (#7406)
ebbed0513 Delete cpp-linter.yml
aa395e5a5 (#7323) Rename CMake files according to project name (#7378)
32328075d Fix error msg format when generate GRPC failed (#7350)
97e89c5ac grpc/compiler: Respect filename suffix and extension during code generation (#7343)
5f6672be4 Fix Clang-Cl compile on Windows (#7308)
28e858c85 [TS/Bazel] Minor improvements to typescript.bzl (#7300)
987bebe67 [TS] fix incorrect reverse when writting array of structs (#7271)
ec0129369 Fix FlexBuffers Verifier tracking vectors reuse at wrong offset
50dd385b3 Add missing const (#7401)
da702cfd8 Compilation issue msys2 (#7403)
6e2791640 keep-prefix keeps relative pathing (#7394)
52fce5e53 fix(#7360): grpc used deprecated functions (#7361)
b7f13cd8e cpp_generator: comment out unused parameter to avoid warnings (#7381)
e42985e5a Updated Newtonsoft.Json to 13.0.1 (#7393)
0a8064637 Fix references to LICENSE file (#7377)
b9eea76a8 [Dart] Implement putBool to fix errors when serializing structs with bools (#7359)
1b9030015 Bump Newtonsoft.Json from 12.0.3 to 13.0.1 in /tests/FlatBuffers.Test (#7363)
83a43fc79 Reenable optional json (#7352)
5f0137602 Only include direct included filed (#7348)
9a1913a87 Revert "Implement optional scalars for JSON (#7322)" (#7351)
b4647beb8 Revert "Move reflection_ts_fbs into a separate directory (#7342)" (#7349)
d6060977a Remove asserting in verifier for flattests
987aa5b5e move -Wextra-semi to GCC 8.0+
42acdb63c [TS] Don't generate self-imports with --ts-flat-file (#7340)
0cc1aeb8c [golang] Create missing namespace directory structure (#7324) (#7325)
ba6c67170 [Kotlin] Remove download benchmark files dependency (#7314)
d2f33fc45 Disable Android on Linux CI build
0d1b72cbc [TS] fix ts import path issue (#7298)
9fce2fbf2 replace io/ioutil to os (#7281)
a18ea40d6 Implement optional scalars for JSON (#7322)
090caa280 Move reflection_ts_fbs into a separate directory (#7342)
49e1ea333 Implement optional scalars for Python (#7318)
11a198870 Started implementation for private flags in rust (#7269)
967df08b1 Adds full supposed for Wasm in the swift lib (#7328)
9aa08a429 Use keep case for Rust union discriminant type. (#7321)
9e8c758f5 Add explicit return types to lobster generated code (#7312)
74a25536b Add size check to fix out of bounds read risk (#7304)
12917af8a Update Rust docs page (#7296)
1ea2472f7 [swift] add had<ArrayName> property for arrays to check presence in a message (#7280)
0fe13cb28 Remove span ConstIterator/cbegin()/cend(). (#7295)
385dddc66 Namerkot (#7245)
750dde766 Make `flatc` generate Rust files not requiring `std` (#7273)
9917a168c [swift] Make swift module public (#7274)
76d3cca19 Rust: fix a name conflict when building with "no_std" feature (#7268)
c86e6d0e3 json inf parsing
d34dc32c2 fix include order
234d86c92 fixed off-by-one in parser
746c73b91 Add Annotations for Monster schema and example buffer
0bbfd4b2e fixes for annotator
716521953 Update readme.md (#7257)
a45f564cf [performance] Add aggressive systematic inlining in ByteBuffer and FlatBufferBuilder (#7253)
9d45a6403 more google merge fixes
ccfb4c20b Handle +/-inf in protos (#7256)
7bcd857b8 Specialize CreateVector with std::initializer_list (#7254)
23c8ab34c Swift update performance benchmark infrastructure (#7255)
70002dc5c various fixes for google merge
6e0e79f24 Add test for nested buffer verifier (#7252)
b856368d7 Turn off go modules temporary until we get a proper fix (#7251)
e37156a30 Keep the underlying storage capacity when clearing the FlatBufferBuilder. Gives a significant performance boost for serialisation of many small messages. (#7250)
a10b0e546 Java namer variable keep case (#7249)
275b73994 allow overriding FLATBUFFERS_MAX_ALIGNMENT
9d1ce9a10 Add parameter back to EndVector (#7246)
79afe6c3d Make Java namespaces keep case by default (#7243)
c6dbb2230 Add write permissions for labeller
18bacd3ea Expand test to make sure {}-initializers are properly understood by template. (#7242)
a2c913aec Add -Wnon-virtual-dtor
67b33b294 set workflows permissions to read-only (#7239)
7b5fd2bd0 [Kotlin] Fix key lookup returning null clashing with default value (#7237)
7181d7770 [Java] Fix key lookup returning null clashing with default value (#7236)
7f663b120 Allow CreateVectorOfStrings() to work with any string-type. (#7238)
173ebb694 Fixes a bug where the create function doesnt optional + required items (#7228)
d65823948 [Kotlin] Update gradle to 7.4.1 and simplify config files. (#7231)
ab4bf59e8 remove toascii (#7234)
eee44bbb2 disable cpp-linter (#7229)
a63fa51a1 Create cpp-linter.yml (#7208)
2049e5210 Adds a way to verify/exposes Entities ids (#7221)
832c618f5 Adds implementation flag for swift (#7202)
14615699f Started to migrate to target_compile_options (#7222)
20aad0c41 [C++] stl_emulation span::count_ is not const anymore (#7226) (#7227)
f083b33f2 code gen flexbuffer verifier (#7207)
bf17df346 [C++] generate sorted #include directives (#7213)
35281dedb Fix for [C++] flatc generates invalid Code in the default constructor for structs, when --cpp-field-case-style is used #7209 (#7211)
c9651b742 Add overloads for C# ByteBuffer/FlatBufferBuilder to allow adding vector blocks from ArraySegments or IntPtr (#7193)
26c3b3ada Update codeql.yml
da6e1b985 Update codeql.yml
ad27d751e Added Oss fuzz badge
0aab623cb Create codeql.yml
6a446bdd8 maximize parallel builds in CI (#7206)
21fb5cbbc Create scorecards.yml
0da6f9486 [C++] Static assert on Flatbuffers Version (#7203)
59e971308 reduce fuzzing time to 1 minute in CI
40866a892 fixed padding in struct for annotated binary (#7199)
b71d968fa Apply Namer prefix/suffix to other generators (#7197)
fac0d7be0 Apply Namer to Java. (#7194)
6c5603fd9 [C#] Fix collision of field name and type name (#7149)
2d21853a7 monster fuzzer fix for json default scalars
fec1a8d01 [swift] Add bazel configuration for Swift (#7195)
7fd857623 structured comments (#7192)
a4cb1599d Namerdart (#7187)
ae4ce7265 fuzzed binary annotator (#7188)
e2be0c0b0 Handle root offset and root table vtable invalidation (#7177)
2ad408697 [TS] Fix generation of struct members in object api (#7148)
4213d9105 VerifySizePrefixed (reflection::Schema) and GetAnySizePrefixedRoot added (#7181)
5a13f622c Correctly parse lists of enums in Dart generated code (#7157)
23a7e4e0b Adds no-includes flags to the swift code generator (#7182)
eeb49c275 Move flatbuffer_ts_library to typescript.bzl (#7183)
824763b31 Typo in flatc options (warning-as-errors instead of warnings-as-errors) (#7180)
d3aeee32b Annotated Flatbuffer Binary (#7174)
0bceba24d [Lua] Apply Namer to Lua (#7171)
b8c77d404 Make inclusion of header <optional> opt-out via macro (#7168)
8468eab83 Namersw (#7167)
2b2e8d4ae Nameroverloads (#7164)
b80b32bfa Use DESCRIPTION only if CMake version >= 3.9 (#7166)

Change-Id: Ic2681dabb1a798b7515e62753ee06aecb9933260
git-subtree-dir: third_party/flatbuffers
git-subtree-split: bc44fad35271e43fd7a79b4d691ac9e41708797f
Signed-off-by: Austin Schuh <austin.schuh@bluerivertech.com>
diff --git a/src/idl_gen_java.cpp b/src/idl_gen_java.cpp
index ee09391..6ee97aa 100644
--- a/src/idl_gen_java.cpp
+++ b/src/idl_gen_java.cpp
@@ -20,20 +20,65 @@
 #include "flatbuffers/flatbuffers.h"
 #include "flatbuffers/idl.h"
 #include "flatbuffers/util.h"
+#include "idl_namer.h"
 
 namespace flatbuffers {
 namespace java {
 
-static TypedFloatConstantGenerator JavaFloatGen("Double.", "Float.", "NaN",
+namespace {
+
+static Namer::Config JavaDefaultConfig() {
+  return {
+    /*types=*/Case::kKeep,
+    /*constants=*/Case::kScreamingSnake,
+    /*methods=*/Case::kLowerCamel,
+    /*functions=*/Case::kLowerCamel,
+    /*fields=*/Case::kLowerCamel,
+    /*variables=*/Case::kLowerCamel,
+    /*variants=*/Case::kKeep,
+    /*enum_variant_seperator=*/".",
+    /*escape_keywords=*/Namer::Config::Escape::AfterConvertingCase,
+    /*namespaces=*/Case::kKeep,
+    /*namespace_seperator=*/".",
+    /*object_prefix=*/"",
+    /*object_suffix=*/"T",
+    /*keyword_prefix=*/"",
+    /*keyword_suffix=*/"_",
+    /*filenames=*/Case::kKeep,
+    /*directories=*/Case::kKeep,
+    /*output_path=*/"",
+    /*filename_suffix=*/"_generated",
+    /*filename_extension=*/".java",
+  };
+}
+
+static std::set<std::string> JavaKeywords() {
+  return {
+    "abstract", "continue", "for",        "new",       "switch",
+    "assert",   "default",  "goto",       "package",   "synchronized",
+    "boolean",  "do",       "if",         "private",   "this",
+    "break",    "double",   "implements", "protected", "throw",
+    "byte",     "else",     "import",     "public",    "throws",
+    "case",     "enum",     "instanceof", "return",    "transient",
+    "catch",    "extends",  "int",        "short",     "try",
+    "char",     "final",    "interface",  "static",    "void",
+    "class",    "finally",  "long",       "strictfp",  "volatile",
+    "const",    "float",    "native",     "super",     "while",
+  };
+}
+
+static const TypedFloatConstantGenerator JavaFloatGen("Double.", "Float.", "NaN",
                                                 "POSITIVE_INFINITY",
                                                 "NEGATIVE_INFINITY");
 
-static CommentConfig comment_config = {
+static const CommentConfig comment_config = {
   "/**",
   " *",
   " */",
 };
 
+} // namespace
+
 class JavaGenerator : public BaseGenerator {
   struct FieldArrayLength {
     std::string name;
@@ -44,7 +89,9 @@
   JavaGenerator(const Parser &parser, const std::string &path,
                 const std::string &file_name)
       : BaseGenerator(parser, path, file_name, "", ".", "java"),
-        cur_name_space_(nullptr) {}
+        cur_name_space_(nullptr),
+        namer_(WithFlagOptions(JavaDefaultConfig(), parser.opts, path),
+               JavaKeywords()) {}
 
   JavaGenerator &operator=(const JavaGenerator &);
   bool generate() {
@@ -56,7 +103,7 @@
       std::string enumcode;
       auto &enum_def = **it;
       if (!parser_.opts.one_file) cur_name_space_ = enum_def.defined_namespace;
-      GenEnum(enum_def, &enumcode);
+      GenEnum(enum_def, enumcode);
       if (parser_.opts.one_file) {
         one_file_code += enumcode;
       } else {
@@ -67,8 +114,8 @@
 
       if (parser_.opts.generate_object_based_api && enum_def.is_union) {
         enumcode = "";
-        GenEnum_ObjectAPI(enum_def, &enumcode, parser_.opts);
-        auto class_name = enum_def.name + "Union";
+        GenEnum_ObjectAPI(enum_def, enumcode);
+        auto class_name = namer_.Type(enum_def) + "Union";
         if (parser_.opts.one_file) {
           one_file_code += enumcode;
         } else {
@@ -85,7 +132,7 @@
       auto &struct_def = **it;
       if (!parser_.opts.one_file)
         cur_name_space_ = struct_def.defined_namespace;
-      GenStruct(struct_def, &declcode, parser_.opts);
+      GenStruct(struct_def, declcode, parser_.opts);
       if (parser_.opts.one_file) {
         one_file_code += declcode;
       } else {
@@ -96,8 +143,8 @@
 
       if (parser_.opts.generate_object_based_api) {
         declcode = "";
-        GenStruct_ObjectAPI(struct_def, &declcode, parser_.opts);
-        auto class_name = GenTypeName_ObjectAPI(struct_def.name, parser_.opts);
+        GenStruct_ObjectAPI(struct_def, declcode);
+        auto class_name = namer_.ObjectType(struct_def);
         if (parser_.opts.one_file) {
           one_file_code += declcode;
         } else {
@@ -124,7 +171,7 @@
     std::string code;
     code = "// " + std::string(FlatBuffersGeneratedWarning()) + "\n\n";
 
-    std::string namespace_name = FullNamespace(".", ns);
+    const std::string namespace_name = FullNamespace(".", ns);
     if (!namespace_name.empty()) {
       code += "package " + namespace_name + ";";
       code += "\n\n";
@@ -144,7 +191,10 @@
 
     code += classcode;
     if (!namespace_name.empty()) code += "";
-    auto filename = NamespaceDir(ns) + defname + ".java";
+    const std::string dirs = namer_.Directories(ns);
+    EnsureDirExists(dirs);
+    const std::string filename =
+        dirs + namer_.File(defname, /*skips=*/SkipFile::Suffix);
     return SaveFile(filename.c_str(), code, false);
   }
 
@@ -181,7 +231,7 @@
     switch (type.base_type) {
       case BASE_TYPE_STRING: return "String";
       case BASE_TYPE_VECTOR: return GenTypeGet(type.VectorType());
-      case BASE_TYPE_STRUCT: return WrapInNameSpace(*type.struct_def);
+      case BASE_TYPE_STRUCT: return namer_.NamespacedType(*type.struct_def);
       case BASE_TYPE_UNION: FLATBUFFERS_FALLTHROUGH();  // else fall thru
       default: return "Table";
     }
@@ -285,7 +335,7 @@
     FLATBUFFERS_ASSERT(value.type.enum_def);
     auto &enum_def = *value.type.enum_def;
     auto enum_val = enum_def.FindByValue(value.constant);
-    return enum_val ? (WrapInNameSpace(enum_def) + "." + enum_val->name)
+    return enum_val ? namer_.NamespacedEnumVariant(enum_def, *enum_val)
                     : value.constant;
   }
 
@@ -320,8 +370,7 @@
     return GenDefaultValue(field);
   }
 
-  void GenEnum(EnumDef &enum_def, std::string *code_ptr) const {
-    std::string &code = *code_ptr;
+  void GenEnum(EnumDef &enum_def, std::string &code) const {
     if (enum_def.generated) return;
 
     // Generate enum definitions of the form:
@@ -329,7 +378,7 @@
     // In Java, we use ints rather than the Enum feature, because we want them
     // to map directly to how they're used in C/C++ and file formats.
     // That, and Java Enums are expensive, and not universally liked.
-    GenComment(enum_def.doc_comment, code_ptr, &comment_config);
+    GenComment(enum_def.doc_comment, &code, &comment_config);
 
     code += "@SuppressWarnings(\"unused\")\n";
     if (enum_def.attributes.Lookup("private")) {
@@ -337,16 +386,16 @@
     } else {
       code += "public ";
     }
-    code += "final class " + enum_def.name;
+    code += "final class " + namer_.Type(enum_def);
     code += " {\n";
-    code += "  private " + enum_def.name + "() { }\n";
+    code += "  private " + namer_.Type(enum_def) + "() { }\n";
     for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) {
       auto &ev = **it;
-      GenComment(ev.doc_comment, code_ptr, &comment_config, "  ");
+      GenComment(ev.doc_comment, &code, &comment_config, "  ");
       code += "  public static final ";
       code += GenTypeBasic(DestinationType(enum_def.underlying_type, false));
       code += " ";
-      code += ev.name + " = ";
+      code += namer_.Variant(ev) + " = ";
       code += enum_def.ToString(ev);
       code += ";\n";
     }
@@ -364,13 +413,14 @@
             "long") {
       code += "\n  public static final String";
       code += "[] names = { ";
-      auto val = enum_def.Vals().front();
+      const EnumVal *prev = enum_def.Vals().front();
       for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end();
            ++it) {
-        auto ev = *it;
-        for (auto k = enum_def.Distance(val, ev); k > 1; --k) code += "\"\", ";
-        val = ev;
-        code += "\"" + (*it)->name + "\", ";
+        const EnumVal &ev = **it;
+        for (auto k = enum_def.Distance(prev, &ev); k > 1; --k)
+          code += "\"\", ";
+        prev = &ev;
+        code += "\"" + namer_.Variant(ev) + "\", ";
       }
       code += "};\n\n";
       code += "  public static ";
@@ -378,7 +428,7 @@
       code += " name";
       code += "(int e) { return names[e";
       if (enum_def.MinValue()->IsNonZero())
-        code += " - " + enum_def.MinValue()->name;
+        code += " - " + namer_.Variant(enum_def.MinValue()->name);
       code += "]; }\n";
     }
 
@@ -445,9 +495,8 @@
 
   // Recursively generate arguments for a constructor, to deal with nested
   // structs.
-  void GenStructArgs(const StructDef &struct_def, std::string *code_ptr,
+  void GenStructArgs(const StructDef &struct_def, std::string &code,
                      const char *nameprefix, size_t array_count = 0) const {
-    std::string &code = *code_ptr;
     for (auto it = struct_def.fields.vec.begin();
          it != struct_def.fields.vec.end(); ++it) {
       auto &field = **it;
@@ -460,7 +509,7 @@
         // Generate arguments for a struct inside a struct. To ensure names
         // don't clash, and to make it obvious these arguments are constructing
         // a nested struct, prefix the name with the field name.
-        GenStructArgs(*field_type.struct_def, code_ptr,
+        GenStructArgs(*field_type.struct_def, code,
                       (nameprefix + (field.name + "_")).c_str(), array_cnt);
       } else {
         code += ", ";
@@ -468,7 +517,7 @@
         for (size_t i = 0; i < array_cnt; i++) code += "[]";
         code += " ";
         code += nameprefix;
-        code += ConvertCase(field.name, Case::kLowerCamel);
+        code += namer_.Field(field);
       }
     }
   }
@@ -476,10 +525,9 @@
   // Recusively generate struct construction statements of the form:
   // builder.putType(name);
   // and insert manual padding.
-  void GenStructBody(const StructDef &struct_def, std::string *code_ptr,
+  void GenStructBody(const StructDef &struct_def, std::string &code,
                      const char *nameprefix, size_t index = 0,
                      bool in_array = false) const {
-    std::string &code = *code_ptr;
     std::string indent((index + 1) * 2, ' ');
     code += indent + "  builder.prep(";
     code += NumToString(struct_def.minalign) + ", ";
@@ -493,7 +541,7 @@
         code += NumToString(field.padding) + ");\n";
       }
       if (IsStruct(field_type)) {
-        GenStructBody(*field_type.struct_def, code_ptr,
+        GenStructBody(*field_type.struct_def, code,
                       (nameprefix + (field.name + "_")).c_str(), index,
                       in_array);
       } else {
@@ -507,7 +555,7 @@
           in_array = true;
         }
         if (IsStruct(type)) {
-          GenStructBody(*field_type.struct_def, code_ptr,
+          GenStructBody(*field_type.struct_def, code,
                         (nameprefix + (field.name + "_")).c_str(), index + 1,
                         in_array);
         } else {
@@ -515,8 +563,7 @@
           code += indent + "  builder.put";
           code += GenMethod(type) + "(";
           code += SourceCast(type);
-          auto argname =
-              nameprefix + ConvertCase(field.name, Case::kLowerCamel);
+          auto argname = nameprefix + namer_.Variable(field);
           code += argname;
           size_t array_cnt = index + (IsArray(field_type) ? 1 : 0);
           for (size_t i = 0; in_array && i < array_cnt; i++) {
@@ -529,12 +576,6 @@
     }
   }
 
-  std::string GenByteBufferLength(const char *bb_name) const {
-    std::string bb_len = bb_name;
-    bb_len += ".capacity()";
-    return bb_len;
-  }
-
   std::string GenOffsetGetter(flatbuffers::FieldDef *key_field,
                               const char *num = nullptr) const {
     std::string key_offset = "";
@@ -543,7 +584,7 @@
       key_offset += num;
       key_offset += ", _bb)";
     } else {
-      key_offset += GenByteBufferLength("bb");
+      key_offset += "bb.capacity()";
       key_offset += " - tableOffset, bb)";
     }
     return key_offset;
@@ -592,10 +633,9 @@
     return key_getter;
   }
 
-  void GenStruct(StructDef &struct_def, std::string *code_ptr,
+  void GenStruct(StructDef &struct_def, std::string &code,
                  const IDLOptions &opts) const {
     if (struct_def.generated) return;
-    std::string &code = *code_ptr;
 
     // Generate a struct accessor class, with methods of the form:
     // public type name() { return bb.getType(i + offset); }
@@ -603,7 +643,7 @@
     // public type name() {
     //   int o = __offset(offset); return o != 0 ? bb.getType(o + i) : default;
     // }
-    GenComment(struct_def.doc_comment, code_ptr, &comment_config);
+    GenComment(struct_def.doc_comment, &code, &comment_config);
 
     if (parser_.opts.gen_generated) {
       code += "@javax.annotation.Generated(value=\"flatc\")\n";
@@ -614,33 +654,35 @@
     } else {
       code += "public ";
     }
-    code += "final class " + struct_def.name;
+    const auto struct_class = namer_.Type(struct_def);
+    code += "final class " + struct_class;
     code += " extends ";
     code += struct_def.fixed ? "Struct" : "Table";
     code += " {\n";
 
     if (!struct_def.fixed) {
-      // Generate verson check method.
+      // Generate version check method.
       // Force compile time error if not using the same version runtime.
       code += "  public static void ValidateVersion() {";
       code += " Constants.";
-      code += "FLATBUFFERS_2_0_0(); ";
+      code += "FLATBUFFERS_2_0_8(); ";
       code += "}\n";
 
       // Generate a special accessor for the table that when used as the root
       // of a FlatBuffer
-      std::string method_name = "getRootAs" + struct_def.name;
-      std::string method_signature =
-          "  public static " + struct_def.name + " " + method_name;
+      const std::string method_name =
+          namer_.LegacyJavaMethod2("getRootAs", struct_def, "");
+      const std::string method_signature =
+          "  public static " + struct_class + " " + method_name;
 
       // create convenience method that doesn't require an existing object
       code += method_signature + "(ByteBuffer _bb) ";
-      code += "{ return " + method_name + "(_bb, new " + struct_def.name +
-              "()); }\n";
+      code +=
+          "{ return " + method_name + "(_bb, new " + struct_class + "()); }\n";
 
       // create method that allows object reuse
       code +=
-          method_signature + "(ByteBuffer _bb, " + struct_def.name + " obj) { ";
+          method_signature + "(ByteBuffer _bb, " + struct_class + " obj) { ";
       code += "_bb.order(ByteOrder.LITTLE_ENDIAN); ";
       code += "return (obj.__assign(_bb.getInt(_bb.";
       code += "position()";
@@ -651,8 +693,10 @@
         if (parser_.file_identifier_.length()) {
           // Check if a buffer has the identifier.
           code += "  public static ";
-          code += "boolean " + struct_def.name;
-          code += "BufferHasIdentifier(ByteBuffer _bb) { return ";
+          code += "boolean " +
+                  namer_.LegacyJavaMethod2(
+                      "", struct_def, "BufferHasIdentifier(ByteBuffer _bb)") +
+                  " { return ";
           code += "__has_identifier(_bb, \"";
           code += parser_.file_identifier_;
           code += "\"); }\n";
@@ -665,27 +709,24 @@
     code += "{ ";
     code += "__reset(_i, _bb); ";
     code += "}\n";
-    code +=
-        "  public " + struct_def.name + " __assign(int _i, ByteBuffer _bb) ";
+    code += "  public " + struct_class + " __assign(int _i, ByteBuffer _bb) ";
     code += "{ __init(_i, _bb); return this; }\n\n";
     for (auto it = struct_def.fields.vec.begin();
          it != struct_def.fields.vec.end(); ++it) {
       auto &field = **it;
       if (field.deprecated) continue;
-      GenComment(field.doc_comment, code_ptr, &comment_config, "  ");
-      std::string type_name = GenTypeGet(field.value.type);
-      std::string type_name_dest = GenTypeNameDest(field.value.type);
-      std::string conditional_cast = "";
-      std::string optional = "";
-      std::string dest_mask = DestinationMask(field.value.type, true);
-      std::string dest_cast = DestinationCast(field.value.type);
-      std::string src_cast = SourceCast(field.value.type);
-      std::string method_start =
+      GenComment(field.doc_comment, &code, &comment_config, "  ");
+      const std::string type_name = GenTypeGet(field.value.type);
+      const std::string type_name_dest = GenTypeNameDest(field.value.type);
+      const std::string dest_mask = DestinationMask(field.value.type, true);
+      const std::string dest_cast = DestinationCast(field.value.type);
+      const std::string src_cast = SourceCast(field.value.type);
+      const std::string method_start =
           "  public " +
           (field.IsRequired() ? "" : GenNullableAnnotation(field.value.type)) +
-          GenPureAnnotation(field.value.type) + type_name_dest + optional +
-          " " + ConvertCase(field.name, Case::kLowerCamel);
-      std::string obj = "obj";
+          GenPureAnnotation(field.value.type) + type_name_dest + " " +
+          namer_.Field(field);
+      const std::string obj = "obj";
 
       // Most field accessors need to retrieve and test the field offset first,
       // this is the prefix code for that:
@@ -698,7 +739,7 @@
       if (field.value.type.base_type == BASE_TYPE_STRUCT) {
         // Calls the accessor that takes an accessor object with a new object.
         code += method_start + "() { return ";
-        code += ConvertCase(field.name, Case::kLowerCamel);
+        code += namer_.Field(field);
         code += "(new ";
         code += type_name + "()); }\n";
       } else if (IsSeries(field.value.type) &&
@@ -706,14 +747,13 @@
         // Accessors for vectors of structs also take accessor objects, this
         // generates a variant without that argument.
         code += method_start + "(int j) { return ";
-        code += ConvertCase(field.name, Case::kLowerCamel);
+        code += namer_.Field(field);
         code += "(new " + type_name + "(), j); }\n";
       }
 
       if (field.IsScalarOptional()) { code += GenOptionalScalarCheck(field); }
       std::string getter = dest_cast + GenGetter(field.value.type);
       code += method_start;
-      std::string default_cast = "";
       std::string member_suffix = "; ";
       if (IsScalar(field.value.type.base_type)) {
         code += "()";
@@ -726,7 +766,7 @@
         } else {
           code += offset_prefix + getter;
           code += "(o + bb_pos)" + dest_mask;
-          code += " : " + default_cast;
+          code += " : ";
           code += GenDefaultValue(field);
         }
       } else {
@@ -738,7 +778,7 @@
               code += "bb_pos + " + NumToString(field.value.offset) + ", ";
               code += "bb)";
             } else {
-              code += offset_prefix + conditional_cast;
+              code += offset_prefix;
               code += obj + ".__assign(";
               code += field.value.type.struct_def->fixed
                           ? "o + bb_pos"
@@ -763,7 +803,7 @@
               code += type_name + " obj, ";
             }
             code += "int j)";
-            const auto body = offset_prefix + conditional_cast + getter + "(";
+            const auto body = offset_prefix + getter + "(";
             if (vectortype.base_type == BASE_TYPE_UNION) {
               code += body + "obj, ";
             } else {
@@ -787,11 +827,9 @@
             code += ")" + dest_mask;
             if (!IsArray(field.value.type)) {
               code += " : ";
-              code +=
-                  field.value.type.element == BASE_TYPE_BOOL
-                      ? "false"
-                      : (IsScalar(field.value.type.element) ? default_cast + "0"
-                                                            : "null");
+              code += field.value.type.element == BASE_TYPE_BOOL
+                          ? "false"
+                          : (IsScalar(field.value.type.element) ? "0" : "null");
             }
 
             break;
@@ -806,7 +844,7 @@
       code += member_suffix;
       code += "}\n";
       if (IsVector(field.value.type)) {
-        code += "  public int " + ConvertCase(field.name, Case::kLowerCamel);
+        code += "  public int " + namer_.Field(field);
         code += "Length";
         code += "()";
         code += offset_prefix;
@@ -821,9 +859,9 @@
           for (auto kit = fields.begin(); kit != fields.end(); ++kit) {
             auto &key_field = **kit;
             if (key_field.key) {
-              auto qualified_name = WrapInNameSpace(sd);
+              auto qualified_name = namer_.NamespacedType(sd);
               code += "  public " + qualified_name + " ";
-              code += ConvertCase(field.name, Case::kLowerCamel) + "ByKey(";
+              code += namer_.Method(field) + "ByKey(";
               code += GenTypeNameDest(key_field.value.type) + " key)";
               code += offset_prefix;
               code += qualified_name + ".__lookup_by_key(";
@@ -832,7 +870,7 @@
               code += "bb) : null; ";
               code += "}\n";
               code += "  public " + qualified_name + " ";
-              code += ConvertCase(field.name, Case::kLowerCamel) + "ByKey(";
+              code += namer_.Method(field) + "ByKey(";
               code += qualified_name + " obj, ";
               code += GenTypeNameDest(key_field.value.type) + " key)";
               code += offset_prefix;
@@ -859,15 +897,14 @@
         } else {
           vector_type_name = type_name + ".Vector";
         }
-        auto vector_method_start =
-            GenNullableAnnotation(field.value.type) + "  public " +
-            vector_type_name + optional + " " +
-            ConvertCase(field.name, Case::kLowerCamel) + "Vector";
+        auto vector_method_start = GenNullableAnnotation(field.value.type) +
+                                   "  public " + vector_type_name + " " +
+                                   namer_.Field(field, "vector");
         code += vector_method_start + "() { return ";
-        code += ConvertCase(field.name, Case::kLowerCamel) + "Vector";
+        code += namer_.Field(field, "vector");
         code += "(new " + vector_type_name + "()); }\n";
         code += vector_method_start + "(" + vector_type_name + " obj)";
-        code += offset_prefix + conditional_cast + obj + ".__assign(";
+        code += offset_prefix + obj + ".__assign(";
         code += "__vector(o), ";
         if (!IsScalar(element_base_type)) {
           auto vectortype = field.value.type.VectorType();
@@ -880,7 +917,7 @@
            IsScalar(field.value.type.VectorType().base_type)) ||
           IsString(field.value.type)) {
         code += "  public ByteBuffer ";
-        code += ConvertCase(field.name, Case::kLowerCamel);
+        code += namer_.Field(field);
         code += "AsByteBuffer() { return ";
         code += "__vector_as_bytebuffer(";
         code += NumToString(field.value.offset) + ", ";
@@ -889,7 +926,7 @@
                                 : InlineSize(field.value.type.VectorType()));
         code += "); }\n";
         code += "  public ByteBuffer ";
-        code += ConvertCase(field.name, Case::kLowerCamel);
+        code += namer_.Field(field);
         code += "InByteBuffer(ByteBuffer _bb) { return ";
         code += "__vector_in_bytebuffer(_bb, ";
         code += NumToString(field.value.offset) + ", ";
@@ -900,9 +937,9 @@
       }
       // generate object accessors if is nested_flatbuffer
       if (field.nested_flatbuffer) {
-        auto nested_type_name = WrapInNameSpace(*field.nested_flatbuffer);
-        auto nested_method_name = ConvertCase(field.name, Case::kLowerCamel) +
-                                  "As" + field.nested_flatbuffer->name;
+        auto nested_type_name = namer_.NamespacedType(*field.nested_flatbuffer);
+        auto nested_method_name =
+            namer_.Field(field) + "As" + field.nested_flatbuffer->name;
         auto get_nested_method_name = nested_method_name;
         code += "  public " + nested_type_name + " ";
         code += nested_method_name + "() { return ";
@@ -913,7 +950,7 @@
         code += nested_type_name + " obj";
         code += ") { int o = __offset(";
         code += NumToString(field.value.offset) + "); ";
-        code += "return o != 0 ? " + conditional_cast + obj + ".__assign(";
+        code += "return o != 0 ? " + obj + ".__assign(";
         code += "";
         code += "__indirect(__vector(o)), ";
         code += "bb) : null; }\n";
@@ -928,7 +965,6 @@
         auto setter_parameter = underlying_type.base_type == BASE_TYPE_BOOL
                                     ? "(byte)(" + field.name + " ? 1 : 0)"
                                     : field.name;
-        auto mutator_prefix = "mutate";
         // A vector mutator also needs the index of the vector element it should
         // mutate.
         auto mutator_params = (is_series ? "(int j, " : "(") +
@@ -946,7 +982,7 @@
         if (IsScalar(underlying_type.base_type) && !IsUnion(field.value.type)) {
           code += "  public ";
           code += struct_def.fixed ? "void " : "boolean ";
-          code += mutator_prefix + ConvertCase(field.name, Case::kUpperCamel);
+          code += namer_.Method("mutate", field);
           code += mutator_params;
           if (struct_def.fixed) {
             code += GenSetter(underlying_type) + "(" + setter_index + ", ";
@@ -962,10 +998,9 @@
       }
       if (parser_.opts.java_primitive_has_method &&
           IsScalar(field.value.type.base_type) && !struct_def.fixed) {
-        auto vt_offset_constant =
-            "  public static final int VT_" +
-            ConvertCase(field.name, Case::kScreamingSnake) + " = " +
-            NumToString(field.value.offset) + ";";
+        auto vt_offset_constant = "  public static final int VT_" +
+                                  namer_.Constant(field) + " = " +
+                                  NumToString(field.value.offset) + ";";
 
         code += vt_offset_constant;
         code += "\n";
@@ -980,10 +1015,10 @@
       // create a struct constructor function
       code += "  public static " + GenOffsetType() + " ";
       code += "create";
-      code += struct_def.name + "(FlatBufferBuilder builder";
-      GenStructArgs(struct_def, code_ptr, "");
+      code += struct_class + "(FlatBufferBuilder builder";
+      GenStructArgs(struct_def, code, "");
       code += ") {\n";
-      GenStructBody(struct_def, code_ptr, "");
+      GenStructBody(struct_def, code, "");
       code += "    return ";
       code += GenOffsetConstruct("builder." + std::string("offset()"));
       code += ";\n  }\n";
@@ -1010,12 +1045,12 @@
         // Generate a table constructor of the form:
         // public static int createName(FlatBufferBuilder builder, args...)
         code += "  public static " + GenOffsetType() + " ";
-        code += "create" + struct_def.name;
+        code += namer_.LegacyJavaMethod2("create", struct_def, "");
         code += "(FlatBufferBuilder builder";
         for (auto it = struct_def.fields.vec.begin();
              it != struct_def.fields.vec.end(); ++it) {
           auto &field = **it;
-          auto field_name = ConvertCase(field.name, Case::kLowerCamel);
+          auto field_name = namer_.Field(field);
           if (field.deprecated) continue;
           code += ",\n      ";
           code += GenTypeBasic(DestinationType(field.value.type, false));
@@ -1031,21 +1066,19 @@
           for (auto it = struct_def.fields.vec.rbegin();
                it != struct_def.fields.vec.rend(); ++it) {
             auto &field = **it;
-            auto field_name = ConvertCase(field.name, Case::kLowerCamel);
-            auto method_name = ConvertCase(field.name, Case::kUpperCamel);
+            auto field_name = namer_.Field(field);
             if (!field.deprecated &&
                 (!struct_def.sortbysize ||
                  size == SizeOf(field.value.type.base_type))) {
-              code += "    " + struct_def.name + ".";
-              code += "add";
-              code += method_name + "(builder, " + field_name;
+              code += "    " + struct_class + ".";
+              code += namer_.Method("add", field) + "(builder, " + field_name;
               if (!IsScalar(field.value.type.base_type)) code += "Offset";
               code += ");\n";
             }
           }
         }
-        code += "    return " + struct_def.name + ".";
-        code += "end" + struct_def.name;
+        code += "    return " + struct_class + ".";
+        code += namer_.LegacyJavaMethod2("end", struct_def, "");
         code += "(builder);\n  }\n\n";
       }
       // Generate a set of static methods that allow table construction,
@@ -1054,7 +1087,7 @@
       // { builder.addShort(id, name, default); }
       // Unlike the Create function, these always work.
       code += "  public static void start";
-      code += struct_def.name;
+      code += struct_class;
       code += "(FlatBufferBuilder builder) { builder.";
       code += "startTable(";
       code += NumToString(struct_def.fields.vec.size()) + "); }\n";
@@ -1062,22 +1095,34 @@
            it != struct_def.fields.vec.end(); ++it) {
         auto &field = **it;
         if (field.deprecated) continue;
-        if (field.key) key_field = &field;
-        code += "  public static void add";
-        code += ConvertCase(field.name, Case::kUpperCamel);
+
+        code += "  public static void " + namer_.Method("add", field);
         code += "(FlatBufferBuilder builder, ";
         code += GenTypeBasic(DestinationType(field.value.type, false));
-        auto argname = ConvertCase(field.name, Case::kLowerCamel);
+        auto argname = namer_.Field(field);
         if (!IsScalar(field.value.type.base_type)) argname += "Offset";
         code += " " + argname + ") { builder.add";
         code += GenMethod(field.value.type) + "(";
-        code += NumToString(it - struct_def.fields.vec.begin()) + ", ";
-        code += SourceCastBasic(field.value.type);
-        code += argname;
-        code += ", ";
-        code += SourceCastBasic(field.value.type);
-        code += GenDefaultValue(field);
-        code += "); }\n";
+
+        if (field.key) {
+          // field has key attribute, so always need to exist
+          // even if its value is equal to default.
+          // Generated code will bypass default checking
+          // resulting in { builder.addShort(name); slot(id); }
+          key_field = &field;
+          code += SourceCastBasic(field.value.type);
+          code += argname;
+          code += "); builder.slot(" +
+                  NumToString(it - struct_def.fields.vec.begin()) + "); }\n";
+        } else {
+          code += NumToString(it - struct_def.fields.vec.begin()) + ", ";
+          code += SourceCastBasic(field.value.type);
+          code += argname;
+          code += ", ";
+          code += SourceCastBasic(field.value.type);
+          code += GenDefaultValue(field);
+          code += "); }\n";
+        }
         if (IsVector(field.value.type)) {
           auto vector_type = field.value.type.VectorType();
           auto alignment = InlineAlignment(vector_type);
@@ -1089,20 +1134,17 @@
                  vector_type.base_type == BASE_TYPE_UCHAR)) {
               // Handle byte[] and ByteBuffers separately for Java
               code += "  public static " + GenVectorOffsetType() + " ";
-              code += "create";
-              code += ConvertCase(field.name, Case::kUpperCamel);
+              code += namer_.Method("create", field);
               code += "Vector(FlatBufferBuilder builder, byte[] data) ";
               code += "{ return builder.createByteVector(data); }\n";
 
               code += "  public static " + GenVectorOffsetType() + " ";
-              code += "create";
-              code += ConvertCase(field.name, Case::kUpperCamel);
+              code += namer_.Method("create", field);
               code += "Vector(FlatBufferBuilder builder, ByteBuffer data) ";
               code += "{ return builder.createByteVector(data); }\n";
             } else {
               code += "  public static " + GenVectorOffsetType() + " ";
-              code += "create";
-              code += ConvertCase(field.name, Case::kUpperCamel);
+              code += namer_.Method("create", field);
               code += "Vector(FlatBufferBuilder builder, ";
               code += GenTypeBasic(DestinationType(vector_type, false)) +
                       "[] data) ";
@@ -1123,8 +1165,7 @@
           }
           // Generate a method to start a vector, data to be added manually
           // after.
-          code += "  public static void start";
-          code += ConvertCase(field.name, Case::kUpperCamel);
+          code += "  public static void " + namer_.Method("start", field);
           code += "Vector(FlatBufferBuilder builder, int numElems) ";
           code += "{ builder.startVector(";
           code += NumToString(elem_size);
@@ -1133,7 +1174,7 @@
         }
       }
       code += "  public static " + GenOffsetType() + " ";
-      code += "end" + struct_def.name;
+      code += namer_.LegacyJavaMethod2("end", struct_def, "");
       code += "(FlatBufferBuilder builder) {\n    int o = builder.";
       code += "endTable();\n";
       for (auto it = struct_def.fields.vec.begin();
@@ -1150,8 +1191,9 @@
         std::string size_prefix[] = { "", "SizePrefixed" };
         for (int i = 0; i < 2; ++i) {
           code += "  public static void ";
-          code += "finish" + size_prefix[i] + struct_def.name;
-          code += "Buffer(FlatBufferBuilder builder, " + GenOffsetType();
+          code += namer_.LegacyJavaMethod2("finish" + size_prefix[i],
+                                           struct_def, "Buffer");
+          code += "(FlatBufferBuilder builder, " + GenOffsetType();
           code += " offset) {";
           code += " builder.finish" + size_prefix[i] + "(offset";
 
@@ -1170,9 +1212,9 @@
       code += GenKeyGetter(key_field);
       code += " }\n";
 
-      code += "\n  public static " + struct_def.name;
+      code += "\n  public static " + struct_class;
       code += " __lookup_by_key(";
-      code += struct_def.name + " obj, ";
+      code += struct_class + " obj, ";
       code += "int vectorLocation, ";
       code += GenTypeNameDest(key_field->value.type);
       code += " key, ByteBuffer bb) {\n";
@@ -1194,15 +1236,15 @@
       code += "        span -= middle;\n";
       code += "      } else {\n";
       code += "        return ";
-      code += "(obj == null ? new " + struct_def.name + "() : obj)";
+      code += "(obj == null ? new " + struct_class + "() : obj)";
       code += ".__assign(tableOffset, bb);\n";
       code += "      }\n    }\n";
       code += "    return null;\n";
       code += "  }\n";
     }
-    GenVectorAccessObject(struct_def, code_ptr);
+    GenVectorAccessObject(struct_def, code);
     if (opts.generate_object_based_api) {
-      GenPackUnPack_ObjectAPI(struct_def, code_ptr, opts, struct_has_create,
+      GenPackUnPack_ObjectAPI(struct_def, code, opts, struct_has_create,
                               field_has_create_set);
     }
     code += "}\n\n";
@@ -1210,14 +1252,12 @@
 
   std::string GenOptionalScalarCheck(FieldDef &field) const {
     if (!field.IsScalarOptional()) return "";
-    return "  public boolean has" + ConvertCase(field.name, Case::kUpperCamel) +
+    return "  public boolean " + namer_.Method("has", field) +
            "() { return 0 != __offset(" + NumToString(field.value.offset) +
            "); }\n";
   }
 
-  void GenVectorAccessObject(StructDef &struct_def,
-                             std::string *code_ptr) const {
-    auto &code = *code_ptr;
+  void GenVectorAccessObject(StructDef &struct_def, std::string &code) const {
     // Generate a vector of structs accessor class.
     code += "\n";
     code += "  ";
@@ -1234,7 +1274,7 @@
     code += "__assign(int _vector, int _element_size, ByteBuffer _bb) { ";
     code += "__reset(_vector, _element_size, _bb); return this; }\n\n";
 
-    auto type_name = struct_def.name;
+    auto type_name = namer_.Type(struct_def);
     auto method_start = method_indent + "public " + type_name + " get";
     // Generate the accessors that don't do object reuse.
     code += method_start + "(int j) { return get";
@@ -1276,18 +1316,12 @@
     code += "  }\n";
   }
 
-  std::string GenGetterFuncName_ObjectAPI(const std::string &field_name) const {
-    return "get" + ConvertCase(field_name, Case::kUpperCamel);
-  }
-
-  void GenEnum_ObjectAPI(EnumDef &enum_def, std::string *code_ptr,
-                         const IDLOptions &opts) const {
-    auto &code = *code_ptr;
+  void GenEnum_ObjectAPI(EnumDef &enum_def, std::string &code) const {
     if (enum_def.generated) return;
     code += "import com.google.flatbuffers.FlatBufferBuilder;\n\n";
 
     if (!enum_def.attributes.Lookup("private")) { code += "public "; }
-    auto union_name = enum_def.name + "Union";
+    auto union_name = namer_.Type(enum_def) + "Union";
     auto union_type =
         GenTypeBasic(DestinationType(enum_def.underlying_type, false));
     code += "class " + union_name + " {\n";
@@ -1304,15 +1338,16 @@
     code += "  public void setValue(Object value) { this.value = value; }\n\n";
     // Constructor
     code += "  public " + union_name + "() {\n";
-    code += "    this.type = " + enum_def.name + "." +
-            enum_def.Vals()[0]->name + ";\n";
+    code +=
+        "    this.type = " + namer_.EnumVariant(enum_def, *enum_def.Vals()[0]) +
+        ";\n";
     code += "    this.value = null;\n";
     code += "  }\n\n";
     // As
     for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) {
       auto &ev = **it;
       if (ev.union_type.base_type == BASE_TYPE_NONE) continue;
-      auto type_name = GenTypeGet_ObjectAPI(ev.union_type, opts, false, true);
+      auto type_name = GenTypeGet_ObjectAPI(ev.union_type, false, true);
       if (ev.union_type.base_type == BASE_TYPE_STRUCT &&
           ev.union_type.struct_def->attributes.Lookup("private")) {
         code += "  ";
@@ -1332,7 +1367,7 @@
       if (ev.union_type.base_type == BASE_TYPE_NONE) {
         continue;
       } else {
-        code += "      case " + enum_def.name + "." + ev.name + ": return ";
+        code += "      case " + namer_.EnumVariant(enum_def, ev) + ": return ";
         if (IsString(ev.union_type)) {
           code += "builder.createString(_o.as" + ev.name + "());\n";
         } else {
@@ -1347,41 +1382,23 @@
     code += "}\n\n";
   }
 
-  std::string GenSetterFuncName_ObjectAPI(const std::string &field_name) const {
-    return "set" + ConvertCase(field_name, Case::kUpperCamel);
-  }
-
-  std::string GenTypeName_ObjectAPI(const std::string &name,
-                                    const IDLOptions &opts) const {
-    return opts.object_prefix + name + opts.object_suffix;
-  }
-
-  void GenUnionUnPack_ObjectAPI(const EnumDef &enum_def, std::string *code_ptr,
+  void GenUnionUnPack_ObjectAPI(const EnumDef &enum_def, std::string &code,
                                 const std::string &type_name,
-                                const std::string &camel_name,
+                                const std::string &field_name,
                                 bool is_vector) const {
-    auto &code = *code_ptr;
+    const std::string variable_type =
+        is_vector ? type_name.substr(0, type_name.length() - 2) : type_name;
+    const std::string variable_name =
+        "_" + namer_.Variable("o", field_name) + (is_vector ? "Element" : "");
+    const std::string type_params = is_vector ? "_j" : "";
+    const std::string value_params = is_vector ? ", _j" : "";
+    const std::string indent = (is_vector ? "      " : "    ");
 
-    std::string variable_type = type_name;
-    std::string variable_name =
-        "_o" + ConvertCase(camel_name, Case::kUpperCamel);
-    std::string type_params = "";
-    std::string value_params = "";
-    std::string func_suffix = "()";
-    std::string indent = "    ";
-    if (is_vector) {
-      variable_type = type_name.substr(0, type_name.length() - 2);
-      variable_name += "Element";
-      type_params = "_j";
-      value_params = ", _j";
-      func_suffix = "(_j)";
-      indent = "      ";
-    }
     code += indent + variable_type + " " + variable_name + " = new " +
             variable_type + "();\n";
     code += indent +
             GenTypeBasic(DestinationType(enum_def.underlying_type, false)) +
-            " " + variable_name + "Type = " + camel_name + "Type(" +
+            " " + variable_name + "Type = " + field_name + "Type(" +
             type_params + ");\n";
     code += indent + variable_name + ".setType(" + variable_name + "Type);\n";
     code += indent + "Table " + variable_name + "Value;\n";
@@ -1399,10 +1416,10 @@
                      // Java which doesn't handle non Table types. Should be
                      // deleted when issue #6561 is fixed.
         }
-        code += indent + "  case " + WrapInNameSpace(enum_def) + "." + ev.name +
-                ":\n";
+        code += indent + "  case " +
+                namer_.NamespacedEnumVariant(enum_def, ev) + ":\n";
         auto actual_type = GenTypeGet(ev.union_type);
-        code += indent + "    " + variable_name + "Value = " + camel_name +
+        code += indent + "    " + variable_name + "Value = " + field_name +
                 "(new " + actual_type + "()" + value_params + ");\n";
         code += indent + "    " + variable_name + ".setValue(" + variable_name +
                 "Value != null ? ((" + actual_type + ") " + variable_name +
@@ -1413,17 +1430,16 @@
     code += indent + "  default: break;\n";
     code += indent + "}\n";
     if (is_vector) {
-      code += indent + "_o" + ConvertCase(camel_name, Case::kUpperCamel) +
+      code += indent + "_" + namer_.Variable("o", field_name) +
               "[_j] = " + variable_name + ";\n";
     }
   }
 
   void GenPackUnPack_ObjectAPI(
-      StructDef &struct_def, std::string *code_ptr, const IDLOptions &opts,
+      StructDef &struct_def, std::string &code, const IDLOptions &opts,
       bool struct_has_create,
       const std::set<FieldDef *> &field_has_create) const {
-    auto &code = *code_ptr;
-    auto struct_name = GenTypeName_ObjectAPI(struct_def.name, opts);
+    auto struct_name = namer_.ObjectType(struct_def);
     // unpack()
     code += "  public " + struct_name + " unpack() {\n";
     code += "    " + struct_name + " _o = new " + struct_name + "();\n";
@@ -1434,35 +1450,34 @@
     code += "  public void unpackTo(" + struct_name + " _o) {\n";
     for (auto it = struct_def.fields.vec.begin();
          it != struct_def.fields.vec.end(); ++it) {
-      auto &field = **it;
+      const auto &field = **it;
       if (field.deprecated) continue;
       if (field.value.type.base_type == BASE_TYPE_UTYPE) continue;
       if (field.value.type.element == BASE_TYPE_UTYPE) continue;
-      auto camel_name = ConvertCase(field.name, Case::kLowerCamel);
-      auto camel_name_with_first = ConvertCase(field.name, Case::kUpperCamel);
-      auto type_name =
-          GenTypeGet_ObjectAPI(field.value.type, opts, false, true);
+      const auto accessor = namer_.Method(field);
+      const auto variable = "_" + namer_.Variable("o", field);
+      const auto get_field = namer_.Method("get", field);
+      const auto set_field = namer_.Method("set", field);
+
+      auto type_name = GenTypeGet_ObjectAPI(field.value.type, false, true);
       if (field.IsScalarOptional())
         type_name = ConvertPrimitiveTypeToObjectWrapper_ObjectAPI(type_name);
-      auto start = "    " + type_name + " _o" + camel_name_with_first + " = ";
+      auto start = "    " + type_name + " " + variable + " = ";
       auto call_setter = true;
       switch (field.value.type.base_type) {
         case BASE_TYPE_STRUCT: {
           auto fixed = struct_def.fixed && field.value.type.struct_def->fixed;
           if (fixed) {
-            code += "    " + camel_name + "().unpackTo(_o.get" +
-                    camel_name_with_first + "());\n";
+            code +=
+                "    " + accessor + "().unpackTo(_o." + get_field + "());\n";
           } else {
-            code += "    if (" + camel_name + "() != null) ";
+            code += "    if (" + accessor + "() != null) ";
             if (field.value.type.struct_def->fixed) {
-              code += camel_name + "().unpackTo(_o.get" +
-                      camel_name_with_first + "());\n";
+              code += accessor + "().unpackTo(_o." + get_field + "());\n";
             } else {
-              code += "_o." + GenSetterFuncName_ObjectAPI(field.name) + "(" +
-                      camel_name + "().unpack());\n";
+              code += "_o." + set_field + "(" + accessor + "().unpack());\n";
             }
-            code += "    else _o." + GenSetterFuncName_ObjectAPI(field.name) +
-                    "(null);\n";
+            code += "    else _o." + set_field + "(null);\n";
           }
           call_setter = false;
           break;
@@ -1471,38 +1486,38 @@
           auto length_str = NumToString(field.value.type.fixed_length);
           auto unpack_method =
               field.value.type.struct_def == nullptr ? "" : ".unpack()";
-          code +=
-              start + "_o." + GenGetterFuncName_ObjectAPI(field.name) + "();\n";
-          code += "    for (int _j = 0; _j < " + length_str + "; ++_j) { _o" +
-                  camel_name_with_first + "[_j] = " + camel_name + "(_j)" +
-                  unpack_method + "; }\n";
+          code += start + "_o." + get_field + "();\n";
+          code += "    for (int _j = 0; _j < " + length_str + "; ++_j) { " +
+                  variable + "[_j] = " + accessor + "(_j)" + unpack_method +
+                  "; }\n";
           call_setter = false;
           break;
         }
         case BASE_TYPE_VECTOR:
           if (field.value.type.element == BASE_TYPE_UNION) {
             code += start + "new " +
-                    GenConcreteTypeGet_ObjectAPI(field.value.type, opts)
+                    GenConcreteTypeGet_ObjectAPI(field.value.type)
                         .substr(0, type_name.length() - 1) +
-                    camel_name + "Length()];\n";
-            code += "    for (int _j = 0; _j < " + camel_name +
-                    "Length(); ++_j) {\n";
-            GenUnionUnPack_ObjectAPI(*field.value.type.enum_def, code_ptr,
-                                     type_name, camel_name, true);
+                    accessor + "Length()];\n";
+            code +=
+                "    for (int _j = 0; _j < " + accessor + "Length(); ++_j) {\n";
+            GenUnionUnPack_ObjectAPI(*field.value.type.enum_def, code,
+                                     type_name, accessor, true);
             code += "    }\n";
           } else if (field.value.type.element != BASE_TYPE_UTYPE) {
             auto fixed = field.value.type.struct_def == nullptr;
+            const auto length_accessor = namer_.Method(field, "length");
             code += start + "new " +
-                    GenConcreteTypeGet_ObjectAPI(field.value.type, opts)
+                    GenConcreteTypeGet_ObjectAPI(field.value.type)
                         .substr(0, type_name.length() - 1) +
-                    camel_name + "Length()];\n";
+                    length_accessor + "()];\n";
             code +=
-                "    for (int _j = 0; _j < " + camel_name + "Length(); ++_j) {";
-            code += "_o" + camel_name_with_first + "[_j] = ";
+                "    for (int _j = 0; _j < " + length_accessor + "(); ++_j) {";
+            code += variable + "[_j] = ";
             if (fixed) {
-              code += camel_name + "(_j)";
+              code += accessor + "(_j)";
             } else {
-              code += "(" + camel_name + "(_j) != null ? " + camel_name +
+              code += "(" + accessor + "(_j) != null ? " + accessor +
                       "(_j).unpack() : null)";
             }
             code += ";}\n";
@@ -1510,23 +1525,22 @@
           break;
         case BASE_TYPE_UTYPE: break;
         case BASE_TYPE_UNION: {
-          GenUnionUnPack_ObjectAPI(*field.value.type.enum_def, code_ptr,
-                                   type_name, camel_name, false);
+          GenUnionUnPack_ObjectAPI(*field.value.type.enum_def, code, type_name,
+                                   accessor, false);
           break;
         }
         default: {
           if (field.IsScalarOptional()) {
-            code += start + "has" + camel_name_with_first + "() ? " +
-                    camel_name + "() : null;\n";
+            code += start + namer_.Method("has", field) + "() ? " + accessor +
+                    "() : null;\n";
           } else {
-            code += start + camel_name + "();\n";
+            code += start + accessor + "();\n";
           }
           break;
         }
       }
       if (call_setter) {
-        code += "    _o." + GenSetterFuncName_ObjectAPI(field.name) + "(_o" +
-                camel_name_with_first + ");\n";
+        code += "    _o." + set_field + "(" + variable + ");\n";
       }
     }
     code += "  }\n";
@@ -1538,17 +1552,17 @@
          it != struct_def.fields.vec.end(); ++it) {
       auto &field = **it;
       if (field.deprecated) continue;
-      auto camel_name = ConvertCase(field.name, Case::kLowerCamel);
-      auto camel_name_with_first = ConvertCase(field.name, Case::kUpperCamel);
+      const auto field_name = namer_.Field(field);
+      const auto variable = "_" + namer_.Variable("o", field);
+      const auto get_field = namer_.Method("get", field);
       // pre
       switch (field.value.type.base_type) {
         case BASE_TYPE_STRUCT: {
           if (!field.value.type.struct_def->fixed) {
-            code += "    " + GenOffsetType() + " _" + field.name + " = _o." +
-                    GenGetterFuncName_ObjectAPI(field.name) +
+            code += "    " + GenOffsetType() + " _" + namer_.Variable(field) +
+                    " = _o." + get_field +
                     "() == null ? 0 : " + GenTypeGet(field.value.type) +
-                    ".pack(builder, _o." +
-                    GenGetterFuncName_ObjectAPI(field.name) + "());\n";
+                    ".pack(builder, _o." + get_field + "());\n";
           } else if (struct_def.fixed && struct_has_create) {
             std::vector<FieldArrayLength> array_lengths;
             FieldArrayLength tmp_array_length = {
@@ -1556,60 +1570,54 @@
               field.value.type.fixed_length,
             };
             array_lengths.push_back(tmp_array_length);
-            GenStructPackDecl_ObjectAPI(*field.value.type.struct_def, code_ptr,
-                                        array_lengths);
+            GenStructPackDecl_ObjectAPI(*field.value.type.struct_def,
+                                        array_lengths, code);
           }
           break;
         }
         case BASE_TYPE_STRING: {
-          std::string create_string = "createString";
-          code += "    int _" + camel_name + " = _o." +
-                  GenGetterFuncName_ObjectAPI(field.name) +
+          code += "    int _" + field_name + " = _o." + get_field +
                   "() == null ? 0 : "
-                  "builder." +
-                  create_string + "(_o." +
-                  GenGetterFuncName_ObjectAPI(field.name) + "());\n";
+                  "builder.createString(_o." +
+                  get_field + "());\n";
           break;
         }
         case BASE_TYPE_VECTOR: {
           if (field_has_create.find(&field) != field_has_create.end()) {
-            auto property_name = camel_name;
+            auto property_name = field_name;
             auto gen_for_loop = true;
-            std::string array_name = "__" + camel_name;
+            std::string array_name = "__" + field_name;
             std::string array_type = "";
             std::string element_type = "";
             std::string to_array = "";
             switch (field.value.type.element) {
               case BASE_TYPE_STRING: {
-                std::string create_string = "createString";
                 array_type = "int";
                 element_type = "String";
-                to_array += "builder." + create_string + "(_e)";
+                to_array = "builder.createString(_e)";
                 break;
               }
               case BASE_TYPE_STRUCT:
                 array_type = "int";
                 element_type =
-                    GenTypeGet_ObjectAPI(field.value.type, opts, true, true);
+                    GenTypeGet_ObjectAPI(field.value.type, true, true);
                 ;
                 to_array = GenTypeGet(field.value.type) + ".pack(builder, _e)";
                 break;
               case BASE_TYPE_UTYPE:
-                property_name = camel_name.substr(0, camel_name.size() - 4);
+                property_name = field_name.substr(0, field_name.size() - 4);
                 array_type = GenTypeBasic(DestinationType(
                     field.value.type.enum_def->underlying_type, false));
                 element_type = field.value.type.enum_def->name + "Union";
-                to_array = "_o." + GenGetterFuncName_ObjectAPI(property_name) +
+                to_array = "_o." + namer_.Method("get", property_name) +
                            "()[_j].getType()";
                 break;
               case BASE_TYPE_UNION:
                 array_type = "int";
                 element_type =
-                    WrapInNameSpace(*field.value.type.enum_def) + "Union";
-                to_array = WrapInNameSpace(*field.value.type.enum_def) +
-                           "Union.pack(builder,  _o." +
-                           GenGetterFuncName_ObjectAPI(property_name) +
-                           "()[_j])";
+                    namer_.NamespacedType(*field.value.type.enum_def) + "Union";
+                to_array = element_type + ".pack(builder,  _o." +
+                           namer_.Method("get", property_name) + "()[_j])";
                 break;
               case BASE_TYPE_UCHAR:  // TODO this branch of the switch is due to
                                      // inconsistent behavior in unsigned byte.
@@ -1620,52 +1628,51 @@
                 break;
               default:
                 gen_for_loop = false;
-                array_name =
-                    "_o." + GenGetterFuncName_ObjectAPI(property_name) + "()";
+                array_name = "_o." + namer_.Method("get", property_name) + "()";
                 array_type = GenTypeNameDest(field.value.type);
                 element_type = array_type;
                 to_array = "_e";
                 break;
             }
-            code += "    int _" + camel_name + " = 0;\n";
-            code += "    if (_o." + GenGetterFuncName_ObjectAPI(property_name) +
+            code += "    int _" + field_name + " = 0;\n";
+            code += "    if (_o." + namer_.Method("get", property_name) +
                     "() != null) {\n";
             if (gen_for_loop) {
               code += "      " + array_type + "[] " + array_name + " = new " +
                       array_type + "[_o." +
-                      GenGetterFuncName_ObjectAPI(property_name) +
-                      "().length];\n";
+                      namer_.Method("get", property_name) + "().length];\n";
               code += "      int _j = 0;\n";
               code += "      for (" + element_type + " _e : _o." +
-                      GenGetterFuncName_ObjectAPI(property_name) + "()) { ";
+                      namer_.Method("get", property_name) + "()) { ";
               code += array_name + "[_j] = " + to_array + "; _j++;}\n";
             }
-            code += "      _" + camel_name + " = create" +
-                    camel_name_with_first + "Vector(builder, " + array_name +
-                    ");\n";
+            code += "      _" + field_name + " = " +
+                    namer_.Method("create", field) + "Vector(builder, " +
+                    array_name + ");\n";
             code += "    }\n";
           } else {
             auto type_name = GenTypeGet(field.value.type);
             auto element_type_name =
-                GenTypeGet_ObjectAPI(field.value.type, opts, true, true);
+                GenTypeGet_ObjectAPI(field.value.type, true, true);
             auto pack_method =
                 field.value.type.struct_def == nullptr
                     ? "builder.add" + GenMethod(field.value.type.VectorType()) +
-                          "(_o" + camel_name_with_first + "[_j]);"
-                    : type_name + ".pack(builder, _o" + camel_name_with_first +
-                          "[_j]);";
-            code += "    int _" + camel_name + " = 0;\n";
-            code += "    " + element_type_name + "[] _o" +
-                    camel_name_with_first + " = _o." +
-                    GenGetterFuncName_ObjectAPI(field.name) + "();\n";
-            code += "    if (_o" + camel_name_with_first + " != null) {\n";
-            code += "      start" + camel_name_with_first +
-                    "Vector(builder, _o" + camel_name_with_first +
-                    ".length);\n";
-            code += "      for (int _j = _o" + camel_name_with_first +
+                          "(" + variable + "[_j]);"
+                    : "_unused_offset = " + type_name + ".pack(builder, " +
+                          variable + "[_j]);";
+            code += "    int _" + field_name + " = 0;\n";
+            code += "    " + element_type_name + "[] " + variable + " = _o." +
+                    get_field + "();\n";
+            code += "    if (" + variable + " != null) {\n";
+            if (field.value.type.struct_def != nullptr) {
+              code += "      int _unused_offset = 0;\n";
+            }
+            code += "      " + namer_.Method("start", field) +
+                    "Vector(builder, " + variable + ".length);\n";
+            code += "      for (int _j = " + variable +
                     ".length - 1; _j >=0; _j--) { ";
             code += pack_method + "}\n";
-            code += "      _" + camel_name + " = builder.endVector();\n";
+            code += "      _" + field_name + " = builder.endVector();\n";
             code += "    }\n";
           }
           break;
@@ -1678,29 +1685,27 @@
               field.value.type.fixed_length,
             };
             array_lengths.push_back(tmp_array_length);
-            GenStructPackDecl_ObjectAPI(*field.value.type.struct_def, code_ptr,
-                                        array_lengths);
+            GenStructPackDecl_ObjectAPI(*field.value.type.struct_def,
+                                        array_lengths, code);
           } else {
             code += "    " +
-                    GenTypeGet_ObjectAPI(field.value.type, opts, false, true) +
-                    " _" + camel_name + " = _o." +
-                    GenGetterFuncName_ObjectAPI(field.name) + "();\n";
+                    GenTypeGet_ObjectAPI(field.value.type, false, true) + " _" +
+                    field_name + " = _o." + get_field + "();\n";
           }
           break;
         }
         case BASE_TYPE_UNION: {
-          code +=
-              "    " +
-              GenTypeBasic(DestinationType(
-                  field.value.type.enum_def->underlying_type, false)) +
-              " _" + camel_name + "Type = _o.get" + camel_name_with_first +
-              "() == null ? " + WrapInNameSpace(*field.value.type.enum_def) +
-              ".NONE : " + "_o.get" + camel_name_with_first + "().getType();\n";
-          code += "    " + GenOffsetType() + " _" + camel_name + " = _o.get" +
-                  camel_name_with_first + "() == null ? 0 : " +
-                  WrapInNameSpace(*field.value.type.enum_def) +
-                  "Union.pack(builder, _o.get" + camel_name_with_first +
-                  "());\n";
+          code += "    " +
+                  GenTypeBasic(DestinationType(
+                      field.value.type.enum_def->underlying_type, false)) +
+                  " _" + field_name + "Type = _o." + get_field +
+                  "() == null ? " +
+                  namer_.NamespacedType(*field.value.type.enum_def) +
+                  ".NONE : " + "_o." + get_field + "().getType();\n";
+          code += "    " + GenOffsetType() + " _" + field_name + " = _o." +
+                  get_field + "() == null ? 0 : " +
+                  namer_.NamespacedType(*field.value.type.enum_def) +
+                  "Union.pack(builder, _o." + get_field + "());\n";
           break;
         }
         default: break;
@@ -1708,42 +1713,42 @@
     }
     if (struct_has_create) {
       // Create
-      code += "    return create" + struct_def.name + "(\n";
+      code += "    return " +
+              namer_.LegacyJavaMethod2("create", struct_def, "") + "(\n";
       code += "      builder";
       for (auto it = struct_def.fields.vec.begin();
            it != struct_def.fields.vec.end(); ++it) {
         auto &field = **it;
         if (field.deprecated) continue;
-        auto camel_name = ConvertCase(field.name, Case::kLowerCamel);
+        const auto field_name = namer_.Field(field);
+        const auto get_field = namer_.Method("get", field);
         switch (field.value.type.base_type) {
           case BASE_TYPE_STRUCT: {
             if (struct_def.fixed) {
-              GenStructPackCall_ObjectAPI(*field.value.type.struct_def,
-                                          code_ptr,
-                                          "      _" + camel_name + "_");
+              GenStructPackCall_ObjectAPI(*field.value.type.struct_def, code,
+                                          "      _" + field_name + "_");
             } else {
               code += ",\n";
               if (field.value.type.struct_def->fixed) {
                 if (opts.generate_object_based_api)
-                  code += "      _o." + camel_name;
+                  code += "      _o." + field_name;
                 else
                   // Seems like unreachable code
                   code += "      " + GenTypeGet(field.value.type) +
-                          ".Pack(builder, _o." + camel_name + ")";
+                          ".Pack(builder, _o." + field_name + ")";
               } else {
-                code += "      _" + field.name;
+                code += "      _" + field_name;
               }
             }
             break;
           }
           case BASE_TYPE_ARRAY: {
             if (field.value.type.struct_def != nullptr) {
-              GenStructPackCall_ObjectAPI(*field.value.type.struct_def,
-                                          code_ptr,
-                                          "      _" + camel_name + "_");
+              GenStructPackCall_ObjectAPI(*field.value.type.struct_def, code,
+                                          "      _" + field_name + "_");
             } else {
               code += ",\n";
-              code += "      _" + camel_name;
+              code += "      _" + field_name;
             }
             break;
           }
@@ -1752,82 +1757,78 @@
           case BASE_TYPE_STRING: FLATBUFFERS_FALLTHROUGH();  // fall thru
           case BASE_TYPE_VECTOR: {
             code += ",\n";
-            code += "      _" + camel_name;
+            code += "      _" + field_name;
             break;
           }
           default:  // scalar
             code += ",\n";
-            code +=
-                "      _o." + GenGetterFuncName_ObjectAPI(field.name) + "()";
+            code += "      _o." + get_field + "()";
             break;
         }
       }
       code += ");\n";
     } else {
       // Start, End
-      code += "    start" + struct_def.name + "(builder);\n";
+      code += "    " + namer_.LegacyJavaMethod2("start", struct_def, "") +
+              "(builder);\n";
       for (auto it = struct_def.fields.vec.begin();
            it != struct_def.fields.vec.end(); ++it) {
         auto &field = **it;
         if (field.deprecated) continue;
-        auto camel_name = ConvertCase(field.name, Case::kLowerCamel);
-        auto camel_name_with_first = ConvertCase(field.name, Case::kUpperCamel);
+        const auto arg = "_" + namer_.Variable(field);
+        const auto get_field = namer_.Method("get", field);
+        const auto add_field = namer_.Method("add", field);
+
         switch (field.value.type.base_type) {
           case BASE_TYPE_STRUCT: {
             if (field.value.type.struct_def->fixed) {
-              code += "    add" + camel_name_with_first + "(builder, " +
+              code += "    " + add_field + "(builder, " +
                       GenTypeGet(field.value.type) + ".pack(builder, _o." +
-                      GenGetterFuncName_ObjectAPI(field.name) + "()));\n";
+                      get_field + "()));\n";
             } else {
-              code += "    add" + camel_name_with_first + "(builder, _" +
-                      field.name + ");\n";
+              code += "    " + add_field + "(builder, " + arg + ");\n";
             }
             break;
           }
           case BASE_TYPE_STRING: FLATBUFFERS_FALLTHROUGH();  // fall thru
           case BASE_TYPE_ARRAY: FLATBUFFERS_FALLTHROUGH();   // fall thru
           case BASE_TYPE_VECTOR: {
-            code += "    add" + camel_name_with_first + "(builder, _" +
-                    camel_name + ");\n";
+            code += "    " + add_field + "(builder, " + arg + ");\n";
             break;
           }
           case BASE_TYPE_UTYPE: break;
           case BASE_TYPE_UNION: {
-            code += "    add" + camel_name_with_first + "Type(builder, _" +
-                    camel_name + "Type);\n";
-            code += "    add" + camel_name_with_first + "(builder, _" +
-                    camel_name + ");\n";
+            code += "    " + add_field + "Type(builder, " + arg + "Type);\n";
+            code += "    " + add_field + "(builder, " + arg + ");\n";
             break;
           }
           // scalar
           default: {
             if (field.IsScalarOptional()) {
-              code += "    if (_o." + GenGetterFuncName_ObjectAPI(field.name) +
-                      "() != null) { add" + camel_name_with_first +
-                      "(builder, _o." +
-                      GenGetterFuncName_ObjectAPI(field.name) + "()); }\n";
+              code += "    if (_o." + get_field + "() != null) { " + add_field +
+                      "(builder, _o." + get_field + "()); }\n";
             } else {
-              code += "    add" + camel_name_with_first + "(builder, _o." +
-                      GenGetterFuncName_ObjectAPI(field.name) + "());\n";
+              code +=
+                  "    " + add_field + "(builder, _o." + get_field + "());\n";
             }
             break;
           }
         }
       }
-      code += "    return end" + struct_def.name + "(builder);\n";
+      code += "    return " + namer_.LegacyJavaMethod2("end", struct_def, "") +
+              "(builder);\n";
     }
     code += "  }\n";
   }
 
-  void GenStructPackDecl_ObjectAPI(
-      const StructDef &struct_def, std::string *code_ptr,
-      std::vector<FieldArrayLength> &array_lengths) const {
-    auto &code = *code_ptr;
+  void GenStructPackDecl_ObjectAPI(const StructDef &struct_def,
+                                   std::vector<FieldArrayLength> &array_lengths,
+                                   std::string &code) const {
     for (auto it = struct_def.fields.vec.begin();
          it != struct_def.fields.vec.end(); ++it) {
-      auto &field = **it;
-      auto is_array = IsArray(field.value.type);
-      const auto &field_type =
+      const FieldDef &field = **it;
+      const bool is_array = IsArray(field.value.type);
+      const Type &field_type =
           is_array ? field.value.type.VectorType() : field.value.type;
       FieldArrayLength tmp_array_length = {
         field.name,
@@ -1835,8 +1836,8 @@
       };
       array_lengths.push_back(tmp_array_length);
       if (field_type.struct_def != nullptr) {
-        GenStructPackDecl_ObjectAPI(*field_type.struct_def, code_ptr,
-                                    array_lengths);
+        GenStructPackDecl_ObjectAPI(*field_type.struct_def, array_lengths,
+                                    code);
       } else {
         std::vector<FieldArrayLength> array_only_lengths;
         for (size_t i = 0; i < array_lengths.size(); ++i) {
@@ -1846,7 +1847,7 @@
         }
         std::string name;
         for (size_t i = 0; i < array_lengths.size(); ++i) {
-          name += "_" + ConvertCase(array_lengths[i].name, Case::kLowerCamel);
+          name += "_" + namer_.Variable(array_lengths[i].name);
         }
         code += "    " + GenTypeBasic(field_type);
         if (array_only_lengths.size() > 0) {
@@ -1878,8 +1879,7 @@
           }
           code += "] = _o";
           for (size_t i = 0, j = 0; i < array_lengths.size(); ++i) {
-            code +=
-                "." + GenGetterFuncName_ObjectAPI(array_lengths[i].name) + "()";
+            code += "." + namer_.Method("get", array_lengths[i].name) + "()";
             if (array_lengths[i].length <= 0) continue;
             code += "[idx" + NumToString(j++) + "]";
           }
@@ -1891,8 +1891,7 @@
           code += " " + name + " = ";
           code += "_o";
           for (size_t i = 0; i < array_lengths.size(); ++i) {
-            code +=
-                "." + GenGetterFuncName_ObjectAPI(array_lengths[i].name) + "()";
+            code += "." + namer_.Method("get", array_lengths[i].name) + "()";
           }
           code += ";";
         }
@@ -1903,26 +1902,24 @@
   }
 
   void GenStructPackCall_ObjectAPI(const StructDef &struct_def,
-                                   std::string *code_ptr,
+                                   std::string &code,
                                    std::string prefix) const {
-    auto &code = *code_ptr;
     for (auto it = struct_def.fields.vec.begin();
          it != struct_def.fields.vec.end(); ++it) {
       auto &field = **it;
       const auto &field_type = field.value.type;
       if (field_type.struct_def != nullptr) {
-        GenStructPackCall_ObjectAPI(
-            *field_type.struct_def, code_ptr,
-            prefix + ConvertCase(field.name, Case::kLowerCamel) + "_");
+        GenStructPackCall_ObjectAPI(*field_type.struct_def, code,
+                                    prefix + namer_.Field(field) + "_");
       } else {
         code += ",\n";
-        code += prefix + ConvertCase(field.name, Case::kLowerCamel);
+        code += prefix + namer_.Field(field);
       }
     }
   }
 
   std::string ConvertPrimitiveTypeToObjectWrapper_ObjectAPI(
-      std::string type_name) const {
+      const std::string &type_name) const {
     if (type_name == "boolean")
       return "Boolean";
     else if (type_name == "byte")
@@ -1942,8 +1939,8 @@
     return type_name;
   }
 
-  std::string GenTypeGet_ObjectAPI(flatbuffers::Type type,
-                                   const IDLOptions &opts, bool vectorelem,
+  std::string GenTypeGet_ObjectAPI(const flatbuffers::Type &type,
+                                   bool vectorelem,
                                    bool wrap_in_namespace) const {
     auto type_name = GenTypeNameDest(type);
     // Replace to ObjectBaseAPI Type Name
@@ -1953,15 +1950,14 @@
       case BASE_TYPE_VECTOR: {
         if (type.struct_def != nullptr) {
           auto type_name_length = type.struct_def->name.length();
-          auto new_type_name =
-              GenTypeName_ObjectAPI(type.struct_def->name, opts);
+          auto new_type_name = namer_.ObjectType(*type.struct_def);
           type_name.replace(type_name.length() - type_name_length,
                             type_name_length, new_type_name);
         } else if (type.element == BASE_TYPE_UNION) {
           if (wrap_in_namespace) {
-            type_name = WrapInNameSpace(*type.enum_def) + "Union";
+            type_name = namer_.NamespacedType(*type.enum_def) + "Union";
           } else {
-            type_name = type.enum_def->name + "Union";
+            type_name = namer_.Type(*type.enum_def) + "Union";
           }
         }
         break;
@@ -1969,9 +1965,9 @@
 
       case BASE_TYPE_UNION: {
         if (wrap_in_namespace) {
-          type_name = WrapInNameSpace(*type.enum_def) + "Union";
+          type_name = namer_.NamespacedType(*type.enum_def) + "Union";
         } else {
-          type_name = type.enum_def->name + "Union";
+          type_name = namer_.Type(*type.enum_def) + "Union";
         }
         break;
       }
@@ -1989,8 +1985,8 @@
     return type_name;
   }
 
-  std::string GenConcreteTypeGet_ObjectAPI(flatbuffers::Type type,
-                                           const IDLOptions &opts) const {
+  std::string GenConcreteTypeGet_ObjectAPI(
+      const flatbuffers::Type &type) const {
     auto type_name = GenTypeNameDest(type);
     // Replace to ObjectBaseAPI Type Name
     switch (type.base_type) {
@@ -1999,18 +1995,17 @@
       case BASE_TYPE_VECTOR: {
         if (type.struct_def != nullptr) {
           auto type_name_length = type.struct_def->name.length();
-          auto new_type_name =
-              GenTypeName_ObjectAPI(type.struct_def->name, opts);
+          auto new_type_name = namer_.ObjectType(*type.struct_def);
           type_name.replace(type_name.length() - type_name_length,
                             type_name_length, new_type_name);
         } else if (type.element == BASE_TYPE_UNION) {
-          type_name = WrapInNameSpace(*type.enum_def) + "Union";
+          type_name = namer_.NamespacedType(*type.enum_def) + "Union";
         }
         break;
       }
 
       case BASE_TYPE_UNION: {
-        type_name = WrapInNameSpace(*type.enum_def) + "Union";
+        type_name = namer_.NamespacedType(*type.enum_def) + "Union";
         break;
       }
       default: break;
@@ -2027,71 +2022,71 @@
     return type_name;
   }
 
-  void GenStruct_ObjectAPI(StructDef &struct_def, std::string *code_ptr,
-                           const IDLOptions &opts) const {
+  void GenStruct_ObjectAPI(const StructDef &struct_def,
+                           std::string &code) const {
     if (struct_def.generated) return;
-    auto &code = *code_ptr;
     if (struct_def.attributes.Lookup("private")) {
       // For Java, we leave the enum unmarked to indicate package-private
     } else {
       code += "public ";
     }
 
-    auto class_name = GenTypeName_ObjectAPI(struct_def.name, opts);
+    const auto class_name = namer_.ObjectType(struct_def);
     code += "class " + class_name;
     code += " {\n";
     // Generate Properties
     for (auto it = struct_def.fields.vec.begin();
          it != struct_def.fields.vec.end(); ++it) {
-      auto &field = **it;
+      const auto &field = **it;
       if (field.deprecated) continue;
       if (field.value.type.base_type == BASE_TYPE_UTYPE) continue;
       if (field.value.type.element == BASE_TYPE_UTYPE) continue;
-      auto type_name =
-          GenTypeGet_ObjectAPI(field.value.type, opts, false, true);
+      auto type_name = GenTypeGet_ObjectAPI(field.value.type, false, true);
       if (field.IsScalarOptional())
         type_name = ConvertPrimitiveTypeToObjectWrapper_ObjectAPI(type_name);
-      auto camel_name = ConvertCase(field.name, Case::kLowerCamel);
-      code += "  private " + type_name + " " + camel_name + ";\n";
+      const auto field_name = namer_.Field(field);
+      code += "  private " + type_name + " " + field_name + ";\n";
     }
     // Generate Java getters and setters
     code += "\n";
     for (auto it = struct_def.fields.vec.begin();
          it != struct_def.fields.vec.end(); ++it) {
-      auto &field = **it;
+      const auto &field = **it;
       if (field.deprecated) continue;
       if (field.value.type.base_type == BASE_TYPE_UTYPE) continue;
       if (field.value.type.element == BASE_TYPE_UTYPE) continue;
-      auto type_name =
-          GenTypeGet_ObjectAPI(field.value.type, opts, false, true);
+      const auto field_name = namer_.Field(field);
+      const auto get_field = namer_.Method("get", field);
+      auto type_name = GenTypeGet_ObjectAPI(field.value.type, false, true);
       if (field.IsScalarOptional())
         type_name = ConvertPrimitiveTypeToObjectWrapper_ObjectAPI(type_name);
-      auto camel_name = ConvertCase(field.name, Case::kLowerCamel);
-      code += "  public " + type_name + " " +
-              GenGetterFuncName_ObjectAPI(field.name) + "() { return " +
-              camel_name + "; }\n\n";
+
+      code += "  public " + type_name + " " + get_field + "() { return " +
+              field_name + "; }\n\n";
       std::string array_validation = "";
       if (field.value.type.base_type == BASE_TYPE_ARRAY) {
         array_validation =
-            "if (" + camel_name + " != null && " + camel_name +
+            "if (" + field_name + " != null && " + field_name +
             ".length == " + NumToString(field.value.type.fixed_length) + ") ";
       }
-      code += "  public void " + GenSetterFuncName_ObjectAPI(field.name) + "(" +
-              type_name + " " + camel_name + ") { " + array_validation +
-              "this." + camel_name + " = " + camel_name + "; }\n\n";
+      code += "  public void " + namer_.Method("set", field) + "(" + type_name +
+              " " + field_name + ") { " + array_validation + "this." +
+              field_name + " = " + field_name + "; }\n\n";
     }
     // Generate Constructor
     code += "\n";
     code += "  public " + class_name + "() {\n";
     for (auto it = struct_def.fields.vec.begin();
          it != struct_def.fields.vec.end(); ++it) {
-      auto &field = **it;
+      const auto &field = **it;
       if (field.deprecated) continue;
       if (field.value.type.base_type == BASE_TYPE_UTYPE) continue;
       if (field.value.type.element == BASE_TYPE_UTYPE) continue;
-      code += "    this." + ConvertCase(field.name, Case::kLowerCamel) + " = ";
-      auto type_name =
-          GenTypeGet_ObjectAPI(field.value.type, opts, false, true);
+      const auto get_field = namer_.Method("get", field);
+
+      code += "    this." + namer_.Field(field) + " = ";
+      const auto type_name =
+          GenTypeGet_ObjectAPI(field.value.type, false, true);
       if (IsScalar(field.value.type.base_type)) {
         if (field.IsScalarOptional()) {
           code += "null;\n";
@@ -2122,15 +2117,18 @@
     }
     code += "  }\n";
     if (parser_.root_struct_def_ == &struct_def) {
+      const std::string struct_type = namer_.Type(struct_def);
       code += "  public static " + class_name +
               " deserializeFromBinary(byte[] fbBuffer) {\n";
-      code += "    return " + struct_def.name + ".getRootAs" + struct_def.name +
+      code += "    return " + struct_type + "." +
+              namer_.LegacyJavaMethod2("getRootAs", struct_def, "") +
               "(ByteBuffer.wrap(fbBuffer)).unpack();\n";
       code += "  }\n";
       code += "  public byte[] serializeToBinary() {\n";
       code += "    FlatBufferBuilder fbb = new FlatBufferBuilder();\n";
-      code += "    " + struct_def.name + ".finish" + struct_def.name +
-              "Buffer(fbb, " + struct_def.name + ".pack(fbb, this));\n";
+      code += "    " + struct_type + "." +
+              namer_.LegacyJavaMethod2("finish", struct_def, "Buffer") +
+              "(fbb, " + struct_type + ".pack(fbb, this));\n";
       code += "    return fbb.sizedByteArray();\n";
       code += "  }\n";
     }
@@ -2140,6 +2138,7 @@
   // This tracks the current namespace used to determine if a type need to be
   // prefixed by its namespace
   const Namespace *cur_name_space_;
+  const IdlNamer namer_;
 };
 }  // namespace java