groovy-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From sun...@apache.org
Subject [33/49] groovy git commit: Move source files to proper packages
Date Wed, 20 Dec 2017 03:47:43 GMT
http://git-wip-us.apache.org/repos/asf/groovy/blob/d638ca43/src/main/groovy/groovy/lang/SpreadListEvaluatingException.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/SpreadListEvaluatingException.java b/src/main/groovy/groovy/lang/SpreadListEvaluatingException.java
new file mode 100644
index 0000000..b6de965
--- /dev/null
+++ b/src/main/groovy/groovy/lang/SpreadListEvaluatingException.java
@@ -0,0 +1,25 @@
+/*
+ *  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.lang;
+
+public class SpreadListEvaluatingException extends GroovyRuntimeException {
+    public SpreadListEvaluatingException(String message) {
+        super(message);
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/d638ca43/src/main/groovy/groovy/lang/SpreadMap.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/SpreadMap.java b/src/main/groovy/groovy/lang/SpreadMap.java
new file mode 100644
index 0000000..7ba9e4f
--- /dev/null
+++ b/src/main/groovy/groovy/lang/SpreadMap.java
@@ -0,0 +1,120 @@
+/*
+ *  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.lang;
+
+import org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Helper to turn a list with an even number of elements into a Map.
+ * 
+ * @author Pilho Kim
+ * @author Tim Tiemens
+ */
+public class SpreadMap extends HashMap {
+    private int hashCode;
+
+    public SpreadMap(Object[] values) {
+        int i = 0;
+        while (i < values.length) {
+            super.put(values[i++], values[i++]);
+        }
+    }
+
+    public SpreadMap(Map map) {
+        super(map);
+    }
+
+    /**
+     * @since 1.8.0
+     * @param list the list to make spreadable
+     */
+    public SpreadMap(List list) {
+        this(list.toArray());
+    }
+
+    public Object put(Object key, Object value) {
+        throw new RuntimeException("SpreadMap: " + this + " is an immutable map, and so ("
+                                   + key + ": " + value + ") cannot be added.");
+    }
+
+    public Object remove(Object key) {
+        throw new RuntimeException("SpreadMap: " + this + " is an immutable map, and so the key ("
+                                   + key + ") cannot be deleted.");
+    }
+
+    public void putAll(Map t) {
+        throw new RuntimeException("SpreadMap: " + this + " is an immutable map, and so the map ("
+                                   + t + ") cannot be put in this spreadMap.");
+    }
+
+    public boolean equals(Object that) {
+        if (that instanceof SpreadMap) {
+            return equals((SpreadMap) that);
+        }
+        return false;
+    }
+
+    public boolean equals(SpreadMap that) {
+        if (that == null) return false;        
+
+        if (size() == that.size()) {
+            for (Object key : keySet()) {
+                if (!DefaultTypeTransformation.compareEqual(get(key), that.get(key))) {
+                    return false;
+                }
+            }
+            return true;
+        }
+        return false;
+    }
+
+    public int hashCode() {
+        if (hashCode == 0) {
+            for (Object key : keySet()) {
+                int hash = (key != null) ? key.hashCode() : 0xbabe;
+                hashCode ^= hash;
+            }
+        }
+        return hashCode;
+    }
+
+    /**
+     * @return the string expression of <code>this</code>
+     */
+    public String toString() {
+        if (isEmpty()) {
+            return "*:[:]";
+        }
+        StringBuilder sb = new StringBuilder("*:[");
+        Iterator iter = keySet().iterator();
+        while (iter.hasNext()) {
+            Object key = iter.next();
+            sb.append(key).append(":").append(get(key));
+            if (iter.hasNext())
+                sb.append(", ");
+        }
+        sb.append("]");
+        return sb.toString();
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/d638ca43/src/main/groovy/groovy/lang/SpreadMapEvaluatingException.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/SpreadMapEvaluatingException.java b/src/main/groovy/groovy/lang/SpreadMapEvaluatingException.java
new file mode 100644
index 0000000..408a223
--- /dev/null
+++ b/src/main/groovy/groovy/lang/SpreadMapEvaluatingException.java
@@ -0,0 +1,25 @@
+/*
+ *  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.lang;
+
+public class SpreadMapEvaluatingException extends GroovyRuntimeException {
+    public SpreadMapEvaluatingException(String message) {
+        super(message);
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/d638ca43/src/main/groovy/groovy/lang/StringWriterIOException.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/StringWriterIOException.java b/src/main/groovy/groovy/lang/StringWriterIOException.java
new file mode 100644
index 0000000..0372399
--- /dev/null
+++ b/src/main/groovy/groovy/lang/StringWriterIOException.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.lang;
+
+import java.io.IOException;
+
+/**
+ * An IO exception occurred trying to append to a StringWriter which should never happen.
+ * 
+ * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
+ */
+public class StringWriterIOException extends RuntimeException {
+
+    public StringWriterIOException(IOException e) {
+        super(e);
+    }
+
+    public IOException getIOException() {
+        return (IOException) getCause();
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/d638ca43/src/main/groovy/groovy/lang/TracingInterceptor.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/TracingInterceptor.java b/src/main/groovy/groovy/lang/TracingInterceptor.java
new file mode 100644
index 0000000..f67de11
--- /dev/null
+++ b/src/main/groovy/groovy/lang/TracingInterceptor.java
@@ -0,0 +1,120 @@
+/*
+ *  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.lang;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.Writer;
+
+/*
+ * This {@link Interceptor} traces method calls on the proxied object to a log. 
+ * By default, the log is simply <pre>System.out</pre>; however, that can be 
+ * changed with the <pre>setWriter(Writer)</pre> method.
+ * <p>
+ * A message will be written to output before a method is invoked and after a method
+ * is invoked. If methods are nested, and invoke one another, then indentation 
+ * of two spaces is written.
+ * <p>
+ * Here is an example usage on the ArrayList object: <br>
+ * <pre class="groovyTestCase">
+ * def proxy = ProxyMetaClass.getInstance(ArrayList.class)
+ * proxy.interceptor = new TracingInterceptor()
+ * proxy.use {
+ *     def list = [1, 2, 3]
+ *     assert 3 == list.size()
+ *     assert list.contains(1)
+ * }
+ * </pre>
+ * Running this code produces this output: 
+ * <pre>
+ * before java.util.ArrayList.size()
+ * after  java.util.ArrayList.size()
+ * before java.util.ArrayList.contains(java.lang.Integer)
+ * after  java.util.ArrayList.contains(java.lang.Integer)
+ * </pre>
+ */
+public class TracingInterceptor implements Interceptor {
+
+    protected Writer writer = new PrintWriter(System.out);
+    private int indent = 0;
+
+    /**
+    * Returns the writer associated with this interceptor. 
+    */ 
+    public Writer getWriter() {
+        return writer;
+    }
+
+    /**
+    * Changes the writer associated with this interceptor. 
+    */ 
+    public void setWriter(Writer writer) {
+        this.writer = writer;
+    }
+
+    public Object beforeInvoke(Object object, String methodName, Object[] arguments) {
+        write(object, methodName, arguments, "before");
+        indent++ ;
+        return null;
+    }
+
+    public Object afterInvoke(Object object, String methodName, Object[] arguments, Object result) {
+        indent--;
+        write(object, methodName, arguments, "after ");
+        return result;
+    }
+
+    public boolean doInvoke() {
+        return true;
+    }
+    private String indent(){
+        StringBuilder result = new StringBuilder();
+        for (int i=0; i<indent;i++){
+            result.append("  ");
+        }
+        return result.toString();
+    }
+
+    protected void write(Object object, String methodName, Object[] arguments, final String origin) {
+        try {
+            writer.write(indent());
+            writer.write(origin);
+            writer.write(" ");
+            Class theClass = object instanceof Class ? (Class) object: object.getClass();
+            writeInfo(theClass, methodName, arguments);
+            writer.write("\n");
+            writer.flush();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+    protected void writeInfo(final Class aClass, String methodName, Object[] arguments) throws IOException {
+        writer.write(aClass.getName());
+        writer.write(".");
+        writer.write(methodName);
+        writer.write("(");
+        for (int i = 0; i < arguments.length; i++) {
+            if (i > 0) writer.write(", ");
+            Object argument = arguments[i];
+            writer.write(argument.getClass().getName());
+        }
+        writer.write(")");
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/d638ca43/src/main/groovy/groovy/lang/TrampolineClosure.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/TrampolineClosure.java b/src/main/groovy/groovy/lang/TrampolineClosure.java
new file mode 100644
index 0000000..ed68f00
--- /dev/null
+++ b/src/main/groovy/groovy/lang/TrampolineClosure.java
@@ -0,0 +1,111 @@
+/*
+ *  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.lang;
+
+/**
+ * A TrampolineClosure wraps a closure that needs to be executed on a functional trampoline.
+ * Upon calling, a TrampolineClosure will call the original closure waiting for its result.
+ * If the outcome of the call is another instance of a TrampolineClosure, created perhaps as a result to a call to the TrampolineClosure.trampoline()
+ * method, the TrampolineClosure will again be invoked. This repetitive invocation of returned TrampolineClosure instances will continue
+ * until a value other than TrampolineClosure is returned.
+ * That value will become the final result of the trampoline.
+ *
+ * @author Vaclav Pech
+ */
+final class TrampolineClosure<V> extends Closure<V> {
+
+    private final Closure<V> original;
+
+    TrampolineClosure(final Closure<V> original) {
+        super(original.getOwner(), original.getDelegate());
+        this.original = original;
+    }
+
+    /**
+     * Delegates to the wrapped closure
+     */
+    @Override
+    public int getMaximumNumberOfParameters() {
+        return original.maximumNumberOfParameters;
+    }
+
+    /**
+     * Delegates to the wrapped closure
+     */
+    @Override
+    public Class[] getParameterTypes() {
+        return original.parameterTypes;
+    }
+
+    /**
+     * Starts the trampoline loop and calls the wrapped closure as the first step.
+     * @return The final result of the trampoline
+     */
+    @Override
+    public V call() {
+        return loop(original.call());
+    }
+
+    /**
+     * Starts the trampoline loop and calls the wrapped closure as the first step.
+     * @return The final result of the trampoline
+     */
+    @Override
+    public V call(final Object arguments) {
+        return loop(original.call(arguments));
+    }
+
+    /**
+     * Starts the trampoline loop and calls the wrapped closure as the first step.
+     * @return The final result of the trampoline
+     */
+    @Override
+    public V call(final Object... args) {
+        return loop(original.call(args));
+    }
+
+    private V loop(final Object lastResult) {
+        Object result = lastResult;
+
+        for (;;) {
+            if (result instanceof TrampolineClosure) {
+                result = ((TrampolineClosure)result).original.call();
+            } else return (V) result;
+        }
+    }
+
+    /**
+     * Builds a trampolined variant of the current closure.
+     * @param args Parameters to curry to the underlying closure.
+     * @return An instance of TrampolineClosure wrapping the original closure after currying.
+     */
+    @Override
+   public Closure<V> trampoline(final Object... args) {
+        return new TrampolineClosure<V>(original.curry(args));
+    }
+
+    /**
+     * Returns itself, since it is a good enough trampolined variant of the current closure.
+     * @return An instance of TrampolineClosure wrapping the original closure.
+     */
+    @Override
+    public Closure<V> trampoline() {
+        return this;
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/d638ca43/src/main/groovy/groovy/lang/Tuple.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/Tuple.java b/src/main/groovy/groovy/lang/Tuple.java
new file mode 100644
index 0000000..036d13e
--- /dev/null
+++ b/src/main/groovy/groovy/lang/Tuple.java
@@ -0,0 +1,85 @@
+/*
+ *  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.lang;
+
+import org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation;
+
+import java.io.Serializable;
+import java.util.AbstractList;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Represents a list of Objects.
+ * 
+ * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
+ */
+public class Tuple<E> extends AbstractList<E> implements Serializable {
+    private static final long serialVersionUID = -6707770506387821031L;
+    private final E[] contents;
+
+    public Tuple(E... contents) {
+        if (contents == null) throw new NullPointerException();
+        this.contents = contents;
+    }
+
+    @Override
+    public E get(int index) {
+        return contents[index];
+    }
+
+    @Override
+    public int size() {
+        return contents.length;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public List<E> subList(int fromIndex, int toIndex) {
+        int size = toIndex - fromIndex;
+        E[] newContent = (E[]) new Object[size];
+        System.arraycopy(contents, fromIndex, newContent, 0, size);
+        return new Tuple<>(newContent);
+    }
+
+    public Tuple<E> subTuple(int fromIndex, int toIndex) {
+        return (Tuple<E>) subList(fromIndex, toIndex);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || !(o instanceof Tuple)) return false;
+
+        Tuple that = (Tuple) o;
+        int size = size();
+        if (size != that.size()) return false;
+        for (int i = 0; i < size; i++) {
+            if (!DefaultTypeTransformation.compareEqual(get(i), that.get(i))) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(contents);
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/d638ca43/src/main/groovy/groovy/lang/Tuple1.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/Tuple1.java b/src/main/groovy/groovy/lang/Tuple1.java
new file mode 100644
index 0000000..9b8d6bd
--- /dev/null
+++ b/src/main/groovy/groovy/lang/Tuple1.java
@@ -0,0 +1,54 @@
+/*
+ *  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.lang;
+
+/**
+ * Represents a list of 1 typed Object.
+ *
+ * @since 2.5.0
+ */
+public class Tuple1<T1> extends Tuple {
+    private static final long serialVersionUID = -4647790147461409603L;
+    private final T1 first;
+
+    public Tuple1(T1 first) {
+        super(first);
+
+        this.first = first;
+    }
+
+    @Override
+    public Object get(int index) {
+        switch (index) {
+            case 0:
+                return first;
+            default:
+                throw new IndexOutOfBoundsException("index: " + index);
+        }
+    }
+
+    @Override
+    public int size() {
+        return 1;
+    }
+
+    public T1 getFirst() {
+        return first;
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/d638ca43/src/main/groovy/groovy/lang/Tuple2.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/Tuple2.java b/src/main/groovy/groovy/lang/Tuple2.java
new file mode 100644
index 0000000..b096aee
--- /dev/null
+++ b/src/main/groovy/groovy/lang/Tuple2.java
@@ -0,0 +1,60 @@
+/*
+ *  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.lang;
+
+/**
+ * Represents a list of 2 typed Objects.
+ */
+public class Tuple2<T1, T2> extends Tuple {
+    private static final long serialVersionUID = 9006144674906325597L;
+    private final T1 first;
+    private final T2 second;
+
+    public Tuple2(T1 first, T2 second) {
+        super(first, second);
+
+        this.first = first;
+        this.second = second;
+    }
+
+    @Override
+    public Object get(int index) {
+        switch (index) {
+            case 0:
+                return first;
+            case 1:
+                return second;
+            default:
+                throw new IndexOutOfBoundsException("index: " + index);
+        }
+    }
+
+    @Override
+    public int size() {
+        return 2;
+    }
+
+    public T1 getFirst() {
+        return first;
+    }
+
+    public T2 getSecond() {
+        return second;
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/d638ca43/src/main/groovy/groovy/lang/Tuple3.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/Tuple3.java b/src/main/groovy/groovy/lang/Tuple3.java
new file mode 100644
index 0000000..b5fe7d9
--- /dev/null
+++ b/src/main/groovy/groovy/lang/Tuple3.java
@@ -0,0 +1,71 @@
+/*
+ *  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.lang;
+
+/**
+ * Represents a list of 3 typed Objects.
+ *
+ * @since 2.5.0
+ */
+public class Tuple3<T1, T2, T3> extends Tuple {
+    private static final long serialVersionUID = 8469774237154310687L;
+    private final T1 first;
+    private final T2 second;
+    private final T3 third;
+
+    public Tuple3(T1 first, T2 second, T3 third) {
+        super(first, second, third);
+
+        this.first = first;
+        this.second = second;
+        this.third = third;
+    }
+
+    @Override
+    public Object get(int index) {
+        switch (index) {
+            case 0:
+                return first;
+            case 1:
+                return second;
+            case 2:
+                return third;
+            default:
+                throw new IndexOutOfBoundsException("index: " + index);
+        }
+    }
+
+    @Override
+    public int size() {
+        return 3;
+    }
+
+    public T1 getFirst() {
+        return first;
+    }
+
+    public T2 getSecond() {
+        return second;
+    }
+
+    public T3 getThird() {
+        return third;
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/d638ca43/src/main/groovy/groovy/lang/Tuple4.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/Tuple4.java b/src/main/groovy/groovy/lang/Tuple4.java
new file mode 100644
index 0000000..04f414e
--- /dev/null
+++ b/src/main/groovy/groovy/lang/Tuple4.java
@@ -0,0 +1,79 @@
+/*
+ *  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.lang;
+
+/**
+ * Represents a list of 4 typed Objects.
+ *
+ * @since 2.5.0
+ */
+public class Tuple4<T1, T2, T3, T4> extends Tuple {
+    private static final long serialVersionUID = -7788878731471377207L;
+    private final T1 first;
+    private final T2 second;
+    private final T3 third;
+    private final T4 fourth;
+
+    public Tuple4(T1 first, T2 second, T3 third, T4 fourth) {
+        super(first, second, third, fourth);
+
+        this.first = first;
+        this.second = second;
+        this.third = third;
+        this.fourth = fourth;
+    }
+
+    @Override
+    public Object get(int index) {
+        switch (index) {
+            case 0:
+                return first;
+            case 1:
+                return second;
+            case 2:
+                return third;
+            case 3:
+                return fourth;
+            default:
+                throw new IndexOutOfBoundsException("index: " + index);
+        }
+    }
+
+    @Override
+    public int size() {
+        return 4;
+    }
+
+    public T1 getFirst() {
+        return first;
+    }
+
+    public T2 getSecond() {
+        return second;
+    }
+
+    public T3 getThird() {
+        return third;
+    }
+
+    public T4 getFourth() {
+        return fourth;
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/d638ca43/src/main/groovy/groovy/lang/Tuple5.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/Tuple5.java b/src/main/groovy/groovy/lang/Tuple5.java
new file mode 100644
index 0000000..ee9c802
--- /dev/null
+++ b/src/main/groovy/groovy/lang/Tuple5.java
@@ -0,0 +1,87 @@
+/*
+ *  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.lang;
+
+/**
+ * Represents a list of 5 typed Objects.
+ *
+ * @since 2.5.0
+ */
+public class Tuple5<T1, T2, T3, T4, T5> extends Tuple {
+    private static final long serialVersionUID = 6722094358774027115L;
+    private final T1 first;
+    private final T2 second;
+    private final T3 third;
+    private final T4 fourth;
+    private final T5 fifth;
+
+    public Tuple5(T1 first, T2 second, T3 third, T4 fourth, T5 fifth) {
+        super(first, second, third, fourth, fifth);
+
+        this.first = first;
+        this.second = second;
+        this.third = third;
+        this.fourth = fourth;
+        this.fifth = fifth;
+    }
+
+    @Override
+    public Object get(int index) {
+        switch (index) {
+            case 0:
+                return first;
+            case 1:
+                return second;
+            case 2:
+                return third;
+            case 3:
+                return fourth;
+            case 4:
+                return fifth;
+            default:
+                throw new IndexOutOfBoundsException("index: " + index);
+        }
+    }
+
+    @Override
+    public int size() {
+        return 5;
+    }
+
+    public T1 getFirst() {
+        return first;
+    }
+
+    public T2 getSecond() {
+        return second;
+    }
+
+    public T3 getThird() {
+        return third;
+    }
+
+    public T4 getFourth() {
+        return fourth;
+    }
+
+    public T5 getFifth() {
+        return fifth;
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/d638ca43/src/main/groovy/groovy/lang/Tuple6.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/Tuple6.java b/src/main/groovy/groovy/lang/Tuple6.java
new file mode 100644
index 0000000..76d12ca
--- /dev/null
+++ b/src/main/groovy/groovy/lang/Tuple6.java
@@ -0,0 +1,95 @@
+/*
+ *  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.lang;
+
+/**
+ * Represents a list of 6 typed Objects.
+ *
+ * @since 2.5.0
+ */
+public class Tuple6<T1, T2, T3, T4, T5, T6> extends Tuple {
+    private static final long serialVersionUID = -7848588473093102288L;
+    private final T1 first;
+    private final T2 second;
+    private final T3 third;
+    private final T4 fourth;
+    private final T5 fifth;
+    private final T6 sixth;
+
+    public Tuple6(T1 first, T2 second, T3 third, T4 fourth, T5 fifth, T6 sixth) {
+        super(first, second, third, fourth, fifth, sixth);
+
+        this.first = first;
+        this.second = second;
+        this.third = third;
+        this.fourth = fourth;
+        this.fifth = fifth;
+        this.sixth = sixth;
+    }
+
+    @Override
+    public Object get(int index) {
+        switch (index) {
+            case 0:
+                return first;
+            case 1:
+                return second;
+            case 2:
+                return third;
+            case 3:
+                return fourth;
+            case 4:
+                return fifth;
+            case 5:
+                return sixth;
+            default:
+                throw new IndexOutOfBoundsException("index: " + index);
+        }
+    }
+
+    @Override
+    public int size() {
+        return 6;
+    }
+
+    public T1 getFirst() {
+        return first;
+    }
+
+    public T2 getSecond() {
+        return second;
+    }
+
+    public T3 getThird() {
+        return third;
+    }
+
+    public T4 getFourth() {
+        return fourth;
+    }
+
+    public T5 getFifth() {
+        return fifth;
+    }
+
+    public T6 getSixth() {
+        return sixth;
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/d638ca43/src/main/groovy/groovy/lang/Tuple7.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/Tuple7.java b/src/main/groovy/groovy/lang/Tuple7.java
new file mode 100644
index 0000000..05046e7
--- /dev/null
+++ b/src/main/groovy/groovy/lang/Tuple7.java
@@ -0,0 +1,103 @@
+/*
+ *  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.lang;
+
+/**
+ * Represents a list of 7 typed Objects.
+ *
+ * @since 2.5.0
+ */
+public class Tuple7<T1, T2, T3, T4, T5, T6, T7> extends Tuple {
+    private static final long serialVersionUID = 4226144828786865766L;
+    private final T1 first;
+    private final T2 second;
+    private final T3 third;
+    private final T4 fourth;
+    private final T5 fifth;
+    private final T6 sixth;
+    private final T7 seventh;
+
+    public Tuple7(T1 first, T2 second, T3 third, T4 fourth, T5 fifth, T6 sixth, T7 seventh) {
+        super(first, second, third, fourth, fifth, sixth, seventh);
+
+        this.first = first;
+        this.second = second;
+        this.third = third;
+        this.fourth = fourth;
+        this.fifth = fifth;
+        this.sixth = sixth;
+        this.seventh = seventh;
+    }
+
+    @Override
+    public Object get(int index) {
+        switch (index) {
+            case 0:
+                return first;
+            case 1:
+                return second;
+            case 2:
+                return third;
+            case 3:
+                return fourth;
+            case 4:
+                return fifth;
+            case 5:
+                return sixth;
+            case 6:
+                return seventh;
+            default:
+                throw new IndexOutOfBoundsException("index: " + index);
+        }
+    }
+
+    @Override
+    public int size() {
+        return 7;
+    }
+
+    public T1 getFirst() {
+        return first;
+    }
+
+    public T2 getSecond() {
+        return second;
+    }
+
+    public T3 getThird() {
+        return third;
+    }
+
+    public T4 getFourth() {
+        return fourth;
+    }
+
+    public T5 getFifth() {
+        return fifth;
+    }
+
+    public T6 getSixth() {
+        return sixth;
+    }
+
+    public T7 getSeventh() {
+        return seventh;
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/d638ca43/src/main/groovy/groovy/lang/Tuple8.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/Tuple8.java b/src/main/groovy/groovy/lang/Tuple8.java
new file mode 100644
index 0000000..1f38ca9
--- /dev/null
+++ b/src/main/groovy/groovy/lang/Tuple8.java
@@ -0,0 +1,111 @@
+/*
+ *  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.lang;
+
+/**
+ * Represents a list of 8 typed Objects.
+ *
+ * @since 2.5.0
+ */
+public class Tuple8<T1, T2, T3, T4, T5, T6, T7, T8> extends Tuple {
+    private static final long serialVersionUID = -8895822084644138566L;
+    private final T1 first;
+    private final T2 second;
+    private final T3 third;
+    private final T4 fourth;
+    private final T5 fifth;
+    private final T6 sixth;
+    private final T7 seventh;
+    private final T8 eighth;
+
+    public Tuple8(T1 first, T2 second, T3 third, T4 fourth, T5 fifth, T6 sixth, T7 seventh, T8 eighth) {
+        super(first, second, third, fourth, fifth, sixth, seventh, eighth);
+
+        this.first = first;
+        this.second = second;
+        this.third = third;
+        this.fourth = fourth;
+        this.fifth = fifth;
+        this.sixth = sixth;
+        this.seventh = seventh;
+        this.eighth = eighth;
+    }
+
+    @Override
+    public Object get(int index) {
+        switch (index) {
+            case 0:
+                return first;
+            case 1:
+                return second;
+            case 2:
+                return third;
+            case 3:
+                return fourth;
+            case 4:
+                return fifth;
+            case 5:
+                return sixth;
+            case 6:
+                return seventh;
+            case 7:
+                return eighth;
+            default:
+                throw new IndexOutOfBoundsException("index: " + index);
+        }
+    }
+
+    @Override
+    public int size() {
+        return 8;
+    }
+
+    public T1 getFirst() {
+        return first;
+    }
+
+    public T2 getSecond() {
+        return second;
+    }
+
+    public T3 getThird() {
+        return third;
+    }
+
+    public T4 getFourth() {
+        return fourth;
+    }
+
+    public T5 getFifth() {
+        return fifth;
+    }
+
+    public T6 getSixth() {
+        return sixth;
+    }
+
+    public T7 getSeventh() {
+        return seventh;
+    }
+
+    public T8 getEighth() {
+        return eighth;
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/d638ca43/src/main/groovy/groovy/lang/Tuple9.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/Tuple9.java b/src/main/groovy/groovy/lang/Tuple9.java
new file mode 100644
index 0000000..3189c10
--- /dev/null
+++ b/src/main/groovy/groovy/lang/Tuple9.java
@@ -0,0 +1,120 @@
+/*
+ *  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.lang;
+
+/**
+ * Represents a list of 9 typed Objects.
+ *
+ * @since 2.5.0
+ */
+public class Tuple9<T1, T2, T3, T4, T5, T6, T7, T8, T9> extends Tuple {
+    private static final long serialVersionUID = -5181196675351911769L;
+    private final T1 first;
+    private final T2 second;
+    private final T3 third;
+    private final T4 fourth;
+    private final T5 fifth;
+    private final T6 sixth;
+    private final T7 seventh;
+    private final T8 eighth;
+    private final T9 ninth;
+
+    public Tuple9(T1 first, T2 second, T3 third, T4 fourth, T5 fifth, T6 sixth, T7 seventh, T8 eighth, T9 ninth) {
+        super(first, second, third, fourth, fifth, sixth, seventh, eighth, ninth);
+
+        this.first = first;
+        this.second = second;
+        this.third = third;
+        this.fourth = fourth;
+        this.fifth = fifth;
+        this.sixth = sixth;
+        this.seventh = seventh;
+        this.eighth = eighth;
+        this.ninth = ninth;
+    }
+
+    @Override
+    public Object get(int index) {
+        switch (index) {
+            case 0:
+                return first;
+            case 1:
+                return second;
+            case 2:
+                return third;
+            case 3:
+                return fourth;
+            case 4:
+                return fifth;
+            case 5:
+                return sixth;
+            case 6:
+                return seventh;
+            case 7:
+                return eighth;
+            case 8:
+                return ninth;
+            default:
+                throw new IndexOutOfBoundsException("index: " + index);
+        }
+    }
+
+    @Override
+    public int size() {
+        return 9;
+    }
+
+    public T1 getFirst() {
+        return first;
+    }
+
+    public T2 getSecond() {
+        return second;
+    }
+
+    public T3 getThird() {
+        return third;
+    }
+
+    public T4 getFourth() {
+        return fourth;
+    }
+
+    public T5 getFifth() {
+        return fifth;
+    }
+
+    public T6 getSixth() {
+        return sixth;
+    }
+
+    public T7 getSeventh() {
+        return seventh;
+    }
+
+    public T8 getEighth() {
+        return eighth;
+    }
+
+    public T9 getNinth() {
+        return ninth;
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/d638ca43/src/main/groovy/groovy/lang/Writable.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/Writable.java b/src/main/groovy/groovy/lang/Writable.java
new file mode 100644
index 0000000..ec135cd
--- /dev/null
+++ b/src/main/groovy/groovy/lang/Writable.java
@@ -0,0 +1,56 @@
+/*
+ *  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.lang;
+
+import java.io.IOException;
+import java.io.Writer;
+
+
+/**
+ * Represents an object which is capable of writing itself to a text stream
+ * in a more efficient format than just creating a toString() representation
+ * of itself. This mechanism is particularly useful for templates and such like.
+ * <p>
+ * It is worth noting that writable implementations often override their
+ * toString() implementation as well to allow rendering the same result 
+ * directly to a String; however this is not required.
+ *
+ * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
+ */
+public interface Writable {
+
+    /**
+     * Writes this object to the given writer.
+     * <p>
+     * This is used to defer content creation until the point when it is
+     * streamed to the output destination.  Oftentimes, content will be defined 
+     * but not necessarily created (as is may be the case with a Closure 
+     * definition.)  In that case, the output is then 'deferred' to the point 
+     * when it is serialized to the writer. This class may be used whenever an 
+     * object should be responsible for creating its own textual representation, 
+     * but creating the entire output as a single String would be inefficient
+     * (such as outputting a multi-gigabyte XML document.)
+     * 
+     * @param out the Writer to which this Writable should output its data.
+     * @return the Writer that was passed
+     * @throws IOException if an error occurred while outputting data to the writer
+     */
+    Writer writeTo(Writer out) throws IOException;
+        
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/d638ca43/src/main/groovy/groovy/lang/groovydoc/Groovydoc.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/groovydoc/Groovydoc.java b/src/main/groovy/groovy/lang/groovydoc/Groovydoc.java
new file mode 100644
index 0000000..d7d4204
--- /dev/null
+++ b/src/main/groovy/groovy/lang/groovydoc/Groovydoc.java
@@ -0,0 +1,96 @@
+/*
+ *  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.lang.groovydoc;
+
+import java.lang.reflect.AnnotatedElement;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Represents groovydoc
+ */
+public class Groovydoc {
+    private final String content;
+    private List<GroovydocTag> tagList;
+    private final GroovydocHolder holder;
+
+    public Groovydoc(String content, GroovydocHolder groovydocHolder) {
+        this.content = content;
+        this.holder = groovydocHolder;
+    }
+
+    public Groovydoc(final String content, final AnnotatedElement annotatedElement) {
+        this.content = content;
+        this.holder = new GroovydocHolder<AnnotatedElement>() {
+            @Override
+            public Groovydoc getGroovydoc() {
+                return Groovydoc.this;
+            }
+
+            @Override
+            public AnnotatedElement getInstance() {
+                return annotatedElement;
+            }
+        };
+    }
+
+    /**
+     * Get the content of groovydoc
+     * @return the text content
+     */
+    public String getContent() {
+        return content;
+    }
+
+    /**
+     * TODO Get list of groovydoc tags
+     * @return a list of tags
+     */
+    public List<GroovydocTag> getTagList() {
+        throw new UnsupportedOperationException("[TODO]parsing tags will be a new features of the next releases");
+//        return tagList;
+    }
+
+    /**
+     * Get the holder of the groovydoc
+     * @return the groovydoc holder
+     */
+    public GroovydocHolder getHolder() {
+        return holder;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        Groovydoc groovydoc = (Groovydoc) o;
+        return Objects.equals(content, groovydoc.content) &&
+                Objects.equals(holder, groovydoc.holder);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(content, holder);
+    }
+
+    @Override
+    public String toString() {
+        return this.content;
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/d638ca43/src/main/groovy/groovy/lang/groovydoc/GroovydocHolder.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/groovydoc/GroovydocHolder.java b/src/main/groovy/groovy/lang/groovydoc/GroovydocHolder.java
new file mode 100644
index 0000000..eb41df4
--- /dev/null
+++ b/src/main/groovy/groovy/lang/groovydoc/GroovydocHolder.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.lang.groovydoc;
+
+/**
+ * Represents Groovydoc Holder
+ */
+public interface GroovydocHolder<T> {
+    String DOC_COMMENT = "_DOC_COMMENT"; // keys for meta data
+    /**
+     * Get the groovydoc
+     * @return the groovydoc
+     */
+    Groovydoc getGroovydoc();
+
+    /**
+     * Get GroovydocHolder instance
+     * @return GroovydocHolder instance
+     */
+    T getInstance();
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/d638ca43/src/main/groovy/groovy/lang/groovydoc/GroovydocTag.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/groovydoc/GroovydocTag.java b/src/main/groovy/groovy/lang/groovydoc/GroovydocTag.java
new file mode 100644
index 0000000..14e5aaa
--- /dev/null
+++ b/src/main/groovy/groovy/lang/groovydoc/GroovydocTag.java
@@ -0,0 +1,68 @@
+/*
+ *  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.lang.groovydoc;
+
+import java.util.Objects;
+
+/**
+ * TODO parse groovydoc to get tag content
+ */
+public class GroovydocTag {
+    private String name;
+    private String content;
+    private Groovydoc groovydoc;
+
+    public GroovydocTag(String name, String content, Groovydoc groovydoc) {
+        this.name = name;
+        this.content = content;
+        this.groovydoc = groovydoc;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public String getContent() {
+        return content;
+    }
+
+    public Groovydoc getGroovydoc() {
+        return groovydoc;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        GroovydocTag that = (GroovydocTag) o;
+        return Objects.equals(name, that.name) &&
+                Objects.equals(content, that.content) &&
+                Objects.equals(groovydoc, that.groovydoc);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(name, content, groovydoc);
+    }
+
+    @Override
+    public String toString() {
+        return content;
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/d638ca43/src/main/groovy/groovy/lang/package.html
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/package.html b/src/main/groovy/groovy/lang/package.html
new file mode 100644
index 0000000..1ea84fc
--- /dev/null
+++ b/src/main/groovy/groovy/lang/package.html
@@ -0,0 +1,28 @@
+<!--
+
+     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.
+
+-->
+<html>
+  <head>
+    <title>package groovy.lang.*</title>
+  </head>
+  <body>
+    <p>Core Groovy language classes for implementing data structures, closures, metadata and so forth.</p>
+  </body>
+</html>

http://git-wip-us.apache.org/repos/asf/groovy/blob/d638ca43/src/main/groovy/groovy/security/GroovyCodeSourcePermission.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/security/GroovyCodeSourcePermission.java b/src/main/groovy/groovy/security/GroovyCodeSourcePermission.java
new file mode 100644
index 0000000..e723e0b
--- /dev/null
+++ b/src/main/groovy/groovy/security/GroovyCodeSourcePermission.java
@@ -0,0 +1,40 @@
+/*
+ *  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.security;
+
+import java.security.BasicPermission;
+
+/**
+ * Permission required to explicitly specify a codebase for a groovy script whose
+ * codebase cannot be determined.  Typically this permission is only
+ * required by clients that want to associate a code source with a script which
+ * is a String or an InputStream.
+ *
+ * @author Steve Goetze
+ */
+public final class GroovyCodeSourcePermission extends BasicPermission {
+
+    public GroovyCodeSourcePermission(String name) {
+        super(name);
+    }
+
+    public GroovyCodeSourcePermission(String name, String actions) {
+        super(name, actions);
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/d638ca43/src/main/groovy/groovy/security/package.html
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/security/package.html b/src/main/groovy/groovy/security/package.html
new file mode 100644
index 0000000..cb094ff
--- /dev/null
+++ b/src/main/groovy/groovy/security/package.html
@@ -0,0 +1,30 @@
+<!--
+
+     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.
+
+-->
+<html>
+  <head>
+    <title>package groovy.security.*</title>
+  </head>
+  <body>
+    <p>
+      Security-related classes
+    </p>
+  </body>
+</html>

http://git-wip-us.apache.org/repos/asf/groovy/blob/d638ca43/src/main/groovy/groovy/time/BaseDuration.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/time/BaseDuration.java b/src/main/groovy/groovy/time/BaseDuration.java
new file mode 100644
index 0000000..e2cc023
--- /dev/null
+++ b/src/main/groovy/groovy/time/BaseDuration.java
@@ -0,0 +1,141 @@
+/*
+ *  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.time;
+
+import org.codehaus.groovy.runtime.DefaultGroovyMethods;
+import org.codehaus.groovy.runtime.StringGroovyMethods;
+
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * Base class for date and time durations.
+ *
+ * @author John Wilson tug@wilson.co.uk
+ * @see Duration
+ */
+public abstract class BaseDuration implements Comparable<BaseDuration> {
+    protected final int years;
+    protected final int months;
+    protected final int days;
+    protected final int hours;
+    protected final int minutes;
+    protected final int seconds;
+    protected final int millis;
+
+    protected BaseDuration(final int years, final int months, final int days, final int hours, final int minutes, final int seconds, final int millis) {
+        this.years = years;
+        this.months = months;
+        this.days = days;
+        this.hours = hours;
+        this.minutes = minutes;
+        this.seconds = seconds;
+        this.millis = millis;
+    }
+
+    protected BaseDuration(final int days, final int hours, final int minutes, final int seconds, final int millis) {
+        this(0, 0, days, hours, minutes, seconds, millis);
+    }
+
+    public int getYears() {
+        return this.years;
+    }
+
+    public int getMonths() {
+        return this.months;
+    }
+
+    public int getDays() {
+        return this.days;
+    }
+
+    public int getHours() {
+        return this.hours;
+    }
+
+    public int getMinutes() {
+        return this.minutes;
+    }
+
+    public int getSeconds() {
+        return this.seconds;
+    }
+
+    public int getMillis() {
+        return this.millis;
+    }
+
+    public Date plus(final Date date) {
+        final Calendar cal = Calendar.getInstance();
+
+        cal.setTime(date);
+        cal.add(Calendar.YEAR, this.years);
+        cal.add(Calendar.MONTH, this.months);
+        cal.add(Calendar.DAY_OF_YEAR, this.days);
+        cal.add(Calendar.HOUR_OF_DAY, this.hours);
+        cal.add(Calendar.MINUTE, this.minutes);
+        cal.add(Calendar.SECOND, this.seconds);
+        cal.add(Calendar.MILLISECOND, this.millis);
+
+        return cal.getTime();
+    }
+
+    public String toString() {
+        List buffer = new ArrayList();
+
+        if (this.years != 0) buffer.add(this.years + " years");
+        if (this.months != 0) buffer.add(this.months + " months");
+        if (this.days != 0) buffer.add(this.days + " days");
+        if (this.hours != 0) buffer.add(this.hours + " hours");
+        if (this.minutes != 0) buffer.add(this.minutes + " minutes");
+
+        if (this.seconds != 0 || this.millis != 0) {
+            int norm_millis = this.millis % 1000;
+            int norm_seconds = this.seconds + DefaultGroovyMethods.intdiv(this.millis - norm_millis, 1000).intValue();
+            CharSequence millisToPad = "" + Math.abs(norm_millis);
+            buffer.add((norm_seconds == 0 ? (norm_millis < 0 ? "-0" : "0") : norm_seconds) + "." + StringGroovyMethods.padLeft(millisToPad, 3, "0") + " seconds");
+        }
+
+        if (!buffer.isEmpty()) {
+            return DefaultGroovyMethods.join(buffer.iterator(), ", ");
+        } else {
+            return "0";
+        }
+    }
+
+    public abstract long toMilliseconds();
+
+    public abstract Date getAgo();
+
+    public abstract From getFrom();
+
+    public int compareTo(BaseDuration otherDuration) {
+        return Long.signum(toMilliseconds() - otherDuration.toMilliseconds());
+    }
+
+    public abstract static class From {
+        public abstract Date getNow();
+
+        public Date getToday() {
+            return getNow();
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/d638ca43/src/main/groovy/groovy/time/DatumDependentDuration.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/time/DatumDependentDuration.java b/src/main/groovy/groovy/time/DatumDependentDuration.java
new file mode 100644
index 0000000..c73d9aa
--- /dev/null
+++ b/src/main/groovy/groovy/time/DatumDependentDuration.java
@@ -0,0 +1,141 @@
+/*
+ *  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.time;
+
+import java.util.Calendar;
+import java.util.Date;
+
+/**
+ * DatumDependentDuration represents durations whose length in milliseconds 
+ * cannot be determined without knowing the datum point.
+ * <p>
+ * I don't know how many days in a year unless I know if it's a leap year or not.
+ * <p>
+ * I don't know how many days in a month unless I know the name of the month 
+ * (and if it's a leap year if the month is February)
+ *
+ * @author John Wilson tug@wilson.co.uk
+ */
+public class DatumDependentDuration extends BaseDuration {
+    public DatumDependentDuration(final int years, final int months, final int days, final int hours, final int minutes, final int seconds, final int millis) {
+        super(years, months, days, hours, minutes, seconds, millis);
+    }
+
+    public int getMonths() {
+        return this.months;
+    }
+
+    public int getYears() {
+        return this.years;
+    }
+
+    public DatumDependentDuration plus(final DatumDependentDuration rhs) {
+        return new DatumDependentDuration(this.getYears() + rhs.getYears(), this.getMonths() + rhs.getMonths(),
+                this.getDays() + rhs.getDays(), this.getHours() + rhs.getHours(),
+                this.getMinutes() + rhs.getMinutes(), this.getSeconds() + rhs.getSeconds(),
+                this.getMillis() + rhs.getMillis());
+    }
+
+    public DatumDependentDuration plus(final TimeDatumDependentDuration rhs) {
+        return rhs.plus(this);
+    }
+
+    public DatumDependentDuration plus(final Duration rhs) {
+        return new DatumDependentDuration(this.getYears(), this.getMonths(),
+                this.getDays() + rhs.getDays(), this.getHours() + rhs.getHours(),
+                this.getMinutes() + rhs.getMinutes(), this.getSeconds() + rhs.getSeconds(),
+                this.getMillis() + rhs.getMillis());
+
+    }
+
+    public DatumDependentDuration plus(final TimeDuration rhs) {
+        return rhs.plus(this);
+
+    }
+
+    public DatumDependentDuration minus(final DatumDependentDuration rhs) {
+        return new DatumDependentDuration(this.getYears() - rhs.getYears(), this.getMonths() - rhs.getMonths(),
+                this.getDays() - rhs.getDays(), this.getHours() - rhs.getHours(),
+                this.getMinutes() - rhs.getMinutes(), this.getSeconds() - rhs.getSeconds(),
+                this.getMillis() - rhs.getMillis());
+
+    }
+
+    public DatumDependentDuration minus(final Duration rhs) {
+        return new DatumDependentDuration(this.getYears(), this.getMonths(),
+                this.getDays() - rhs.getDays(), this.getHours() - rhs.getHours(),
+                this.getMinutes() - rhs.getMinutes(), this.getSeconds() - rhs.getSeconds(),
+                this.getMillis() - rhs.getMillis());
+
+    }
+
+    /**
+     * @see groovy.time.BaseDuration#toMilliseconds()
+     *
+     * Change the duration into milliseconds, relative to 'now.'  Therefore
+     * things like timezone and time of year will affect how this conversion 
+     * occurs.
+     */
+    public long toMilliseconds() {
+        final Date now = new Date();
+        return TimeCategory.minus(plus(now), now).toMilliseconds();
+    }
+
+    public Date getAgo() {
+        final Calendar cal = Calendar.getInstance();
+
+        cal.add(Calendar.YEAR, -this.getYears());
+        cal.add(Calendar.MONTH, -this.getMonths());
+        cal.add(Calendar.DAY_OF_YEAR, -this.getDays());
+        cal.add(Calendar.HOUR_OF_DAY, -this.getHours());
+        cal.add(Calendar.MINUTE, -this.getMinutes());
+        cal.add(Calendar.SECOND, -this.getSeconds());
+        cal.add(Calendar.MILLISECOND, -this.getMillis());
+
+        cal.set(Calendar.HOUR_OF_DAY, 0);
+        cal.set(Calendar.MINUTE, 0);
+        cal.set(Calendar.SECOND, 0);
+        cal.set(Calendar.MILLISECOND, 0);
+
+        return new Date(cal.getTimeInMillis());
+    }
+
+    public From getFrom() {
+        return new From() {
+            public Date getNow() {
+                final Calendar cal = Calendar.getInstance();
+
+                cal.add(Calendar.YEAR, DatumDependentDuration.this.getYears());
+                cal.add(Calendar.MONTH, DatumDependentDuration.this.getMonths());
+                cal.add(Calendar.DAY_OF_YEAR, DatumDependentDuration.this.getDays());
+                cal.add(Calendar.HOUR_OF_DAY, DatumDependentDuration.this.getHours());
+                cal.add(Calendar.MINUTE, DatumDependentDuration.this.getMinutes());
+                cal.add(Calendar.SECOND, DatumDependentDuration.this.getSeconds());
+                cal.add(Calendar.MILLISECOND, DatumDependentDuration.this.getMillis());
+
+                cal.set(Calendar.HOUR_OF_DAY, 0);
+                cal.set(Calendar.MINUTE, 0);
+                cal.set(Calendar.SECOND, 0);
+                cal.set(Calendar.MILLISECOND, 0);
+
+                return new Date(cal.getTimeInMillis());
+            }
+        };
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/d638ca43/src/main/groovy/groovy/time/Duration.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/time/Duration.java b/src/main/groovy/groovy/time/Duration.java
new file mode 100644
index 0000000..e187957
--- /dev/null
+++ b/src/main/groovy/groovy/time/Duration.java
@@ -0,0 +1,119 @@
+/*
+ *  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.time;
+
+import java.util.Calendar;
+import java.util.Date;
+
+/**
+ * Duration represents time periods which have values independent of the context.
+ * So, whilst we can't say how long a month is without knowing the year and the name of the month,
+ * we know how long a day is independent of the date.
+ * <p>
+ * This is not 100% true for days.
+ * Days can actually be 23, 24 or 25 hours long (due to daylight saving adjustments.)
+ * <p>
+ * If you ask Duration to convert itself to milliseconds then it will work on the basis of 24 hours
+ * in a day. If you add or subtract it from a date it will take daylight saving into account.
+ *
+ * @author John Wilson tug@wilson.co.uk
+ */
+public class Duration extends BaseDuration {
+    public Duration(final int days, final int hours, final int minutes, final int seconds, final int millis) {
+        super(days, hours, minutes, seconds, millis);
+    }
+    
+    public Duration plus(final Duration rhs) {
+        return new Duration(this.getDays() + rhs.getDays(), this.getHours() + rhs.getHours(),
+                            this.getMinutes() + rhs.getMinutes(), this.getSeconds() + rhs.getSeconds(),
+                            this.getMillis() + rhs.getMillis());
+    }
+
+    public Duration plus(final TimeDuration rhs) {
+        return rhs.plus(this);
+    }
+    
+    public DatumDependentDuration plus(final DatumDependentDuration rhs) {
+        return rhs.plus(this);
+    }
+    
+    public Duration minus(final Duration rhs) {
+        return new Duration(this.getDays() - rhs.getDays(), this.getHours() - rhs.getHours(),
+                            this.getMinutes() - rhs.getMinutes(), this.getSeconds() - rhs.getSeconds(),
+                            this.getMillis() - rhs.getMillis());
+    }
+    
+    public TimeDuration minus(final TimeDuration rhs) {
+        return new TimeDuration(this.getDays() - rhs.getDays(), this.getHours() - rhs.getHours(),
+                                this.getMinutes() - rhs.getMinutes(), this.getSeconds() - rhs.getSeconds(),
+                                this.getMillis() - rhs.getMillis());
+    }
+    
+    public DatumDependentDuration minus(final DatumDependentDuration rhs) {
+        return new DatumDependentDuration(-rhs.getYears(), -rhs.getMonths(),
+                                          this.getDays() - rhs.getDays(), this.getHours() - rhs.getHours(),
+                                          this.getMinutes() - rhs.getMinutes(), this.getSeconds() - rhs.getSeconds(),
+                                          this.getMillis() - rhs.getMillis());
+    }
+    
+    public TimeDatumDependentDuration minus(final TimeDatumDependentDuration rhs) {
+        return new TimeDatumDependentDuration(-rhs.getYears(), -rhs.getMonths(),
+                                              this.getDays() - rhs.getDays(), this.getHours() - rhs.getHours(),
+                                              this.getMinutes() - rhs.getMinutes(), this.getSeconds() - rhs.getSeconds(),
+                                              this.getMillis() - rhs.getMillis());
+    }
+    
+    public long toMilliseconds() {
+        return ((((((long)(this.getDays() * 24 ) + this.getHours()) * 60 + this.getMinutes()) * 60) + this.getSeconds()) * 1000) + this.getMillis();
+    }
+    
+    public Date getAgo() {
+    final Calendar cal = Calendar.getInstance();
+
+        cal.add(Calendar.DAY_OF_YEAR, -this.getDays());
+        cal.add(Calendar.HOUR_OF_DAY, -this.getHours());
+        cal.add(Calendar.MINUTE, -this.getMinutes());
+        cal.add(Calendar.SECOND, -this.getSeconds());
+        cal.add(Calendar.MILLISECOND, -this.getMillis());
+
+        cal.set(Calendar.HOUR_OF_DAY, 0);
+        cal.set(Calendar.MINUTE, 0);
+        cal.set(Calendar.SECOND, 0);
+        cal.set(Calendar.MILLISECOND, 0);
+        
+        return new Date(cal.getTimeInMillis());
+    }
+     
+    public From getFrom() {
+        return new From() {
+            public Date getNow() {
+            final Calendar cal = Calendar.getInstance();
+
+                cal.add(Calendar.DAY_OF_YEAR, Duration.this.getDays());
+
+                cal.set(Calendar.HOUR_OF_DAY, 0);
+                cal.set(Calendar.MINUTE, 0);
+                cal.set(Calendar.SECOND, 0);
+                cal.set(Calendar.MILLISECOND, 0);
+
+                return new Date(cal.getTimeInMillis());
+            }
+        };
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/d638ca43/src/main/groovy/groovy/time/TimeCategory.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/time/TimeCategory.java b/src/main/groovy/groovy/time/TimeCategory.java
new file mode 100644
index 0000000..dbc08cd
--- /dev/null
+++ b/src/main/groovy/groovy/time/TimeCategory.java
@@ -0,0 +1,203 @@
+/*
+ *  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.time;
+
+import java.util.Calendar;
+import java.util.Date;
+import java.util.TimeZone;
+
+/**
+ * Apply a number of methods to allow convenient Date/Time manipulation,such as:
+ * <pre class="groovyTestCase">
+ * use (groovy.time.TimeCategory) {
+ *     // application on numbers:
+ *     println 1.minute.from.now
+ *     println 10.hours.ago
+ *
+ *     // application on dates
+ *     def someDate = new Date()
+ *     println someDate - 3.months
+ * }
+ * </pre>
+ *
+ * @see BaseDuration
+ */
+public class TimeCategory {
+    /*
+     * Methods to allow Date Duration arithmetic
+     */
+
+    public static Date plus(final Date date, final BaseDuration duration) {
+        return duration.plus(date);
+    }
+
+    public static Date minus(final Date date, final BaseDuration duration) {
+        final Calendar cal = Calendar.getInstance();
+
+        cal.setTime(date);
+        cal.add(Calendar.YEAR, -duration.getYears());
+        cal.add(Calendar.MONTH, -duration.getMonths());
+        cal.add(Calendar.DAY_OF_YEAR, -duration.getDays());
+        cal.add(Calendar.HOUR_OF_DAY, -duration.getHours());
+        cal.add(Calendar.MINUTE, -duration.getMinutes());
+        cal.add(Calendar.SECOND, -duration.getSeconds());
+        cal.add(Calendar.MILLISECOND, -duration.getMillis());
+
+        return cal.getTime();
+    }
+
+    /**
+     * Retrieves the default TimeZone for a date by using the default Locale
+     * settings. Recommended that you use {@code TimeZone.getDefault()} instead.
+     *
+     * @param self a Date
+     * @return the TimeZone
+     */
+    @Deprecated
+    public static TimeZone getTimeZone(Date self) {
+        Calendar calendar = Calendar.getInstance();
+        calendar.setTime(self);
+        return calendar.getTimeZone();
+    }
+
+    /**
+     * Get the DST offset (if any) for the default locale and the given date.
+     *
+     * @param self a Date
+     * @return the DST offset as a Duration.
+     */
+    public static Duration getDaylightSavingsOffset(Date self) {
+        TimeZone timeZone = getTimeZone(self);
+        int millis = (timeZone.useDaylightTime() && timeZone.inDaylightTime(self))
+                ? timeZone.getDSTSavings() : 0;
+        return new TimeDuration(0, 0, 0, millis);
+    }
+
+    public static Duration getDaylightSavingsOffset(BaseDuration self) {
+        return getDaylightSavingsOffset(new Date(self.toMilliseconds() + 1));
+    }
+
+    /**
+     * Return a Duration representing the DST difference (if any) between two
+     * dates.  i.e. if one date is before the DST changeover, and the other
+     * date is after, the resulting duration will represent the DST offset.
+     *
+     * @param self  a Date
+     * @param other another Date
+     * @return a Duration
+     */
+    public static Duration getRelativeDaylightSavingsOffset(Date self, Date other) {
+        Duration d1 = getDaylightSavingsOffset(self);
+        Duration d2 = getDaylightSavingsOffset(other);
+        return new TimeDuration(0, 0, 0, (int) (d2.toMilliseconds() - d1.toMilliseconds()));
+    }
+
+    /**
+     * Subtract one date from the other.
+     *
+     * @param lhs a Date
+     * @param rhs another Date
+     * @return a Duration
+     */
+    public static TimeDuration minus(final Date lhs, final Date rhs) {
+        long milliseconds = lhs.getTime() - rhs.getTime();
+        long days = milliseconds / (24 * 60 * 60 * 1000);
+        milliseconds -= days * 24 * 60 * 60 * 1000;
+        int hours = (int) (milliseconds / (60 * 60 * 1000));
+        milliseconds -= hours * 60 * 60 * 1000;
+        int minutes = (int) (milliseconds / (60 * 1000));
+        milliseconds -= minutes * 60 * 1000;
+        int seconds = (int) (milliseconds / 1000);
+        milliseconds -= seconds * 1000;
+
+        return new TimeDuration((int) days, hours, minutes, seconds, (int) milliseconds);
+    }
+
+    /*
+    * Methods on Integer to implement 1.month, 4.years etc.
+    */
+
+    public static DatumDependentDuration getMonths(final Integer self) {
+        return new DatumDependentDuration(0, self, 0, 0, 0, 0, 0);
+    }
+
+    public static DatumDependentDuration getMonth(final Integer self) {
+        return getMonths(self);
+    }
+
+    public static DatumDependentDuration getYears(final Integer self) {
+        return new DatumDependentDuration(self, 0, 0, 0, 0, 0, 0);
+    }
+
+    public static DatumDependentDuration getYear(final Integer self) {
+        return getYears(self);
+    }
+
+    /*
+    * Methods on Integer to implement 1.week, 4.days etc.
+    */
+
+    public static Duration getWeeks(final Integer self) {
+        return new Duration(self * 7, 0, 0, 0, 0);
+    }
+
+    public static Duration getWeek(final Integer self) {
+        return getWeeks(self);
+    }
+
+    public static Duration getDays(final Integer self) {
+        return new Duration(self, 0, 0, 0, 0);
+    }
+
+    public static Duration getDay(final Integer self) {
+        return getDays(self);
+    }
+
+    public static TimeDuration getHours(final Integer self) {
+        return new TimeDuration(0, self, 0, 0, 0);
+    }
+
+    public static TimeDuration getHour(final Integer self) {
+        return getHours(self);
+    }
+
+    public static TimeDuration getMinutes(final Integer self) {
+        return new TimeDuration(0, 0, self, 0, 0);
+    }
+
+    public static TimeDuration getMinute(final Integer self) {
+        return getMinutes(self);
+    }
+
+    public static TimeDuration getSeconds(final Integer self) {
+        return new TimeDuration(0, 0, 0, self, 0);
+    }
+
+    public static TimeDuration getSecond(final Integer self) {
+        return getSeconds(self);
+    }
+
+    public static TimeDuration getMilliseconds(final Integer self) {
+        return new TimeDuration(0, 0, 0, 0, self);
+    }
+
+    public static TimeDuration getMillisecond(final Integer self) {
+        return getMilliseconds(self);
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/d638ca43/src/main/groovy/groovy/time/TimeDatumDependentDuration.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/time/TimeDatumDependentDuration.java b/src/main/groovy/groovy/time/TimeDatumDependentDuration.java
new file mode 100644
index 0000000..eead45a
--- /dev/null
+++ b/src/main/groovy/groovy/time/TimeDatumDependentDuration.java
@@ -0,0 +1,81 @@
+/*
+ *  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.time;
+
+import java.util.Calendar;
+import java.util.Date;
+
+/**
+ * TimeDatumDuration represents a time period which results from an
+ * arithmetic operation between a TimeDuration object and a DatumDuration object
+ * 
+ * @author John Wilson tug@wilson.co.uk
+ */
+public class TimeDatumDependentDuration extends DatumDependentDuration {
+    public TimeDatumDependentDuration(int years, int months, int days, int hours, int minutes, int seconds, int millis) {
+        super(years, months, days, hours, minutes, seconds, millis);
+    }
+    
+    public DatumDependentDuration plus(final Duration rhs) {
+        return new TimeDatumDependentDuration(this.getYears(), this.getMonths(),
+                                              this.getDays() + rhs.getDays(), this.getHours() + rhs.getHours(),
+                                              this.getMinutes() + rhs.getMinutes(), this.getSeconds() + rhs.getSeconds(),
+                                              this.getMillis() + rhs.getMillis());
+    }
+    
+    public DatumDependentDuration plus(final DatumDependentDuration rhs) {
+        return new TimeDatumDependentDuration(this.getYears() + rhs.getYears(), this.getMonths() + rhs.getMonths(),
+                                              this.getDays() + rhs.getDays(), this.getHours() + rhs.getHours(),
+                                              this.getMinutes() + rhs.getMinutes(), this.getSeconds() + rhs.getSeconds(),
+                                              this.getMillis() + rhs.getMillis());
+    }
+    
+    public DatumDependentDuration minus(final Duration rhs) {
+        return new TimeDatumDependentDuration(this.getYears(), this.getMonths(),
+                                              this.getDays() - rhs.getDays(), this.getHours() - rhs.getHours(),
+                                              this.getMinutes() - rhs.getMinutes(), this.getSeconds() - rhs.getSeconds(),
+                                              this.getMillis() - rhs.getMillis());
+    }
+    
+    public DatumDependentDuration minus(final DatumDependentDuration rhs) {
+        return new TimeDatumDependentDuration(this.getYears() - rhs.getYears(), this.getMonths() - rhs.getMonths(),
+                                              this.getDays() - rhs.getDays(), this.getHours() - rhs.getHours(),
+                                              this.getMinutes() - rhs.getMinutes(), this.getSeconds() - rhs.getSeconds(),
+                                              this.getMillis() - rhs.getMillis());
+    }
+    
+    public From getFrom() {
+        return new From() {
+            public Date getNow() {
+            final Calendar cal = Calendar.getInstance();
+
+                cal.add(Calendar.YEAR, TimeDatumDependentDuration.this.getYears());
+                cal.add(Calendar.MONTH, TimeDatumDependentDuration.this.getMonths());
+                cal.add(Calendar.DAY_OF_YEAR, TimeDatumDependentDuration.this.getDays());
+                cal.add(Calendar.HOUR_OF_DAY, TimeDatumDependentDuration.this.getHours());
+                cal.add(Calendar.MINUTE, TimeDatumDependentDuration.this.getMinutes());
+                cal.add(Calendar.SECOND, TimeDatumDependentDuration.this.getSeconds());
+                cal.add(Calendar.MILLISECOND, TimeDatumDependentDuration.this.getMillis());
+                
+                return cal.getTime();
+            }
+        };
+    }
+
+}


Mime
View raw message