Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrian Vosburgh2013-08-21 20:53:23 +0000
committerBrian Vosburgh2013-08-26 19:14:27 +0000
commite5cc7d1d3cc759388c6d3c6a8b082433d421dc39 (patch)
treee3f5b169d2e3d1b5b41c749b36272202d4e0f1f3
parentb7f4808580b8ba3e394cb77a7852377731c2cfd6 (diff)
downloadwebtools.dali-e5cc7d1d3cc759388c6d3c6a8b082433d421dc39.tar.gz
webtools.dali-e5cc7d1d3cc759388c6d3c6a8b082433d421dc39.tar.xz
webtools.dali-e5cc7d1d3cc759388c6d3c6a8b082433d421dc39.zip
add a bunch of simple Closure implementations
-rw-r--r--common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/ArrayTools.java6
-rw-r--r--common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/AbstractClosure.java38
-rw-r--r--common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/AbstractInterruptibleClosure.java38
-rw-r--r--common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/ClosureAdapter.java1
-rw-r--r--common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/ClosureTools.java282
-rw-r--r--common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/CompositeClosure.java45
-rw-r--r--common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/CompositeInterruptibleClosure.java45
-rw-r--r--common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/ConditionalClosure.java51
-rw-r--r--common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/ConditionalInterruptibleClosure.java51
-rw-r--r--common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/InterruptibleTransformerClosure.java45
-rw-r--r--common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/MethodClosure.java75
-rw-r--r--common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/NullCheckClosureWrapper.java51
-rw-r--r--common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/NullCheckInterruptibleClosureWrapper.java51
-rw-r--r--common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/RepeatingClosure.java48
-rw-r--r--common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/RepeatingInterruptibleClosure.java48
-rw-r--r--common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/SafeClosureWrapper.java52
-rw-r--r--common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/SafeInterruptibleClosureWrapper.java55
-rw-r--r--common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/SwitchClosure.java58
-rw-r--r--common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/SwitchInterruptibleClosure.java58
-rw-r--r--common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/TransformerClosure.java45
-rw-r--r--common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/UntilClosure.java53
-rw-r--r--common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/UntilInterruptibleClosure.java52
-rw-r--r--common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/WhileClosure.java47
-rw-r--r--common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/WhileInterruptibleClosure.java47
-rw-r--r--common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/comparator/ComparatorTools.java65
-rw-r--r--common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/iterable/IterableTools.java16
-rw-r--r--common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/transformer/ClosureTransformer.java47
-rw-r--r--common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/transformer/ConditionalTransformer.java50
-rw-r--r--common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/transformer/SwitchTransformer.java58
-rw-r--r--common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/transformer/TransformerChain.java12
-rw-r--r--common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/transformer/TransformerTools.java120
31 files changed, 1661 insertions, 49 deletions
diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/ArrayTools.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/ArrayTools.java
index 935ae8c1c2..81674a35e0 100644
--- a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/ArrayTools.java
+++ b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/ArrayTools.java
@@ -925,7 +925,7 @@ public final class ArrayTools {
* check array length
*/
private static boolean contains(Object[] array, Object value, int arrayLength) {
- return (arrayLength == 0) ? false : contains_(array, value, arrayLength);
+ return (arrayLength != 0) && contains_(array, value, arrayLength);
}
/**
@@ -960,7 +960,7 @@ public final class ArrayTools {
* check array length
*/
private static boolean contains(char[] array, char value, int arrayLength) {
- return (arrayLength == 0) ? false : contains_(array, value, arrayLength);
+ return (arrayLength != 0) && contains_(array, value, arrayLength);
}
/**
@@ -987,7 +987,7 @@ public final class ArrayTools {
* check array length
*/
private static boolean contains(int[] array, int value, int arrayLength) {
- return (arrayLength == 0) ? false : contains_(array, value, arrayLength);
+ return (arrayLength != 0) && contains_(array, value, arrayLength);
}
/**
diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/AbstractClosure.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/AbstractClosure.java
new file mode 100644
index 0000000000..c6153c6e41
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/AbstractClosure.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.utility.internal.closure;
+
+/**
+ * Convenience superclass that does nothing if the argument
+ * is <code>null</code>; otherwise it calls {@link #execute_(Object)},
+ * which is to be implemented by subclasses.
+ *
+ * @param <A> the type of the object passed to the closure
+ *
+ * @see NullClosure
+ * @see ClosureAdapter
+ * @see NullCheckClosureWrapper
+ */
+public abstract class AbstractClosure<A>
+ extends ClosureAdapter<A>
+{
+ @Override
+ public final void execute(A argument) {
+ if (argument != null) {
+ this.execute_(argument);
+ }
+ }
+
+ /**
+ * Process the specified argument; its value is guaranteed to be not
+ * <code>null</code>.
+ */
+ protected abstract void execute_(A argument);
+}
diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/AbstractInterruptibleClosure.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/AbstractInterruptibleClosure.java
new file mode 100644
index 0000000000..8d7ee03adf
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/AbstractInterruptibleClosure.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.utility.internal.closure;
+
+/**
+ * Convenience superclass that does nothing if the argument
+ * is <code>null</code>; otherwise it calls {@link #execute_(Object)},
+ * which is to be implemented by subclasses.
+ *
+ * @param <A> the type of the object passed to the closure
+ *
+ * @see NullClosure
+ * @see InterruptibleClosureAdapter
+ * @see NullCheckInterruptibleClosureWrapper
+ */
+public abstract class AbstractInterruptibleClosure<A>
+ extends InterruptibleClosureAdapter<A>
+{
+ @Override
+ public final void execute(A argument) throws InterruptedException {
+ if (argument != null) {
+ this.execute_(argument);
+ }
+ }
+
+ /**
+ * Process the specified argument; its value is guaranteed to be not
+ * <code>null</code>.
+ */
+ protected abstract void execute_(A argument) throws InterruptedException;
+}
diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/ClosureAdapter.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/ClosureAdapter.java
index 064123e706..25f93ec82e 100644
--- a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/ClosureAdapter.java
+++ b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/ClosureAdapter.java
@@ -17,6 +17,7 @@ import org.eclipse.jpt.common.utility.internal.ObjectTools;
*
* @param <A> the type of the object passed to the closure
*
+ * @see AbstractClosure
* @see NullClosure
*/
public class ClosureAdapter<A>
diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/ClosureTools.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/ClosureTools.java
new file mode 100644
index 0000000000..e56d0e24ec
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/ClosureTools.java
@@ -0,0 +1,282 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.utility.internal.closure;
+
+import org.eclipse.jpt.common.utility.Association;
+import org.eclipse.jpt.common.utility.closure.Closure;
+import org.eclipse.jpt.common.utility.command.Command;
+import org.eclipse.jpt.common.utility.exception.ExceptionHandler;
+import org.eclipse.jpt.common.utility.internal.ArrayTools;
+import org.eclipse.jpt.common.utility.internal.ClassTools;
+import org.eclipse.jpt.common.utility.internal.ObjectTools;
+import org.eclipse.jpt.common.utility.internal.command.NullCommand;
+import org.eclipse.jpt.common.utility.internal.exception.DefaultExceptionHandler;
+import org.eclipse.jpt.common.utility.predicate.Predicate;
+import org.eclipse.jpt.common.utility.transformer.Transformer;
+
+/**
+ * {@link Closure} utility methods.
+ */
+public final class ClosureTools {
+
+ // ********** wrappers **********
+
+ /**
+ * Return a closure that wraps the specified closure and checks
+ * for a <code>null</code> argument before forwarding the argument to the
+ * specified closure. If the argument is <code>null</code>, the closure will
+ * do nothing.
+ * @param <A> the type of the object passed to the closure
+ * @see #nullCheck(Closure, Command)
+ */
+ public static <A> Closure<A> nullCheck(Closure<? super A> closure) {
+ return nullCheck(closure, NullCommand.instance());
+ }
+
+ /**
+ * Return a closure that wraps the specified closure and checks
+ * for a <code>null</code> argument before forwarding the argument to the
+ * specified closure. If the argument is <code>null</code>,
+ * the closure will execute the specified command.
+ * @param <A> the type of the object passed to the closure
+ * @see #nullCheck(Closure)
+ */
+ public static <A> Closure<A> nullCheck(Closure<? super A> closure, Command nullCommand) {
+ return new NullCheckClosureWrapper<A>(closure, nullCommand);
+ }
+
+ /**
+ * Return a closure that can have its wrapped closure changed,
+ * allowing a client to change a previously-supplied closure's
+ * behavior mid-stream.
+ * @param <A> the type of the object passed to the closure
+ */
+ public static <A> Closure<A> wrap(Closure<? super A> closure) {
+ return new ClosureWrapper<A>(closure);
+ }
+
+
+ // ********** safe **********
+
+ /**
+ * Return closure will handle any exceptions thrown by the specified
+ * closure. If the wrapped closure throws an exception,
+ * the exception's stack trace will be printed to {@link System#err
+ * the "standard" error output stream}.
+ * @param <A> the type of the object passed to the closure
+ * @see #safe(Closure, ExceptionHandler)
+ */
+ public static <A> Closure<A> safe(Closure<? super A> closure) {
+ return safe(closure, DefaultExceptionHandler.instance());
+ }
+
+ /**
+ * Return closure will handle any exceptions thrown by the specified
+ * closure with an {@link ExceptionHandler exception handler}. If the
+ * wrapped closure throws an exception, the safe closure will handle
+ * the exception and return.
+ * @param <A> the type of the object passed to the closure
+ * @see #safe(Closure)
+ */
+ public static <A> Closure<A> safe(Closure<? super A> closure, ExceptionHandler exceptionHandler) {
+ return new SafeClosureWrapper<A>(closure, exceptionHandler);
+ }
+
+
+ // ********** reflection **********
+
+ /**
+ * Return a closure that uses Java reflection to invoke the specified
+ * zero-argument method on the argument.
+ * <p>
+ * <strong>NB:</strong> The actual method is determined at execution time,
+ * not construction time. As a result, the closure can be used to emulate
+ * "duck typing".
+ * @param <A> the type of the object passed to the closure
+ */
+ public static <A> Closure<A> execute(String methodName) {
+ return execute(methodName, ClassTools.EMPTY_ARRAY, ObjectTools.EMPTY_OBJECT_ARRAY);
+ }
+
+ /**
+ * Return a closure that uses Java reflection to invoke the specified
+ * single-argument method on the argument.
+ * <p>
+ * <strong>NB:</strong> The actual method is determined at execution time,
+ * not construction time. As a result, the closure can be used to emulate
+ * "duck typing".
+ * @param <A> the type of the object passed to the closure
+ */
+ public static <A> Closure<A> execute(String methodName, Class<?> parameterType, Object argument) {
+ return execute(methodName, new Class<?>[] { parameterType }, new Object[] { argument });
+ }
+
+ /**
+ * Return a closure that uses Java reflection to invoke the specified method
+ * on the argument.
+ * <p>
+ * <strong>NB:</strong> The actual method is determined at execution time,
+ * not construction time. As a result, the closure can be used to emulate
+ * "duck typing".
+ * @param <A> the type of the object passed to the closure
+ */
+ public static <A> Closure<A> execute(String methodName, Class<?>[] parameterTypes, Object[] arguments) {
+ return new MethodClosure<A>(methodName, parameterTypes, arguments);
+ }
+
+
+ // ********** composite **********
+
+ /**
+ * Return a composite of the specified closures. The composite's argument
+ * will be passed to each closure, in sequence.
+ * @param <A> the type of the object passed to the closure
+ */
+ public static <A> Closure<A> composite(Closure<? super A>... closures) {
+ return composite(ArrayTools.iterable(closures));
+ }
+
+ /**
+ * Return a composite of the specified closures. The composite's argument
+ * will be passed to each closure, in sequence.
+ * @param <A> the type of the object passed to the closure
+ */
+ public static <A> Closure<A> composite(Iterable<Closure<? super A>> closures) {
+ return new CompositeClosure<A>(closures);
+ }
+
+
+ // ********** transformer **********
+
+ /**
+ * Adapt the specified {@link Transformer} to the {@link Closure} interface.
+ * The transformer's output is ignored. This really only useful for a
+ * transformer that has side-effects.
+ * @param <A> the type of the object passed to the closure and forwarded to the
+ * transformer
+ * @see TransformerClosure
+ */
+ public static <A, O> Closure<A> adapt(Transformer<? super A, ? extends O> transformer) {
+ return new TransformerClosure<A>(transformer);
+ }
+
+
+ // ********** conditional **********
+
+ /**
+ * Return a closure that passes its argument to the specified predicate to
+ * determine whether to execute the specified closure.
+ * If the predicate evaluates to <code>false</code>, the closure will do
+ * nothing.
+ * @param <A> the type of the object passed to the closure
+ */
+ public static <A> Closure<A> conditionalClosure(Predicate<? super A> predicate, Closure<? super A> closure) {
+ return conditionalClosure(predicate, closure, NullClosure.instance());
+ }
+
+ /**
+ * Return a closure that passes its argument to the specified predicate to
+ * determine which of the two specified closures to execute.
+ * @param <A> the type of the object passed to the closure
+ */
+ public static <A> Closure<A> conditionalClosure(Predicate<? super A> predicate, Closure<? super A> trueClosure, Closure<? super A> falseClosure) {
+ return new ConditionalClosure<A>(predicate, trueClosure, falseClosure);
+ }
+
+
+ // ********** switch **********
+
+ /**
+ * Return a closure that loops over the specified set of predicate/closure
+ * pairs, passing its argument to each predicate to determine
+ * which of the closures to execute. Only the first closure whose predicate
+ * evaluates to <code>true</code> is executed, even if other, following,
+ * predicates would evaluate to <code>true</code>.
+ * If none of the predicates evaluates to <code>true</code>, the closure
+ * will do nothing.
+ * @param <A> the type of the object passed to the closure
+ */
+ public static <A> Closure<A> switchClosure(Iterable<Association<Predicate<? super A>, Closure<? super A>>> closures) {
+ return switchClosure(closures, NullClosure.instance());
+ }
+
+ /**
+ * Return a closure that loops over the specified set of predicate/closure
+ * pairs, passing its argument to each predicate to determine
+ * which of the closures to execute. Only the first closure whose predicate
+ * evaluates to <code>true</code> is executed, even if other, following,
+ * predicates would evaluate to <code>true</code>.
+ * If none of the predicates evaluates to <code>true</code>, the specified
+ * default closure is executed.
+ * @param <A> the type of the object passed to the closure
+ */
+ public static <A> Closure<A> switchClosure(Iterable<Association<Predicate<? super A>, Closure<? super A>>> closures, Closure<? super A> defaultClosure) {
+ return new SwitchClosure<A>(closures, defaultClosure);
+ }
+
+
+ // ********** disabled **********
+
+ /**
+ * Return a closure that will throw an
+ * {@link UnsupportedOperationException exception} when executed.
+ * @param <A> the type of the object passed to the closure
+ */
+ public static <A> Closure<A> disabledClosure() {
+ return DisabledClosure.instance();
+ }
+
+
+ // ********** looping **********
+
+ /**
+ * Return a closure that executes the specified closure the specified
+ * number of times.
+ * @param <A> the type of the object passed to the closure
+ */
+ public static <A> Closure<A> repeat(Closure<? super A> closure, int count) {
+ return new RepeatingClosure<A>(closure, count);
+ }
+
+ /**
+ * Return a closure that executes the specified closure while the specified
+ * predicate evaluates to <code>true</code> when passed the argument.
+ * @param <A> the type of the object passed to the closure
+ */
+ public static <A> Closure<A> while_(Predicate<? super A> predicate, Closure<? super A> closure) {
+ return new WhileClosure<A>(predicate, closure);
+ }
+
+ /**
+ * Return a closure that executes the specified closure until the specified
+ * predicate evaluates to <code>true</code> when passed the argument. The
+ * specifie closure will always execute at least once.
+ * <p>
+ * <strong>NB:</strong> This is the inverse of the Java <code>do-while</code>
+ * statement (i.e. it executes until the predicate evaluates to
+ * <strong><code>true</code></strong>,
+ * <em>not</em> <code>false</code>).
+ * @param <A> the type of the object passed to the closure
+ */
+ public static <A> Closure<A> until(Closure<? super A> closure, Predicate<? super A> predicate) {
+ return new UntilClosure<A>(closure, predicate);
+ }
+
+
+ // ********** constructor **********
+
+ /**
+ * Suppress default constructor, ensuring non-instantiability.
+ */
+ private ClosureTools() {
+ super();
+ throw new UnsupportedOperationException();
+ }
+}
diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/CompositeClosure.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/CompositeClosure.java
new file mode 100644
index 0000000000..792547aee0
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/CompositeClosure.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.utility.internal.closure;
+
+import org.eclipse.jpt.common.utility.closure.Closure;
+import org.eclipse.jpt.common.utility.internal.ObjectTools;
+import org.eclipse.jpt.common.utility.internal.iterable.IterableTools;
+
+/**
+ * A composite of closures. Pass the composite's argument to each closure,
+ * in sequence.
+ *
+ * @param <A> the type of the object passed to the closure
+ */
+public class CompositeClosure<A>
+ implements Closure<A>
+{
+ private final Iterable<Closure<? super A>> closures;
+
+ public CompositeClosure(Iterable<Closure<? super A>> closures) {
+ super();
+ if (IterableTools.isOrContainsNull(closures)) {
+ throw new NullPointerException();
+ }
+ this.closures = closures;
+ }
+
+ public void execute(A argument) {
+ for (Closure<? super A> closure : this.closures) {
+ closure.execute(argument);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return ObjectTools.toString(this, this.closures);
+ }
+}
diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/CompositeInterruptibleClosure.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/CompositeInterruptibleClosure.java
new file mode 100644
index 0000000000..42113ad0d6
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/CompositeInterruptibleClosure.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.utility.internal.closure;
+
+import org.eclipse.jpt.common.utility.closure.InterruptibleClosure;
+import org.eclipse.jpt.common.utility.internal.ObjectTools;
+import org.eclipse.jpt.common.utility.internal.iterable.IterableTools;
+
+/**
+ * A composite of closures. Pass the chain's argument to each closure,
+ * in sequence.
+ *
+ * @param <A> the type of the object passed to the closure
+ */
+public class CompositeInterruptibleClosure<A>
+ implements InterruptibleClosure<A>
+{
+ private final Iterable<InterruptibleClosure<? super A>> closures;
+
+ public CompositeInterruptibleClosure(Iterable<InterruptibleClosure<? super A>> closures) {
+ super();
+ if (IterableTools.isOrContainsNull(closures)) {
+ throw new NullPointerException();
+ }
+ this.closures = closures;
+ }
+
+ public void execute(A argument) throws InterruptedException {
+ for (InterruptibleClosure<? super A> closure : this.closures) {
+ closure.execute(argument);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return ObjectTools.toString(this, this.closures);
+ }
+}
diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/ConditionalClosure.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/ConditionalClosure.java
new file mode 100644
index 0000000000..10c2dcba17
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/ConditionalClosure.java
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.utility.internal.closure;
+
+import org.eclipse.jpt.common.utility.closure.Closure;
+import org.eclipse.jpt.common.utility.internal.ObjectTools;
+import org.eclipse.jpt.common.utility.predicate.Predicate;
+
+/**
+ * Closure that passes its argument to a configured predicate to determine
+ * which of its two closures to execute.
+ *
+ * @param <A> the type of the object passed to the closure
+ */
+public class ConditionalClosure<A>
+ implements Closure<A>
+{
+ private final Predicate<? super A> predicate;
+ private final Closure<? super A> trueClosure;
+ private final Closure<? super A> falseClosure;
+
+ public ConditionalClosure(Predicate<? super A> predicate, Closure<? super A> trueClosure, Closure<? super A> falseClosure) {
+ super();
+ if ((predicate == null) || (trueClosure == null) || (falseClosure == null)) {
+ throw new NullPointerException();
+ }
+ this.predicate = predicate;
+ this.trueClosure = trueClosure;
+ this.falseClosure = falseClosure;
+ }
+
+ public void execute(A argument) {
+ if (this.predicate.evaluate(argument)) {
+ this.trueClosure.execute(argument);
+ } else {
+ this.falseClosure.execute(argument);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return ObjectTools.toString(this, this.predicate);
+ }
+}
diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/ConditionalInterruptibleClosure.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/ConditionalInterruptibleClosure.java
new file mode 100644
index 0000000000..1a3d21c490
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/ConditionalInterruptibleClosure.java
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.utility.internal.closure;
+
+import org.eclipse.jpt.common.utility.closure.InterruptibleClosure;
+import org.eclipse.jpt.common.utility.internal.ObjectTools;
+import org.eclipse.jpt.common.utility.predicate.Predicate;
+
+/**
+ * Closure that passes its argument to a configured predicate to determine
+ * which of its two closures to execute.
+ *
+ * @param <A> the type of the object passed to the closure
+ */
+public class ConditionalInterruptibleClosure<A>
+ implements InterruptibleClosure<A>
+{
+ private final Predicate<? super A> predicate;
+ private final InterruptibleClosure<? super A> trueClosure;
+ private final InterruptibleClosure<? super A> falseClosure;
+
+ public ConditionalInterruptibleClosure(Predicate<? super A> predicate, InterruptibleClosure<? super A> trueClosure, InterruptibleClosure<? super A> falseClosure) {
+ super();
+ if ((predicate == null) || (trueClosure == null) || (falseClosure == null)) {
+ throw new NullPointerException();
+ }
+ this.predicate = predicate;
+ this.trueClosure = trueClosure;
+ this.falseClosure = falseClosure;
+ }
+
+ public void execute(A argument) throws InterruptedException {
+ if (this.predicate.evaluate(argument)) {
+ this.trueClosure.execute(argument);
+ } else {
+ this.falseClosure.execute(argument);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return ObjectTools.toString(this, this.predicate);
+ }
+}
diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/InterruptibleTransformerClosure.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/InterruptibleTransformerClosure.java
new file mode 100644
index 0000000000..39b30f3c70
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/InterruptibleTransformerClosure.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.utility.internal.closure;
+
+import org.eclipse.jpt.common.utility.closure.InterruptibleClosure;
+import org.eclipse.jpt.common.utility.internal.ObjectTools;
+import org.eclipse.jpt.common.utility.transformer.InterruptibleTransformer;
+
+/**
+ * Adapt an {@link InterruptibleTransformer} to the {@link InterruptibleClosure}
+ * interface. The transformer's output is ignored. This really only useful for a
+ * transformer that has side-effects.
+ *
+ * @param <A> the type of the object passed to the closure and forwarded to the
+ * transformer
+ */
+public class InterruptibleTransformerClosure<A>
+ implements InterruptibleClosure<A>
+{
+ private final InterruptibleTransformer<? super A, ?> transformer;
+
+ public InterruptibleTransformerClosure(InterruptibleTransformer<? super A, ?> transformer) {
+ super();
+ if (transformer == null) {
+ throw new NullPointerException();
+ }
+ this.transformer = transformer;
+ }
+
+ public void execute(A argument) throws InterruptedException {
+ this.transformer.transform(argument);
+ }
+
+ @Override
+ public String toString() {
+ return ObjectTools.toString(this, this.transformer);
+ }
+}
diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/MethodClosure.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/MethodClosure.java
new file mode 100644
index 0000000000..bea0748c6f
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/MethodClosure.java
@@ -0,0 +1,75 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.utility.internal.closure;
+
+import java.io.Serializable;
+import java.util.Arrays;
+import org.eclipse.jpt.common.utility.internal.ArrayTools;
+import org.eclipse.jpt.common.utility.internal.ClassTools;
+import org.eclipse.jpt.common.utility.internal.ObjectTools;
+import org.eclipse.jpt.common.utility.closure.Closure;
+
+/**
+ * A closure that uses Java reflection to invoke a method on the argument.
+ * <p>
+ * <strong>NB:</strong> The actual method is determined at execution time,
+ * not construction time. As a result, the closure can be used to emulate
+ * "duck typing".
+ *
+ * @param <A> the type of the object passed to the closure
+ *
+ * @see Class#getDeclaredMethod(String, Class...)
+ * @see java.lang.reflect.Method#invoke(Object, Object...)
+ */
+public class MethodClosure<A>
+ implements Closure<A>, Serializable
+{
+ private final String methodName;
+ private final Class<?>[] parameterTypes;
+ private final Object[] arguments;
+
+ private static final long serialVersionUID = 1L;
+
+
+ public MethodClosure(String methodName, Class<?>[] parameterTypes, Object[] arguments) {
+ super();
+ if ((methodName == null) || ArrayTools.isOrContainsNull(parameterTypes) || (arguments == null)) {
+ throw new NullPointerException();
+ }
+ this.methodName = methodName;
+ this.parameterTypes = parameterTypes;
+ this.arguments = arguments;
+ }
+
+ public void execute(A argument) {
+ ObjectTools.execute(argument, this.methodName, this.parameterTypes, this.arguments);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if ( ! (o instanceof MethodClosure<?>)) {
+ return false;
+ }
+ MethodClosure<?> other = (MethodClosure<?>) o;
+ return ObjectTools.equals(this.methodName, other.methodName) &&
+ Arrays.equals(this.parameterTypes, other.parameterTypes) &&
+ Arrays.equals(this.arguments, other.arguments);
+ }
+
+ @Override
+ public int hashCode() {
+ return this.methodName.hashCode() ^ Arrays.hashCode(this.parameterTypes) ^ Arrays.hashCode(this.arguments);
+ }
+
+ @Override
+ public String toString() {
+ return ObjectTools.toString(this, ClassTools.buildMethodSignature(this.methodName, this.parameterTypes));
+ }
+}
diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/NullCheckClosureWrapper.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/NullCheckClosureWrapper.java
new file mode 100644
index 0000000000..cecd255b67
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/NullCheckClosureWrapper.java
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.utility.internal.closure;
+
+import org.eclipse.jpt.common.utility.closure.Closure;
+import org.eclipse.jpt.common.utility.command.Command;
+import org.eclipse.jpt.common.utility.internal.ObjectTools;
+
+/**
+ * Closure wrapper that checks for a <code>null</code> argument before forwarding
+ * the argument to the wrapped closure. If the argument is <code>null</code>,
+ * the closure will execute the configured command.
+ *
+ * @param <A> the type of the object passed to the closure
+ */
+public class NullCheckClosureWrapper<A>
+ implements Closure<A>
+{
+ private final Closure<? super A> closure;
+ private final Command nullCommand;
+
+
+ public NullCheckClosureWrapper(Closure<? super A> closure, Command nullCommand) {
+ super();
+ if (closure == null) {
+ throw new NullPointerException();
+ }
+ this.closure = closure;
+ this.nullCommand = nullCommand;
+ }
+
+ public void execute(A argument) {
+ if (argument == null) {
+ this.nullCommand.execute();
+ } else {
+ this.closure.execute(argument);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return ObjectTools.toString(this, this.closure);
+ }
+}
diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/NullCheckInterruptibleClosureWrapper.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/NullCheckInterruptibleClosureWrapper.java
new file mode 100644
index 0000000000..398fc4cbed
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/NullCheckInterruptibleClosureWrapper.java
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.utility.internal.closure;
+
+import org.eclipse.jpt.common.utility.closure.InterruptibleClosure;
+import org.eclipse.jpt.common.utility.command.InterruptibleCommand;
+import org.eclipse.jpt.common.utility.internal.ObjectTools;
+
+/**
+ * Closure wrapper that checks for a <code>null</code> argument before forwarding
+ * the argument to the wrapped closure. If the argument is <code>null</code>,
+ * the closer will execute the configured command.
+ *
+ * @param <A> the type of the object passed to the closure
+ */
+public class NullCheckInterruptibleClosureWrapper<A>
+ implements InterruptibleClosure<A>
+{
+ private final InterruptibleClosure<? super A> closure;
+ private final InterruptibleCommand nullCommand;
+
+
+ public NullCheckInterruptibleClosureWrapper(InterruptibleClosure<? super A> closure, InterruptibleCommand nullCommand) {
+ super();
+ if (closure == null) {
+ throw new NullPointerException();
+ }
+ this.closure = closure;
+ this.nullCommand = nullCommand;
+ }
+
+ public void execute(A argument) throws InterruptedException {
+ if (argument == null) {
+ this.nullCommand.execute();
+ } else {
+ this.closure.execute(argument);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return ObjectTools.toString(this, this.closure);
+ }
+}
diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/RepeatingClosure.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/RepeatingClosure.java
new file mode 100644
index 0000000000..a6f15da783
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/RepeatingClosure.java
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.utility.internal.closure;
+
+import org.eclipse.jpt.common.utility.closure.Closure;
+import org.eclipse.jpt.common.utility.internal.ObjectTools;
+
+/**
+ * Closure that executes another closure a specified number of times.
+ *
+ * @param <A> the type of the object passed to the closure
+ */
+public class RepeatingClosure<A>
+ implements Closure<A>
+{
+ private final int count;
+ private final Closure<? super A> closure;
+
+ public RepeatingClosure(Closure<? super A> closure, int count) {
+ super();
+ if (closure == null) {
+ throw new NullPointerException();
+ }
+ if (count <= 0) {
+ throw new IndexOutOfBoundsException("invalid count: " + count); //$NON-NLS-1$
+ }
+ this.closure = closure;
+ this.count = count;
+ }
+
+ public void execute(A argument) {
+ for (int i = this.count; i-- > 0;) {
+ this.closure.execute(argument);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return ObjectTools.toString(this, this.closure);
+ }
+}
diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/RepeatingInterruptibleClosure.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/RepeatingInterruptibleClosure.java
new file mode 100644
index 0000000000..906e7dd695
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/RepeatingInterruptibleClosure.java
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.utility.internal.closure;
+
+import org.eclipse.jpt.common.utility.closure.InterruptibleClosure;
+import org.eclipse.jpt.common.utility.internal.ObjectTools;
+
+/**
+ * InterruptibleClosure that executes another closure a specified number of times.
+ *
+ * @param <A> the type of the object passed to the closure
+ */
+public class RepeatingInterruptibleClosure<A>
+ implements InterruptibleClosure<A>
+{
+ private final int count;
+ private final InterruptibleClosure<? super A> closure;
+
+ public RepeatingInterruptibleClosure(InterruptibleClosure<? super A> closure, int count) {
+ super();
+ if (closure == null) {
+ throw new NullPointerException();
+ }
+ if (count <= 0) {
+ throw new IndexOutOfBoundsException("invalid count: " + count); //$NON-NLS-1$
+ }
+ this.closure = closure;
+ this.count = count;
+ }
+
+ public void execute(A argument) throws InterruptedException {
+ for (int i = this.count; i-- > 0;) {
+ this.closure.execute(argument);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return ObjectTools.toString(this, this.closure);
+ }
+}
diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/SafeClosureWrapper.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/SafeClosureWrapper.java
new file mode 100644
index 0000000000..0fae6e1ca7
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/SafeClosureWrapper.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.utility.internal.closure;
+
+import org.eclipse.jpt.common.utility.exception.ExceptionHandler;
+import org.eclipse.jpt.common.utility.internal.ObjectTools;
+import org.eclipse.jpt.common.utility.closure.Closure;
+
+/**
+ * Closure wrapper that will handle any exceptions thrown by the wrapped
+ * closure with an {@link ExceptionHandler exception handler}. If the
+ * wrapped closure throws an exception, the safe closure will handle
+ * the exception and return.
+ *
+ * @param <A> the type of the object passed to the closure
+ */
+public class SafeClosureWrapper<A>
+ implements Closure<A>
+{
+ private final Closure<? super A> closure;
+ private final ExceptionHandler exceptionHandler;
+
+
+ public SafeClosureWrapper(Closure<? super A> closure, ExceptionHandler exceptionHandler) {
+ super();
+ if ((closure == null) || (exceptionHandler == null)) {
+ throw new NullPointerException();
+ }
+ this.closure = closure;
+ this.exceptionHandler = exceptionHandler;
+ }
+
+ public void execute(A argument) {
+ try {
+ this.closure.execute(argument);
+ } catch (Throwable ex) {
+ this.exceptionHandler.handleException(ex);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return ObjectTools.toString(this, this.closure);
+ }
+}
diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/SafeInterruptibleClosureWrapper.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/SafeInterruptibleClosureWrapper.java
new file mode 100644
index 0000000000..21060ec37b
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/SafeInterruptibleClosureWrapper.java
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.utility.internal.closure;
+
+import org.eclipse.jpt.common.utility.closure.InterruptibleClosure;
+import org.eclipse.jpt.common.utility.exception.ExceptionHandler;
+import org.eclipse.jpt.common.utility.internal.ObjectTools;
+
+/**
+ * Closure wrapper that will handle any exceptions (other than
+ * {@link InterruptedException}) thrown by the wrapped
+ * closure with an {@link ExceptionHandler exception handler}. If the
+ * wrapped closure throws an exception, the safe closure will handle
+ * the exception and return.
+ *
+ * @param <A> the type of the object passed to the closure
+ */
+public class SafeInterruptibleClosureWrapper<A>
+ implements InterruptibleClosure<A>
+{
+ private final InterruptibleClosure<? super A> closure;
+ private final ExceptionHandler exceptionHandler;
+
+
+ public SafeInterruptibleClosureWrapper(InterruptibleClosure<? super A> closure, ExceptionHandler exceptionHandler) {
+ super();
+ if ((closure == null) || (exceptionHandler == null)) {
+ throw new NullPointerException();
+ }
+ this.closure = closure;
+ this.exceptionHandler = exceptionHandler;
+ }
+
+ public void execute(A argument) throws InterruptedException {
+ try {
+ this.closure.execute(argument);
+ } catch (InterruptedException ex) {
+ throw ex;
+ } catch (Throwable ex) {
+ this.exceptionHandler.handleException(ex);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return ObjectTools.toString(this, this.closure);
+ }
+}
diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/SwitchClosure.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/SwitchClosure.java
new file mode 100644
index 0000000000..efce303681
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/SwitchClosure.java
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.utility.internal.closure;
+
+import org.eclipse.jpt.common.utility.Association;
+import org.eclipse.jpt.common.utility.closure.Closure;
+import org.eclipse.jpt.common.utility.internal.ObjectTools;
+import org.eclipse.jpt.common.utility.internal.iterable.IterableTools;
+import org.eclipse.jpt.common.utility.predicate.Predicate;
+
+/**
+ * Closure that loops over a configured set of predicate/closure pairs,
+ * passing its argument to each predicate to determine
+ * which of the closures to execute. Only the first closure whose predicate
+ * evaluates to <code>true</code> is executed, even if other, following,
+ * predicates would evaluate to <code>true</code>.
+ * If none of the predicates evaluates to <code>true</code>, the default closure
+ * is executed.
+ *
+ * @param <A> the type of the object passed to the closure
+ */
+public class SwitchClosure<A>
+ implements Closure<A>
+{
+ private final Iterable<Association<Predicate<? super A>, Closure<? super A>>> closures;
+ private final Closure<? super A> defaultClosure;
+
+ public SwitchClosure(Iterable<Association<Predicate<? super A>, Closure<? super A>>> closures, Closure<? super A> defaultClosure) {
+ super();
+ if (IterableTools.isOrContainsNull(closures) || (defaultClosure == null)) {
+ throw new NullPointerException();
+ }
+ this.closures = closures;
+ this.defaultClosure = defaultClosure;
+ }
+
+ public void execute(A argument) {
+ for (Association<Predicate<? super A>, Closure<? super A>> association : this.closures) {
+ if (association.getKey().evaluate(argument)) {
+ association.getValue().execute(argument);
+ return; // execute only one closure
+ }
+ }
+ this.defaultClosure.execute(argument);
+ }
+
+ @Override
+ public String toString() {
+ return ObjectTools.toString(this, this.closures);
+ }
+}
diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/SwitchInterruptibleClosure.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/SwitchInterruptibleClosure.java
new file mode 100644
index 0000000000..bbc5bcb167
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/SwitchInterruptibleClosure.java
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.utility.internal.closure;
+
+import org.eclipse.jpt.common.utility.Association;
+import org.eclipse.jpt.common.utility.closure.InterruptibleClosure;
+import org.eclipse.jpt.common.utility.internal.ObjectTools;
+import org.eclipse.jpt.common.utility.internal.iterable.IterableTools;
+import org.eclipse.jpt.common.utility.predicate.Predicate;
+
+/**
+ * Interruptible closure that loops over a configured set of predicate/closure pairs,
+ * passing its argument to each predicate to determine
+ * which of the closures to execute. Only the first closure whose predicate
+ * evaluates to <code>true</code> is executed, even if other, following,
+ * predicates would evaluate to <code>true</code>.
+ * If none of the predicates evaluates to <code>true</code>, the default closure
+ * is executed.
+ *
+ * @param <A> the type of the object passed to the closure
+ */
+public class SwitchInterruptibleClosure<A>
+ implements InterruptibleClosure<A>
+{
+ private final Iterable<Association<Predicate<? super A>, InterruptibleClosure<? super A>>> closures;
+ private final InterruptibleClosure<? super A> defaultInterruptibleClosure;
+
+ public SwitchInterruptibleClosure(Iterable<Association<Predicate<? super A>, InterruptibleClosure<? super A>>> closures, InterruptibleClosure<? super A> defaultInterruptibleClosure) {
+ super();
+ if (IterableTools.isOrContainsNull(closures) || (defaultInterruptibleClosure == null)) {
+ throw new NullPointerException();
+ }
+ this.closures = closures;
+ this.defaultInterruptibleClosure = defaultInterruptibleClosure;
+ }
+
+ public void execute(A argument) throws InterruptedException {
+ for (Association<Predicate<? super A>, InterruptibleClosure<? super A>> association : this.closures) {
+ if (association.getKey().evaluate(argument)) {
+ association.getValue().execute(argument);
+ return; // execute only one closure
+ }
+ }
+ this.defaultInterruptibleClosure.execute(argument);
+ }
+
+ @Override
+ public String toString() {
+ return ObjectTools.toString(this, this.closures);
+ }
+}
diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/TransformerClosure.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/TransformerClosure.java
new file mode 100644
index 0000000000..3846f7c6b4
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/TransformerClosure.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.utility.internal.closure;
+
+import org.eclipse.jpt.common.utility.closure.Closure;
+import org.eclipse.jpt.common.utility.internal.ObjectTools;
+import org.eclipse.jpt.common.utility.transformer.Transformer;
+
+/**
+ * Adapt a {@link Transformer} to the {@link Closure} interface.
+ * The transformer's output is ignored. This really only useful for a
+ * transformer that has side-effects.
+ *
+ * @param <A> the type of the object passed to the closure and forwarded to the
+ * transformer
+ */
+public class TransformerClosure<A>
+ implements Closure<A>
+{
+ private final Transformer<? super A, ?> transformer;
+
+ public TransformerClosure(Transformer<? super A, ?> transformer) {
+ super();
+ if (transformer == null) {
+ throw new NullPointerException();
+ }
+ this.transformer = transformer;
+ }
+
+ public void execute(A argument) {
+ this.transformer.transform(argument);
+ }
+
+ @Override
+ public String toString() {
+ return ObjectTools.toString(this, this.transformer);
+ }
+}
diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/UntilClosure.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/UntilClosure.java
new file mode 100644
index 0000000000..7efe5ed941
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/UntilClosure.java
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.utility.internal.closure;
+
+import org.eclipse.jpt.common.utility.closure.Closure;
+import org.eclipse.jpt.common.utility.internal.ObjectTools;
+import org.eclipse.jpt.common.utility.predicate.Predicate;
+
+/**
+ * Closure that executes another closure until a predicate evaluates to
+ * <code>true</code> when passed the argument. The wrapped closure will
+ * always execute at least once.
+ * <p>
+ * <strong>NB:</strong> This is the inverse of the Java <code>do-while</code>
+ * statement (i.e. it executes until the predicate evaluates to
+ * <strong><code>true</code></strong>,
+ * <em>not</em> <code>false</code>).
+ *
+ * @param <A> the type of the object passed to the closure
+ */
+public class UntilClosure<A>
+ implements Closure<A>
+{
+ private final Closure<? super A> closure;
+ private final Predicate<? super A> predicate;
+
+ public UntilClosure(Closure<? super A> closure, Predicate<? super A> predicate) {
+ super();
+ if ((closure == null) || (predicate == null)) {
+ throw new NullPointerException();
+ }
+ this.predicate = predicate;
+ this.closure = closure;
+ }
+
+ public void execute(A argument) {
+ do {
+ this.closure.execute(argument);
+ } while ( ! this.predicate.evaluate(argument));
+ }
+
+ @Override
+ public String toString() {
+ return ObjectTools.toString(this, this.predicate);
+ }
+}
diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/UntilInterruptibleClosure.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/UntilInterruptibleClosure.java
new file mode 100644
index 0000000000..b7df93e05a
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/UntilInterruptibleClosure.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.utility.internal.closure;
+
+import org.eclipse.jpt.common.utility.closure.InterruptibleClosure;
+import org.eclipse.jpt.common.utility.internal.ObjectTools;
+import org.eclipse.jpt.common.utility.predicate.Predicate;
+
+/**
+ * Interruptible closure that executes another closure until a predicate evaluates to
+ * <code>true</code> when passed the argument. The
+ * <p>
+ * <strong>NB:</strong> This is the inverse of the Java <code>do-while</code>
+ * statement (i.e. it executes until the predicate evaluates to
+ * <strong><code>true</code></strong>,
+ * <em>not</em> <code>false</code>).
+ *
+ * @param <A> the type of the object passed to the closure
+ */
+public class UntilInterruptibleClosure<A>
+ implements InterruptibleClosure<A>
+{
+ private final InterruptibleClosure<? super A> closure;
+ private final Predicate<? super A> predicate;
+
+ public UntilInterruptibleClosure(InterruptibleClosure<? super A> closure, Predicate<? super A> predicate) {
+ super();
+ if ((closure == null) || (predicate == null)) {
+ throw new NullPointerException();
+ }
+ this.predicate = predicate;
+ this.closure = closure;
+ }
+
+ public void execute(A argument) throws InterruptedException {
+ do {
+ this.closure.execute(argument);
+ } while ( ! this.predicate.evaluate(argument));
+ }
+
+ @Override
+ public String toString() {
+ return ObjectTools.toString(this, this.predicate);
+ }
+}
diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/WhileClosure.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/WhileClosure.java
new file mode 100644
index 0000000000..7c6164aeb0
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/WhileClosure.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.utility.internal.closure;
+
+import org.eclipse.jpt.common.utility.closure.Closure;
+import org.eclipse.jpt.common.utility.internal.ObjectTools;
+import org.eclipse.jpt.common.utility.predicate.Predicate;
+
+/**
+ * Closure that executes another closure while a predicate evaluates to
+ * <code>true</code> when passed the argument.
+ *
+ * @param <A> the type of the object passed to the closure
+ */
+public class WhileClosure<A>
+ implements Closure<A>
+{
+ private final Predicate<? super A> predicate;
+ private final Closure<? super A> closure;
+
+ public WhileClosure(Predicate<? super A> predicate, Closure<? super A> closure) {
+ super();
+ if ((predicate == null) || (closure == null)) {
+ throw new NullPointerException();
+ }
+ this.predicate = predicate;
+ this.closure = closure;
+ }
+
+ public void execute(A argument) {
+ while (this.predicate.evaluate(argument)) {
+ this.closure.execute(argument);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return ObjectTools.toString(this, this.predicate);
+ }
+}
diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/WhileInterruptibleClosure.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/WhileInterruptibleClosure.java
new file mode 100644
index 0000000000..90b89f30b5
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/WhileInterruptibleClosure.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.utility.internal.closure;
+
+import org.eclipse.jpt.common.utility.closure.InterruptibleClosure;
+import org.eclipse.jpt.common.utility.internal.ObjectTools;
+import org.eclipse.jpt.common.utility.predicate.Predicate;
+
+/**
+ * InterruptibleClosure that executes another closure while a predicate evaluates to
+ * <code>true</code> when passed the argument.
+ *
+ * @param <A> the type of the object passed to the closure
+ */
+public class WhileInterruptibleClosure<A>
+ implements InterruptibleClosure<A>
+{
+ private final Predicate<? super A> predicate;
+ private final InterruptibleClosure<? super A> closure;
+
+ public WhileInterruptibleClosure(Predicate<? super A> predicate, InterruptibleClosure<? super A> closure) {
+ super();
+ if ((predicate == null) || (closure == null)) {
+ throw new NullPointerException();
+ }
+ this.predicate = predicate;
+ this.closure = closure;
+ }
+
+ public void execute(A argument) throws InterruptedException {
+ while (this.predicate.evaluate(argument)) {
+ this.closure.execute(argument);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return ObjectTools.toString(this, this.predicate);
+ }
+}
diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/comparator/ComparatorTools.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/comparator/ComparatorTools.java
new file mode 100644
index 0000000000..12881f2b13
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/comparator/ComparatorTools.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.utility.internal.comparator;
+
+import java.util.Comparator;
+import org.eclipse.jpt.common.utility.internal.transformer.TransformationComparator;
+import org.eclipse.jpt.common.utility.transformer.Transformer;
+
+/**
+ * {@link Comparator} utility methods.
+ */
+public final class ComparatorTools {
+
+ // ********** transformation **********
+
+ /**
+ * Return a comparator will transform the elements to be compared and
+ * compare the resulting outputs (i.e. assume the outputs
+ * implement the {@link Comparable} interface).
+ *
+ * @param <E> the type of elements to be compared
+ * @param <O> the type of the result of transforming the elements and the type
+ * of the elements to be compared by the wrapped comaparator, if present
+ *
+ * @see TransformationComparator
+ */
+ public static <E, O> Comparator<E> transformationComparator(Transformer<? super E, ? extends O> transformer) {
+ return transformationComparator(transformer, null);
+ }
+
+ /**
+ * Return a comparator will transform the elements to be compared and pass the
+ * resulting outputs to a specified comparator.
+ * If the specified comparator is <code>null</code>,
+ * the natural ordering of the outputs will be used (i.e. assume the outputs
+ * implement the {@link Comparable} interface).
+ *
+ * @param <E> the type of elements to be compared
+ * @param <O> the type of the result of transforming the elements and the type
+ * of the elements to be compared by the wrapped comaparator, if present
+ *
+ * @see TransformationComparator
+ */
+ public static <E, O> Comparator<E> transformationComparator(Transformer<? super E, ? extends O> transformer, Comparator<O> comparator) {
+ return new TransformationComparator<E, O>(transformer, comparator);
+ }
+
+
+ // ********** constructor **********
+
+ /**
+ * Suppress default constructor, ensuring non-instantiability.
+ */
+ private ComparatorTools() {
+ super();
+ throw new UnsupportedOperationException();
+ }
+}
diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/iterable/IterableTools.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/iterable/IterableTools.java
index f7d0179e40..6a77ae72fc 100644
--- a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/iterable/IterableTools.java
+++ b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/iterable/IterableTools.java
@@ -71,6 +71,22 @@ public final class IterableTools {
}
/**
+ * Return whether the specified iterable is <code>null</code>
+ * or, if it is not <code>null</code>, contains a <code>null</code>.
+ * Convenient for argument checking.
+ */
+ public static boolean isOrContainsNull(Iterable<?> iterable) {
+ return (iterable == null) || contains(iterable, null);
+ }
+
+ /**
+ * Return whether the specified array contains a <code>null</code>.
+ */
+ public static boolean containsNull(Iterable<?> iterable) {
+ return contains(iterable, null);
+ }
+
+ /**
* Return whether the specified iterable contains the
* specified element.
*/
diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/transformer/ClosureTransformer.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/transformer/ClosureTransformer.java
new file mode 100644
index 0000000000..cd5c923b46
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/transformer/ClosureTransformer.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.utility.internal.transformer;
+
+import org.eclipse.jpt.common.utility.closure.Closure;
+import org.eclipse.jpt.common.utility.internal.ObjectTools;
+import org.eclipse.jpt.common.utility.transformer.Transformer;
+
+/**
+ * Adapt a {@link Closure} to the {@link Transformer} interface.
+ * The transformer will always return <code>null</code>.
+ *
+ * @param <I> input: the type of the object passed to the transformer and forwarded
+ * to the closure
+ * @param <O> output: the type of the object returned by the transformer; always
+ * <code>null</code>
+ */
+public class ClosureTransformer<I, O>
+ implements Transformer<I, O>
+{
+ private final Closure<? super I> closure;
+
+ public ClosureTransformer(Closure<? super I> closure) {
+ super();
+ if (closure == null) {
+ throw new NullPointerException();
+ }
+ this.closure = closure;
+ }
+
+ public O transform(I input) {
+ this.closure.execute(input);
+ return null;
+ }
+
+ @Override
+ public String toString() {
+ return ObjectTools.toString(this, this.closure);
+ }
+}
diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/transformer/ConditionalTransformer.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/transformer/ConditionalTransformer.java
new file mode 100644
index 0000000000..42a7f5dbc3
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/transformer/ConditionalTransformer.java
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.utility.internal.transformer;
+
+import org.eclipse.jpt.common.utility.transformer.Transformer;
+import org.eclipse.jpt.common.utility.internal.ObjectTools;
+import org.eclipse.jpt.common.utility.predicate.Predicate;
+
+/**
+ * Transformer that passes its input to a configured predicate to determine
+ * which of its two transformers to execute.
+ *
+ * @param <I> input: the type of the object passed to the transformer
+ * @param <O> output: the type of the object returned by the transformer
+ */
+public class ConditionalTransformer<I, O>
+ implements Transformer<I, O>
+{
+ private final Predicate<? super I> predicate;
+ private final Transformer<? super I, ? extends O> trueTransformer;
+ private final Transformer<? super I, ? extends O> falseTransformer;
+
+ public ConditionalTransformer(Predicate<? super I> predicate, Transformer<? super I, ? extends O> trueTransformer, Transformer<? super I, ? extends O> falseTransformer) {
+ super();
+ if ((predicate == null) || (trueTransformer == null) || (falseTransformer == null)) {
+ throw new NullPointerException();
+ }
+ this.predicate = predicate;
+ this.trueTransformer = trueTransformer;
+ this.falseTransformer = falseTransformer;
+ }
+
+ public O transform(I input) {
+ return this.predicate.evaluate(input) ?
+ this.trueTransformer.transform(input) :
+ this.falseTransformer.transform(input);
+ }
+
+ @Override
+ public String toString() {
+ return ObjectTools.toString(this, this.predicate);
+ }
+}
diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/transformer/SwitchTransformer.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/transformer/SwitchTransformer.java
new file mode 100644
index 0000000000..35b244ab8c
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/transformer/SwitchTransformer.java
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.utility.internal.transformer;
+
+import org.eclipse.jpt.common.utility.Association;
+import org.eclipse.jpt.common.utility.transformer.Transformer;
+import org.eclipse.jpt.common.utility.internal.ObjectTools;
+import org.eclipse.jpt.common.utility.internal.iterable.IterableTools;
+import org.eclipse.jpt.common.utility.predicate.Predicate;
+
+/**
+ * Transformer that loops over a configured set of predicate/transformer pairs,
+ * passing its input to each predicate to determine
+ * which of the transformers to execute. Only the first transformer whose predicate
+ * evaluates to <code>true</code> is executed, even if other, following,
+ * predicates would evaluate to <code>true</code>.
+ * If none of the predicates evaluates to <code>true</code>, the default transformer
+ * is executed.
+ *
+ * @param <I> input: the type of the object passed to the transformer
+ * @param <O> output: the type of the object returned by the transformer
+ */
+public class SwitchTransformer<I, O>
+ implements Transformer<I, O>
+{
+ private final Iterable<Association<Predicate<? super I>, Transformer<? super I, ? extends O>>> transformers;
+ private final Transformer<? super I, ? extends O> defaultTransformer;
+
+ public SwitchTransformer(Iterable<Association<Predicate<? super I>, Transformer<? super I, ? extends O>>> transformers, Transformer<? super I, ? extends O> defaultTransformer) {
+ super();
+ if (IterableTools.isOrContainsNull(transformers) || (defaultTransformer == null)) {
+ throw new NullPointerException();
+ }
+ this.transformers = transformers;
+ this.defaultTransformer = defaultTransformer;
+ }
+
+ public O transform(I input) {
+ for (Association<Predicate<? super I>, Transformer<? super I, ? extends O>> association : this.transformers) {
+ if (association.getKey().evaluate(input)) {
+ return association.getValue().transform(input); // execute only one transformer
+ }
+ }
+ return this.defaultTransformer.transform(input);
+ }
+
+ @Override
+ public String toString() {
+ return ObjectTools.toString(this, this.transformers);
+ }
+}
diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/transformer/TransformerChain.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/transformer/TransformerChain.java
index c491d3158e..e053438a92 100644
--- a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/transformer/TransformerChain.java
+++ b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/transformer/TransformerChain.java
@@ -9,9 +9,8 @@
******************************************************************************/
package org.eclipse.jpt.common.utility.internal.transformer;
-import java.util.Arrays;
-import org.eclipse.jpt.common.utility.internal.ArrayTools;
import org.eclipse.jpt.common.utility.internal.ObjectTools;
+import org.eclipse.jpt.common.utility.internal.iterable.IterableTools;
import org.eclipse.jpt.common.utility.transformer.Transformer;
/**
@@ -29,12 +28,11 @@ import org.eclipse.jpt.common.utility.transformer.Transformer;
public class TransformerChain<I, O>
implements Transformer<I, O>
{
- @SuppressWarnings("rawtypes")
- private final Transformer[] transformers;
+ private final Iterable<Transformer<?, ?>> transformers;
- public TransformerChain(@SuppressWarnings("rawtypes") Transformer[] transformers) {
+ public TransformerChain(Iterable<Transformer<?, ?>> transformers) {
super();
- if (ArrayTools.isOrContainsNull(transformers)) {
+ if (IterableTools.isOrContainsNull(transformers)) {
throw new NullPointerException();
}
this.transformers = transformers;
@@ -51,6 +49,6 @@ public class TransformerChain<I, O>
@Override
public String toString() {
- return ObjectTools.toString(this, Arrays.toString(this.transformers));
+ return ObjectTools.toString(this, this.transformers);
}
}
diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/transformer/TransformerTools.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/transformer/TransformerTools.java
index 2afc542bc1..74f1db863c 100644
--- a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/transformer/TransformerTools.java
+++ b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/transformer/TransformerTools.java
@@ -9,14 +9,15 @@
******************************************************************************/
package org.eclipse.jpt.common.utility.internal.transformer;
-import java.util.Comparator;
import java.util.Iterator;
import java.util.Map;
+import org.eclipse.jpt.common.utility.Association;
+import org.eclipse.jpt.common.utility.closure.Closure;
import org.eclipse.jpt.common.utility.exception.ExceptionHandler;
+import org.eclipse.jpt.common.utility.internal.ArrayTools;
import org.eclipse.jpt.common.utility.internal.ClassTools;
import org.eclipse.jpt.common.utility.internal.ObjectTools;
import org.eclipse.jpt.common.utility.internal.exception.DefaultExceptionHandler;
-import org.eclipse.jpt.common.utility.internal.iterator.IteratorTools;
import org.eclipse.jpt.common.utility.predicate.Predicate;
import org.eclipse.jpt.common.utility.transformer.Transformer;
@@ -349,7 +350,6 @@ public final class TransformerTools {
* Wrap the specified transformer converting it
* into one that converts the same input object into an <em>iterator</em>
* of objects of the same type as the input object.
- *
* @param <I> input: the type of the object passed to the transformer; also the
* type of object returned by the output iterator
* @see IterableTransformerWrapper
@@ -555,7 +555,6 @@ public final class TransformerTools {
* Return a transformer that transforms a {@link Class} into an instance
* by calling {@link Class#newInstance()}. Checked exceptions are converted
* to {@link RuntimeException}s.
- *
* @param <O> output: the type of the object returned by the transformer (and
* the class, or superclass of the class, passed to the transformer)
* @see InstantiationTransformer
@@ -631,17 +630,10 @@ public final class TransformerTools {
// ********** chain **********
/**
- * @see #chain(Transformer[])
+ * @see #chain(Iterable)
*/
- public static <I, O> Transformer<I, O> chain(@SuppressWarnings("rawtypes") Iterable<Transformer> transformers) {
- return chain(transformers.iterator());
- }
-
- /**
- * @see #chain(Transformer[])
- */
- public static <I, O> Transformer<I, O> chain(@SuppressWarnings("rawtypes") Iterator<Transformer> transformers) {
- return chain(IteratorTools.toArray(transformers, EMPTY_ARRAY));
+ public static <I, O> Transformer<I, O> chain(@SuppressWarnings("rawtypes") Transformer... transformers) {
+ return chain(ArrayTools.<Transformer<?, ?>>iterable(transformers));
}
/**
@@ -652,44 +644,95 @@ public final class TransformerTools {
* <p>
* <strong>NB:</strong> The transformer's generic types are for convenience only
* and cannot be enforced on the transformers in the chain.
- *
* @param <I> input: the type of the object passed to the transformer
* @param <O> output: the type of the object returned by the transformer
* @see TransformerChain
*/
- public static <I, O> Transformer<I, O> chain(@SuppressWarnings("rawtypes") Transformer[] transformers) {
+ public static <I, O> Transformer<I, O> chain(Iterable<Transformer<?, ?>> transformers) {
return new TransformerChain<I, O>(transformers);
}
- // ********** comparator **********
+ // ********** closure **********
+
+ /**
+ * Adapt the specified {@link Closure} to the {@link Transformer} interface.
+ * The returned transformer will always return <code>null</code>.
+ * @param <I> input: the type of the object passed to the transformer
+ * @param <O> output: the type of the object returned by the transformer
+ * @see ClosureTransformer
+ */
+ public static <I, O> Transformer<I, O> adapt(Closure<? super I> closure) {
+ return new ClosureTransformer<I, O>(closure);
+ }
+
+
+ // ********** conditional **********
/**
- * Return a comparator will transform the elements to be compared and
- * compare the resulting outputs (i.e. assume the outputs
- * implement the {@link Comparable} interface).
- * @param <E> the type of elements to be compared
- * @param <O> the type of the result of transforming the elements and the type
- * of the elements to be compared by the wrapped comaparator, if present
- * @see TransformationComparator
+ * Return a transformer that passes its input to the specified predicate to
+ * determine whether to forward the input to the specified transformer.
+ * If the predicate evaluates to <code>false</code>, the transformer returns
+ * <code>null</code>.
+ * @param <I> input: the type of the object passed to the transformer
+ * @param <O> output: the type of the object returned by the transformer
+ * @see ClosureTransformer
*/
- public static <E, O> Comparator<E> comparator(Transformer<? super E, ? extends O> transformer) {
- return new TransformationComparator<E, O>(transformer, null);
+ public static <I, O> Transformer<I, O> conditionalTransformer(Predicate<? super I> predicate, Transformer<? super I, ? extends O> transformer) {
+ return conditionalTransformer(predicate, transformer, NullOutputTransformer.<I, O>instance());
}
/**
- * Return a comparator will transform the elements to be compared and pass the
- * resulting outputs to a specified transformer.
- * If the specified comparator is <code>null</code>,
- * the natural ordering of the outputs will be used (i.e. assume the outputs
- * implement the {@link Comparable} interface).
- * @param <E> the type of elements to be compared
- * @param <O> the type of the result of transforming the elements and the type
- * of the elements to be compared by the wrapped comaparator, if present
- * @see TransformationComparator
+ * Return a transformer that passes its input to the specified predicate to
+ * determine which of the two specified transformers to execute.
+ * @param <I> input: the type of the object passed to the transformer
+ * @param <O> output: the type of the object returned by the transformer
+ * @see ClosureTransformer
*/
- public static <E, O> Comparator<E> comparator(Transformer<? super E, ? extends O> transformer, Comparator<O> comparator) {
- return new TransformationComparator<E, O>(transformer, comparator);
+ public static <I, O> Transformer<I, O> conditionalTransformer(Predicate<? super I> predicate, Transformer<? super I, ? extends O> trueTransformer, Transformer<? super I, ? extends O> falseTransformer) {
+ return new ConditionalTransformer<I, O>(predicate, trueTransformer, falseTransformer);
+ }
+
+
+ // ********** switch **********
+
+ /**
+ * @see #switchTransformer(Iterable)
+ */
+ public static <I, O> Transformer<I, O> switchTransformer(Association<Predicate<? super I>, Transformer<? super I, ? extends O>>... transformers) {
+ return switchTransformer(ArrayTools.iterable(transformers));
+ }
+
+ /**
+ * Return a transformer that loops over the specified set of
+ * predicate/transformer pairs, passing its input to each predicate to
+ * determine which of the transformers to execute. Only the first
+ * transformer whose predicate evaluates to <code>true</code> is executed,
+ * even if other, following, predicates would evaluate to <code>true</code>.
+ * If none of the predicates evaluates to <code>true</code>, the transformer
+ * returns <code>null</code>.
+ * @param <I> input: the type of the object passed to the transformer
+ * @param <O> output: the type of the object returned by the transformer
+ * @see SwitchTransformer
+ */
+ public static <I, O> Transformer<I, O> switchTransformer(Iterable<Association<Predicate<? super I>, Transformer<? super I, ? extends O>>> transformers) {
+ return switchTransformer(transformers, NullOutputTransformer.<I, O>instance());
+ }
+
+ /**
+ * Return a transformer that loops over the specified set of
+ * predicate/transformer pairs, passing its input to each predicate to
+ * determine which of the transformers to execute. Only the first
+ * transformer whose predicate evaluates to <code>true</code> is executed,
+ * even if other, following, predicates would evaluate to <code>true</code>.
+ * If none of the predicates evaluates to <code>true</code>, the default transformer
+ * is executed.
+ * @param <I> input: the type of the object passed to the transformer
+ * @param <O> output: the type of the object returned by the transformer
+ * @see SwitchTransformer
+ */
+ public static <I, O> Transformer<I, O> switchTransformer(Iterable<Association<Predicate<? super I>, Transformer<? super I, ? extends O>>> transformers, Transformer<? super I, ? extends O> defaultTransformer) {
+ return new SwitchTransformer<I, O>(transformers, defaultTransformer);
}
@@ -750,8 +793,7 @@ public final class TransformerTools {
// ********** empty array **********
- @SuppressWarnings("unchecked")
- public static <I, O> Transformer<I, O>[] emptyArray() {
+ public static Transformer<?, ?>[] emptyArray() {
return EMPTY_ARRAY;
}

Back to the top