THRIFT-2469 "java:fullcamel" option to automatically camel-case underscored attribute names

Client: Java
Patch: Tom Lee
diff --git a/compiler/cpp/src/generate/t_java_generator.cc b/compiler/cpp/src/generate/t_java_generator.cc
index 9c6b4a5..2814099 100644
--- a/compiler/cpp/src/generate/t_java_generator.cc
+++ b/compiler/cpp/src/generate/t_java_generator.cc
@@ -66,6 +66,9 @@
     iter = parsed_options.find("nocamel");
     nocamel_style_ = (iter != parsed_options.end());
 
+    iter = parsed_options.find("fullcamel");
+    fullcamel_style_ = (iter != parsed_options.end());
+
     iter = parsed_options.find("android_legacy");
     android_legacy_ = (iter != parsed_options.end());
 
@@ -313,6 +316,7 @@
   bool bean_style_;
   bool private_members_;
   bool nocamel_style_;
+  bool fullcamel_style_;
   bool android_legacy_;
   bool java5_;
   bool sorted_containers_;
@@ -3821,10 +3825,26 @@
 
 /**
  * Applies the correct style to a string based on the value of nocamel_style_
+ * and/or fullcamel_style_
  */
 std::string t_java_generator::get_cap_name(std::string name){
   if (nocamel_style_) {
     return "_" + name;
+  } if (fullcamel_style_) {
+    std::string new_name;
+    new_name += toupper(name[0]);
+    for (size_t i = 1; i < name.size(); i++) {
+      if (name[i] == '_') {
+        if (i < name.size()-1) {
+          i++;
+          new_name += toupper(name[i]);
+        }
+      }
+      else {
+        new_name += name[i];
+      }
+    }
+    return new_name;
   } else {
     name[0] = toupper(name[0]);
     return name;
@@ -4574,6 +4594,7 @@
 "    beans:           Members will be private, and setter methods will return void.\n"
 "    private-members: Members will be private, but setter methods will return 'this' like usual.\n"
 "    nocamel:         Do not use CamelCase field accessors with beans.\n"
+"    fullcamel:       Convert underscored_field_names to CamelCase.\n"
 "    android_legacy:  Do not use java.io.IOException(throwable) (available for Android 2.3 and above).\n"
 "    java5:           Generate Java 1.5 compliant code (includes android_legacy flag).\n"
 "    reuse-objects:   Data objects will not be allocated, but existing instances will be used (read and write).\n"
diff --git a/lib/java/README.md b/lib/java/README.md
index 12b3afe..66bcfa5 100644
--- a/lib/java/README.md
+++ b/lib/java/README.md
@@ -29,7 +29,7 @@
 
 To compile the Java Thrift libraries, simply do the following:
 
-ant
+    ant
 
 Yep, that's easy. Look for libthrift.jar in the base directory.
 
@@ -39,11 +39,11 @@
 
 Build Thrift behind a proxy:
 
-ant -Dproxy.enabled=1 -Dproxy.host=myproxyhost -Dproxy.user=thriftuser -Dproxy.pass=topsecret
+    ant -Dproxy.enabled=1 -Dproxy.host=myproxyhost -Dproxy.user=thriftuser -Dproxy.pass=topsecret
 
 or via
 
-./configure --with-java ANT_FLAGS='-Dproxy.enabled=1 -Dproxy.host=myproxyhost -Dproxy.user=thriftuser -Dproxy.pass=topsecret'
+    ./configure --with-java ANT_FLAGS='-Dproxy.enabled=1 -Dproxy.host=myproxyhost -Dproxy.user=thriftuser -Dproxy.pass=topsecret'
 
 
 Dependencies
diff --git a/lib/java/build.xml b/lib/java/build.xml
index bfc619a..f8afed2 100755
--- a/lib/java/build.xml
+++ b/lib/java/build.xml
@@ -48,6 +48,7 @@
   <property name="gen" location="gen-java"/>
   <property name="genbean" location="gen-javabean"/>
   <property name="genreuse" location="gen-javareuse"/>
+  <property name="genfullcamel" location="gen-fullcamel"/>
 
   <property name="jar.file" location="${build.dir}/${final.name}.jar"/>
   <property name="test.jar.file" location="${build.dir}/${final.name}-test.jar"/>
@@ -167,6 +168,7 @@
     <delete dir="${gen}"/>
     <delete dir="${genbean}"/>
     <delete dir="${genreuse}"/>
+    <delete dir="${genfullcamel}"/>
   </target>
 
   <target name="optional-generate" unless="no-gen-thrift"> 
@@ -187,6 +189,10 @@
       <compilerarg value="-Xlint:deprecation"/>
       <!--<compilerarg value="-Xlint:unchecked"/>-->
     </javac>
+    <javac debug="true" srcdir="${genfullcamel}" destdir="${build.test.dir}" classpathref="test.classpath" includeantruntime="false" encoding="UTF-8">
+      <compilerarg value="-Xlint:deprecation"/>
+      <!--<compilerarg value="-Xlint:unchecked"/>-->
+    </javac>
     <javac debug="true" srcdir="${src.test}" destdir="${build.test.dir}" classpathref="test.classpath" includeantruntime="false" encoding="UTF-8">
       <compilerarg value="-Xlint:deprecation"/>
       <!--<compilerarg value="-Xlint:unchecked"/>-->
@@ -279,6 +285,12 @@
       <arg line="--gen java:hashcode ${test.thrift.home}/ManyOptionals.thrift"/>
     </exec>
     <exec executable="mkdir" failonerror="true">
+      <arg line="-p ${genfullcamel}"/>
+    </exec>
+    <exec executable="../../compiler/cpp/thrift" failonerror="true">
+      <arg line="--gen java:hashcode,fullcamel -out ${genfullcamel} ${test.thrift.home}/DenseLinkingTest.thrift"/>
+    </exec>
+    <exec executable="mkdir" failonerror="true">
       <arg line="-p ${genreuse}"/>
     </exec>
     <exec executable="../../compiler/cpp/thrift" failonerror="true">
diff --git a/test/DenseLinkingTest.thrift b/test/DenseLinkingTest.thrift
index cf61496..f18234b 100644
--- a/test/DenseLinkingTest.thrift
+++ b/test/DenseLinkingTest.thrift
@@ -34,6 +34,7 @@
 */
 
 namespace cpp thrift.test
+namespace java thrift.test
 
 struct OneOfEachZZ {
   1: bool im_true,