http://git-wip-us.apache.org/repos/asf/groovy/blob/d638ca43/src/main/groovy/groovy/transform/ToString.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/transform/ToString.java 
b/src/main/groovy/groovy/transform/ToString.java
new file mode 100644
index 0000000..25fccab
--- /dev/null
+++ b/src/main/groovy/groovy/transform/ToString.java
@@ -0,0 +1,339 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package groovy.transform;
+
+import org.codehaus.groovy.transform.GroovyASTTransformationClass;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Class annotation used to assist in the creation of {@code toString()} 
methods in classes.
+ * The {@code @ToString} annotation instructs the compiler to execute an
+ * AST transformation which adds the necessary toString() method.
+ * <p>
+ * It allows you to write classes in this shortened form:
+ * <pre>
+ * {@code @ToString}
+ * class Customer {
+ *     String first, last
+ *     int age
+ *     Date since = new Date()
+ *     Collection favItems
+ *     private answer = 42
+ * }
+ * println new Customer(first:'Tom', last:'Jones', age:21, favItems:['Books', 
'Games'])
+ * </pre>
+ * Which will have this output:
+ * <pre>
+ * Customer(Tom, Jones, 21, Wed Jul 14 23:57:14 EST 2010, [Books, Games])
+ * </pre>
+ * There are numerous options to customize the format of the generated output.
+ * E.g. if you change the first annotation to:
+ * <pre>
+ * {@code @ToString(includeNames=true)}
+ * </pre>
+ * Then the output will be:
+ * <pre>
+ * Customer(first:Tom, last:Jones, age:21, since:Wed Jul 14 23:57:50 EST 2010, 
favItems:[Books, Games])
+ * </pre>
+ * Or if you change the first annotation to:
+ * <pre>
+ * {@code 
@ToString(includeNames=true,includeFields=true,excludes="since,favItems")}
+ * </pre>
+ * Then the output will be:
+ * <pre>
+ * Customer(first:Tom, last:Jones, age:21, answer:42)
+ * </pre>
+ * If you have this example:
+ * <pre class="groovyTestCase">
+ * import groovy.transform.ToString
+ * {@code @ToString} class NamedThing {
+ *     String name
+ * }
+ * {@code @ToString}(includeNames=true,includeSuper=true)
+ * class AgedThing extends NamedThing {
+ *     int age
+ * }
+ * String agedThingAsString = new AgedThing(name:'Lassie', age:5).toString()
+ * assert agedThingAsString == 'AgedThing(age:5, super:NamedThing(Lassie))'
+ * </pre>
+ * {@code @ToString} can also be used in conjunction with {@code @Canonical} 
and {@code @Immutable}.
+ * <p>
+ * If you want to omit fields or properties referring to <tt>null</tt>, you 
can use the <tt>ignoreNulls</tt> flag:
+ * <pre class="groovyTestCase">
+ * import groovy.transform.ToString
+ * {@code @ToString(ignoreNulls = true)} class NamedThing {
+ *     String name
+ * }
+ * assert new NamedThing(name: null).toString() == 'NamedThing()'
+ * </pre>
+ * <p>
+ * By default the fully-qualified class name is used as part of the generated 
toString.
+ * If you want to exclude the package, you can set the includePackage flag to 
false, e.g.:
+ * <pre>
+ * package my.company
+ * import groovy.transform.ToString
+ * {@code @ToString(includePackage = false)} class NamedThing {
+ *     String name
+ * }
+ * println new NamedThing(name: "Lassie")
+ * </pre>
+ * Which results in:
+ * <pre>
+ * NamedThing(name: Lassie)
+ * </pre>
+ * If the includePackage flag is {@code true} (the default), then the output 
will be:
+ * <pre>
+ * my.company.NamedThing(name: Lassie)
+ * </pre>
+ * <p>More examples:</p>
+ * <pre class="groovyTestCase">
+ * 
//--------------------------------------------------------------------------    
+ * // 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 class="groovyTestCase">
+ * 
//--------------------------------------------------------------------------    
+ * // includeNames to output the names of the properties.
+ * import groovy.transform.ToString
+ *
+ * &#64;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 class="groovyTestCase">
+ * //--------------------------------------------------------------------------
+ * // includeFields to not only output properties, but also field values.
+ * import groovy.transform.ToString
+ *
+ * &#64;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
+ *
+ * &#64;ToString(includeNames=true)
+ * class Person {
+ *     String name
+ *     List likes
+ *     private boolean active = false
+ * }
+ *
+ * &#64;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 class="groovyTestCase">
+ * 
//--------------------------------------------------------------------------    
+ * // excludes active field and likes property from output
+ * import groovy.transform.ToString
+ *
+ * &#64;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 class="groovyTestCase">
+ * //--------------------------------------------------------------------------
+ * // Don't include the package name in the output
+ * package com.mrhaki.blog.groovy
+ *
+ * import groovy.transform.*
+ *
+ * &#64;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 class="groovyTestCase">
+ * //--------------------------------------------------------------------------
+ * // Don't use properties with null value.
+ * package com.mrhaki.blog.groovy
+ *
+ * import groovy.transform.*
+ *
+ * &#64;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 class="groovyTestCase">
+ * //--------------------------------------------------------------------------
+ * // Cache toString() result.
+ * package com.mrhaki.blog.groovy
+ *
+ * import groovy.transform.*
+ *
+ * &#64;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
+ * @see groovy.transform.Immutable
+ * @see groovy.transform.Canonical
+ * @since 1.8.0
+ */
[email protected]
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE})
+@GroovyASTTransformationClass("org.codehaus.groovy.transform.ToStringASTTransformation")
+public @interface ToString {
+    /**
+     * List of field and/or property names to exclude from generated toString.
+     * Must not be used if 'includes' is used. For convenience, a String with 
comma separated names
+     * can be used in addition to an array (using Groovy's literal list 
notation) of String values.
+     */
+    String[] excludes() default {};
+
+    /**
+     * List of field and/or property names to include within the generated 
toString.
+     * Must not be used if 'excludes' is used. For convenience, a String with 
comma separated names
+     * can be used in addition to an array (using Groovy's literal list 
notation) of String values.
+     * The default value is a special marker value indicating that no includes 
are defined; all fields and/or properties
+     * are included if 'includes' remains undefined and 'excludes' is 
explicitly or implicitly an empty list.
+     * The special name 'super' can be used instead of using the 
'includeSuper' flag.
+     */
+    String[] includes() default {Undefined.STRING};
+
+    /**
+     * Whether to include the toString() of super in the generated toString.
+     */
+    boolean includeSuper() default false;
+
+    /**
+     * Whether to include super properties in the generated toString.
+     * @since 2.4.0
+     */
+    boolean includeSuperProperties() default false;
+
+    /**
+     * Whether to include names of properties/fields in the generated toString.
+     */
+    boolean includeNames() default false;
+
+    /**
+     * Include fields as well as properties in the generated toString.
+     */
+    boolean includeFields() default false;
+
+    /**
+     * Don't display any fields or properties with value <tt>null</tt>.
+     */
+    boolean ignoreNulls() default false;
+
+    /**
+     * Whether to include the fully-qualified class name (i.e. including
+     * the package) or just the simple class name in the generated toString.
+     * @since 2.0.6
+     */
+    boolean includePackage() default true;
+
+    /**
+     * Whether to include all properties (as per the JavaBean spec) in the 
generated toString.
+     * Groovy recognizes any field-like definitions with no explicit 
visibility as property definitions
+     * and always includes them in the {@code @ToString} generated toString 
(as well as auto-generating the
+     * appropriate getters and setters). Groovy also treats any explicitly 
created getXxx() or isYyy()
+     * methods as property getters as per the JavaBean specification. Old 
versions of Groovy did not.
+     * So set this flag to false for the old behavior or if you want to 
explicitly exclude such properties.
+     *
+     * @since 2.5.0
+     */
+    boolean allProperties() default true;
+
+    /**
+     * Whether to cache toString() calculations. You should only set this to 
true if
+     * you know the object is immutable (or technically mutable but never 
changed).
+     * @since 2.1.0
+     */
+    boolean cache() default false;
+
+    /**
+     * Whether to include all fields and/or properties in the generated 
toString, including those with names that
+     * are considered internal.
+     *
+     * @since 2.5.0
+     */
+    boolean allNames() default false;
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/d638ca43/src/main/groovy/groovy/transform/Trait.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/transform/Trait.java 
b/src/main/groovy/groovy/transform/Trait.java
new file mode 100644
index 0000000..de88180
--- /dev/null
+++ b/src/main/groovy/groovy/transform/Trait.java
@@ -0,0 +1,38 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package groovy.transform;
+
+import org.codehaus.groovy.transform.GroovyASTTransformationClass;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Used to mark a class as being a trait.
+ *
+ * @since 2.3.0
+ */
[email protected]
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE})
+@GroovyASTTransformationClass("org.codehaus.groovy.transform.trait.TraitASTTransformation")
+public @interface Trait {
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/d638ca43/src/main/groovy/groovy/transform/TupleConstructor.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/transform/TupleConstructor.java 
b/src/main/groovy/groovy/transform/TupleConstructor.java
new file mode 100644
index 0000000..2cd2be7
--- /dev/null
+++ b/src/main/groovy/groovy/transform/TupleConstructor.java
@@ -0,0 +1,278 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package groovy.transform;
+
+import org.codehaus.groovy.transform.GroovyASTTransformationClass;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Class annotation used to assist in the creation of tuple constructors in 
classes.
+ * Should be used with care with other annotations which create constructors - 
see "Known
+ * Limitations" for more details.
+ * <p>
+ * It allows you to write classes in this shortened form:
+ * <pre class="groovyTestCase">
+ * {@code @groovy.transform.TupleConstructor} class Customer {
+ *     String first, last
+ *     int age
+ *     Date since
+ *     Collection favItems
+ * }
+ * def c1 = new Customer(first:'Tom', last:'Jones', age:21, since:new Date(), 
favItems:['Books', 'Games'])
+ * def c2 = new Customer('Tom', 'Jones', 21, new Date(), ['Books', 'Games'])
+ * def c3 = new Customer('Tom', 'Jones')
+ * </pre>
+ * The {@code @TupleConstructor} annotation instructs the compiler to execute 
an
+ * AST transformation which adds the necessary constructor method to your 
class.
+ * <p>
+ * A tuple constructor is created with a parameter for each property (and 
optionally field and
+ * super properties).
+ * A default value is provided (using Java's default values) for all 
parameters in the constructor.
+ * Groovy's normal conventions then allows any number of parameters to be left 
off the end of the parameter list
+ * including all of the parameters - giving a no-arg constructor which can be 
used with the map-style naming conventions.
+ * <p>
+ * The order of parameters is given by the properties of any super classes 
with most super first
+ * (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 class="groovyTestCase">
+ * //--------------------------------------------------------------------------
+ * import groovy.transform.TupleConstructor
+ *
+ * &#64;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 class="groovyTestCase">
+ * //--------------------------------------------------------------------------
+ * // includeFields in the constructor creation.
+ * import groovy.transform.TupleConstructor
+ *
+ * &#64;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 class="groovyTestCase">
+ * //--------------------------------------------------------------------------
+ * // use force attribute to force creation of constructor
+ * // even if we define our own constructors.
+ * import groovy.transform.TupleConstructor
+ *
+ * &#64;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 class="groovyTestCase">
+ * //--------------------------------------------------------------------------
+ * // include properties and fields from super class.
+ * import groovy.transform.TupleConstructor
+ *
+ * &#64;TupleConstructor(includeFields=true)
+ * class Person {
+ *     String name
+ *     List likes
+ *     private boolean active = false
+ *
+ *     boolean isActivated() { active }
+ * }
+ *
+ * &#64;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>
+ * Known Limitations:
+ * <ul>
+ * <li>This AST transform might become a no-op if you are defining your own 
constructors or
+ * combining with other AST transforms which create constructors (e.g. {@code 
@InheritConstructors});
+ * the order in which the particular transforms are processed becomes 
important in that case.
+ * See the {@code force} attribute for further details about customizing this 
behavior.</li>
+ * <li>This AST transform normally uses default parameter values which creates 
multiple constructors under
+ * the covers. You should use with care if you are defining your own 
constructors or
+ * combining with other AST transforms which create constructors (e.g. {@code 
@InheritConstructors});
+ * the order in which the particular transforms are processed becomes 
important in that case.
+ * See the {@code defaults} attribute for further details about customizing 
this behavior.</li>
+ * <li>Groovy's normal map-style naming conventions will not be available if 
the first property (or field)
+ * has type {@code LinkedHashMap} or if there is a single Map, AbstractMap or 
HashMap property (or field)</li>
+ * </ul>
+ *
+ * @since 1.8.0
+ */
[email protected]
+@Retention(RetentionPolicy.SOURCE)
+@Target({ElementType.TYPE})
+@GroovyASTTransformationClass("org.codehaus.groovy.transform.TupleConstructorASTTransformation")
+public @interface TupleConstructor {
+    /**
+     * List of field and/or property names to exclude from the constructor.
+     * Must not be used if 'includes' is used. For convenience, a String with 
comma separated names
+     * can be used in addition to an array (using Groovy's literal list 
notation) of String values.
+     */
+    String[] excludes() default {};
+
+    /**
+     * List of field and/or property names to include within the constructor.
+     * Must not be used if 'excludes' is used. For convenience, a String with 
comma separated names
+     * can be used in addition to an array (using Groovy's literal list 
notation) of String values.
+     * The default value is a special marker value indicating that no includes 
are defined;
+     * all fields are included if includes remains undefined and excludes is 
explicitly or implicitly
+     * an empty list.
+     */
+    String[] includes() default {Undefined.STRING};
+
+    /**
+     * Include fields in the constructor.
+     */
+    boolean includeFields() default false;
+
+    /**
+     * Include properties in the constructor.
+     */
+    boolean includeProperties() default true;
+
+    /**
+     * Include fields from super classes in the constructor.
+     */
+    boolean includeSuperFields() default false;
+
+    /**
+     * Include properties from super classes in the constructor.
+     */
+    boolean includeSuperProperties() default false;
+
+    /**
+     * Should super properties be called within a call to the parent 
constructor
+     * rather than set as properties. Typically used in combination with 
{@code includeSuperProperties}.
+     * Can't be true if using {@code pre} with a {@code super} first statement.
+     */
+    boolean callSuper() default false;
+
+    /**
+     * By default, this annotation becomes a no-op if you provide your own 
constructor.
+     * By setting {@code force=true} then the tuple constructor(s) will be 
added regardless of
+     * whether existing constructors exist. It is up to you to avoid creating 
duplicate constructors.
+     */
+    boolean force() default false;
+
+    /**
+     * Used to set whether default value processing is enabled (the default) 
or disabled.
+     *
+     * By default, every constructor parameter is given a default value. This 
value will
+     * be Java's default for primitive types (zero or false) and null for 
Objects, unless
+     * an initial value is given when declaring the property or field. A 
consequence of
+     * this design is that you can leave off parameters from the right if the 
default
+     * value will suffice. As far as Java interoperability is concerned, 
Groovy will
+     * create additional constructors under the covers representing the 
constructors
+     * with parameters left off, all the way from the constructor with all 
arguments
+     * to the no-arg constructor.
+     *
+     * However, when set to false, default values are not allowed for 
properties and fields.
+     * Only the constructor containing all arguments will be provided.
+     * In particular, a no-arg constructor won't be provided and since this is 
currently
+     * used by Groovy when using named-arguments, the named-argument style 
won't be available.
+     */
+    boolean defaults() default true;
+
+    /**
+     * By default, properties are set directly using their respective field.
+     * By setting {@code useSetters=true} then a writable property will be set 
using its setter.
+     * If turning on this flag we recommend that setters that might be called 
are
+     * made null-safe wrt the parameter.
+     */
+    boolean useSetters() default false;
+
+    /**
+     * Whether to include all fields and/or properties within the constructor, 
including those with names that are
+     * considered internal.
+     *
+     * @since 2.5.0
+     */
+    boolean allNames() default false;
+
+    /**
+     * A Closure containing statements which will be prepended to the 
generated constructor. The first statement
+     * within the Closure may be {@code super(someArgs)} in which case the 
no-arg super constructor won't be called.
+     *
+     * @since 2.5.0
+     */
+    Class pre() default Undefined.CLASS.class;
+
+    /**
+     * A Closure containing statements which will be appended to the end of 
the generated constructor. Useful for validation steps or tweaking the 
populated fields/properties.
+     *
+     * @since 2.5.0
+     */
+    Class post() default Undefined.CLASS.class;
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/d638ca43/src/main/groovy/groovy/transform/TypeChecked.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/transform/TypeChecked.java 
b/src/main/groovy/groovy/transform/TypeChecked.java
new file mode 100644
index 0000000..b902f3f
--- /dev/null
+++ b/src/main/groovy/groovy/transform/TypeChecked.java
@@ -0,0 +1,70 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package groovy.transform;
+
+import org.codehaus.groovy.transform.GroovyASTTransformationClass;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * This will let the Groovy compiler use compile time checks in the style of 
Java.
+ * @author <a href="mailto:[email protected]";>Jochen "blackdrag" Theodorou</a>
+ */
[email protected]
+@Retention(RetentionPolicy.SOURCE)
+@Target({   ElementType.METHOD,         ElementType.TYPE,
+            ElementType.CONSTRUCTOR
+})
+@GroovyASTTransformationClass("org.codehaus.groovy.transform.StaticTypesTransformation")
+public @interface TypeChecked {
+    TypeCheckingMode value() default TypeCheckingMode.PASS;
+
+    /**
+     * The list of (classpath resources) paths to type checking DSL scripts, 
also known
+     * as type checking extensions.
+     * @return an array of paths to groovy scripts that must be on compile 
classpath
+     */
+    String[] extensions() default {};
+
+    /**
+     * This annotation is added by @TypeChecked on methods which have type 
checking turned on.
+     * It is used to embed type information into binary, so that the type 
checker can use this information,
+     * if available, for precompiled classes.
+     */
+
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target(ElementType.METHOD)
+    public @interface TypeCheckingInfo {
+        /**
+         * Returns the type checker information protocol number. This is used 
if the format of the
+         * string used in {@link #inferredType()} changes.
+         * @return the protocol version
+         */
+        int version() default 0;
+
+        /**
+         * An encoded type information.
+         * @return the inferred type
+         */
+        String inferredType();
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/groovy/blob/d638ca43/src/main/groovy/groovy/transform/TypeCheckingMode.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/transform/TypeCheckingMode.java 
b/src/main/groovy/groovy/transform/TypeCheckingMode.java
new file mode 100644
index 0000000..075bd71
--- /dev/null
+++ b/src/main/groovy/groovy/transform/TypeCheckingMode.java
@@ -0,0 +1,31 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package groovy.transform;
+
+/**
+ * This enumeration can be used whenever it is preferred to annotate a class as
+ * {@link TypeChecked} in general, but where only one or more methods are 
"dynamic". This allows the user
+ * to annotate the class itself then annotate only the methods which require 
exclusion.
+ *
+ * @author Cedric Champeau
+ */
+public enum TypeCheckingMode {
+    PASS,
+    SKIP
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/d638ca43/src/main/groovy/groovy/transform/Undefined.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/transform/Undefined.java 
b/src/main/groovy/groovy/transform/Undefined.java
new file mode 100644
index 0000000..35b360d
--- /dev/null
+++ b/src/main/groovy/groovy/transform/Undefined.java
@@ -0,0 +1,37 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package groovy.transform;
+
+import org.codehaus.groovy.ast.ClassNode;
+
+/**
+ * Java doesn't allow you to have null as an attribute value. It wants you to 
indicate what you really
+ * mean by null, so that is what we do here - as ugly as it is.
+ */
+public final class Undefined {
+    private Undefined() {}
+    public static final String STRING = 
"<DummyUndefinedMarkerString-DoNotUse>";
+    public static final class CLASS {}
+    public static final class EXCEPTION extends RuntimeException {
+        private static final long serialVersionUID = -3960500360386581172L;
+    }
+    public static boolean isUndefined(String other) { return 
STRING.equals(other); }
+    public static boolean isUndefined(ClassNode other) { return 
CLASS.class.getName().equals(other.getName()); }
+    public static boolean isUndefinedException(ClassNode other) { return 
EXCEPTION.class.getName().equals(other.getName()); }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/d638ca43/src/main/groovy/groovy/transform/WithReadLock.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/transform/WithReadLock.java 
b/src/main/groovy/groovy/transform/WithReadLock.java
new file mode 100644
index 0000000..475786a
--- /dev/null
+++ b/src/main/groovy/groovy/transform/WithReadLock.java
@@ -0,0 +1,107 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package groovy.transform;
+
+import org.codehaus.groovy.transform.GroovyASTTransformationClass;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * This annotation is used in conjunction with {@link WithWriteLock} to 
support read and write synchronization on a method.
+ * <p>
+ * To use this annotation, declare {@code @WithReadLock} on your method. The 
method may be either an instance method or
+ * a static method. The resulting method will allow multiple threads to read 
the information at the same time.
+ * However, if some other method obtains a write lock, then this method will 
force callers to wait until the write is complete.
+ * <p>
+ * This annotation is a declarative wrapper around the JDK's 
<code>java.util.concurrent.locks.ReentrantReadWriteLock</code>.
+ * Objects containing this annotation will have a ReentrantReadWriteLock field 
named <code>$reentrantLock</code> added to the class,
+ * and method access is protected by the lock. If the method is static then 
the field is static and named <code>$REENTRANTLOCK</code>.
+ * <p>
+ * The annotation takes an optional parameter for the name of the field. This 
field must exist on the class and must be
+ * of type ReentrantReadWriteLock.
+ * <p>
+ * To understand how this annotation works, it is convenient to think in terms 
of the source code it replaces. The following
+ * is a typical usage of this annotation from Groovy:
+ * <pre>
+ * import groovy.transform.*;
+ *
+ * public class ResourceProvider {
+ *
+ *     private final Map&lt;String, String&gt; data = new HashMap&lt;String, 
String&gt;();
+ *
+ *    {@code @WithReadLock}
+ *     public String getResource(String key) throws Exception {
+ *             return data.get(key);
+ *     }
+ *
+ *    {@code @WithWriteLock}
+ *     public void refresh() throws Exception {
+ *             //reload the resources into memory
+ *     }
+ * }
+ * </pre>
+ * As part of the Groovy compiler, code resembling this is produced:
+ * <pre>
+ * import java.util.concurrent.locks.ReentrantReadWriteLock;
+ * import java.util.concurrent.locks.ReadWriteLock;
+ *
+ * public class ResourceProvider {
+ *
+ *     private final ReadWriteLock $reentrantlock = new 
ReentrantReadWriteLock();
+ *     private final Map&lt;String, String&gt; data = new HashMap&lt;String, 
String&gt;();
+ *
+ *     public String getResource(String key) throws Exception {
+ *         $reentrantlock.readLock().lock();
+ *         try {
+ *             return data.get(key);
+ *         } finally {
+ *             $reentrantlock.readLock().unlock();
+ *         }
+ *     }
+ *
+ *     public void refresh() throws Exception {
+ *         $reentrantlock.writeLock().lock();
+ *         try {
+ *             //reload the resources into memory
+ *         } finally {
+ *             $reentrantlock.writeLock().unlock();
+ *         }
+ *     }
+ * }
+ * </pre>
+ *
+ * @author Hamlet D'Arcy
+ * @since 1.8.0
+ */
[email protected]
+@Retention(RetentionPolicy.SOURCE)
+@Target({ElementType.METHOD})
+@GroovyASTTransformationClass("org.codehaus.groovy.transform.ReadWriteLockASTTransformation")
+public @interface WithReadLock {
+    /**
+     * @return if a user specified lock object with the given name should be 
used
+     *      the lock object must exist. If the annotated method is static then 
the 
+     *      lock object must be static. If the annotated method is not static 
then 
+     *      the lock object must not be static. 
+     */
+    String value () default "";
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/d638ca43/src/main/groovy/groovy/transform/WithWriteLock.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/transform/WithWriteLock.java 
b/src/main/groovy/groovy/transform/WithWriteLock.java
new file mode 100644
index 0000000..1eeb7f0
--- /dev/null
+++ b/src/main/groovy/groovy/transform/WithWriteLock.java
@@ -0,0 +1,107 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package groovy.transform;
+
+import org.codehaus.groovy.transform.GroovyASTTransformationClass;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * This annotation is used in conjunction with {@link WithReadLock} to support 
read and write synchronization on a method.
+ * <p>
+ * To use this annotation, declare {@code @WithWriteLock} on your method. The 
method may be either an instance method or
+ * a static method. The resulting method will allow only one thread access to 
the method at a time, and will wait to access
+ * the method until any other read locks have been released.
+ * <p>
+ * This annotation is a declarative wrapper around the JDK's 
<code>java.util.concurrent.locks.ReentrantReadWriteLock</code>.
+ * Objects containing this annotation will have a ReentrantReadWriteLock field 
named <code>$reentrantLock</code> added to the class,
+ * and method access is protected by the lock. If the method is static then 
the field is static and named <code>$REENTRANTLOCK</code>.
+ * <p>
+ * The annotation takes an optional parameter for the name of the field. This 
field must exist on the class and must be
+ * of type ReentrantReadWriteLock.
+ * <p>
+ * To understand how this annotation works, it is convenient to think in terms 
of the source code it replaces. The following
+ * is a typical usage of this annotation from Groovy:
+ * <pre>
+ * import groovy.transform.*;
+ *
+ * public class ResourceProvider {
+ *
+ *     private final Map&lt;String, String&gt; data = new HashMap&lt;String, 
String&gt;();
+ *
+ *    {@code @WithReadLock}
+ *     public String getResource(String key) throws Exception {
+ *             return data.get(key);
+ *     }
+ *
+ *    {@code @WithWriteLock}
+ *     public void refresh() throws Exception {
+ *             //reload the resources into memory
+ *     }
+ * }
+ * </pre>
+ * As part of the Groovy compiler, code resembling this is produced:
+ * <pre>
+ * import java.util.concurrent.locks.ReentrantReadWriteLock;
+ * import java.util.concurrent.locks.ReadWriteLock;
+ *
+ * public class ResourceProvider {
+ *
+ *     private final ReadWriteLock $reentrantlock = new 
ReentrantReadWriteLock();
+ *     private final Map&lt;String, String&gt; data = new HashMap&lt;String, 
String&gt;();
+ *
+ *     public String getResource(String key) throws Exception {
+ *         $reentrantlock.readLock().lock();
+ *         try {
+ *             return data.get(key);
+ *         } finally {
+ *             $reentrantlock.readLock().unlock();
+ *         }
+ *     }
+ *
+ *     public void refresh() throws Exception {
+ *         $reentrantlock.writeLock().lock();
+ *         try {
+ *             //reload the resources into memory
+ *         } finally {
+ *             $reentrantlock.writeLock().unlock();
+ *         }
+ *     }
+ * }
+ * </pre>
+ *
+ * @author Hamlet D'Arcy
+ * @since 1.8.0
+ */
[email protected]
+@Retention(RetentionPolicy.SOURCE)
+@Target({ElementType.METHOD})
+@GroovyASTTransformationClass("org.codehaus.groovy.transform.ReadWriteLockASTTransformation")
+public @interface WithWriteLock {
+    /**
+     * @return if a user specified lock object with the given name should be 
used
+     *      the lock object must exist. If the annotated method is static then 
the 
+     *      lock object must be static. If the annotated method is not static 
then 
+     *      the lock object must not be static. 
+     */
+    String value () default "";
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/d638ca43/src/main/groovy/groovy/transform/builder/Builder.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/transform/builder/Builder.java 
b/src/main/groovy/groovy/transform/builder/Builder.java
new file mode 100644
index 0000000..93b6090
--- /dev/null
+++ b/src/main/groovy/groovy/transform/builder/Builder.java
@@ -0,0 +1,160 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package groovy.transform.builder;
+
+import groovy.transform.Undefined;
+import org.codehaus.groovy.transform.GroovyASTTransformationClass;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import static 
org.codehaus.groovy.transform.BuilderASTTransformation.BuilderStrategy;
+
+/**
+ * The {@code @Builder} AST transformation is used to help write classes that 
can be created using <em>fluent</em> api calls.<!-- -->
+ * The transform supports multiple building strategies to cover a range of 
cases and there are a number
+ * of configuration options to customize the building process.
+ *
+ * In addition, a number of annotation attributes let you customise the 
building process. Not all annotation attributes
+ * are supported by all strategies. See the individual strategy documentation 
for more details.
+ * If you're an AST hacker, you can also define your own strategy class.
+ *
+ * The following strategies are bundled with Groovy:
+ * <ul>
+ *     <li>{@link SimpleStrategy} for creating chained setters</li>
+ *     <li>{@link ExternalStrategy} where you annotate an explicit builder 
class while leaving some buildee class being built untouched</li>
+ *     <li>{@link DefaultStrategy} which creates a nested helper class for 
instance creation</li>
+ *     <li>{@link InitializerStrategy} which creates a nested helper class for 
instance creation which when used with {@code @CompileStatic} allows type-safe 
object creation</li>
+ * </ul>
+ *
+ * Note that Groovy provides other built-in mechanisms for easy creation of 
objects, e.g. the named-args constructor:
+ * <pre>
+ * new Person(firstName: "Robert", lastName: "Lewandowski", age: 21)
+ * </pre>
+ * or the with statement:
+ * <pre>
+ * new Person().with {
+ *     firstName = "Robert"
+ *     lastName = "Lewandowski"
+ *     age = 21
+ * }
+ * </pre>
+ * so you might not find value in using the builder transform at all. But if 
you need Java integration or in some cases improved type safety, the {@code 
@Builder} transform might prove very useful.
+ *
+ * @see groovy.transform.builder.SimpleStrategy
+ * @see groovy.transform.builder.ExternalStrategy
+ * @see groovy.transform.builder.DefaultStrategy
+ * @see groovy.transform.builder.InitializerStrategy
+ */
+@Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ ElementType.TYPE, ElementType.CONSTRUCTOR, ElementType.METHOD})
+@GroovyASTTransformationClass("org.codehaus.groovy.transform.BuilderASTTransformation")
+public @interface Builder {
+
+    /**
+     * A class for which builder methods should be created. It will be an 
error to leave
+     * this attribute with its default value for some strategies.
+     */
+    Class forClass() default Undefined.CLASS.class;
+
+    /**
+     * A class capturing the builder strategy
+     */
+    Class<? extends BuilderStrategy> builderStrategy() default 
DefaultStrategy.class;
+
+    /**
+     * The prefix to use when creating the setter methods.
+     * Default is determined by the strategy which might use "" or "set" but 
you can choose your own, e.g. "with".
+     * If non-empty the first letter of the property will be capitalized 
before being appended to the prefix.
+     */
+    String prefix() default Undefined.STRING;
+
+    /**
+     * For strategies which create a builder helper class, the class name to 
use for the helper class.
+     * Not used if using {@code forClass} since in such cases the builder 
class is explicitly supplied.
+     * Default is determined by the strategy, e.g. <em>TargetClass</em> + 
"Builder" or <em>TargetClass</em> + "Initializer".
+     */
+    String builderClassName() default Undefined.STRING;
+
+    /**
+     * For strategies which create a builder helper class that creates the 
instance, the method name to call to create the instance.
+     * Default is determined by the strategy, e.g. <em>build</em> or 
<em>create</em>.
+     */
+    String buildMethodName() default Undefined.STRING;
+
+    /**
+     * The method name to use for a builder factory method in the source class 
for easy access of the
+     * builder helper class for strategies which create such a helper class.
+     * Must not be used if using {@code forClass}.
+     * Default is determined by the strategy, e.g. <em>builder</em> or 
<em>createInitializer</em>.
+     */
+    String builderMethodName() default Undefined.STRING;
+
+    /**
+     * List of field and/or property names to exclude from generated builder 
methods.
+     * Must not be used if 'includes' is used. For convenience, a String with 
comma separated names
+     * can be used in addition to an array (using Groovy's literal list 
notation) of String values.
+     */
+    String[] excludes() default {};
+
+    /**
+     * List of field and/or property names to include within the generated 
builder methods.
+     * Must not be used if 'excludes' is used. For convenience, a String with 
comma separated names
+     * can be used in addition to an array (using Groovy's literal list 
notation) of String values.
+     * The default value is a special marker value indicating that no includes 
are defined; all fields
+     * are included if includes remains undefined and excludes is explicitly 
or implicitly an empty list.
+     */
+    String[] includes() default {Undefined.STRING};
+
+    /**
+     * By default, properties are set directly using their respective field.
+     * By setting {@code useSetters=true} then a writable property will be set 
using its setter.
+     * If turning on this flag we recommend that setters that might be called 
are
+     * made null-safe wrt the parameter.
+     */
+    boolean useSetters() default false;
+
+    /**
+     * Generate builder methods for properties from super classes.
+     */
+    boolean includeSuperProperties() default false;
+
+    /**
+     * Whether the generated builder should support all properties, including 
those with names that are considered internal.
+     *
+     * @since 2.5.0
+     */
+    boolean allNames() default false;
+
+    /**
+     * Whether to include all properties (as per the JavaBean spec) in the 
generated builder.
+     * Groovy recognizes any field-like definitions with no explicit 
visibility as property definitions
+     * and always includes them in the {@code @Builder} generated classes. 
Groovy also treats any explicitly created getXxx() or isYyy()
+     * methods as property getters as per the JavaBean specification. Old 
versions of Groovy did not.
+     * So set this flag to false for the old behavior or if you want to 
explicitly exclude such properties.
+     * Currently only supported by DefaultStrategy and ExternalStrategy.
+     *
+     * @since 2.5.0
+     */
+    boolean allProperties() default true;
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/d638ca43/src/main/groovy/groovy/transform/builder/DefaultStrategy.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/transform/builder/DefaultStrategy.java 
b/src/main/groovy/groovy/transform/builder/DefaultStrategy.java
new file mode 100644
index 0000000..65d90e3
--- /dev/null
+++ b/src/main/groovy/groovy/transform/builder/DefaultStrategy.java
@@ -0,0 +1,293 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package groovy.transform.builder;
+
+import groovy.transform.Undefined;
+import org.codehaus.groovy.ast.AnnotatedNode;
+import org.codehaus.groovy.ast.AnnotationNode;
+import org.codehaus.groovy.ast.ClassNode;
+import org.codehaus.groovy.ast.ConstructorNode;
+import org.codehaus.groovy.ast.FieldNode;
+import org.codehaus.groovy.ast.InnerClassNode;
+import org.codehaus.groovy.ast.MethodNode;
+import org.codehaus.groovy.ast.Parameter;
+import org.codehaus.groovy.ast.expr.Expression;
+import org.codehaus.groovy.ast.stmt.BlockStatement;
+import org.codehaus.groovy.transform.BuilderASTTransformation;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import static org.codehaus.groovy.ast.ClassHelper.OBJECT_TYPE;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.args;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.assignX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.block;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.callX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.constX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.ctorX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.declS;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.param;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.params;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.propX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.returnS;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.stmt;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.varX;
+import static 
org.codehaus.groovy.ast.tools.GenericsUtils.correctToGenericsSpecRecurse;
+import static org.codehaus.groovy.ast.tools.GenericsUtils.createGenericsSpec;
+import static 
org.codehaus.groovy.ast.tools.GenericsUtils.extractSuperClassGenerics;
+import static org.codehaus.groovy.ast.tools.GenericsUtils.newClass;
+import static 
org.codehaus.groovy.transform.AbstractASTTransformation.getMemberStringValue;
+import static 
org.codehaus.groovy.transform.BuilderASTTransformation.NO_EXCEPTIONS;
+import static org.codehaus.groovy.transform.BuilderASTTransformation.NO_PARAMS;
+import static org.objectweb.asm.Opcodes.ACC_PRIVATE;
+import static org.objectweb.asm.Opcodes.ACC_PUBLIC;
+import static org.objectweb.asm.Opcodes.ACC_STATIC;
+
+/**
+ * This strategy is used with the {@link Builder} AST transform to create a 
builder helper class
+ * for the fluent creation of instances of a specified class.&nbsp;It can be 
used at the class,
+ * static method or constructor levels.
+ *
+ * You use it as follows:
+ * <pre class="groovyTestCase">
+ * import groovy.transform.builder.*
+ *
+ * {@code @Builder}
+ * class Person {
+ *     String firstName
+ *     String lastName
+ *     int age
+ * }
+ * def person = 
Person.builder().firstName("Robert").lastName("Lewandowski").age(21).build()
+ * assert person.firstName == "Robert"
+ * assert person.lastName == "Lewandowski"
+ * assert person.age == 21
+ * </pre>
+ * The {@code prefix} annotation attribute can be used to create setters with 
a different naming convention. The default is the
+ * empty string but you could change that to "set" as follows:
+ * <pre class="groovyTestCase">
+ * {@code @groovy.transform.builder.Builder}(prefix='set')
+ * class Person {
+ *     String firstName
+ *     String lastName
+ *     int age
+ * }
+ * def p2 = 
Person.builder().setFirstName("Robert").setLastName("Lewandowski").setAge(21).build()
+ * </pre>
+ * or using a prefix of 'with' would result in usage like this:
+ * <pre>
+ * def p3 = 
Person.builder().withFirstName("Robert").withLastName("Lewandowski").withAge(21).build()
+ * </pre>
+ *
+ * You can also use the {@code @Builder} annotation in combination with this 
strategy on one or more constructor or
+ * static method instead of or in addition to using it at the class level. An 
example with a constructor follows:
+ * <pre class="groovyTestCase">
+ * import groovy.transform.ToString
+ * import groovy.transform.builder.Builder
+ *
+ * {@code @ToString}
+ * class Person {
+ *     String first, last
+ *     int born
+ *
+ *     {@code @Builder}
+ *     Person(String roleName) {
+ *         if (roleName == 'Jack Sparrow') {
+ *             first = 'Johnny'; last = 'Depp'; born = 1963
+ *         }
+ *     }
+ * }
+ * assert Person.builder().roleName("Jack Sparrow").build().toString() == 
'Person(Johnny, Depp, 1963)'
+ * </pre>
+ * In this case, the parameter(s) for the constructor or static method become 
the properties available
+ * in the builder. For the case of a static method, the return type of the 
static method becomes the
+ * class of the instance being created. For static factory methods, this is 
normally the class containing the
+ * static method but in general it can be any class.
+ *
+ * Note: if using more than one {@code @Builder} annotation, which is only 
possible when using static method
+ * or constructor variants, it is up to you to ensure that any generated 
helper classes or builder methods
+ * have unique names. E.g.&nbsp;we can modify the previous example to have 
three builders. At least two of the builders
+ * in our case will need to set the 'builderClassName' and 'builderMethodName' 
annotation attributes to ensure
+ * we have unique names. This is shown in the following example:
+ * <pre class="groovyTestCase">
+ * import groovy.transform.builder.*
+ * import groovy.transform.*
+ *
+ * {@code @ToString}
+ * {@code @Builder}
+ * class Person {
+ *     String first, last
+ *     int born
+ *
+ *     Person(){} // required to retain no-arg constructor
+ *
+ *     {@code @Builder}(builderClassName='MovieBuilder', 
builderMethodName='byRoleBuilder')
+ *     Person(String roleName) {
+ *         if (roleName == 'Jack Sparrow') {
+ *             this.first = 'Johnny'; this.last = 'Depp'; this.born = 1963
+ *         }
+ *     }
+ *
+ *     {@code @Builder}(builderClassName='SplitBuilder', 
builderMethodName='splitBuilder')
+ *     static Person split(String name, int year) {
+ *         def parts = name.split(' ')
+ *         new Person(first: parts[0], last: parts[1], born: year)
+ *     }
+ * }
+ *
+ * assert Person.splitBuilder().name("Johnny 
Depp").year(1963).build().toString() == 'Person(Johnny, Depp, 1963)'
+ * assert Person.byRoleBuilder().roleName("Jack Sparrow").build().toString() 
== 'Person(Johnny, Depp, 1963)'
+ * assert 
Person.builder().first("Johnny").last('Depp').born(1963).build().toString() == 
'Person(Johnny, Depp, 1963)'
+ * </pre>
+ *
+ * The 'forClass' annotation attribute for the {@code @Builder} transform 
isn't applicable for this strategy.
+ * The 'useSetters' annotation attribute for the {@code @Builder} transform is 
ignored by this strategy which always uses setters.
+ */
+public class DefaultStrategy extends 
BuilderASTTransformation.AbstractBuilderStrategy {
+    private static final Expression DEFAULT_INITIAL_VALUE = null;
+    private static final int PUBLIC_STATIC = ACC_PUBLIC | ACC_STATIC;
+
+    public void build(BuilderASTTransformation transform, AnnotatedNode 
annotatedNode, AnnotationNode anno) {
+        if (unsupportedAttribute(transform, anno, "forClass")) return;
+        if (annotatedNode instanceof ClassNode) {
+            buildClass(transform, (ClassNode) annotatedNode, anno);
+        } else if (annotatedNode instanceof MethodNode) {
+            buildMethod(transform, (MethodNode) annotatedNode, anno);
+        }
+    }
+
+    public void buildMethod(BuilderASTTransformation transform, MethodNode 
mNode, AnnotationNode anno) {
+        if (transform.getMemberValue(anno, "includes") != null || 
transform.getMemberValue(anno, "excludes") != null) {
+            transform.addError("Error during " + 
BuilderASTTransformation.MY_TYPE_NAME +
+                    " processing: includes/excludes only allowed on classes", 
anno);
+        }
+        ClassNode buildee = mNode.getDeclaringClass();
+        ClassNode builder = createBuilder(anno, buildee);
+        createBuilderFactoryMethod(anno, buildee, builder);
+        for (Parameter parameter : mNode.getParameters()) {
+            builder.addField(createFieldCopy(buildee, parameter));
+            builder.addMethod(createBuilderMethodForProp(builder, new 
PropertyInfo(parameter.getName(), parameter.getType()), getPrefix(anno)));
+        }
+        builder.addMethod(createBuildMethodForMethod(anno, buildee, mNode, 
mNode.getParameters()));
+    }
+
+    public void buildClass(BuilderASTTransformation transform, ClassNode 
buildee, AnnotationNode anno) {
+        List<String> excludes = new ArrayList<String>();
+        List<String> includes = new ArrayList<String>();
+        includes.add(Undefined.STRING);
+        if (!getIncludeExclude(transform, anno, buildee, excludes, includes)) 
return;
+        if (includes.size() == 1 && Undefined.isUndefined(includes.get(0))) 
includes = null;
+        ClassNode builder = createBuilder(anno, buildee);
+        createBuilderFactoryMethod(anno, buildee, builder);
+//        List<FieldNode> fields = getFields(transform, anno, buildee);
+        boolean allNames = transform.memberHasValue(anno, "allNames", true);
+        boolean allProperties = !transform.memberHasValue(anno, 
"allProperties", false);
+        List<PropertyInfo> props = getPropertyInfos(transform, anno, buildee, 
excludes, includes, allNames, allProperties);
+        for (PropertyInfo pi : props) {
+            ClassNode correctedType = getCorrectedType(buildee, pi.getType(), 
builder);
+            String fieldName = pi.getName();
+            builder.addField(createFieldCopy(buildee, fieldName, 
correctedType));
+            builder.addMethod(createBuilderMethodForProp(builder, new 
PropertyInfo(fieldName, correctedType), getPrefix(anno)));
+        }
+        builder.addMethod(createBuildMethod(anno, buildee, props));
+    }
+
+    private static ClassNode getCorrectedType(ClassNode buildee, ClassNode 
fieldType, ClassNode declaringClass) {
+        Map<String,ClassNode> genericsSpec = 
createGenericsSpec(declaringClass);
+        extractSuperClassGenerics(fieldType, buildee, genericsSpec);
+        return correctToGenericsSpecRecurse(genericsSpec, fieldType);
+    }
+
+    private static void createBuilderFactoryMethod(AnnotationNode anno, 
ClassNode buildee, ClassNode builder) {
+        buildee.getModule().addClass(builder);
+        buildee.addMethod(createBuilderMethod(anno, builder));
+    }
+
+    private static ClassNode createBuilder(AnnotationNode anno, ClassNode 
buildee) {
+        return new InnerClassNode(buildee, getFullName(anno, buildee), 
PUBLIC_STATIC, OBJECT_TYPE);
+    }
+
+    private static String getFullName(AnnotationNode anno, ClassNode buildee) {
+        String builderClassName = getMemberStringValue(anno, 
"builderClassName", buildee.getNameWithoutPackage() + "Builder");
+        return buildee.getName() + "$" + builderClassName;
+    }
+
+    private static String getPrefix(AnnotationNode anno) {
+        return getMemberStringValue(anno, "prefix", "");
+    }
+
+    private static MethodNode createBuildMethodForMethod(AnnotationNode anno, 
ClassNode buildee, MethodNode mNode, Parameter[] params) {
+        String buildMethodName = getMemberStringValue(anno, "buildMethodName", 
"build");
+        final BlockStatement body = new BlockStatement();
+        ClassNode returnType;
+        if (mNode instanceof ConstructorNode) {
+            returnType = newClass(buildee);
+            
body.addStatement(returnS(ctorX(newClass(mNode.getDeclaringClass()), 
args(params))));
+        } else {
+            
body.addStatement(returnS(callX(newClass(mNode.getDeclaringClass()), 
mNode.getName(), args(params))));
+            returnType = newClass(mNode.getReturnType());
+        }
+        return new MethodNode(buildMethodName, ACC_PUBLIC, returnType, 
NO_PARAMS, NO_EXCEPTIONS, body);
+    }
+
+    private static MethodNode createBuilderMethod(AnnotationNode anno, 
ClassNode builder) {
+        String builderMethodName = getMemberStringValue(anno, 
"builderMethodName", "builder");
+        final BlockStatement body = new BlockStatement();
+        body.addStatement(returnS(ctorX(builder)));
+        return new MethodNode(builderMethodName, PUBLIC_STATIC, builder, 
NO_PARAMS, NO_EXCEPTIONS, body);
+    }
+
+    private static MethodNode createBuildMethod(AnnotationNode anno, ClassNode 
buildee, List<PropertyInfo> props) {
+        String buildMethodName = getMemberStringValue(anno, "buildMethodName", 
"build");
+        final BlockStatement body = new BlockStatement();
+        body.addStatement(returnS(initializeInstance(buildee, props, body)));
+        return new MethodNode(buildMethodName, ACC_PUBLIC, newClass(buildee), 
NO_PARAMS, NO_EXCEPTIONS, body);
+    }
+
+    private MethodNode createBuilderMethodForProp(ClassNode builder, 
PropertyInfo pinfo, String prefix) {
+        ClassNode fieldType = pinfo.getType();
+        String fieldName = pinfo.getName();
+        String setterName = getSetterName(prefix, fieldName);
+        return new MethodNode(setterName, ACC_PUBLIC, newClass(builder), 
params(param(fieldType, fieldName)), NO_EXCEPTIONS, block(
+                stmt(assignX(propX(varX("this"), constX(fieldName)), 
varX(fieldName, fieldType))),
+                returnS(varX("this", builder))
+        ));
+    }
+
+    private static FieldNode createFieldCopy(ClassNode buildee, Parameter 
param) {
+        Map<String,ClassNode> genericsSpec = createGenericsSpec(buildee);
+        extractSuperClassGenerics(param.getType(), buildee, genericsSpec);
+        ClassNode correctedParamType = 
correctToGenericsSpecRecurse(genericsSpec, param.getType());
+        return new FieldNode(param.getName(), ACC_PRIVATE, correctedParamType, 
buildee, param.getInitialExpression());
+    }
+
+    private static FieldNode createFieldCopy(ClassNode buildee, String 
fieldName, ClassNode fieldType) {
+        return new FieldNode(fieldName, ACC_PRIVATE, fieldType, buildee, 
DEFAULT_INITIAL_VALUE);
+    }
+
+    private static Expression initializeInstance(ClassNode buildee, 
List<PropertyInfo> props, BlockStatement body) {
+        Expression instance = varX("_the" + buildee.getNameWithoutPackage(), 
buildee);
+        body.addStatement(declS(instance, ctorX(buildee)));
+        for (PropertyInfo pi : props) {
+            body.addStatement(stmt(assignX(propX(instance, pi.getName()), 
varX(pi.getName(), pi.getType()))));
+        }
+        return instance;
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/d638ca43/src/main/groovy/groovy/transform/builder/ExternalStrategy.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/transform/builder/ExternalStrategy.java 
b/src/main/groovy/groovy/transform/builder/ExternalStrategy.java
new file mode 100644
index 0000000..c482bef
--- /dev/null
+++ b/src/main/groovy/groovy/transform/builder/ExternalStrategy.java
@@ -0,0 +1,158 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package groovy.transform.builder;
+
+import groovy.transform.Undefined;
+import org.codehaus.groovy.ast.AnnotatedNode;
+import org.codehaus.groovy.ast.AnnotationNode;
+import org.codehaus.groovy.ast.ClassNode;
+import org.codehaus.groovy.ast.FieldNode;
+import org.codehaus.groovy.ast.MethodNode;
+import org.codehaus.groovy.ast.expr.Expression;
+import org.codehaus.groovy.ast.stmt.BlockStatement;
+import org.codehaus.groovy.transform.BuilderASTTransformation;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.codehaus.groovy.ast.tools.GeneralUtils.assignX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.block;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.constX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.ctorX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.declS;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.param;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.params;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.propX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.returnS;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.stmt;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.varX;
+import static org.codehaus.groovy.ast.tools.GenericsUtils.newClass;
+import static 
org.codehaus.groovy.transform.BuilderASTTransformation.MY_TYPE_NAME;
+import static 
org.codehaus.groovy.transform.BuilderASTTransformation.NO_EXCEPTIONS;
+import static org.codehaus.groovy.transform.BuilderASTTransformation.NO_PARAMS;
+import static org.objectweb.asm.Opcodes.ACC_PRIVATE;
+import static org.objectweb.asm.Opcodes.ACC_PUBLIC;
+
+/**
+ * This strategy is used with the {@link Builder} AST transform to populate a 
builder helper class
+ * so that it can be used for the fluent creation of instances of a specified 
class.&nbsp;The specified class is not modified in any way and may be a Java 
class.
+ *
+ * You use it by creating and annotating an explicit builder class which will 
be filled in by during
+ * annotation processing with the appropriate build method and setters. An 
example is shown here:
+ * <pre class="groovyTestCase">
+ * import groovy.transform.builder.*
+ *
+ * class Person {
+ *     String firstName
+ *     String lastName
+ * }
+ *
+ * {@code @Builder}(builderStrategy=ExternalStrategy, forClass=Person)
+ * class PersonBuilder { }
+ *
+ * def person = new 
PersonBuilder().firstName("Robert").lastName("Lewandowski").build()
+ * assert person.firstName == "Robert"
+ * assert person.lastName == "Lewandowski"
+ * </pre>
+ * The {@code prefix} annotation attribute, which defaults to the empty String 
for this strategy, can be used to create setters with a different naming 
convention, e.g. with
+ * the {@code prefix} changed to 'set', you would use your setters as follows:
+ * <pre>
+ * def p1 = new 
PersonBuilder().setFirstName("Robert").setLastName("Lewandowski").setAge(21).build()
+ * </pre>
+ * or using a prefix of 'with':
+ * <pre>
+ * def p2 = new 
PersonBuilder().withFirstName("Robert").withLastName("Lewandowski").withAge(21).build()
+ * </pre>
+ *
+ * The properties to use can be filtered using either the 'includes' or 
'excludes' annotation attributes for {@code @Builder}.
+ * The {@code @Builder} 'buildMethodName' annotation attribute can be used for 
configuring the build method's name, default "build".
+ *
+ * The {@code @Builder} 'builderMethodName' and 'builderClassName' annotation 
attributes aren't applicable for this strategy.
+ * The {@code @Builder} 'useSetters' annotation attribute is ignored by this 
strategy which always uses setters.
+ */
+public class ExternalStrategy extends 
BuilderASTTransformation.AbstractBuilderStrategy {
+    private static final Expression DEFAULT_INITIAL_VALUE = null;
+
+    public void build(BuilderASTTransformation transform, AnnotatedNode 
annotatedNode, AnnotationNode anno) {
+        if (!(annotatedNode instanceof ClassNode)) {
+            transform.addError("Error during " + 
BuilderASTTransformation.MY_TYPE_NAME + " processing: building for " +
+                    annotatedNode.getClass().getSimpleName() + " not supported 
by " + getClass().getSimpleName(), annotatedNode);
+            return;
+        }
+        ClassNode builder = (ClassNode) annotatedNode;
+        String prefix = transform.getMemberStringValue(anno, "prefix", "");
+        ClassNode buildee = transform.getMemberClassValue(anno, "forClass");
+        if (buildee == null) {
+            transform.addError("Error during " + MY_TYPE_NAME + " processing: 
'forClass' must be specified for " + getClass().getName(), anno);
+            return;
+        }
+        List<String> excludes = new ArrayList<String>();
+        List<String> includes = new ArrayList<String>();
+        includes.add(Undefined.STRING);
+        if (!getIncludeExclude(transform, anno, buildee, excludes, includes)) 
return;
+        if (includes.size() == 1 && Undefined.isUndefined(includes.get(0))) 
includes = null;
+        if (unsupportedAttribute(transform, anno, "builderClassName")) return;
+        if (unsupportedAttribute(transform, anno, "builderMethodName")) return;
+        boolean allNames = transform.memberHasValue(anno, "allNames", true);
+        boolean allProperties = !transform.memberHasValue(anno, 
"allProperties", false);
+        List<PropertyInfo> props = getPropertyInfos(transform, anno, buildee, 
excludes, includes, allNames, allProperties);
+        if (includes != null) {
+            for (String name : includes) {
+                checkKnownProperty(transform, anno, name, props);
+            }
+        }
+        for (PropertyInfo prop : props) {
+            builder.addField(createFieldCopy(builder, prop));
+            builder.addMethod(createBuilderMethodForField(builder, prop, 
prefix));
+        }
+        builder.addMethod(createBuildMethod(transform, anno, buildee, props));
+    }
+
+    private static MethodNode createBuildMethod(BuilderASTTransformation 
transform, AnnotationNode anno, ClassNode sourceClass, List<PropertyInfo> 
fields) {
+        String buildMethodName = transform.getMemberStringValue(anno, 
"buildMethodName", "build");
+        final BlockStatement body = new BlockStatement();
+        Expression sourceClassInstance = initializeInstance(sourceClass, 
fields, body);
+        body.addStatement(returnS(sourceClassInstance));
+        return new MethodNode(buildMethodName, ACC_PUBLIC, sourceClass, 
NO_PARAMS, NO_EXCEPTIONS, body);
+    }
+
+    private MethodNode createBuilderMethodForField(ClassNode builderClass, 
PropertyInfo prop, String prefix) {
+        String propName = prop.getName().equals("class") ? "clazz" : 
prop.getName();
+        String setterName = getSetterName(prefix, prop.getName());
+        return new MethodNode(setterName, ACC_PUBLIC, newClass(builderClass), 
params(param(newClass(prop.getType()), propName)), NO_EXCEPTIONS, block(
+                stmt(assignX(propX(varX("this"), constX(propName)), 
varX(propName))),
+                returnS(varX("this", newClass(builderClass)))
+        ));
+    }
+
+    private static FieldNode createFieldCopy(ClassNode builderClass, 
PropertyInfo prop) {
+        String propName = prop.getName();
+        return new FieldNode(propName.equals("class") ? "clazz" : propName, 
ACC_PRIVATE, newClass(prop.getType()), builderClass, DEFAULT_INITIAL_VALUE);
+    }
+
+    private static Expression initializeInstance(ClassNode sourceClass, 
List<PropertyInfo> props, BlockStatement body) {
+        Expression instance = varX("_the" + 
sourceClass.getNameWithoutPackage(), sourceClass);
+        body.addStatement(declS(instance, ctorX(sourceClass)));
+        for (PropertyInfo prop : props) {
+            body.addStatement(stmt(assignX(propX(instance, prop.getName()), 
varX(prop.getName().equals("class") ? "clazz" : prop.getName(), 
newClass(prop.getType())))));
+        }
+        return instance;
+    }
+
+}

Reply via email to