可重复代码生成
Repeatable Code generation
经常需要编写重复table 段代码。
考虑以下来自 Java
的例子(尽管它可能不是最好的例子,但我希望你能理解一般的想法...)
String X = rs.getString("X");
其中 X
将具有以下值:'name'
、'surname'
... 和 20
-30
其他值。
(另一个示例是 HTML
代码和任何其他代码 - 您需要为 X
创建)
最终结果应该是:
String name=rs.getString("name");
String surname=rs.getString("surname");
....
String whatever = rs.getString("whatever");
这是另一个例子 html
table 和一些 scriplets
,在这种情况下要复制的字符串将是 <th>X</th>
和 <td><%=myBean.getX()%></td>
最终结果将是:
<table style="width:100%">
<tr>
<th>name</th>
<th>surname</th>
<th>..</th>
<th>whatever</th>
</tr>
<tr>
<td><%=myBean.getName()%></td>
<td><%=myBean.getSurname()%></td>
<td>..</td>
<td><%=myBean.getWhatever()%></td>
</tr>
</table>
所以,除了将上面的内容复制粘贴 30
次然后编辑之外,我发现处理此问题的唯一 'clever' 方法是使用 python
,jinja2
库并编写一个小型代码生成器。
但是,为了做到这一点,我必须安装 python
、安装库、创建 template
、创建自定义 script
以从 [=31] 中读取值=] 然后为读取的值生成代码。
我想知道有没有更简单的方法来实现上述目标?
有支持代码生成的编辑器或插件吗?
我知道像 Netbeans、Eclipse 这样的 IDE 可以生成一些代码——比如 getters 和 setters……等等,但这还不够……
简而言之,
我想通过仅更改特定部分来重新生成一些代码行......问题是如何轻松实现? (我知道这样做的困难方法)..我正在寻求想法...
在 IntelliJ 中,我们有 "Live Template" 功能,您可以使用它来生成部分代码。
例如,当您键入 "sout" 时,IntelliJ 会建议 "System.out.println".
当您键入 "main" 时,Eclipse 会建议 "public static void main(String[] args)"
您可以为非常常见的代码片段创建类似的东西。
在这种情况下,您能做的最好的事情就是将常量数组与 HashMap 一起使用。常量数组将保存 hashmap 的键名,而 hashmap 还将保存每个键名。
例如:
String[] keys = {"name", "surname", "whatever" };
HashMap<String, String> elements = new HashMap<String, String>();
for (String key : keys)
{
elements.put(key, rs.getString(key));
}
您只需要注意所有元素都来自同一类型即可。如果不是,则必须将它们存储为对象然后再进行转换。
编辑:为了在 Scriptlet 中使用,一个好主意是:
<tr>
<% for (String key : keys)
{
%>
<td><%= elements.get(key)%></td>
<% } %>
</tr>
如果我对您的问题的理解正确,您的 ResultSet
包含很多列。而且您不想一一得到它们。
可以通过以下方式从 ResultSet
中获取所有列:
ResultSetMetaData metaData = resultSet.getMetaData();
for (int columnIndex = 1; columnIndex <= metaData.getColumnCount(); columnIndex++) {
String columnName = metaData.getColumnName(columnIndex);
String value = resultSet.getString(columnIndex);
}
当然,在此示例中,所有值都将表示为字符串,但您也可以使用相同的 metaData
对象来确定列的类型。在文档中阅读更多相关信息:https://docs.oracle.com/javase/7/docs/api/java/sql/ResultSetMetaData.html
可能我正在寻找不存在的东西。
所以,我将 post 我的“困难方式”实现,我在问题中描述的内容(希望这对有人 - 某个时候)。
这里我会预设一个我正在使用的小型代码生成器,用于生成java、html、jsp、xsd等代码。
我正在使用 Python27 and Jinja2-2.7.2
我的文件:
InputData.txt
:This is field list
field1:field1 description
field2:field2 description
field3:field3 description
field4:field4 description
name:first name of the person
surname:last name of the person
whatever:whatever you need
CodeGenerator.py
import jinja2
import codecs
templateLoader = jinja2.FileSystemLoader( searchpath="." )
templateEnv = jinja2.Environment( loader=templateLoader )
TEMPLATE_FILE = "CodeGenerator.jinja"
template = templateEnv.get_template( TEMPLATE_FILE )
COLUMNS = [tuple(line.split(':')) for line in codecs.open( "InputData.txt", "r", "utf-8" )]
COLUMNS = map(lambda s: (s[0],(s[0].strip().title(),s[1].strip())), COLUMNS)
#title() copy of the string in which first characters of all the words are capitalized.
#strip() copy of the string, all chars have been stripped from the beginning and the end
#lambda s --> (field1,(Field1,field1 description))
#ignore the first line
COLUMNS.pop(0)
#add variables to work with
templateVars = { "table" : "MyTableName",
"description" : "A simple code generator",
"columns" : COLUMNS
}
outputText = template.render( templateVars )
f = open('Generated.txt', 'w')
outputText = outputText.encode('utf-8')
f.write(outputText)
f.close()
print outputText
CodeGenerator.jinja
//------------------model------------------------
//Generated code for model
import java.io.Serializable;
public class {{table|capitalize}}_Model implements Serializable{
{%for columnName,columnTitle in columns%}
private String {{columnName|lower}};{%endfor%}
{% for columnName,columnTitle in columns %}
public void set{{columnName|capitalize}}(String {{columnName|lower}}){
this.{{columnName|lower}}={{columnName|lower}};
}
public String get{{columnName|capitalize}}(){
return this.{{columnName|lower}};
}
{% endfor %}
public {{table|capitalize}}_Model({% for columnName,columnTitle in columns %}String {{columnName|lower}}{% if not loop.last %},{% endif %}{% endfor %}){
{% for columnName,columnTitle in columns %}
this.{{columnName|lower}}={{columnName|lower}}; {% endfor %}
}
public String toString(){
return {% for columnName,columnTitle in columns %}"{{columnName|lower}}:" + this.{{columnName|lower}}{% if not loop.last %}+{% endif %}{% endfor %};
}
}
//------------------model------------------------
//-----------------getStrings--------------------
{% for columnName,columnTitle in columns %}
String {{columnName}}=rs.getString("{{columnName}}");
{% endfor %}
//----------------------------------------------
//------------------jsp example-----------------
{% for columnName,columnTitle in columns %}
<s:label cssStyle ="margin-top:5px;color:blue;" value="{{columnTitle[1]}} :" id="{{columnName}}_label"/>
<s:textfield label="{{columnTitle[1]}}" name="myBean.{{columnName}}" />
{% endfor %}
//------------------jsp example-----------------
您可以使用像 Telosys 这样的轻量级代码生成器来做到这一点:
- http://www.telosys.org/
- https://modeling-languages.com/telosys-tools-the-concept-of-lightweight-model-for-code-generation/
在你的情况下,带有 DSL 模型的 Telosys-CLI 可能是正确的选择,你只需要用 Velocity 语言创建你的特定模板 (http://velocity.apache.org/)
经常需要编写重复table 段代码。
考虑以下来自 Java
的例子(尽管它可能不是最好的例子,但我希望你能理解一般的想法...)
String X = rs.getString("X");
其中 X
将具有以下值:'name'
、'surname'
... 和 20
-30
其他值。
(另一个示例是 HTML
代码和任何其他代码 - 您需要为 X
创建)
最终结果应该是:
String name=rs.getString("name");
String surname=rs.getString("surname");
....
String whatever = rs.getString("whatever");
这是另一个例子 html
table 和一些 scriplets
,在这种情况下要复制的字符串将是 <th>X</th>
和 <td><%=myBean.getX()%></td>
最终结果将是:
<table style="width:100%">
<tr>
<th>name</th>
<th>surname</th>
<th>..</th>
<th>whatever</th>
</tr>
<tr>
<td><%=myBean.getName()%></td>
<td><%=myBean.getSurname()%></td>
<td>..</td>
<td><%=myBean.getWhatever()%></td>
</tr>
</table>
所以,除了将上面的内容复制粘贴 30
次然后编辑之外,我发现处理此问题的唯一 'clever' 方法是使用 python
,jinja2
库并编写一个小型代码生成器。
但是,为了做到这一点,我必须安装 python
、安装库、创建 template
、创建自定义 script
以从 [=31] 中读取值=] 然后为读取的值生成代码。
我想知道有没有更简单的方法来实现上述目标?
有支持代码生成的编辑器或插件吗?
我知道像 Netbeans、Eclipse 这样的 IDE 可以生成一些代码——比如 getters 和 setters……等等,但这还不够……
简而言之, 我想通过仅更改特定部分来重新生成一些代码行......问题是如何轻松实现? (我知道这样做的困难方法)..我正在寻求想法...
在 IntelliJ 中,我们有 "Live Template" 功能,您可以使用它来生成部分代码。
例如,当您键入 "sout" 时,IntelliJ 会建议 "System.out.println".
当您键入 "main" 时,Eclipse 会建议 "public static void main(String[] args)"
您可以为非常常见的代码片段创建类似的东西。
在这种情况下,您能做的最好的事情就是将常量数组与 HashMap 一起使用。常量数组将保存 hashmap 的键名,而 hashmap 还将保存每个键名。
例如:
String[] keys = {"name", "surname", "whatever" };
HashMap<String, String> elements = new HashMap<String, String>();
for (String key : keys)
{
elements.put(key, rs.getString(key));
}
您只需要注意所有元素都来自同一类型即可。如果不是,则必须将它们存储为对象然后再进行转换。
编辑:为了在 Scriptlet 中使用,一个好主意是:
<tr>
<% for (String key : keys)
{
%>
<td><%= elements.get(key)%></td>
<% } %>
</tr>
如果我对您的问题的理解正确,您的 ResultSet
包含很多列。而且您不想一一得到它们。
可以通过以下方式从 ResultSet
中获取所有列:
ResultSetMetaData metaData = resultSet.getMetaData();
for (int columnIndex = 1; columnIndex <= metaData.getColumnCount(); columnIndex++) {
String columnName = metaData.getColumnName(columnIndex);
String value = resultSet.getString(columnIndex);
}
当然,在此示例中,所有值都将表示为字符串,但您也可以使用相同的 metaData
对象来确定列的类型。在文档中阅读更多相关信息:https://docs.oracle.com/javase/7/docs/api/java/sql/ResultSetMetaData.html
可能我正在寻找不存在的东西。
所以,我将 post 我的“困难方式”实现,我在问题中描述的内容(希望这对有人 - 某个时候)。
这里我会预设一个我正在使用的小型代码生成器,用于生成java、html、jsp、xsd等代码。
我正在使用 Python27 and Jinja2-2.7.2
我的文件:
InputData.txt
:This is field list
field1:field1 description
field2:field2 description
field3:field3 description
field4:field4 description
name:first name of the person
surname:last name of the person
whatever:whatever you need
CodeGenerator.py
import jinja2
import codecs
templateLoader = jinja2.FileSystemLoader( searchpath="." )
templateEnv = jinja2.Environment( loader=templateLoader )
TEMPLATE_FILE = "CodeGenerator.jinja"
template = templateEnv.get_template( TEMPLATE_FILE )
COLUMNS = [tuple(line.split(':')) for line in codecs.open( "InputData.txt", "r", "utf-8" )]
COLUMNS = map(lambda s: (s[0],(s[0].strip().title(),s[1].strip())), COLUMNS)
#title() copy of the string in which first characters of all the words are capitalized.
#strip() copy of the string, all chars have been stripped from the beginning and the end
#lambda s --> (field1,(Field1,field1 description))
#ignore the first line
COLUMNS.pop(0)
#add variables to work with
templateVars = { "table" : "MyTableName",
"description" : "A simple code generator",
"columns" : COLUMNS
}
outputText = template.render( templateVars )
f = open('Generated.txt', 'w')
outputText = outputText.encode('utf-8')
f.write(outputText)
f.close()
print outputText
CodeGenerator.jinja
//------------------model------------------------
//Generated code for model
import java.io.Serializable;
public class {{table|capitalize}}_Model implements Serializable{
{%for columnName,columnTitle in columns%}
private String {{columnName|lower}};{%endfor%}
{% for columnName,columnTitle in columns %}
public void set{{columnName|capitalize}}(String {{columnName|lower}}){
this.{{columnName|lower}}={{columnName|lower}};
}
public String get{{columnName|capitalize}}(){
return this.{{columnName|lower}};
}
{% endfor %}
public {{table|capitalize}}_Model({% for columnName,columnTitle in columns %}String {{columnName|lower}}{% if not loop.last %},{% endif %}{% endfor %}){
{% for columnName,columnTitle in columns %}
this.{{columnName|lower}}={{columnName|lower}}; {% endfor %}
}
public String toString(){
return {% for columnName,columnTitle in columns %}"{{columnName|lower}}:" + this.{{columnName|lower}}{% if not loop.last %}+{% endif %}{% endfor %};
}
}
//------------------model------------------------
//-----------------getStrings--------------------
{% for columnName,columnTitle in columns %}
String {{columnName}}=rs.getString("{{columnName}}");
{% endfor %}
//----------------------------------------------
//------------------jsp example-----------------
{% for columnName,columnTitle in columns %}
<s:label cssStyle ="margin-top:5px;color:blue;" value="{{columnTitle[1]}} :" id="{{columnName}}_label"/>
<s:textfield label="{{columnTitle[1]}}" name="myBean.{{columnName}}" />
{% endfor %}
//------------------jsp example-----------------
您可以使用像 Telosys 这样的轻量级代码生成器来做到这一点:
- http://www.telosys.org/
- https://modeling-languages.com/telosys-tools-the-concept-of-lightweight-model-for-code-generation/
在你的情况下,带有 DSL 模型的 Telosys-CLI 可能是正确的选择,你只需要用 Velocity 语言创建你的特定模板 (http://velocity.apache.org/)