GenerateToString feature request
I have a feature request for the GenerateToString plugin.
In addition to printing fields as the plugin currently does, I would like to be able to automatically print getters too. Often fields and getter methods match up one-to-one, but not always. So, for example, if a class does not have a field "foo1" of type Foo, but has a getFoo1() method (perhaps dynamically constructed in the method), I'd like GenerateToString to generate "foo1=" + getFoo1(), in addition to printing out the object's fields.
I don't know how easy or difficult it would be to implement this.
Thanks for considering this, and terrific, very useful time-saving plugin as is!
Brian
Please sign in to leave a comment.
Brian Buckley wrote:
great idea. I have the same problem at work where some getter methods
don't have any fields.
regards
Anders Holmbech Nielsen
Jesus two feature requests for this plugin in one day.
I'm adding this as a todo and would implement this feature in an upcomming release. Maybe I release v2.13 without this feature as it is mainly the new inspect code feature to warn against out of sync situations where you have fields that are not dumped in your toString method.
I can see a potential problem with getting the getXXX() methods to be displayed in the field chooser dialog. I might have to do somekind of cheating to simulate a field named getXXX().
And the getXXX() method should be avail in the velocity context for you to use in the template code. Well now I know what to do in the weekend.
/Claus
Any requirement for sorting? I would assume the sorting should be as the name of the method with the get/is prefix?
Should be sorted as:
I do a basic investigation and I think it is doable however I do not know what approach to take:
- fake getAddress() to be considered as a field in the velocity template
- introduce a new element type: MethodElement
There should be some criteria for not dumping certain methods even though they start with getXXX(). Sometimes you have helper methods named that (eg. private methods).
Default only public getXXX() methods would be dumped if their name does not match an existing fieldname (in the example above the class having a method named getAddress() but no fields named address). The method should also be non static?. Any other requirements? And should some of these parameters be changeable from the settings?
And generally there should be a swtich to turn this feature on/off allowing to dump getXXX() methods.
/Claus
Claus,
Public, non-static getters, alphabetically inserted in with the fields would probably be my normal preference.
Keep with the ability to reorder and remove in the dialog as GenerateToString currently allows with fields.
The switch is a good idea. FYI, I currently almost always remove the static fields when the dialog pops up, so another potential feature could be to add a switch to include/exclude statics (for both fields and getters). Maybe also have a switch to display getters ONLY, and not fields at all.
Just my two cents. I don't mean to be putting more on your plate :)
Brian
You can exclude static fields today. The switch are in the settings.
/Claus
I hope to have time next week. However I need to finish the javadoc feature request first - it is doable as I can insert the javadoc text now but need to integrate it into the UI.
Then my attention will be on this feature. I can add the getXXX() methods to the field dialog chooser. But I need the code generator to be aware of methods also. This would take some extra time and testing.
I will keep you posted with the progress.
/Claus
v2.14 is just released with the javadoc integration.
Now I have time for this feature request.
/Claus
If you're able to get getters printing, in addition to or instead of fields, that'd be sweet.
I worked this evening on this feature and I got pretty far.
I got a basic setup for introspect a class for both:
- fields
- methods
What I will introduce is two new lists to velocity context:
- methods (only methods)
- elements (fields and methods sorted as defined in prev posts).
This will enable you to define a template like this:
0 ) #set ( $i = 0 ) return "$classname{" + #foreach( $element in $elements ) #if ( $i == 0 ) "## #else ", ## #end #if ( $element.objectArray ) $field.name=" + ($field.accessor == null ? null : Arrays.asList($field.accessor)) + #elseif ( $element.string ) $element.name='" + $field.accessor + "'" + #else $element.name=" + $field.accessor + #end #set ( $i = $i + 1 ) #end "}"; #else return "$classname{}"; #end]]>We use elements instead of fields. Elements contains both fields and methods.
The element.accessor will return for a method:
getXXX()
and for a field:
fieldname
I only reached so far to gather the information and create all the objects.
Todo:
- integrate to velocity
- integrate to memeber dialog chooser
- settings to specify filtering of getter methods (to only include the ones that does not have a belonging field)
- other exlucde by options as with fields (maybe it should use the same as for fields = I think so)
- testing
I will only have time thursday to continue coding, so release a stable version will be at least one week as I will be out of time in the weekend + 3 more days.
If you want a beta build to test and see if it fits your needs then drop me an email:
/Claus
The code should of course use element.XXX instead of field.XXX.
0 ) #set ( $i = 0 ) return "$classname{" + #foreach( $element in $elements ) #if ( $i == 0 ) "## #else ", ## #end #if ( $element.objectArray ) $element.name=" + ($element.accessor == null ? null : Arrays.asList($element.accessor)) + #elseif ( $element.string ) $element.name='" + $element.accessor + "'" + #else $element.name=" + $element.accessor + #end #set ( $i = $i + 1 ) #end "}"; #else return "$classname{}"; #end]]>/Claus
I think the default requirement would be:
1) getter
2) public
3) non static
4) must not return 'void'
5) name should not match an existing fieldname
6) must not have parameters
7) must not throw checked exceptions (or any exception at all?)
I got 1-5 covered right now.
/Claus
I don't know how your code does its thing internally, but I was envisioning your code putting three collection into the velocity context for our templates to use: 1) fields (current), 2) the getters, and 3) elements (a merging of (1) and (2) so one can simply print out each item without overlaps.
On getters, I'm not a javabean expert but I believe they have to be public, non-static, and of the form getXXX() (or isXXX() if type is boolean). They can throw exceptions. If you care, I think the jakarta commons beanutils library has methods which do the work of pick them out of a class, not that it is difficult.
Brian
Yeah you are spot on. However throwing Exceptions is not nice in a toString() method as you can not overwrite it to throw a checked exception. Solution is to use try .. catch.
It could avoid dumping methods ala:
The twist with isXXX must return a boolean or java.lang.Boolean is something I must remember to add.
Will work on this tonight
Isnt the jakarta beansutils used at runtime?
The plugin is used at edit time.
/Claus
Correct this is how it will be implemented.
/Claus
A beta is not compiled with this feature.
A stable version will not be released for at least one week as I will be out of town.
/Claus
v2.15 is just released with this feature.
In the velocity template how does one print the method name into the toString code instead of just the property name(ie we want, "x = getX()", not "x = x")
#foreach( $method in $methods )
$method.name=" + $method.name
//prints property but we must use the getter for "virtual fields"
end
-Brian
You can do it in two ways:
1) $method.name=" + $method.methodName
or
2) $method.name=" + $method.accessor
No 2 also works for fields as it would paste the getFoo() for a method and foo for a field.
PS: Ups I forgot to add this to the velocity description on the homepage.
/Claus
Correction to no 1
$method.name=" + $method.methodName ()
You need manually add the () and use a space between.
Using $methodName.accessor is easier as it will automatic add the ().
/Claus