groovy-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From sun...@apache.org
Subject [30/49] groovy git commit: Move source files to proper packages
Date Wed, 20 Dec 2017 03:47:40 GMT
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
+ */
+@java.lang.annotation.Documented
+@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
+ */
+@java.lang.annotation.Documented
+@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
+ */
+@java.lang.annotation.Documented
+@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:blackdrag@gmx.org">Jochen "blackdrag" Theodorou</a>
+ */
+@java.lang.annotation.Documented
+@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
+ */
+@java.lang.annotation.Documented
+@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
+ */
+@java.lang.annotation.Documented
+@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;
+    }
+
+}


Mime
View raw message