You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by pa...@apache.org on 2016/03/02 20:26:29 UTC

[1/2] groovy git commit: More example code to show usage of annotations based on MrHaki's Groovy Goodness blog posts (closes #275, closes #271)

Repository: groovy
Updated Branches:
  refs/heads/GROOVY_2_4_X 3452d2952 -> 730df4f1f


More example code to show usage of annotations based on MrHaki's Groovy Goodness blog posts (closes #275, closes #271)

* More examples for API doc readers to understand how to use the annotations.
* Used HTML entity code for @-symbol instead of enclosing in {@code...} block.


Project: http://git-wip-us.apache.org/repos/asf/groovy/repo
Commit: http://git-wip-us.apache.org/repos/asf/groovy/commit/730df4f1
Tree: http://git-wip-us.apache.org/repos/asf/groovy/tree/730df4f1
Diff: http://git-wip-us.apache.org/repos/asf/groovy/diff/730df4f1

Branch: refs/heads/GROOVY_2_4_X
Commit: 730df4f1f56fdd4cb0c1ca0ab40c0460aaea9aff
Parents: bb33d4c
Author: Hubert Klein Ikkink <h....@gmail.com>
Authored: Wed Mar 2 15:44:52 2016 +0100
Committer: pascalschumacher <pa...@gmx.net>
Committed: Wed Mar 2 20:26:17 2016 +0100

----------------------------------------------------------------------
 .../groovy/transform/AnnotationCollector.java   | 94 ++++++++++++++++++++
 src/main/groovy/transform/BaseScript.java       | 56 ++++++++++++
 .../groovy/transform/EqualsAndHashCode.java     | 25 ++++++
 src/main/groovy/transform/Immutable.java        | 44 +++++++++
 src/main/groovy/transform/ToString.java         | 16 ++--
 src/main/groovy/transform/TupleConstructor.java | 10 +--
 6 files changed, 232 insertions(+), 13 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/groovy/blob/730df4f1/src/main/groovy/transform/AnnotationCollector.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/transform/AnnotationCollector.java b/src/main/groovy/transform/AnnotationCollector.java
index 9a256bf..89b3014 100644
--- a/src/main/groovy/transform/AnnotationCollector.java
+++ b/src/main/groovy/transform/AnnotationCollector.java
@@ -73,6 +73,100 @@ import java.lang.annotation.Target;
  * EqualsAndHashCode.
  * If both ways are combined, then the list overwrites annotation usage.
  * NOTE: The aliasing does not support aliasing of aliased annotations. 
