[69→100]用Python自动生成java类

随着公司的并行项目越来越多,Android新项目初始化的变成一个问题,一开始是每个人建立项目不一样,为此设计了清单列表。后来发现项目是一致了,但是每次都要手动执行列表,大部分都是简单地新建文件,很无聊,而且偶尔思想开个小差,还出错,又要找问题、修bug,烦~。
都说懒惰是程序员的优良品质,所以决定研究一下怎么自动化整个过程。

需求

经过分析,发现这里面最核心需求有两个:

  1. 根据模板java文件生成最终的java文件,主要是替换类名包名app包名
  2. 根据包名规则生成相应的文件夹。

其中涉及的流程有:

  1. 读取、解析配置文件;
  2. 根据名称,生成相应的文件夹;
  3. 根据模板文件,生成文件夹下相应的文件;

涉及的技术点有:

  1. 配置文件的格式用什么好?
  2. 怎么解析配置文件?

技术点1:配置文件的格式用什么好?

经过分析,考虑扩展性和简洁程序,决定json来写配置。

方案一:json和文件(夹)的层级结构保持一致。

  1. type:这一层级的类型:
  • dir: 表示文件夹
  • file: 表示文件
  1. 如果 type为dir,则需要定义:
  • name:文件夹的名字
  • list:子文件(夹)列表
  • package_name:包名。默认为 父级文件夹名字和自身文件夹的名字的叠加。
  1. 如果 type为file,则需要定义:
  • name:文件的名字
  • template:模板文件的名字

这样一个配置两个文件的json如下:

{
    "type":"dir",
    "name":"baby",
    "list":[
        {
            "type":"dir",
            "name":"view",
            "list":[
                {
                    "type":"file",
                    "name":"BabyFragment",
                    "template":"BaseFragment.java.tpl"
                },
                {
                    "type":"file",
                    "name":"MorningCheckFragment",
                    "template":"BaseFragment.java.tpl"
                }
            ]
        }
    ]
}

才两个文件,就有三层嵌套,就算是增加同包文件,都要增加三行,太繁琐了。换一种思路:

方案二:根据模板、包名,把同一个包名下的同一个模板的文件汇总在一起

  1. 第一层:
  • app_id: 应用包名
  • list: 模板新建列表
  1. 第二层:模板新建列表项
  • package_name: 对应的包名
  • template: 采用的模板
  • fileList: 需要新建的文件列表

这样json变成如下:

{
  "app_id":"panda.android.test",
  "list":[
      {
          "package_name":"panda.android.test",
          "template":"BaseFragment.java.tpl",
          "fileList":[
              "BabyFragment",
              "MorningCheckFragment"
          ]
      }
  ]
}

简单直观很多。

怎么解析配置文件?

这里当然选择强大易用的Python了。
Python字符串替换的3种方法:

1. 字符串替换

将需要替换的内容使用格式化符替代,后续补上替换内容;

template = "hello %s , your website is %s " % ("简书","http://www.jianshu.com/")
print(template)

也可使用format函数完成:

template = "hello {0} , your website is {1} ".format("简书","http://www.jianshu.com/")
print(template)

2. 字符串命名格式化符替换

使用命名格式化符,这样,对于多个相同变量的引用,在后续替换只用申明一次即可;

template = "hello %(name)s ,your name is %(name), your website is %(message)s" %{"name":"简书","message":"http://www.jianshu.com/"}
print(template)

使用format函数的语法方式:

template = "hello {name} , your name is {name}, your website is {message} ".format(name="大CC",message="http://blog.me115.com")
print(template)

3. 模版方法替换

使用string中的Template方法;

from string import Template
tempTemplate = string.Template("Hello $name ,your website is $message")
print(tempTemplate.substitute(name='大CC',message='http://blog.me115.com'))

有了模版方法后,就可以将模版保存到文件单独编辑,在生成的地方替换为需要的变量。

样例代码

  1. BaseFragment.java.tpl如下:
package ${PACKAGE_NAME};
import ${ANDROID_APP_ID}.R;
import panda.android.lib.base.ui.fragment.BaseFragment;
/**
 * Created on ${DATA}.
 */
public class ${CLASS_NAME} extends BaseFragment{
    @Override
    public int getLayoutId() {
        return R.layout.fragment_net;
    }
}
  1. 配置文件如下:
{
  "app_id":"panda.android.test",
  "list":[
      {
          "package_name":"panda.android.test",
          "template":"BaseFragment.java.tpl",
          "fileList":[
              "BabyFragment",
              "MorningCheckFragment"
          ]
      }
  ]
}
  1. 脚本如下:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os,sys,re,traceback
from datetime import datetime
from string import Template
import json
def generateAndroidJavaCode(app_id, package_name, template, fileName):
    className = fileName;
    path = "./" + package_name.replace('.','/');
    filePath = r'%s/%s.java' % (path,className)
    if os.path.exists(path) == False:
        os.makedirs(path)
    class_file = open(filePath,'w')
    lines = []
    #模版文件
    template_file = open(r'BaseFragment.java.tpl','r')
    tmpl = Template(template_file.read())
    #模版替换
    lines.append(tmpl.substitute(
                PACKAGE_NAME = package_name,
                ANDROID_APP_ID = app_id,
                DATA = datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
                CLASS_NAME = className))
    # 0.将生成的代码写入文件
    class_file.writelines(lines)
    class_file.close()
    print 'generate %s over. ~ ~' % filePath
## 1. 解析配置文件
configuration = """
{
  "app_id":"panda.android.test",
  "list":[
      {
          "package_name":"panda.android.test",
          "template":"BaseFragment.java.tpl",
          "fileList":[
              "BabyFragment",
              "MorningCheckFragment"
          ]
      }
  ]
}
"""
configurationJson = json.loads(configuration);
## 2. 按照模板生成对应的文件
app_id =  configurationJson["app_id"]
for filesInfo in configurationJson["list"]:
    package_name = filesInfo["package_name"]
    template = filesInfo["template"]
    for fileName in filesInfo["fileList"]:
        generateAndroidJavaCode(app_id, package_name, template, fileName);
  1. 最后生成的文件如下:


引用

  1. python 自动生成C++代码 (代码生成器)

Panda
2016-07-04

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,948评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,371评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,490评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,521评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,627评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,842评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,997评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,741评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,203评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,534评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,673评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,339评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,955评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,770评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,000评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,394评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,562评论 2 349

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,633评论 18 139
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,796评论 25 707
  • 22年12月更新:个人网站关停,如果仍旧对旧教程有兴趣参考 Github 的markdown内容[https://...
    tangyefei阅读 35,170评论 22 257
  • Spring Boot 参考指南 介绍 转载自:https://www.gitbook.com/book/qbgb...
    毛宇鹏阅读 46,773评论 6 342
  • 潮红暮色观阁景 半百知行览路晴 不惑之年思乱径 唯心稳见夜来临
    晴天映白云阅读 176评论 0 0