PKey
PKey

Reputation: 3841

Repeatable Code generation

It is awfully often required to write repeatable pieces of code.

Consider the following example from Java (although, it may not be the best example, but I hope you get the general idea...)

String X = rs.getString("X");

Where X will have values: 'name','surname' ... and 20-30 other values.

(Another example would be an HTML code and any other code - you need to create for X)

The end result should be:

String name=rs.getString("name");
String surname=rs.getString("surname");
....

String whatever = rs.getString("whatever");

Here is another example with html table and some scriplets, in this case string to replicate would be <th>X</th> and <td><%=myBean.getX()%></td> the end result would be:

<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>

So, apart form copy-pasting the above for 30 times and then editing, the the only 'clever' way I found to deal with this is to use python, jinja2 library and write a small code generator.

But, in order to do that I had to install python, install the library, create a template, create a custom script to read values from a text file and then generate code for the values read.

I was wondering is there any easier way to achieve the above?

Any editor or plugin to support code generation?

I know that IDEs such as Netbeans, Eclipse can generate some code - like getters and setters ... etc, but it is not enough...

In a nutshell, I want to regenerate some lines of code by altering only specific parts ... The question is how to achieve that easily? (I know the hard way to do this) ..I am seeking for ideas...

Upvotes: 2

Views: 654

Answers (5)

lgu
lgu

Reputation: 2460

You can do that with a lightweight code generator like Telosys :

In your case Telosys-CLI with a DSL model is probably the right choice, you'll just have to create your specific templates in Velocity language ( http://velocity.apache.org/ )

Upvotes: 2

PKey
PKey

Reputation: 3841

Probably I am looking for something that does not exist.

So, I'll just post my 'hard way' of achieving, what I have described in my question (in hope that this would be useful for somebody - sometime).

Here I will preset a small code generator I am using to generate java, html, jsp, xsd and other codes.

I am using Python27 and Jinja2-2.7.2

My Files:

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-----------------

Upvotes: 1

In such scenarios, the best thing you could do is to use a constant array together with a HashMap. The constant array will hold keynames for the hashmap whereas the hashmap will also hold the value for each one.

For instance:

String[] keys = {"name", "surname", "whatever" };
HashMap<String, String> elements = new HashMap<String, String>();
for (String key : keys)
{
    elements.put(key, rs.getString(key));
}

You just have to be careful that all the elements are from the same type. If they are not, you will have to either store them as Objects and then cast them.

EDIT: for using in a Scriptlet, a good idea would be:

<tr>
    <% for (String key : keys)
       {
    %>      
    <td><%= elements.get(key)%></td>
    <% } %>
</tr>

Upvotes: 0

Justas
Justas

Reputation: 811

If I understand your problem correctly, you have a ResultSet with a lot of columns. And you do not want to get them one by one. It is possible to get all the columns from a ResultSet the following way:

ResultSetMetaData metaData = resultSet.getMetaData();
for (int columnIndex = 1; columnIndex <= metaData.getColumnCount(); columnIndex++) {
    String columnName = metaData.getColumnName(columnIndex);
    String value = resultSet.getString(columnIndex);
}

Granted all the values will b e represented as strings in this example, but you can determine the type of the column also by using the same metaData object. Read more about it in the documentation: https://docs.oracle.com/javase/7/docs/api/java/sql/ResultSetMetaData.html

Upvotes: -1

Denis Arruda
Denis Arruda

Reputation: 19

In IntelliJ we have "Live Template" feature that you use to generate part of the code.

For example, when you type "sout" , IntelliJ suggests "System.out.println".

When you type "main" , Eclipse suggests "public static void main(String[] args)"

You can create something like that for pieces of code that are very commom.

Upvotes: -1

Related Questions