+ * <p>More examples:</p>
+ * <pre>
+ * //--------------------------------------------------------------------------
+ * &#64;AnnotationCollector([EqualsAndHashCode, ToString])
+ * &#64;interface Simple {}
+ *
+ *
+ * &#64;Simple
+ * class User {
+ *     String username
+ *     int age
+ * }
+ *
+ * def user = new User(username: 'mrhaki', age: 39)
+ * assert user.toString() == 'User(mrhaki, 39)'
+ *
+ * // We still have 2 annotations:
+ * assert User.class.annotations.size() == 2
+ *
+ *
+ * // We can use the attributes from the 
+ * // grouped annotations.
+ * &#64;Simple(excludes = 'street') 
+ * class Address {
+ *     String street, town
+ * }
+ *
+ * def address = new Address(street: 'Evergreen Terrace', town: 'Springfield') 
+ * assert address.toString() == 'Address(Springfield)'
+ * </pre>
+ * <pre>
+ * //--------------------------------------------------------------------------
+ * // Use a custom processor to handle attributes.
+ * import org.codehaus.groovy.transform.*
+ * import org.codehaus.groovy.ast.*
+ * import org.codehaus.groovy.control.*
+ *
+ * class SimpleProcessor extends AnnotationCollectorTransform {
+ *
+ *     public List&lt;AnnotationNode&gt; visit(AnnotationNode collector, 
+ *                                       AnnotationNode aliasAnnotationUsage, 
+ *                                       AnnotatedNode aliasAnnotated, 
+ *                                       SourceUnit source) {
+ *
+ *         // Get attributes and attribute value for dontUse.
+ *         def attributes = aliasAnnotationUsage.getMembers()
+ *         def dontUse = attributes.get('dontUse')
+ *         attributes.remove('dontUse')
+ *
+ *         if (dontUse) {
+ *             // Assign value of dontUse to excludes attributes.
+ *             aliasAnnotationUsage.addMember("excludes", dontUse)
+ *         }
+ *
+ *         super.visit(collector, aliasAnnotationUsage, aliasAnnotated, source)
+ *     }
+ *
+ * }
+ *
+ * new GroovyShell(this.class.classLoader).evaluate '''
+ * import groovy.transform.*
+ *
+ * &#64;AnnotationCollector(value = [EqualsAndHashCode, ToString], processor = 'SimpleProcessor')
+ * &#64;interface Simple {}
+ *
+ *
+ * &#64;Simple(dontUse = 'age')
+ * class User {
+ *     String username
+ *     int age
+ * }
+ *
+ * def user = new User(username: 'mrhaki', age: 39)
+ * assert user.toString() == 'User(mrhaki)'
+ * '''
+ * </pre>
+ * <pre>
+ * //--------------------------------------------------------------------------
+ * // Use AnnotationCollector as last annotation to group the
+ * // previous annotations.
+ * &#64;EqualsAndHashCode
+ * &#64;ToString
+ * &#64;AnnotationCollector
+ * &#64;interface Simple {}
+ *
+ *
+ * &#64;Simple
+ * class User {
+ *     String username
+ * }
+ *
+ * def user = new User(username: 'mrhaki')
+ * assert user.toString() == 'User(mrhaki)'
+ * </pre>
  * 
  * @author <a href="mailto:blackdrag@gmx.org">Jochen "blackdrag" Theodorou</a>
  * @see org.codehaus.groovy.transform.AnnotationCollectorTransform

http://git-wip-us.apache.org/repos/asf/groovy/blob/730df4f1/src/main/groovy/transform/BaseScript.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/transform/BaseScript.java b/src/main/groovy/transform/BaseScript.java
index 5eb3a7a..af3e594 100644
--- a/src/main/groovy/transform/BaseScript.java
+++ b/src/main/groovy/transform/BaseScript.java
@@ -84,6 +84,62 @@ import java.lang.annotation.Target;
  * Note that while you can declare arguments for the script body's method, as
  * the AST is currently implemented they are not accessible in the script body code.
  * </p>
+ * <p>More examples:</p>
+ * <pre>
+ * // Simple Car class to save state and distance.
+ * class Car {
+ *     String state
+ *     Long distance = 0
+ * }
+ *
+ * // Custom Script with methods that change the Car's state.
+ * // The Car object is passed via the binding.
+ * abstract class CarScript extends Script {
+ *     def start() {
+ *         this.binding.car.state = 'started'
+ *     }
+ *
+ *     def stop() {
+ *         this.binding.car.state = 'stopped'
+ *     }
+ *
+ *     def drive(distance) {
+ *         this.binding.car.distance += distance
+ *     }
+ * }
+ *
+ *
+ * // Define Car object here, so we can use it in assertions later on.
+ * def car = new Car()
+ * // Add to script binding (CarScript references this.binding.car).
+ * def binding = new Binding(car: car)
+ *
+ * // Configure the GroovyShell.
+ * def shell = new GroovyShell(this.class.classLoader, binding)
+ *
+ * // Simple DSL to start, drive and stop the car.
+ * // The methods are defined in the CarScript class.
+ * def carDsl = '''
+ * start()
+ * drive 20
+ * stop()
+ * '''
+ *
+ *
+ * // Run DSL script.
+ * shell.evaluate """
+ * // Use BaseScript annotation to set script
+ * // for evaluating the DSL.
+ * &#64;groovy.transform.BaseScript CarScript carScript
+ *
+ * $carDsl
+ * """
+ *
+ * // Checks to see that Car object has changed.
+ * assert car.distance == 20
+ * assert car.state == 'stopped'
+ * </pre>
+ * 
  * @author Paul King
  * @author Vladimir Orany
  * @author Jim White

