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

19 comments
Comment actions Permalink

Brian Buckley wrote:

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


great idea. I have the same problem at work where some getter methods
don't have any fields.

regards

Anders Holmbech Nielsen

0
Comment actions Permalink

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

0
Comment actions Permalink

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

0
Comment actions Permalink

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

Any requirement for sorting? I would assume the
sorting should be as the name of the method with the
get/is prefix?

 private String email;
> private String getAddress() { ... }]]>


Should be sorted as:

   return "MyClass{" +
>          "address='" + getAddress() + "'" +
>          "email='" + email + "'" +
>          "name='" + name + "'" +
>          "}";
> }]]>



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


0
Comment actions Permalink

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

You can exclude static fields today. The switch are in the settings.

/Claus

0
Comment actions Permalink

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

0
Comment actions Permalink

v2.14 is just released with the javadoc integration.

Now I have time for this feature request.

/Claus

0
Comment actions Permalink

If you're able to get getters printing, in addition to or instead of fields, that'd be sweet.

0
Comment actions Permalink

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

0
Comment actions Permalink

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

0
Comment actions Permalink

Public, non-static getters, alphabetically inserted
in with the fields would probably be my normal
preference.

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

0
Comment actions Permalink

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

0
Comment actions Permalink

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.

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

0
Comment actions Permalink

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.

Correct this is how it will be implemented.

/Claus

0
Comment actions Permalink

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

0
Comment actions Permalink

v2.15 is just released with this feature.

0
Comment actions Permalink

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

0
Comment actions Permalink

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

0
Comment actions Permalink

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

0

Please sign in to leave a comment.