├── .gitignore ├── LICENSE ├── README.md ├── TODO.txt ├── example ├── pom.xml └── src │ └── main │ ├── java │ └── Main.java │ └── resources │ └── SimpleExample │ ├── custom.conf │ ├── pom.xml │ └── src │ └── main │ ├── java │ ├── ${package} │ │ ├── controller │ │ │ ├── ${bean.name}Controller.java │ │ │ └── BaseController.java │ │ ├── dao │ │ │ ├── ${bean.name}Dao.java │ │ │ └── BaseDao.java │ │ ├── model │ │ │ └── ${bean.name}.java │ │ ├── service │ │ │ ├── ${bean.name}Service.java │ │ │ └── impl │ │ │ │ └── ${bean.name}ServiceImpl.java │ │ └── util │ │ │ └── JsonUtil.java │ └── net │ │ └── sf │ │ └── log4jdbc │ │ └── DataSourceSpyInterceptor.java │ ├── resources │ ├── log4j.properties │ ├── mappers │ │ └── ${bean.name}Mapper.xml │ ├── mybatis │ │ └── mybatis.xml │ └── spring │ │ ├── application-context.xml │ │ ├── application-datasource.xml │ │ ├── application-mybatis.xml │ │ └── application-servlet.xml │ └── webapp │ └── WEB-INF │ ├── jetty-web.xml │ └── web.xml ├── pom.xml └── src └── main ├── java └── github │ └── jadetang │ └── maliang │ ├── MEngine.java │ ├── bean │ ├── Column.java │ ├── JavaClass.java │ ├── JavaDataBaseRelation.java │ ├── JavaField.java │ ├── Relation.java │ ├── Table.java │ └── Tuple.java │ ├── builder │ ├── ContextBuilder.java │ ├── JavaDataBaseRelationBuilder.java │ └── SourceCodeGenerator.java │ ├── conf │ └── MConfig.java │ ├── exception │ └── MaliangException.java │ ├── resource │ ├── ClassLoaderWrapper.java │ └── Resources.java │ └── util │ ├── ContextUtil.java │ └── FileUtil.java └── resources ├── log4j.properties └── reference.conf /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | 3 | # Mobile Tools for Java (J2ME) 4 | .mtj.tmp/ 5 | 6 | # Package Files # 7 | *.jar 8 | *.war 9 | *.ear 10 | 11 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 12 | hs_err_pid* 13 | 14 | 15 | 16 | .idea 17 | 18 | /target 19 | 20 | *.iml -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Tang Sicheng 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Maliang 2 | 3 | Maliang(马良), the name of this project comes from a character of folk tail in China who has a magical brush by which he can draw any thing and turn it to real thing. 4 | 5 | ## Motivation 6 | In most of J2EE projet, there are a lot of codes are about CRUD which refer to the basic functions of a database or persistence layer in a software system. By using Maliang, you can generate these template codes based on your DDL 7 | ``` 8 | CREATE TABLE `user` ( 9 | `id` int(11) NOT NULL AUTO_INCREMENT, 10 | `name` varchar(32) DEFAULT NULL, 11 | `age` int(11) DEFAULT NULL, 12 | `sex` varchar(2) DEFAULT NULL, 13 | PRIMARY KEY (`id`) 14 | ) 15 | ``` 16 | 17 | ## Under the hood 18 | Maliang use sql parser to parser DDL, then convert the result to a VelocityContext. 19 | The *SourceCodeGenerator.generate(VelocityContext context)* will generate the code with the template and output directory, so acctually you could generate code with your own context builder and your own tempalte. 20 | 21 | ## Some rules 22 | 1. **Directroy and File Name** 23 | The *SourceCodeGenerator* will replace automatically replace the directory path and the file name with the value in VelocityContext. Suppose you have a template file called ```/${basepackage}/${name}Dao.java```, and in the context the ```${basepackage}``` equals ```com.github.maliang``` and the ```${name}``` equals ```jadetang```, you will get a new file ```/com/github/maliang/jadetangDao.java``` 24 | 25 | 2. **Database table naming convention** 26 | Usually we name the database objects in a different way comparing we name the java objects, with the custom config file, you can control how the database object name are converted to the java object name.Here is a config examle 27 | ``` 28 | name { 29 | separator = "T_APP" 30 | table.prefix = "F" 31 | column.prefix = "_" 32 | } 33 | ``` 34 | -------------------------------------------------------------------------------- /TODO.txt: -------------------------------------------------------------------------------- 1 | 按照是否值得做从前到后排序 2 | 0. 更多的模板 3 | 4 | 1. 领域对象需要更加完善的信息以生成更加强大的模板。例如 5 | ~ 某个字段为空,则生成的java对象应该有@NotNull标注。 6 | ~ 如果表有一个自增长的id字段,则可以生成selectById,deleteById等方法 7 | ~ 如果某些字段是date类型,生成的spring controller方法实际上是需要对于date类型的http参数进行特殊。 8 | 现在用的是jsqlparser,这些信息都应该可以拿到,通过修改JavaDataBaseRelationBuilder方法,可以增强model包下的领域模型的信息,例如java type是否是日期类型,是否为空,是否是主键。 9 | 或者重新写一个真对create table的parser 10 | 11 | 2. 目前的路径只能是绝对路径,如果在windows下,配置成/data/dirX之类的路径是不行的,但是log4j等日志框架,可以支持。 12 | 13 | 3. 目前的ddl只能通过输入的方式,也可以通过直接连数据库的方式来获取,例如mybatis generator的做法。 14 | 15 | 4. 只支持单表生成sql,可以通过配置表和表之间关系的方式生成join sql和更加复杂的复合model,可以参考 spring roo的one to many的表关系配置。 -------------------------------------------------------------------------------- /example/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | maliang 7 | github.jadetang 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | github.jadetang 13 | maliang-example 14 | 15 | 16 | -------------------------------------------------------------------------------- /example/src/main/java/Main.java: -------------------------------------------------------------------------------- 1 | import com.typesafe.config.ConfigFactory; 2 | import github.jadetang.maliang.MEngine; 3 | import github.jadetang.maliang.conf.MConfig; 4 | import github.jadetang.maliang.resource.Resources; 5 | 6 | import java.io.File; 7 | import java.io.IOException; 8 | 9 | /** 10 | * @Author Tang Sicheng 11 | */ 12 | public class Main { 13 | 14 | 15 | private static MConfig mConfig = new MConfig(ConfigFactory.load()); 16 | 17 | private static String sql = "CREATE TABLE user (\n" + 18 | " age INT,\n" + 19 | " NAME VARCHAR(32),\n" + 20 | " sex VARCHAR\n" + 21 | ");" + 22 | "create table salary(" + 23 | "name varchar(32)," + 24 | "pay int)"; 25 | 26 | public static void main(String[] args) throws IOException { 27 | 28 | File customConfig = Resources.getResourceAsFile(Main.class.getClassLoader(),"SimpleExample/custom.conf"); 29 | MEngine engine = new MEngine(customConfig); 30 | engine.generateCode(sql); 31 | 32 | /* Path simpleExample = Paths.get("example/src/main/resources/SimpleExample"); 33 | Path outPut = Paths.get("example/target/output"); 34 | 35 | JavaObjectBuilder javaObjectBuilder = new JavaObjectBuilder(mConfig); 36 | Tuple t = javaObjectBuilder.parser(sql); 37 | VelocityContext c = ContextBuilder.build(t._1(),t._2(),mConfig); 38 | 39 | // System.out.println(m.getBasePackage()); 40 | SourceCodeGenerator generator = new SourceCodeGenerator(simpleExample.toAbsolutePath().toString(), outPut.toAbsolutePath().toString(), mConfig); 41 | generator.init(); 42 | generator.generate(c);*/ 43 | } 44 | 45 | 46 | } 47 | -------------------------------------------------------------------------------- /example/src/main/resources/SimpleExample/custom.conf: -------------------------------------------------------------------------------- 1 | maven { 2 | groupId = com.meizu.orion 3 | artifactId = quick-start 4 | version = 1.0.0-SNAPSHOT 5 | package = com.meizu.orion 6 | } 7 | 8 | 9 | 10 | dir{ 11 | template = "E:\\code_base\\maliang\\example\\src\\main\\resources\\SimpleExample" 12 | output = "E:\\test" 13 | backup = "E:\\temp" 14 | } 15 | 16 | 17 | -------------------------------------------------------------------------------- /example/src/main/resources/SimpleExample/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | 6 | com.meizu.base 7 | parent.war 8 | 2.2.1 9 | 10 | ${groupId} 11 | ${artifactId} 12 | ${version} 13 | ${artifactId} 14 | war 15 | http://maven.apache.org 16 | 17 | 18 | 19 | 20 | 21 | com.meizu.framework 22 | framework-service 23 | 1.0.2 24 | 25 | 26 | 27 | 28 | 29 | 30 | org.springframework 31 | spring-beans 32 | 33 | 34 | org.springframework 35 | spring-core 36 | 37 | 38 | org.springframework 39 | spring-context 40 | 41 | 42 | org.springframework 43 | spring-webmvc 44 | 45 | 46 | javaee 47 | javaee 48 | provided 49 | 50 | 51 | 52 | 53 | 54 | org.mybatis 55 | mybatis 56 | 3.5.6 57 | 58 | 59 | org.mybatis 60 | mybatis-spring 61 | 1.2.0 62 | 63 | 64 | org.springframework 65 | spring-tx 66 | 67 | 68 | 69 | 70 | com.github.miemiedev 71 | mybatis-paginator 72 | 1.2.17 73 | 74 | 75 | 76 | 77 | 78 | 79 | org.apache.commons 80 | commons-lang3 81 | 3.3.2 82 | 83 | 84 | 85 | 86 | 87 | log4j 88 | log4j 89 | 90 | 91 | org.slf4j 92 | slf4j-log4j12 93 | 1.7.5 94 | 95 | 96 | com.googlecode.log4jdbc 97 | log4jdbc 98 | 1.2 99 | 100 | 101 | 102 | 103 | 104 | 105 | com.google.code.gson 106 | gson 107 | 2.2.4 108 | 109 | 110 | 111 | 112 | 113 | 114 | com.jolbox 115 | bonecp 116 | 0.8.0.RELEASE 117 | 118 | 119 | mysql-connector-java 120 | mysql-connector-java 121 | 5.1.22 122 | 123 | 124 | 125 | 126 | 127 | 128 | org.springframework 129 | spring-test 130 | test 131 | 132 | 133 | junit 134 | junit 135 | test 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | env.develop 146 | 147 | true 148 | 149 | 150 | 151 | 152 | 153 | org.apache.maven.plugins 154 | maven-war-ant-plugin 155 | 156 | 157 | combining js... 158 | 159 | 160 | 162 | 164 | 165 | 166 | 167 | 169 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | env.production 181 | 182 | 183 | 184 | org.apache.maven.plugins 185 | maven-war-ant-plugin 186 | 187 | 188 | combining js... 189 | 190 | 191 | 193 | 195 | 196 | 197 | 198 | 200 | 202 | 203 | 206 | 208 | 209 | 210 | 211 | 212 | 215 | 217 | 218 | 219 | 220 | 221 | 222 | 225 | 226 | 227 | 228 | 229 | 230 | org.codehaus.mojo 231 | rpm-maven-plugin 232 | 233 | 234 | org.apache.maven.plugins 235 | maven-deploy-plugin 236 | 237 | 238 | org.codehaus.mojo 239 | build-helper-maven-plugin 240 | 241 | 242 | 243 | 244 | 245 | 246 | -------------------------------------------------------------------------------- /example/src/main/resources/SimpleExample/src/main/java/${package}/controller/${bean.name}Controller.java: -------------------------------------------------------------------------------- 1 | #define( $service ) ${StringUtil.lowerFirstLetter(${bean.name})}Service#end 2 | #set( $beanRef = ${StringUtil.lowerFirstLetter(${bean.name})} ) 3 | 4 | package ${package}.controller; 5 | 6 | import ${package}.service.${bean.name}Service; 7 | import ${package}.model.${bean.name}; 8 | 9 | import com.github.miemiedev.mybatis.paginator.domain.PageBounds; 10 | import com.github.miemiedev.mybatis.paginator.domain.PageList; 11 | import org.springframework.beans.factory.annotation.Autowired; 12 | import org.springframework.stereotype.Controller; 13 | import org.springframework.web.bind.annotation.RequestMapping; 14 | import org.springframework.web.bind.annotation.RequestMethod; 15 | import org.springframework.web.bind.annotation.RequestParam; 16 | 17 | import javax.servlet.http.HttpServletResponse; 18 | import java.io.IOException; 19 | import java.util.List; 20 | 21 | @Controller 22 | @RequestMapping(value = "/v1/${beanRef}s") 23 | public class ${bean.name}Controller extends BaseController{ 24 | 25 | 26 | @Autowired 27 | private ${bean.name}Service ${service}; 28 | 29 | @RequestMapping(value="",method=RequestMethod.POST) 30 | public void insert${bean.name}(${bean.name} $beanRef,HttpServletResponse response) throws IOException { 31 | Integer affectRecord = ${service}.insert($beanRef); 32 | responseAsJson(response,affectRecord); 33 | } 34 | 35 | @RequestMapping(value="",method=RequestMethod.GET) 36 | public void selectAll${bean.name}(HttpServletResponse response) throws IOException { 37 | List<${bean.name}> all${bean.name} = ${service}.selectAll(); 38 | responseAsJson(response,all${bean.name}); 39 | } 40 | 41 | @RequestMapping(value="/$beanRef",method=RequestMethod.GET) 42 | public void select${bean.name}(${bean.name} $beanRef,@RequestParam(required = false, defaultValue = "1") int page, 43 | @RequestParam(required = false, defaultValue = "10") int limit,HttpServletResponse response) 44 | throws IOException { 45 | List ${bean.name}s = ${service}.select($beanRef, new PageBounds(page, limit)); 46 | responseAsJson(response,(PageList)${bean.name}s); 47 | } 48 | 49 | @RequestMapping(value="/$beanRef",method=RequestMethod.DELETE) 50 | public void delele${bean.name}(${bean.name} $beanRef,HttpServletResponse response )throws IOException { 51 | Integer affectRecord = ${service}.delete($beanRef); 52 | responseAsJson(response,affectRecord); 53 | } 54 | 55 | @RequestMapping(value="/$beanRef",method=RequestMethod.PUT) 56 | public void update${bean.name}(${bean.name} $beanRef,HttpServletResponse response )throws IOException { 57 | Integer affectRecord = ${service}.update($beanRef); 58 | responseAsJson(response,affectRecord); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /example/src/main/resources/SimpleExample/src/main/java/${package}/controller/BaseController.java: -------------------------------------------------------------------------------- 1 | package ${package}.controller; 2 | 3 | 4 | import ${package}.util.JsonUtil; 5 | 6 | import javax.servlet.http.HttpServletResponse; 7 | import java.io.IOException; 8 | import java.io.PrintWriter; 9 | 10 | public class BaseController{ 11 | 12 | protected void responseAsJson(HttpServletResponse response,Object object) throws IOException { 13 | response.setContentType("application/json; charset=utf-8"); 14 | PrintWriter out = response.getWriter(); 15 | out.write(JsonUtil.toJson(object)); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /example/src/main/resources/SimpleExample/src/main/java/${package}/dao/${bean.name}Dao.java: -------------------------------------------------------------------------------- 1 | package ${config.basePackage}.dao; 2 | 3 | import java.util.List; 4 | import ${config.basePackage}.model.${bean.name}; 5 | 6 | import org.springframework.stereotype.Repository; 7 | import com.github.miemiedev.mybatis.paginator.domain.PageBounds; 8 | 9 | @Repository("${StringUtil.lowerFirstLetter(${bean.name})}Dao") 10 | public class ${bean.name}Dao extends BaseDao{ 11 | 12 | public List select(${bean.name} entity,PageBounds pageBounds) { 13 | return this.getSqlMap().selectList(this.getClass().getName()+".select", entity, pageBounds); 14 | } 15 | 16 | public List<${bean.name}> selectAll(){ 17 | return this.getSqlMap().selectList(this.getClass().getName()+".selectAll"); 18 | } 19 | 20 | public Integer delete(${bean.name} entity){ 21 | return this.getSqlMap().delete(this.getClass().getName()+".delete",entity); 22 | } 23 | 24 | public Integer update(${bean.name} entity){ 25 | return this.getSqlMap().update(this.getClass().getName()+".update",entity); 26 | } 27 | 28 | public Integer insert(${bean.name} entity){ 29 | return this.getSqlMap().insert(this.getClass().getName()+".insert",entity); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /example/src/main/resources/SimpleExample/src/main/java/${package}/dao/BaseDao.java: -------------------------------------------------------------------------------- 1 | package ${package}.dao; 2 | 3 | import org.mybatis.spring.SqlSessionTemplate; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.beans.factory.annotation.Qualifier; 6 | 7 | public abstract class BaseDao{ 8 | protected SqlSessionTemplate getSqlMap(){ 9 | return sqlSessionTemplate; 10 | } 11 | 12 | public SqlSessionTemplate getSqlSessionTemplate() { 13 | return sqlSessionTemplate; 14 | } 15 | 16 | public void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) { 17 | this.sqlSessionTemplate = sqlSessionTemplate; 18 | } 19 | 20 | @Autowired 21 | @Qualifier("sqlSessionTemplate") 22 | private SqlSessionTemplate sqlSessionTemplate; 23 | 24 | } 25 | -------------------------------------------------------------------------------- /example/src/main/resources/SimpleExample/src/main/java/${package}/model/${bean.name}.java: -------------------------------------------------------------------------------- 1 | #set( $symbol_pound = '#' ) 2 | #set( $symbol_dollar = '$' ) 3 | #set( $symbol_escape = '\' ) 4 | package ${package}.model; 5 | 6 | import org.apache.commons.lang3.builder.ToStringBuilder; 7 | import org.apache.commons.lang3.builder.ToStringStyle; 8 | 9 | public class ${bean.name}{ 10 | 11 | public ${bean.name}(){} 12 | 13 | #foreach ( $field in $bean.getFields() ) 14 | private $field.type ${StringUtil.lowerFirstLetter(${field.name})}; 15 | 16 | #end 17 | #foreach ( $field in $bean.getFields() ) 18 | public void set${field.name}($field.type ${StringUtil.lowerFirstLetter(${field.name})}){ 19 | this.${StringUtil.lowerFirstLetter(${field.name})} = ${StringUtil.lowerFirstLetter(${field.name})}; 20 | } 21 | 22 | public $field.type get${field.name}(){ 23 | return ${StringUtil.lowerFirstLetter(${field.name})}; 24 | } 25 | #end 26 | 27 | @Override 28 | public String toString() { 29 | return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /example/src/main/resources/SimpleExample/src/main/java/${package}/service/${bean.name}Service.java: -------------------------------------------------------------------------------- 1 | package ${package}.service; 2 | 3 | import ${package}.dao.${bean.name}Dao; 4 | import ${package}.model.${bean.name}; 5 | import com.github.miemiedev.mybatis.paginator.domain.PageBounds; 6 | import java.util.List; 7 | 8 | public interface ${bean.name}Service{ 9 | 10 | Integer insert(${bean.name} entity); 11 | 12 | Integer update(${bean.name} entity); 13 | 14 | List select(${bean.name} entity,PageBounds pageBounds); 15 | 16 | List<${bean.name}> selectAll(); 17 | 18 | Integer delete(${bean.name} entity); 19 | } 20 | -------------------------------------------------------------------------------- /example/src/main/resources/SimpleExample/src/main/java/${package}/service/impl/${bean.name}ServiceImpl.java: -------------------------------------------------------------------------------- 1 | #define( $dao ) ${StringUtil.lowerFirstLetter(${bean.name})}Dao#end 2 | package ${package}.service.impl; 3 | 4 | import ${package}.dao.${bean.name}Dao; 5 | import ${package}.model.${bean.name}; 6 | import ${package}.service.${bean.name}Service; 7 | import com.github.miemiedev.mybatis.paginator.domain.PageBounds; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.stereotype.Service; 10 | import java.util.List; 11 | 12 | @Service("${beanRef}ServiceImpl") 13 | public class ${bean.name}ServiceImpl implements ${bean.name}Service{ 14 | 15 | @Autowired 16 | private ${bean.name}Dao ${dao}; 17 | 18 | public Integer insert(${bean.name} entity){ 19 | return ${dao}.insert(entity); 20 | } 21 | 22 | public Integer update(${bean.name} entity){ 23 | return ${dao}.update(entity); 24 | } 25 | 26 | public List select(${bean.name} entity,PageBounds pageBounds){ 27 | return ${dao}.select(entity,pageBounds); 28 | } 29 | 30 | public List<${bean.name}> selectAll(){ 31 | return ${dao}.selectAll(); 32 | } 33 | 34 | public Integer delete(${bean.name} entity){ 35 | return ${dao}.delete(entity); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /example/src/main/resources/SimpleExample/src/main/java/${package}/util/JsonUtil.java: -------------------------------------------------------------------------------- 1 | package ${package}.util; 2 | 3 | import com.github.miemiedev.mybatis.paginator.domain.PageList; 4 | import com.github.miemiedev.mybatis.paginator.domain.Paginator; 5 | import com.google.gson.*; 6 | 7 | import java.lang.reflect.Type; 8 | import java.util.ArrayList; 9 | 10 | /** 11 | * @author TANG SICHENG 12 | */ 13 | public class JsonUtil { 14 | 15 | 16 | 17 | private final static Gson gson; 18 | static { 19 | GsonBuilder gsonBuilder = new GsonBuilder(); 20 | gsonBuilder.registerTypeAdapter(PageList.class, new PageListSerialiser()); 21 | gson = gsonBuilder.create(); 22 | } 23 | 24 | 25 | public static String toJson(Object o){ 26 | return gson.toJson(o); 27 | } 28 | 29 | private static class PageListSerialiser implements JsonSerializer { 30 | 31 | 32 | @Override 33 | public JsonElement serialize(PageList pageList, Type type, JsonSerializationContext context) { 34 | final JsonObject jsonObject = new JsonObject(); 35 | Paginator paginator = pageList.getPaginator(); 36 | jsonObject.addProperty("totalCount", paginator.getTotalCount()); 37 | jsonObject.addProperty("totalPages", paginator.getTotalPages()); 38 | jsonObject.addProperty("page", paginator.getPage()); 39 | 40 | final JsonElement items = context.serialize(new ArrayList(pageList)); 41 | jsonObject.add("items", items); 42 | 43 | jsonObject.addProperty("startRow", paginator.getStartRow()); 44 | jsonObject.addProperty("endRow", paginator.getEndRow()); 45 | 46 | jsonObject.addProperty("offset", paginator.getOffset()); 47 | 48 | final JsonArray jsonSlides = new JsonArray(); 49 | for (final Integer slide : paginator.getSlider()) { 50 | final JsonPrimitive jsonSlide = new JsonPrimitive(slide); 51 | jsonSlides.add(jsonSlide); 52 | } 53 | jsonObject.add("slider", jsonSlides); 54 | 55 | jsonObject.addProperty("prePage", paginator.getPrePage()); 56 | jsonObject.addProperty("nextPage", paginator.getNextPage()); 57 | 58 | jsonObject.addProperty("firstPage", paginator.isFirstPage()); 59 | jsonObject.addProperty("hasNextPage", paginator.isHasNextPage()); 60 | jsonObject.addProperty("hasPrePage", paginator.isHasPrePage()); 61 | jsonObject.addProperty("lastPage", paginator.isLastPage()); 62 | 63 | return jsonObject; 64 | } 65 | } 66 | 67 | 68 | } 69 | -------------------------------------------------------------------------------- /example/src/main/resources/SimpleExample/src/main/java/net/sf/log4jdbc/DataSourceSpyInterceptor.java: -------------------------------------------------------------------------------- 1 | package net.sf.log4jdbc; 2 | 3 | import org.aopalliance.intercept.MethodInterceptor; 4 | import org.aopalliance.intercept.MethodInvocation; 5 | 6 | import java.sql.Connection; 7 | 8 | /** 9 | * @author badqiu 10 | */ 11 | public class DataSourceSpyInterceptor implements MethodInterceptor { 12 | 13 | private RdbmsSpecifics rdbmsSpecifics = null; 14 | 15 | private RdbmsSpecifics getRdbmsSpecifics(Connection conn) { 16 | if(rdbmsSpecifics == null) { 17 | rdbmsSpecifics = DriverSpy.getRdbmsSpecifics(conn); 18 | } 19 | return rdbmsSpecifics; 20 | } 21 | 22 | public Object invoke(MethodInvocation invocation) throws Throwable { 23 | Object result = invocation.proceed(); 24 | if(SpyLogFactory.getSpyLogDelegator().isJdbcLoggingEnabled()) { 25 | if(result instanceof Connection) { 26 | Connection conn = (Connection)result; 27 | return new ConnectionSpy(conn,DriverSpy.getRdbmsSpecifics(conn)); 28 | } 29 | } 30 | return result; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /example/src/main/resources/SimpleExample/src/main/resources/log4j.properties: -------------------------------------------------------------------------------- 1 | log4j.rootLogger=INFO,stdout,FILE 2 | 3 | log4j.appender.stdout=org.apache.log4j.ConsoleAppender 4 | log4j.appender.stdout.layout=org.apache.log4j.PatternLayout 5 | log4j.appender.stdout.layout.conversionPattern= %d [%t] %-p %x %m%n 6 | 7 | 8 | log4j.appender.FILE = org.apache.log4j.DailyRollingFileAppender 9 | log4j.appender.FILE.File = /data/logs/${artifactId}.log 10 | log4j.appender.FILE.Append = true 11 | log4j.appender.FILE.encoding = UTF-8 12 | log4j.appender.FILE.layout = org.apache.log4j.PatternLayout 13 | log4j.appender.FILE.MaxBackupIndex = 3 14 | log4j.appender.FILE.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n 15 | 16 | log4j.logger.org.springframework=INFO 17 | 18 | log4j.logger.jdbc.sqlonly = INFO 19 | log4j.logger.jdbc.sqltiming = OFF 20 | log4j.logger.jdbc.audit = OFF 21 | log4j.logger.jdbc.resultset = OFF 22 | log4j.logger.jdbc.connection = ERROR 23 | -------------------------------------------------------------------------------- /example/src/main/resources/SimpleExample/src/main/resources/mappers/${bean.name}Mapper.xml: -------------------------------------------------------------------------------- 1 | #set( $empty = '' ) 2 | #define( $beanClass )${package}.model.${bean.name}#end 3 | #define( $daoClass )${config.basePackage}.dao.${bean.name}Dao#end 4 | 5 | 6 | 7 | 8 | 9 | 10 | #foreach ( $relation in ${relations.getRelations()} ) 11 | ${relation.column.name} as ${StringUtil.lowerFirstLetter(${relation.field.name})}#if($foreach.hasNext),#end$empty 12 | #end 13 | 14 | 15 | 16 | 17 | #foreach ( $relation in ${relations.getRelations()} ) 18 | 19 | and ${relation.column.name} = #{${StringUtil.lowerFirstLetter(${relation.field.name})}} 20 | 21 | #end$empty 22 | 23 | 24 | 25 | 28 | 29 | 30 | 34 | 35 | 36 | delete from ${table.name} 37 | 38 | 39 | 40 | 41 | UPDATE ${table.name} SET 42 | #foreach ( $relation in ${relations.getRelations()} ) 43 | 44 | ${relation.column.name}=#{${StringUtil.lowerFirstLetter(${relation.field.name})},jdbyType=${relation.column.type}}, 45 | 46 | #end 47 | 48 | 49 | 50 | 51 | 52 | 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /example/src/main/resources/SimpleExample/src/main/resources/mybatis/mybatis.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 17 | 18 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /example/src/main/resources/SimpleExample/src/main/resources/spring/application-context.xml: -------------------------------------------------------------------------------- 1 | #set( $symbol_pound = '#' ) 2 | #set( $symbol_dollar = '$' ) 3 | #set( $symbol_escape = '\' ) 4 | 5 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /example/src/main/resources/SimpleExample/src/main/resources/spring/application-datasource.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 35 | 36 | 38 | 39 | 40 | log4jdbcInterceptor 41 | 42 | 43 | 44 | 45 | dataSource 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /example/src/main/resources/SimpleExample/src/main/resources/spring/application-mybatis.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | classpath:mappers/*Mapper.xml 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /example/src/main/resources/SimpleExample/src/main/resources/spring/application-servlet.xml: -------------------------------------------------------------------------------- 1 | #set( $symbol_pound = '#' ) 2 | #set( $symbol_dollar = '$' ) 3 | #set( $symbol_escape = '\' ) 4 | 5 | 15 | 16 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /example/src/main/resources/SimpleExample/src/main/webapp/WEB-INF/jetty-web.xml: -------------------------------------------------------------------------------- 1 | #set( $symbol_pound = '#' ) 2 | #set( $symbol_dollar = '$' ) 3 | #set( $symbol_escape = '\' ) 4 | 5 | 6 | 7 | 16 | 17 | 18 | 19 | / 20 | 200000 21 | true 22 | false 23 | 24 | 25 | 127.0.0.1 26 | localhost 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /example/src/main/resources/SimpleExample/src/main/webapp/WEB-INF/web.xml: -------------------------------------------------------------------------------- 1 | #set( $symbol_pound = '#' ) 2 | #set( $symbol_dollar = '$' ) 3 | #set( $symbol_escape = '\' ) 4 | 5 | 9 | ${artifactId} 10 | 11 | SessionFilter 12 | com.meizu.framework.impl.servlet.SessionFilter 13 | 14 | IgnoreContent 15 | js,css,jpg,png,gif,swf,bmp,ico 16 | 17 | 18 | 19 | SessionFilter 20 | /* 21 | 22 | 23 | EncodingFilter 24 | org.springframework.web.filter.CharacterEncodingFilter 25 | 26 | encoding 27 | UTF-8 28 | 29 | 30 | forceEncoding 31 | true 32 | 33 | 34 | 35 | EncodingFilter 36 | /* 37 | 38 | 39 | log4jConfigLocation 40 | classpath:log4j.properties 41 | 42 | 43 | contextConfigLocation 44 | classpath:spring/application-context.xml 45 | 46 | 47 | org.springframework.web.util.Log4jConfigListener 48 | 49 | 50 | org.springframework.web.context.request.RequestContextListener 51 | 52 | 53 | com.meizu.framework.impl.container.WebContextLoaderListener 54 | 55 | 56 | dispatcher 57 | org.springframework.web.servlet.DispatcherServlet 58 | 59 | contextConfigLocation 60 | classpath:spring/application-context.xml 61 | 62 | 1 63 | 64 | 65 | dispatcher 66 | / 67 | 68 | 69 | index.html 70 | 71 | 72 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.github.jadetang 8 | maliang 9 | jar 10 | 1.0-SNAPSHOT 11 | 12 | 13 | 14 | org.apache.velocity 15 | velocity 16 | 1.7 17 | 18 | 19 | com.github.jsqlparser 20 | jsqlparser 21 | 0.9 22 | 23 | 24 | com.google.guava 25 | guava 26 | 29.0-jre 27 | 28 | 29 | com.typesafe 30 | config 31 | 1.2.1 32 | 33 | 34 | 35 | 36 | org.slf4j 37 | slf4j-api 38 | 1.6.1 39 | 40 | 41 | org.slf4j 42 | slf4j-log4j12 43 | 1.6.1 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | org.apache.maven.plugins 52 | maven-compiler-plugin 53 | 2.3.2 54 | 55 | 1.7 56 | 1.7 57 | UTF-8 58 | 59 | 60 | 61 | maven-source-plugin 62 | 2.2.1 63 | 64 | true 65 | 66 | 67 | 68 | compile 69 | 70 | jar 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /src/main/java/github/jadetang/maliang/MEngine.java: -------------------------------------------------------------------------------- 1 | package github.jadetang.maliang; 2 | 3 | import com.typesafe.config.Config; 4 | import com.typesafe.config.ConfigFactory; 5 | import github.jadetang.maliang.bean.JavaDataBaseRelation; 6 | import github.jadetang.maliang.builder.ContextBuilder; 7 | import github.jadetang.maliang.builder.JavaDataBaseRelationBuilder; 8 | import github.jadetang.maliang.builder.SourceCodeGenerator; 9 | import github.jadetang.maliang.conf.MConfig; 10 | import org.apache.velocity.VelocityContext; 11 | 12 | import java.io.File; 13 | import java.io.IOException; 14 | import java.util.List; 15 | import java.util.Properties; 16 | 17 | /** 18 | * @Author Tang Sicheng 19 | */ 20 | public class MEngine { 21 | 22 | private MConfig mConfig; 23 | private JavaDataBaseRelationBuilder javaObjectBuilder; 24 | private SourceCodeGenerator generator; 25 | 26 | /** 27 | * Construct an instance with default configuration 28 | */ 29 | public MEngine() { 30 | this(ConfigFactory.empty()); 31 | } 32 | 33 | /** 34 | * Construct an instance with custom properties 35 | * @param properties custom properties 36 | */ 37 | public MEngine(Properties properties) { 38 | this(ConfigFactory.parseProperties(properties)); 39 | } 40 | 41 | /** 42 | * Construct an instance with custom properties written in file 43 | * @param file 44 | */ 45 | public MEngine(File file){ 46 | this(ConfigFactory.parseFile(file)); 47 | } 48 | 49 | 50 | public MEngine(Config config) { 51 | Config defaultConfig = ConfigFactory.load(); 52 | mConfig = new MConfig(config.withFallback(defaultConfig)); 53 | javaObjectBuilder = new JavaDataBaseRelationBuilder(mConfig); 54 | generator = new SourceCodeGenerator(mConfig); 55 | } 56 | 57 | 58 | public void generateCode(String createStatement) throws IOException { 59 | List relations = javaObjectBuilder.parserMulit(createStatement); 60 | generator.init(); 61 | for (JavaDataBaseRelation relation : relations) { 62 | VelocityContext context = ContextBuilder.build(relation, mConfig); 63 | generator.generate(context); 64 | } 65 | } 66 | 67 | 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/github/jadetang/maliang/bean/Column.java: -------------------------------------------------------------------------------- 1 | package github.jadetang.maliang.bean; 2 | 3 | import org.apache.commons.lang.builder.ToStringBuilder; 4 | import org.apache.commons.lang.builder.ToStringStyle; 5 | 6 | /** 7 | * @Author Tang Sicheng 8 | */ 9 | public class Column { 10 | 11 | private String name; 12 | 13 | private String type; 14 | 15 | public String getName() { 16 | return name.toUpperCase(); 17 | } 18 | 19 | public void setName(String name) { 20 | this.name = name; 21 | } 22 | 23 | public String getType() { 24 | return type; 25 | } 26 | 27 | public void setType(String type) { 28 | this.type = type; 29 | } 30 | 31 | private Column(){} 32 | 33 | private Column(ColumnBuilder builder){ 34 | this.name = builder.name; 35 | this.type = builder.type; 36 | } 37 | 38 | public static class ColumnBuilder{ 39 | private String name; 40 | private String type; 41 | public ColumnBuilder(){} 42 | 43 | public ColumnBuilder withName(String name){ 44 | this.name = name; 45 | return this; 46 | } 47 | 48 | public ColumnBuilder withType(String type){ 49 | this.type = type; 50 | return this; 51 | } 52 | 53 | public Column build(){ 54 | return new Column(this); 55 | } 56 | } 57 | 58 | @Override 59 | public String toString() { 60 | return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE); 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/github/jadetang/maliang/bean/JavaClass.java: -------------------------------------------------------------------------------- 1 | package github.jadetang.maliang.bean; 2 | 3 | import org.apache.commons.lang.builder.ToStringBuilder; 4 | import org.apache.commons.lang.builder.ToStringStyle; 5 | 6 | import java.util.LinkedList; 7 | 8 | /** 9 | * @author TANG SICHENG 10 | */ 11 | public class JavaClass { 12 | 13 | private String name; 14 | 15 | private LinkedList fields; 16 | 17 | private JavaClass() { 18 | } 19 | 20 | private JavaClass(JavaClassBuilder builder) { 21 | this.name = builder.name; 22 | this.fields = builder.javaFields; 23 | } 24 | 25 | public String getName() { 26 | return name; 27 | } 28 | 29 | public LinkedList getFields() { 30 | return fields; 31 | } 32 | 33 | @Override 34 | public String toString() { 35 | return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE); 36 | } 37 | 38 | public static class JavaClassBuilder { 39 | 40 | private String name; 41 | private LinkedList javaFields; 42 | 43 | public JavaClassBuilder() { 44 | } 45 | 46 | public JavaClassBuilder withName(String name) { 47 | JavaClassBuilder.this.name = name; 48 | return this; 49 | } 50 | 51 | public JavaClassBuilder withFields(LinkedList fields) { 52 | JavaClassBuilder.this.javaFields = new LinkedList(fields); 53 | return this; 54 | } 55 | 56 | public JavaClass build() { 57 | return new JavaClass(this); 58 | } 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/github/jadetang/maliang/bean/JavaDataBaseRelation.java: -------------------------------------------------------------------------------- 1 | package github.jadetang.maliang.bean; 2 | 3 | import com.google.common.collect.Lists; 4 | 5 | import java.util.LinkedList; 6 | 7 | /** 8 | * @author TANG SICHENG 9 | */ 10 | public class JavaDataBaseRelation { 11 | 12 | private JavaClass bean; 13 | private Table table; 14 | private LinkedList relations; 15 | 16 | public JavaDataBaseRelation(JavaClass bean,Table table){ 17 | this.bean = bean; 18 | this.table = table; 19 | this.relations = getRelations(bean,table); 20 | } 21 | 22 | private LinkedList getRelations(JavaClass bean, Table table) { 23 | LinkedList relations = Lists.newLinkedList(); 24 | assert bean.getFields().size() == table.getColumns().size(); 25 | int length = bean.getFields().size(); 26 | for (int i = 0; i < length; i++) { 27 | relations.add(new Relation(bean.getFields().get(i),table.getColumns().get(i))); 28 | } 29 | return relations; 30 | } 31 | 32 | public JavaClass getBean() { 33 | return bean; 34 | } 35 | 36 | public void setBean(JavaClass bean) { 37 | this.bean = bean; 38 | } 39 | 40 | public Table getTable() { 41 | return table; 42 | } 43 | 44 | public void setTable(Table table) { 45 | this.table = table; 46 | } 47 | 48 | public LinkedList getRelations() { 49 | return relations; 50 | } 51 | 52 | public void setRelations(LinkedList relations) { 53 | this.relations = relations; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/github/jadetang/maliang/bean/JavaField.java: -------------------------------------------------------------------------------- 1 | package github.jadetang.maliang.bean; 2 | 3 | import org.apache.commons.lang.builder.ToStringBuilder; 4 | import org.apache.commons.lang.builder.ToStringStyle; 5 | 6 | 7 | /** 8 | * @author TANG SICHENG 9 | */ 10 | public class JavaField { 11 | 12 | private String name; 13 | 14 | /** 15 | * represent a field type like Integer,Double,etc 16 | */ 17 | private String type; 18 | 19 | private JavaField(){} 20 | 21 | private JavaField(JavaFieldBuilder javaFieldBuilder){ 22 | this.name = javaFieldBuilder.name; 23 | this.type = javaFieldBuilder.type; 24 | } 25 | 26 | public String getName() { 27 | return name; 28 | } 29 | 30 | public String getType() { 31 | return type; 32 | } 33 | 34 | @Override 35 | public String toString(){ 36 | return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE); 37 | } 38 | 39 | public static class JavaFieldBuilder{ 40 | private String name; 41 | private String type; 42 | 43 | public JavaFieldBuilder(){} 44 | 45 | public JavaFieldBuilder withName(String name){ 46 | JavaFieldBuilder.this.name = name; 47 | return this; 48 | } 49 | 50 | public JavaFieldBuilder withType(String type){ 51 | JavaFieldBuilder.this.type = type; 52 | return this; 53 | } 54 | 55 | public JavaField build(){ 56 | return new JavaField(this); 57 | } 58 | 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/github/jadetang/maliang/bean/Relation.java: -------------------------------------------------------------------------------- 1 | package github.jadetang.maliang.bean; 2 | 3 | /** 4 | * @author TANG SICHENG 5 | */ 6 | public class Relation extends Tuple { 7 | 8 | private JavaField field; 9 | 10 | private Column column; 11 | 12 | public Relation(JavaField first, Column second) { 13 | super(first, second); 14 | this.field = first; 15 | this.column = second; 16 | } 17 | 18 | public JavaField bean(){ 19 | return super._1(); 20 | } 21 | 22 | public Column table(){ 23 | return super._2(); 24 | } 25 | 26 | public JavaField getField() { 27 | return field; 28 | } 29 | 30 | public void setField(JavaField field) { 31 | this.field = field; 32 | } 33 | 34 | public Column getColumn() { 35 | return column; 36 | } 37 | 38 | public void setColumn(Column column) { 39 | this.column = column; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/github/jadetang/maliang/bean/Table.java: -------------------------------------------------------------------------------- 1 | package github.jadetang.maliang.bean; 2 | 3 | import com.google.common.collect.Lists; 4 | import org.apache.commons.lang.builder.ToStringBuilder; 5 | import org.apache.commons.lang.builder.ToStringStyle; 6 | 7 | import java.util.LinkedList; 8 | 9 | /** 10 | * A simple pojo representing a table in database 11 | * @Author Tang Sicheng 12 | */ 13 | public class Table { 14 | 15 | private String name; 16 | 17 | private LinkedList columns; 18 | 19 | public String getName() { 20 | return name.toUpperCase(); 21 | } 22 | 23 | public void setName(String name) { 24 | this.name = name; 25 | } 26 | 27 | public LinkedList getColumns() { 28 | return columns; 29 | } 30 | 31 | public void setColumns(LinkedList columns) { 32 | this.columns = columns; 33 | } 34 | 35 | private Table(){} 36 | 37 | private Table(TableBuilder builder){ 38 | this.name = builder.name; 39 | this.columns = Lists.newLinkedList(builder.columns); 40 | } 41 | 42 | public static class TableBuilder{ 43 | private String name; 44 | 45 | private LinkedList columns; 46 | 47 | public TableBuilder(){} 48 | 49 | public TableBuilder withName(String name){ 50 | this.name = name; 51 | return this; 52 | } 53 | 54 | public TableBuilder withColumns(LinkedList columns){ 55 | this.columns = Lists.newLinkedList(columns); 56 | return this; 57 | } 58 | 59 | public Table build(){ 60 | return new Table(this); 61 | } 62 | } 63 | 64 | @Override 65 | public String toString() { 66 | return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/github/jadetang/maliang/bean/Tuple.java: -------------------------------------------------------------------------------- 1 | package github.jadetang.maliang.bean; 2 | 3 | /** 4 | * @Author Tang Sicheng 5 | */ 6 | public class Tuple { 7 | private T first; 8 | private S second; 9 | 10 | public Tuple(T first, S second) { 11 | this.first = first; 12 | this.second = second; 13 | } 14 | 15 | public T _1() { 16 | return first; 17 | } 18 | 19 | public S _2() { 20 | return second; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/github/jadetang/maliang/builder/ContextBuilder.java: -------------------------------------------------------------------------------- 1 | package github.jadetang.maliang.builder; 2 | 3 | import github.jadetang.maliang.bean.JavaDataBaseRelation; 4 | import github.jadetang.maliang.conf.MConfig; 5 | import github.jadetang.maliang.util.ContextUtil; 6 | import org.apache.velocity.VelocityContext; 7 | 8 | /** 9 | * @Author Tang Sicheng 10 | */ 11 | public class ContextBuilder { 12 | 13 | /** 14 | * populate a {@link org.apache.velocity.VelocityContext} 15 | * @param relation 16 | * @return 17 | */ 18 | public static VelocityContext build(JavaDataBaseRelation relation,MConfig config){ 19 | VelocityContext context = new VelocityContext(); 20 | context.put("bean", relation.getBean()); 21 | context.put("table",relation.getTable()); 22 | context.put("relations",relation); 23 | context.put("config",config); 24 | context.put("groupId",config.getGroupId()); 25 | context.put("artifactId",config.getArtifactId()); 26 | context.put("version",config.getVersion()); 27 | context.put("package",config.getBasePackage()); 28 | context.put("StringUtil", ContextUtil.newWrapper()); 29 | return context; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/github/jadetang/maliang/builder/JavaDataBaseRelationBuilder.java: -------------------------------------------------------------------------------- 1 | package github.jadetang.maliang.builder; 2 | 3 | import com.google.common.base.Function; 4 | import com.google.common.base.Joiner; 5 | import com.google.common.base.Splitter; 6 | import com.google.common.collect.Lists; 7 | import github.jadetang.maliang.bean.*; 8 | import github.jadetang.maliang.bean.JavaClass.JavaClassBuilder; 9 | import github.jadetang.maliang.bean.JavaField.JavaFieldBuilder; 10 | import github.jadetang.maliang.conf.MConfig; 11 | import github.jadetang.maliang.exception.MaliangException; 12 | import github.jadetang.maliang.util.ContextUtil; 13 | import net.sf.jsqlparser.JSQLParserException; 14 | import net.sf.jsqlparser.parser.CCJSqlParserUtil; 15 | import net.sf.jsqlparser.statement.Statement; 16 | import net.sf.jsqlparser.statement.create.table.ColumnDefinition; 17 | import net.sf.jsqlparser.statement.create.table.CreateTable; 18 | import org.apache.commons.lang.StringUtils; 19 | 20 | import java.util.LinkedList; 21 | import java.util.List; 22 | 23 | /** 24 | * using jsqlparser to parser a create table 25 | * then convert the result to {@link github.jadetang.maliang.bean.JavaDataBaseRelation} 26 | * @author TANG SICHENG 27 | */ 28 | public class JavaDataBaseRelationBuilder { 29 | 30 | private MConfig mConfig; 31 | 32 | public JavaDataBaseRelationBuilder(MConfig mConfig) { 33 | this.mConfig = mConfig; 34 | this.tablePrefix = mConfig.getTablePrefix(); 35 | this.columnPrefix = mConfig.getColumnPrefix(); 36 | this.separator = mConfig.getSeparator(); 37 | } 38 | 39 | private String tablePrefix; 40 | 41 | private String separator; 42 | 43 | private String columnPrefix; 44 | 45 | 46 | private Tuple parseToTuple(String createSQL) { 47 | try { 48 | Statement statement = CCJSqlParserUtil.parse(createSQL); 49 | if (statement instanceof CreateTable) { 50 | JavaClass javaClass= buildJavaClass((CreateTable) statement); 51 | Table table = buildTable((CreateTable) statement); 52 | return new Tuple<>(javaClass,table); 53 | } else { 54 | throw new MaliangException("only accept create statement"); 55 | } 56 | } catch (JSQLParserException e) { 57 | throw new MaliangException(e); 58 | 59 | } 60 | } 61 | 62 | 63 | public JavaDataBaseRelation parser(String createSQL){ 64 | Tuple tuple = parseToTuple(createSQL); 65 | return new JavaDataBaseRelation(tuple._1(),tuple._2()); 66 | } 67 | 68 | 69 | 70 | 71 | public List parserMulit(String createSQLs){ 72 | List sqls = Lists.newLinkedList(Splitter.on(";").omitEmptyStrings().trimResults().split(createSQLs)); 73 | return Lists.transform(sqls, new Function() { 74 | public JavaDataBaseRelation apply(String input) { 75 | return parser(input); 76 | } 77 | }); 78 | } 79 | 80 | 81 | 82 | private Table buildTable(CreateTable createStatement) { 83 | Table.TableBuilder tableBuilder = new Table.TableBuilder(); 84 | tableBuilder.withName(createStatement.getTable().getName().toUpperCase()); 85 | tableBuilder.withColumns(extractColumns(createStatement)); 86 | return tableBuilder.build(); 87 | } 88 | 89 | private LinkedList extractColumns(CreateTable createStatement) { 90 | LinkedList columns = Lists.newLinkedList(); 91 | List columnDefinitions = createStatement.getColumnDefinitions(); 92 | for (ColumnDefinition c:columnDefinitions){ 93 | Column.ColumnBuilder cBuilder = new Column.ColumnBuilder(); 94 | cBuilder.withName(c.getColumnName().toUpperCase()); 95 | cBuilder.withType(c.getColDataType().getDataType()); 96 | columns.add(cBuilder.build()); 97 | } 98 | return columns; 99 | } 100 | 101 | private JavaClass buildJavaClass(CreateTable createStatement) { 102 | JavaClassBuilder jBuilder = new JavaClassBuilder(); 103 | String tableName = createStatement.getTable().getName(); 104 | String javaClassName = transformName(tableName,tablePrefix,separator); 105 | jBuilder.withName(javaClassName); 106 | jBuilder.withFields(extractFields(createStatement)); 107 | return jBuilder.build(); 108 | } 109 | 110 | /** 111 | * transform a database name to a java name,for example, a table in database called 112 | * T_APP_USER,then with prefix T 113 | * @param originName database object name 114 | * @param prefix database object name prefix 115 | * @param separator database object separator 116 | * @return 117 | */ 118 | private String transformName(String originName,String prefix,String separator){ 119 | if(StringUtils.isNotBlank(originName)){ 120 | originName = StringUtils.removeStart(originName,prefix); 121 | } 122 | if(StringUtils.isNotBlank(separator)){ 123 | List names = Splitter.on(separator).omitEmptyStrings().trimResults().splitToList(originName); 124 | List javaStyleNames = Lists.transform(names, new Function() { 125 | public String apply(String input) { 126 | return ContextUtil.onlyFirstLetterIsUp(input); 127 | } 128 | }); 129 | originName = Joiner.on("").join(javaStyleNames); 130 | }else { 131 | originName = ContextUtil.onlyFirstLetterIsUp(originName); 132 | } 133 | return ContextUtil.upperFirstLetter(originName); 134 | } 135 | 136 | private LinkedList extractFields(CreateTable createStatement) { 137 | LinkedList javaFields = Lists.newLinkedList(); 138 | List columnDefinitions = createStatement.getColumnDefinitions(); 139 | for (ColumnDefinition c:columnDefinitions){ 140 | javaFields.add(convertColumnToField(c)); 141 | } 142 | return javaFields; 143 | } 144 | 145 | private JavaField convertColumnToField(ColumnDefinition columnDefinition){ 146 | JavaFieldBuilder jfBuilder = new JavaFieldBuilder(); 147 | String columnName = columnDefinition.getColumnName(); 148 | String javaFieldName = transformName(columnName,columnPrefix,separator); 149 | jfBuilder.withName(javaFieldName); 150 | String javaType = mConfig.getJavaType(columnDefinition.getColDataType().getDataType()); 151 | jfBuilder.withType(javaType); 152 | return jfBuilder.build(); 153 | } 154 | 155 | 156 | } 157 | -------------------------------------------------------------------------------- /src/main/java/github/jadetang/maliang/builder/SourceCodeGenerator.java: -------------------------------------------------------------------------------- 1 | package github.jadetang.maliang.builder; 2 | 3 | import github.jadetang.maliang.conf.MConfig; 4 | import github.jadetang.maliang.exception.MaliangException; 5 | import github.jadetang.maliang.util.FileUtil; 6 | import org.apache.velocity.Template; 7 | import org.apache.velocity.VelocityContext; 8 | import org.apache.velocity.app.VelocityEngine; 9 | import org.slf4j.Logger; 10 | import org.slf4j.LoggerFactory; 11 | 12 | import java.io.*; 13 | import java.nio.file.DirectoryStream; 14 | import java.nio.file.Files; 15 | import java.nio.file.Path; 16 | import java.nio.file.Paths; 17 | import java.nio.file.attribute.FileAttribute; 18 | import java.util.regex.Matcher; 19 | import java.util.regex.Pattern; 20 | 21 | /** 22 | * @Author Tang Sicheng 23 | */ 24 | public class SourceCodeGenerator { 25 | 26 | 27 | private static Logger log = LoggerFactory.getLogger(SourceCodeGenerator.class); 28 | 29 | 30 | private String templatePathStr; 31 | private String outPutPath; 32 | private MConfig config; 33 | private VelocityEngine ve; 34 | private Path templatePath; 35 | private boolean ready = false; 36 | 37 | public SourceCodeGenerator(MConfig mConfig) { 38 | this.config = mConfig; 39 | this.templatePathStr = config.getTemplateDir(); 40 | this.templatePath = Paths.get(templatePathStr); 41 | this.outPutPath = config.getOutputDir(); 42 | } 43 | 44 | public void init() throws IOException { 45 | initEngine(); 46 | FileUtil.delDirectory(outPutPath); 47 | ready = true; 48 | } 49 | 50 | 51 | private void initEngine() { 52 | ve = new VelocityEngine(); 53 | ve.setProperty(ve.FILE_RESOURCE_LOADER_PATH, templatePathStr); 54 | } 55 | 56 | public void generate(VelocityContext context) throws IOException { 57 | if (!ready) { 58 | throw new MaliangException("should call init before"); 59 | } 60 | Path outputPath = Paths.get(outPutPath); 61 | driver(templatePath, outputPath, context); 62 | ve.setProperty(ve.FILE_RESOURCE_LOADER_PATH, templatePath); 63 | } 64 | 65 | private void driver(Path sourcePath, Path desPath, VelocityContext context) throws IOException { 66 | File sourceFile = sourcePath.toFile(); 67 | if (!sourceFile.exists()) { 68 | return; 69 | } else if (sourceFile.isDirectory()) { 70 | desPath = newDirPath(desPath, context); 71 | Files.createDirectories( desPath, new FileAttribute[]{}); 72 | try (DirectoryStream subPaths = Files.newDirectoryStream(sourcePath)) { 73 | for (Path subPath : subPaths) { 74 | driver(subPath, Paths.get(desPath.toAbsolutePath().toString() + File.separator + subPath.getFileName()), context); 75 | } 76 | } 77 | } else if (sourceFile.isFile()) { 78 | generateCode(sourcePath, desPath.getParent(), context); 79 | } 80 | } 81 | 82 | private void generateCode(Path oriFileName, Path tmpDir, VelocityContext context) throws IOException { 83 | String newFileName = newPathName(oriFileName.getFileName().toString(), context); 84 | String absoluteFileName = tmpDir.toAbsolutePath().toString() + File.separator + newFileName; 85 | if (Paths.get(absoluteFileName).toFile().exists()) { 86 | //the file already exist 87 | return; 88 | } else { 89 | log.debug("FILE_RESOURCE_LOADER_PATH:" + oriFileName.getParent().toAbsolutePath().toString()); 90 | log.debug("try find resource:" + templatePath.relativize(oriFileName).toString()); 91 | Template template = ve.getTemplate(templatePath.relativize(oriFileName).toString(), "UTF-8"); 92 | assert template != null; 93 | Writer writer = null; 94 | try { 95 | writer = new FileWriter(new File(absoluteFileName), false); 96 | template.merge(context, writer); 97 | } finally { 98 | if (writer != null) { 99 | writer.close(); 100 | } 101 | } 102 | } 103 | } 104 | 105 | /** 106 | * if the path string has velocity reference like ${bean.name},then replace it with 107 | * the content in the Velocity Context, and replace "." with File.pathSeparator 108 | * @param 109 | * @return 110 | */ 111 | private Path newDirPath(Path originPath, VelocityContext context) { 112 | String newPathNameString = newPathName(originPath.toAbsolutePath().toString(), context).replace(".", File.separator); 113 | log.debug("new Path :"+newPathNameString); 114 | return Paths.get(newPathNameString); 115 | } 116 | 117 | /** 118 | * if the pathName has velocity reference like ${bean.name},then replace it with 119 | * the content in the Velocity Context 120 | * @param fileName 121 | * @return 122 | */ 123 | private String newPathName(String fileName, VelocityContext context) { 124 | //match ${xxxx} 125 | String patternString = "\\$\\{(.|\\w)+\\}"; 126 | Pattern pattern = Pattern.compile(patternString); 127 | Matcher matcher = pattern.matcher(fileName); 128 | while (matcher.find()){ 129 | String contextValue = evaluateVTL(matcher.group(), context); 130 | fileName = fileName.replaceFirst(patternString, contextValue); 131 | } 132 | return fileName; 133 | } 134 | 135 | private String evaluateVTL(String contextKey, VelocityContext context) { 136 | try (StringWriter writer = new StringWriter()) { 137 | ve.evaluate(context, writer, "Maliang", contextKey); 138 | return writer.toString(); 139 | } catch (IOException e) { 140 | e.printStackTrace(); 141 | } 142 | return null; 143 | } 144 | 145 | } 146 | -------------------------------------------------------------------------------- /src/main/java/github/jadetang/maliang/conf/MConfig.java: -------------------------------------------------------------------------------- 1 | package github.jadetang.maliang.conf; 2 | 3 | import com.google.common.collect.Maps; 4 | import com.typesafe.config.Config; 5 | import com.typesafe.config.ConfigFactory; 6 | import com.typesafe.config.ConfigValue; 7 | 8 | import java.util.Map; 9 | import java.util.Set; 10 | 11 | /** 12 | * @author TANG SICHENG 13 | */ 14 | public class MConfig { 15 | 16 | private String groupId; 17 | 18 | private String artifactId; 19 | 20 | private String version; 21 | 22 | private String basePackage; 23 | 24 | private Config config; 25 | 26 | private Map typeMap; 27 | 28 | 29 | public String getJavaType(String sqlType) { 30 | return typeMap.get(sqlType.toUpperCase()); 31 | } 32 | 33 | public MConfig(Config config) { 34 | config.checkValid(ConfigFactory.defaultReference(), "maven"); 35 | this.groupId = config.getString("maven.groupId"); 36 | this.artifactId = config.getString("maven.artifactId"); 37 | this.version = config.getString("maven.version"); 38 | this.basePackage = config.getString("maven.package"); 39 | this.typeMap = buildMap(config.getConfig("database.type")); 40 | this.config = config; 41 | } 42 | 43 | private Map buildMap(Config config) { 44 | Set> entrySet = config.entrySet(); 45 | Map m = Maps.newHashMap(); 46 | for (Map.Entry e : entrySet) { 47 | m.put(e.getKey(), String.valueOf(e.getValue().unwrapped())); 48 | } 49 | return m; 50 | } 51 | 52 | public String getVersion() { 53 | return version; 54 | } 55 | 56 | public String getArtifactId() { 57 | return artifactId; 58 | } 59 | 60 | public String getGroupId() { 61 | return groupId; 62 | } 63 | 64 | public String getBasePackage() { 65 | return basePackage; 66 | } 67 | 68 | public void setBasePackage(String basePackage) { 69 | this.basePackage = basePackage; 70 | } 71 | 72 | public String getOutputDir() { 73 | return this.config.getString("dir.output"); 74 | } 75 | 76 | public String getTemplateDir() { 77 | return this.config.getString("dir.template"); 78 | } 79 | 80 | public String getTablePrefix() { 81 | return this.config.getString("name.table.prefix"); 82 | } 83 | 84 | public String getSeparator() { 85 | return this.config.getString("name.separator"); 86 | } 87 | 88 | public String getColumnPrefix() { 89 | return this.config.getString("name.column.prefix"); 90 | } 91 | 92 | 93 | } 94 | -------------------------------------------------------------------------------- /src/main/java/github/jadetang/maliang/exception/MaliangException.java: -------------------------------------------------------------------------------- 1 | package github.jadetang.maliang.exception;/** 2 | * Created by tangsicheng on 2015/9/18. 3 | */ 4 | 5 | /** 6 | * @author TANG SICHENG 7 | */ 8 | public class MaliangException extends RuntimeException { 9 | 10 | static final long serialVersionUID = -7034897190745766938L; 11 | 12 | public MaliangException() { 13 | super(); 14 | } 15 | 16 | public MaliangException(String message) { 17 | super(message); 18 | } 19 | 20 | 21 | public MaliangException(String message, Throwable cause) { 22 | super(message, cause); 23 | } 24 | 25 | public MaliangException(Throwable cause) { 26 | super(cause); 27 | } 28 | 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/github/jadetang/maliang/resource/ClassLoaderWrapper.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2009-2015 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package github.jadetang.maliang.resource; 17 | 18 | import java.io.InputStream; 19 | import java.net.URL; 20 | 21 | /** 22 | * A class to wrap access to multiple class loaders making them work as one 23 | * @author Clinton Begin 24 | * copy from https://github.com/mybatis/mybatis-3/blob/master/src/main/java/org/apache/ibatis/io/ClassLoaderWrapper.java 25 | */ 26 | public class ClassLoaderWrapper { 27 | 28 | ClassLoader defaultClassLoader; 29 | ClassLoader systemClassLoader; 30 | 31 | ClassLoaderWrapper() { 32 | try { 33 | systemClassLoader = ClassLoader.getSystemClassLoader(); 34 | } catch (SecurityException ignored) { 35 | // AccessControlException on Google App Engine 36 | } 37 | } 38 | 39 | /* 40 | * Get a resource as a URL using the current class path 41 | * 42 | * @param resource - the resource to locate 43 | * @return the resource or null 44 | */ 45 | public URL getResourceAsURL(String resource) { 46 | return getResourceAsURL(resource, getClassLoaders(null)); 47 | } 48 | 49 | /* 50 | * Get a resource from the classpath, starting with a specific class loader 51 | * 52 | * @param resource - the resource to find 53 | * @param classLoader - the first classloader to try 54 | * @return the stream or null 55 | */ 56 | public URL getResourceAsURL(String resource, ClassLoader classLoader) { 57 | return getResourceAsURL(resource, getClassLoaders(classLoader)); 58 | } 59 | 60 | /* 61 | * Get a resource from the classpath 62 | * 63 | * @param resource - the resource to find 64 | * @return the stream or null 65 | */ 66 | public InputStream getResourceAsStream(String resource) { 67 | return getResourceAsStream(resource, getClassLoaders(null)); 68 | } 69 | 70 | /* 71 | * Get a resource from the classpath, starting with a specific class loader 72 | * 73 | * @param resource - the resource to find 74 | * @param classLoader - the first class loader to try 75 | * @return the stream or null 76 | */ 77 | public InputStream getResourceAsStream(String resource, ClassLoader classLoader) { 78 | return getResourceAsStream(resource, getClassLoaders(classLoader)); 79 | } 80 | 81 | /* 82 | * Find a class on the classpath (or die trying) 83 | * 84 | * @param name - the class to look for 85 | * @return - the class 86 | * @throws ClassNotFoundException Duh. 87 | */ 88 | public Class classForName(String name) throws ClassNotFoundException { 89 | return classForName(name, getClassLoaders(null)); 90 | } 91 | 92 | /* 93 | * Find a class on the classpath, starting with a specific classloader (or die trying) 94 | * 95 | * @param name - the class to look for 96 | * @param classLoader - the first classloader to try 97 | * @return - the class 98 | * @throws ClassNotFoundException Duh. 99 | */ 100 | public Class classForName(String name, ClassLoader classLoader) throws ClassNotFoundException { 101 | return classForName(name, getClassLoaders(classLoader)); 102 | } 103 | 104 | /* 105 | * Try to get a resource from a group of classloaders 106 | * 107 | * @param resource - the resource to get 108 | * @param classLoader - the classloaders to examine 109 | * @return the resource or null 110 | */ 111 | InputStream getResourceAsStream(String resource, ClassLoader[] classLoader) { 112 | for (ClassLoader cl : classLoader) { 113 | if (null != cl) { 114 | 115 | // try to find the resource as passed 116 | InputStream returnValue = cl.getResourceAsStream(resource); 117 | 118 | // now, some class loaders want this leading "/", so we'll add it and try again if we didn't find the resource 119 | if (null == returnValue) { 120 | returnValue = cl.getResourceAsStream("/" + resource); 121 | } 122 | 123 | if (null != returnValue) { 124 | return returnValue; 125 | } 126 | } 127 | } 128 | return null; 129 | } 130 | 131 | /* 132 | * Get a resource as a URL using the current class path 133 | * 134 | * @param resource - the resource to locate 135 | * @param classLoader - the class loaders to examine 136 | * @return the resource or null 137 | */ 138 | URL getResourceAsURL(String resource, ClassLoader[] classLoader) { 139 | 140 | URL url; 141 | 142 | for (ClassLoader cl : classLoader) { 143 | 144 | if (null != cl) { 145 | 146 | // look for the resource as passed in... 147 | url = cl.getResource(resource); 148 | 149 | // ...but some class loaders want this leading "/", so we'll add it 150 | // and try again if we didn't find the resource 151 | if (null == url) { 152 | url = cl.getResource("/" + resource); 153 | } 154 | 155 | // "It's always in the last place I look for it!" 156 | // ... because only an idiot would keep looking for it after finding it, so stop looking already. 157 | if (null != url) { 158 | return url; 159 | } 160 | 161 | } 162 | 163 | } 164 | 165 | // didn't find it anywhere. 166 | return null; 167 | 168 | } 169 | 170 | /* 171 | * Attempt to load a class from a group of classloaders 172 | * 173 | * @param name - the class to load 174 | * @param classLoader - the group of classloaders to examine 175 | * @return the class 176 | * @throws ClassNotFoundException - Remember the wisdom of Judge Smails: Well, the world needs ditch diggers, too. 177 | */ 178 | Class classForName(String name, ClassLoader[] classLoader) throws ClassNotFoundException { 179 | 180 | for (ClassLoader cl : classLoader) { 181 | 182 | if (null != cl) { 183 | 184 | try { 185 | 186 | Class c = Class.forName(name, true, cl); 187 | 188 | if (null != c) { 189 | return c; 190 | } 191 | 192 | } catch (ClassNotFoundException e) { 193 | // we'll ignore this until all classloaders fail to locate the class 194 | } 195 | 196 | } 197 | 198 | } 199 | 200 | throw new ClassNotFoundException("Cannot find class: " + name); 201 | 202 | } 203 | 204 | ClassLoader[] getClassLoaders(ClassLoader classLoader) { 205 | return new ClassLoader[]{ 206 | classLoader, 207 | defaultClassLoader, 208 | Thread.currentThread().getContextClassLoader(), 209 | getClass().getClassLoader(), 210 | systemClassLoader}; 211 | } 212 | 213 | } 214 | -------------------------------------------------------------------------------- /src/main/java/github/jadetang/maliang/resource/Resources.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2009-2015 the original author or authors. 3 | *

4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | *

8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | *

10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package github.jadetang.maliang.resource; 17 | 18 | import java.io.File; 19 | import java.io.IOException; 20 | import java.io.InputStream; 21 | import java.io.InputStreamReader; 22 | import java.io.Reader; 23 | import java.net.URL; 24 | import java.net.URLConnection; 25 | import java.nio.charset.Charset; 26 | import java.util.Properties; 27 | 28 | /** 29 | * A class to simplify access to resources through the classloader. 30 | * @author Clinton Begin 31 | * copy from https://github.com/mybatis/mybatis-3/blob/master/src/main/java/org/apache/ibatis/io/Resources.java 32 | * 33 | */ 34 | public class Resources { 35 | 36 | private static ClassLoaderWrapper classLoaderWrapper = new ClassLoaderWrapper(); 37 | 38 | /* 39 | * Charset to use when calling getResourceAsReader. 40 | * null means use the system default. 41 | */ 42 | private static Charset charset; 43 | 44 | Resources() { 45 | } 46 | 47 | /* 48 | * Returns the default classloader (may be null). 49 | * 50 | * @return The default classloader 51 | */ 52 | public static ClassLoader getDefaultClassLoader() { 53 | return classLoaderWrapper.defaultClassLoader; 54 | } 55 | 56 | /* 57 | * Sets the default classloader 58 | * 59 | * @param defaultClassLoader - the new default ClassLoader 60 | */ 61 | public static void setDefaultClassLoader(ClassLoader defaultClassLoader) { 62 | classLoaderWrapper.defaultClassLoader = defaultClassLoader; 63 | } 64 | 65 | /* 66 | * Returns the URL of the resource on the classpath 67 | * 68 | * @param resource The resource to find 69 | * @return The resource 70 | * @throws java.io.IOException If the resource cannot be found or read 71 | */ 72 | public static URL getResourceURL(String resource) throws IOException { 73 | // issue #625 74 | return getResourceURL(null, resource); 75 | } 76 | 77 | /* 78 | * Returns the URL of the resource on the classpath 79 | * 80 | * @param loader The classloader used to fetch the resource 81 | * @param resource The resource to find 82 | * @return The resource 83 | * @throws java.io.IOException If the resource cannot be found or read 84 | */ 85 | public static URL getResourceURL(ClassLoader loader, String resource) throws IOException { 86 | URL url = classLoaderWrapper.getResourceAsURL(resource, loader); 87 | if (url == null) { 88 | throw new IOException("Could not find resource " + resource); 89 | } 90 | return url; 91 | } 92 | 93 | /* 94 | * Returns a resource on the classpath as a Stream object 95 | * 96 | * @param resource The resource to find 97 | * @return The resource 98 | * @throws java.io.IOException If the resource cannot be found or read 99 | */ 100 | public static InputStream getResourceAsStream(String resource) throws IOException { 101 | return getResourceAsStream(null, resource); 102 | } 103 | 104 | /* 105 | * Returns a resource on the classpath as a Stream object 106 | * 107 | * @param loader The classloader used to fetch the resource 108 | * @param resource The resource to find 109 | * @return The resource 110 | * @throws java.io.IOException If the resource cannot be found or read 111 | */ 112 | public static InputStream getResourceAsStream(ClassLoader loader, String resource) throws IOException { 113 | InputStream in = classLoaderWrapper.getResourceAsStream(resource, loader); 114 | if (in == null) { 115 | throw new IOException("Could not find resource " + resource); 116 | } 117 | return in; 118 | } 119 | 120 | /* 121 | * Returns a resource on the classpath as a Properties object 122 | * 123 | * @param resource The resource to find 124 | * @return The resource 125 | * @throws java.io.IOException If the resource cannot be found or read 126 | */ 127 | public static Properties getResourceAsProperties(String resource) throws IOException { 128 | Properties props = new Properties(); 129 | InputStream in = getResourceAsStream(resource); 130 | props.load(in); 131 | in.close(); 132 | return props; 133 | } 134 | 135 | /* 136 | * Returns a resource on the classpath as a Properties object 137 | * 138 | * @param loader The classloader used to fetch the resource 139 | * @param resource The resource to find 140 | * @return The resource 141 | * @throws java.io.IOException If the resource cannot be found or read 142 | */ 143 | public static Properties getResourceAsProperties(ClassLoader loader, String resource) throws IOException { 144 | Properties props = new Properties(); 145 | InputStream in = getResourceAsStream(loader, resource); 146 | props.load(in); 147 | in.close(); 148 | return props; 149 | } 150 | 151 | /* 152 | * Returns a resource on the classpath as a Reader object 153 | * 154 | * @param resource The resource to find 155 | * @return The resource 156 | * @throws java.io.IOException If the resource cannot be found or read 157 | */ 158 | public static Reader getResourceAsReader(String resource) throws IOException { 159 | Reader reader; 160 | if (charset == null) { 161 | reader = new InputStreamReader(getResourceAsStream(resource)); 162 | } else { 163 | reader = new InputStreamReader(getResourceAsStream(resource), charset); 164 | } 165 | return reader; 166 | } 167 | 168 | /* 169 | * Returns a resource on the classpath as a Reader object 170 | * 171 | * @param loader The classloader used to fetch the resource 172 | * @param resource The resource to find 173 | * @return The resource 174 | * @throws java.io.IOException If the resource cannot be found or read 175 | */ 176 | public static Reader getResourceAsReader(ClassLoader loader, String resource) throws IOException { 177 | Reader reader; 178 | if (charset == null) { 179 | reader = new InputStreamReader(getResourceAsStream(loader, resource)); 180 | } else { 181 | reader = new InputStreamReader(getResourceAsStream(loader, resource), charset); 182 | } 183 | return reader; 184 | } 185 | 186 | /* 187 | * Returns a resource on the classpath as a File object 188 | * 189 | * @param resource The resource to find 190 | * @return The resource 191 | * @throws java.io.IOException If the resource cannot be found or read 192 | */ 193 | public static File getResourceAsFile(String resource) throws IOException { 194 | return new File(getResourceURL(resource).getFile()); 195 | } 196 | 197 | /* 198 | * Returns a resource on the classpath as a File object 199 | * 200 | * @param loader - the classloader used to fetch the resource 201 | * @param resource - the resource to find 202 | * @return The resource 203 | * @throws java.io.IOException If the resource cannot be found or read 204 | */ 205 | public static File getResourceAsFile(ClassLoader loader, String resource) throws IOException { 206 | return new File(getResourceURL(loader, resource).getFile()); 207 | } 208 | 209 | /* 210 | * Gets a URL as an input stream 211 | * 212 | * @param urlString - the URL to get 213 | * @return An input stream with the data from the URL 214 | * @throws java.io.IOException If the resource cannot be found or read 215 | */ 216 | public static InputStream getUrlAsStream(String urlString) throws IOException { 217 | URL url = new URL(urlString); 218 | URLConnection conn = url.openConnection(); 219 | return conn.getInputStream(); 220 | } 221 | 222 | /* 223 | * Gets a URL as a Reader 224 | * 225 | * @param urlString - the URL to get 226 | * @return A Reader with the data from the URL 227 | * @throws java.io.IOException If the resource cannot be found or read 228 | */ 229 | public static Reader getUrlAsReader(String urlString) throws IOException { 230 | Reader reader; 231 | if (charset == null) { 232 | reader = new InputStreamReader(getUrlAsStream(urlString)); 233 | } else { 234 | reader = new InputStreamReader(getUrlAsStream(urlString), charset); 235 | } 236 | return reader; 237 | } 238 | 239 | /* 240 | * Gets a URL as a Properties object 241 | * 242 | * @param urlString - the URL to get 243 | * @return A Properties object with the data from the URL 244 | * @throws java.io.IOException If the resource cannot be found or read 245 | */ 246 | public static Properties getUrlAsProperties(String urlString) throws IOException { 247 | Properties props = new Properties(); 248 | InputStream in = getUrlAsStream(urlString); 249 | props.load(in); 250 | in.close(); 251 | return props; 252 | } 253 | 254 | /* 255 | * Loads a class 256 | * 257 | * @param className - the class to fetch 258 | * @return The loaded class 259 | * @throws ClassNotFoundException If the class cannot be found (duh!) 260 | */ 261 | public static Class classForName(String className) throws ClassNotFoundException { 262 | return classLoaderWrapper.classForName(className); 263 | } 264 | 265 | public static Charset getCharset() { 266 | return charset; 267 | } 268 | 269 | public static void setCharset(Charset charset) { 270 | Resources.charset = charset; 271 | } 272 | 273 | } 274 | -------------------------------------------------------------------------------- /src/main/java/github/jadetang/maliang/util/ContextUtil.java: -------------------------------------------------------------------------------- 1 | package github.jadetang.maliang.util; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | 6 | /** 7 | * @Author Tang Sicheng 8 | */ 9 | public class ContextUtil { 10 | 11 | public static final Logger log = LoggerFactory.getLogger(ContextUtil.class); 12 | 13 | 14 | private ContextUtil(){} 15 | 16 | public static String upperFirstLetter(String str) { 17 | return str.substring(0, 1).toUpperCase() + str.substring(1); 18 | } 19 | 20 | public static String lowerFirstLetter(String str) { 21 | return str.substring(0, 1).toLowerCase() + str.substring(1); 22 | } 23 | 24 | public static String onlyFirstLetterIsUp(String str) { 25 | return upperFirstLetter(str.toLowerCase()); 26 | } 27 | 28 | /** 29 | * Velocity context seems do not support static method 30 | * @return 31 | */ 32 | public static ContextUtilWrapper newWrapper(){ 33 | return new ContextUtilWrapper(); 34 | } 35 | 36 | public static class ContextUtilWrapper { 37 | public ContextUtilWrapper() { 38 | } 39 | 40 | public String upperFirstLetter(String str) { 41 | return ContextUtil.upperFirstLetter(str); 42 | } 43 | 44 | public static String lowerFirstLetter(String str) { 45 | return ContextUtil.lowerFirstLetter(str); 46 | } 47 | 48 | public static String onlyFirstLetterIsUp(String str) { 49 | return ContextUtil.onlyFirstLetterIsUp(str); 50 | } 51 | 52 | } 53 | } 54 | 55 | 56 | -------------------------------------------------------------------------------- /src/main/java/github/jadetang/maliang/util/FileUtil.java: -------------------------------------------------------------------------------- 1 | package github.jadetang.maliang.util; 2 | 3 | import com.google.common.base.Joiner; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | 7 | import java.io.File; 8 | import java.io.IOException; 9 | import java.nio.file.DirectoryStream; 10 | import java.nio.file.Files; 11 | import java.nio.file.Path; 12 | import java.nio.file.Paths; 13 | import java.util.Arrays; 14 | import java.util.List; 15 | 16 | /** 17 | * @Author Tang Sicheng 18 | */ 19 | public class FileUtil { 20 | 21 | 22 | private static Logger log = LoggerFactory.getLogger(FileUtil.class); 23 | 24 | public static void delDirectory(String path) throws IOException { 25 | Path p = Paths.get(path); 26 | delHelp(p); 27 | } 28 | 29 | private static void delHelp(Path p) throws IOException { 30 | if (!p.toFile().exists()) { 31 | return; 32 | } else if (p.toFile().isFile()) { 33 | log.debug("delete file:" + p.toAbsolutePath().toString()); 34 | Files.delete(p); 35 | } else if (p.toFile().isDirectory()) { 36 | try (DirectoryStream ds = Files.newDirectoryStream(p)) { 37 | for (Path subPath : ds) { 38 | delHelp(subPath); 39 | } 40 | } 41 | log.debug("delete directory:" + p.toAbsolutePath().toString()); 42 | Files.delete(p); 43 | } 44 | } 45 | 46 | public static String concatPath(String... paths) { 47 | List pathList = Arrays.asList(paths); 48 | return Joiner.on(File.separator).join(pathList).toString(); 49 | } 50 | 51 | public static void main(String[] args) throws IOException { 52 | FileUtil.delDirectory("E:\\test"); 53 | 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/resources/log4j.properties: -------------------------------------------------------------------------------- 1 | logRoot=/data2/log/distinctservice/ 2 | 3 | # This is the configuring for logging displayed in the Application Server 4 | log4j.rootLogger=DEBUG,stdout 5 | 6 | 7 | ################################ 8 | #stdout configure 9 | log4j.appender.stdout=org.apache.log4j.ConsoleAppender 10 | log4j.appender.stdout.layout=org.apache.log4j.PatternLayout 11 | log4j.appender.stdout.layout.conversionPattern=[%C{1}:%L] [%d{yyyy-MM-dd HH:mm:ss}] [%-5p] - %m%n 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/main/resources/reference.conf: -------------------------------------------------------------------------------- 1 | maven { 2 | groupId = github.jadetang 3 | artifactId = maliang 4 | version = 1.0.0-SNAPSHOT 5 | package = github.jadetang.maliang 6 | } 7 | 8 | database { 9 | type { 10 | VARCHAR = java.lang.String 11 | CHAR = java.lang.String 12 | BLOB = "java.lang.byte[]" 13 | VARCHAR = java.lang.String 14 | INTEGER = java.lang.Long 15 | TINYINT = java.lang.Integer 16 | SMALLINT = java.lang.Integer 17 | MEDIUMINT = java.lang.Integer 18 | BIT = java.lang.Boolean 19 | BIGINT = java.math.BigInteger 20 | FLOAT = java.lang.Float 21 | DOUBLE = java.lang.Double 22 | DECIMAL = java.math.BigDecimal 23 | DATE = java.sql.Date 24 | TIME = java.sql.Time 25 | DATETIME = java.sql.Timestamp 26 | TIMESTAMP = java.sql.Timestamp 27 | YEAR = java.sql.Date 28 | } 29 | } 30 | 31 | dir { 32 | template = tempalate 33 | output = maliang 34 | } 35 | 36 | name { 37 | separator = "" 38 | table.prefix = "" 39 | column.prefix = "" 40 | } 41 | --------------------------------------------------------------------------------