http://git-wip-us.apache.org/repos/asf/groovy/blob/730df4f1/src/main/groovy/transform/EqualsAndHashCode.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/transform/EqualsAndHashCode.java b/src/main/groovy/transform/EqualsAndHashCode.java
index 54315da..533df3b 100644
--- a/src/main/groovy/transform/EqualsAndHashCode.java
+++ b/src/main/groovy/transform/EqualsAndHashCode.java
@@ -192,6 +192,31 @@ import java.lang.annotation.Target;
  * infinite recursion but the algorithm used may not suit your scenario, so use with caution if
  * you have such structures.
  * A future version of this transform may better handle some additional recursive scenarios.
+ * <p>More examples:</p>
+ * <pre>
+ * import groovy.transform.EqualsAndHashCode
+ *
+ * &#64;EqualsAndHashCode(includeFields=true)
+ * class User {
+ *     String name
+ *     boolean active
+ *     List likes
+ *     private int age = 37
+ * }
+ *
+ * def user = new User(name: 'mrhaki', active: false, likes: ['Groovy', 'Java'])
+ * def mrhaki = new User(name: 'mrhaki', likes: ['Groovy', 'Java'])
+ * def hubert = new User(name: 'Hubert Klein Ikkink', likes: ['Groovy', 'Java'])
+ *
+ * assert user == mrhaki
+ * assert mrhaki != hubert
+ *
+ * Set users = new HashSet()
+ * users.add user
+ * users.add mrhaki
+ * users.add hubert
+ * assert users.size() == 2
+ * </pre>
  *
  * @see org.codehaus.groovy.util.HashCodeHelper
  * @author Paul King

http://git-wip-us.apache.org/repos/asf/groovy/blob/730df4f1/src/main/groovy/transform/Immutable.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/transform/Immutable.java b/src/main/groovy/transform/Immutable.java
index 0cbffdc..314abbc 100644
--- a/src/main/groovy/transform/Immutable.java
+++ b/src/main/groovy/transform/Immutable.java
@@ -122,6 +122,50 @@ import java.lang.annotation.Target;
  * has type {@code LinkedHashMap} or if there is a single Map, AbstractMap or HashMap property.
  * </li>
  * </ul>
+ * <p>More examples:</p>
+ --------------------------------------------------------------------------------
+ * <pre>
+ * import groovy.transform.*
+ *
+ * &#64;Canonical
+ * class Building {
+ *     String name
+ *     int floors
+ *     boolean officeSpace
+ * }
+ *
+ * // Constructors are added.
+ * def officeSpace = new Building('Initech office', 1, true)
+ *
+ * // toString() added.
+ * assert officeSpace.toString() == 'Building(Initech office, 1, true)'
+ *
+ * // Default values are used if constructor
+ * // arguments are not assigned.
+ * def theOffice = new Building('Wernham Hogg Paper Company')
+ * assert theOffice.floors == 0
+ * theOffice.officeSpace = true
+ *
+ * def anotherOfficeSpace = new Building(name: 'Initech office', floors: 1, officeSpace: true)
+ *
+ * // equals() method is added.
+ * assert anotherOfficeSpace == officeSpace
+ *
+ * // equals() and hashCode() are added, so duplicate is not in Set.
+ * def offices = [officeSpace, anotherOfficeSpace, theOffice] as Set  
+ * assert offices.size() == 2 
+ * assert offices.name.join(',') == 'Initech office,Wernham Hogg Paper Company'
+ *
+ * &#64;Canonical
+ * &#64;ToString(excludes='age')  // Customize one of the transformations.
+ * class Person {
+ *     String name
+ *     int age
+ * }
+ *
+ * def mrhaki = new Person('mrhaki', 37)
+ * assert mrhaki.toString() == 'Person(mrhaki)'
+ * </pre>
  *
  * @author Paul King
  * @author Andre Steingress

