blob: b6cc7b4d05b8cc42fa8503a4f908bcda95519cf1 [file] [log] [blame]
[% import "../thrift-helper-functions.eol";
operation String makeJavaComment(padding : String) : String {
return self.makeComment("/**"+EOL(), " * ", " */"+EOL(), padding);
}
operation Field isPrimitive() : Boolean {
return self.fieldType.isPrimitive();
}
@cached
operation FieldType isPrimitive() : Boolean {
return self.javaType().isJavaPrimitive();
}
operation String javaString() : String {
return self.escapedString();
}
@cached
operation String isBaseJava() : Boolean {
return self.matches("ByteBuffer") or self.convertToPrimitive().isJavaPrimitive();
}
@cached
operation String convertToPrimitive() : String {
if (self.matches("String") or self.matches("ByteBuffer") or self.isJavaContainer()) {
return self;
}
switch (self) {
case "Integer": return "int";
case "Character": return "char";
default: return self.firstToLowerCase();
}
}
@cached
operation String isJavaType() : Boolean {
return
self.isJavaPrimitive() or
self.isJavaContainer() or
self == "Byte" or
self == "ByteBuffer" or
self == "Boolean" or
self == "Integer" or
self == "Double" or
self == "Long" or
self == "Short" or
self == "Character" or
self.firstToLowerCase() == "void";
}
operation String isJavaContainer() : Boolean {
return "<".isSubstringOf(self) and (
self.startsWith("Array") or
self.startsWith("List") or
self.startsWith("Map") or
self.startsWith("Set") or
self.startsWith("HashMap") or
self.startsWith("TreeMap") or
self.startsWith("HashSet") or
self.startsWith("TreeSet"));
}
@cached
operation String isJavaPrimitive() : Boolean {
return
self == "byte" or
self == "boolean" or
self == "int" or
self == "double" or
self == "long" or
self == "short" or
self == "char";
}
@cached
operation String javaToThriftType() : String {
return self.toLowerCase()
.replace("bytebuffer", "binary")
.replace("boolean", "bool")
.replace("int", "i32")
.replace("integer", "i32")
.replace("long", "i64")
.replace("short", "i16");
}
operation String resolveJavaType(generic : Boolean) : String {
var javaType : String = self
.replace("string", "String")
.replace("map", "Map")
.replace("list", "List")
.replace("set", "Set")
.replace("binary", "ByteBuffer")
.replace("slist", "String")
.replace("i8", "byte");
if (generic) {
javaType = javaType
.replace("bool", "Boolean")
.replace("i32", "Integer")
.replace("double", "Double")
.replace("i64", "Long")
.replace("byte", "Byte")
.replace("i16", "Short")
.replace("void", "Void");
}
else {
javaType = javaType
.replace("bool", "boolean")
.replace("i32", "int")
.replace("i64", "long")
.replace("i16", "short");
}
return javaType;
}
operation String resolveJavaType() : String {
return self.resolveJavaType("<".isSubstringOf(self));
}
@cached
operation Const javaType() : String {
if (self.fieldType.isUndefined()) return "";
return self.fieldType.javaType();
}
@cached
operation Field javaType() : String {
if (self.fieldType.isUndefined()) return "";
return self.fieldType.javaType();
}
operation Field javaType(generic : Boolean) : String {
if (self.fieldType.isUndefined()) return "";
return self.fieldType.javaType(generic);
}
operation FieldType javaType(generic : Boolean) : String {
if (generic) {
if (self.~genericJavaType.isUndefined()) {
self.~genericJavaType = self.thriftType().resolveJavaType(true);
}
return self.~genericJavaType;
}
if (self.~normalJavaType.isUndefined()) {
self.~normalJavaType = self.thriftType().resolveJavaType(false);
}
return self.~normalJavaType;
}
@cached
operation FieldType javaType() : String {
return self.javaType(self.isContainer());
}
@cached
operation Field concreteJavaType() : String {
if (self.fieldType.isUndefined()) return "";
return self.fieldType.concreteJavaType();
}
operation FieldType concreteJavaType() : String {
if (self.~concreteJavaType.isUndefined()) {
self.~concreteJavaType = self.javaType().concreteJavaType();
}
return self.~concreteJavaType;
}
@cached
operation String concreteJavaType() : String {
if (self.startsWith("List"))
return "Array"+self;
else if (self.startsWith("Set") or self.startsWith("Map"))
return "Hash"+self;
return self;
}
operation Field getTtype() : String {
assertTrue(self.fieldType.isDefined());
return self.fieldType.getTtype();
}
@cached
operation FieldType getTtype() : String {
return self.getTtype(true);
}
operation FieldType getTtype(changeEnumToI32 : Boolean) : String {
var typename : String = self.getTypeName();
return "org.apache.thrift.protocol.TType."+typename.changeIf(changeEnumToI32 and self.isEnum(), "I32");
}
@cached
operation Function getType() : String {
return self.getType(false);
}
operation Function getType(generic : Boolean) : String {
if (self.isVoid()) {
return generic.ternary("Void", "void");
}
if (self.funcType.isDefined() and self.funcType.fieldType.isDefined()) {
return self.funcType.fieldType.javaType(generic);
}
return "";
}
operation Function isPrimitive() : Boolean {
if (self.~isPrimitive.isUndefined()) {
self.~isPrimitive = self.funcType.fieldType.isDefined() and self.funcType.fieldType.isPrimitive();
}
return self.~isPrimitive;
}
operation Function getSignature(exception : String) : String {
if (not self.~javaSignature.isDefined()) {
self.~javaSignature = self.getType()+' '+self.identifier+'('+self.getArgs(true)+')';
}
if (exception.isDefined() and exception.length() > 0) {
return self.~javaSignature+" throws "+exception;
}
return self.~javaSignature;
}
operation Function getArgs(includeTypes : Boolean) : String {
return self.getArgs(includeTypes, false);
}
operation Function getArgs(includeTypes : Boolean, includeContinuation : Boolean) : String {
return self.getArgs(includeTypes, "", "".changeIf(includeContinuation, ", "));
}
operation Function getArgs(includeTypes : Boolean, prefixText : String, continuation : String) : String {
var argstr : String = "";
for (arg in self.args) {
if (includeTypes and arg.fieldType.isDefined()) {
argstr += arg.fieldType.javaType()+' ';
}
argstr += prefixText+arg.identifier+", ";
}
if (argstr.endsWith(", ")) {
argstr = argstr.substring(0, argstr.length()-2);
}
if (self.args.size() > 0) {
argstr += continuation;
}
return argstr;
}
@cached
operation Function getExceptions() : String {
var excsig : String = "";
for (xception in self.exceptions) {
excsig += xception.fieldType.identifier+", ";
}
return excsig+"org.apache.thrift.TException";
}
operation Field getDeclaration() : String {
return self.getDeclaration("", false, "");
}
operation Field getDeclaration(visibility : String, reqComment : Boolean) : String {
return self.getDeclaration(visibility, reqComment, ';');
}
operation Field getDeclaration(visibility : String, reqComment : Boolean, sep : String) : String {
var decStr : String = "";
if (visibility.isDefined() and visibility.length() > 0) {
decStr = visibility+' ';
}
if (self.fieldType.isDefined()) {
decStr += self.fieldType.javaType()+' '+self.identifier+sep;
}
if (reqComment) {
var requiredness : String = "required";
if (self.fieldReq.isDefined() and self.fieldReq.literal == "optional")
requiredness = "optional";
decStr += " // "+requiredness;
}
return decStr;
}
operation Function printComment(padding : String) {
if (self.comment.isDefined()) {
var contents : String = self.comment.getCommentContents();
for (arg in self.args) {
contents += "\n@param "+arg.identifier;
if (arg.comment.isDefined()) {
contents += ' '+arg.getRawComment();
}
}
out.print(contents.makeJavaComment(padding));
}
}
operation Field printComment(padding : String) {
if (self.isEnum()) {
out.print((self.comment+"\n@see "+self.thriftType()).makeJavaComment(padding));
}
if (self.comment.isDefined()) {
out.print(self.getRawComment().makeJavaComment(padding));
}
}
operation FieldType printMetaData(basePadding : String) {
var padding : String = basePadding+" ";
var ttype : String = self.getTtype(false);
var typeName = self.getTypeName().toLowerCase.firstToUpperCase();
var tmeta : String = "new org.apache.thrift.meta_data.";
if (self.isBase()) {
tmeta += "FieldValue";
}
else {
tmeta += typeName;
}
tmeta += "MetaData("+ttype;
if (not self.isBase()) {
tmeta += ", ";
}
out.print(padding+tmeta);
if (self.isEnum() or self.isStruct()) {
out.print(self.identifier+".class");
}
else if (self.isBase()) {
if (self.~typedef.isDefined() or self.isBinary()) {
out.print(padding+", ");
if (self.~typedef.isDefined()) {
out.print('"'+self.~typedef+'"');
}
else {
out.print("true");
}
}
}
else if (self.defType.isDefined()) {
out.println();
var container = self.defType.container;
if (container.isDefined()) {
if (container.keyword == "map") {
container.keyType.printMetaData(padding);
out.println(", ");
container.valType.printMetaData(padding);
}
else {
container.fieldType.printMetaData(padding);
}
}
else if (self.defType.base.isDefined()) {
tmeta = tmeta.replace(typeName, "FieldValue").replace(typeName, self.defType.base.literal.toUpperCase());
out.print(padding+tmeta);
}
}
out.print(')');
}
operation printDeepCopyContainer(padding : String, innerType : String, iteratorName : String, resultName : String, afterFor : String) {
out.print(padding+innerType+' '+resultName+" = new "+innerType.concreteJavaType()+'('+iteratorName);
if (innerType.hasNesting()) {
var nextInner : String = innerType.getInnerType();
var nextIterName : String = iteratorName.split("\\.").first()+"_element";
var nextResName : String = resultName+"_copy";
var nextPadding : String = padding+" ";
out.println(".size());");
out.print(padding+"for (");
if (innerType.startsWith("Map")) {
var nextKey : String = innerType.getMapKey();
var nextValue : String = innerType.getMapValue();
out.println("Map.Entry<"+nextInner.spaceBetweenMap()+"> "+nextIterName+" : "+iteratorName+".entrySet()) {");
out.println();
out.println(nextPadding+nextKey+' '+nextIterName+"_key = "+nextIterName+".getKey();");
out.println(nextPadding+nextValue+' '+nextIterName+"_value = "+nextIterName+".getValue();");
out.println();
printDeepCopyContainer(nextPadding, nextKey, nextIterName+"_key", nextResName+"_key", null);
out.println();
printDeepCopyContainer(nextPadding, nextValue, nextIterName+"_value", nextResName+"_value", null);
out.println();
out.println(nextPadding+resultName+".put("+nextResName+"_key, "+nextResName+"_value);");
}
else {
out.println(nextInner+' '+nextIterName+" : "+iteratorName+") {");
if (nextInner.hasNesting()) {
printDeepCopyContainer(nextPadding, nextInner, nextIterName, nextResName, nextPadding+resultName+".add("+nextResName+");");
}
else {
var addArg : String = nextIterName;
if (nextInner.isType("ByteBuffer")) {
out.println(nextPadding+"ByteBuffer temp_binary_element = org.apache.thrift.TBaseHelper.copyBinary("+nextIter+");");
addArg += "temp_binary_element";
}
else if (not nextInner.isJavaType()) {
addArg = "new "+nextInner+'('+addArg+')';
}
addArg += ");";
out.println(nextPadding+resultName+".add("+addArg);
}
}
out.println(padding+'}');
if (afterFor.isDefined()) {
out.println(afterFor);
}
}
else {
out.println(");");
}
}
operation Field printDeepCopy(padding : String) {
var otherName : String = "other."+self.identifier;
if (not self.isPrimitive()) {
out.println(padding+"if (other.isSet"+self.~accessorName+"()) {");
padding += " ";
}
if (self.isContainer()) {
var resultName : String = "__this__"+self.identifier;
var javaType : String = self.javaType();
if (self.fieldType.nestedTypeIsBase()) {
out.println(padding+javaType+' '+resultName+" = new "+javaType.concreteJavaType()+'('+otherName+");");
}
else {
printDeepCopyContainer(padding, javaType, otherName, resultName, null);
}
otherName = "__this__"+self.identifier;
}
//For some reason, this logic is not executed by the Thrift Java generator even though it's in the source code!
else if (self.fieldType.isBinary()) {
otherName = "org.apache.thrift.TBaseHelper.copyBinary("+otherName+')';
}
else if (self.fieldType.isStruct()) {
otherName = "new "+self.fieldType.identifier+'('+otherName+')';
}
out.println(padding+"this."+self.identifier+" = "+otherName+';');
if (not self.isPrimitive()) {
padding = padding.substring(2);
out.println(padding+'}');
}
}
operation Field printSerialize(prefix : String, hasMetadata : Boolean, padding : String) {
self.fieldType.printSerialize(prefix, self.identifier, hasMetadata, padding);
}
operation FieldType printSerialize(prefix : String, identifier : String, hasMetadata : Boolean, padding : String) {
var thriftType : String = self.thriftType();
var javaType = self.javaType();
var name : String = prefix+identifier;
if (self.isStruct() or self.isException()) {
out.println(padding+name+".write(oprot);");
}
else if (self.isEnum()) {
out.println(padding+"oprot.writeI32("+name+".getValue());");
}
else if (self.isContainer()) {
var iterName : String = "_iter".iterNum();
var container = self.defType.container;
var containerType : String = container.keyword.firstToUpperCase();
out.println(padding+'{');
padding += " ";
out.print(padding+"oprot.write");
if (hasMetadata) {
out.print(containerType+"Begin(new org.apache.thrift.protocol.T"+containerType+'(');
if (self.isMap()) {
var key = container.keyType;
var value = container.valType;
out.print(key.getTtype()+", "+value.getTtype());
}
else {
out.print(container.fieldType.getTtype());
}
out.print(", ");
}
else {
out.print("I32(");
}
out.println(name+".size())"+("".changeIf(hasMetadata, ")"))+';');
out.print(padding+"for (");
if (self.isMap() and container.keyType.isDefined() and container.valType.isDefined()) {
out.print("Map.Entry<"+container.keyType.javaType()+", "+container.valType.javaType()+"> "+iterName+" : "+name+".entrySet()");
}
else if (container.fieldType.isDefined()) {
out.print(container.fieldType.javaType()+' '+iterName+" : "+name);
}
out.println(')');
out.println(padding+'{');
if (self.isMap()) {
container.keyType.printSerialize("", iterName+".getKey()", hasMetadata, padding+" ");
container.valType.printSerialize("", iterName+".getValue()", hasMetadata, padding+" ");
}
else {
container.fieldType.printSerialize("", iterName, hasMetadata, padding+" ");
}
out.println(padding+'}');
if (hasMetadata) {
out.println(padding+"oprot.write"+containerType+"End();");
}
padding = padding.substring(2);
out.println(padding+'}');
}
else if (self.isBase()) {
out.println(padding+"oprot.write"+thriftType.firstToUpperCase()+'('+name+");");
}
}
operation Field printDeserialize(prefix : String, hasMetadata : Boolean, padding : String) {
self.fieldType.printDeserialize(prefix, self.identifier, hasMetadata, padding);
}
operation FieldType printDeserialize(prefix : String, identifier : String, hasMetadata : Boolean, padding : String) {
var thriftType : String = self.thriftType();
var javaType = self.javaType();
var name : String = prefix+identifier;
if (self.isStruct() or self.isException()) {
out.println(padding+name+" = new "+self.identifier+"();");
out.println(padding+name+".read(iprot);");
}
else if (self.isEnum()) {
out.println(padding+name+" = "+self.identifier+".findByValue(iprot.readI32());");
}
else if (self.isContainer()) {
var isMap = self.isMap();
var container = self.defType.container;
var containerType : String = container.keyword.firstToUpperCase();
var objName : String = ("_"+container.keyword).iterNum();
out.println(padding+'{');
padding += " ";
out.print(padding+"org.apache.thrift.protocol.T"+containerType+' '+objName+" = ");
if (hasMetadata) {
out.println("iprot.read"+containerType+"Begin();");
}
else {
out.print("new org.apache.thrift.protocol.T"+containerType+'(');
if (isMap) {
out.print(container.keyType.getTtype()+", "+container.valType.getTtype());
}
else {
out.print(container.fieldType.getTtype());
}
out.println(", iprot.readI32());");
}
out.println(padding+name+" = new "+self.concreteJavaType()+'('+"2*".changeIf(self.isList(), "")+objName+".size);");
var i : String;
var colElem : String;
var keyElem : String;
var valElem : String;
if (isMap and container.keyType.isDefined() and container.valType.isDefined()) {
keyElem = "_key".iterNum();
valElem = "_val".iterNum();
out.println(padding+container.keyType.javaType()+' '+keyElem+';');
out.println(padding+container.valType.javaType()+' '+valElem+';');
}
else if (container.fieldType.isDefined()) {
colElem = "_elem".iterNum();
out.println(padding+container.fieldType.javaType()+' '+colElem+';');
}
i = "_i".iterNum();
out.println(padding+"for (int "+i+" = 0; "+i+" < "+objName+".size; ++"+i+')');
out.println(padding+'{');
padding += " ";
if (isMap) {
container.keyType.printDeserialize("", keyElem, hasMetadata, padding);
container.valType.printDeserialize("", valElem, hasMetadata, padding);
out.println(padding+name+".put("+keyElem+", "+valElem+");");
}
else if (container.fieldType.isDefined()) {
container.fieldType.printDeserialize("", colElem, hasMetadata, padding);
out.println(padding+name+".add("+colElem+");");
}
padding = padding.substring(2);
out.println(padding+'}');
if (hasMetadata) {
out.println(padding+"iprot.read"+containerType+"End();");
}
padding = padding.substring(2);
out.println(padding+'}');
}
else if (self.isBase()) {
out.println(padding+name+" = iprot.read"+thriftType.firstToUpperCase()+"();");
}
}
operation printMetadataMap(fields, identifier : String) {%]
public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
static {
Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
[% for (field in fields) {%]
tmpMap.put(_Fields.[%=field.~capsIdentifier%], new org.apache.thrift.meta_data.FieldMetaData("[%=field.identifier%]", org.apache.thrift.TFieldRequirementType.[%=field.getRequirement()%],
[% field.fieldType.printMetaData(" ");
out.println("));");
}%]
metaDataMap = Collections.unmodifiableMap(tmpMap);
org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap([%=identifier%].class, metaDataMap);
}
[%}
operation printFieldsEnum(fields) {%]
/** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
public enum _Fields implements org.apache.thrift.TFieldIdEnum {
[% if (fields.size() > 0)
for (i : Integer in Sequence{0..fields.size()-1}) {
var field : Field = fields.at(i);
field.printComment(" "); %]
[%=field.~capsIdentifier%]((short)[%=field.fieldID%], "[%=field.identifier%]")[%=",".changeIf(i == fields.size()-1, ";")%]
[%}%]
private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
static {
for (_Fields field : EnumSet.allOf(_Fields.class)) {
byName.put(field.getFieldName(), field);
}
}
/**
* Find the _Fields constant that matches fieldId, or null if its not found.
*/
public static _Fields findByThriftId(int fieldId) {
switch(fieldId) {
[% for (field in fields) {%]
case [%=field.fieldID%]: // [%=field.~capsIdentifier%]
return [%=field.~capsIdentifier%];
[%}%]
default:
return null;
}
}
/**
* Find the _Fields constant that matches fieldId, throwing an exception
* if it is not found.
*/
public static _Fields findByThriftIdOrThrow(int fieldId) {
_Fields fields = findByThriftId(fieldId);
if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
return fields;
}
/**
* Find the _Fields constant that matches name, or null if its not found.
*/
public static _Fields findByName(String name) {
return byName.get(name);
}
private final short _thriftId;
private final String _fieldName;
_Fields(short thriftId, String fieldName) {
_thriftId = thriftId;
_fieldName = fieldName;
}
public short getThriftFieldId() {
return _thriftId;
}
public String getFieldName() {
return _fieldName;
}
}
[%}
operation printTFieldDeclarations(fields, padding : String) {
for (field in fields) {
out.println(padding+"private static final org.apache.thrift.protocol.TField "+field.identifier.camelToUnderscore()+"_FIELD_DESC = new org.apache.thrift.protocol.TField(\""+field.identifier+"\", "+field.getTtype()+", (short)"+field.fieldID+");");
}
}
operation printFileHead(author : String, pkg, comment : String) {
printFileHead(author, pkg, comment, null);
}
operation printFileHead(author : String, pkg, comment : String, date : String) {
printHeaderMessage(author); %]
[% printPackage(pkg); %]
[% printImports(); %]
[% printSuppressWarnings(); %]
[% if (comment.isDefined() and comment.length() > 3)
out.println(comment); %]
[% if (date.isDefined() and date.length() > 1) {
printDateAuthor(date, author);
}
}
operation printHeaderMessage(author : String) {%]
/**
* Autogenerated by [%=author%]
*
* DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
* @generated
*/
[%}
operation printPackage(pkg) {
if (pkg.isDefined()) {%]
[%="package "+pkg%];
[%}
}
operation printImports() {
%]import org.apache.thrift.scheme.IScheme;
import org.apache.thrift.scheme.SchemeFactory;
import org.apache.thrift.scheme.StandardScheme;
import org.apache.thrift.scheme.TupleScheme;
import org.apache.thrift.protocol.TTupleProtocol;
import org.apache.thrift.protocol.TProtocolException;
import org.apache.thrift.EncodingUtils;
import org.apache.thrift.TException;
import org.apache.thrift.async.AsyncMethodCallback;
import org.apache.thrift.server.AbstractNonblockingServer.*;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.util.HashMap;
import java.util.EnumMap;
import java.util.Set;
import java.util.HashSet;
import java.util.EnumSet;
import java.util.Collections;
import java.util.BitSet;
import java.nio.ByteBuffer;
import java.util.Arrays;
import javax.annotation.Generated;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
[%}
operation printDateAuthor(date : String, author : String) {%]
@Generated(value = "Autogenerated by [%=author%]", date = "[%=date%]")
[%}
operation printSuppressWarnings() {%]
@SuppressWarnings({"cast", "rawtypes", "serial", "unchecked"})
[%}
%]