blob: 59030937a65dc78e28855dc04ab683751e1593e2 [file] [log] [blame]
<html>
<body>
<h2>Generate toString() plugin</h2>
<h3>Introduction</h3>
GenerateToString is a action plugin for IDEA that is used to create or update java classes <code>toString()</code> method.
The reason is valuebeans usually needs to dump their field values for debug purpose, and it's tedious to write
the dump code for this. This plugin generates the toString() method dumping all the fields in a simple manner.
<h3>Usage</h3>
Press <b>alt + ins</b> to active the generate menu and select toString.
<h3>Example</h3>
In the code below we need to override the public <code>toString</code> method so the fields can be dumped:
<pre>
public class MyServerConfigBean {
private String name;
private String url;
private int port;
private String[] validIPs;
...
}
</pre>
After invoking the <b>GenerateToString</b> action the bean is now added with the following method
<pre>
public String toString() {
return "MyServerConfigBean{" +
"name='" + name + "'" +
", url='" + url + "'" +
", port=" + port +
", validIPs=" + (validIPs == null ? null : "length:" + validIPs.length + Arrays.asList(validIPs)) +
"}";
}
</pre>
And if you change the fields you can run the action again and have it update the toString() method.
In this situation where the toString() method already exists a dialog is displayed with options to:
<ul>
<li/>Replace existing method
<li/>Create a new toString() method, so you'll have duplicate methods
<li/>Cancel
</ul>
The plugin uses Velocity Template Language to generate the code, so it is very flexible to customize.
The template can be changed from the settings.
<h3>Enable getters in code generation</h3>
Using this feature getter methods that does not directly use an existing field are avail in the Velocity Template Macro
language as the variable $methods.
<br/>The example again with getters enabled:
<pre>
public class MyServerConfigBean {
private String name;
private String url;
private int port;
private String[] validIPs;
...
<b>public String getServerAddress() {
return url + ":" + port;
}</b>
}
</pre>
And so after invoking the action, the result is:
<pre>
public String toString() {
return "MyServerConfigBean{" +
"name='" + name + "'" +
", url='" + url + "'" +
", port=" + port +
<b>", serverAddress='" + getServerAddress() + "'" +</b>
", validIPs=" + (validIPs == null ? null : Arrays.asList(validIPs)) +
"}";
}
</pre>
The getter <code>getServerAddress</code> is now outputted in the toString method.
<h3>Adding super class aware</h3>
The plugin supports calling super.toString() in the generated code this is done using a test in the velocity macro.
Here is an example:<br/>
<pre>
#if ($class.hasSuper)
return super.toString() + " :: $classname{" +
#else
return "$classname{" +
#end
</pre>
<h3>Settings</h3>
You can change the settings of the plugin in <b>File -> Settings</b>.
<table border="1">
<tr><td width="150"><b>Configuration</b></td><td width="300"><b>Description</b></td></tr>
<tr/><td>Use field chooser dialog</td><td>A dialog for selecting fields is used (like the getter/setter dialog).</td>
<tr/><td>Always use default conflict resolution policy</td><td>Will use the option selected from the <b>Conflict Resolution Policy</b> settings.</td>
<tr/><td>Enable on-the-fly code inspection</td><td>If selected the code inspection for toString() will be run in the background (on-the-fly) and report any errors as warnings. This is like some existing IDEA code inspection for fields not used etc.</td>
<tr/><td>Use fully qualified classname</td><td>The dumped classname will be including its packagename. (The <code>$classname</code> variable in the Velocity Context)</td>
<tr/><td>Enable getters in code generation</td><td>If selected the code generator will have $methods avail in the Velocity Macro Language.</td>
<tr/><td>Move caret to generated method</td><td>If selected the caret will be moved/scrolled to the generated toString method.</td>
<tr/><td>Sort fields</td><td>If selected the fields will be sorted. This feature is only working when <b>not</b> using the dialog chooser as it has it's own sort function you should use.</td>
<tr/><td>Default Conflict Resolution Policy</td><td>Policy what to do when there already exists a toString() method.<br/><b>Replace Existing</b> = automatic replace existing toString() code. <br/><b>Duplicate</b> = Create a duplicate toString() method (will not erase you existing code).<br/><b>Cancel</b> = No code changes.</td>
<tr/><td>Insert New Method Policy</td><td>Policy what to do when inserting a new toString() method.<br/><b>At caret</b> = inserted at caret position.<br/><b>After equals/hashCode</b> = inserted after the equals/hashCode if present in the javafile, if not it will be inserted at the current caret position.<br/><b>Last</b> = inserted as the last method.<br/></td>
<tr/><td>Exclude all constant fields</td><td>If checked then any fields that's a constant will not be part of available fields for the code generator.</td>
<tr/><td>Exclude all static fields</td><td>If checked then any fields that's has a static modifier will not be part of available fields for the code generator.</td>
<tr/><td>Exclude all transient fields</td><td>If checked then any fields that has a transient modifier will not be part of available fields for the code generator.</td>
<tr/><td>Exclude all enum fields</td><td>If checked then any fields that is an enum type (JDK1.5) will not be part of available fields for the code generator.</td>
<tr/><td>Exclude loggers</td><td>If checked then any field that is a either a Log4j Logger, Java JDK Logger or a Jakarta Commons Logger will not be part of available fields for the code generator.</td>
<tr/><td>Exclude fields by name</td><td>Performs a regular expression matching on the field name. If the result is <b>true</b> the field will <b>not</b> be part of available fields for the code generator.</td>
<tr/><td>Exclude fields by typename</td><td>Performs a regular expression matching on the field type name (fully qualified name). If the result is <b>true</b> the field will <b>not</b> be part of available fields for the code generator.</td>
<tr/><td>Exclude methods by name</td><td>Performs a regular expression matching on the method name. If the result is <b>true</b> the method will <b>not</b> be part of available methods for the code generator.</td>
<tr/><td>Exclude methods by return typename</td><td>Performs a regular expression matching on the method return typename (fully qualified name). If the result is <b>true</b> the method will <b>not</b> be part of available methods for the code generator.</td>
<tr/><td>Automatic add implements java.io.Serializable</td><td>Will automatic add <code>implements Serializable</code> to the java bean class if not already implemented. This is useful for value objects that usually have to implement this interface for working in J2EE environments.</td>
<tr/><td>Automatic import packages</td><td>Will automatic import the packages. Additional packages can be separated using comma. IDEA will optimize the imports so java.util.* will be optimized to java.util.List;java.util.Arrays etc. <br/>Can be used to import your own classes that might be added to the generated code in the toString method.</td>
<tr/><td>Templates</td><td>A list of predefined templates to choose. To use a new template first select it and click the <b>Use this template</b> button.</td>
<tr/><td>Active template</td><td>Activates the current selected template. A confirm dialog will be prompted.</td>
<tr/><td>Save template</td><td>Saving the current template to a file. A file chooser dialog will be prompted.</td>
<tr/><td>Syntax check</td><td>Performs a Velocity syntax check of the current template code from the text area. Can be used to catch early syntax errors during customizing of templates.</td>
<tr/><td>Method body (Velocity Macro Language)</td><td>The java code for the toString() method body is generated using Velocity Macro Language. In this text area you can change how the code is generated.</td>
</table>
<h3>Excluding fields</h3>
Usually you don't want constant fields as debug information in your toString() method. So you can check this filtering option, and prevent
constant fields in the output. Also you can filter by the field's name. You could have an internal debug field not to be used in the toString method.
So you type <code>^debug</code> in the textfield <b>Exclude fields by name (reg exp)</b>, to prevent debug fields.
<br/>The example again using excluded fields:
<pre>
public class MyServerConfigBean {
private final static String USERNAME = "scott";
private final static String PASSWORD = "tiger";
private String name;
private String url;
private int port;
private String[] validIPs;
private boolean debug = true;
...
}
</pre>
And so after invoking the action, the result is still:
<pre>
public String toString() {
return "MyServerConfigBean{" +
"name='" + name + "'" +
", url='" + url + "'" +
", port=" + port +
", validIPs=" + (validIPs == null ? null : Arrays.asList(validIPs)) +
"}";
}
</pre>
We do not output the constant fields (USERNAME, PASSWORD). And the regular expression excluded the debug field.
The excluded fields will also not be in the choose fields dialog.
<h3>Excluding methods</h3>
Only the methodname can be excluded for methods using a regular expression test.
<br/>Typing <code>^getCausedBy.*</code> in the textfield <b>By methodname (regexp)</b>, to prevent outputting methods
starting with the name <code>getCausedBy</code>.
<h3>JavaDoc</h3>
It is possible to add javadoc comments to the generated toString() method. This is done by inserting the javadoc
comments in the velocity template. See the supplied javadoc template example. A requirement is to use /** and */
enclosing the javadoc comments. The javadoc comments should be in the top of the template.
<p/>
Here is an example:
<pre>
/**
* Insert your javadoc comments here
*
* @return a string representation of the object.
*/
return "$classname{}";
</pre>
<h3>Template Quick Selection List</h3>
This feature let you on the fly choose what template to use. When the action is invoked a little list is displayed with
the templates you have selected to be in this list. For instance if you add the two default templates for toString you
could chose between the concat or StringBuffer style.
<h3>Support for generating other methods</h3>
This plugin was meant only to generate toString() methods. But why can't it be useful to generate other methods as well?
It does have a lot of class information in the velocity context so it should be possible to create a compareTo template.
<br/>
This is now possible as you <b>have</b> to provide the method signature in the top of the template:
<pre>
public String toString() {
TEMPLATE CODE HERE
}
</pre>
The template code must be enclosed in { }.
<h3>Template repository</h3>
The template repository is a new feature in the settings dialog where you can choose a new template from the 4 included
default templates. Additional templates stored in the folder <code><i>IDEA_HOME</i>\plugins\tostring-plugin</code> will
be listed also. Hence you can store your own templates in a text file (.vm, .txt or other) and have it listed here.
This avoids any problem upgrading this plugin to a new version and loosing your customized template.
<h3>Saving templates</h3>
You can save your custom template to a file using the <b>Save template</b> button. The save dialog will default to the
<code><i>IDEA_HOME</i>\plugins\tostring-plugin</code> folder where it is possible to store additional templates to be
listed in the template repository list. Storing templates <b>outside</b> this folder will not list the template in the
list. If the filename has not been given an extension the <code>.vm</code> will be used (.vm = Velocity Macro).
<h3>Annotations</h3>
You can add annotations to your method. There is a default template included that illustrates this.
<br/>Here is a short example:
<pre>
@Override
public String toString() {
...
}
</pre>
<h3>A Velocity Macro Example: The default template</h3>
This is the default velocity template that is used in this plugin:
<pre>
public String toString() {
#if ( $fields.size() > 0 )
#set ( $i = 0 )
return "$classname{" +
#foreach( $field in $fields )
#if ( $i == 0 )
"##
#else
", ##
#end
#if ( $field.objectArray )
$field.name=" + ($field.name == null ? null : Arrays.asList($field.name)) +
#elseif ( $field.string )
$field.name='" + $field.name + "'" +
#else
$field.name=" + $field.name +
#end
#set ( $i = $i + 1 )
#end
"}";
#else
return "$classname{}";
#end
}
</pre>
The macro code can be changed to your needs. Just change the code in the text area. The active template is <b>always</b>
the template that is editable.
<h3>Inspection</h3>
This plugin provides two code inspections:
<ul>
<li/>Class does not override toString() method
<li/>Field not used in toString() method
</ul>
The <b>Field not used in toString() method</b> inspection can be used to identify out of synchronization situations
where you have an existing toString() method that dumps the fields. However some fields have been added to the class
later and these new fields are not dumped in the toString() method.
<br/>
This inspection can use on-the-fly code inspection by enabling it to show errors as warnings. This will highlight
any unused fields on-the-fly in the java editor - also the right gutter will indicate the location of the error using
a yellow marker. This is the same feature as the build in inspection 'Field XXX is never assigned'.
Enabling the on-the-fly feature can be done from setting <b>settings -> Errors -> ToString() Issues</b>.
Also on-the-fly should be enabled from the settings to the plugin.
<p/>
The inspection <b>Class does not override toString() method</b> can be used to identify any classes where you
might have forgotten to add a toString() method. This inspection will use the exclude settings from the plugin
configuration to ignore classes having fields not supposed to be dumped. An additional settings is to exclude certain
classes by using a regular expression matching their classname. As default this is used to exclude any Exception classes.
This setting can be changed from <b>settings -> Errors -> ToString() Issues</b>.
Also on-the-fly should be enabled from the settings to the plugin.
<h3>Keymaps</h3>
You can assign a keymap to this action from the settings. This keymap can be active even if
the action is disabled from the code and editor popup menus. The Generate toString() action is located
under other in the keymap tree.
<h3 id="velocity">Velocity context</h3>
There are now three type of elements avail in the macro language:
<ul>
<li/>Members ($member)
<li/>Fields ($field)
<li/>Methods ($method)
</ul>
<br/>A member is the common for both fields and methods. So using $member.string is the same as $field.string or $method.string.
<br/>A field extends a member. Field have a few extra special field related attributes.
<br/>A method extends a member. Method has a few extra special method related attributes.
<br/>In the table below $member can be used for both $field and $method.
<p/>
The following variables are possible in the Velocity Template (variables are stored in the Velocity Context):
<br/>
<table border="1">
<tr><td width="150"><b>Variable</b></td><td width="100"><b>Returns</b></td><td width="300"><b>Description</b></td></tr>
<tr><td>$classname</td><td>String</td><td>The name of the class (can be the qualified classname if this is selected in the settings)</td></tr>
<tr><td>$FQClassname</td><td>String</td><td><b>@deprecated</b> (use $class.qualifiedName) - The fully qualified name of the class</td></tr>
<tr><td></td><td></td></tr>
<tr><td>$fields</td><td>java.util.List</td><td>List of FieldElement objects</td></tr>
<tr><td>$methods</td><td>java.util.List</td><td>List of MethodElement objects</td></tr>
<tr><td>$members</td><td>java.util.List</td><td>List of both FieldElement and MethodElement objects</td></tr>
<tr><td></td><td></td></tr>
<tr><td>$member</td><td>Element</td><td>The Element object</td></tr>
<tr><td>$member.accessor</td><td>String</td><td>The accessor of the field or method. For field it is the <code>$field.name</code> and for method it is <code>$method.methodName</code></td></tr>
<tr><td>$member.typeName</td><td>String</td><td>The classname of the type (Object, String, List etc.)</td></tr>
<tr><td>$member.typeQualifiedName</td><td>String</td><td>The qualified classname of the type (java.lang.Object, java.lang.String, java.uti.List etc.)</td></tr>
<tr><td>$member.array</td><td>boolean</td><td>Tests if the type is an array type (either a primitive array or object array)?</td></tr>
<tr><td>$member.primitiveArray</td><td>boolean</td><td>Is the type a primitive array type? (int[], short[], float[] etc.)</td></tr>
<tr><td>$member.objectArray</td><td>boolean</td><td>Is the type an Object array type? (Object[], String[] etc.)</td></tr>
<tr><td>$member.stringArray</td><td>boolean</td><td>Is the type an String array type? (String[])</td></tr>
<tr><td>$member.collection</td><td>boolean</td><td>Is the type assignable from java.util.Collection?</td></tr>
<tr><td>$member.list</td><td>boolean</td><td>Is the type assignable from java.util.List?</td></tr>
<tr><td>$member.map</td><td>boolean</td><td>Is the type assignable from java.util.Map?</td></tr>
<tr><td>$member.set</td><td>boolean</td><td>Is the type assignable from java.util.Set?</td></tr>
<tr><td>$member.primitive</td><td>boolean</td><td>Is the type a primitive type? (int, char, float etc.)</td></tr>
<tr><td>$member.modifierStatic</td><td>boolean</td><td>Does the type have a static modifier?</td></tr>
<tr><td>$member.modifierPublic</td><td>boolean</td><td>Does the type have a public modifier?</td></tr>
<tr><td>$member.modifierProtected</td><td>boolean</td><td>Does the type have a protected modifier?</td></tr>
<tr><td>$member.modifierPackageLocal</td><td>boolean</td><td>Does the type have a package-local modifier?</td></tr>
<tr><td>$member.modifierPrivate</td><td>boolean</td><td>Does the type have a private modifier?</td></tr>
<tr><td>$member.modifierFinal</td><td>boolean</td><td>Does the type have a final modifier?</td></tr>
<tr><td>$member.string</td><td>boolean</td><td>Is the type assignable from java.lang.String?</td></tr>
<tr><td>$member.numeric</td><td>boolean</td><td>Is the type either assignable from java.lang.Numeric or a primitive type of byte, short, int, long, float, double?</td></tr>
<tr><td>$member.object</td><td>boolean</td><td>Is the type assignable from java.lang.Object?</td></tr>
<tr><td>$member.date</td><td>boolean</td><td>Is the type assignable from java.util.Date?</td></tr>
<tr><td>$member.calendar</td><td>boolean</td><td>Is the type assignable from java.util.Calendar?</td></tr>
<tr><td>$member.boolean</td><td>boolean</td><td>Is the type assignable from java.lang.Boolean? or a primitive boolean</td></tr>
<tr><td></td><td></td></tr>
<tr><td>$field</td><td>FieldElement</td><td>The FieldElement object</td></tr>
<tr><td>$field.name</td><td>String</td><td>The name of the field</td></tr>
<tr><td>$field.modifierTransient</td><td>boolean</td><td>Does the field have a transient modifier?</td></tr>
<tr><td>$field.modifierVolatile</td><td>boolean</td><td>Does the field have a volatile modifier?</td></tr>
<tr><td>$field.constant</td><td>boolean</td><td>Is the field a constant type? (has static modified and its name is in UPPERCASE only)</td></tr>
<tr><td>$field.matchName(regexp)</td><td>boolean</td><td>Performs a regular expression matching on the fieldname.</td></tr>
<tr><td>$field.enum</td><td>boolean</td><td>Is this field a enum type?</td></tr>
<tr><td></td><td></td></tr>
<tr><td>$method</td><td>MethodElement</td><td>The MethodElement object</td></tr>
<tr><td>$method.name</td><td>String</td><td>Either: 1) The name of the field this getter method covers or 2) the name of the method 'getFoo' when the method does not cover a field as in situation 1</td></tr>
<tr><td>$method.methodName</td><td>String</td><td>The name of the method (getFoo).</td></tr>
<tr><td>$method.fieldName</td><td>String</td><td>The name of the field this getter method covers - null if the method is not a getter for a field</td></tr>
<tr><td>$method.modifierAbstract</td><td>boolean</td><td>Is this method an abstract method?</td></tr>
<tr><td>$method.modifierSynchronized</td><td>boolean</td><td>Is this method a synchronized method?</td></tr>
<tr><td>$method.returnTypeVoid</td><td>boolean</td><td>Is this method a void method (does not return anything) ?</td></tr>
<tr><td>$method.getter</td><td>boolean</td><td>Is this a getter method?</td></tr>
<tr><td>$method.matchName(regexp)</td><td>boolean</td><td>Performs a regular expression matching on the methodname.</td></tr>
<tr><td>$method.deprecated</td><td>boolean</td><td>Is this method deprecated?</td></tr>
<tr><td></td><td></td></tr>
<tr><td>$class</td><td>ClassElement</td><td>The ClassElement object</td></tr>
<tr><td>$class.name</td><td>String</td><td>The name of the class</td></tr>
<tr><td>$class.matchName(regexp)</td><td>boolean</td><td>Performs a regular expression matching on the classname.</td></tr>
<tr><td>$class.qualifiedName</td><td>String</td><td>The fully qualified name of the class</td></tr>
<tr><td>$class.hasSuper</td><td>boolean</td><td>Does the class have a superclass? (extends another class - note extending java.lang.Object is not considered having a superclass)</td></tr>
<tr><td>$class.superName</td><td>String</td><td>The name of the superclass (empty if no superclass)</td></tr>
<tr><td>$class.superQualifiedName</td><td>String</td><td>The fully qualified name of the superclass (empty if no superclass)</td></tr>
<tr><td>$class.implements(interfaceNames)</td><td>boolean</td><td>Tests if the class implements the given interface name. Testing several interfaces names can be done by separating the names with comma. Tests is based using the short classname.</td></tr>
<tr><td>$class.implementNames</td><td>String[]</td><td>Returns the classnames of the interfaces the class implements. An empty array is returned if the class does not implement any interfaces.</td></tr>
<tr><td>$class.extends(classNames)</td><td>boolean</td><td>Tests if the class extends any of the the given class names. Testing several class names can be done by separating the names with comma. Tests is based using the short classname.</td></tr>
<tr><td>$class.exception</td><td>boolean</td><td>Is this class an exception class (extends Throwable)?</td></tr>
<tr><td>$class.deprecated</td><td>boolean</td><td>Is this class deprecated?</td></tr>
<tr><td>$class.enum</td><td>boolean</td><td>Is this class an enum class?</td></tr>
<tr><td>$class.abstract</td><td>boolean</td><td>Is this class abstract?</td></tr>
</table>
<p/>
The following output variables are possible in the Velocity Template (variables are stored in the Velocity Context):
Output parameters will be available for the plugin generate after the Velocity context has been executed and act upon.
<br/>
<table border="1">
<tr><td width="150"><b>Variable</b></td><td width="100"><b>Parameter</b></td><td width="300"><b>Description</b></td></tr>
<tr><td>$autoImportPackages</td><td>String</td><td>Packagenames that should automatically be imported. Use comma to separate packagenames.</td></tr>
</table>
<br/>For an example see the included template "Default using org.apache.commons.lang.ToStringBuilder".
<h3>Logging</h3>
This plugin used log4j for logging. Logging can be enabled by editing the log4j.xml used by IDEA. The file is
in the <i>IDEA_HOME</i>\bin folder. Add the category to this file:
<pre>
&amp;lt;category name=&quot;org.jetbrains.generate.tostring&quot;&amp;gt;
&amp;lt;priority value=&quot;DEBUG&quot;/&amp;gt;
&amp;lt;appender-ref ref=&quot;FILE&quot;/&amp;gt;
&amp;lt;/category&amp;gt;
</pre>
</body>
</html>