http://git-wip-us.apache.org/repos/asf/groovy/blob/730df4f1/src/main/groovy/transform/ToString.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/transform/ToString.java b/src/main/groovy/transform/ToString.java
index 2d33ff9..4b57b8e 100644
--- a/src/main/groovy/transform/ToString.java
+++ b/src/main/groovy/transform/ToString.java
@@ -134,7 +134,7 @@ import java.lang.annotation.Target;
  * // includeNames to output the names of the properties.
  * import groovy.transform.ToString
  *
- * {@code @ToString(includeNames=true)}
+ * &#64;@ToString(includeNames=true)
  * class Person {
  *     String name
  *     List likes
@@ -150,7 +150,7 @@ import java.lang.annotation.Target;
  * // includeFields to not only output properties, but also field values.
  * import groovy.transform.ToString
  *
- * {@code @ToString(includeNames=true, includeFields=true)}
+ * &#64;ToString(includeNames=true, includeFields=true)
  * class Person {
  *     String name
  *     List likes
@@ -166,14 +166,14 @@ import java.lang.annotation.Target;
  * // Use includeSuper to include properties from super class in output.
  * import groovy.transform.ToString
  *
- * {@code @ToString(includeNames=true)}
+ * &#64;ToString(includeNames=true)
  * class Person {
  *     String name
  *     List likes
  *     private boolean active = false
  * }
  *
- * {@code @ToString(includeSuper=true, includeNames=true)}
+ * &#64;ToString(includeSuper=true, includeNames=true)
  * class Student extends Person {
  *     List courses
  * }
@@ -187,7 +187,7 @@ import java.lang.annotation.Target;
  * // excludes active field and likes property from output
  * import groovy.transform.ToString
  *
- * {@code @ToString(includeNames=true, includeFields=true, excludes='active,likes')}
+ * &#64;ToString(includeNames=true, includeFields=true, excludes='active,likes')
  * class Person {
  *     String name
  *     List likes
@@ -205,7 +205,7 @@ import java.lang.annotation.Target;
  *
  * import groovy.transform.*
  *
- * {@code @ToString(includePackage=false)}
+ * &#64;ToString(includePackage=false)
  * class Course {
  *     String title
  *     Integer maxAttendees
@@ -222,7 +222,7 @@ import java.lang.annotation.Target;
  *
  * import groovy.transform.*
  *
- * {@code @ToString(ignoreNulls=true)}
+ * &#64;ToString(ignoreNulls=true)
  * class Course {
  *     String title
  *     Integer maxAttendees
@@ -239,7 +239,7 @@ import java.lang.annotation.Target;
  *
  * import groovy.transform.*
  *
- * {@code @ToString(cache=true)}
+ * &#64;@ToString(cache=true)
  * class Course {
  *     String title
  *     Integer maxAttendees

http://git-wip-us.apache.org/repos/asf/groovy/blob/730df4f1/src/main/groovy/transform/TupleConstructor.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/transform/TupleConstructor.java b/src/main/groovy/transform/TupleConstructor.java
index 54cbdda..bfb2918 100644
--- a/src/main/groovy/transform/TupleConstructor.java
+++ b/src/main/groovy/transform/TupleConstructor.java
@@ -59,7 +59,7 @@ import java.lang.annotation.Target;
  * //--------------------------------------------------------------------------
  * import groovy.transform.TupleConstructor
  *
- * {@code @TupleConstructor()}
+ * &#64;TupleConstructor()
  * class Person {
  *     String name
  *     List likes
@@ -81,7 +81,7 @@ import java.lang.annotation.Target;
  * // includeFields in the constructor creation.
  * import groovy.transform.TupleConstructor
  *
- * {@code @TupleConstructor(includeFields=true)}
+ * &#64;TupleConstructor(includeFields=true)
  * class Person {
  *     String name
  *     List likes
@@ -102,7 +102,7 @@ import java.lang.annotation.Target;
  * // even if we define our own constructors.
  * import groovy.transform.TupleConstructor
  *
- * {@code @TupleConstructor(force=true)}
+ * &#64;TupleConstructor(force=true)
  * class Person {
  *     String name
  *     List likes
@@ -130,7 +130,7 @@ import java.lang.annotation.Target;
  * // include properties and fields from super class.
  * import groovy.transform.TupleConstructor
  *
- * {@code @TupleConstructor(includeFields=true)}
+ * &#64;TupleConstructor(includeFields=true)
  * class Person {
  *     String name
  *     List likes
@@ -139,7 +139,7 @@ import java.lang.annotation.Target;
  *     boolean isActivated() { active }
  * }
  *
- * {@code @TupleConstructor(callSuper=true, includeSuperProperties=true, includeSuperFields=true)}
+ * &#64;TupleConstructor(callSuper=true, includeSuperProperties=true, includeSuperFields=true)
  * class Student extends Person {
  *     List courses
  * }


[2/2] groovy git commit: More code examples in Javadoc for TupleConstructor and ToString

Posted by pa...@apache.org.
More code examples in Javadoc for TupleConstructor and ToString

Based on discussion on the dev mailing list on how to include code example from the MrHaki Groovy Goodness blog series. Instead of external link the code samples from the blog posts are included in the Javadoc comments.

See also:
* http://groovy.329449.n5.nabble.com/Re-GitHub-groovy-pull-request-Link-to-MrHaki-s-blog-in-TupleConstructor-jav-tp5731382.html


Project: http://git-wip-us.apache.org/repos/asf/groovy/repo
Commit: http://git-wip-us.apache.org/repos/asf/groovy/commit/bb33d4c5
Tree: http://git-wip-us.apache.org/repos/asf/groovy/tree/bb33d4c5
Diff: http://git-wip-us.apache.org/repos/asf/groovy/diff/bb33d4c5

Branch: refs/heads/GROOVY_2_4_X
Commit: bb33d4c5624a1f4384ca40f26eb7e20ed689e0bb
Parents: 3452d29
Author: Hubert Klein Ikkink <h....@gmail.com>
Authored: Wed Mar 2 08:49:13 2016 +0100
Committer: pascalschumacher <pa...@gmx.net>
Committed: Wed Mar 2 20:26:17 2016 +0100

----------------------------------------------------------------------
 src/main/groovy/transform/ToString.java         | 143 +++++++++++++++++++
 src/main/groovy/transform/TupleConstructor.java |  97 +++++++++++++
 2 files changed, 240 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/groovy/blob/bb33d4c5/src/main/groovy/transform/ToString.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/transform/ToString.java b/src/main/groovy/transform/ToString.java
index c5236af..2d33ff9 100644
--- a/src/main/groovy/transform/ToString.java
+++ b/src/main/groovy/transform/ToString.java
@@ -112,6 +112,149 @@ import java.lang.annotation.Target;
  * <pre>
  * my.company.NamedThing(name: Lassie)
  * </pre>
+ * <p>More examples:</p>
+ * <pre>
+ * //--------------------------------------------------------------------------    
+ * // Most simple implementation of toString.
+ * import groovy.transform.ToString
+ *
+ * {@code @ToString}
+ * class Person {
+ *     String name
+ *     List likes
+ *     private boolean active = false
+ * }
+ *
+ * def person = new Person(name: 'mrhaki', likes: ['Groovy', 'Java'])
+ *
+ * assert person.toString() == 'Person(mrhaki, [Groovy, Java])'
+ * </pre>
+ * <pre>
+ * //--------------------------------------------------------------------------    
+ * // includeNames to output the names of the properties.
+ * import groovy.transform.ToString
+ *
+ * {@code @ToString(includeNames=true)}
+ * class Person {
+ *     String name
+ *     List likes
+ *     private boolean active = false
+ * }
+ *
+ * def person = new Person(name: 'mrhaki', likes: ['Groovy', 'Java'])
+ *
+ * assert person.toString() == 'Person(name:mrhaki, likes:[Groovy, Java])'
+ * </pre>
+ * <pre>
+ * //--------------------------------------------------------------------------
+ * // includeFields to not only output properties, but also field values.
+ * import groovy.transform.ToString
+ *
+ * {@code @ToString(includeNames=true, includeFields=true)}
+ * class Person {
+ *     String name
+ *     List likes
+ *     private boolean active = false
+ * }
+ *
+ * def person = new Person(name: 'mrhaki', likes: ['Groovy', 'Java'])
+ *
+ * assert person.toString() == 'Person(name:mrhaki, likes:[Groovy, Java], active:false)'
+ * </pre>
+ * <pre>
+ * //--------------------------------------------------------------------------    
+ * // Use includeSuper to include properties from super class in output.
+ * import groovy.transform.ToString
+ *
+ * {@code @ToString(includeNames=true)}
+ * class Person {
+ *     String name
+ *     List likes
+ *     private boolean active = false
+ * }
+ *
+ * {@code @ToString(includeSuper=true, includeNames=true)}
+ * class Student extends Person {
+ *     List courses
+ * }
+ *
+ * def student = new Student(name: 'mrhaki', likes: ['Groovy', 'Java'], courses: ['IT', 'Business'])
+ *
+ * assert student.toString() == 'Student(courses:[IT, Business], super:Person(name:mrhaki, likes:[Groovy, Java]))'
+ * </pre>
+ * <pre>
+ * //--------------------------------------------------------------------------    
+ * // excludes active field and likes property from output
+ * import groovy.transform.ToString
+ *
+ * {@code @ToString(includeNames=true, includeFields=true, excludes='active,likes')}
+ * class Person {
+ *     String name
+ *     List likes
+ *     private boolean active = false
+ * }
+ *
+ * def person = new Person(name: 'mrhaki', likes: ['Groovy', 'Java'])
+ *
+ * assert person.toString() == 'Person(name:mrhaki)'
+ * </pre>
+ * <pre>
+ * //--------------------------------------------------------------------------
+ * // Don't include the package name in the output
+ * package com.mrhaki.blog.groovy
+ *
+ * import groovy.transform.*
+ *
+ * {@code @ToString(includePackage=false)}
+ * class Course {
+ *     String title
+ *     Integer maxAttendees
+ * }
+ *
+ * final Course course = new Course(title: 'Groovy 101', maxAttendees: 200)
+ *
+ * assert course.toString() == 'Course(Groovy 101, 200)'
+ * </pre>
+ * <pre>
+ * //--------------------------------------------------------------------------
+ * // Don't use properties with null value.
+ * package com.mrhaki.blog.groovy
+ *
+ * import groovy.transform.*
+ *
+ * {@code @ToString(ignoreNulls=true)}
+ * class Course {
+ *     String title
+ *     Integer maxAttendees
+ * }
+ *
+ * final Course course = new Course(title: 'Groovy 101')
+ *
+ * assert course.toString() == 'com.mrhaki.blog.groovy.Course(Groovy 101)'
+ * </pre>
+ * <pre>
+ * //--------------------------------------------------------------------------
+ * // Cache toString() result.
+ * package com.mrhaki.blog.groovy
+ *
+ * import groovy.transform.*
+ *
+ * {@code @ToString(cache=true)}
+ * class Course {
+ *     String title
+ *     Integer maxAttendees
+ * }
+ *
+ * Course course = new Course(title: 'Groovy 101', maxAttendees: 200)
+ *
+ * assert course.toString() == 'com.mrhaki.blog.groovy.Course(Groovy 101, 200)'
+ *
+ * // Value change will not be reflected in toString().
+ * course.title = 'Grails with REST'
+ *
+ * assert course.toString() == 'com.mrhaki.blog.groovy.Course(Groovy 101, 200)'
+ * assert course.title == 'Grails with REST'
+ * </pre> 
  *
  * @author Paul King
  * @author Andre Steingress

http://git-wip-us.apache.org/repos/asf/groovy/blob/bb33d4c5/src/main/groovy/transform/TupleConstructor.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/transform/TupleConstructor.java b/src/main/groovy/transform/TupleConstructor.java
index 949f77d..54cbdda 100644
--- a/src/main/groovy/transform/TupleConstructor.java
+++ b/src/main/groovy/transform/TupleConstructor.java
@@ -54,6 +54,103 @@ import java.lang.annotation.Target;
  * (if {@code includeSuperProperties} is set) followed by the properties of the class followed
  * by the fields of the class (if {@code includeFields} is set). Within each grouping the order
  * is as attributes appear within the respective class.
+ * <p>More examples:</p>
+ * <pre>
+ * //--------------------------------------------------------------------------
+ * import groovy.transform.TupleConstructor
+ *
+ * {@code @TupleConstructor()}
+ * class Person {
+ *     String name
+ *     List likes
+ *     private boolean active = false
+ * }
+ *
+ * def person = new Person('mrhaki', ['Groovy', 'Java'])
+ *
+ * assert person.name == 'mrhaki'
+ * assert person.likes == ['Groovy', 'Java']
+ *
+ * person = new Person('mrhaki')
+ *
+ * assert person.name == 'mrhaki'
+ * assert !person.likes
+ * </pre>
+ * <pre>
+ * //--------------------------------------------------------------------------
+ * // includeFields in the constructor creation.
+ * import groovy.transform.TupleConstructor
+ *
+ * {@code @TupleConstructor(includeFields=true)}
+ * class Person {
+ *     String name
+ *     List likes
+ *     private boolean active = false
+ *
+ *     boolean isActivated() { active }
+ * }
+ *
+ * def person = new Person('mrhaki', ['Groovy', 'Java'], true)
+ *
+ * assert person.name == 'mrhaki'
+ * assert person.likes == ['Groovy', 'Java']
+ * assert person.activated
+ * </pre>
+ * <pre>
+ * //--------------------------------------------------------------------------
+ * // use force attribute to force creation of constructor
+ * // even if we define our own constructors.
+ * import groovy.transform.TupleConstructor
+ *
+ * {@code @TupleConstructor(force=true)}
+ * class Person {
+ *     String name
+ *     List likes
+ *     private boolean active = false
+ *
+ *     Person(boolean active) {
+ *         this.active = active
+ *     }
+ *
+ *     boolean isActivated() { active }
+ * }
+ *
+ * def person = new Person('mrhaki', ['Groovy', 'Java'])
+ *
+ * assert person.name == 'mrhaki'
+ * assert person.likes == ['Groovy', 'Java']
+ * assert !person.activated
+ *
+ * person = new Person(true)
+ *
+ * assert person.activated
+ * </pre>
+ * <pre>
+ * //--------------------------------------------------------------------------
+ * // include properties and fields from super class.
+ * import groovy.transform.TupleConstructor
+ *
+ * {@code @TupleConstructor(includeFields=true)}
+ * class Person {
+ *     String name
+ *     List likes
+ *     private boolean active = false
+ *
+ *     boolean isActivated() { active }
+ * }
+ *
+ * {@code @TupleConstructor(callSuper=true, includeSuperProperties=true, includeSuperFields=true)}
+ * class Student extends Person {
+ *     List courses
+ * }
+ *
+ * def student = new Student('mrhaki', ['Groovy', 'Java'], true, ['IT'])
+ *
+ * assert student.name == 'mrhaki'
+ * assert student.likes == ['Groovy', 'Java']
+ * assert student.activated
+ * assert student.courses == ['IT']
+ * </pre>
  * <p>
  * Limitations:
  * <ul>