Skip to content

Instantly share code, notes, and snippets.

@pcqpcq
Last active August 29, 2015 14:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pcqpcq/93675e3e02d8d44d8da3 to your computer and use it in GitHub Desktop.
Save pcqpcq/93675e3e02d8d44d8da3 to your computer and use it in GitHub Desktop.
Android JavaBean Generator for android. Java Bean with Parcelable. Version 1.0.1
## 使命行参数格式:
## ARGV[0] ==> config文件路径[必须有]
## ARGV[1] ==> 保存文件路径[必须有]
## ARGV[2] ==> 包名[必须有]
##
## 示例:
## ruby ./AndroidBeanGen.rb ./config.txt ./resp com.a.b
##
##
##
##
##
## config文件格式:
## Cls:类名1:类注释1
## 属性名1:属性类型1
## Cls:类名2:类注释2
## 属性名2:属性类型2
##
## 示例:
## Cls:ArticleReqEntity:文章请求实体
## id:int
## Cls:ArticleRespEntity:文章响应实体
## id:int
## title:String
##
##
##
## ps. 目前已知最低兼容ruby1.8.7
##
## 1.0.1(2014.03.24):增加set方法集
## 1.0.0(2014.03.20):第一版
##
##
##
# 一个类包含:类名,属性列表和内部类指针
class Clazz
def initialize(cls_name)
@cls_name = cls_name
@cls_comment = ""
@attrs=[]
@lead_cls_names=nil #前面有几个前导类名
@cls_import_advanced = 0 #是否需要导入额外内容
end
def cls_name
@cls_name
end
attr_accessor :cls_comment, :attrs, :lead_cls_names, :cls_import_advanced
end
#属性
class Attr
def initialize(type=nil,name=nil)
@type,@name=type,name
end
attr_accessor :type, :name
end
class Env
def initialize()
@clz_list = [] #类的容器
@cur_clz = nil #当前类
@cur_clz_comment = nil #当前类注释
@attr = nil #当前属性
@attr_index=0 #当前类的第几个属性
@clz_index=0 #当前属于第几个类
end
attr_accessor :clz_list,:cur_clz,:cur_clz_comment,:attr,:attr_index,:clz_index
end
$env = Env.new
# 转换首字母大写,此处算法为了兼容ruby1.8.7
def getFirstUpcase(str)
str_first_cap = str[0].capitalize
str_remainder = str[1..str.size-1]
str = "#{str_first_cap}#{str_remainder}"
return str
end
# 转换首字母小写,此处算法为了兼容ruby1.8.7
def getFirstDowncase(str)
str_first_min = "0#{str}".capitalize[1]
str_remainder = str[1..str.size-1]
str = "#{str_first_min}#{str_remainder}"
return str
end
def print_clz_list #测试容器数据
$env.clz_list.each do |clzz|
lead_cls_names = clzz.lead_cls_names
print "============"
lead_cls_names.each do |lead_names|
print lead_names + "-"
end
print "#{clzz.cls_name}============\n"
attrs = clzz.attrs
attrs.each do |attr|
puts attr.type + "=" + attr.name
end
end
end
def print_cls_import(i)
template = "package #{ARGV[2]};\n"
template += "\n"
template += "import android.os.Parcel;\n"
template += "import android.os.Parcelable;\n"
template += "import com.google.gson.annotations.SerializedName;\n"
if (i == 1)
template += "import java.util.List;\n"
end
template += "\n"
template
end
def print_cls_head(i)
clazz = $env.clz_list[i]
lead_clz_names = clazz.lead_cls_names
lead_num = lead_clz_names.size
cls_name = clazz.cls_name
cls_comment = clazz.cls_comment
template = "/**\n"
template += " * #{cls_comment}\n"
template += " * <p>build by AndroidBeanGen</p>\n"
template += " * <a href=\"https\://gist.github.com/pcqpcq/93675e3e02d8d44d8da3\">get it here</a>\n"
template += " */\n"
template += "public class #{cls_name} implements Parcelable {\n"
# if(i == 0)
# template += "public class #{cls_name} {\n"
# else
# template += "\n"
# template += "\t" * lead_num
# template += "public static class #{cls_name} {\n"
# end
template
end
#返回前导类的个数
def get_lead_num(i)
lead_cls_names = $env.clz_list[i].lead_cls_names
lead_num = 0
# if(lead_cls_names == nil)
# lead_num = 0
# else
# lead_num = lead_cls_names.size
# end
lead_num
end
def print_cls_end(i)
lead_num = get_lead_num(i)
template = "\t" * lead_num + "}\n\n"
template
end
def print_attrs(i)
lead_type = "\t" * get_lead_num(i) + "\t"
attrs = $env.clz_list[i].attrs
template = "\n"
attrs.each do |attr|
type = attr.type
name = attr.name
template += "#{lead_type}@SerializedName(\"#{name}\")\n"
if type == "String"
template += "#{lead_type}#{type} #{name} = \"\";\n"
else
template += "#{lead_type}#{type} #{name};\n"
end
end
template
end
def get_template(i)
clazz = $env.clz_list[i]
lead_type = "\t" * get_lead_num(i) + "\t"
template = "\n"
clazz.attrs.each do |attr|
first_cap_name = getFirstUpcase(attr.name)
template += "#{lead_type}public #{attr.type} get#{first_cap_name}() {\n"
template += "#{lead_type}\treturn #{attr.name};\n"
template += "#{lead_type}}\n\n"
end
template
end
def set_template(i)
clazz = $env.clz_list[i]
lead_type = "\t" * get_lead_num(i) + "\t"
template = ""
clazz.attrs.each do |attr|
first_cap_name = getFirstUpcase(attr.name)
template += "#{lead_type}public void set#{first_cap_name}(#{attr.type} #{attr.name}) {\n"
template += "#{lead_type}\tthis.#{attr.name} = #{attr.name};\n"
template += "#{lead_type}}\n\n"
end
template
end
def parcel_template(i)
clazz = $env.clz_list[i]
template = ""
# 输出describeContents()方法
template += "\t@Override\n"
template += "\tpublic int describeContents() {\n"
template += "\t\treturn 0;\n"
template += "\t}\n\n"
# 输出writeToParcel()方法
template += "\t@Override\n"
template += "\tpublic void writeToParcel(Parcel dest, int flags) {\n"
clazz.attrs.each do |attr|
first_type_name = getFirstUpcase(attr.type)
# 特殊处理List
if first_type_name.include? "List"
first_type_name = "List"
end
# 特殊处理实体对象
if first_type_name.include? "Entity"
first_type_name = "Parcelable"
template += "\t\tdest.write#{first_type_name}(this.#{attr.name}, flags);\n"
else
template += "\t\tdest.write#{first_type_name}(this.#{attr.name});\n"
end
end
template += "\t}\n\n"
# 输出CREATOR对象
template += "\tpublic static final Parcelable.Creator<#{clazz.cls_name}> CREATOR = new Creator<#{clazz.cls_name}>() {\n\n"
template += "\t\t@Override\n"
template += "\t\tpublic #{clazz.cls_name}[] newArray(int size) {\n"
template += "\t\t\treturn new #{clazz.cls_name}[size];\n"
template += "\t\t}\n\n"
template += "\t\t@Override\n"
template += "\t\tpublic #{clazz.cls_name} createFromParcel(Parcel source) {\n"
template_builder = ""
clazz.attrs.each do |attr|
first_cap_name = getFirstUpcase(attr.name)
first_type_name = getFirstUpcase(attr.type)
if first_type_name.include? "List"
listtype_first_index = 1+first_type_name.index('<')
listtype_name = first_type_name[listtype_first_index..first_type_name.size-2]
template += "\t\t\tArrayList<#{listtype_name}> #{attr.name} = new ArrayList<#{listtype_name}>();\n"
template += "\t\t\tsource.readList(#{attr.name}, #{listtype_name}.class.getClassLoader());\n\n"
elsif first_type_name.include? "Entity"
template += "\t\t\t#{attr.type} #{attr.name} = source.readParcelable(#{attr.type}.class.getClassLoader());\n"
else
template += "\t\t\t#{attr.type} #{attr.name} = source.read#{first_type_name}();\n"
end
template_builder += "\t\t\t\t\t.set#{first_cap_name}(#{attr.name})\n"
end
template += "\n\t\t\treturn new Builder()\n"
template += template_builder
template += "\t\t\t\t\t.get#{clazz.cls_name}();\n"
template += "\t\t}\n"
template += "\t};\n\n"
template
end
def builder_template(i=0)
clazz = $env.clz_list[i]
cls_name = clazz.cls_name
instance_name = getFirstDowncase(cls_name)
attrs = clazz.attrs
lead_type = "\t" * get_lead_num(i) + "\t"
template = "#{lead_type}public static class Builder {\n\n"
template += "#{lead_type}\tprivate #{cls_name} #{instance_name} = new #{cls_name}();\n\n"
attrs.each do |attr|
first_cap_name = getFirstUpcase(attr.name)
template += "#{lead_type}\tpublic Builder set#{first_cap_name}(#{attr.type} #{attr.name}) {\n"
template += "#{lead_type}\t\t#{instance_name}.#{attr.name} = #{attr.name};\n"
template += "#{lead_type}\t\treturn this;\n"
template += "#{lead_type}\t}\n\n"
end
template += "#{lead_type}\tpublic #{cls_name} get#{cls_name}() {\n"
template += "#{lead_type}\t\treturn #{instance_name};\n"
template +="#{lead_type}\t}\n"
template += "#{lead_type}}\n\n"
template
end
def genBean
clazz_list=$env.clz_list
output_path = ARGV[1]
0.upto(clazz_list.size-1) do |i|
cur_clz = clazz_list[i]
output_file = File.new("#{output_path}/#{cur_clz.cls_name}\.java", "w")
output_file.puts print_cls_import(cur_clz.cls_import_advanced)
output_file.puts print_cls_head(i)
output_file.puts print_attrs(i)
output_file.puts get_template(i)
output_file.puts set_template(i)
output_file.puts parcel_template(i)
output_file.puts builder_template(i)
output_file.puts print_cls_end(0)
output_file.close
end
end
=begin
$clz_list = [] #类的容器
$cur_clz = nil #当前类
$attr = nil #当前属性
$attr_index=0 #当前类的第几个属性
$clz_index=0 #当前属于第几个类
=end
File.open("#{ARGV[0]}", "r:UTF-8"){|f|
f.each_line do |line|
line = line.gsub("\n","") #去除换行符
if /^Cls/ =~ line #碰到以Cls开头,表名以下的属性属于该类
type_cls_names = line.split(":") #将该行分成两部分,第一部分为Cls,第二部分为类名集合,每个类名之间用-相连
cls_names = type_cls_names[1].split("-") #获取类名集合
# 类名之后的内容为类注释,尝试获取类注释,如果有的话
if type_cls_names.size > 2
cls_comment = type_cls_names[2]
$env.cur_clz_comment = cls_comment
end
cls_name = cls_names[cls_names.size-1]
$env.cur_clz = Clazz.new(cls_name)
$env.cur_clz.lead_cls_names = cls_names[0...cls_names.size-1] #获取前导类名集合
$env.clz_list[$env.clz_index] = $env.cur_clz;
$env.clz_index += 1
$env.attr_index = 0 #重置attr_index
else #将该类的属性,填充在该类中
if $env.cur_clz == nil
puts "nil"
else
attr_type_name = line.split(":")
attr_name=attr_type_name[0]
attr_type=attr_type_name[1]
$env.attr = Attr.new(attr_type,attr_name)
$env.cur_clz.attrs[$env.attr_index] = $env.attr
$env.attr_index += 1
# 如果包含List,则导入List包
if (attr_type.include? "List")
$env.cur_clz.cls_import_advanced = 1
end
# 如果当前类有注释
if $env.cur_clz_comment != nil
$env.cur_clz.cls_comment = $env.cur_clz_comment
end
end
end
end
=begin
print_clz_list
puts get_template(0)
puts builder_template
=end
genBean
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment