Created
August 11, 2010 18:48
-
-
Save fpotter/519511 to your computer and use it in GitHub Desktop.
Patch to make Thrift (rev 684377) output J2ME compatible Java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Index: compiler/cpp/src/generate/t_java_generator.cc | |
=================================================================== | |
--- compiler/cpp/src/generate/t_java_generator.cc (revision 687530) | |
+++ compiler/cpp/src/generate/t_java_generator.cc (working copy) | |
@@ -41,7 +41,21 @@ | |
iter = parsed_options.find("hashcode"); | |
gen_hash_code_ = (iter != parsed_options.end()); | |
- out_dir_base_ = (bean_style_ ? "gen-javabean" : "gen-java"); | |
+ iter = parsed_options.find("j2me"); | |
+ j2me_style_ = (iter != parsed_options.end()); | |
+ | |
+ if (bean_style_) | |
+ { | |
+ out_dir_base_ = "gen-javabean"; | |
+ } | |
+ else if (j2me_style_) | |
+ { | |
+ out_dir_base_ = "gen-j2me"; | |
+ } | |
+ else | |
+ { | |
+ out_dir_base_ = "gen-java"; | |
+ } | |
} | |
@@ -183,8 +197,8 @@ | |
bool bean_style_; | |
bool nocamel_style_; | |
+ bool j2me_style_; | |
bool gen_hash_code_; | |
- | |
}; | |
@@ -233,19 +247,32 @@ | |
* @return List of imports for Java types that are used in here | |
*/ | |
string t_java_generator::java_type_imports() { | |
+ | |
string hash_builder; | |
if (gen_hash_code_) { | |
hash_builder = "import org.apache.commons.lang.builder.HashCodeBuilder;\n"; | |
} | |
+ string collections; | |
+ | |
+ if (j2me_style_) { | |
+ collections = string() + | |
+ "import java.util.Vector;\n" + | |
+ "import java.util.Hashtable;\n"; | |
+ } else { | |
+ collections = string() + | |
+ "import java.util.List;\n" + | |
+ "import java.util.ArrayList;\n" + | |
+ "import java.util.Map;\n" + | |
+ "import java.util.HashMap;\n" + | |
+ "import java.util.Set;\n" + | |
+ "import java.util.HashSet;\n"; | |
+ } | |
+ | |
+ | |
return | |
string() + | |
- "import java.util.List;\n" + | |
- "import java.util.ArrayList;\n" + | |
- "import java.util.Map;\n" + | |
- "import java.util.HashMap;\n" + | |
- "import java.util.Set;\n" + | |
- "import java.util.HashSet;\n" + | |
+ collections + | |
hash_builder + | |
"import com.facebook.thrift.*;\n\n"; | |
} | |
@@ -567,7 +594,11 @@ | |
if (is_exception) { | |
out << "extends Exception "; | |
} | |
- out << "implements TBase, java.io.Serializable "; | |
+ out << "implements TBase "; | |
+ | |
+ if (!j2me_style_) { | |
+ out << ", java.io.Serializable "; | |
+ } | |
scope_up(out); | |
@@ -587,8 +618,17 @@ | |
if (members.size() > 0) { | |
out << | |
endl << | |
- indent() << "public final Isset __isset = new Isset();" << endl << | |
- indent() << "public static final class Isset implements java.io.Serializable {" << endl; | |
+ indent() << "public final Isset __isset = new Isset();" << endl; | |
+ | |
+ out << | |
+ indent() << "public static final class Isset"; | |
+ | |
+ if (!j2me_style_) { | |
+ out << " implements java.io.Serializable"; | |
+ } | |
+ | |
+ out << " {" << endl; | |
+ | |
indent_up(); | |
for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { | |
indent(out) << | |
@@ -723,7 +763,31 @@ | |
indent() << " return false;" << endl; | |
if (t->is_base_type() && ((t_base_type*)t)->is_binary()) { | |
- unequal = "!java.util.Arrays.equals(this." + name + ", that." + name + ")"; | |
+ | |
+ // There's no Arrays.equals on CLDC | |
+ if (j2me_style_) { | |
+ // test the length first so we give ourselves a chance to shortcircuit the comparison loop | |
+ out << | |
+ indent() << "boolean arraysAreEqual = (this." + name + ".length == that." + name + ".length);" << endl << | |
+ indent() << "if (arraysAreEqual)" << endl; | |
+ scope_up(out); | |
+ out << | |
+ indent() << "for (int i = 0; i < this." + name + ".length; i++)" << endl; | |
+ scope_up(out); | |
+ out << | |
+ indent() << "if (this." + name + "[i] != that." + name + "[i])" << endl; | |
+ scope_up(out); | |
+ out << | |
+ indent() << "arraysAreEqual = false;" << endl << | |
+ indent() << "break;" << endl; | |
+ scope_down(out); | |
+ scope_down(out); | |
+ scope_down(out); | |
+ | |
+ unequal = "!arraysAreEqual"; | |
+ } else { | |
+ unequal = "!java.util.Arrays.equals(this." + name + ", that." + name + ")"; | |
+ } | |
} else if (can_be_null) { | |
unequal = "!this." + name + ".equals(that." + name + ")"; | |
} else { | |
@@ -1158,8 +1222,11 @@ | |
indent() << "public String toString() {" << endl; | |
indent_up(); | |
+ // Prefer to use StringBuilder on J2SE platforms, as it doesn't have synchronization overhead | |
+ string className = j2me_style_ ? "StringBuffer" : "StringBuilder"; | |
+ | |
out << | |
- indent() << "StringBuilder sb = new StringBuilder(\"" << tstruct->get_name() << "(\");" << endl; | |
+ indent() << className + " sb = new " + className + "(\"" << tstruct->get_name() << "(\");" << endl; | |
const vector<t_field*>& fields = tstruct->get_members(); | |
vector<t_field*>::const_iterator f_iter; | |
@@ -1516,8 +1583,13 @@ | |
indent() << "private Iface iface_;" << endl; | |
if (extends.empty()) { | |
- f_service_ << | |
- indent() << "protected final HashMap<String,ProcessFunction> processMap_ = new HashMap<String,ProcessFunction>();" << endl; | |
+ if (j2me_style_) { | |
+ f_service_ << | |
+ indent() << "protected final Hashtable processMap_ = new Hashtable();" << endl; | |
+ } else { | |
+ f_service_ << | |
+ indent() << "protected final HashMap<String,ProcessFunction> processMap_ = new HashMap<String,ProcessFunction>();" << endl; | |
+ } | |
} | |
f_service_ << endl; | |
@@ -1533,7 +1605,7 @@ | |
// TODO(mcslee): validate message, was the seqid etc. legit? | |
f_service_ << | |
- indent() << "ProcessFunction fn = processMap_.get(msg.name);" << endl << | |
+ indent() << "ProcessFunction fn = (ProcessFunction) processMap_.get(msg.name);" << endl << | |
indent() << "if (fn == null) {" << endl << | |
indent() << " TProtocolUtil.skip(iprot, TType.STRUCT);" << endl << | |
indent() << " iprot.readMessageEnd();" << endl << | |
@@ -1917,8 +1989,11 @@ | |
generate_deserialize_field(out, &felem); | |
+ // CLDC only supports addElement | |
+ string addMethod = j2me_style_ ? "addElement" : "add"; | |
+ | |
indent(out) << | |
- prefix << ".add(" << elem << ");" << endl; | |
+ prefix << "." + addMethod + "(" << elem << ");" << endl; | |
} | |
@@ -2043,6 +2118,7 @@ | |
} | |
string iter = tmp("_iter"); | |
+ | |
if (ttype->is_map()) { | |
indent(out) << | |
"for (" << | |
@@ -2056,11 +2132,18 @@ | |
" : " << | |
prefix << ")"; | |
} else if (ttype->is_list()) { | |
- indent(out) << | |
- "for (" << | |
- type_name(((t_list*)ttype)->get_elem_type()) << " " << iter << | |
- " : " << | |
- prefix << ")"; | |
+ if (j2me_style_) { | |
+ indent(out) << | |
+ "final int count = " + prefix + ".size();" << endl; | |
+ indent(out) << | |
+ "for (int i = 0; i < count; i++) "; | |
+ } else { | |
+ indent(out) << | |
+ "for (" << | |
+ type_name(((t_list*)ttype)->get_elem_type()) << " " << iter << | |
+ " : " << | |
+ prefix << ")"; | |
+ } | |
} | |
scope_up(out); | |
@@ -2070,6 +2153,9 @@ | |
} else if (ttype->is_set()) { | |
generate_serialize_set_element(out, (t_set*)ttype, iter); | |
} else if (ttype->is_list()) { | |
+ if (j2me_style_) { | |
+ indent(out) << type_name(((t_list*)ttype)->get_elem_type()) << " " << iter << " = (" + type_name(((t_list*)ttype)->get_elem_type()) + ")" + prefix + ".elementAt(i);" << endl; | |
+ } | |
generate_serialize_list_element(out, (t_list*)ttype, iter); | |
} | |
@@ -2139,31 +2225,43 @@ | |
} else if (ttype->is_enum()) { | |
return (in_container ? "Integer" : "int"); | |
} else if (ttype->is_map()) { | |
- t_map* tmap = (t_map*) ttype; | |
- if (in_init) { | |
- prefix = "HashMap"; | |
- } else { | |
- prefix = "Map"; | |
- } | |
- return prefix + "<" + | |
- type_name(tmap->get_key_type(), true) + "," + | |
- type_name(tmap->get_val_type(), true) + ">"; | |
+ if (j2me_style_) { | |
+ return "Hashtable"; | |
+ } else { | |
+ t_map* tmap = (t_map*) ttype; | |
+ if (in_init) { | |
+ prefix = "HashMap"; | |
+ } else { | |
+ prefix = "Map"; | |
+ } | |
+ return prefix + "<" + | |
+ type_name(tmap->get_key_type(), true) + "," + | |
+ type_name(tmap->get_val_type(), true) + ">"; | |
+ } | |
} else if (ttype->is_set()) { | |
- t_set* tset = (t_set*) ttype; | |
- if (in_init) { | |
- prefix = "HashSet<"; | |
- } else { | |
- prefix = "Set<"; | |
- } | |
- return prefix + type_name(tset->get_elem_type(), true) + ">"; | |
+ if (j2me_style_) { | |
+ return "Set"; | |
+ } else { | |
+ t_set* tset = (t_set*) ttype; | |
+ if (in_init) { | |
+ prefix = "HashSet<"; | |
+ } else { | |
+ prefix = "Set<"; | |
+ } | |
+ return prefix + type_name(tset->get_elem_type(), true) + ">"; | |
+ } | |
} else if (ttype->is_list()) { | |
- t_list* tlist = (t_list*) ttype; | |
- if (in_init) { | |
- prefix = "ArrayList<"; | |
- } else { | |
- prefix = "List<"; | |
- } | |
- return prefix + type_name(tlist->get_elem_type(), true) + ">"; | |
+ if (j2me_style_) { | |
+ return "Vector"; | |
+ } else { | |
+ t_list* tlist = (t_list*) ttype; | |
+ if (in_init) { | |
+ prefix = "ArrayList<"; | |
+ } else { | |
+ prefix = "List<"; | |
+ } | |
+ return prefix + type_name(tlist->get_elem_type(), true) + ">"; | |
+ } | |
} | |
// Check for namespacing | |
@@ -2364,6 +2462,7 @@ | |
THRIFT_REGISTER_GENERATOR(java, "Java", | |
" beans: Generate bean-style output files.\n" | |
+" j2me: Generate J2ME compliant output files.\n" | |
" nocamel: Do not use CamelCase field accessors with beans.\n" | |
" hashcode: Generate quality hashCode methods.\n" | |
); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment