├── .gitignore ├── JavaWebCodeGenerator ├── .gitignore ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── zju │ │ │ ├── CodeGenerator.java │ │ │ ├── FileGenerator.java │ │ │ ├── ShellRunner.java │ │ │ ├── meta │ │ │ ├── Configuration.java │ │ │ ├── FullyQualifiedJavaType.java │ │ │ ├── PrimitiveTypeWrapper.java │ │ │ └── TableColumn.java │ │ │ └── util │ │ │ ├── ConfigurationParser.java │ │ │ ├── JavaTypeResolver.java │ │ │ └── StringUtils.java │ ├── resources │ │ └── ftl │ │ │ ├── Dao.ftl │ │ │ ├── DaoImpl.ftl │ │ │ └── Meta.ftl │ └── webapp │ │ ├── WEB-INF │ │ └── web.xml │ │ └── index.jsp │ └── test │ ├── com │ └── zju │ │ ├── CodeGeneratorTest.java │ │ └── ConfigurationParserTest.java │ └── resources │ └── ftl │ ├── Dao.ftl │ ├── DaoImpl.ftl │ └── Meta.ftl ├── README.md └── TheGameOfLife ├── .gitignore ├── pom.xml └── src └── main ├── java └── com │ └── zju │ ├── Main.java │ ├── controller │ └── TheGameOfLifeController.java │ ├── meta │ ├── CellState.java │ └── CellularArray.java │ └── service │ └── TheGameOfLifeService.java ├── resources └── Spring │ └── spring-config.xml └── webapp ├── WEB-INF └── web.xml ├── index.css ├── index.html └── index.js /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | */.classpath 3 | */.project 4 | */.idea/ 5 | */*.iml 6 | */target/ 7 | */classes/ -------------------------------------------------------------------------------- /JavaWebCodeGenerator/.gitignore: -------------------------------------------------------------------------------- 1 | .classpath 2 | .project 3 | .idea/ 4 | *.iml 5 | target/ 6 | classes/ -------------------------------------------------------------------------------- /JavaWebCodeGenerator/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | com.zju 5 | JavaWebCodeGenerator 6 | war 7 | 1.0-SNAPSHOT 8 | JavaWebCodeGenerator Maven Webapp 9 | http://maven.apache.org 10 | 11 | 12 | 13 | org.springframework 14 | spring-framework-bom 15 | 4.3.2.RELEASE 16 | pom 17 | import 18 | 19 | 20 | 21 | 22 | 23 | org.springframework 24 | spring-core 25 | 26 | 27 | org.springframework 28 | spring-beans 29 | 30 | 31 | org.springframework 32 | spring-context 33 | 34 | 35 | mysql 36 | mysql-connector-java 37 | 5.1.38 38 | 39 | 40 | com.google.guava 41 | guava 42 | 18.0 43 | 44 | 45 | org.freemarker 46 | freemarker 47 | 2.3.23 48 | 49 | 50 | org.hsqldb 51 | hsqldb 52 | 2.3.4 53 | 54 | 55 | com.alibaba 56 | fastjson 57 | 1.2.7 58 | 59 | 60 | junit 61 | junit 62 | 4.12 63 | test 64 | 65 | 66 | 67 | JavaWebCodeGenerator 68 | 69 | 70 | -------------------------------------------------------------------------------- /JavaWebCodeGenerator/src/main/java/com/zju/CodeGenerator.java: -------------------------------------------------------------------------------- 1 | package com.zju; 2 | 3 | import com.google.common.collect.Lists; 4 | import com.zju.meta.Configuration; 5 | import com.zju.meta.TableColumn; 6 | import com.zju.util.JavaTypeResolver; 7 | import com.zju.util.StringUtils; 8 | import freemarker.template.TemplateException; 9 | 10 | import java.io.IOException; 11 | import java.sql.*; 12 | import java.util.List; 13 | 14 | /** 15 | * 代码生成器 16 | */ 17 | public class CodeGenerator { 18 | public static void generate(Configuration configuration) { 19 | System.out.println("开始连接数据库!"); 20 | // File file = new File(configuration.getClassPathEntry()); 21 | // if (!file.exists()) { 22 | // throw new RuntimeException("Class not found:"+file.getPath()); 23 | // } 24 | // URL url; 25 | // try { 26 | // url = file.toURI().toURL(); 27 | // } catch (MalformedURLException e) { 28 | // throw new RuntimeException("uri error"); 29 | // } 30 | // ClassLoader parent = Thread.currentThread().getContextClassLoader(); 31 | // URLClassLoader ucl = new URLClassLoader(new URL[]{url}, parent); 32 | Connection connection=null; 33 | ResultSet rs=null; 34 | DatabaseMetaData databaseMetaData=null; 35 | List columns= Lists.newArrayList(); 36 | TableColumn column; 37 | JavaTypeResolver javaTypeResolver=new JavaTypeResolver(); 38 | try { 39 | Class.forName(configuration.getDriverClass()); 40 | //获取数据库连接 41 | connection = DriverManager.getConnection(configuration.getConnectionURL(), configuration.getUserId(), configuration.getPassword()); 42 | databaseMetaData = connection.getMetaData(); 43 | //获取表结构信息 44 | rs = databaseMetaData.getColumns("", "", configuration.getTableName(), "%"); 45 | boolean supportsIsAutoIncrement = false; 46 | boolean supportsIsGeneratedColumn = false; 47 | ResultSetMetaData rsmd = rs.getMetaData(); 48 | int colCount = rsmd.getColumnCount(); 49 | for (int i = 1; i <= colCount; i++) { 50 | if ("IS_AUTOINCREMENT".equals(rsmd.getColumnName(i))) { 51 | supportsIsAutoIncrement = true; 52 | } 53 | if ("IS_GENERATEDCOLUMN".equals(rsmd.getColumnName(i))) { 54 | supportsIsGeneratedColumn = true; 55 | } 56 | } 57 | while (rs.next()) { 58 | column = new TableColumn(); 59 | column.setJdbcType(rs.getInt("DATA_TYPE")); 60 | column.setLength(rs.getInt("COLUMN_SIZE")); 61 | column.setActualColumnName(rs.getString("COLUMN_NAME")); 62 | column.setNullable(rs.getInt("NULLABLE") == DatabaseMetaData.columnNullable); 63 | column.setScale(rs.getInt("DECIMAL_DIGITS")); 64 | column.setRemarks(rs.getString("REMARKS")); 65 | column.setDefaultValue(rs.getString("COLUMN_DEF")); 66 | 67 | if (supportsIsAutoIncrement) { 68 | column.setIsAutoIncrement("YES".equals(rs.getString("IS_AUTOINCREMENT"))); 69 | } 70 | if (supportsIsGeneratedColumn) { 71 | column.setIsGeneratedColumn("YES".equals(rs.getString("IS_GENERATEDCOLUMN"))); 72 | } 73 | column.setJavaType(javaTypeResolver.get(column)); 74 | column.setJdbcTypeName(javaTypeResolver.calculateJdbcTypeName(column)); 75 | column.setJavaProperty(StringUtils.getCamelCaseString(column.getActualColumnName(), false)); 76 | columns.add(column); 77 | } 78 | } catch (ClassNotFoundException e) { 79 | e.printStackTrace(); 80 | } catch (SQLException e) { 81 | e.printStackTrace(); 82 | }finally { 83 | if(rs!=null){ 84 | try { 85 | rs.close(); 86 | } catch (SQLException e) { 87 | System.out.println("ResultSet 关闭失败"); 88 | } 89 | } 90 | if(connection!=null){ 91 | try { 92 | connection.close(); 93 | } catch (SQLException e) { 94 | System.out.println("Connection 关闭失败"); 95 | } 96 | } 97 | } 98 | System.out.println("数据表信息解析成功!"); 99 | try { 100 | FileGenerator.writeFile(configuration,columns);//写文件 101 | } catch (IOException e) { 102 | e.printStackTrace(); 103 | } catch (TemplateException e) { 104 | e.printStackTrace(); 105 | } 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /JavaWebCodeGenerator/src/main/java/com/zju/FileGenerator.java: -------------------------------------------------------------------------------- 1 | package com.zju; 2 | 3 | import com.alibaba.fastjson.JSON; 4 | import com.zju.meta.TableColumn; 5 | import freemarker.template.Configuration; 6 | import freemarker.template.Template; 7 | import freemarker.template.TemplateException; 8 | import freemarker.template.TemplateExceptionHandler; 9 | 10 | import java.io.File; 11 | import java.io.FileWriter; 12 | import java.io.IOException; 13 | import java.io.Writer; 14 | import java.util.HashMap; 15 | import java.util.List; 16 | import java.util.Map; 17 | 18 | /** 19 | * 文件生成器 20 | */ 21 | public class FileGenerator { 22 | 23 | private static String sf = "%s/%s/%s%s"; 24 | 25 | public static void writeFile(com.zju.meta.Configuration configuration, List columns) throws IOException, TemplateException { 26 | System.out.println("开始生成文件!"); 27 | File r=new File(""); 28 | //测试环境获取项目根目录路径 29 | //String path=Class.class.getClass().getResource("/").getPath(); 30 | //Jar包获取根目录路径 31 | String path=r.getAbsolutePath(); 32 | //System.out.println("path:"+path); 33 | Configuration cfg = new Configuration(); 34 | cfg.setDirectoryForTemplateLoading(new File(path + "/ftl")); //需要文件夹绝对路径 35 | cfg.setDefaultEncoding("UTF-8"); 36 | cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER); 37 | Map root = new HashMap(); 38 | root.put("configuration", configuration); 39 | root.put("columnList", columns); 40 | writeSingleFile(cfg, root, "DaoImpl.ftl", configuration.getProjectPath(), configuration.getSqlMappingPackage().replace(".", "/"), configuration.getDomainObjectName(), "DaoImpl.java",configuration.getOverwrite()); 41 | writeSingleFile(cfg, root, "Dao.ftl", configuration.getProjectPath(), configuration.getSqlMappingPackage().replace(".", "/"), configuration.getDomainObjectName(), "Dao.java",configuration.getOverwrite()); 42 | writeSingleFile(cfg, root, "Meta.ftl", configuration.getProjectPath(), configuration.getJavaModelPackage().replace(".", "/"), configuration.getDomainObjectName(), ".java",configuration.getOverwrite()); 43 | } 44 | 45 | public static boolean writeSingleFile(Configuration cfg, Map root, String template, String projectPath, String packagePath, String fileName, String suffix,Boolean overwrite) throws IOException, TemplateException { 46 | Template temp = cfg.getTemplate(template); 47 | File file = new File(String.format(sf, projectPath, packagePath, fileName, suffix)); 48 | if (!file.getParentFile().exists()) { 49 | if (!file.getParentFile().mkdirs()) { 50 | System.out.println("创建目标文件所在目录失败!"); 51 | return false; 52 | } 53 | } 54 | if(file.exists()){ 55 | if(!overwrite) { 56 | System.out.println(String.format("创建单个文件%s失败! 文件已存在", file.getPath())); 57 | return false; 58 | } 59 | }else { 60 | if (file.createNewFile()) { 61 | System.out.println(String.format("创建单个文件%s成功!", file.getPath())); 62 | } else { 63 | System.out.println(String.format("创建单个文件%s失败!", file.getPath())); 64 | return false; 65 | } 66 | } 67 | Writer out = null; 68 | try { 69 | out = new FileWriter(file); 70 | temp.process(root, out); 71 | out.flush(); 72 | System.out.println(String.format(sf+"完成.", projectPath, packagePath, fileName, suffix)); 73 | } catch (Exception e) { 74 | System.out.println(String.format("写入%s失败!", file.getPath())); 75 | } finally { 76 | if (out != null) { 77 | out.close(); 78 | } 79 | } 80 | return true; 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /JavaWebCodeGenerator/src/main/java/com/zju/ShellRunner.java: -------------------------------------------------------------------------------- 1 | package com.zju; 2 | 3 | import com.google.common.collect.Maps; 4 | import com.zju.meta.Configuration; 5 | import com.zju.util.ConfigurationParser; 6 | 7 | import java.io.File; 8 | import java.io.IOException; 9 | import java.util.Map; 10 | 11 | /** 12 | * 支持命令行运行项目 13 | */ 14 | public class ShellRunner { 15 | 16 | private static final String CONFIG_FILE = "-configfile"; //配置文件 17 | private static final String OVERWRITE="-overwrite"; //是否重写文件 18 | 19 | public static void main(String[] args) throws IOException { 20 | System.out.println("开始执行命令!"); 21 | boolean overwrite=false; 22 | if (args.length == 0) { 23 | System.out.println("args is empty"); 24 | System.exit(0); 25 | return; 26 | } 27 | //命令参数 28 | Map arguments = parseCommandLine(args); 29 | if (!arguments.containsKey(CONFIG_FILE)) { 30 | System.out.println("args do not contain configfile"); 31 | return; 32 | } 33 | if(arguments.containsKey(OVERWRITE)){ 34 | overwrite=true; 35 | } 36 | String configfile = arguments.get(CONFIG_FILE); 37 | File configurationFile = new File(configfile); 38 | if (!configurationFile.exists()) { 39 | System.out.println("configfile is not exist"); 40 | return; 41 | } 42 | Configuration configuration= ConfigurationParser.parseConfiguration(configurationFile,overwrite); 43 | System.out.println("配置文件解析成功!"); 44 | CodeGenerator.generate(configuration);//生成代码 45 | } 46 | 47 | private static Map parseCommandLine(String[] args) { 48 | Map arguments = Maps.newHashMap(); 49 | for (int i = 0; i < args.length; ++i) { 50 | if (CONFIG_FILE.equalsIgnoreCase(args[i])) { 51 | if ((i + 1) < args.length) { 52 | arguments.put(CONFIG_FILE, args[i + 1]); 53 | ++i; 54 | } else { 55 | System.out.println("args error"); 56 | System.exit(-1); 57 | } 58 | }else if(OVERWRITE.equalsIgnoreCase(args[i])){ 59 | arguments.put(OVERWRITE,""); 60 | } 61 | } 62 | return arguments; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /JavaWebCodeGenerator/src/main/java/com/zju/meta/Configuration.java: -------------------------------------------------------------------------------- 1 | package com.zju.meta; 2 | 3 | /** 4 | * 配置类 5 | */ 6 | public class Configuration { 7 | private String classPathEntry; 8 | private String driverClass; 9 | private String connectionURL; 10 | private String userId; 11 | private String password; 12 | private String javaModelPackage; 13 | private String sqlMappingPackage; 14 | private String projectPath; 15 | private String tableName; 16 | private String domainObjectName; 17 | private Boolean overwrite; 18 | 19 | public Configuration() { 20 | } 21 | 22 | public String getClassPathEntry() { 23 | return classPathEntry; 24 | } 25 | 26 | public void setClassPathEntry(String classPathEntry) { 27 | this.classPathEntry = classPathEntry; 28 | } 29 | 30 | public String getDriverClass() { 31 | return driverClass; 32 | } 33 | 34 | public void setDriverClass(String driverClass) { 35 | this.driverClass = driverClass; 36 | } 37 | 38 | public String getConnectionURL() { 39 | return connectionURL; 40 | } 41 | 42 | public void setConnectionURL(String connectionURL) { 43 | this.connectionURL = connectionURL; 44 | } 45 | 46 | public String getUserId() { 47 | return userId; 48 | } 49 | 50 | public void setUserId(String userId) { 51 | this.userId = userId; 52 | } 53 | 54 | public String getPassword() { 55 | return password; 56 | } 57 | 58 | public void setPassword(String password) { 59 | this.password = password; 60 | } 61 | 62 | public String getJavaModelPackage() { 63 | return javaModelPackage; 64 | } 65 | 66 | public void setJavaModelPackage(String javaModelPackage) { 67 | this.javaModelPackage = javaModelPackage; 68 | } 69 | 70 | public String getSqlMappingPackage() { 71 | return sqlMappingPackage; 72 | } 73 | 74 | public void setSqlMappingPackage(String sqlMappingPackage) { 75 | this.sqlMappingPackage = sqlMappingPackage; 76 | } 77 | 78 | public String getProjectPath() { 79 | return projectPath; 80 | } 81 | 82 | public void setProjectPath(String projectPath) { 83 | this.projectPath = projectPath; 84 | } 85 | 86 | public String getTableName() { 87 | return tableName; 88 | } 89 | 90 | public void setTableName(String tableName) { 91 | this.tableName = tableName; 92 | } 93 | 94 | public String getDomainObjectName() { 95 | return domainObjectName; 96 | } 97 | 98 | public void setDomainObjectName(String domainObjectName) { 99 | this.domainObjectName = domainObjectName; 100 | } 101 | 102 | public Boolean getOverwrite() { 103 | return overwrite; 104 | } 105 | 106 | public void setOverwrite(Boolean overwrite) { 107 | this.overwrite = overwrite; 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /JavaWebCodeGenerator/src/main/java/com/zju/meta/FullyQualifiedJavaType.java: -------------------------------------------------------------------------------- 1 | package com.zju.meta; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import java.util.StringTokenizer; 6 | 7 | public class FullyQualifiedJavaType implements 8 | Comparable { 9 | 10 | private static final String JAVA_LANG = "java.lang"; //$NON-NLS-1$ 11 | 12 | private String baseShortName; 13 | 14 | private String baseQualifiedName; 15 | 16 | private boolean explicitlyImported; 17 | 18 | private String packageName; 19 | 20 | private boolean primitive; 21 | 22 | private boolean isArray; 23 | 24 | private PrimitiveTypeWrapper primitiveTypeWrapper; 25 | 26 | private List typeArguments; 27 | 28 | private boolean wildcardType; 29 | 30 | private boolean boundedWildcard; 31 | 32 | private boolean extendsBoundedWildcard; 33 | 34 | public FullyQualifiedJavaType(String fullTypeSpecification) { 35 | super(); 36 | typeArguments = new ArrayList(); 37 | parse(fullTypeSpecification); 38 | } 39 | 40 | public boolean isExplicitlyImported() { 41 | return explicitlyImported; 42 | } 43 | 44 | public String getFullyQualifiedName() { 45 | StringBuilder sb = new StringBuilder(); 46 | if (wildcardType) { 47 | sb.append('?'); 48 | if (boundedWildcard) { 49 | if (extendsBoundedWildcard) { 50 | sb.append(" extends "); //$NON-NLS-1$ 51 | } else { 52 | sb.append(" super "); //$NON-NLS-1$ 53 | } 54 | 55 | sb.append(baseQualifiedName); 56 | } 57 | } else { 58 | sb.append(baseQualifiedName); 59 | } 60 | 61 | if (typeArguments.size() > 0) { 62 | boolean first = true; 63 | sb.append('<'); 64 | for (FullyQualifiedJavaType fqjt : typeArguments) { 65 | if (first) { 66 | first = false; 67 | } else { 68 | sb.append(", "); //$NON-NLS-1$ 69 | } 70 | sb.append(fqjt.getFullyQualifiedName()); 71 | 72 | } 73 | sb.append('>'); 74 | } 75 | 76 | return sb.toString(); 77 | } 78 | 79 | @Override 80 | public boolean equals(Object obj) { 81 | if (this == obj) { 82 | return true; 83 | } 84 | 85 | if (!(obj instanceof FullyQualifiedJavaType)) { 86 | return false; 87 | } 88 | 89 | FullyQualifiedJavaType other = (FullyQualifiedJavaType) obj; 90 | 91 | return getFullyQualifiedName().equals(other.getFullyQualifiedName()); 92 | } 93 | 94 | @Override 95 | public int hashCode() { 96 | return getFullyQualifiedName().hashCode(); 97 | } 98 | 99 | @Override 100 | public String toString() { 101 | return getFullyQualifiedName(); 102 | } 103 | 104 | public int compareTo(FullyQualifiedJavaType other) { 105 | return getFullyQualifiedName().compareTo(other.getFullyQualifiedName()); 106 | } 107 | 108 | 109 | private void parse(String fullTypeSpecification) { 110 | String spec = fullTypeSpecification.trim(); 111 | 112 | if (spec.startsWith("?")) { //$NON-NLS-1$ 113 | wildcardType = true; 114 | spec = spec.substring(1).trim(); 115 | if (spec.startsWith("extends ")) { //$NON-NLS-1$ 116 | boundedWildcard = true; 117 | extendsBoundedWildcard = true; 118 | spec = spec.substring(8); // "extends ".length() 119 | } else if (spec.startsWith("super ")) { //$NON-NLS-1$ 120 | boundedWildcard = true; 121 | extendsBoundedWildcard = false; 122 | spec = spec.substring(6); // "super ".length() 123 | } else { 124 | boundedWildcard = false; 125 | } 126 | parse(spec); 127 | } else { 128 | int index = fullTypeSpecification.indexOf('<'); 129 | if (index == -1) { 130 | simpleParse(fullTypeSpecification); 131 | } else { 132 | simpleParse(fullTypeSpecification.substring(0, index)); 133 | int endIndex = fullTypeSpecification.lastIndexOf('>'); 134 | if (endIndex == -1) { 135 | throw new RuntimeException(fullTypeSpecification); //$NON-NLS-1$ 136 | } 137 | genericParse(fullTypeSpecification.substring(index, endIndex + 1)); 138 | } 139 | 140 | // this is far from a perfect test for detecting arrays, but is close 141 | // enough for most cases. It will not detect an improperly specified 142 | // array type like byte], but it will detect byte[] and byte[ ] 143 | // which are both valid 144 | isArray = fullTypeSpecification.endsWith("]"); //$NON-NLS-1$ 145 | } 146 | } 147 | 148 | private void simpleParse(String typeSpecification) { 149 | baseQualifiedName = typeSpecification.trim(); 150 | if (baseQualifiedName.contains(".")) { //$NON-NLS-1$ 151 | packageName = getPackage(baseQualifiedName); 152 | baseShortName = baseQualifiedName 153 | .substring(packageName.length() + 1); 154 | int index = baseShortName.lastIndexOf('.'); 155 | if (index != -1) { 156 | baseShortName = baseShortName.substring(index + 1); 157 | } 158 | 159 | if (JAVA_LANG.equals(packageName)) { //$NON-NLS-1$ 160 | explicitlyImported = false; 161 | } else { 162 | explicitlyImported = true; 163 | } 164 | } else { 165 | baseShortName = baseQualifiedName; 166 | explicitlyImported = false; 167 | packageName = ""; //$NON-NLS-1$ 168 | 169 | if ("byte".equals(baseQualifiedName)) { //$NON-NLS-1$ 170 | primitive = true; 171 | primitiveTypeWrapper = PrimitiveTypeWrapper.getByteInstance(); 172 | } else if ("short".equals(baseQualifiedName)) { //$NON-NLS-1$ 173 | primitive = true; 174 | primitiveTypeWrapper = PrimitiveTypeWrapper.getShortInstance(); 175 | } else if ("int".equals(baseQualifiedName)) { //$NON-NLS-1$ 176 | primitive = true; 177 | primitiveTypeWrapper = PrimitiveTypeWrapper 178 | .getIntegerInstance(); 179 | } else if ("long".equals(baseQualifiedName)) { //$NON-NLS-1$ 180 | primitive = true; 181 | primitiveTypeWrapper = PrimitiveTypeWrapper.getLongInstance(); 182 | } else if ("char".equals(baseQualifiedName)) { //$NON-NLS-1$ 183 | primitive = true; 184 | primitiveTypeWrapper = PrimitiveTypeWrapper 185 | .getCharacterInstance(); 186 | } else if ("float".equals(baseQualifiedName)) { //$NON-NLS-1$ 187 | primitive = true; 188 | primitiveTypeWrapper = PrimitiveTypeWrapper.getFloatInstance(); 189 | } else if ("double".equals(baseQualifiedName)) { //$NON-NLS-1$ 190 | primitive = true; 191 | primitiveTypeWrapper = PrimitiveTypeWrapper.getDoubleInstance(); 192 | } else if ("boolean".equals(baseQualifiedName)) { //$NON-NLS-1$ 193 | primitive = true; 194 | primitiveTypeWrapper = PrimitiveTypeWrapper 195 | .getBooleanInstance(); 196 | } else { 197 | primitive = false; 198 | primitiveTypeWrapper = null; 199 | } 200 | } 201 | } 202 | 203 | private void genericParse(String genericSpecification) { 204 | int lastIndex = genericSpecification.lastIndexOf('>'); 205 | if (lastIndex == -1) { 206 | // shouldn't happen - should be caught already, but just in case... 207 | throw new RuntimeException(genericSpecification); //$NON-NLS-1$ 208 | } 209 | String argumentString = genericSpecification.substring(1, lastIndex); 210 | // need to find "," outside of a <> bounds 211 | StringTokenizer st = new StringTokenizer(argumentString, ",<>", true); //$NON-NLS-1$ 212 | int openCount = 0; 213 | StringBuilder sb = new StringBuilder(); 214 | while (st.hasMoreTokens()) { 215 | String token = st.nextToken(); 216 | if ("<".equals(token)) { //$NON-NLS-1$ 217 | sb.append(token); 218 | openCount++; 219 | } else if (">".equals(token)) { //$NON-NLS-1$ 220 | sb.append(token); 221 | openCount--; 222 | } else if (",".equals(token)) { //$NON-NLS-1$ 223 | if (openCount == 0) { 224 | typeArguments 225 | .add(new FullyQualifiedJavaType(sb.toString())); 226 | sb.setLength(0); 227 | } else { 228 | sb.append(token); 229 | } 230 | } else { 231 | sb.append(token); 232 | } 233 | } 234 | 235 | if (openCount != 0) { 236 | throw new RuntimeException(genericSpecification); //$NON-NLS-1$ 237 | } 238 | 239 | String finalType = sb.toString(); 240 | if (!finalType.isEmpty()) { 241 | typeArguments.add(new FullyQualifiedJavaType(finalType)); 242 | } 243 | } 244 | 245 | private static String getPackage(String baseQualifiedName) { 246 | int index = baseQualifiedName.lastIndexOf('.'); 247 | return baseQualifiedName.substring(0, index); 248 | } 249 | 250 | 251 | public String getBaseShortName() { 252 | return baseShortName; 253 | } 254 | 255 | public void setBaseShortName(String baseShortName) { 256 | this.baseShortName = baseShortName; 257 | } 258 | } 259 | -------------------------------------------------------------------------------- /JavaWebCodeGenerator/src/main/java/com/zju/meta/PrimitiveTypeWrapper.java: -------------------------------------------------------------------------------- 1 | package com.zju.meta; 2 | 3 | public class PrimitiveTypeWrapper extends FullyQualifiedJavaType { 4 | private static PrimitiveTypeWrapper booleanInstance; 5 | private static PrimitiveTypeWrapper byteInstance; 6 | private static PrimitiveTypeWrapper characterInstance; 7 | private static PrimitiveTypeWrapper doubleInstance; 8 | private static PrimitiveTypeWrapper floatInstance; 9 | private static PrimitiveTypeWrapper integerInstance; 10 | private static PrimitiveTypeWrapper longInstance; 11 | private static PrimitiveTypeWrapper shortInstance; 12 | 13 | private String toPrimitiveMethod; 14 | 15 | private PrimitiveTypeWrapper(String fullyQualifiedName, 16 | String toPrimitiveMethod) { 17 | super(fullyQualifiedName); 18 | this.toPrimitiveMethod = toPrimitiveMethod; 19 | } 20 | 21 | public static PrimitiveTypeWrapper getBooleanInstance() { 22 | if (booleanInstance == null) { 23 | booleanInstance = new PrimitiveTypeWrapper("java.lang.Boolean", //$NON-NLS-1$ 24 | "booleanValue()"); //$NON-NLS-1$ 25 | } 26 | 27 | return booleanInstance; 28 | } 29 | 30 | public static PrimitiveTypeWrapper getByteInstance() { 31 | if (byteInstance == null) { 32 | byteInstance = new PrimitiveTypeWrapper("java.lang.Byte", //$NON-NLS-1$ 33 | "byteValue()"); //$NON-NLS-1$ 34 | } 35 | 36 | return byteInstance; 37 | } 38 | 39 | public static PrimitiveTypeWrapper getCharacterInstance() { 40 | if (characterInstance == null) { 41 | characterInstance = new PrimitiveTypeWrapper("java.lang.Character", //$NON-NLS-1$ 42 | "charValue()"); //$NON-NLS-1$ 43 | } 44 | 45 | return characterInstance; 46 | } 47 | 48 | public static PrimitiveTypeWrapper getDoubleInstance() { 49 | if (doubleInstance == null) { 50 | doubleInstance = new PrimitiveTypeWrapper("java.lang.Double", //$NON-NLS-1$ 51 | "doubleValue()"); //$NON-NLS-1$ 52 | } 53 | 54 | return doubleInstance; 55 | } 56 | 57 | public static PrimitiveTypeWrapper getFloatInstance() { 58 | if (floatInstance == null) { 59 | floatInstance = new PrimitiveTypeWrapper("java.lang.Float", //$NON-NLS-1$ 60 | "floatValue()"); //$NON-NLS-1$ 61 | } 62 | 63 | return floatInstance; 64 | } 65 | 66 | public static PrimitiveTypeWrapper getIntegerInstance() { 67 | if (integerInstance == null) { 68 | integerInstance = new PrimitiveTypeWrapper("java.lang.Integer", //$NON-NLS-1$ 69 | "intValue()"); //$NON-NLS-1$ 70 | } 71 | 72 | return integerInstance; 73 | } 74 | 75 | public static PrimitiveTypeWrapper getLongInstance() { 76 | if (longInstance == null) { 77 | longInstance = new PrimitiveTypeWrapper("java.lang.Long", //$NON-NLS-1$ 78 | "longValue()"); //$NON-NLS-1$ 79 | } 80 | 81 | return longInstance; 82 | } 83 | 84 | public static PrimitiveTypeWrapper getShortInstance() { 85 | if (shortInstance == null) { 86 | shortInstance = new PrimitiveTypeWrapper("java.lang.Short", //$NON-NLS-1$ 87 | "shortValue()"); //$NON-NLS-1$ 88 | } 89 | 90 | return shortInstance; 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /JavaWebCodeGenerator/src/main/java/com/zju/meta/TableColumn.java: -------------------------------------------------------------------------------- 1 | package com.zju.meta; 2 | 3 | import java.util.Properties; 4 | 5 | /** 6 | * 数据表列 7 | */ 8 | public class TableColumn { 9 | protected String actualColumnName; 10 | 11 | protected int jdbcType; 12 | 13 | protected String jdbcTypeName; 14 | 15 | protected boolean nullable; 16 | 17 | protected int length; 18 | 19 | protected int scale; 20 | 21 | protected boolean identity; 22 | 23 | protected boolean isSequenceColumn; 24 | 25 | protected String javaProperty; 26 | 27 | 28 | protected String tableAlias; 29 | 30 | protected String typeHandler; 31 | 32 | 33 | protected boolean isColumnNameDelimited; 34 | 35 | protected Properties properties; 36 | 37 | protected FullyQualifiedJavaType javaType; 38 | 39 | // any database comment associated with this column. May be null 40 | protected String remarks; 41 | 42 | protected String defaultValue; 43 | 44 | /** 45 | * true if the JDBC driver reports that this column is auto-increment 46 | */ 47 | protected boolean isAutoIncrement; 48 | 49 | /** 50 | * true if the JDBC driver reports that this column is generated 51 | */ 52 | protected boolean isGeneratedColumn; 53 | 54 | /** 55 | * True if there is a column override that defines this column as GENERATED ALWAYS 56 | */ 57 | protected boolean isGeneratedAlways; 58 | 59 | public String getActualColumnName() { 60 | return actualColumnName; 61 | } 62 | 63 | public void setActualColumnName(String actualColumnName) { 64 | this.actualColumnName = actualColumnName; 65 | } 66 | 67 | public int getJdbcType() { 68 | return jdbcType; 69 | } 70 | 71 | public void setJdbcType(int jdbcType) { 72 | this.jdbcType = jdbcType; 73 | } 74 | 75 | public String getJdbcTypeName() { 76 | return jdbcTypeName; 77 | } 78 | 79 | public void setJdbcTypeName(String jdbcTypeName) { 80 | this.jdbcTypeName = jdbcTypeName; 81 | } 82 | 83 | public boolean isNullable() { 84 | return nullable; 85 | } 86 | 87 | public void setNullable(boolean nullable) { 88 | this.nullable = nullable; 89 | } 90 | 91 | public int getLength() { 92 | return length; 93 | } 94 | 95 | public void setLength(int length) { 96 | this.length = length; 97 | } 98 | 99 | public int getScale() { 100 | return scale; 101 | } 102 | 103 | public void setScale(int scale) { 104 | this.scale = scale; 105 | } 106 | 107 | 108 | 109 | public String getTableAlias() { 110 | return tableAlias; 111 | } 112 | 113 | public void setTableAlias(String tableAlias) { 114 | this.tableAlias = tableAlias; 115 | } 116 | 117 | public String getRemarks() { 118 | return remarks; 119 | } 120 | 121 | public void setRemarks(String remarks) { 122 | this.remarks = remarks; 123 | } 124 | 125 | public String getDefaultValue() { 126 | return defaultValue; 127 | } 128 | 129 | public void setDefaultValue(String defaultValue) { 130 | this.defaultValue = defaultValue; 131 | } 132 | 133 | public boolean isAutoIncrement() { 134 | return isAutoIncrement; 135 | } 136 | 137 | public void setIsAutoIncrement(boolean isAutoIncrement) { 138 | this.isAutoIncrement = isAutoIncrement; 139 | } 140 | 141 | public boolean isGeneratedColumn() { 142 | return isGeneratedColumn; 143 | } 144 | 145 | public void setIsGeneratedColumn(boolean isGeneratedColumn) { 146 | this.isGeneratedColumn = isGeneratedColumn; 147 | } 148 | 149 | public boolean isIdentity() { 150 | return identity; 151 | } 152 | 153 | public void setIdentity(boolean identity) { 154 | this.identity = identity; 155 | } 156 | 157 | public boolean isSequenceColumn() { 158 | return isSequenceColumn; 159 | } 160 | 161 | public void setIsSequenceColumn(boolean isSequenceColumn) { 162 | this.isSequenceColumn = isSequenceColumn; 163 | } 164 | 165 | public String getJavaProperty() { 166 | return javaProperty; 167 | } 168 | 169 | public void setJavaProperty(String javaProperty) { 170 | this.javaProperty = javaProperty; 171 | } 172 | 173 | public String getTypeHandler() { 174 | return typeHandler; 175 | } 176 | 177 | public void setTypeHandler(String typeHandler) { 178 | this.typeHandler = typeHandler; 179 | } 180 | 181 | public boolean isColumnNameDelimited() { 182 | return isColumnNameDelimited; 183 | } 184 | 185 | public void setIsColumnNameDelimited(boolean isColumnNameDelimited) { 186 | this.isColumnNameDelimited = isColumnNameDelimited; 187 | } 188 | 189 | public Properties getProperties() { 190 | return properties; 191 | } 192 | 193 | public void setProperties(Properties properties) { 194 | this.properties = properties; 195 | } 196 | 197 | public boolean isGeneratedAlways() { 198 | return isGeneratedAlways; 199 | } 200 | 201 | public void setIsGeneratedAlways(boolean isGeneratedAlways) { 202 | this.isGeneratedAlways = isGeneratedAlways; 203 | } 204 | 205 | public FullyQualifiedJavaType getJavaType() { 206 | return javaType; 207 | } 208 | 209 | public void setJavaType(FullyQualifiedJavaType javaType) { 210 | this.javaType = javaType; 211 | } 212 | } 213 | -------------------------------------------------------------------------------- /JavaWebCodeGenerator/src/main/java/com/zju/util/ConfigurationParser.java: -------------------------------------------------------------------------------- 1 | package com.zju.util; 2 | 3 | import com.zju.meta.Configuration; 4 | 5 | import java.io.File; 6 | import java.io.FileReader; 7 | import java.io.IOException; 8 | import java.util.Properties; 9 | 10 | /** 11 | * 解析配置文件 12 | */ 13 | public class ConfigurationParser { 14 | 15 | private static final String CLASS_PATH_ENTRY = "class.path.entry"; 16 | private static final String DRIVER_CLASS = "driver.class"; 17 | private static final String CONNECTION_URL = "connection.url"; 18 | private static final String USER_ID = "user.id"; 19 | private static final String USER_PASSWORD = "user.password"; 20 | private static final String JAVA_MODEL_PACKAGE = "java.model.package"; 21 | private static final String SQL_MAPPING_PACKAGE = "sql.mapping.package"; 22 | private static final String PROJECT = "project"; 23 | private static final String TABLE_NAME = "table.name"; 24 | private static final String DOMAIN_OBJECT_NAME = "domain.object.name"; 25 | 26 | /** 27 | * 配置文件解析 28 | * @param inputFile 配置文件 29 | * @param overwrite 是否重写参数 30 | * @return 31 | * @throws IOException 32 | */ 33 | public static Configuration parseConfiguration(File inputFile,Boolean overwrite) throws IOException { 34 | FileReader fr = new FileReader(inputFile); 35 | Properties prop = new Properties(); 36 | prop.load(fr); 37 | Configuration config = new Configuration(); 38 | for (Object key : prop.keySet()) { 39 | if (CLASS_PATH_ENTRY.equalsIgnoreCase(key.toString())) { 40 | config.setClassPathEntry(prop.get(key).toString()); 41 | } else if (DRIVER_CLASS.equalsIgnoreCase(key.toString())) { 42 | config.setDriverClass(prop.get(key).toString()); 43 | } else if (CONNECTION_URL.equalsIgnoreCase(key.toString())) { 44 | config.setConnectionURL(prop.get(key).toString()); 45 | } else if (USER_ID.equalsIgnoreCase(key.toString())) { 46 | config.setUserId(prop.get(key).toString()); 47 | } else if (USER_PASSWORD.equalsIgnoreCase(key.toString())) { 48 | config.setPassword(prop.get(key).toString()); 49 | } else if (JAVA_MODEL_PACKAGE.equalsIgnoreCase(key.toString())) { 50 | config.setJavaModelPackage(prop.get(key).toString()); 51 | } else if (SQL_MAPPING_PACKAGE.equalsIgnoreCase(key.toString())) { 52 | config.setSqlMappingPackage(prop.get(key).toString()); 53 | } else if (PROJECT.equalsIgnoreCase(key.toString())) { 54 | config.setProjectPath(prop.get(key).toString()); 55 | } else if (TABLE_NAME.equalsIgnoreCase(key.toString())) { 56 | config.setTableName(prop.get(key).toString()); 57 | } else if (DOMAIN_OBJECT_NAME.equalsIgnoreCase(key.toString())) { 58 | config.setDomainObjectName(prop.get(key).toString()); 59 | } 60 | } 61 | config.setOverwrite(overwrite); 62 | return config; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /JavaWebCodeGenerator/src/main/java/com/zju/util/JavaTypeResolver.java: -------------------------------------------------------------------------------- 1 | package com.zju.util; 2 | 3 | import com.zju.meta.TableColumn; 4 | import com.zju.meta.FullyQualifiedJavaType; 5 | 6 | import java.math.BigDecimal; 7 | import java.sql.Types; 8 | import java.util.Date; 9 | import java.util.HashMap; 10 | import java.util.Map; 11 | 12 | /** 13 | * 计算Java类型 14 | */ 15 | public class JavaTypeResolver { 16 | protected Map typeMap; 17 | 18 | public JavaTypeResolver() { 19 | typeMap = new HashMap(); 20 | 21 | typeMap.put(Types.ARRAY, new JdbcTypeInformation("ARRAY", 22 | new FullyQualifiedJavaType(Object.class.getName()))); 23 | typeMap.put(Types.BIGINT, new JdbcTypeInformation("BIGINT", 24 | new FullyQualifiedJavaType(Long.class.getName()))); 25 | typeMap.put(Types.BINARY, new JdbcTypeInformation("BINARY", 26 | new FullyQualifiedJavaType("byte[]"))); 27 | typeMap.put(Types.BIT, new JdbcTypeInformation("BIT", 28 | new FullyQualifiedJavaType(Boolean.class.getName()))); 29 | typeMap.put(Types.BLOB, new JdbcTypeInformation("BLOB", 30 | new FullyQualifiedJavaType("byte[]"))); 31 | typeMap.put(Types.BOOLEAN, new JdbcTypeInformation("BOOLEAN", 32 | new FullyQualifiedJavaType(Boolean.class.getName()))); 33 | typeMap.put(Types.CHAR, new JdbcTypeInformation("CHAR", 34 | new FullyQualifiedJavaType(String.class.getName()))); 35 | typeMap.put(Types.CLOB, new JdbcTypeInformation("CLOB", 36 | new FullyQualifiedJavaType(String.class.getName()))); 37 | typeMap.put(Types.DATALINK, new JdbcTypeInformation("DATALINK", 38 | new FullyQualifiedJavaType(Object.class.getName()))); 39 | typeMap.put(Types.DATE, new JdbcTypeInformation("DATE", 40 | new FullyQualifiedJavaType(Date.class.getName()))); 41 | typeMap.put(Types.DECIMAL, new JdbcTypeInformation("DECIMAL", 42 | new FullyQualifiedJavaType(BigDecimal.class.getName()))); 43 | typeMap.put(Types.DISTINCT, new JdbcTypeInformation("DISTINCT", 44 | new FullyQualifiedJavaType(Object.class.getName()))); 45 | typeMap.put(Types.DOUBLE, new JdbcTypeInformation("DOUBLE", 46 | new FullyQualifiedJavaType(Double.class.getName()))); 47 | typeMap.put(Types.FLOAT, new JdbcTypeInformation("FLOAT", 48 | new FullyQualifiedJavaType(Double.class.getName()))); 49 | typeMap.put(Types.INTEGER, new JdbcTypeInformation("INTEGER", 50 | new FullyQualifiedJavaType(Integer.class.getName()))); 51 | typeMap.put(Types.JAVA_OBJECT, new JdbcTypeInformation("JAVA_OBJECT", 52 | new FullyQualifiedJavaType(Object.class.getName()))); 53 | typeMap.put(Types.LONGNVARCHAR, new JdbcTypeInformation("LONGNVARCHAR", 54 | new FullyQualifiedJavaType(String.class.getName()))); 55 | typeMap.put(Types.LONGVARBINARY, new JdbcTypeInformation( 56 | "LONGVARBINARY", 57 | new FullyQualifiedJavaType("byte[]"))); 58 | typeMap.put(Types.LONGVARCHAR, new JdbcTypeInformation("LONGVARCHAR", 59 | new FullyQualifiedJavaType(String.class.getName()))); 60 | typeMap.put(Types.NCHAR, new JdbcTypeInformation("NCHAR", 61 | new FullyQualifiedJavaType(String.class.getName()))); 62 | typeMap.put(Types.NCLOB, new JdbcTypeInformation("NCLOB", 63 | new FullyQualifiedJavaType(String.class.getName()))); 64 | typeMap.put(Types.NVARCHAR, new JdbcTypeInformation("NVARCHAR", 65 | new FullyQualifiedJavaType(String.class.getName()))); 66 | typeMap.put(Types.NULL, new JdbcTypeInformation("NULL", 67 | new FullyQualifiedJavaType(Object.class.getName()))); 68 | typeMap.put(Types.NUMERIC, new JdbcTypeInformation("NUMERIC", 69 | new FullyQualifiedJavaType(BigDecimal.class.getName()))); 70 | typeMap.put(Types.OTHER, new JdbcTypeInformation("OTHER", 71 | new FullyQualifiedJavaType(Object.class.getName()))); 72 | typeMap.put(Types.REAL, new JdbcTypeInformation("REAL", 73 | new FullyQualifiedJavaType(Float.class.getName()))); 74 | typeMap.put(Types.REF, new JdbcTypeInformation("REF", 75 | new FullyQualifiedJavaType(Object.class.getName()))); 76 | typeMap.put(Types.SMALLINT, new JdbcTypeInformation("SMALLINT", 77 | new FullyQualifiedJavaType(Short.class.getName()))); 78 | typeMap.put(Types.STRUCT, new JdbcTypeInformation("STRUCT", 79 | new FullyQualifiedJavaType(Object.class.getName()))); 80 | typeMap.put(Types.TIME, new JdbcTypeInformation("TIME", 81 | new FullyQualifiedJavaType(Date.class.getName()))); 82 | typeMap.put(Types.TIMESTAMP, new JdbcTypeInformation("TIMESTAMP", 83 | new FullyQualifiedJavaType(Date.class.getName()))); 84 | typeMap.put(Types.TINYINT, new JdbcTypeInformation("TINYINT", 85 | new FullyQualifiedJavaType(Byte.class.getName()))); 86 | typeMap.put(Types.VARBINARY, new JdbcTypeInformation("VARBINARY", 87 | new FullyQualifiedJavaType("byte[]"))); 88 | typeMap.put(Types.VARCHAR, new JdbcTypeInformation("VARCHAR", 89 | new FullyQualifiedJavaType(String.class.getName()))); 90 | } 91 | 92 | public static class JdbcTypeInformation { 93 | private String jdbcTypeName; 94 | 95 | private FullyQualifiedJavaType fullyQualifiedJavaType; 96 | 97 | public JdbcTypeInformation(String jdbcTypeName, 98 | FullyQualifiedJavaType fullyQualifiedJavaType) { 99 | this.jdbcTypeName = jdbcTypeName; 100 | this.fullyQualifiedJavaType = fullyQualifiedJavaType; 101 | } 102 | 103 | public String getJdbcTypeName() { 104 | return jdbcTypeName; 105 | } 106 | 107 | public FullyQualifiedJavaType getFullyQualifiedJavaType() { 108 | return fullyQualifiedJavaType; 109 | } 110 | } 111 | 112 | protected FullyQualifiedJavaType overrideDefaultType(TableColumn column, FullyQualifiedJavaType defaultType) { 113 | FullyQualifiedJavaType answer = defaultType; 114 | 115 | switch (column.getJdbcType()) { 116 | case Types.BIT: 117 | answer = calculateBitReplacement(column, defaultType); 118 | break; 119 | case Types.DECIMAL: 120 | case Types.NUMERIC: 121 | answer = calculateBigDecimalReplacement(column, defaultType); 122 | break; 123 | } 124 | 125 | return answer; 126 | } 127 | 128 | protected FullyQualifiedJavaType calculateBitReplacement(TableColumn column, FullyQualifiedJavaType defaultType) { 129 | FullyQualifiedJavaType answer; 130 | 131 | if (column.getLength() > 1) { 132 | answer = new FullyQualifiedJavaType("byte[]"); //$NON-NLS-1$ 133 | } else { 134 | answer = defaultType; 135 | } 136 | 137 | return answer; 138 | } 139 | 140 | protected FullyQualifiedJavaType calculateBigDecimalReplacement(TableColumn column, FullyQualifiedJavaType defaultType) { 141 | FullyQualifiedJavaType answer; 142 | 143 | if (column.getScale() > 0 || column.getLength() > 18) { 144 | answer = defaultType; 145 | } else if (column.getLength() > 9) { 146 | answer = new FullyQualifiedJavaType(Long.class.getName()); 147 | } else if (column.getLength() > 4) { 148 | answer = new FullyQualifiedJavaType(Integer.class.getName()); 149 | } else { 150 | answer = new FullyQualifiedJavaType(Short.class.getName()); 151 | } 152 | 153 | return answer; 154 | } 155 | 156 | public FullyQualifiedJavaType get(TableColumn column) { 157 | FullyQualifiedJavaType answer = null; 158 | JdbcTypeInformation jdbcTypeInformation = typeMap 159 | .get(column.getJdbcType()); 160 | 161 | if (jdbcTypeInformation != null) { 162 | answer = jdbcTypeInformation.getFullyQualifiedJavaType(); 163 | answer = overrideDefaultType(column, answer); 164 | } 165 | return answer; 166 | } 167 | 168 | public String calculateJdbcTypeName(TableColumn introspectedColumn) { 169 | String answer = null; 170 | JdbcTypeInformation jdbcTypeInformation = typeMap 171 | .get(introspectedColumn.getJdbcType()); 172 | 173 | if (jdbcTypeInformation != null) { 174 | answer = jdbcTypeInformation.getJdbcTypeName(); 175 | } 176 | 177 | return answer; 178 | } 179 | } 180 | -------------------------------------------------------------------------------- /JavaWebCodeGenerator/src/main/java/com/zju/util/StringUtils.java: -------------------------------------------------------------------------------- 1 | package com.zju.util; 2 | 3 | /** 4 | * 字符串处理 5 | */ 6 | public class StringUtils { 7 | public static String getCamelCaseString(String inputString, 8 | boolean firstCharacterUppercase) { 9 | StringBuilder sb = new StringBuilder(); 10 | 11 | boolean nextUpperCase = false; 12 | for (int i = 0; i < inputString.length(); i++) { 13 | char c = inputString.charAt(i); 14 | 15 | switch (c) { 16 | case '_': 17 | case '-': 18 | case '@': 19 | case '$': 20 | case '#': 21 | case ' ': 22 | case '/': 23 | case '&': 24 | if (sb.length() > 0) { 25 | nextUpperCase = true; 26 | } 27 | break; 28 | 29 | default: 30 | if (nextUpperCase) { 31 | sb.append(Character.toUpperCase(c)); 32 | nextUpperCase = false; 33 | } else { 34 | sb.append(Character.toLowerCase(c)); 35 | } 36 | break; 37 | } 38 | } 39 | 40 | if (firstCharacterUppercase) { 41 | sb.setCharAt(0, Character.toUpperCase(sb.charAt(0))); 42 | } 43 | 44 | return sb.toString(); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /JavaWebCodeGenerator/src/main/resources/ftl/Dao.ftl: -------------------------------------------------------------------------------- 1 | public interface ${configuration.domainObjectName}Dao { 2 | 3 | boolean add(${configuration.domainObjectName} obj); 4 | 5 | ${configuration.domainObjectName} getById(long id); 6 | 7 | } -------------------------------------------------------------------------------- /JavaWebCodeGenerator/src/main/resources/ftl/DaoImpl.ftl: -------------------------------------------------------------------------------- 1 | public class ${configuration.domainObjectName}DaoImpl implements ${configuration.domainObjectName}Dao{ 2 | 3 | @Override 4 | public boolean add(${configuration.domainObjectName} obj) { 5 | long id = this.allocateRecordId(); 6 | if (id < 1) { 7 | return false; 8 | } 9 | String sql = "insert into ${configuration.tableName}("+ 10 | "<#list columnList as column><#if 0,${column.actualColumnName}"+ 11 | ") values ( <#list columnList as column><#if 0,? ) "; 12 | List params = new ArrayList(); 13 | <#list columnList as column> 14 | params.add(obj.get${column.javaProperty?cap_first}()); 15 | 16 | return getSqlSupport().addRecord(sql, params); 17 | } 18 | 19 | @Override 20 | public ${configuration.domainObjectName} getById(long id) { 21 | String sql = "select * from ${configuration.tableName} where id = ?"; 22 | return queryObject(sql, id); 23 | } 24 | 25 | @Override 26 | public ${configuration.domainObjectName} getObjectFromRs(ResultSet rs) throws SQLException { 27 | ${configuration.domainObjectName} obj=new ${configuration.domainObjectName}(); 28 | <#list columnList as column> 29 | obj.set${column.javaProperty?cap_first}(rs.get${column.javaType.baseShortName?cap_first}("${column.actualColumnName}")); 30 | 31 | return obj; 32 | } 33 | } -------------------------------------------------------------------------------- /JavaWebCodeGenerator/src/main/resources/ftl/Meta.ftl: -------------------------------------------------------------------------------- 1 | public class ${configuration.domainObjectName}{ 2 | 3 | <#list columnList as column> 4 | //${column.remarks} 5 | private ${column.javaType.baseShortName?cap_first} ${column.javaProperty}; 6 | 7 | 8 | <#list columnList as column> 9 | public ${column.javaType.baseShortName?cap_first} get${column.javaProperty?cap_first}() { 10 | return this.${column.javaProperty}; 11 | } 12 | public void set${column.javaProperty?cap_first}(${column.javaType.baseShortName?cap_first} ${column.javaProperty}) { 13 | this.${column.javaProperty} = ${column.javaProperty}; 14 | } 15 | 16 | 17 | 18 | } 19 | -------------------------------------------------------------------------------- /JavaWebCodeGenerator/src/main/webapp/WEB-INF/web.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | Archetype Created Web Application 7 | 8 | -------------------------------------------------------------------------------- /JavaWebCodeGenerator/src/main/webapp/index.jsp: -------------------------------------------------------------------------------- 1 | 2 | 3 |

Hello World!

4 | 5 | 6 | -------------------------------------------------------------------------------- /JavaWebCodeGenerator/src/test/com/zju/CodeGeneratorTest.java: -------------------------------------------------------------------------------- 1 | package com.zju; 2 | 3 | import com.zju.meta.Configuration; 4 | import com.zju.util.ConfigurationParser; 5 | import org.junit.Test; 6 | 7 | import java.io.File; 8 | 9 | /** 10 | * 代码生成 测试类 11 | */ 12 | public class CodeGeneratorTest { 13 | 14 | @Test 15 | public void testGenerate() throws Exception { 16 | File file=new File("src/test/resources/generatorConfig.properties"); 17 | Configuration configuration= ConfigurationParser.parseConfiguration(file,true); 18 | System.out.println(configuration); 19 | CodeGenerator.generate(configuration); 20 | } 21 | } -------------------------------------------------------------------------------- /JavaWebCodeGenerator/src/test/com/zju/ConfigurationParserTest.java: -------------------------------------------------------------------------------- 1 | package com.zju; 2 | 3 | import com.zju.meta.Configuration; 4 | import com.zju.util.ConfigurationParser; 5 | import org.junit.Test; 6 | 7 | import java.io.File; 8 | 9 | /** 10 | * 配置解析 测试类 11 | */ 12 | public class ConfigurationParserTest { 13 | 14 | @Test 15 | public void testParseConfiguration() throws Exception { 16 | File file=new File("src/test/resources/generatorConfig.properties"); 17 | Configuration configuration= ConfigurationParser.parseConfiguration(file,true); 18 | System.out.println(configuration); 19 | } 20 | } -------------------------------------------------------------------------------- /JavaWebCodeGenerator/src/test/resources/ftl/Dao.ftl: -------------------------------------------------------------------------------- 1 | public interface ${configuration.domainObjectName}Dao { 2 | 3 | boolean add(${configuration.domainObjectName} obj); 4 | 5 | ${configuration.domainObjectName} getById(long id); 6 | 7 | } -------------------------------------------------------------------------------- /JavaWebCodeGenerator/src/test/resources/ftl/DaoImpl.ftl: -------------------------------------------------------------------------------- 1 | public class ${configuration.domainObjectName}DaoImpl implements ${configuration.domainObjectName}Dao{ 2 | 3 | @Override 4 | public boolean add(${configuration.domainObjectName} obj) { 5 | long id = this.allocateRecordId(); 6 | if (id < 1) { 7 | return false; 8 | } 9 | String sql = "insert into ${configuration.tableName}("+ 10 | "<#list columnList as column><#if 0,${column.actualColumnName}"+ 11 | ") values ( <#list columnList as column><#if 0,? ) "; 12 | List params = new ArrayList(); 13 | <#list columnList as column> 14 | params.add(obj.get${column.javaProperty?cap_first}()); 15 | 16 | return getSqlSupport().addRecord(sql, params); 17 | } 18 | 19 | @Override 20 | public ${configuration.domainObjectName} getById(long id) { 21 | String sql = "select * from ${configuration.tableName} where id = ?"; 22 | return queryObject(sql, id); 23 | } 24 | 25 | @Override 26 | public ${configuration.domainObjectName} getObjectFromRs(ResultSet rs) throws SQLException { 27 | ${configuration.domainObjectName} obj=new ${configuration.domainObjectName}(); 28 | <#list columnList as column> 29 | obj.set${column.javaProperty?cap_first}(rs.get${column.javaType.baseShortName?cap_first}("${column.actualColumnName}")); 30 | 31 | return obj; 32 | } 33 | } -------------------------------------------------------------------------------- /JavaWebCodeGenerator/src/test/resources/ftl/Meta.ftl: -------------------------------------------------------------------------------- 1 | public class ${configuration.domainObjectName}{ 2 | 3 | <#list columnList as column> 4 | //${column.remarks} 5 | private ${column.javaType.baseShortName?cap_first} ${column.javaProperty}; 6 | 7 | 8 | <#list columnList as column> 9 | public ${column.javaType.baseShortName?cap_first} get${column.javaProperty?cap_first}() { 10 | return this.${column.javaProperty}; 11 | } 12 | public void set${column.javaProperty?cap_first}(${column.javaType.baseShortName?cap_first} ${column.javaProperty}) { 13 | this.${column.javaProperty} = ${column.javaProperty}; 14 | } 15 | 16 | 17 | 18 | } 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 练习场 2 | 想做的,有趣的,好玩的 3 | 4 | 1. TheGameOfLife 可视化生命游戏 5 | 2. JavaWebCodeGenerator 简单的MySQL代码生成器 -------------------------------------------------------------------------------- /TheGameOfLife/.gitignore: -------------------------------------------------------------------------------- 1 | .classpath 2 | .project 3 | .idea/ 4 | *.iml 5 | target/ -------------------------------------------------------------------------------- /TheGameOfLife/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | com.zju 5 | TheGameOfLife 6 | war 7 | 1.0-SNAPSHOT 8 | TheGameOfLife Maven Webapp 9 | http://maven.apache.org 10 | 11 | 4.3.2.RELEASE 12 | 13 | 14 | 15 | junit 16 | junit 17 | 3.8.1 18 | test 19 | 20 | 21 | org.springframework 22 | spring-context 23 | ${spring.version} 24 | 25 | 26 | org.springframework 27 | spring-core 28 | ${spring.version} 29 | 30 | 31 | org.springframework 32 | spring-beans 33 | ${spring.version} 34 | 35 | 36 | javax.servlet 37 | javax.servlet-api 38 | 3.1.0 39 | 40 | 41 | org.springframework 42 | spring-web 43 | ${spring.version} 44 | 45 | 46 | org.springframework 47 | spring-webmvc 48 | ${spring.version} 49 | 50 | 51 | org.springframework 52 | spring-aop 53 | ${spring.version} 54 | 55 | 56 | log4j 57 | log4j 58 | 1.2.17 59 | 60 | 61 | com.alibaba 62 | fastjson 63 | 1.2.17 64 | 65 | 66 | 67 | TheGameOfLife 68 | 69 | 70 | -------------------------------------------------------------------------------- /TheGameOfLife/src/main/java/com/zju/Main.java: -------------------------------------------------------------------------------- 1 | package com.zju; 2 | 3 | import com.zju.meta.CellularArray; 4 | import com.zju.service.TheGameOfLifeService; 5 | 6 | public class Main { 7 | 8 | public static void print(CellularArray cellularArray) { 9 | if (null == cellularArray) { 10 | System.out.println("null"); 11 | return; 12 | } 13 | for (int i = 0; i < cellularArray.getRow(); ++i) { 14 | for (int j = 0; j < cellularArray.getCol(); ++j) { 15 | System.out.print(cellularArray.getCell(i, j) + " "); 16 | } 17 | System.out.println(); 18 | } 19 | System.out.println("print end"); 20 | } 21 | 22 | public static void main(String[] args) { 23 | TheGameOfLifeService service = new TheGameOfLifeService(); 24 | CellularArray cellularArray = new CellularArray(15, 20); 25 | cellularArray = service.randInit(cellularArray); 26 | print(cellularArray); 27 | System.out.println("------"); 28 | cellularArray = service.generate(cellularArray); 29 | print(cellularArray); 30 | } 31 | } -------------------------------------------------------------------------------- /TheGameOfLife/src/main/java/com/zju/controller/TheGameOfLifeController.java: -------------------------------------------------------------------------------- 1 | package com.zju.controller; 2 | 3 | import com.zju.meta.CellularArray; 4 | import com.zju.service.TheGameOfLifeService; 5 | import org.springframework.stereotype.Controller; 6 | import org.springframework.web.bind.annotation.RequestBody; 7 | import org.springframework.web.bind.annotation.RequestMapping; 8 | import org.springframework.web.bind.annotation.RequestParam; 9 | import org.springframework.web.bind.annotation.ResponseBody; 10 | 11 | import javax.annotation.Resource; 12 | 13 | @Controller 14 | @RequestMapping("/") 15 | public class TheGameOfLifeController { 16 | 17 | private static final int defaultRow = 15; 18 | private static final int defaultCol = 15; 19 | 20 | @Resource 21 | private TheGameOfLifeService service; 22 | 23 | @ResponseBody 24 | @RequestMapping("/randInit") 25 | public Object getRandInit(@RequestParam(required = false) Integer row, @RequestParam(required = false) Integer col) { 26 | if (null == row) row = defaultRow; 27 | if (null == col) col = defaultCol; 28 | CellularArray cellularArray = service.randInit(new CellularArray(row, col)); 29 | return cellularArray; 30 | } 31 | 32 | @ResponseBody 33 | @RequestMapping("/generate") 34 | public Object generate(@RequestBody CellularArray now) { 35 | CellularArray next = service.generate(now); 36 | return next; 37 | } 38 | 39 | @ResponseBody 40 | @RequestMapping("/empty") 41 | public Object empty(@RequestParam(required = false) Integer row, @RequestParam(required = false) Integer col) { 42 | if (null == row) row = defaultRow; 43 | if (null == col) col = defaultCol; 44 | CellularArray next = service.emptyInit(new CellularArray(row,col)); 45 | return next; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /TheGameOfLife/src/main/java/com/zju/meta/CellState.java: -------------------------------------------------------------------------------- 1 | package com.zju.meta; 2 | 3 | /** 4 | * 细胞状态 5 | */ 6 | public enum CellState { 7 | DEAD(0), 8 | LIVE(1); 9 | private int value; 10 | 11 | CellState(int value) { 12 | this.value = value; 13 | } 14 | 15 | public int getValue() { 16 | return value; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /TheGameOfLife/src/main/java/com/zju/meta/CellularArray.java: -------------------------------------------------------------------------------- 1 | package com.zju.meta; 2 | 3 | /** 4 | * 细胞阵列 5 | */ 6 | public class CellularArray { 7 | private int[][] cells; 8 | private int row; 9 | private int col; 10 | 11 | public CellularArray() { 12 | } 13 | 14 | public CellularArray(int row, int col) { 15 | this.row = row; 16 | this.col = col; 17 | this.cells = new int[row][col]; 18 | } 19 | 20 | public int getRow() { 21 | return row; 22 | } 23 | 24 | public void setRow(int row) { 25 | this.row = row; 26 | } 27 | 28 | public int getCol() { 29 | return col; 30 | } 31 | 32 | public void setCol(int col) { 33 | this.col = col; 34 | } 35 | 36 | public int[][] getCells() { 37 | return cells; 38 | } 39 | 40 | public void setCells(int[][] cells) { 41 | this.cells = cells; 42 | } 43 | 44 | public int getCell(int x, int y) { 45 | if (x < 0 || this.row <= x || y < 0 || this.col <= y) { 46 | return -1; 47 | } 48 | return this.cells[x][y]; 49 | } 50 | 51 | public boolean setCell(int x, int y, int cell) { 52 | if (x < 0 || this.row <= x || y < 0 || this.col <= y) { 53 | return false; 54 | } 55 | this.cells[x][y] = cell; 56 | return true; 57 | } 58 | 59 | @Override 60 | public boolean equals(Object obj) { 61 | if (this == obj) return true; 62 | if (obj == null) return false; 63 | if (this.getClass() != obj.getClass()) return false; 64 | CellularArray other = (CellularArray) obj; 65 | if (this.row != other.getRow() || this.col != other.getCol()) return false; 66 | for (int i = 0; i < this.row; ++i) { 67 | for (int j = 0; j < this.col; ++j) { 68 | if (this.cells[i][j] != other.getCell(i, j)) { 69 | return false; 70 | } 71 | } 72 | } 73 | return true; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /TheGameOfLife/src/main/java/com/zju/service/TheGameOfLifeService.java: -------------------------------------------------------------------------------- 1 | package com.zju.service; 2 | 3 | import com.zju.meta.CellState; 4 | import com.zju.meta.CellularArray; 5 | import org.springframework.stereotype.Service; 6 | 7 | import java.util.Random; 8 | 9 | @Service 10 | public class TheGameOfLifeService { 11 | //方向数组 12 | private int[] direct = {-1, 0, 1}; 13 | 14 | /** 15 | * 给定阵列和坐标,计算坐标点的邻居存活数量 16 | * @param now 细胞阵列 17 | * @param x 横坐标 18 | * @param y 纵坐标 19 | * @return 20 | */ 21 | private int countLiveNeighbor(CellularArray now, int x, int y) { 22 | int count = 0; 23 | for (int i = 0; i < 3; ++i) { 24 | for (int j = 0; j < 3; ++j) { 25 | if (CellState.LIVE.getValue() == now.getCell(x + this.direct[i], y + this.direct[j])) { 26 | ++count; 27 | } 28 | } 29 | } 30 | if (CellState.LIVE.getValue() == now.getCell(x, y)) { 31 | --count; 32 | } 33 | return count; 34 | } 35 | 36 | /** 37 | * 给定细胞阵列,生成下一代的细胞阵列 38 | * @param now 细胞阵列 39 | * @return 40 | */ 41 | public CellularArray generate(CellularArray now) { 42 | if (null == now) { 43 | return null; 44 | } 45 | int liveCount; 46 | CellularArray next = new CellularArray(now.getRow(), now.getCol()); 47 | for (int i = 0; i < next.getRow(); ++i) { 48 | for (int j = 0; j < next.getCol(); ++j) { 49 | liveCount = this.countLiveNeighbor(now, i, j); 50 | if (CellState.LIVE.getValue() == now.getCell(i, j) && (liveCount < 2 || liveCount > 3)) { //人口过少,人口过多 51 | next.setCell(i, j, CellState.DEAD.getValue()); 52 | } else if (CellState.LIVE.getValue() == now.getCell(i, j) && (2 <= liveCount && liveCount <= 3)) { //正常 53 | next.setCell(i, j, CellState.LIVE.getValue()); 54 | } else if (CellState.DEAD.getValue() == now.getCell(i, j) && (3 == liveCount)) { //繁殖 55 | next.setCell(i, j, CellState.LIVE.getValue()); 56 | } 57 | } 58 | } 59 | return next; 60 | } 61 | 62 | /** 63 | * 给定细胞阵列,产生随机结果 64 | * @param cellularArray 细胞阵列 65 | * @return 66 | */ 67 | public CellularArray randInit(CellularArray cellularArray) { 68 | if (null == cellularArray) return null; 69 | Random r = new Random(); 70 | int value; 71 | for (int i = 0; i < cellularArray.getRow(); ++i) { 72 | for (int j = 0; j < cellularArray.getCol(); ++j) { 73 | value = r.nextInt(2); 74 | cellularArray.setCell(i, j, value); 75 | } 76 | } 77 | return cellularArray; 78 | } 79 | 80 | /** 81 | * 给定细胞阵列,产生初始化结果 82 | * @param cellularArray 83 | * @return 84 | */ 85 | public CellularArray emptyInit(CellularArray cellularArray) { 86 | if (null == cellularArray) return null; 87 | for (int i = 0; i < cellularArray.getRow(); ++i) { 88 | for (int j = 0; j < cellularArray.getCol(); ++j) { 89 | cellularArray.setCell(i, j, CellState.DEAD.getValue()); 90 | } 91 | } 92 | return cellularArray; 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /TheGameOfLife/src/main/resources/Spring/spring-config.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | text/plain 20 | application/json 21 | 22 | 23 | 24 | 25 | WriteMapNullValue 26 | DisableCircularReferenceDetect 27 | WriteDateUseDateFormat 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /TheGameOfLife/src/main/webapp/WEB-INF/web.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | The Game Of Life 7 | 8 | spring-mvc 9 | org.springframework.web.servlet.DispatcherServlet 10 | 11 | contextConfigLocation 12 | classpath:Spring/*.xml 13 | 14 | 1 15 | 16 | 17 | spring-mvc 18 | 19 | /backend/* 20 | 21 | 22 | /index.html 23 | 24 | 25 | -------------------------------------------------------------------------------- /TheGameOfLife/src/main/webapp/index.css: -------------------------------------------------------------------------------- 1 | .td-white { 2 | background-color: white; 3 | width: 20px; 4 | height: 20px; 5 | } 6 | 7 | .td-black { 8 | background-color: black; 9 | width: 20px; 10 | height: 20px; 11 | } 12 | 13 | body { 14 | margin: 10px; 15 | } -------------------------------------------------------------------------------- /TheGameOfLife/src/main/webapp/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | The Game Of Life 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 |
15 |
16 | 17 | 18 |
19 |
20 | 21 | 22 |
23 |
24 | 25 | 26 |
27 | 28 | 29 | 30 | 31 |
32 |
33 |
34 |
35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /TheGameOfLife/src/main/webapp/index.js: -------------------------------------------------------------------------------- 1 | var cellularArray; 2 | //根据参数控制页面显示的细胞阵列 3 | function createTable(cellularArray) { 4 | //清空控件内容 5 | $("#table").empty(); 6 | var rowCount = cellularArray.row; 7 | var colCount = cellularArray.col; 8 | var table = $(""); 9 | table.appendTo($("#table")); 10 | var cells = cellularArray.cells; 11 | for (var i = 0; i < rowCount; ++i) { 12 | var tr = $(""); 13 | tr.appendTo(table); 14 | for (var j = 0; j < colCount; ++j) { 15 | var td; 16 | if (cells[i][j] == 0) { 17 | td = $(""); 18 | } else { 19 | td = $(""); 20 | } 21 | td.appendTo(tr); 22 | } 23 | } 24 | $("#table").append("
" + "" + "
"); 25 | } 26 | //点击细胞后反转其生死 27 | function checkCell(cell) { 28 | var x = parseInt($(cell).attr("data-x")); 29 | var y = parseInt($(cell).attr("data-y")); 30 | var cells = cellularArray.cells; 31 | cells[x][y] = (cells[x][y] + 1) % 2; 32 | this.createTable(cellularArray); 33 | } 34 | $("#initButton").click(function () { 35 | var rowCount = $("#rowText").val(); 36 | var colCount = $("#colText").val(); 37 | $.ajax({ 38 | url: "/backend/randInit", 39 | type: "GET", 40 | dataType: "JSON", 41 | contentType: "application/json", 42 | data: { 43 | row: rowCount, 44 | col: colCount 45 | }, 46 | success: function (result) { 47 | cellularArray = result; 48 | createTable(cellularArray); 49 | } 50 | }); 51 | $("#generateCount").val(0); 52 | }); 53 | $("#generateButton").click(function () { 54 | var rowCount = $("#rowText").val(); 55 | var colCount = $("#colText").val(); 56 | var generateCount = $("#generateCount").val(); 57 | $.ajax({ 58 | type: "POST", 59 | url: "/backend/generate", 60 | dataType: "JSON", 61 | contentType: "application/json", 62 | data: JSON.stringify(cellularArray), 63 | success: function (result) { 64 | cellularArray = result; 65 | createTable(cellularArray); 66 | } 67 | }); 68 | $("#generateCount").val(parseInt(generateCount) + 1); 69 | }); 70 | $("#countCleanButton").click(function () { 71 | $("#generateCount").val(0); 72 | }); 73 | $("#cellCleanButton").click(function () { 74 | var rowCount = $("#rowText").val(); 75 | var colCount = $("#colText").val(); 76 | $.ajax({ 77 | url: "/backend/empty", 78 | type: "GET", 79 | dataType: "JSON", 80 | contentType: "application/json", 81 | data: { 82 | row: rowCount, 83 | col: colCount 84 | }, 85 | success: function (result) { 86 | cellularArray = result; 87 | createTable(cellularArray); 88 | $("#generateCount").val(0); 89 | $("#rowText").val(cellularArray.row); 90 | $("#colText").val(cellularArray.col); 91 | } 92 | }); 93 | }); --------------------------------------------------------------------------------