patternjavaMinor
Generation of Groovy source from parent Java class
Viewed 0 times
sourceparentjavagenerationfromclassgroovy
Problem
I use Groovy to write business rules into big, long term Java software. Use Groovy in object way, that is not as groovy Script, but every elementary groovy source overrides some Java API class.
i.e.
I had an idea to clone in very little scale IDE functionality: generate class from, or Override method.
My idea is much simpler: do automatically, only first-shot, write method stub where this must be done (abstract method), maybe in comment where may be done (non-abstract).
My mini project has first effects, in this sample
My target for next days is to:
I haven't big trouble with coding (one small problem: reflection usually doesn't give parameters name), but with idea.
This tool is made for in-place IT-man, who generate business rules in, for example, Notepad or simple editor non-capable in generation.
What can be done better in this project?
```
package pl.cogitat.scripting;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
public class GroovyGenerator {
Class analyzedClass;
private String packg;
private String name;
public GroovyGenerator(String pckg, String name, Class analyzedClass) {
super();
this.analyzedClass = analyzedClass;
this.packg = pckg;
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPackg() {
return packg;
}
public String performGeneration()
{
StringBuilder sb = new StringBuilder();
sb.append("p
i.e.
AtLoginScript, PreparePaport etc.I had an idea to clone in very little scale IDE functionality: generate class from, or Override method.
My idea is much simpler: do automatically, only first-shot, write method stub where this must be done (abstract method), maybe in comment where may be done (non-abstract).
My mini project has first effects, in this sample
GroovyGenerator create his-own 'child class'.My target for next days is to:
- implement negative conditions for final or private method,
- some decisions with more deep parent class (now only one-level)
- types when applicable
- maybe implement groovy property from getter/setter pair?
- constructors
extendfrom 0 or 1 class andimplementzero to \$n\$ interfaces (What to do with override level?)
I haven't big trouble with coding (one small problem: reflection usually doesn't give parameters name), but with idea.
This tool is made for in-place IT-man, who generate business rules in, for example, Notepad or simple editor non-capable in generation.
What can be done better in this project?
```
package pl.cogitat.scripting;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
public class GroovyGenerator {
Class analyzedClass;
private String packg;
private String name;
public GroovyGenerator(String pckg, String name, Class analyzedClass) {
super();
this.analyzedClass = analyzedClass;
this.packg = pckg;
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPackg() {
return packg;
}
public String performGeneration()
{
StringBuilder sb = new StringBuilder();
sb.append("p
Solution
You can use Groovy to generate the Groovy source code.
The source code generator
Here's an example source code generator.
How it works
It's actually quite simple. The method signatures are gathered from the class's MetaClass. Then some hefty formatting is applied to write the method signatures correctly. Also, final methods are excluded.
Example
Generated source code
Templates
Ideally, you'd have two templates: one for the class and one for the methods. That would avoid the clunky JSP-style programming. You can read more about Groovy's template engines here.
The source code generator
Here's an example source code generator.
import groovy.text.SimpleTemplateEngine
def generate(Class klass, String packageName, String name, String template) {
def engine = new SimpleTemplateEngine()
def binding = [
packageName: packageName,
name: name,
superClass: klass.name,
methods: klass.metaClass.methods
.findAll { !(it.toString().contains(' final ')) }
.collect {
def args = []
def m = it.toString() =~ /(.*) (.*\.)(.*)(\((.*)\).*)/
m.matches()
if(m.group(5).size() > 0) {
m.group(5).split(',').eachWithIndex {arg, index ->
args << "$arg p$index"
}
}
return "${m.group(1).replace('native', '')} ${m.group(3)}(${args.join(', ')})"
}
]
engine.createTemplate(template).make(binding).toString()
}How it works
It's actually quite simple. The method signatures are gathered from the class's MetaClass. Then some hefty formatting is applied to write the method signatures correctly. Also, final methods are excluded.
Example
def template = '''
package $packageName
/* Code auto generated
* do edit what You want
*/
class $name extends $superClass {
}
'''
generate(Object, 'my.script', 'SelfGenerator', template)Generated source code
package my.script
/* Code auto generated
* do edit what You want
*/
class SelfGenerator extends java.lang.Object {
public boolean equals(java.lang.Object p0) {
}
public int hashCode() {
}
public java.lang.String toString() {
}
}Templates
Ideally, you'd have two templates: one for the class and one for the methods. That would avoid the clunky JSP-style programming. You can read more about Groovy's template engines here.
Code Snippets
import groovy.text.SimpleTemplateEngine
def generate(Class klass, String packageName, String name, String template) {
def engine = new SimpleTemplateEngine()
def binding = [
packageName: packageName,
name: name,
superClass: klass.name,
methods: klass.metaClass.methods
.findAll { !(it.toString().contains(' final ')) }
.collect {
def args = []
def m = it.toString() =~ /(.*) (.*\.)(.*)(\((.*)\).*)/
m.matches()
if(m.group(5).size() > 0) {
m.group(5).split(',').eachWithIndex {arg, index ->
args << "$arg p$index"
}
}
return "${m.group(1).replace('native', '')} ${m.group(3)}(${args.join(', ')})"
}
]
engine.createTemplate(template).make(binding).toString()
}def template = '''
package $packageName
/* Code auto generated
* do edit what You want
*/
class $name extends $superClass {
<%
methods.each {
println ''
println "\t$it {"
println ''
println "\t}"
} %>
}
'''
generate(Object, 'my.script', 'SelfGenerator', template)package my.script
/* Code auto generated
* do edit what You want
*/
class SelfGenerator extends java.lang.Object {
public boolean equals(java.lang.Object p0) {
}
public int hashCode() {
}
public java.lang.String toString() {
}
}Context
StackExchange Code Review Q#102672, answer score: 2
Revisions (0)
No revisions yet.