From f91968e110d50306c5d8144ea401ba888c66abf7 Mon Sep 17 00:00:00 2001 From: Brian Vosburgh Date: Wed, 20 Jul 2016 11:18:39 -0400 Subject: add BiClosure --- .../jpt/common/utility/closure/BiClosure.java | 38 + .../utility/closure/InterruptibleBiClosure.java | 39 + .../utility/internal/closure/BiClosureAdapter.java | 34 + .../utility/internal/closure/BiClosureTools.java | 364 ++++ .../utility/internal/closure/BiClosureWrapper.java | 53 + .../utility/internal/closure/ClosureTools.java | 381 +++- .../utility/internal/closure/CommandBiClosure.java | 45 + .../internal/closure/CompositeBiClosure.java | 46 + .../utility/internal/closure/CompositeClosure.java | 6 +- .../closure/CompositeInterruptibleBiClosure.java | 46 + .../closure/CompositeInterruptibleClosure.java | 6 +- .../internal/closure/ConditionalClosure.java | 10 +- .../closure/ConditionalInterruptibleClosure.java | 10 +- .../internal/closure/DisabledBiClosure.java | 54 + .../utility/internal/closure/FactoryBiClosure.java | 46 + .../internal/closure/InterruptedBiClosure.java | 54 + .../closure/InterruptibleBiClosureAdapter.java | 35 + .../closure/InterruptibleBiClosureWrapper.java | 53 + .../closure/InterruptibleCommandBiClosure.java | 45 + .../closure/InterruptibleFactoryBiClosure.java | 46 + .../utility/internal/closure/MethodClosure.java | 10 +- .../utility/internal/closure/NullBiClosure.java | 54 + .../internal/closure/NullCheckClosureWrapper.java | 5 +- .../NullCheckInterruptibleClosureWrapper.java | 5 +- .../internal/closure/RepeatingBiClosure.java | 49 + .../utility/internal/closure/RepeatingClosure.java | 6 +- .../closure/RepeatingInterruptibleBiClosure.java | 49 + .../closure/RepeatingInterruptibleClosure.java | 4 +- .../internal/closure/SafeBiClosureWrapper.java | 56 + .../internal/closure/SafeClosureWrapper.java | 7 +- .../closure/SafeInterruptibleBiClosureWrapper.java | 58 + .../closure/SafeInterruptibleClosureWrapper.java | 7 +- .../utility/internal/closure/SwitchClosure.java | 13 +- .../closure/SwitchInterruptibleClosure.java | 19 +- .../internal/closure/ThreadLocalBiClosure.java | 66 + .../internal/closure/ThreadLocalClosure.java | 5 +- .../closure/ThreadLocalInterruptibleBiClosure.java | 67 + .../closure/ThreadLocalInterruptibleClosure.java | 13 +- .../utility/internal/closure/UntilClosure.java | 9 +- .../closure/UntilInterruptibleClosure.java | 9 +- .../utility/internal/closure/WhileClosure.java | 7 +- .../closure/WhileInterruptibleClosure.java | 7 +- .../tests/internal/JptCommonUtilityTests.java | 4 +- .../internal/closure/BiClosureToolsTests.java | 726 ++++++++ .../tests/internal/closure/ClosureToolsTests.java | 1854 ++++++++++++++++++++ .../closure/JptCommonUtilityClosureTests.java | 2 + 46 files changed, 4430 insertions(+), 92 deletions(-) create mode 100644 common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/closure/BiClosure.java create mode 100644 common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/closure/InterruptibleBiClosure.java create mode 100644 common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/BiClosureAdapter.java create mode 100644 common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/BiClosureTools.java create mode 100644 common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/BiClosureWrapper.java create mode 100644 common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/CommandBiClosure.java create mode 100644 common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/CompositeBiClosure.java create mode 100644 common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/CompositeInterruptibleBiClosure.java create mode 100644 common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/DisabledBiClosure.java create mode 100644 common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/FactoryBiClosure.java create mode 100644 common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/InterruptedBiClosure.java create mode 100644 common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/InterruptibleBiClosureAdapter.java create mode 100644 common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/InterruptibleBiClosureWrapper.java create mode 100644 common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/InterruptibleCommandBiClosure.java create mode 100644 common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/InterruptibleFactoryBiClosure.java create mode 100644 common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/NullBiClosure.java create mode 100644 common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/RepeatingBiClosure.java create mode 100644 common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/RepeatingInterruptibleBiClosure.java create mode 100644 common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/SafeBiClosureWrapper.java create mode 100644 common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/SafeInterruptibleBiClosureWrapper.java create mode 100644 common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/ThreadLocalBiClosure.java create mode 100644 common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/ThreadLocalInterruptibleBiClosure.java create mode 100644 common/tests/org.eclipse.jpt.common.utility.tests/src/org/eclipse/jpt/common/utility/tests/internal/closure/BiClosureToolsTests.java create mode 100644 common/tests/org.eclipse.jpt.common.utility.tests/src/org/eclipse/jpt/common/utility/tests/internal/closure/ClosureToolsTests.java diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/closure/BiClosure.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/closure/BiClosure.java new file mode 100644 index 0000000000..5a308c54f4 --- /dev/null +++ b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/closure/BiClosure.java @@ -0,0 +1,38 @@ +/******************************************************************************* + * Copyright (c) 2016 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.closure; + +/** + * Simple interface for implementing a command that takes two arguments. + * The expectation is the closure will have side effects. + *

+ * Provisional API: This interface is part of an interim API that is still + * under development and expected to change significantly before reaching + * stability. It is available at this early stage to solicit feedback from + * pioneering adopters on the understanding that any code that uses this API + * will almost certainly be broken (repeatedly) as the API evolves. + * + * @param the type of the first object passed to the command + * @param the type of the second object passed to the command + * + * @see Closure + * @see org.eclipse.jpt.common.utility.command.Command + * @see org.eclipse.jpt.common.utility.factory.Factory + * @see org.eclipse.jpt.common.utility.transformer.Transformer + */ +public interface BiClosure + extends InterruptibleBiClosure +{ + /** + * Execute the command. The semantics of the command + * is determined by the contract between the client and server. + */ + void execute(A1 argument1, A2 argument2); +} diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/closure/InterruptibleBiClosure.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/closure/InterruptibleBiClosure.java new file mode 100644 index 0000000000..e1e64b7960 --- /dev/null +++ b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/closure/InterruptibleBiClosure.java @@ -0,0 +1,39 @@ +/******************************************************************************* + * Copyright (c) 2016 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.closure; + +/** + * Simple interface for implementing a command that takes two arguments + * and allows for the closure to throw an {@link InterruptedException}. + * The expectation is the closure will have side effects. + *

+ * Provisional API: This interface is part of an interim API that is still + * under development and expected to change significantly before reaching + * stability. It is available at this early stage to solicit feedback from + * pioneering adopters on the understanding that any code that uses this API + * will almost certainly be broken (repeatedly) as the API evolves. + * + * @param the type of the first object passed to the command + * @param the type of the second object passed to the command + * + * @see BiClosure + * @see InterruptibleClosure + * @see org.eclipse.jpt.common.utility.command.InterruptibleCommand + * @see org.eclipse.jpt.common.utility.factory.InterruptibleFactory + * @see org.eclipse.jpt.common.utility.transformer.InterruptibleTransformer + */ +public interface InterruptibleBiClosure { + + /** + * Execute the command. The semantics of the command + * is determined by the contract between the client and server. + */ + void execute(A1 argument1, A2 argument2) throws InterruptedException; +} diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/BiClosureAdapter.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/BiClosureAdapter.java new file mode 100644 index 0000000000..4713a8a48b --- /dev/null +++ b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/BiClosureAdapter.java @@ -0,0 +1,34 @@ +/******************************************************************************* + * Copyright (c) 2012, 2016 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.BiClosure; +import org.eclipse.jpt.common.utility.internal.ObjectTools; + +/** + * Convenience bi-closure that does nothing. + * + * @param the type of the first object passed to the closure + * @param the type of the second object passed to the closure + * + * @see NullBiClosure + */ +public class BiClosureAdapter + implements BiClosure +{ + public void execute(A1 argument1, A2 argument2) { + // NOP + } + + @Override + public String toString() { + return ObjectTools.toString(this); + } +} diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/BiClosureTools.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/BiClosureTools.java new file mode 100644 index 0000000000..b0d2e342c2 --- /dev/null +++ b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/BiClosureTools.java @@ -0,0 +1,364 @@ +/******************************************************************************* + * Copyright (c) 2013, 2016 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.BiClosure; +import org.eclipse.jpt.common.utility.closure.InterruptibleBiClosure; +import org.eclipse.jpt.common.utility.command.Command; +import org.eclipse.jpt.common.utility.command.InterruptibleCommand; +import org.eclipse.jpt.common.utility.exception.ExceptionHandler; +import org.eclipse.jpt.common.utility.factory.Factory; +import org.eclipse.jpt.common.utility.factory.InterruptibleFactory; +import org.eclipse.jpt.common.utility.internal.ArrayTools; +import org.eclipse.jpt.common.utility.internal.exception.DefaultExceptionHandler; + +/** + * {@link BiClosure} utility methods. + */ +public final class BiClosureTools { + + // ********** adapters ********** + + /** + * Adapt the specified {@link Command} to the {@link BiClosure} interface. + * The closure's argument is ignored. + * + * @param the type of the first object passed to the closure + * @param the type of the second object passed to the closure + */ + public static BiClosure adapt(Command command) { + return new CommandBiClosure<>(command); + } + + /** + * Adapt the specified {@link InterruptibleCommand} to the {@link InterruptibleBiClosure} interface. + * The closure's argument is ignored. + * + * @param the type of the first object passed to the closure + * @param the type of the second object passed to the closure + */ + public static InterruptibleBiClosure adapt(InterruptibleCommand command) { + return new InterruptibleCommandBiClosure<>(command); + } + + /** + * Adapt the specified {@link Factory} to the {@link BiClosure} interface. + * The closure's argument and the factory's output are ignored. This really + * only useful for a factory that has side-effects. + * + * @param the type of the first object passed to the closure + * @param the type of the second object passed to the closure + */ + public static BiClosure adapt(Factory factory) { + return new FactoryBiClosure<>(factory); + } + + /** + * Adapt the specified {@link InterruptibleFactory} to the {@link InterruptibleBiClosure} interface. + * The closure's argument and the factory's output are ignored. This really + * only useful for a factory that has side-effects. + * + * @param the type of the first object passed to the closure + * @param the type of the second object passed to the closure + */ + public static InterruptibleBiClosure adapt(InterruptibleFactory factory) { + return new InterruptibleFactoryBiClosure<>(factory); + } + + + // ********** null closure ********** + + /** + * Return a closure that will do nothing. + * + * @param the type of the first object passed to the closure + * @param the type of the second object passed to the closure + * + * @see NullBiClosure + */ + public static BiClosure nullBiClosure() { + return NullBiClosure.instance(); + } + + + // ********** thread local ********** + + /** + * Return a closure that allows the client to specify a different closure + * for each thread. If there is no closure for the current thread, the + * closure will do nothing. + * + * @param the type of the first object passed to the closure + * @param the type of the second object passed to the closure + * @see ThreadLocalBiClosure + */ + public static ThreadLocalBiClosure threadLocalBiClosure() { + return threadLocalBiClosure(NullBiClosure.instance()); + } + + /** + * Return a closure that allows the client to specify a different closure + * for each thread. If there is no closure for the current thread, the + * specified default closure is executed. + * + * @param the type of the first object passed to the closure + * @param the type of the second object passed to the closure + * @see ThreadLocalBiClosure + */ + public static ThreadLocalBiClosure threadLocalBiClosure(BiClosure defaultClosure) { + return new ThreadLocalBiClosure<>(defaultClosure); + } + + /** + * Return a closure that allows the client to specify a different closure + * for each thread. If there is no closure for the current thread, the + * closure will do nothing. + * + * @param the type of the first object passed to the closure + * @param the type of the second object passed to the closure + * @see ThreadLocalBiClosure + */ + public static ThreadLocalInterruptibleBiClosure threadLocalInterruptibleBiClosure() { + return threadLocalInterruptibleBiClosure(NullBiClosure.instance()); + } + + /** + * Return a closure that allows the client to specify a different closure + * for each thread. If there is no closure for the current thread, the + * specified default closure is executed. + * + * @param the type of the first object passed to the closure + * @param the type of the second object passed to the closure + * @see ThreadLocalBiClosure + */ + public static ThreadLocalInterruptibleBiClosure threadLocalInterruptibleBiClosure(InterruptibleBiClosure defaultClosure) { + return new ThreadLocalInterruptibleBiClosure<>(defaultClosure); + } + + + // ********** wrappers ********** + + /** + * Return a closure that can have its wrapped closure changed, + * allowing a client to change a previously-supplied closure's + * behavior mid-stream. + * + * @param the type of the first object passed to the closure + * @param the type of the second object passed to the closure + * + * @see BiClosureWrapper + */ + public static BiClosureWrapper wrap(BiClosure closure) { + return new BiClosureWrapper<>(closure); + } + + /** + * Return a closure that can have its wrapped closure changed, + * allowing a client to change a previously-supplied closure's + * behavior mid-stream. + * + * @param the type of the first object passed to the closure + * @param the type of the second object passed to the closure + * + * @see InterruptibleBiClosureWrapper + */ + public static InterruptibleBiClosureWrapper wrap(InterruptibleBiClosure closure) { + return new InterruptibleBiClosureWrapper<>(closure); + } + + + // ********** safe wrappers ********** + + /** + * Return closure that 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 the type of the first object passed to the closure + * @param the type of the second object passed to the closure + * + * @see #safeBiClosure(BiClosure, ExceptionHandler) + */ + public static BiClosure safeBiClosure(BiClosure closure) { + return safeBiClosure(closure, DefaultExceptionHandler.instance()); + } + + /** + * Return closure that will handle any exceptions thrown by the specified + * closure with the specified exception handler. If the + * wrapped closure throws an exception, the safe closure will handle + * the exception and return. + * + * @param the type of the first object passed to the closure + * @param the type of the second object passed to the closure + * + * @see #safeBiClosure(BiClosure) + */ + public static BiClosure safeBiClosure(BiClosure closure, ExceptionHandler exceptionHandler) { + return new SafeBiClosureWrapper<>(closure, exceptionHandler); + } + + /** + * Return closure that 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 the type of the first object passed to the closure + * @param the type of the second object passed to the closure + * + * @see #safeBiClosure(InterruptibleBiClosure, ExceptionHandler) + */ + public static InterruptibleBiClosure safeBiClosure(InterruptibleBiClosure closure) { + return safeBiClosure(closure, DefaultExceptionHandler.instance()); + } + + /** + * Return closure that will handle any exceptions thrown by the specified + * closure with the specified exception handler. If the + * wrapped closure throws an exception, the safe closure will handle + * the exception and return. + * + * @param the type of the first object passed to the closure + * @param the type of the second object passed to the closure + * + * @see #safeBiClosure(InterruptibleBiClosure) + */ + public static InterruptibleBiClosure safeBiClosure(InterruptibleBiClosure closure, ExceptionHandler exceptionHandler) { + return new SafeInterruptibleBiClosureWrapper<>(closure, exceptionHandler); + } + + + // ********** composite ********** + + /** + * Return a composite of the specified closures. The composite's argument + * will be passed to each closure, in sequence. + * + * @param the type of the first object passed to the closure + * @param the type of the second object passed to the closure + */ + @SafeVarargs + public static BiClosure compositeBiClosure(BiClosure... closures) { + return (closures.length != 0) ? compositeBiClosure_(ArrayTools.iterable(closures)) : nullBiClosure(); + } + + /** + * Return a composite of the specified closures. The composite's argument + * will be passed to each closure, in sequence. + * + * @param the type of the first object passed to the closure + * @param the type of the second object passed to the closure + */ + public static BiClosure compositeBiClosure(Iterable> closures) { + return (closures.iterator().hasNext()) ? compositeBiClosure_(closures) : nullBiClosure(); + } + + /** + * assume non-empty + */ + private static BiClosure compositeBiClosure_(Iterable> closures) { + return new CompositeBiClosure<>(closures); + } + + /** + * Return a composite of the specified closures. The composite's argument + * will be passed to each closure, in sequence. + * + * @param the type of the first object passed to the closure + * @param the type of the second object passed to the closure + */ + @SafeVarargs + public static InterruptibleBiClosure compositeInterruptibleBiClosure(InterruptibleBiClosure... closures) { + return (closures.length != 0) ? compositeInterruptibleBiClosure_(ArrayTools.iterable(closures)) : nullBiClosure(); + } + + /** + * Return a composite of the specified closures. The composite's argument + * will be passed to each closure, in sequence. + * + * @param the type of the first object passed to the closure + * @param the type of the second object passed to the closure + */ + public static InterruptibleBiClosure compositeInterruptibleBiClosure(Iterable> closures) { + return (closures.iterator().hasNext()) ? compositeInterruptibleBiClosure_(closures) : nullBiClosure(); + } + + /** + * assume non-empty + */ + private static InterruptibleBiClosure compositeInterruptibleBiClosure_(Iterable> closures) { + return new CompositeInterruptibleBiClosure<>(closures); + } + + + // ********** disabled ********** + + /** + * Return a closure that will throw an + * {@link UnsupportedOperationException exception} when executed. + * + * @param the type of the first object passed to the closure + * @param the type of the second object passed to the closure + */ + public static BiClosure disabledBiClosure() { + return DisabledBiClosure.instance(); + } + + + // ********** interrupted ********** + + /** + * Return a closure that will throw an + * {@link InterruptedException exception} when executed. + * + * @param the type of the first object passed to the closure + * @param the type of the second object passed to the closure + */ + public static InterruptibleBiClosure interruptedBiClosure() { + return InterruptedBiClosure.instance(); + } + + // ********** looping ********** + + /** + * Return a closure that executes the specified closure the specified + * number of times. + * + * @param the type of the first object passed to the closure + * @param the type of the second object passed to the closure + */ + public static BiClosure repeatingBiClosure(BiClosure closure, int count) { + return new RepeatingBiClosure<>(closure, count); + } + + /** + * Return a closure that executes the specified closure the specified + * number of times. + * + * @param the type of the first object passed to the closure + * @param the type of the second object passed to the closure + */ + public static InterruptibleBiClosure repeatingBiClosure(InterruptibleBiClosure closure, int count) { + return new RepeatingInterruptibleBiClosure<>(closure, count); + } + + + // ********** constructor ********** + + /** + * Suppress default constructor, ensuring non-instantiability. + */ + private BiClosureTools() { + super(); + throw new UnsupportedOperationException(); + } +} diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/BiClosureWrapper.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/BiClosureWrapper.java new file mode 100644 index 0000000000..6f7d4feb6a --- /dev/null +++ b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/BiClosureWrapper.java @@ -0,0 +1,53 @@ +/******************************************************************************* + * Copyright (c) 2012, 2016 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.BiClosure; +import org.eclipse.jpt.common.utility.internal.ObjectTools; + +/** + * Closure wrapper that can have its wrapped closure changed, + * allowing a client to change a previously-supplied closure's + * behavior mid-stream. + * + * @param the type of the first object passed to the closure + * @param the type of the second object passed to the closure + * + * @see #setClosure(BiClosure) + */ +public class BiClosureWrapper + implements BiClosure +{ + protected volatile BiClosure closure; + + public BiClosureWrapper(BiClosure closure) { + super(); + if (closure == null) { + throw new NullPointerException(); + } + this.closure = closure; + } + + public void execute(A1 argument1, A2 argument2) { + this.closure.execute(argument1, argument2); + } + + public void setClosure(BiClosure closure) { + if (closure == null) { + throw new NullPointerException(); + } + this.closure = closure; + } + + @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/ClosureTools.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/ClosureTools.java index 83a4a8f576..aa0864869c 100644 --- 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 @@ -11,15 +11,19 @@ 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.closure.InterruptibleClosure; import org.eclipse.jpt.common.utility.command.Command; +import org.eclipse.jpt.common.utility.command.InterruptibleCommand; import org.eclipse.jpt.common.utility.exception.ExceptionHandler; import org.eclipse.jpt.common.utility.factory.Factory; +import org.eclipse.jpt.common.utility.factory.InterruptibleFactory; 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.InterruptibleTransformer; import org.eclipse.jpt.common.utility.transformer.Transformer; /** @@ -32,26 +36,50 @@ public final class ClosureTools { /** * Adapt the specified {@link Command} to the {@link Closure} interface. * The closure's argument is ignored. + * * @param the type of the object passed to the closure */ public static Closure adapt(Command command) { return new CommandClosure<>(command); } + /** + * Adapt the specified {@link InterruptibleCommand} to the {@link InterruptibleClosure} interface. + * The closure's argument is ignored. + * + * @param the type of the object passed to the closure + */ + public static InterruptibleClosure adapt(InterruptibleCommand command) { + return new InterruptibleCommandClosure<>(command); + } + /** * Adapt the specified {@link Factory} to the {@link Closure} interface. - * The closure's argument and the factory's output are ignored. This really - * only useful for a factory that has side-effects. + * The closure's argument and the factory's output are ignored. In practice, + * this is useful only for a factory that has side-effects. + * * @param the type of the object passed to the closure */ public static Closure adapt(Factory factory) { return new FactoryClosure<>(factory); } + /** + * Adapt the specified {@link InterruptibleFactory} to the {@link InterruptibleClosure} interface. + * The closure's argument and the factory's output are ignored. In practice, + * this is useful only for a factory that has side-effects. + * + * @param the type of the object passed to the closure + */ + public static InterruptibleClosure adapt(InterruptibleFactory factory) { + return new InterruptibleFactoryClosure<>(factory); + } + /** * Adapt the specified {@link Transformer} to the {@link Closure} interface. - * The transformer's output is ignored. This really only useful for a + * The transformer's output is ignored. In practice, this is useful only for a * transformer that has side-effects. + * * @param the type of the object passed to the closure and forwarded to * the transformer */ @@ -59,6 +87,32 @@ public final class ClosureTools { return new TransformerClosure<>(transformer); } + /** + * Adapt the specified {@link InterruptibleTransformer} to the {@link InterruptibleClosure} interface. + * The transformer's output is ignored. In practice, this is useful only for a + * transformer that has side-effects. + * + * @param the type of the object passed to the closure and forwarded to + * the transformer + */ + public static InterruptibleClosure adapt(InterruptibleTransformer transformer) { + return new InterruptibleTransformerClosure<>(transformer); + } + + + // ********** null closure ********** + + /** + * Return a closure that will do nothing. + * + * @param the type of the object passed to the closure + * + * @see NullClosure + */ + public static Closure nullClosure() { + return NullClosure.instance(); + } + // ********** thread local ********** @@ -66,33 +120,94 @@ public final class ClosureTools { * Return a closure that allows the client to specify a different closure * for each thread. If there is no closure for the current thread, the * closure will do nothing. + * * @param the type of the object passed to the closure + * * @see ThreadLocalClosure */ public static ThreadLocalClosure threadLocalClosure() { - return threadLocalClosure(NullClosure.instance()); + return threadLocalClosure(nullClosure()); } /** * Return a closure that allows the client to specify a different closure * for each thread. If there is no closure for the current thread, the * specified default closure is executed. + * * @param the type of the object passed to the closure + * * @see ThreadLocalClosure */ public static ThreadLocalClosure threadLocalClosure(Closure defaultClosure) { return new ThreadLocalClosure<>(defaultClosure); } + /** + * Return a closure that allows the client to specify a different closure + * for each thread. If there is no closure for the current thread, the + * closure will do nothing. + * + * @param the type of the object passed to the closure + * + * @see ThreadLocalInterruptibleClosure + */ + public static ThreadLocalInterruptibleClosure threadLocalInterruptibleClosure() { + return threadLocalInterruptibleClosure(nullClosure()); + } - // ********** wrappers ********** + /** + * Return a closure that allows the client to specify a different closure + * for each thread. If there is no closure for the current thread, the + * specified default closure is executed. + * + * @param the type of the object passed to the closure + * + * @see ThreadLocalInterruptibleClosure + */ + public static ThreadLocalInterruptibleClosure threadLocalInterruptibleClosure(InterruptibleClosure defaultClosure) { + return new ThreadLocalInterruptibleClosure<>(defaultClosure); + } + + + // ********** plain wrappers ********** + + /** + * Return a closure that can have its wrapped closure changed, + * allowing a client to change a previously-supplied closure's + * behavior mid-stream. + * + * @param the type of the object passed to the closure + * + * @see ClosureWrapper + */ + public static ClosureWrapper wrap(Closure closure) { + return new ClosureWrapper<>(closure); + } + + /** + * Return a closure that can have its wrapped closure changed, + * allowing a client to change a previously-supplied closure's + * behavior mid-stream. + * + * @param the type of the object passed to the closure + * + * @see InterruptibleClosureWrapper + */ + public static InterruptibleClosureWrapper wrap(InterruptibleClosure closure) { + return new InterruptibleClosureWrapper<>(closure); + } + + + // ********** null check wrappers ********** /** * Return a closure that wraps the specified closure and checks * for a null argument before forwarding the argument to the * specified closure. If the argument is null, the closure will * do nothing. + * * @param the type of the object passed to the closure + * * @see #nullCheck(Closure, Command) */ public static Closure nullCheck(Closure closure) { @@ -104,7 +219,9 @@ public final class ClosureTools { * for a null argument before forwarding the argument to the * specified closure. If the argument is null, * the closure will execute the specified command. + * * @param the type of the object passed to the closure + * * @see #nullCheck(Closure) */ public static Closure nullCheck(Closure closure, Command nullCommand) { @@ -112,18 +229,35 @@ public final class ClosureTools { } /** - * Return a closure that can have its wrapped closure changed, - * allowing a client to change a previously-supplied closure's - * behavior mid-stream. + * Return a closure that wraps the specified closure and checks + * for a null argument before forwarding the argument to the + * specified closure. If the argument is null, the closure will + * do nothing. + * * @param the type of the object passed to the closure - * @see ClosureWrapper + * + * @see #nullCheck(InterruptibleClosure, InterruptibleCommand) */ - public static ClosureWrapper wrap(Closure closure) { - return new ClosureWrapper<>(closure); + public static InterruptibleClosure nullCheck(InterruptibleClosure closure) { + return nullCheck(closure, NullCommand.instance()); } + /** + * Return a closure that wraps the specified closure and checks + * for a null argument before forwarding the argument to the + * specified closure. If the argument is null, + * the closure will execute the specified command. + * + * @param the type of the object passed to the closure + * + * @see #nullCheck(InterruptibleClosure) + */ + public static InterruptibleClosure nullCheck(InterruptibleClosure closure, InterruptibleCommand nullCommand) { + return new NullCheckInterruptibleClosureWrapper<>(closure, nullCommand); + } - // ********** safe ********** + + // ********** safe wrappers ********** /** * Return closure that will handle any exceptions thrown by the specified @@ -131,10 +265,12 @@ public final class ClosureTools { * the exception's stack trace will be printed to {@link System#err * the "standard" error output stream}. * @param the type of the object passed to the closure - * @see #safe(Closure, ExceptionHandler) + * + * + * @see #safeClosure(Closure, ExceptionHandler) */ - public static Closure safe(Closure closure) { - return safe(closure, DefaultExceptionHandler.instance()); + public static Closure safeClosure(Closure closure) { + return safeClosure(closure, DefaultExceptionHandler.instance()); } /** @@ -142,13 +278,43 @@ public final class ClosureTools { * closure with the specified exception handler. If the * wrapped closure throws an exception, the safe closure will handle * the exception and return. + * * @param the type of the object passed to the closure - * @see #safe(Closure) + * + * @see #safeClosure(Closure) */ - public static Closure safe(Closure closure, ExceptionHandler exceptionHandler) { + public static Closure safeClosure(Closure closure, ExceptionHandler exceptionHandler) { return new SafeClosureWrapper<>(closure, exceptionHandler); } + /** + * Return closure that 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 the type of the object passed to the closure + * + * + * @see #safeClosure(InterruptibleClosure, ExceptionHandler) + */ + public static InterruptibleClosure safeClosure(InterruptibleClosure closure) { + return safeClosure(closure, DefaultExceptionHandler.instance()); + } + + /** + * Return closure that will handle any exceptions thrown by the specified + * closure with the specified exception handler. If the + * wrapped closure throws an exception, the safe closure will handle + * the exception and return. + * + * @param the type of the object passed to the closure + * + * @see #safeClosure(InterruptibleClosure) + */ + public static InterruptibleClosure safeClosure(InterruptibleClosure closure, ExceptionHandler exceptionHandler) { + return new SafeInterruptibleClosureWrapper<>(closure, exceptionHandler); + } + // ********** reflection ********** @@ -159,10 +325,11 @@ public final class ClosureTools { * NB: The actual method is determined at execution time, * not construction time. As a result, the closure can be used to emulate * "duck typing". + * * @param the type of the object passed to the closure */ - public static Closure execute(String methodName) { - return execute(methodName, ClassTools.EMPTY_ARRAY, ObjectTools.EMPTY_OBJECT_ARRAY); + public static Closure methodClosure(String methodName) { + return methodClosure(methodName, ClassTools.EMPTY_ARRAY, ObjectTools.EMPTY_OBJECT_ARRAY); } /** @@ -172,10 +339,11 @@ public final class ClosureTools { * NB: The actual method is determined at execution time, * not construction time. As a result, the closure can be used to emulate * "duck typing". + * * @param the type of the object passed to the closure */ - public static Closure execute(String methodName, Class parameterType, Object argument) { - return execute(methodName, new Class[] { parameterType }, new Object[] { argument }); + public static Closure methodClosure(String methodName, Class parameterType, Object argument) { + return methodClosure(methodName, new Class[] { parameterType }, new Object[] { argument }); } /** @@ -185,9 +353,10 @@ public final class ClosureTools { * NB: The actual method is determined at execution time, * not construction time. As a result, the closure can be used to emulate * "duck typing". + * * @param the type of the object passed to the closure */ - public static Closure execute(String methodName, Class[] parameterTypes, Object[] arguments) { + public static Closure methodClosure(String methodName, Class[] parameterTypes, Object[] arguments) { return new MethodClosure<>(methodName, parameterTypes, arguments); } @@ -197,22 +366,59 @@ public final class ClosureTools { /** * Return a composite of the specified closures. The composite's argument * will be passed to each closure, in sequence. + * * @param the type of the object passed to the closure */ @SafeVarargs - public static Closure composite(Closure... closures) { - return composite(ArrayTools.iterable(closures)); + public static Closure compositeClosure(Closure... closures) { + return (closures.length != 0) ? compositeClosure_(ArrayTools.iterable(closures)) : nullClosure(); } /** * Return a composite of the specified closures. The composite's argument * will be passed to each closure, in sequence. + * * @param the type of the object passed to the closure */ - public static Closure composite(Iterable> closures) { + public static Closure compositeClosure(Iterable> closures) { + return (closures.iterator().hasNext()) ? compositeClosure_(closures) : nullClosure(); + } + + /** + * assume non-empty + */ + private static Closure compositeClosure_(Iterable> closures) { return new CompositeClosure<>(closures); } + /** + * Return a composite of the specified closures. The composite's argument + * will be passed to each closure, in sequence. + * + * @param the type of the object passed to the closure + */ + @SafeVarargs + public static InterruptibleClosure compositeInterruptibleClosure(InterruptibleClosure... closures) { + return (closures.length != 0) ? compositeInterruptibleClosure_(ArrayTools.iterable(closures)) : nullClosure(); + } + + /** + * Return a composite of the specified closures. The composite's argument + * will be passed to each closure, in sequence. + * + * @param the type of the object passed to the closure + */ + public static InterruptibleClosure compositeInterruptibleClosure(Iterable> closures) { + return (closures.iterator().hasNext()) ? compositeInterruptibleClosure_(closures) : nullClosure(); + } + + /** + * assume non-empty + */ + private static InterruptibleClosure compositeInterruptibleClosure_(Iterable> closures) { + return new CompositeInterruptibleClosure<>(closures); + } + // ********** conditional ********** @@ -221,21 +427,45 @@ public final class ClosureTools { * determine whether to execute the specified closure. * If the predicate evaluates to false, the closure will do * nothing. + * * @param the type of the object passed to the closure */ public static Closure conditionalClosure(Predicate predicate, Closure closure) { - return conditionalClosure(predicate, closure, NullClosure.instance()); + return conditionalClosure(predicate, closure, nullClosure()); } /** * Return a closure that passes its argument to the specified predicate to * determine which of the two specified closures to execute. + * * @param the type of the object passed to the closure */ public static Closure conditionalClosure(Predicate predicate, Closure trueClosure, Closure falseClosure) { return new ConditionalClosure<>(predicate, trueClosure, falseClosure); } + /** + * Return a closure that passes its argument to the specified predicate to + * determine whether to execute the specified closure. + * If the predicate evaluates to false, the closure will do + * nothing. + * + * @param the type of the object passed to the closure + */ + public static InterruptibleClosure conditionalClosure(Predicate predicate, InterruptibleClosure closure) { + return conditionalClosure(predicate, closure, nullClosure()); + } + + /** + * Return a closure that passes its argument to the specified predicate to + * determine which of the two specified closures to execute. + * + * @param the type of the object passed to the closure + */ + public static InterruptibleClosure conditionalClosure(Predicate predicate, InterruptibleClosure trueClosure, InterruptibleClosure falseClosure) { + return new ConditionalInterruptibleClosure<>(predicate, trueClosure, falseClosure); + } + // ********** switch ********** @@ -247,10 +477,11 @@ public final class ClosureTools { * predicates would evaluate to true. * If none of the predicates evaluates to true, the closure * will do nothing. + * * @param the type of the object passed to the closure */ - public static Closure switchClosure(Iterable, Closure>> closures) { - return switchClosure(closures, NullClosure.instance()); + public static Closure switchClosure(Iterable, ? extends Closure>> closures) { + return switchClosure(closures, nullClosure()); } /** @@ -261,12 +492,43 @@ public final class ClosureTools { * predicates would evaluate to true. * If none of the predicates evaluates to true, the specified * default closure is executed. + * * @param the type of the object passed to the closure */ - public static Closure switchClosure(Iterable, Closure>> closures, Closure defaultClosure) { + public static Closure switchClosure(Iterable, ? extends Closure>> closures, Closure defaultClosure) { return new SwitchClosure<>(closures, defaultClosure); } + /** + * 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 true is executed, even if other, following, + * predicates would evaluate to true. + * If none of the predicates evaluates to true, the closure + * will do nothing. + * + * @param the type of the object passed to the closure + */ + public static InterruptibleClosure switchInterruptibleClosure(Iterable, ? extends InterruptibleClosure>> closures) { + return switchInterruptibleClosure(closures, nullClosure()); + } + + /** + * 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 true is executed, even if other, following, + * predicates would evaluate to true. + * If none of the predicates evaluates to true, the specified + * default closure is executed. + * + * @param the type of the object passed to the closure + */ + public static InterruptibleClosure switchInterruptibleClosure(Iterable, ? extends InterruptibleClosure>> closures, InterruptibleClosure defaultClosure) { + return new SwitchInterruptibleClosure<>(closures, defaultClosure); + } + // ********** boolean ********** @@ -303,6 +565,7 @@ public final class ClosureTools { /** * Return a closure that will throw an * {@link UnsupportedOperationException exception} when executed. + * * @param the type of the object passed to the closure */ public static Closure disabledClosure() { @@ -310,26 +573,61 @@ public final class ClosureTools { } + // ********** interrupted ********** + + /** + * Return a closure that will throw an + * {@link InterruptedException exception} when executed. + * + * @param the type of the object passed to the closure + */ + public static InterruptibleClosure interruptedClosure() { + return InterruptedClosure.instance(); + } + + // ********** looping ********** /** * Return a closure that executes the specified closure the specified * number of times. + * * @param the type of the object passed to the closure */ - public static Closure repeat(Closure closure, int count) { - return new RepeatingClosure<>(closure, count); + public static Closure repeatingClosure(Closure closure, int count) { + return (count == 0) ? nullClosure() : new RepeatingClosure<>(closure, count); + } + + /** + * Return a closure that executes the specified closure the specified + * number of times. + * + * @param the type of the object passed to the closure + */ + public static InterruptibleClosure repeatingClosure(InterruptibleClosure closure, int count) { + return (count == 0) ? nullClosure() : new RepeatingInterruptibleClosure<>(closure, count); } /** * Return a closure that executes the specified closure while the specified * predicate evaluates to true when passed the argument. + * * @param the type of the object passed to the closure */ - public static Closure while_(Predicate predicate, Closure closure) { + public static Closure whileClosure(Predicate predicate, Closure closure) { return new WhileClosure<>(predicate, closure); } + /** + * Return a closure that executes the specified closure while the specified + * predicate evaluates to true when passed the argument. + * + * @param the type of the object passed to the closure + */ + public static InterruptibleClosure whileClosure(Predicate predicate, InterruptibleClosure closure) { + return new WhileInterruptibleClosure<>(predicate, closure); + } + /** * Return a closure that executes the specified closure until the specified * predicate evaluates to true when passed the argument. The @@ -339,12 +637,29 @@ public final class ClosureTools { * statement (i.e. it executes until the predicate evaluates to * true, * not false). + * * @param the type of the object passed to the closure */ - public static Closure until(Closure closure, Predicate predicate) { + public static Closure untilClosure(Closure closure, Predicate predicate) { return new UntilClosure<>(closure, predicate); } + /** + * Return a closure that executes the specified closure until the specified + * predicate evaluates to true when passed the argument. The + * specifie closure will always execute at least once. + *

+ * NB: This is the inverse of the Java do-while + * statement (i.e. it executes until the predicate evaluates to + * true, + * not false). + * + * @param the type of the object passed to the closure + */ + public static InterruptibleClosure untilClosure(InterruptibleClosure closure, Predicate predicate) { + return new UntilInterruptibleClosure<>(closure, predicate); + } + // ********** constructor ********** diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/CommandBiClosure.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/CommandBiClosure.java new file mode 100644 index 0000000000..9be7d10d9f --- /dev/null +++ b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/CommandBiClosure.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.BiClosure; +import org.eclipse.jpt.common.utility.command.Command; +import org.eclipse.jpt.common.utility.internal.ObjectTools; + +/** + * Adapt a {@link Command} to the {@link BiClosure} interface. + * The closure's arguments are ignored. + * + * @param the type of the first object passed to the closure; ignored + * @param the type of the second object passed to the closure; ignored + */ +public class CommandBiClosure + implements BiClosure +{ + private final Command command; + + + public CommandBiClosure(Command command) { + super(); + if (command == null) { + throw new NullPointerException(); + } + this.command = command; + } + + public void execute(A1 argument1, A2 argument2) { + this.command.execute(); + } + + @Override + public String toString() { + return ObjectTools.toString(this, this.command); + } +} diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/CompositeBiClosure.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/CompositeBiClosure.java new file mode 100644 index 0000000000..de8583f962 --- /dev/null +++ b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/CompositeBiClosure.java @@ -0,0 +1,46 @@ +/******************************************************************************* + * Copyright (c) 2013, 2016 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.BiClosure; +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 arguments to each closure, + * in sequence. + * + * @param the type of the first object passed to the closure + * @param the type of the second object passed to the closure + */ +public class CompositeBiClosure + implements BiClosure +{ + private final Iterable> closures; + + public CompositeBiClosure(Iterable> closures) { + super(); + if (IterableTools.isOrContainsNull(closures)) { + throw new NullPointerException(); + } + this.closures = closures; + } + + public void execute(A1 argument1, A2 argument2) { + for (BiClosure closure : this.closures) { + closure.execute(argument1, argument2); + } + } + + @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/CompositeClosure.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/CompositeClosure.java index 792547aee0..bbeb4bc8c6 100644 --- 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 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2013 Oracle. All rights reserved. + * Copyright (c) 2013, 2016 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. @@ -22,9 +22,9 @@ import org.eclipse.jpt.common.utility.internal.iterable.IterableTools; public class CompositeClosure implements Closure { - private final Iterable> closures; + private final Iterable> closures; - public CompositeClosure(Iterable> closures) { + public CompositeClosure(Iterable> closures) { super(); if (IterableTools.isOrContainsNull(closures)) { throw new NullPointerException(); diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/CompositeInterruptibleBiClosure.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/CompositeInterruptibleBiClosure.java new file mode 100644 index 0000000000..1d83f5515b --- /dev/null +++ b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/CompositeInterruptibleBiClosure.java @@ -0,0 +1,46 @@ +/******************************************************************************* + * Copyright (c) 2013, 2016 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.InterruptibleBiClosure; +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 arguments to each closure, + * in sequence. + * + * @param the type of the first object passed to the closure + * @param the type of the second object passed to the closure + */ +public class CompositeInterruptibleBiClosure + implements InterruptibleBiClosure +{ + private final Iterable> closures; + + public CompositeInterruptibleBiClosure(Iterable> closures) { + super(); + if (IterableTools.isOrContainsNull(closures)) { + throw new NullPointerException(); + } + this.closures = closures; + } + + public void execute(A1 argument1, A2 argument2) throws InterruptedException { + for (InterruptibleBiClosure closure : this.closures) { + closure.execute(argument1, argument2); + } + } + + @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 index 5564a840a2..e1669c766c 100644 --- 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 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2013 Oracle. All rights reserved. + * Copyright (c) 2013, 2016 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. @@ -19,9 +19,9 @@ import org.eclipse.jpt.common.utility.internal.iterable.IterableTools; public class CompositeInterruptibleClosure implements InterruptibleClosure { - private final Iterable> closures; + private final Iterable> closures; - public CompositeInterruptibleClosure(Iterable> closures) { + public CompositeInterruptibleClosure(Iterable> closures) { super(); if (IterableTools.isOrContainsNull(closures)) { throw new NullPointerException(); 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 index 9e6c6d4680..7dd8ad1605 100644 --- 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 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2013 Oracle. All rights reserved. + * Copyright (c) 2013, 2016 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. @@ -33,11 +33,17 @@ public class ConditionalClosure public ConditionalClosure(Predicate predicate, Closure trueClosure, Closure falseClosure) { super(); - if ((predicate == null) || (trueClosure == null) || (falseClosure == null)) { + if (predicate == null) { throw new NullPointerException(); } this.predicate = predicate; + if (trueClosure == null) { + throw new NullPointerException(); + } this.trueClosure = trueClosure; + if (falseClosure == null) { + throw new NullPointerException(); + } this.falseClosure = falseClosure; } 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 index 64a766ff92..e2f62b5243 100644 --- 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 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2013 Oracle. All rights reserved. + * Copyright (c) 2013, 2016 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. @@ -29,11 +29,17 @@ public class ConditionalInterruptibleClosure public ConditionalInterruptibleClosure(Predicate predicate, InterruptibleClosure trueClosure, InterruptibleClosure falseClosure) { super(); - if ((predicate == null) || (trueClosure == null) || (falseClosure == null)) { + if (predicate == null) { throw new NullPointerException(); } this.predicate = predicate; + if (trueClosure == null) { + throw new NullPointerException(); + } this.trueClosure = trueClosure; + if (falseClosure == null) { + throw new NullPointerException(); + } this.falseClosure = falseClosure; } diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/DisabledBiClosure.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/DisabledBiClosure.java new file mode 100644 index 0000000000..e5c3fc5649 --- /dev/null +++ b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/DisabledBiClosure.java @@ -0,0 +1,54 @@ +/******************************************************************************* + * Copyright (c) 2012, 2016 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 org.eclipse.jpt.common.utility.closure.BiClosure; +import org.eclipse.jpt.common.utility.internal.ObjectTools; + +/** + * Closure that will throw an + * {@link UnsupportedOperationException exception} when executed. + * + * @param the type of the first object passed to the closure + * @param the type of the second object passed to the closure + */ +public final class DisabledBiClosure + implements BiClosure, Serializable +{ + @SuppressWarnings("rawtypes") + public static final BiClosure INSTANCE = new DisabledBiClosure(); + + @SuppressWarnings("unchecked") + public static BiClosure instance() { + return INSTANCE; + } + + // ensure single instance + private DisabledBiClosure() { + super(); + } + + // throw an exception + public void execute(A1 argument1, A2 argument2) { + throw new UnsupportedOperationException(); + } + + @Override + public String toString() { + return ObjectTools.singletonToString(this); + } + + private static final long serialVersionUID = 1L; + private Object readResolve() { + // replace this object with the singleton + return INSTANCE; + } +} diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/FactoryBiClosure.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/FactoryBiClosure.java new file mode 100644 index 0000000000..16b424e8e5 --- /dev/null +++ b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/FactoryBiClosure.java @@ -0,0 +1,46 @@ +/******************************************************************************* + * Copyright (c) 2013, 2016 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.BiClosure; +import org.eclipse.jpt.common.utility.factory.Factory; +import org.eclipse.jpt.common.utility.internal.ObjectTools; + +/** + * Adapt a {@link Factory} to the {@link BiClosure} interface. + * The closure's arguments and the factory's output are ignored. + * This really only useful for a factory that has side-effects. + * + * @param the type of the first object passed to the closure; ignored + * @param the type of the second object passed to the closure; ignored + */ +public class FactoryBiClosure + implements BiClosure +{ + private final Factory factory; + + + public FactoryBiClosure(Factory factory) { + super(); + if (factory == null) { + throw new NullPointerException(); + } + this.factory = factory; + } + + public void execute(A1 argument1, A2 argument2) { + this.factory.create(); + } + + @Override + public String toString() { + return ObjectTools.toString(this, this.factory); + } +} diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/InterruptedBiClosure.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/InterruptedBiClosure.java new file mode 100644 index 0000000000..9dba95aa14 --- /dev/null +++ b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/InterruptedBiClosure.java @@ -0,0 +1,54 @@ +/******************************************************************************* + * Copyright (c) 2012, 2016 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 org.eclipse.jpt.common.utility.closure.InterruptibleBiClosure; +import org.eclipse.jpt.common.utility.internal.ObjectTools; + +/** + * Closure that will throw an {@link InterruptedException exception} + * when executed. + * + * @param the type of the first object passed to the closure + * @param the type of the second object passed to the closure + */ +public final class InterruptedBiClosure + implements InterruptibleBiClosure, Serializable +{ + @SuppressWarnings("rawtypes") + public static final InterruptibleBiClosure INSTANCE = new InterruptedBiClosure(); + + @SuppressWarnings("unchecked") + public static InterruptibleBiClosure instance() { + return INSTANCE; + } + + // ensure single instance + private InterruptedBiClosure() { + super(); + } + + // throw an exception + public void execute(A1 argument1, A2 argument2) throws InterruptedException { + throw new InterruptedException(); + } + + @Override + public String toString() { + return ObjectTools.singletonToString(this); + } + + private static final long serialVersionUID = 1L; + private Object readResolve() { + // replace this object with the singleton + return INSTANCE; + } +} diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/InterruptibleBiClosureAdapter.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/InterruptibleBiClosureAdapter.java new file mode 100644 index 0000000000..9d05d7b70c --- /dev/null +++ b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/InterruptibleBiClosureAdapter.java @@ -0,0 +1,35 @@ +/******************************************************************************* + * Copyright (c) 2012, 2016 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.InterruptibleBiClosure; +import org.eclipse.jpt.common.utility.internal.ObjectTools; + +/** + * Convenience interruptible bi-closure that does nothing. + * + * @param the type of the first object passed to the closure + * @param the type of the second object passed to the closure + * + * @see BiClosureAdapter + * @see NullBiClosure + */ +public class InterruptibleBiClosureAdapter + implements InterruptibleBiClosure +{ + public void execute(A1 argument1, A2 argument2) throws InterruptedException { + // NOP + } + + @Override + public String toString() { + return ObjectTools.toString(this); + } +} diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/InterruptibleBiClosureWrapper.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/InterruptibleBiClosureWrapper.java new file mode 100644 index 0000000000..fced788030 --- /dev/null +++ b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/InterruptibleBiClosureWrapper.java @@ -0,0 +1,53 @@ +/******************************************************************************* + * Copyright (c) 2012, 2016 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.InterruptibleBiClosure; +import org.eclipse.jpt.common.utility.internal.ObjectTools; + +/** + * Closure wrapper that can have its wrapped closure changed, + * allowing a client to change a previously-supplied closure's + * behavior mid-stream. + * + * @param the type of the first object passed to the closure + * @param the type of the second object passed to the closure + * + * @see #setClosure(InterruptibleBiClosure) + */ +public class InterruptibleBiClosureWrapper + implements InterruptibleBiClosure +{ + protected volatile InterruptibleBiClosure closure; + + public InterruptibleBiClosureWrapper(InterruptibleBiClosure closure) { + super(); + if (closure == null) { + throw new NullPointerException(); + } + this.closure = closure; + } + + public void execute(A1 argument1, A2 argument2) throws InterruptedException { + this.closure.execute(argument1, argument2); + } + + public void setClosure(InterruptibleBiClosure closure) { + if (closure == null) { + throw new NullPointerException(); + } + this.closure = closure; + } + + @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/InterruptibleCommandBiClosure.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/InterruptibleCommandBiClosure.java new file mode 100644 index 0000000000..a71d62a62c --- /dev/null +++ b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/InterruptibleCommandBiClosure.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.InterruptibleBiClosure; +import org.eclipse.jpt.common.utility.command.InterruptibleCommand; +import org.eclipse.jpt.common.utility.internal.ObjectTools; + +/** + * Adapt an {@link InterruptibleCommand} to the {@link InterruptibleBiClosure} interface. + * The closure's arguments are ignored. + * + * @param the type of the first object passed to the closure; ignored + * @param the type of the second object passed to the closure; ignored + */ +public class InterruptibleCommandBiClosure + implements InterruptibleBiClosure +{ + private final InterruptibleCommand command; + + + public InterruptibleCommandBiClosure(InterruptibleCommand command) { + super(); + if (command == null) { + throw new NullPointerException(); + } + this.command = command; + } + + public void execute(A1 argument1, A2 argument2) throws InterruptedException { + this.command.execute(); + } + + @Override + public String toString() { + return ObjectTools.toString(this, this.command); + } +} diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/InterruptibleFactoryBiClosure.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/InterruptibleFactoryBiClosure.java new file mode 100644 index 0000000000..d36186807c --- /dev/null +++ b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/InterruptibleFactoryBiClosure.java @@ -0,0 +1,46 @@ +/******************************************************************************* + * Copyright (c) 2013, 2016 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.InterruptibleBiClosure; +import org.eclipse.jpt.common.utility.factory.InterruptibleFactory; +import org.eclipse.jpt.common.utility.internal.ObjectTools; + +/** + * Adapt an {@link InterruptibleFactory} to the {@link InterruptibleBiClosure} interface. + * The closure's arguments and the factory's output are ignored. + * This really only useful for a factory that has side-effects. + * + * @param the type of the first object passed to the closure; ignored + * @param the type of the second object passed to the closure; ignored + */ +public class InterruptibleFactoryBiClosure + implements InterruptibleBiClosure +{ + private final InterruptibleFactory factory; + + + public InterruptibleFactoryBiClosure(InterruptibleFactory factory) { + super(); + if (factory == null) { + throw new NullPointerException(); + } + this.factory = factory; + } + + public void execute(A1 argument1, A2 argument2) throws InterruptedException { + this.factory.create(); + } + + @Override + public String toString() { + return ObjectTools.toString(this, this.factory); + } +} 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 index bea0748c6f..571388f12a 100644 --- 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 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2013 Oracle. All rights reserved. + * Copyright (c) 2013, 2016 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. @@ -40,11 +40,17 @@ public class MethodClosure public MethodClosure(String methodName, Class[] parameterTypes, Object[] arguments) { super(); - if ((methodName == null) || ArrayTools.isOrContainsNull(parameterTypes) || (arguments == null)) { + if (methodName == null) { throw new NullPointerException(); } this.methodName = methodName; + if (ArrayTools.isOrContainsNull(parameterTypes)) { + throw new NullPointerException(); + } this.parameterTypes = parameterTypes; + if (arguments == null) { + throw new NullPointerException(); + } this.arguments = arguments; } diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/NullBiClosure.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/NullBiClosure.java new file mode 100644 index 0000000000..c1e21e8423 --- /dev/null +++ b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/NullBiClosure.java @@ -0,0 +1,54 @@ +/******************************************************************************* + * Copyright (c) 2012, 2016 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 org.eclipse.jpt.common.utility.closure.BiClosure; +import org.eclipse.jpt.common.utility.internal.ObjectTools; + +/** + * BiClosure that will do nothing when executed. + * + * @param the type of the first object passed to the closure + * @param the type of the second object passed to the closure + * + * @see BiClosureAdapter + */ +public final class NullBiClosure + implements BiClosure, Serializable +{ + @SuppressWarnings("rawtypes") + public static final BiClosure INSTANCE = new NullBiClosure(); + + @SuppressWarnings("unchecked") + public static BiClosure instance() { + return INSTANCE; + } + + // ensure single instance + private NullBiClosure() { + super(); + } + + public void execute(A1 argument1, A2 argument2) { + // NOP + } + + @Override + public String toString() { + return ObjectTools.singletonToString(this); + } + + private static final long serialVersionUID = 1L; + private Object readResolve() { + // replace this object with the singleton + return INSTANCE; + } +} 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 index 78c1ac3dd8..23ba6f3522 100644 --- 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 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2013 Oracle. All rights reserved. + * Copyright (c) 2013, 2016 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. @@ -37,6 +37,9 @@ public class NullCheckClosureWrapper throw new NullPointerException(); } this.closure = closure; + if (nullCommand == null) { + throw new NullPointerException(); + } this.nullCommand = nullCommand; } 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 index 9033212fae..ef029729b1 100644 --- 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 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2013 Oracle. All rights reserved. + * Copyright (c) 2013, 2016 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. @@ -32,6 +32,9 @@ public class NullCheckInterruptibleClosureWrapper throw new NullPointerException(); } this.closure = closure; + if (nullCommand == null) { + throw new NullPointerException(); + } this.nullCommand = nullCommand; } diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/RepeatingBiClosure.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/RepeatingBiClosure.java new file mode 100644 index 0000000000..6540dddf53 --- /dev/null +++ b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/RepeatingBiClosure.java @@ -0,0 +1,49 @@ +/******************************************************************************* + * Copyright (c) 2013, 2016 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.BiClosure; +import org.eclipse.jpt.common.utility.internal.ObjectTools; + +/** + * BiClosure that executes another closure a specified number of times. + * + * @param the type of the first object passed to the closure + * @param the type of the second object passed to the closure + */ +public class RepeatingBiClosure + implements BiClosure +{ + private final int count; + private final BiClosure closure; + + public RepeatingBiClosure(BiClosure closure, int count) { + super(); + if (closure == null) { + throw new NullPointerException(); + } + this.closure = closure; + if (count < 0) { + throw new IndexOutOfBoundsException("invalid count: " + count); //$NON-NLS-1$ + } + this.count = count; + } + + public void execute(A1 argument1, A2 argument2) { + for (int i = this.count; i-- > 0;) { + this.closure.execute(argument1, argument2); + } + } + + @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 index 2eb80a1421..a1d6e3c995 100644 --- 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 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2013 Oracle. All rights reserved. + * Copyright (c) 2013, 2016 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. @@ -33,10 +33,10 @@ public class RepeatingClosure if (closure == null) { throw new NullPointerException(); } - if (count <= 0) { + this.closure = closure; + if (count < 0) { throw new IndexOutOfBoundsException("invalid count: " + count); //$NON-NLS-1$ } - this.closure = closure; this.count = count; } diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/RepeatingInterruptibleBiClosure.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/RepeatingInterruptibleBiClosure.java new file mode 100644 index 0000000000..937d4d5a3a --- /dev/null +++ b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/RepeatingInterruptibleBiClosure.java @@ -0,0 +1,49 @@ +/******************************************************************************* + * Copyright (c) 2013, 2016 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.InterruptibleBiClosure; +import org.eclipse.jpt.common.utility.internal.ObjectTools; + +/** + * BiClosure that executes another closure a specified number of times. + * + * @param the type of the first object passed to the closure + * @param the type of the second object passed to the closure + */ +public class RepeatingInterruptibleBiClosure + implements InterruptibleBiClosure +{ + private final int count; + private final InterruptibleBiClosure closure; + + public RepeatingInterruptibleBiClosure(InterruptibleBiClosure closure, int count) { + super(); + if (closure == null) { + throw new NullPointerException(); + } + this.closure = closure; + if (count < 0) { + throw new IndexOutOfBoundsException("invalid count: " + count); //$NON-NLS-1$ + } + this.count = count; + } + + public void execute(A1 argument1, A2 argument2) throws InterruptedException { + for (int i = this.count; i-- > 0;) { + this.closure.execute(argument1, argument2); + } + } + + @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 index a401a79a9d..9599946900 100644 --- 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 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2013 Oracle. All rights reserved. + * Copyright (c) 2013, 2016 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. @@ -30,7 +30,7 @@ public class RepeatingInterruptibleClosure if (closure == null) { throw new NullPointerException(); } - if (count <= 0) { + if (count < 0) { throw new IndexOutOfBoundsException("invalid count: " + count); //$NON-NLS-1$ } this.closure = closure; diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/SafeBiClosureWrapper.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/SafeBiClosureWrapper.java new file mode 100644 index 0000000000..aeb4e43d4c --- /dev/null +++ b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/SafeBiClosureWrapper.java @@ -0,0 +1,56 @@ +/******************************************************************************* + * Copyright (c) 2013, 2016 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.BiClosure; +import org.eclipse.jpt.common.utility.exception.ExceptionHandler; +import org.eclipse.jpt.common.utility.internal.ObjectTools; + +/** + * 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 the type of the first object passed to the closure + * @param the type of the second object passed to the closure + */ +public class SafeBiClosureWrapper + implements BiClosure +{ + private final BiClosure closure; + private final ExceptionHandler exceptionHandler; + + + public SafeBiClosureWrapper(BiClosure closure, ExceptionHandler exceptionHandler) { + super(); + if (closure == null) { + throw new NullPointerException(); + } + this.closure = closure; + if (exceptionHandler == null) { + throw new NullPointerException(); + } + this.exceptionHandler = exceptionHandler; + } + + public void execute(A1 argument1, A2 argument2) { + try { + this.closure.execute(argument1, argument2); + } 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/SafeClosureWrapper.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/SafeClosureWrapper.java index 0fae6e1ca7..9caa77e632 100644 --- 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 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2013 Oracle. All rights reserved. + * Copyright (c) 2013, 2016 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. @@ -30,10 +30,13 @@ public class SafeClosureWrapper public SafeClosureWrapper(Closure closure, ExceptionHandler exceptionHandler) { super(); - if ((closure == null) || (exceptionHandler == null)) { + if (closure == null) { throw new NullPointerException(); } this.closure = closure; + if (exceptionHandler == null) { + throw new NullPointerException(); + } this.exceptionHandler = exceptionHandler; } diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/SafeInterruptibleBiClosureWrapper.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/SafeInterruptibleBiClosureWrapper.java new file mode 100644 index 0000000000..776ff9552d --- /dev/null +++ b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/SafeInterruptibleBiClosureWrapper.java @@ -0,0 +1,58 @@ +/******************************************************************************* + * Copyright (c) 2013, 2016 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.InterruptibleBiClosure; +import org.eclipse.jpt.common.utility.exception.ExceptionHandler; +import org.eclipse.jpt.common.utility.internal.ObjectTools; + +/** + * 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 the type of the first object passed to the closure + * @param the type of the second object passed to the closure + */ +public class SafeInterruptibleBiClosureWrapper + implements InterruptibleBiClosure +{ + private final InterruptibleBiClosure closure; + private final ExceptionHandler exceptionHandler; + + + public SafeInterruptibleBiClosureWrapper(InterruptibleBiClosure closure, ExceptionHandler exceptionHandler) { + super(); + if (closure == null) { + throw new NullPointerException(); + } + this.closure = closure; + if (exceptionHandler == null) { + throw new NullPointerException(); + } + this.exceptionHandler = exceptionHandler; + } + + public void execute(A1 argument1, A2 argument2) throws InterruptedException { + try { + this.closure.execute(argument1, argument2); + } 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/SafeInterruptibleClosureWrapper.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/SafeInterruptibleClosureWrapper.java index b106b075b8..cc3a317353 100644 --- 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 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2013 Oracle. All rights reserved. + * Copyright (c) 2013, 2016 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. @@ -25,10 +25,13 @@ public class SafeInterruptibleClosureWrapper public SafeInterruptibleClosureWrapper(InterruptibleClosure closure, ExceptionHandler exceptionHandler) { super(); - if ((closure == null) || (exceptionHandler == null)) { + if (closure == null) { throw new NullPointerException(); } this.closure = closure; + if (exceptionHandler == null) { + throw new NullPointerException(); + } this.exceptionHandler = exceptionHandler; } 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 index c4839d7af7..d62730a374 100644 --- 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 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2013 Oracle. All rights reserved. + * Copyright (c) 2013, 2016 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. @@ -34,20 +34,23 @@ import org.eclipse.jpt.common.utility.predicate.Predicate; public class SwitchClosure implements Closure { - private final Iterable, Closure>> closures; + private final Iterable, ? extends Closure>> closures; private final Closure defaultClosure; - public SwitchClosure(Iterable, Closure>> closures, Closure defaultClosure) { + public SwitchClosure(Iterable, ? extends Closure>> closures, Closure defaultClosure) { super(); - if (IterableTools.isOrContainsNull(closures) || (defaultClosure == null)) { + if (IterableTools.isOrContainsNull(closures)) { throw new NullPointerException(); } this.closures = closures; + if (defaultClosure == null) { + throw new NullPointerException(); + } this.defaultClosure = defaultClosure; } public void execute(A argument) { - for (Association, Closure> association : this.closures) { + for (Association, ? extends Closure> association : this.closures) { if (association.getKey().evaluate(argument)) { association.getValue().execute(argument); return; // execute only one closure 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 index 086c518f0e..f6640be275 100644 --- 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 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2013 Oracle. All rights reserved. + * Copyright (c) 2013, 2016 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. @@ -25,26 +25,29 @@ import org.eclipse.jpt.common.utility.predicate.Predicate; public class SwitchInterruptibleClosure implements InterruptibleClosure { - private final Iterable, InterruptibleClosure>> closures; - private final InterruptibleClosure defaultInterruptibleClosure; + private final Iterable, ? extends InterruptibleClosure>> closures; + private final InterruptibleClosure defaultClosure; - public SwitchInterruptibleClosure(Iterable, InterruptibleClosure>> closures, InterruptibleClosure defaultInterruptibleClosure) { + public SwitchInterruptibleClosure(Iterable, ? extends InterruptibleClosure>> closures, InterruptibleClosure defaultClosure) { super(); - if (IterableTools.isOrContainsNull(closures) || (defaultInterruptibleClosure == null)) { + if (IterableTools.isOrContainsNull(closures)) { throw new NullPointerException(); } this.closures = closures; - this.defaultInterruptibleClosure = defaultInterruptibleClosure; + if (defaultClosure == null) { + throw new NullPointerException(); + } + this.defaultClosure = defaultClosure; } public void execute(A argument) throws InterruptedException { - for (Association, InterruptibleClosure> association : this.closures) { + for (Association, ? extends InterruptibleClosure> association : this.closures) { if (association.getKey().evaluate(argument)) { association.getValue().execute(argument); return; // execute only one closure } } - this.defaultInterruptibleClosure.execute(argument); + this.defaultClosure.execute(argument); } @Override diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/ThreadLocalBiClosure.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/ThreadLocalBiClosure.java new file mode 100644 index 0000000000..e62cb12056 --- /dev/null +++ b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/ThreadLocalBiClosure.java @@ -0,0 +1,66 @@ +/******************************************************************************* + * Copyright (c) 2008, 2016 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.BiClosure; + +/** + * This closure allows the client to specify a different closure for each + * thread. If there is no closure for the current thread, the configured default + * closure is executed. + * + * @param the type of the first object passed to the closure + * @param the type of the second object passed to the closure + * + * @see #set(BiClosure) + */ +public class ThreadLocalBiClosure + implements BiClosure +{ + private final ThreadLocal> threadLocal; + private final BiClosure defaultClosure; + + public ThreadLocalBiClosure(BiClosure defaultClosure) { + super(); + if (defaultClosure == null) { + throw new NullPointerException(); + } + this.defaultClosure = defaultClosure; + this.threadLocal = this.buildThreadLocal(); + } + + private ThreadLocal> buildThreadLocal() { + return new ThreadLocal<>(); + } + + public void execute(A1 argument1, A2 argument2) { + this.get().execute(argument1, argument2); + } + + private BiClosure get() { + BiClosure closure = this.threadLocal.get(); + return (closure != null) ? closure : this.defaultClosure; + } + + /** + * Set the current thread's closure to the specified value. + */ + public void set(BiClosure closure) { + this.threadLocal.set(closure); + } + + /** + * Return the string representation of the current thread's closure. + */ + @Override + public String toString() { + return this.get().toString(); + } +} diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/ThreadLocalClosure.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/ThreadLocalClosure.java index 7d9d93bab0..4857697c81 100644 --- a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/ThreadLocalClosure.java +++ b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/ThreadLocalClosure.java @@ -45,10 +45,7 @@ public class ThreadLocalClosure private Closure get() { Closure closure = this.threadLocal.get(); - if (closure != null) { - return closure; - } - return this.defaultClosure; + return (closure != null) ? closure : this.defaultClosure; } /** diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/ThreadLocalInterruptibleBiClosure.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/ThreadLocalInterruptibleBiClosure.java new file mode 100644 index 0000000000..a722dec737 --- /dev/null +++ b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/ThreadLocalInterruptibleBiClosure.java @@ -0,0 +1,67 @@ +/******************************************************************************* + * Copyright (c) 2008, 2016 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.BiClosure; +import org.eclipse.jpt.common.utility.closure.InterruptibleBiClosure; + +/** + * This closure allows the client to specify a different closure for each + * thread. If there is no closure for the current thread, the configured default + * closure is executed. + * + * @param the type of the first object passed to the closure + * @param the type of the second object passed to the closure + * + * @see #set(BiClosure) + */ +public class ThreadLocalInterruptibleBiClosure + implements InterruptibleBiClosure +{ + private final ThreadLocal> threadLocal; + private final InterruptibleBiClosure defaultClosure; + + public ThreadLocalInterruptibleBiClosure(InterruptibleBiClosure defaultClosure) { + super(); + if (defaultClosure == null) { + throw new NullPointerException(); + } + this.defaultClosure = defaultClosure; + this.threadLocal = this.buildThreadLocal(); + } + + private ThreadLocal> buildThreadLocal() { + return new ThreadLocal<>(); + } + + public void execute(A1 argument1, A2 argument2) throws InterruptedException { + this.get().execute(argument1, argument2); + } + + private InterruptibleBiClosure get() { + InterruptibleBiClosure closure = this.threadLocal.get(); + return (closure != null) ? closure : this.defaultClosure; + } + + /** + * Set the current thread's closure to the specified value. + */ + public void set(BiClosure closure) { + this.threadLocal.set(closure); + } + + /** + * Return the string representation of the current thread's closure. + */ + @Override + public String toString() { + return this.get().toString(); + } +} diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/ThreadLocalInterruptibleClosure.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/ThreadLocalInterruptibleClosure.java index f9cca6122b..43616a3894 100644 --- a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/ThreadLocalInterruptibleClosure.java +++ b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/closure/ThreadLocalInterruptibleClosure.java @@ -18,14 +18,14 @@ public class ThreadLocalInterruptibleClosure implements InterruptibleClosure { private final ThreadLocal> threadLocal; - private final InterruptibleClosure defaultInterruptibleClosure; + private final InterruptibleClosure defaultClosure; - public ThreadLocalInterruptibleClosure(InterruptibleClosure defaultInterruptibleClosure) { + public ThreadLocalInterruptibleClosure(InterruptibleClosure defaultClosure) { super(); - if (defaultInterruptibleClosure == null) { + if (defaultClosure == null) { throw new NullPointerException(); } - this.defaultInterruptibleClosure = defaultInterruptibleClosure; + this.defaultClosure = defaultClosure; this.threadLocal = this.buildThreadLocal(); } @@ -39,10 +39,7 @@ public class ThreadLocalInterruptibleClosure private InterruptibleClosure get() { InterruptibleClosure closure = this.threadLocal.get(); - if (closure != null) { - return closure; - } - return this.defaultInterruptibleClosure; + return (closure != null) ? closure : this.defaultClosure; } /** 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 index 1caa60423b..4632b96ea9 100644 --- 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 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2013 Oracle. All rights reserved. + * Copyright (c) 2013, 2016 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. @@ -38,11 +38,14 @@ public class UntilClosure public UntilClosure(Closure closure, Predicate predicate) { super(); - if ((closure == null) || (predicate == null)) { + if (closure == null) { throw new NullPointerException(); } - this.predicate = predicate; this.closure = closure; + if (predicate == null) { + throw new NullPointerException(); + } + this.predicate = predicate; } public void execute(A argument) { 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 index a307e8ebac..38b69adaed 100644 --- 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 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2013 Oracle. All rights reserved. + * Copyright (c) 2013, 2016 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. @@ -28,11 +28,14 @@ public class UntilInterruptibleClosure public UntilInterruptibleClosure(InterruptibleClosure closure, Predicate predicate) { super(); - if ((closure == null) || (predicate == null)) { + if (closure == null) { throw new NullPointerException(); } - this.predicate = predicate; this.closure = closure; + if (predicate == null) { + throw new NullPointerException(); + } + this.predicate = predicate; } public void execute(A argument) throws InterruptedException { 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 index dfbd8c8f2e..147e7e5e27 100644 --- 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 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2013 Oracle. All rights reserved. + * Copyright (c) 2013, 2016 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. @@ -32,10 +32,13 @@ public class WhileClosure public WhileClosure(Predicate predicate, Closure closure) { super(); - if ((predicate == null) || (closure == null)) { + if (predicate == null) { throw new NullPointerException(); } this.predicate = predicate; + if (closure == null) { + throw new NullPointerException(); + } this.closure = closure; } 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 index de0014ab88..06a332f625 100644 --- 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 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2013 Oracle. All rights reserved. + * Copyright (c) 2013, 2015 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. @@ -28,10 +28,13 @@ public class WhileInterruptibleClosure public WhileInterruptibleClosure(Predicate predicate, InterruptibleClosure closure) { super(); - if ((predicate == null) || (closure == null)) { + if (predicate == null) { throw new NullPointerException(); } this.predicate = predicate; + if (closure == null) { + throw new NullPointerException(); + } this.closure = closure; } diff --git a/common/tests/org.eclipse.jpt.common.utility.tests/src/org/eclipse/jpt/common/utility/tests/internal/JptCommonUtilityTests.java b/common/tests/org.eclipse.jpt.common.utility.tests/src/org/eclipse/jpt/common/utility/tests/internal/JptCommonUtilityTests.java index ab7b8c52ec..a0e2cd0d9e 100644 --- a/common/tests/org.eclipse.jpt.common.utility.tests/src/org/eclipse/jpt/common/utility/tests/internal/JptCommonUtilityTests.java +++ b/common/tests/org.eclipse.jpt.common.utility.tests/src/org/eclipse/jpt/common/utility/tests/internal/JptCommonUtilityTests.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2015 Oracle. All rights reserved. + * Copyright (c) 2005, 2016 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. @@ -9,6 +9,7 @@ ******************************************************************************/ package org.eclipse.jpt.common.utility.tests.internal; +import org.eclipse.jpt.common.utility.tests.internal.closure.JptCommonUtilityClosureTests; import org.eclipse.jpt.common.utility.tests.internal.collection.JptCommonUtilityCollectionTests; import org.eclipse.jpt.common.utility.tests.internal.command.JptCommonUtilityCommandTests; import org.eclipse.jpt.common.utility.tests.internal.comparator.JptCommonUtilityComparatorTests; @@ -38,6 +39,7 @@ public class JptCommonUtilityTests { public static Test suite() { TestSuite suite = new TestSuite(JptCommonUtilityTests.class.getPackage().getName()); + suite.addTest(JptCommonUtilityClosureTests.suite()); suite.addTest(JptCommonUtilityCollectionTests.suite()); suite.addTest(JptCommonUtilityCommandTests.suite()); suite.addTest(JptCommonUtilityComparatorTests.suite()); diff --git a/common/tests/org.eclipse.jpt.common.utility.tests/src/org/eclipse/jpt/common/utility/tests/internal/closure/BiClosureToolsTests.java b/common/tests/org.eclipse.jpt.common.utility.tests/src/org/eclipse/jpt/common/utility/tests/internal/closure/BiClosureToolsTests.java new file mode 100644 index 0000000000..da20ae3efa --- /dev/null +++ b/common/tests/org.eclipse.jpt.common.utility.tests/src/org/eclipse/jpt/common/utility/tests/internal/closure/BiClosureToolsTests.java @@ -0,0 +1,726 @@ +/******************************************************************************* + * Copyright (c) 2016 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.tests.internal.closure; + +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import org.eclipse.jpt.common.utility.closure.BiClosure; +import org.eclipse.jpt.common.utility.closure.InterruptibleBiClosure; +import org.eclipse.jpt.common.utility.command.Command; +import org.eclipse.jpt.common.utility.command.InterruptibleCommand; +import org.eclipse.jpt.common.utility.factory.Factory; +import org.eclipse.jpt.common.utility.factory.InterruptibleFactory; +import org.eclipse.jpt.common.utility.internal.ClassTools; +import org.eclipse.jpt.common.utility.internal.closure.BiClosureAdapter; +import org.eclipse.jpt.common.utility.internal.closure.BiClosureTools; +import org.eclipse.jpt.common.utility.internal.closure.BiClosureWrapper; +import org.eclipse.jpt.common.utility.internal.closure.InterruptibleBiClosureAdapter; +import org.eclipse.jpt.common.utility.internal.closure.InterruptibleBiClosureWrapper; +import org.eclipse.jpt.common.utility.internal.closure.ThreadLocalBiClosure; +import org.eclipse.jpt.common.utility.internal.closure.ThreadLocalInterruptibleBiClosure; +import org.eclipse.jpt.common.utility.internal.exception.CollectingExceptionHandler; +import org.eclipse.jpt.common.utility.internal.iterable.IterableTools; +import org.eclipse.jpt.common.utility.internal.reference.SimpleIntReference; +import org.eclipse.jpt.common.utility.reference.ModifiableIntReference; +import org.eclipse.jpt.common.utility.tests.internal.TestTools; +import org.eclipse.jpt.common.utility.tests.internal.closure.ClosureToolsTests.LocalCommand; +import org.eclipse.jpt.common.utility.tests.internal.closure.ClosureToolsTests.LocalFactory; +import org.eclipse.jpt.common.utility.tests.internal.closure.ClosureToolsTests.LocalInterruptibleCommand; +import org.eclipse.jpt.common.utility.tests.internal.closure.ClosureToolsTests.LocalInterruptibleFactory; +import junit.framework.TestCase; + +@SuppressWarnings("nls") +public class BiClosureToolsTests + extends TestCase +{ + public BiClosureToolsTests(String name) { + super(name); + } + + public void testAdaptCommand_execute() { + LocalCommand command = new LocalCommand(); + BiClosure closure = BiClosureTools.adapt(command); + closure.execute(Boolean.FALSE, Boolean.TRUE); + assertEquals(1, command.count); + } + + public void testAdaptCommand_toString() { + LocalCommand command = new LocalCommand(); + BiClosure closure = BiClosureTools.adapt(command); + assertTrue(closure.toString().indexOf("CommandBiClosure") != -1); + assertTrue(closure.toString().indexOf("LocalCommand") != -1); + } + + public void testAdaptCommand_NPE() { + boolean exCaught = false; + try { + BiClosure closure = BiClosureTools.adapt((Command) null); + fail("bogus: " + closure); + } catch (NullPointerException ex) { + exCaught = true; + } + assertTrue(exCaught); + } + + public void testAdaptInterruptibleCommand_execute() throws Exception { + LocalInterruptibleCommand command = new LocalInterruptibleCommand(); + InterruptibleBiClosure closure = BiClosureTools.adapt(command); + closure.execute(Boolean.FALSE, Boolean.TRUE); + assertEquals(1, command.count); + } + + public void testAdaptInterruptibleCommand_toString() throws Exception { + LocalInterruptibleCommand command = new LocalInterruptibleCommand(); + InterruptibleBiClosure closure = BiClosureTools.adapt(command); + assertTrue(closure.toString().indexOf("InterruptibleCommandBiClosure") != -1); + assertTrue(closure.toString().indexOf("LocalInterruptibleCommand") != -1); + } + + public void testAdaptInterruptibleCommand_NPE() { + boolean exCaught = false; + try { + InterruptibleBiClosure closure = BiClosureTools.adapt((InterruptibleCommand) null); + fail("bogus: " + closure); + } catch (NullPointerException ex) { + exCaught = true; + } + assertTrue(exCaught); + } + + public void testAdaptFactory_execute() throws Exception { + LocalFactory factory = new LocalFactory<>(); + BiClosure closure = BiClosureTools.adapt(factory); + closure.execute(Boolean.FALSE, Boolean.TRUE); + assertEquals(1, factory.count); + } + + public void testAdaptFactory_toString() throws Exception { + LocalFactory factory = new LocalFactory<>(); + BiClosure closure = BiClosureTools.adapt(factory); + assertTrue(closure.toString().indexOf("FactoryBiClosure") != -1); + assertTrue(closure.toString().indexOf("LocalFactory") != -1); + } + + public void testAdaptFactory_NPE() { + boolean exCaught = false; + try { + BiClosure closure = BiClosureTools.adapt((Factory) null); + fail("bogus: " + closure); + } catch (NullPointerException ex) { + exCaught = true; + } + assertTrue(exCaught); + } + + public void testAdaptInterruptibleFactory_execute() throws Exception { + LocalInterruptibleFactory factory = new LocalInterruptibleFactory<>(); + InterruptibleBiClosure closure = BiClosureTools.adapt(factory); + closure.execute(Boolean.FALSE, Boolean.TRUE); + assertEquals(1, factory.count); + } + + public void testAdaptInterruptibleFactory_toString() throws Exception { + LocalInterruptibleFactory factory = new LocalInterruptibleFactory<>(); + InterruptibleBiClosure closure = BiClosureTools.adapt(factory); + assertTrue(closure.toString().indexOf("InterruptibleFactoryBiClosure") != -1); + assertTrue(closure.toString().indexOf("LocalInterruptibleFactory") != -1); + } + + public void testAdaptInterruptibleFactory_NPE() { + boolean exCaught = false; + try { + InterruptibleBiClosure closure = BiClosureTools.adapt((InterruptibleFactory) null); + fail("bogus: " + closure); + } catch (NullPointerException ex) { + exCaught = true; + } + assertTrue(exCaught); + } + + public void testNullBiClosure_execute() throws Exception { + BiClosure closure = BiClosureTools.nullBiClosure(); + closure.execute(Boolean.FALSE, null); + assertNotNull(closure); + } + + public void testNullBiClosure_toString() throws Exception { + BiClosure closure = BiClosureTools.nullBiClosure(); + assertTrue(closure.toString().indexOf("NullBiClosure") != -1); + } + + public void testNullBiClosure_serialization() throws Exception { + BiClosure closure = BiClosureTools.nullBiClosure(); + Object clone = TestTools.serialize(closure); + assertSame(closure, clone); + } + + public void testThreadLocalBiClosure_execute() throws Exception { + final ModifiableIntReference ref = new SimpleIntReference(); + final ThreadLocalBiClosure closure = BiClosureTools.threadLocalBiClosure(); + closure.execute(Integer.valueOf(3), Integer.valueOf(2)); + assertEquals(0, ref.getValue()); + Runnable r = new Runnable() { + @Override + public void run() { + closure.set(new BiClosureAdapter() { + @Override + public void execute(Integer integer1, Integer integer2) { + ref.add(integer1.intValue()); + ref.add(integer2.intValue()); + } + }); + closure.execute(Integer.valueOf(3), Integer.valueOf(2)); + } + }; + Thread thread = new Thread(r); + thread.start(); + thread.join(); + assertEquals(5, ref.getValue()); + } + + public void testThreadLocalBiClosure_toString() { + ThreadLocalBiClosure closure = BiClosureTools.threadLocalBiClosure(); + assertTrue(closure.toString().indexOf("NullBiClosure") != -1); + } + + public void testThreadLocalBiClosure_NPE() { + boolean exCaught = false; + try { + ThreadLocalBiClosure closure = BiClosureTools.threadLocalBiClosure(null); + fail("bogus: " + closure); + } catch (NullPointerException ex) { + exCaught = true; + } + assertTrue(exCaught); + } + + public void testThreadLocalInterruptibleBiClosure_execute() throws Exception { + final ModifiableIntReference ref = new SimpleIntReference(); + final ThreadLocalInterruptibleBiClosure closure = BiClosureTools.threadLocalInterruptibleBiClosure(); + closure.execute(Integer.valueOf(3), Integer.valueOf(2)); + assertEquals(0, ref.getValue()); + Runnable r = new Runnable() { + @Override + public void run() { + closure.set(new BiClosureAdapter() { + @Override + public void execute(Integer integer1, Integer integer2) { + ref.add(integer1.intValue()); + ref.add(integer2.intValue()); + } + }); + try { + closure.execute(Integer.valueOf(3), Integer.valueOf(2)); + } catch (InterruptedException ex) { + throw new RuntimeException(ex); + } + } + }; + Thread thread = new Thread(r); + thread.start(); + thread.join(); + assertEquals(5, ref.getValue()); + } + + public void testThreadLocalInterruptibleBiClosure_toString() { + ThreadLocalInterruptibleBiClosure closure = BiClosureTools.threadLocalInterruptibleBiClosure(); + assertTrue(closure.toString().indexOf("NullBiClosure") != -1); + } + + public void testThreadLocalInterruptibleBiClosure_NPE() { + boolean exCaught = false; + try { + ThreadLocalInterruptibleBiClosure closure = BiClosureTools.threadLocalInterruptibleBiClosure(null); + fail("bogus: " + closure); + } catch (NullPointerException ex) { + exCaught = true; + } + assertTrue(exCaught); + } + + public void testWrap_execute() throws Exception { + final ModifiableIntReference ref = new SimpleIntReference(); + BiClosureWrapper closure = BiClosureTools.wrap(new BiClosureAdapter() { + @Override + public void execute(Integer argument1, Integer argument2) { + ref.add(argument1.intValue()); + ref.add(argument2.intValue()); + } + }); + closure.execute(Integer.valueOf(3), Integer.valueOf(2)); + assertEquals(5, ref.getValue()); + closure.setClosure(new BiClosureAdapter() { + @Override + public void execute(Integer argument1, Integer argument2) { + ref.add(2 * argument1.intValue()); + ref.add(2 * argument2.intValue()); + } + }); + closure.execute(Integer.valueOf(3), Integer.valueOf(2)); + assertEquals(15, ref.getValue()); + } + + public void testWrap_toString() { + BiClosureWrapper closure = BiClosureTools.wrap(new BiClosureAdapter() { + @Override + public void execute(Integer argument1, Integer argument2) { + // NOP + } + }); + assertTrue(closure.toString().indexOf("BiClosureWrapper") != -1); + } + + public void testWrap_NPE1() { + boolean exCaught = false; + try { + BiClosure closure = BiClosureTools.wrap((BiClosure) null); + fail("bogus: " + closure); + } catch (NullPointerException ex) { + exCaught = true; + } + assertTrue(exCaught); + } + + public void testWrap_NPE2() { + BiClosureWrapper closure = BiClosureTools.wrap(new BiClosureAdapter()); + boolean exCaught = false; + try { + closure.setClosure(null); + fail("bogus: " + closure); + } catch (NullPointerException ex) { + exCaught = true; + } + assertTrue(exCaught); + } + + public void testWrapInterruptible_execute() throws Exception { + final ModifiableIntReference ref = new SimpleIntReference(); + InterruptibleBiClosureWrapper closure = BiClosureTools.wrap(new InterruptibleBiClosureAdapter() { + @Override + public void execute(Integer argument1, Integer argument2) throws InterruptedException { + ref.add(argument1.intValue()); + ref.add(argument2.intValue()); + } + }); + closure.execute(Integer.valueOf(3), Integer.valueOf(2)); + assertEquals(5, ref.getValue()); + closure.setClosure(new InterruptibleBiClosureAdapter() { + @Override + public void execute(Integer argument1, Integer argument2) throws InterruptedException { + ref.add(2 * argument1.intValue()); + ref.add(2 * argument2.intValue()); + } + }); + closure.execute(Integer.valueOf(3), Integer.valueOf(2)); + assertEquals(15, ref.getValue()); + } + + public void testWrapInterruptible_toString() { + InterruptibleBiClosureWrapper closure = BiClosureTools.wrap(new InterruptibleBiClosureAdapter() { + @Override + public void execute(Integer argument1, Integer argument2) throws InterruptedException { + // NOP + } + }); + assertTrue(closure.toString().indexOf("InterruptibleBiClosureWrapper") != -1); + } + + public void testWrapInterruptible_NPE1() { + boolean exCaught = false; + try { + InterruptibleBiClosure closure = BiClosureTools.wrap((InterruptibleBiClosure) null); + fail("bogus: " + closure); + } catch (NullPointerException ex) { + exCaught = true; + } + assertTrue(exCaught); + } + + public void testWrapInterruptible_NPE2() { + InterruptibleBiClosureWrapper closure = BiClosureTools.wrap(new InterruptibleBiClosureAdapter()); + boolean exCaught = false; + try { + closure.setClosure(null); + fail("bogus: " + closure); + } catch (NullPointerException ex) { + exCaught = true; + } + assertTrue(exCaught); + } + + public void testSafeClosure_execute() throws Exception { + LocalBiClosure closure1 = new LocalBiClosure(); + BiClosure closure2 = BiClosureTools.safeBiClosure(closure1); + closure2.execute(Integer.valueOf(3), Integer.valueOf(2)); + assertEquals(5, closure1.count); + CollectingExceptionHandler handler = new CollectingExceptionHandler(); + closure2 = BiClosureTools.safeBiClosure(closure1, handler); + closure2.execute(null, null); + assertEquals(1, IterableTools.size(handler.getExceptions())); + } + + public void testSafeBiClosure_toString() { + BiClosure closure = BiClosureTools.safeBiClosure(new LocalBiClosure()); + assertTrue(closure.toString().indexOf("SafeBiClosureWrapper") != -1); + assertTrue(closure.toString().indexOf("LocalBiClosure") != -1); + } + + public void testSafeBiClosure_NPE1() { + boolean exCaught = false; + try { + BiClosure closure = BiClosureTools.safeBiClosure((BiClosure) null); + fail("bogus: " + closure); + } catch (NullPointerException ex) { + exCaught = true; + } + assertTrue(exCaught); + } + + public void testSafeBiClosure_NPE2() { + boolean exCaught = false; + try { + BiClosure closure = BiClosureTools.safeBiClosure(new LocalBiClosure(), null); + fail("bogus: " + closure); + } catch (NullPointerException ex) { + exCaught = true; + } + assertTrue(exCaught); + } + + public void testSafeInterruptibleClosure_execute() throws Exception { + LocalInterruptibleBiClosure closure1 = new LocalInterruptibleBiClosure(); + InterruptibleBiClosure closure2 = BiClosureTools.safeBiClosure(closure1); + closure2.execute(Integer.valueOf(3), Integer.valueOf(2)); + assertEquals(5, closure1.count); + CollectingExceptionHandler handler = new CollectingExceptionHandler(); + closure2 = BiClosureTools.safeBiClosure(closure1, handler); + closure2.execute(null, null); + assertEquals(1, IterableTools.size(handler.getExceptions())); + } + + public void testSafeInterruptibleBiClosure_toString() { + InterruptibleBiClosure closure = BiClosureTools.safeBiClosure(new LocalInterruptibleBiClosure()); + assertTrue(closure.toString().indexOf("SafeInterruptibleBiClosureWrapper") != -1); + assertTrue(closure.toString().indexOf("LocalInterruptibleBiClosure") != -1); + } + + public void testSafeInterruptibleBiClosure_NPE1() { + boolean exCaught = false; + try { + InterruptibleBiClosure closure = BiClosureTools.safeBiClosure((InterruptibleBiClosure) null); + fail("bogus: " + closure); + } catch (NullPointerException ex) { + exCaught = true; + } + assertTrue(exCaught); + } + + public void testSafeInterruptibleBiClosure_NPE2() { + boolean exCaught = false; + try { + InterruptibleBiClosure closure = BiClosureTools.safeBiClosure(new LocalInterruptibleBiClosure(), null); + fail("bogus: " + closure); + } catch (NullPointerException ex) { + exCaught = true; + } + assertTrue(exCaught); + } + + public void testCompositeClosure_execute1() throws Exception { + LocalBiClosure closure1 = new LocalBiClosure(); + LocalBiClosure closure2 = new LocalBiClosure(); + BiClosure closure = BiClosureTools.compositeBiClosure(closure1, closure2); + closure.execute(Integer.valueOf(3), Integer.valueOf(2)); + assertEquals(5, closure1.count); + assertEquals(5, closure2.count); + @SuppressWarnings("unchecked") + BiClosure[] closureArray = new BiClosure[0]; + closure = BiClosureTools.compositeBiClosure(closureArray); + closure.execute(Integer.valueOf(3), Integer.valueOf(2)); + } + + public void testCompositeBiClosure_execute2() throws Exception { + LocalBiClosure closure1 = new LocalBiClosure(); + LocalBiClosure closure2 = new LocalBiClosure(); + ArrayList list = new ArrayList<>(); + list.add(closure1); + list.add(closure2); + BiClosure closure = BiClosureTools.compositeBiClosure(list); + closure.execute(Integer.valueOf(3), Integer.valueOf(2)); + assertEquals(5, closure1.count); + assertEquals(5, closure2.count); + list.clear(); + closure = BiClosureTools.compositeBiClosure(list); + closure.execute(Integer.valueOf(3), Integer.valueOf(2)); + } + + public void testCompositeBiClosure_toString() { + LocalBiClosure closure1 = new LocalBiClosure(); + LocalBiClosure closure2 = new LocalBiClosure(); + BiClosure closure = BiClosureTools.compositeBiClosure(closure1, closure2); + assertTrue(closure.toString().indexOf("CompositeBiClosure") != -1); + assertTrue(closure.toString().indexOf("LocalBiClosure") != -1); + } + + public void testCompositeBiClosure_NPE1() { + LocalBiClosure closure1 = new LocalBiClosure(); + boolean exCaught = false; + try { + BiClosure closure = BiClosureTools.compositeBiClosure(closure1, null); + fail("bogus: " + closure); + } catch (NullPointerException ex) { + exCaught = true; + } + assertTrue(exCaught); + } + + public void testCompositeBiClosure_NPE2() { + boolean exCaught = false; + try { + BiClosure closure = BiClosureTools.compositeBiClosure((Iterable>) null); + fail("bogus: " + closure); + } catch (NullPointerException ex) { + exCaught = true; + } + assertTrue(exCaught); + } + + public void testCompositeInterruptibleClosure_execute1() throws Exception { + LocalInterruptibleBiClosure closure1 = new LocalInterruptibleBiClosure(); + LocalInterruptibleBiClosure closure2 = new LocalInterruptibleBiClosure(); + InterruptibleBiClosure closure = BiClosureTools.compositeInterruptibleBiClosure(closure1, closure2); + closure.execute(Integer.valueOf(3), Integer.valueOf(2)); + assertEquals(5, closure1.count); + assertEquals(5, closure2.count); + @SuppressWarnings("unchecked") + InterruptibleBiClosure[] closureArray = new InterruptibleBiClosure[0]; + closure = BiClosureTools.compositeInterruptibleBiClosure(closureArray); + closure.execute(Integer.valueOf(3), Integer.valueOf(2)); + } + + public void testCompositeInterruptibleBiClosure_execute2() throws Exception { + LocalInterruptibleBiClosure closure1 = new LocalInterruptibleBiClosure(); + LocalInterruptibleBiClosure closure2 = new LocalInterruptibleBiClosure(); + ArrayList list = new ArrayList<>(); + list.add(closure1); + list.add(closure2); + InterruptibleBiClosure closure = BiClosureTools.compositeInterruptibleBiClosure(list); + closure.execute(Integer.valueOf(3), Integer.valueOf(2)); + assertEquals(5, closure1.count); + assertEquals(5, closure2.count); + list.clear(); + closure = BiClosureTools.compositeInterruptibleBiClosure(list); + closure.execute(Integer.valueOf(3), Integer.valueOf(2)); + } + + public void testCompositeInterruptibleBiClosure_toString() { + LocalInterruptibleBiClosure closure1 = new LocalInterruptibleBiClosure(); + LocalInterruptibleBiClosure closure2 = new LocalInterruptibleBiClosure(); + InterruptibleBiClosure closure = BiClosureTools.compositeInterruptibleBiClosure(closure1, closure2); + assertTrue(closure.toString().indexOf("CompositeInterruptibleBiClosure") != -1); + assertTrue(closure.toString().indexOf("LocalInterruptibleBiClosure") != -1); + } + + public void testCompositeInterruptibleBiClosure_NPE1() { + LocalInterruptibleBiClosure closure1 = new LocalInterruptibleBiClosure(); + boolean exCaught = false; + try { + InterruptibleBiClosure closure = BiClosureTools.compositeInterruptibleBiClosure(closure1, null); + fail("bogus: " + closure); + } catch (NullPointerException ex) { + exCaught = true; + } + assertTrue(exCaught); + } + + public void testCompositeInterruptibleBiClosure_NPE2() { + boolean exCaught = false; + try { + InterruptibleBiClosure closure = BiClosureTools.compositeInterruptibleBiClosure((Iterable>) null); + fail("bogus: " + closure); + } catch (NullPointerException ex) { + exCaught = true; + } + assertTrue(exCaught); + } + + public void testDisabledBiClosure_execute() { + BiClosure closure = BiClosureTools.disabledBiClosure(); + boolean exCaught = false; + try { + closure.execute(null, null); + fail(); + } catch (UnsupportedOperationException ex) { + exCaught = true; + } + assertTrue(exCaught); + } + + public void testDisabledBiClosure_toString() { + BiClosure closure = BiClosureTools.disabledBiClosure(); + assertTrue(closure.toString().indexOf("DisabledBiClosure") != -1); + } + + public void testDisabledBiClosure_serialization() throws Exception { + BiClosure closure = BiClosureTools.disabledBiClosure(); + assertSame(closure, TestTools.serialize(closure)); + } + + public void testInterruptedBiClosure_execute() { + InterruptibleBiClosure closure = BiClosureTools.interruptedBiClosure(); + boolean exCaught = false; + try { + closure.execute(null, null); + fail(); + } catch (InterruptedException ex) { + exCaught = true; + } + assertTrue(exCaught); + } + + public void testInterruptedBiClosure_toString() { + InterruptibleBiClosure closure = BiClosureTools.interruptedBiClosure(); + assertTrue(closure.toString().indexOf("InterruptedBiClosure") != -1); + } + + public void testInterruptedBiClosure_serialization() throws Exception { + InterruptibleBiClosure closure = BiClosureTools.interruptedBiClosure(); + assertSame(closure, TestTools.serialize(closure)); + } + + public void testRepeatingBiClosure_execute1() throws Exception { + LocalBiClosure closure1 = new LocalBiClosure(); + BiClosure closure2 = BiClosureTools.repeatingBiClosure(closure1, 3); + closure2.execute(Integer.valueOf(3), Integer.valueOf(2)); + assertEquals(15, closure1.count); + } + + public void testRepeatingBiClosure_execute2() throws Exception { + LocalBiClosure closure1 = new LocalBiClosure(); + BiClosure closure2 = BiClosureTools.repeatingBiClosure(closure1, 0); + closure2.execute(Integer.valueOf(3), Integer.valueOf(2)); + assertEquals(0, closure1.count); + } + + public void testRepeatingBiClosure_toString() { + LocalBiClosure closure1 = new LocalBiClosure(); + BiClosure closure2 = BiClosureTools.repeatingBiClosure(closure1, 3); + assertTrue(closure2.toString().indexOf("RepeatingBiClosure") != -1); + assertTrue(closure2.toString().indexOf("LocalBiClosure") != -1); + } + + public void testRepeatingBiClosure_NPE1() { + boolean exCaught = false; + try { + BiClosure closure = BiClosureTools.repeatingBiClosure((BiClosure) null, 3); + fail("bogus: " + closure); + } catch (NullPointerException ex) { + exCaught = true; + } + assertTrue(exCaught); + } + + public void testRepeatingBiClosure_NPE2() { + LocalBiClosure closure1 = new LocalBiClosure(); + boolean exCaught = false; + try { + BiClosure closure2 = BiClosureTools.repeatingBiClosure(closure1, -3); + fail("bogus: " + closure2); + } catch (IndexOutOfBoundsException ex) { + exCaught = true; + } + assertTrue(exCaught); + } + + public void testRepeatingInterruptibleBiClosure_execute1() throws Exception { + LocalInterruptibleBiClosure closure1 = new LocalInterruptibleBiClosure(); + InterruptibleBiClosure closure2 = BiClosureTools.repeatingBiClosure(closure1, 3); + closure2.execute(Integer.valueOf(3), Integer.valueOf(2)); + assertEquals(15, closure1.count); + } + + public void testRepeatingInterruptibleBiClosure_execute2() throws Exception { + LocalInterruptibleBiClosure closure1 = new LocalInterruptibleBiClosure(); + InterruptibleBiClosure closure2 = BiClosureTools.repeatingBiClosure(closure1, 0); + closure2.execute(Integer.valueOf(3), Integer.valueOf(2)); + assertEquals(0, closure1.count); + } + + public void testRepeatingInterruptibleBiClosure_toString() { + LocalInterruptibleBiClosure closure1 = new LocalInterruptibleBiClosure(); + InterruptibleBiClosure closure2 = BiClosureTools.repeatingBiClosure(closure1, 3); + assertTrue(closure2.toString().indexOf("RepeatingInterruptibleBiClosure") != -1); + assertTrue(closure2.toString().indexOf("LocalInterruptibleBiClosure") != -1); + } + + public void testRepeatingInterruptibleBiClosure_NPE1() { + boolean exCaught = false; + try { + InterruptibleBiClosure closure = BiClosureTools.repeatingBiClosure((InterruptibleBiClosure) null, 3); + fail("bogus: " + closure); + } catch (NullPointerException ex) { + exCaught = true; + } + assertTrue(exCaught); + } + + public void testRepeatingInterruptibleBiClosure_NPE2() { + LocalInterruptibleBiClosure closure1 = new LocalInterruptibleBiClosure(); + boolean exCaught = false; + try { + InterruptibleBiClosure closure2 = BiClosureTools.repeatingBiClosure(closure1, -3); + fail("bogus: " + closure2); + } catch (IndexOutOfBoundsException ex) { + exCaught = true; + } + assertTrue(exCaught); + } + + public void testConstructor() { + boolean exCaught = false; + try { + Object at = ClassTools.newInstance(BiClosureTools.class); + fail("bogus: " + at); + } catch (RuntimeException ex) { + if (ex.getCause() instanceof InvocationTargetException) { + if (ex.getCause().getCause() instanceof UnsupportedOperationException) { + exCaught = true; + } + } + } + assertTrue(exCaught); + } + + // ********** test classes ********** + + public static class LocalBiClosure + extends BiClosureAdapter + { + public int count = 0; + + @Override + public void execute(Integer argument1, Integer argument2) { + this.count += argument1.intValue(); // possible NPE + this.count += argument2.intValue(); // possible NPE + } + } + + public static class LocalInterruptibleBiClosure + extends InterruptibleBiClosureAdapter + { + public int count = 0; + + @Override + public void execute(Integer argument1, Integer argument2) throws InterruptedException { + this.count += argument1.intValue(); // possible NPE + this.count += argument2.intValue(); // possible NPE + } + } +} diff --git a/common/tests/org.eclipse.jpt.common.utility.tests/src/org/eclipse/jpt/common/utility/tests/internal/closure/ClosureToolsTests.java b/common/tests/org.eclipse.jpt.common.utility.tests/src/org/eclipse/jpt/common/utility/tests/internal/closure/ClosureToolsTests.java new file mode 100644 index 0000000000..242d28fa84 --- /dev/null +++ b/common/tests/org.eclipse.jpt.common.utility.tests/src/org/eclipse/jpt/common/utility/tests/internal/closure/ClosureToolsTests.java @@ -0,0 +1,1854 @@ +/******************************************************************************* + * Copyright (c) 2016 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.tests.internal.closure; + +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.List; +import org.eclipse.jpt.common.utility.Association; +import org.eclipse.jpt.common.utility.closure.Closure; +import org.eclipse.jpt.common.utility.closure.InterruptibleClosure; +import org.eclipse.jpt.common.utility.command.Command; +import org.eclipse.jpt.common.utility.command.InterruptibleCommand; +import org.eclipse.jpt.common.utility.factory.Factory; +import org.eclipse.jpt.common.utility.factory.InterruptibleFactory; +import org.eclipse.jpt.common.utility.internal.ClassTools; +import org.eclipse.jpt.common.utility.internal.SimpleAssociation; +import org.eclipse.jpt.common.utility.internal.closure.ClosureAdapter; +import org.eclipse.jpt.common.utility.internal.closure.ClosureTools; +import org.eclipse.jpt.common.utility.internal.closure.ClosureWrapper; +import org.eclipse.jpt.common.utility.internal.closure.InterruptibleClosureAdapter; +import org.eclipse.jpt.common.utility.internal.closure.InterruptibleClosureWrapper; +import org.eclipse.jpt.common.utility.internal.closure.ThreadLocalClosure; +import org.eclipse.jpt.common.utility.internal.closure.ThreadLocalInterruptibleClosure; +import org.eclipse.jpt.common.utility.internal.command.CommandAdapter; +import org.eclipse.jpt.common.utility.internal.command.CommandTools; +import org.eclipse.jpt.common.utility.internal.command.InterruptibleCommandAdapter; +import org.eclipse.jpt.common.utility.internal.exception.CollectingExceptionHandler; +import org.eclipse.jpt.common.utility.internal.factory.FactoryAdapter; +import org.eclipse.jpt.common.utility.internal.factory.InterruptibleFactoryAdapter; +import org.eclipse.jpt.common.utility.internal.iterable.IterableTools; +import org.eclipse.jpt.common.utility.internal.predicate.PredicateAdapter; +import org.eclipse.jpt.common.utility.internal.predicate.PredicateTools; +import org.eclipse.jpt.common.utility.internal.reference.SimpleIntReference; +import org.eclipse.jpt.common.utility.internal.transformer.InterruptibleTransformerAdapter; +import org.eclipse.jpt.common.utility.internal.transformer.TransformerAdapter; +import org.eclipse.jpt.common.utility.predicate.Predicate; +import org.eclipse.jpt.common.utility.reference.ModifiableIntReference; +import org.eclipse.jpt.common.utility.tests.internal.TestTools; +import org.eclipse.jpt.common.utility.transformer.InterruptibleTransformer; +import org.eclipse.jpt.common.utility.transformer.Transformer; +import junit.framework.TestCase; + +@SuppressWarnings("nls") +public class ClosureToolsTests + extends TestCase +{ + public ClosureToolsTests(String name) { + super(name); + } + + public void testAdaptCommand_execute() { + LocalCommand command = new LocalCommand(); + Closure closure = ClosureTools.adapt(command); + closure.execute(Boolean.FALSE); + assertEquals(1, command.count); + } + + public void testAdaptCommand_toString() { + LocalCommand command = new LocalCommand(); + Closure closure = ClosureTools.adapt(command); + assertTrue(closure.toString().indexOf("CommandClosure") != -1); + assertTrue(closure.toString().indexOf("LocalCommand") != -1); + } + + public void testAdaptCommand_NPE() { + boolean exCaught = false; + try { + Closure closure = ClosureTools.adapt((Command) null); + fail("bogus: " + closure); + } catch (NullPointerException ex) { + exCaught = true; + } + assertTrue(exCaught); + } + + public void testAdaptInterruptibleCommand_execute() throws Exception { + LocalInterruptibleCommand command = new LocalInterruptibleCommand(); + InterruptibleClosure closure = ClosureTools.adapt(command); + closure.execute(Boolean.FALSE); + assertEquals(1, command.count); + } + + public void testAdaptInterruptibleCommand_toString() { + LocalInterruptibleCommand command = new LocalInterruptibleCommand(); + InterruptibleClosure closure = ClosureTools.adapt(command); + assertTrue(closure.toString().indexOf("InterruptibleCommandClosure") != -1); + assertTrue(closure.toString().indexOf("LocalInterruptibleCommand") != -1); + } + + public void testAdaptInterruptibleCommand_NPE() { + boolean exCaught = false; + try { + InterruptibleClosure closure = ClosureTools.adapt((InterruptibleCommand) null); + fail("bogus: " + closure); + } catch (NullPointerException ex) { + exCaught = true; + } + assertTrue(exCaught); + } + + public void testAdaptFactory_execute() { + LocalFactory factory = new LocalFactory<>(); + Closure closure = ClosureTools.adapt(factory); + closure.execute(Boolean.FALSE); + assertEquals(1, factory.count); + } + + public void testAdaptFactory_toString() { + LocalFactory factory = new LocalFactory<>(); + Closure closure = ClosureTools.adapt(factory); + assertTrue(closure.toString().indexOf("FactoryClosure") != -1); + assertTrue(closure.toString().indexOf("LocalFactory") != -1); + } + + public void testAdaptFactory_NPE() { + boolean exCaught = false; + try { + Closure closure = ClosureTools.adapt((Factory) null); + fail("bogus: " + closure); + } catch (NullPointerException ex) { + exCaught = true; + } + assertTrue(exCaught); + } + + public void testAdaptInterruptibleFactory_execute() throws Exception { + LocalInterruptibleFactory factory = new LocalInterruptibleFactory<>(); + InterruptibleClosure closure = ClosureTools.adapt(factory); + closure.execute(Boolean.FALSE); + assertEquals(1, factory.count); + } + + public void testAdaptInterruptibleFactory_toString() { + LocalInterruptibleFactory factory = new LocalInterruptibleFactory<>(); + InterruptibleClosure closure = ClosureTools.adapt(factory); + assertTrue(closure.toString().indexOf("InterruptibleFactoryClosure") != -1); + assertTrue(closure.toString().indexOf("LocalInterruptibleFactory") != -1); + } + + public void testAdaptInterruptibleFactory_NPE() { + boolean exCaught = false; + try { + InterruptibleClosure closure = ClosureTools.adapt((InterruptibleFactory) null); + fail("bogus: " + closure); + } catch (NullPointerException ex) { + exCaught = true; + } + assertTrue(exCaught); + } + + public void testAdaptTransformer_execute() { + LocalTransformer transformer = new LocalTransformer<>(); + Closure closure = ClosureTools.adapt(transformer); + closure.execute(Boolean.FALSE); + assertEquals(1, transformer.count); + } + + public void testAdaptTransformer_toString() { + LocalTransformer transformer = new LocalTransformer<>(); + Closure closure = ClosureTools.adapt(transformer); + assertTrue(closure.toString().indexOf("TransformerClosure") != -1); + assertTrue(closure.toString().indexOf("LocalTransformer") != -1); + } + + public void testAdaptTransformer_NPE() { + boolean exCaught = false; + try { + Closure closure = ClosureTools.adapt((Transformer) null); + fail("bogus: " + closure); + } catch (NullPointerException ex) { + exCaught = true; + } + assertTrue(exCaught); + } + + public void testAdaptInterruptibleTransformer_execute() throws Exception { + LocalInterruptibleTransformer transformer = new LocalInterruptibleTransformer<>(); + InterruptibleClosure closure = ClosureTools.adapt(transformer); + closure.execute(Boolean.FALSE); + assertEquals(1, transformer.count); + } + + public void testAdaptInterruptibleTransformer_toString() { + LocalInterruptibleTransformer transformer = new LocalInterruptibleTransformer<>(); + InterruptibleClosure closure = ClosureTools.adapt(transformer); + assertTrue(closure.toString().indexOf("InterruptibleTransformerClosure") != -1); + assertTrue(closure.toString().indexOf("LocalInterruptibleTransformer") != -1); + } + + public void testAdaptInterruptibleTransformer_NPE() { + boolean exCaught = false; + try { + InterruptibleClosure closure = ClosureTools.adapt((InterruptibleTransformer) null); + fail("bogus: " + closure); + } catch (NullPointerException ex) { + exCaught = true; + } + assertTrue(exCaught); + } + + public void testNullClosure_execute() throws Exception { + Closure closure = ClosureTools.nullClosure(); + closure.execute(Boolean.FALSE); + assertNotNull(closure); + } + + public void testNullClosure_toString() throws Exception { + Closure closure = ClosureTools.nullClosure(); + assertTrue(closure.toString().indexOf("NullClosure") != -1); + } + + public void testNullClosure_serialization() throws Exception { + Closure closure = ClosureTools.nullClosure(); + Object clone = TestTools.serialize(closure); + assertSame(closure, clone); + } + + public void testThreadLocalClosure_execute() throws Exception { + final ModifiableIntReference ref = new SimpleIntReference(); + final ThreadLocalClosure closure = ClosureTools.threadLocalClosure(); + closure.execute(Integer.valueOf(3)); + assertEquals(0, ref.getValue()); + Runnable r = new Runnable() { + @Override + public void run() { + closure.set(new ClosureAdapter() { + @Override + public void execute(Integer integer) { + ref.add(integer.intValue()); + } + }); + closure.execute(Integer.valueOf(3)); + } + }; + Thread thread = new Thread(r); + thread.start(); + thread.join(); + assertEquals(3, ref.getValue()); + } + + public void testThreadLocalClosure_toString() { + ThreadLocalClosure closure = ClosureTools.threadLocalClosure(); + assertTrue(closure.toString().indexOf("NullClosure") != -1); + } + + public void testThreadLocalClosure_NPE() { + boolean exCaught = false; + try { + ThreadLocalClosure closure = ClosureTools.threadLocalClosure(null); + fail("bogus: " + closure); + } catch (NullPointerException ex) { + exCaught = true; + } + assertTrue(exCaught); + } + + public void testThreadLocalInterruptibleClosure_execute() throws Exception { + final ModifiableIntReference ref = new SimpleIntReference(); + final ThreadLocalInterruptibleClosure closure = ClosureTools.threadLocalInterruptibleClosure(); + closure.execute(Integer.valueOf(3)); + assertEquals(0, ref.getValue()); + Runnable r = new Runnable() { + @Override + public void run() { + closure.set(new ClosureAdapter() { + @Override + public void execute(Integer integer) { + ref.add(integer.intValue()); + } + }); + try { + closure.execute(Integer.valueOf(3)); + } catch (InterruptedException ex) { + throw new RuntimeException(ex); + } + } + }; + Thread thread = new Thread(r); + thread.start(); + thread.join(); + assertEquals(3, ref.getValue()); + } + + public void testThreadLocalInterruptibleClosure_toString() { + ThreadLocalInterruptibleClosure closure = ClosureTools.threadLocalInterruptibleClosure(); + assertTrue(closure.toString().indexOf("NullClosure") != -1); + } + + public void testThreadLocalInterruptibleClosure_NPE() { + boolean exCaught = false; + try { + ThreadLocalInterruptibleClosure closure = ClosureTools.threadLocalInterruptibleClosure(null); + fail("bogus: " + closure); + } catch (NullPointerException ex) { + exCaught = true; + } + assertTrue(exCaught); + } + + public void testNullCheck_execute() throws Exception { + LocalClosure closure1 = new LocalClosure(); + Closure closure2 = ClosureTools.nullCheck(closure1); + closure2.execute(null); + assertEquals(0, closure1.count); + closure2.execute(Integer.valueOf(3)); + assertEquals(3, closure1.count); + } + + public void testNullCheck_toString() { + Closure closure1 = new LocalClosure(); + Closure closure2 = ClosureTools.nullCheck(closure1); + assertTrue(closure2.toString().indexOf("NullCheckClosure") != -1); + assertTrue(closure2.toString().indexOf("LocalClosure") != -1); + } + + public void testNullCheck_NPE1() { + boolean exCaught = false; + try { + Closure closure = ClosureTools.nullCheck((Closure) null, CommandTools.nullCommand()); + fail("bogus: " + closure); + } catch (NullPointerException ex) { + exCaught = true; + } + assertTrue(exCaught); + } + + public void testNullCheck_NPE2() { + Closure closure1 = new LocalClosure(); + boolean exCaught = false; + try { + Closure closure2 = ClosureTools.nullCheck(closure1, null); + fail("bogus: " + closure2); + } catch (NullPointerException ex) { + exCaught = true; + } + assertTrue(exCaught); + } + + public void testNullCheckInterruptible_execute() throws Exception { + LocalInterruptibleClosure closure1 = new LocalInterruptibleClosure(); + InterruptibleClosure closure2 = ClosureTools.nullCheck(closure1); + closure2.execute(null); + assertEquals(0, closure1.count); + closure2.execute(Integer.valueOf(3)); + assertEquals(3, closure1.count); + } + + public void testNullCheckInterruptible_toString() { + InterruptibleClosure closure1 = new LocalInterruptibleClosure(); + InterruptibleClosure closure2 = ClosureTools.nullCheck(closure1); + assertTrue(closure2.toString().indexOf("NullCheckInterruptibleClosure") != -1); + assertTrue(closure2.toString().indexOf("LocalInterruptibleClosure") != -1); + } + + public void testNullCheckInterruptible_NPE1() { + boolean exCaught = false; + try { + InterruptibleClosure closure = ClosureTools.nullCheck((InterruptibleClosure) null, CommandTools.nullCommand()); + fail("bogus: " + closure); + } catch (NullPointerException ex) { + exCaught = true; + } + assertTrue(exCaught); + } + + public void testNullCheckInterruptible_NPE2() { + InterruptibleClosure closure1 = new LocalInterruptibleClosure(); + boolean exCaught = false; + try { + InterruptibleClosure closure2 = ClosureTools.nullCheck(closure1, null); + fail("bogus: " + closure2); + } catch (NullPointerException ex) { + exCaught = true; + } + assertTrue(exCaught); + } + + public void testWrap_execute() throws Exception { + final ModifiableIntReference ref = new SimpleIntReference(); + ClosureWrapper closure = ClosureTools.wrap(new ClosureAdapter() { + @Override + public void execute(Integer argument) { + ref.add(argument.intValue()); + } + }); + closure.execute(Integer.valueOf(3)); + assertEquals(3, ref.getValue()); + closure.setClosure(new ClosureAdapter() { + @Override + public void execute(Integer argument) { + ref.add(2 * argument.intValue()); + } + }); + closure.execute(Integer.valueOf(3)); + assertEquals(9, ref.getValue()); + } + + public void testWrap_toString() { + ClosureWrapper closure = ClosureTools.wrap(new ClosureAdapter() { + @Override + public void execute(Integer argument) { + // NOP + } + }); + assertTrue(closure.toString().indexOf("ClosureWrapper") != -1); + } + + public void testWrap_NPE1() { + boolean exCaught = false; + try { + Closure closure = ClosureTools.wrap((Closure) null); + fail("bogus: " + closure); + } catch (NullPointerException ex) { + exCaught = true; + } + assertTrue(exCaught); + } + + public void testWrap_NPE2() { + ClosureWrapper closure = ClosureTools.wrap(new LocalClosure()); + boolean exCaught = false; + try { + closure.setClosure(null); + fail("bogus: " + closure); + } catch (NullPointerException ex) { + exCaught = true; + } + assertTrue(exCaught); + } + + public void testWrapInterruptible_execute() throws Exception { + final ModifiableIntReference ref = new SimpleIntReference(); + InterruptibleClosureWrapper closure = ClosureTools.wrap(new InterruptibleClosureAdapter() { + @Override + public void execute(Integer argument) throws InterruptedException { + ref.add(argument.intValue()); + } + }); + closure.execute(Integer.valueOf(3)); + assertEquals(3, ref.getValue()); + closure.setClosure(new InterruptibleClosureAdapter() { + @Override + public void execute(Integer argument) throws InterruptedException { + ref.add(2 * argument.intValue()); + } + }); + closure.execute(Integer.valueOf(3)); + assertEquals(9, ref.getValue()); + } + + public void testWrapInterruptible_toString() { + InterruptibleClosureWrapper closure = ClosureTools.wrap(new InterruptibleClosureAdapter() { + @Override + public void execute(Integer argument) throws InterruptedException { + // NOP + } + }); + assertTrue(closure.toString().indexOf("InterruptibleClosureWrapper") != -1); + } + + public void testWrapInterruptible_NPE1() { + boolean exCaught = false; + try { + InterruptibleClosure closure = ClosureTools.wrap((InterruptibleClosure) null); + fail("bogus: " + closure); + } catch (NullPointerException ex) { + exCaught = true; + } + assertTrue(exCaught); + } + + public void testWrapInterruptible_NPE2() { + InterruptibleClosureWrapper closure = ClosureTools.wrap(new LocalInterruptibleClosure()); + boolean exCaught = false; + try { + closure.setClosure(null); + fail("bogus: " + closure); + } catch (NullPointerException ex) { + exCaught = true; + } + assertTrue(exCaught); + } + + public void testSafeClosure_execute() throws Exception { + LocalClosure closure1 = new LocalClosure(); + Closure closure2 = ClosureTools.safeClosure(closure1); + closure2.execute(Integer.valueOf(3)); + assertEquals(3, closure1.count); + CollectingExceptionHandler handler = new CollectingExceptionHandler(); + closure2 = ClosureTools.safeClosure(closure1, handler); + closure2.execute(null); + assertEquals(1, IterableTools.size(handler.getExceptions())); + } + + public void testSafeClosure_toString() { + Closure closure = ClosureTools.safeClosure(new LocalClosure()); + assertTrue(closure.toString().indexOf("SafeClosureWrapper") != -1); + assertTrue(closure.toString().indexOf("LocalClosure") != -1); + } + + public void testSafeClosure_NPE1() { + boolean exCaught = false; + try { + Closure closure = ClosureTools.safeClosure((Closure) null); + fail("bogus: " + closure); + } catch (NullPointerException ex) { + exCaught = true; + } + assertTrue(exCaught); + } + + public void testSafeClosure_NPE2() { + boolean exCaught = false; + try { + Closure closure = ClosureTools.safeClosure(new LocalClosure(), null); + fail("bogus: " + closure); + } catch (NullPointerException ex) { + exCaught = true; + } + assertTrue(exCaught); + } + + public void testSafeInterruptibleClosure_execute() throws Exception { + LocalInterruptibleClosure closure1 = new LocalInterruptibleClosure(); + InterruptibleClosure closure2 = ClosureTools.safeClosure(closure1); + closure2.execute(Integer.valueOf(3)); + assertEquals(3, closure1.count); + CollectingExceptionHandler handler = new CollectingExceptionHandler(); + closure2 = ClosureTools.safeClosure(closure1, handler); + closure2.execute(null); + assertEquals(1, IterableTools.size(handler.getExceptions())); + } + + public void testSafeInterruptibleClosure_toString() { + InterruptibleClosure closure = ClosureTools.safeClosure(new LocalInterruptibleClosure()); + assertTrue(closure.toString().indexOf("SafeInterruptibleClosureWrapper") != -1); + assertTrue(closure.toString().indexOf("LocalInterruptibleClosure") != -1); + } + + public void testSafeInterruptibleClosure_NPE1() { + boolean exCaught = false; + try { + InterruptibleClosure closure = ClosureTools.safeClosure((InterruptibleClosure) null); + fail("bogus: " + closure); + } catch (NullPointerException ex) { + exCaught = true; + } + assertTrue(exCaught); + } + + public void testSafeInterruptibleClosure_NPE2() { + boolean exCaught = false; + try { + InterruptibleClosure closure = ClosureTools.safeClosure(new LocalInterruptibleClosure(), null); + fail("bogus: " + closure); + } catch (NullPointerException ex) { + exCaught = true; + } + assertTrue(exCaught); + } + + public void testMethodClosure_execute() throws Exception { + Closure closure = ClosureTools.methodClosure("execute"); + LocalCommand cmd = new LocalCommand(); + assertEquals(0, cmd.count); + closure.execute(cmd); + assertEquals(1, cmd.count); + } + + public void testMethodClosure_execute_arg() throws Exception { + LocalCommand cmd = new LocalCommand(); + Closure closure = ClosureTools.methodClosure("equals", Object.class, cmd); + assertEquals(0, cmd.count); + closure.execute(cmd); + assertEquals(0, cmd.count); + } + + public void testMethodClosure_equals() throws Exception { + Closure closure1 = ClosureTools.methodClosure("equals", Object.class, "foo"); + Closure closure2 = ClosureTools.methodClosure("equals", Object.class, "foo"); + assertFalse(closure1.equals(null)); + assertFalse(closure1.equals("foo")); + assertTrue(closure1.equals(closure1)); + assertTrue(closure1.equals(closure2)); + closure2 = ClosureTools.methodClosure("equals", Object.class, "bar"); + assertFalse(closure1.equals(closure2)); + closure2 = ClosureTools.methodClosure("equals", String.class, "foo"); + assertFalse(closure1.equals(closure2)); + closure2 = ClosureTools.methodClosure("toString", Object.class, "foo"); + assertFalse(closure1.equals(closure2)); + } + + public void testMethodClosure_hashCode() throws Exception { + Closure closure1 = ClosureTools.methodClosure("equals", Object.class, "foo"); + Closure closure2 = ClosureTools.methodClosure("equals", Object.class, "foo"); + assertEquals(closure1.hashCode(), closure1.hashCode()); + assertEquals(closure1.hashCode(), closure2.hashCode()); + } + + public void testMethodClosure_toString() { + Closure closure = ClosureTools.methodClosure("execute"); + assertTrue(closure.toString().indexOf("MethodClosure") != -1); + assertTrue(closure.toString().indexOf("execute()") != -1); + } + + public void testMethodClosure_NPE1() { + boolean exCaught = false; + try { + Closure closure = ClosureTools.methodClosure(null); + fail("bogus: " + closure); + } catch (NullPointerException ex) { + exCaught = true; + } + assertTrue(exCaught); + } + + public void testMethodClosure_NPE2() { + boolean exCaught = false; + try { + Closure closure = ClosureTools.methodClosure("execute", (Class[]) null, new Object[0]); + fail("bogus: " + closure); + } catch (NullPointerException ex) { + exCaught = true; + } + assertTrue(exCaught); + } + + public void testMethodClosure_NPE2a() { + boolean exCaught = false; + try { + Closure closure = ClosureTools.methodClosure("execute", new Class[] {Object.class, null}, new Object[2]); + fail("bogus: " + closure); + } catch (NullPointerException ex) { + exCaught = true; + } + assertTrue(exCaught); + } + + public void testMethodClosure_NPE3() { + boolean exCaught = false; + try { + Closure closure = ClosureTools.methodClosure("execute", new Class[0], null); + fail("bogus: " + closure); + } catch (NullPointerException ex) { + exCaught = true; + } + assertTrue(exCaught); + } + + public void testCompositeClosure_execute1() throws Exception { + LocalClosure closure1 = new LocalClosure(); + LocalClosure closure2 = new LocalClosure(); + Closure closure = ClosureTools.compositeClosure(closure1, closure2); + closure.execute(Integer.valueOf(3)); + assertEquals(3, closure1.count); + assertEquals(3, closure2.count); + @SuppressWarnings("unchecked") + Closure[] closureArray = new Closure[0]; + closure = ClosureTools.compositeClosure(closureArray); + closure.execute(Integer.valueOf(3)); + } + + public void testCompositeClosure_execute2() throws Exception { + LocalClosure closure1 = new LocalClosure(); + LocalClosure closure2 = new LocalClosure(); + ArrayList list = new ArrayList<>(); + list.add(closure1); + list.add(closure2); + Closure closure = ClosureTools.compositeClosure(list); + closure.execute(Integer.valueOf(3)); + assertEquals(3, closure1.count); + assertEquals(3, closure2.count); + list.clear(); + closure = ClosureTools.compositeClosure(list); + closure.execute(Integer.valueOf(3)); + } + + public void testCompositeClosure_toString() { + LocalClosure closure1 = new LocalClosure(); + LocalClosure closure2 = new LocalClosure(); + Closure closure = ClosureTools.compositeClosure(closure1, closure2); + assertTrue(closure.toString().indexOf("CompositeClosure") != -1); + assertTrue(closure.toString().indexOf("LocalClosure") != -1); + } + + public void testCompositeClosure_NPE1() { + LocalClosure closure1 = new LocalClosure(); + boolean exCaught = false; + try { + Closure closure = ClosureTools.compositeClosure(closure1, null); + fail("bogus: " + closure); + } catch (NullPointerException ex) { + exCaught = true; + } + assertTrue(exCaught); + } + + public void testCompositeClosure_NPE2() { + boolean exCaught = false; + try { + Closure closure = ClosureTools.compositeClosure((Iterable>) null); + fail("bogus: " + closure); + } catch (NullPointerException ex) { + exCaught = true; + } + assertTrue(exCaught); + } + + public void testCompositeInterruptibleClosure_execute1() throws Exception { + LocalInterruptibleClosure closure1 = new LocalInterruptibleClosure(); + LocalInterruptibleClosure closure2 = new LocalInterruptibleClosure(); + InterruptibleClosure closure = ClosureTools.compositeInterruptibleClosure(closure1, closure2); + closure.execute(Integer.valueOf(3)); + assertEquals(3, closure1.count); + assertEquals(3, closure2.count); + @SuppressWarnings("unchecked") + InterruptibleClosure[] closureArray = new InterruptibleClosure[0]; + closure = ClosureTools.compositeInterruptibleClosure(closureArray); + closure.execute(Integer.valueOf(3)); + } + + public void testCompositeInterruptibleClosure_execute2() throws Exception { + LocalInterruptibleClosure closure1 = new LocalInterruptibleClosure(); + LocalInterruptibleClosure closure2 = new LocalInterruptibleClosure(); + ArrayList list = new ArrayList<>(); + list.add(closure1); + list.add(closure2); + InterruptibleClosure closure = ClosureTools.compositeInterruptibleClosure(list); + closure.execute(Integer.valueOf(3)); + assertEquals(3, closure1.count); + assertEquals(3, closure2.count); + list.clear(); + closure = ClosureTools.compositeInterruptibleClosure(list); + closure.execute(Integer.valueOf(3)); + } + + public void testCompositeInterruptibleClosure_toString() { + LocalInterruptibleClosure closure1 = new LocalInterruptibleClosure(); + LocalInterruptibleClosure closure2 = new LocalInterruptibleClosure(); + InterruptibleClosure closure = ClosureTools.compositeInterruptibleClosure(closure1, closure2); + assertTrue(closure.toString().indexOf("CompositeInterruptibleClosure") != -1); + assertTrue(closure.toString().indexOf("LocalInterruptibleClosure") != -1); + } + + public void testCompositeInterruptibleClosure_NPE1() { + LocalInterruptibleClosure closure1 = new LocalInterruptibleClosure(); + boolean exCaught = false; + try { + InterruptibleClosure closure = ClosureTools.compositeInterruptibleClosure(closure1, null); + fail("bogus: " + closure); + } catch (NullPointerException ex) { + exCaught = true; + } + assertTrue(exCaught); + } + + public void testCompositeInterruptibleClosure_NPE2() { + boolean exCaught = false; + try { + InterruptibleClosure closure = ClosureTools.compositeInterruptibleClosure((Iterable>) null); + fail("bogus: " + closure); + } catch (NullPointerException ex) { + exCaught = true; + } + assertTrue(exCaught); + } + + public void testConditionalClosure_execute1() throws Exception { + LocalClosure closure1 = new LocalClosure(); + Predicate predicate = new PredicateAdapter() { + @Override + public boolean evaluate(Integer variable) { + return variable.intValue() > 3; + } + }; + Closure closure = ClosureTools.conditionalClosure(predicate, closure1); + closure.execute(Integer.valueOf(3)); + assertEquals(0, closure1.count); + closure.execute(Integer.valueOf(4)); + assertEquals(4, closure1.count); + } + + public void testConditionalClosure_execute2() throws Exception { + LocalClosure closure1 = new LocalClosure(); + LocalClosure closure2 = new LocalClosure(); + Predicate predicate = new PredicateAdapter() { + @Override + public boolean evaluate(Integer variable) { + return variable.intValue() > 3; + } + }; + Closure closure = ClosureTools.conditionalClosure(predicate, closure1, closure2); + closure.execute(Integer.valueOf(3)); + assertEquals(0, closure1.count); + assertEquals(3, closure2.count); + closure.execute(Integer.valueOf(4)); + assertEquals(4, closure1.count); + assertEquals(3, closure2.count); + } + + public void testConditionalClosure_toString() { + LocalClosure closure1 = new LocalClosure(); + LocalClosure closure2 = new LocalClosure(); + Predicate predicate = new PredicateAdapter() { + @Override + public boolean evaluate(Integer variable) { + return variable.intValue() > 3; + } + }; + Closure closure = ClosureTools.conditionalClosure(predicate, closure1, closure2); + assertTrue(closure.toString().indexOf("ConditionalClosure") != -1); + assertTrue(closure.toString().indexOf("Predicate") != -1); + } + + public void testConditionalClosure_NPE1() { + LocalClosure closure1 = new LocalClosure(); + LocalClosure closure2 = new LocalClosure(); + boolean exCaught = false; + try { + Closure closure = ClosureTools.conditionalClosure(null, closure1, closure2); + fail("bogus: " + closure); + } catch (NullPointerException ex) { + exCaught = true; + } + assertTrue(exCaught); + } + + public void testConditionalClosure_NPE2() { + LocalClosure closure1 = new LocalClosure(); + boolean exCaught = false; + try { + Closure closure = ClosureTools.conditionalClosure(null, closure1, null); + fail("bogus: " + closure); + } catch (NullPointerException ex) { + exCaught = true; + } + assertTrue(exCaught); + } + + public void testConditionalClosure_NPE3() { + LocalClosure closure2 = new LocalClosure(); + boolean exCaught = false; + try { + Closure closure = ClosureTools.conditionalClosure(PredicateTools.true_(), null, closure2); + fail("bogus: " + closure); + } catch (NullPointerException ex) { + exCaught = true; + } + assertTrue(exCaught); + } + + public void testConditionalInterruptibleClosure_execute1() throws Exception { + LocalInterruptibleClosure closure1 = new LocalInterruptibleClosure(); + Predicate predicate = new PredicateAdapter() { + @Override + public boolean evaluate(Integer variable) { + return variable.intValue() > 3; + } + }; + InterruptibleClosure closure = ClosureTools.conditionalClosure(predicate, closure1); + closure.execute(Integer.valueOf(3)); + assertEquals(0, closure1.count); + closure.execute(Integer.valueOf(4)); + assertEquals(4, closure1.count); + } + + public void testConditionalInterruptibleClosure_execute2() throws Exception { + LocalInterruptibleClosure closure1 = new LocalInterruptibleClosure(); + LocalInterruptibleClosure closure2 = new LocalInterruptibleClosure(); + Predicate predicate = new PredicateAdapter() { + @Override + public boolean evaluate(Integer variable) { + return variable.intValue() > 3; + } + }; + InterruptibleClosure closure = ClosureTools.conditionalClosure(predicate, closure1, closure2); + closure.execute(Integer.valueOf(3)); + assertEquals(0, closure1.count); + assertEquals(3, closure2.count); + closure.execute(Integer.valueOf(4)); + assertEquals(4, closure1.count); + assertEquals(3, closure2.count); + } + + public void testConditionalInterruptibleClosure_toString() { + LocalInterruptibleClosure closure1 = new LocalInterruptibleClosure(); + LocalInterruptibleClosure closure2 = new LocalInterruptibleClosure(); + Predicate predicate = new PredicateAdapter() { + @Override + public boolean evaluate(Integer variable) { + return variable.intValue() > 3; + } + }; + InterruptibleClosure closure = ClosureTools.conditionalClosure(predicate, closure1, closure2); + assertTrue(closure.toString().indexOf("ConditionalInterruptibleClosure") != -1); + assertTrue(closure.toString().indexOf("Predicate") != -1); + } + + public void testConditionalInterruptibleClosure_NPE1() { + LocalInterruptibleClosure closure1 = new LocalInterruptibleClosure(); + LocalInterruptibleClosure closure2 = new LocalInterruptibleClosure(); + boolean exCaught = false; + try { + InterruptibleClosure closure = ClosureTools.conditionalClosure(null, closure1, closure2); + fail("bogus: " + closure); + } catch (NullPointerException ex) { + exCaught = true; + } + assertTrue(exCaught); + } + + public void testConditionalInterruptibleClosure_NPE2() { + LocalInterruptibleClosure closure1 = new LocalInterruptibleClosure(); + boolean exCaught = false; + try { + InterruptibleClosure closure = ClosureTools.conditionalClosure(null, closure1, null); + fail("bogus: " + closure); + } catch (NullPointerException ex) { + exCaught = true; + } + assertTrue(exCaught); + } + + public void testConditionalInterruptibleClosure_NPE3() { + LocalInterruptibleClosure closure2 = new LocalInterruptibleClosure(); + boolean exCaught = false; + try { + InterruptibleClosure closure = ClosureTools.conditionalClosure(PredicateTools.true_(), null, closure2); + fail("bogus: " + closure); + } catch (NullPointerException ex) { + exCaught = true; + } + assertTrue(exCaught); + } + + public void testSwitchClosure_execute1() throws Exception { + List, LocalClosure>> list = new ArrayList<>(); + + Predicate predicate1 = PredicateTools.isEqual(Integer.valueOf(1)); + LocalClosure closure1 = new LocalClosure(); + Association, LocalClosure> association1 = new SimpleAssociation<>(predicate1, closure1); + list.add(association1); + + Predicate predicate2 = PredicateTools.isEqual(Integer.valueOf(2)); + LocalClosure closure2 = new LocalClosure(); + Association, LocalClosure> association2 = new SimpleAssociation<>(predicate2, closure2); + list.add(association2); + + Predicate predicate3 = PredicateTools.isEqual(Integer.valueOf(3)); + LocalClosure closure3 = new LocalClosure(); + Association, LocalClosure> association3 = new SimpleAssociation<>(predicate3, closure3); + list.add(association3); + + Closure closure = ClosureTools.switchClosure(list); + assertEquals(0, closure1.count); + assertEquals(0, closure2.count); + assertEquals(0, closure3.count); + + closure.execute(Integer.valueOf(0)); + assertEquals(0, closure1.count); + assertEquals(0, closure2.count); + assertEquals(0, closure3.count); + + closure.execute(Integer.valueOf(4)); + assertEquals(0, closure1.count); + assertEquals(0, closure2.count); + assertEquals(0, closure3.count); + + closure.execute(Integer.valueOf(1)); + assertEquals(1, closure1.count); + assertEquals(0, closure2.count); + assertEquals(0, closure3.count); + + closure.execute(Integer.valueOf(2)); + assertEquals(1, closure1.count); + assertEquals(2, closure2.count); + assertEquals(0, closure3.count); + + closure.execute(Integer.valueOf(2)); + assertEquals(1, closure1.count); + assertEquals(4, closure2.count); + assertEquals(0, closure3.count); + + closure.execute(Integer.valueOf(3)); + assertEquals(1, closure1.count); + assertEquals(4, closure2.count); + assertEquals(3, closure3.count); + } + + public void testSwitchClosure_execute2() throws Exception { + List, LocalClosure>> list = new ArrayList<>(); + + Predicate predicate1 = PredicateTools.isEqual(Integer.valueOf(1)); + LocalClosure closure1 = new LocalClosure(); + Association, LocalClosure> association1 = new SimpleAssociation<>(predicate1, closure1); + list.add(association1); + + Predicate predicate2 = PredicateTools.isEqual(Integer.valueOf(2)); + LocalClosure closure2 = new LocalClosure(); + Association, LocalClosure> association2 = new SimpleAssociation<>(predicate2, closure2); + list.add(association2); + + Predicate predicate3 = PredicateTools.isEqual(Integer.valueOf(3)); + LocalClosure closure3 = new LocalClosure(); + Association, LocalClosure> association3 = new SimpleAssociation<>(predicate3, closure3); + list.add(association3); + + LocalClosure closureX = new LocalClosure(); + + Closure closure = ClosureTools.switchClosure(list, closureX); + assertEquals(0, closure1.count); + assertEquals(0, closure2.count); + assertEquals(0, closure3.count); + assertEquals(0, closureX.count); + + closure.execute(Integer.valueOf(0)); + assertEquals(0, closure1.count); + assertEquals(0, closure2.count); + assertEquals(0, closure3.count); + assertEquals(0, closureX.count); + + closure.execute(Integer.valueOf(4)); + assertEquals(0, closure1.count); + assertEquals(0, closure2.count); + assertEquals(0, closure3.count); + assertEquals(4, closureX.count); + + closure.execute(Integer.valueOf(1)); + assertEquals(1, closure1.count); + assertEquals(0, closure2.count); + assertEquals(0, closure3.count); + assertEquals(4, closureX.count); + + closure.execute(Integer.valueOf(2)); + assertEquals(1, closure1.count); + assertEquals(2, closure2.count); + assertEquals(0, closure3.count); + assertEquals(4, closureX.count); + + closure.execute(Integer.valueOf(2)); + assertEquals(1, closure1.count); + assertEquals(4, closure2.count); + assertEquals(0, closure3.count); + assertEquals(4, closureX.count); + + closure.execute(Integer.valueOf(3)); + assertEquals(1, closure1.count); + assertEquals(4, closure2.count); + assertEquals(3, closure3.count); + assertEquals(4, closureX.count); + + closure.execute(Integer.valueOf(-7)); + assertEquals(1, closure1.count); + assertEquals(4, closure2.count); + assertEquals(3, closure3.count); + assertEquals(-3, closureX.count); + } + + public void testSwitchClosure_toString() { + List, LocalClosure>> list = new ArrayList<>(); + + Predicate predicate1 = PredicateTools.isEqual(Integer.valueOf(1)); + LocalClosure closure1 = new LocalClosure(); + Association, LocalClosure> association1 = new SimpleAssociation<>(predicate1, closure1); + list.add(association1); + + Predicate predicate2 = PredicateTools.isEqual(Integer.valueOf(2)); + LocalClosure closure2 = new LocalClosure(); + Association, LocalClosure> association2 = new SimpleAssociation<>(predicate2, closure2); + list.add(association2); + + Predicate predicate3 = PredicateTools.isEqual(Integer.valueOf(3)); + LocalClosure closure3 = new LocalClosure(); + Association, LocalClosure> association3 = new SimpleAssociation<>(predicate3, closure3); + list.add(association3); + + LocalClosure closureX = new LocalClosure(); + + Closure closure = ClosureTools.switchClosure(list, closureX); + + assertTrue(closure.toString().indexOf("SwitchClosure") != -1); + assertTrue(closure.toString().indexOf("LocalClosure") != -1); + } + + public void testSwitchClosure_NPE1() { + List, LocalClosure>> list = new ArrayList<>(); + + Predicate predicate1 = PredicateTools.isEqual(Integer.valueOf(1)); + LocalClosure closure1 = new LocalClosure(); + Association, LocalClosure> association1 = new SimpleAssociation<>(predicate1, closure1); + list.add(association1); + + Predicate predicate2 = PredicateTools.isEqual(Integer.valueOf(2)); + LocalClosure closure2 = new LocalClosure(); + Association, LocalClosure> association2 = new SimpleAssociation<>(predicate2, closure2); + list.add(association2); + + Predicate predicate3 = PredicateTools.isEqual(Integer.valueOf(3)); + LocalClosure closure3 = new LocalClosure(); + Association, LocalClosure> association3 = new SimpleAssociation<>(predicate3, closure3); + list.add(association3); + + boolean exCaught = false; + try { + Closure closure = ClosureTools.switchClosure(list, null); + fail("bogus: " + closure); + } catch (NullPointerException ex) { + exCaught = true; + } + assertTrue(exCaught); + } + + public void testSwitchClosure_NPE2() { + List, LocalClosure>> list = new ArrayList<>(); + + Predicate predicate1 = PredicateTools.isEqual(Integer.valueOf(1)); + LocalClosure closure1 = new LocalClosure(); + Association, LocalClosure> association1 = new SimpleAssociation<>(predicate1, closure1); + list.add(association1); + + Predicate predicate2 = PredicateTools.isEqual(Integer.valueOf(2)); + LocalClosure closure2 = new LocalClosure(); + Association, LocalClosure> association2 = new SimpleAssociation<>(predicate2, closure2); + list.add(association2); + + Predicate predicate3 = PredicateTools.isEqual(Integer.valueOf(3)); + LocalClosure closure3 = new LocalClosure(); + Association, LocalClosure> association3 = new SimpleAssociation<>(predicate3, closure3); + list.add(association3); + list.add(null); + + boolean exCaught = false; + try { + Closure closure = ClosureTools.switchClosure(list); + fail("bogus: " + closure); + } catch (NullPointerException ex) { + exCaught = true; + } + assertTrue(exCaught); + } + + public void testSwitchClosure_NPE3() { + boolean exCaught = false; + try { + Closure closure = ClosureTools.switchClosure(null); + fail("bogus: " + closure); + } catch (NullPointerException ex) { + exCaught = true; + } + assertTrue(exCaught); + } + + public void testSwitchInterruptibleClosure_execute1() throws Exception { + List, LocalInterruptibleClosure>> list = new ArrayList<>(); + + Predicate predicate1 = PredicateTools.isEqual(Integer.valueOf(1)); + LocalInterruptibleClosure closure1 = new LocalInterruptibleClosure(); + Association, LocalInterruptibleClosure> association1 = new SimpleAssociation<>(predicate1, closure1); + list.add(association1); + + Predicate predicate2 = PredicateTools.isEqual(Integer.valueOf(2)); + LocalInterruptibleClosure closure2 = new LocalInterruptibleClosure(); + Association, LocalInterruptibleClosure> association2 = new SimpleAssociation<>(predicate2, closure2); + list.add(association2); + + Predicate predicate3 = PredicateTools.isEqual(Integer.valueOf(3)); + LocalInterruptibleClosure closure3 = new LocalInterruptibleClosure(); + Association, LocalInterruptibleClosure> association3 = new SimpleAssociation<>(predicate3, closure3); + list.add(association3); + + InterruptibleClosure closure = ClosureTools.switchInterruptibleClosure(list); + assertEquals(0, closure1.count); + assertEquals(0, closure2.count); + assertEquals(0, closure3.count); + + closure.execute(Integer.valueOf(0)); + assertEquals(0, closure1.count); + assertEquals(0, closure2.count); + assertEquals(0, closure3.count); + + closure.execute(Integer.valueOf(4)); + assertEquals(0, closure1.count); + assertEquals(0, closure2.count); + assertEquals(0, closure3.count); + + closure.execute(Integer.valueOf(1)); + assertEquals(1, closure1.count); + assertEquals(0, closure2.count); + assertEquals(0, closure3.count); + + closure.execute(Integer.valueOf(2)); + assertEquals(1, closure1.count); + assertEquals(2, closure2.count); + assertEquals(0, closure3.count); + + closure.execute(Integer.valueOf(2)); + assertEquals(1, closure1.count); + assertEquals(4, closure2.count); + assertEquals(0, closure3.count); + + closure.execute(Integer.valueOf(3)); + assertEquals(1, closure1.count); + assertEquals(4, closure2.count); + assertEquals(3, closure3.count); + } + + public void testSwitchInterruptibleClosure_execute2() throws Exception { + List, LocalInterruptibleClosure>> list = new ArrayList<>(); + + Predicate predicate1 = PredicateTools.isEqual(Integer.valueOf(1)); + LocalInterruptibleClosure closure1 = new LocalInterruptibleClosure(); + Association, LocalInterruptibleClosure> association1 = new SimpleAssociation<>(predicate1, closure1); + list.add(association1); + + Predicate predicate2 = PredicateTools.isEqual(Integer.valueOf(2)); + LocalInterruptibleClosure closure2 = new LocalInterruptibleClosure(); + Association, LocalInterruptibleClosure> association2 = new SimpleAssociation<>(predicate2, closure2); + list.add(association2); + + Predicate predicate3 = PredicateTools.isEqual(Integer.valueOf(3)); + LocalInterruptibleClosure closure3 = new LocalInterruptibleClosure(); + Association, LocalInterruptibleClosure> association3 = new SimpleAssociation<>(predicate3, closure3); + list.add(association3); + + LocalInterruptibleClosure closureX = new LocalInterruptibleClosure(); + + InterruptibleClosure closure = ClosureTools.switchInterruptibleClosure(list, closureX); + assertEquals(0, closure1.count); + assertEquals(0, closure2.count); + assertEquals(0, closure3.count); + assertEquals(0, closureX.count); + + closure.execute(Integer.valueOf(0)); + assertEquals(0, closure1.count); + assertEquals(0, closure2.count); + assertEquals(0, closure3.count); + assertEquals(0, closureX.count); + + closure.execute(Integer.valueOf(4)); + assertEquals(0, closure1.count); + assertEquals(0, closure2.count); + assertEquals(0, closure3.count); + assertEquals(4, closureX.count); + + closure.execute(Integer.valueOf(1)); + assertEquals(1, closure1.count); + assertEquals(0, closure2.count); + assertEquals(0, closure3.count); + assertEquals(4, closureX.count); + + closure.execute(Integer.valueOf(2)); + assertEquals(1, closure1.count); + assertEquals(2, closure2.count); + assertEquals(0, closure3.count); + assertEquals(4, closureX.count); + + closure.execute(Integer.valueOf(2)); + assertEquals(1, closure1.count); + assertEquals(4, closure2.count); + assertEquals(0, closure3.count); + assertEquals(4, closureX.count); + + closure.execute(Integer.valueOf(3)); + assertEquals(1, closure1.count); + assertEquals(4, closure2.count); + assertEquals(3, closure3.count); + assertEquals(4, closureX.count); + + closure.execute(Integer.valueOf(-7)); + assertEquals(1, closure1.count); + assertEquals(4, closure2.count); + assertEquals(3, closure3.count); + assertEquals(-3, closureX.count); + } + + public void testSwitchInterruptibleClosure_toString() { + List, LocalInterruptibleClosure>> list = new ArrayList<>(); + + Predicate predicate1 = PredicateTools.isEqual(Integer.valueOf(1)); + LocalInterruptibleClosure closure1 = new LocalInterruptibleClosure(); + Association, LocalInterruptibleClosure> association1 = new SimpleAssociation<>(predicate1, closure1); + list.add(association1); + + Predicate predicate2 = PredicateTools.isEqual(Integer.valueOf(2)); + LocalInterruptibleClosure closure2 = new LocalInterruptibleClosure(); + Association, LocalInterruptibleClosure> association2 = new SimpleAssociation<>(predicate2, closure2); + list.add(association2); + + Predicate predicate3 = PredicateTools.isEqual(Integer.valueOf(3)); + LocalInterruptibleClosure closure3 = new LocalInterruptibleClosure(); + Association, LocalInterruptibleClosure> association3 = new SimpleAssociation<>(predicate3, closure3); + list.add(association3); + + LocalInterruptibleClosure closureX = new LocalInterruptibleClosure(); + + InterruptibleClosure closure = ClosureTools.switchInterruptibleClosure(list, closureX); + + assertTrue(closure.toString().indexOf("SwitchInterruptibleClosure") != -1); + assertTrue(closure.toString().indexOf("LocalInterruptibleClosure") != -1); + } + + public void testSwitchInterruptibleClosure_NPE1() { + List, LocalInterruptibleClosure>> list = new ArrayList<>(); + + Predicate predicate1 = PredicateTools.isEqual(Integer.valueOf(1)); + LocalInterruptibleClosure closure1 = new LocalInterruptibleClosure(); + Association, LocalInterruptibleClosure> association1 = new SimpleAssociation<>(predicate1, closure1); + list.add(association1); + + Predicate predicate2 = PredicateTools.isEqual(Integer.valueOf(2)); + LocalInterruptibleClosure closure2 = new LocalInterruptibleClosure(); + Association, LocalInterruptibleClosure> association2 = new SimpleAssociation<>(predicate2, closure2); + list.add(association2); + + Predicate predicate3 = PredicateTools.isEqual(Integer.valueOf(3)); + LocalInterruptibleClosure closure3 = new LocalInterruptibleClosure(); + Association, LocalInterruptibleClosure> association3 = new SimpleAssociation<>(predicate3, closure3); + list.add(association3); + + boolean exCaught = false; + try { + InterruptibleClosure closure = ClosureTools.switchInterruptibleClosure(list, null); + fail("bogus: " + closure); + } catch (NullPointerException ex) { + exCaught = true; + } + assertTrue(exCaught); + } + + public void testSwitchInterruptibleClosure_NPE2() { + List, LocalInterruptibleClosure>> list = new ArrayList<>(); + + Predicate predicate1 = PredicateTools.isEqual(Integer.valueOf(1)); + LocalInterruptibleClosure closure1 = new LocalInterruptibleClosure(); + Association, LocalInterruptibleClosure> association1 = new SimpleAssociation<>(predicate1, closure1); + list.add(association1); + + Predicate predicate2 = PredicateTools.isEqual(Integer.valueOf(2)); + LocalInterruptibleClosure closure2 = new LocalInterruptibleClosure(); + Association, LocalInterruptibleClosure> association2 = new SimpleAssociation<>(predicate2, closure2); + list.add(association2); + + Predicate predicate3 = PredicateTools.isEqual(Integer.valueOf(3)); + LocalInterruptibleClosure closure3 = new LocalInterruptibleClosure(); + Association, LocalInterruptibleClosure> association3 = new SimpleAssociation<>(predicate3, closure3); + list.add(association3); + list.add(null); + + boolean exCaught = false; + try { + InterruptibleClosure closure = ClosureTools.switchInterruptibleClosure(list); + fail("bogus: " + closure); + } catch (NullPointerException ex) { + exCaught = true; + } + assertTrue(exCaught); + } + + public void testSwitchInterruptibleClosure_NPE3() { + boolean exCaught = false; + try { + InterruptibleClosure closure = ClosureTools.switchInterruptibleClosure(null); + fail("bogus: " + closure); + } catch (NullPointerException ex) { + exCaught = true; + } + assertTrue(exCaught); + } + + public void testDisabledClosure_execute() { + Closure closure = ClosureTools.disabledClosure(); + boolean exCaught = false; + try { + closure.execute(null); + fail(); + } catch (UnsupportedOperationException ex) { + exCaught = true; + } + assertTrue(exCaught); + } + + public void testDisabledClosure_toString() { + Closure closure = ClosureTools.disabledClosure(); + assertTrue(closure.toString().indexOf("DisabledClosure") != -1); + } + + public void testDisabledClosure_serialization() throws Exception { + Closure closure = ClosureTools.disabledClosure(); + assertSame(closure, TestTools.serialize(closure)); + } + + public void testInterruptedClosure_execute() throws Exception { + InterruptibleClosure closure = ClosureTools.interruptedClosure(); + boolean exCaught = false; + try { + closure.execute(null); + fail(); + } catch (InterruptedException ex) { + exCaught = true; + } + assertTrue(exCaught); + } + + public void testInterruptedClosure_toString() { + InterruptibleClosure closure = ClosureTools.interruptedClosure(); + assertTrue(closure.toString().indexOf("InterruptedClosure") != -1); + } + + public void testInterruptedClosure_serialization() throws Exception { + InterruptibleClosure closure = ClosureTools.interruptedClosure(); + assertSame(closure, TestTools.serialize(closure)); + } + + public void testRepeatingClosure_execute1() throws Exception { + LocalClosure closure1 = new LocalClosure(); + Closure closure2 = ClosureTools.repeatingClosure(closure1, 3); + closure2.execute(Integer.valueOf(3)); + assertEquals(9, closure1.count); + } + + public void testRepeatingClosure_execute2() throws Exception { + LocalClosure closure1 = new LocalClosure(); + Closure closure2 = ClosureTools.repeatingClosure(closure1, 0); + closure2.execute(Integer.valueOf(3)); + assertEquals(0, closure1.count); + } + + public void testRepeatingClosure_toString() { + LocalClosure closure1 = new LocalClosure(); + Closure closure2 = ClosureTools.repeatingClosure(closure1, 3); + assertTrue(closure2.toString().indexOf("RepeatingClosure") != -1); + assertTrue(closure2.toString().indexOf("LocalClosure") != -1); + } + + public void testRepeatingClosure_NPE1() { + boolean exCaught = false; + try { + Closure closure = ClosureTools.repeatingClosure((Closure) null, 3); + fail("bogus: " + closure); + } catch (NullPointerException ex) { + exCaught = true; + } + assertTrue(exCaught); + } + + public void testRepeatingClosure_NPE2() { + LocalClosure closure1 = new LocalClosure(); + boolean exCaught = false; + try { + Closure closure2 = ClosureTools.repeatingClosure(closure1, -3); + fail("bogus: " + closure2); + } catch (IndexOutOfBoundsException ex) { + exCaught = true; + } + assertTrue(exCaught); + } + + public void testRepeatingInterruptibleClosure_execute1() throws Exception { + LocalInterruptibleClosure closure1 = new LocalInterruptibleClosure(); + InterruptibleClosure closure2 = ClosureTools.repeatingClosure(closure1, 3); + closure2.execute(Integer.valueOf(3)); + assertEquals(9, closure1.count); + } + + public void testRepeatingInterruptibleClosure_execute2() throws Exception { + LocalInterruptibleClosure closure1 = new LocalInterruptibleClosure(); + InterruptibleClosure closure2 = ClosureTools.repeatingClosure(closure1, 0); + closure2.execute(Integer.valueOf(3)); + assertEquals(0, closure1.count); + } + + public void testRepeatingInterruptibleClosure_toString() { + LocalInterruptibleClosure closure1 = new LocalInterruptibleClosure(); + InterruptibleClosure closure2 = ClosureTools.repeatingClosure(closure1, 3); + assertTrue(closure2.toString().indexOf("RepeatingInterruptibleClosure") != -1); + assertTrue(closure2.toString().indexOf("LocalInterruptibleClosure") != -1); + } + + public void testRepeatingInterruptibleClosure_NPE1() { + boolean exCaught = false; + try { + InterruptibleClosure closure = ClosureTools.repeatingClosure((InterruptibleClosure) null, 3); + fail("bogus: " + closure); + } catch (NullPointerException ex) { + exCaught = true; + } + assertTrue(exCaught); + } + + public void testRepeatingInterruptibleClosure_NPE2() { + LocalInterruptibleClosure closure1 = new LocalInterruptibleClosure(); + boolean exCaught = false; + try { + InterruptibleClosure closure2 = ClosureTools.repeatingClosure(closure1, -3); + fail("bogus: " + closure2); + } catch (IndexOutOfBoundsException ex) { + exCaught = true; + } + assertTrue(exCaught); + } + + public void testWhileClosure_execute() throws Exception { + ModifiableIntReference ref = new SimpleIntReference(0); + IntRefClosure closure1 = new IntRefClosure(); + Predicate predicate = new IntRefValueNotEqualPredicate(3); + Closure closure2 = ClosureTools.whileClosure(predicate, closure1); + closure2.execute(ref); + assertEquals(6, closure1.count); + ref.setValue(-6); + closure2.execute(ref); + assertEquals(24, closure1.count); + } + + public void testWhileClosure_toString() { + IntRefClosure closure1 = new IntRefClosure(); + Predicate predicate = new IntRefValueNotEqualPredicate(3); + Closure closure2 = ClosureTools.whileClosure(predicate, closure1); + assertTrue(closure2.toString().indexOf("WhileClosure") != -1); + assertTrue(closure2.toString().indexOf("IntRefValueNotEqualPredicate") != -1); + } + + public void testWhileClosure_NPE1() { + IntRefClosure closure1 = new IntRefClosure(); + boolean exCaught = false; + try { + Closure closure2 = ClosureTools.whileClosure(null, closure1); + fail("bogus: " + closure2); + } catch (NullPointerException ex) { + exCaught = true; + } + assertTrue(exCaught); + } + + public void testWhileClosure_NPE2() { + Predicate predicate = new IntRefValueNotEqualPredicate(3); + boolean exCaught = false; + try { + Closure closure2 = ClosureTools.whileClosure(predicate, (IntRefClosure) null); + fail("bogus: " + closure2); + } catch (NullPointerException ex) { + exCaught = true; + } + assertTrue(exCaught); + } + + public static class IntRefClosure + extends ClosureAdapter + { + public int count = 0; + @Override + public void execute(ModifiableIntReference argument) { + this.count += 2; + argument.increment(); + } + } + + public void testWhileInterruptibleClosure_execute() throws Exception { + ModifiableIntReference ref = new SimpleIntReference(0); + IntRefInterruptibleClosure closure1 = new IntRefInterruptibleClosure(); + Predicate predicate = new IntRefValueNotEqualPredicate(3); + InterruptibleClosure closure2 = ClosureTools.whileClosure(predicate, closure1); + closure2.execute(ref); + assertEquals(6, closure1.count); + ref.setValue(-6); + closure2.execute(ref); + assertEquals(24, closure1.count); + } + + public void testWhileInterruptibleClosure_toString() { + IntRefInterruptibleClosure closure1 = new IntRefInterruptibleClosure(); + Predicate predicate = new IntRefValueNotEqualPredicate(3); + InterruptibleClosure closure2 = ClosureTools.whileClosure(predicate, closure1); + assertTrue(closure2.toString().indexOf("WhileInterruptibleClosure") != -1); + assertTrue(closure2.toString().indexOf("IntRefValueNotEqualPredicate") != -1); + } + + public void testWhileInterruptibleClosure_NPE1() { + IntRefInterruptibleClosure closure1 = new IntRefInterruptibleClosure(); + boolean exCaught = false; + try { + InterruptibleClosure closure2 = ClosureTools.whileClosure(null, closure1); + fail("bogus: " + closure2); + } catch (NullPointerException ex) { + exCaught = true; + } + assertTrue(exCaught); + } + + public void testWhileInterruptibleClosure_NPE2() { + Predicate predicate = new IntRefValueNotEqualPredicate(3); + boolean exCaught = false; + try { + InterruptibleClosure closure2 = ClosureTools.whileClosure(predicate, (IntRefInterruptibleClosure) null); + fail("bogus: " + closure2); + } catch (NullPointerException ex) { + exCaught = true; + } + assertTrue(exCaught); + } + + public static class IntRefInterruptibleClosure + extends InterruptibleClosureAdapter + { + public int count = 0; + @Override + public void execute(ModifiableIntReference argument) throws InterruptedException { + this.count += 2; + argument.increment(); + } + } + + public static class IntRefValueNotEqualPredicate + extends PredicateAdapter + { + private final int count; + public IntRefValueNotEqualPredicate(int count) { + super(); + this.count = count; + } + @Override + public boolean evaluate(ModifiableIntReference variable) { + return variable.notEqual(this.count); + } + } + + public void testUntilClosure_execute() throws Exception { + ModifiableIntReference ref = new SimpleIntReference(0); + IntRefClosure closure1 = new IntRefClosure(); + Predicate predicate = new IntRefValueEqualPredicate(3); + Closure closure2 = ClosureTools.untilClosure(closure1, predicate); + closure2.execute(ref); + assertEquals(6, closure1.count); + ref.setValue(-6); + closure2.execute(ref); + assertEquals(24, closure1.count); + } + + public void testUntilClosure_toString() { + IntRefClosure closure1 = new IntRefClosure(); + Predicate predicate = new IntRefValueEqualPredicate(3); + Closure closure2 = ClosureTools.untilClosure(closure1, predicate); + assertTrue(closure2.toString().indexOf("UntilClosure") != -1); + assertTrue(closure2.toString().indexOf("IntRefValueEqualPredicate") != -1); + } + + public void testUntilClosure_NPE1() { + IntRefClosure closure1 = new IntRefClosure(); + boolean exCaught = false; + try { + Closure closure2 = ClosureTools.untilClosure(closure1, null); + fail("bogus: " + closure2); + } catch (NullPointerException ex) { + exCaught = true; + } + assertTrue(exCaught); + } + + public void testUntilClosure_NPE2() { + Predicate predicate = new IntRefValueEqualPredicate(3); + boolean exCaught = false; + try { + Closure closure2 = ClosureTools.untilClosure((IntRefClosure) null, predicate); + fail("bogus: " + closure2); + } catch (NullPointerException ex) { + exCaught = true; + } + assertTrue(exCaught); + } + + public void testUntilInterruptibleClosure_execute() throws Exception { + ModifiableIntReference ref = new SimpleIntReference(0); + IntRefInterruptibleClosure closure1 = new IntRefInterruptibleClosure(); + Predicate predicate = new IntRefValueEqualPredicate(3); + InterruptibleClosure closure2 = ClosureTools.untilClosure(closure1, predicate); + closure2.execute(ref); + assertEquals(6, closure1.count); + ref.setValue(-6); + closure2.execute(ref); + assertEquals(24, closure1.count); + } + + public void testUntilInterruptibleClosure_toString() { + IntRefInterruptibleClosure closure1 = new IntRefInterruptibleClosure(); + Predicate predicate = new IntRefValueEqualPredicate(3); + InterruptibleClosure closure2 = ClosureTools.untilClosure(closure1, predicate); + assertTrue(closure2.toString().indexOf("UntilInterruptibleClosure") != -1); + assertTrue(closure2.toString().indexOf("IntRefValueEqualPredicate") != -1); + } + + public void testUntilInterruptibleClosure_NPE1() { + IntRefInterruptibleClosure closure1 = new IntRefInterruptibleClosure(); + boolean exCaught = false; + try { + InterruptibleClosure closure2 = ClosureTools.untilClosure(closure1, null); + fail("bogus: " + closure2); + } catch (NullPointerException ex) { + exCaught = true; + } + assertTrue(exCaught); + } + + public void testUntilInterruptibleClosure_NPE2() { + Predicate predicate = new IntRefValueEqualPredicate(3); + boolean exCaught = false; + try { + InterruptibleClosure closure2 = ClosureTools.untilClosure((IntRefInterruptibleClosure) null, predicate); + fail("bogus: " + closure2); + } catch (NullPointerException ex) { + exCaught = true; + } + assertTrue(exCaught); + } + + public static class IntRefValueEqualPredicate + extends PredicateAdapter + { + private final int count; + public IntRefValueEqualPredicate(int count) { + super(); + this.count = count; + } + @Override + public boolean evaluate(ModifiableIntReference variable) { + return variable.equals(this.count); + } + } + + public void testConstructor() { + boolean exCaught = false; + try { + Object at = ClassTools.newInstance(ClosureTools.class); + fail("bogus: " + at); + } catch (RuntimeException ex) { + if (ex.getCause() instanceof InvocationTargetException) { + if (ex.getCause().getCause() instanceof UnsupportedOperationException) { + exCaught = true; + } + } + } + assertTrue(exCaught); + } + + // ********** test classes ********** + + public static class LocalClosure + extends ClosureAdapter + { + public int count = 0; + + @Override + public void execute(Integer argument) { + this.count += argument.intValue(); // possible NPE + } + } + + public static class LocalClosure2 + extends ClosureAdapter + { + public int count = 0; + + @Override + public void execute(Integer argument) { + this.count += (2 * argument.intValue()); // possible NPE + } + } + + public static class LocalInterruptibleClosure + extends InterruptibleClosureAdapter + { + public int count = 0; + + @Override + public void execute(Integer argument) throws InterruptedException { + this.count += argument.intValue(); // possible NPE + } + } + + public static class LocalCommand + extends CommandAdapter + { + public int count = 0; + + @Override + public void execute() { + this.count++; + } + } + + public static class LocalInterruptibleCommand + extends InterruptibleCommandAdapter + { + public int count = 0; + + @Override + public void execute() { + this.count++; + } + } + + public static class LocalFactory + extends FactoryAdapter + { + public int count = 0; + + @Override + public T create() { + this.count++; + return null; + } + } + + public static class LocalInterruptibleFactory + extends InterruptibleFactoryAdapter + { + public int count = 0; + + @Override + public T create() throws InterruptedException { + this.count++; + return null; + } + } + + public static class LocalTransformer + extends TransformerAdapter + { + public int count = 0; + + @Override + public O transform(I input) { + this.count++; + return null; + } + } + + public static class LocalInterruptibleTransformer + extends InterruptibleTransformerAdapter + { + public int count = 0; + + @Override + public O transform(I input) throws InterruptedException { + this.count++; + return null; + } + } +} diff --git a/common/tests/org.eclipse.jpt.common.utility.tests/src/org/eclipse/jpt/common/utility/tests/internal/closure/JptCommonUtilityClosureTests.java b/common/tests/org.eclipse.jpt.common.utility.tests/src/org/eclipse/jpt/common/utility/tests/internal/closure/JptCommonUtilityClosureTests.java index 40f8b348ec..cf0c333f35 100644 --- a/common/tests/org.eclipse.jpt.common.utility.tests/src/org/eclipse/jpt/common/utility/tests/internal/closure/JptCommonUtilityClosureTests.java +++ b/common/tests/org.eclipse.jpt.common.utility.tests/src/org/eclipse/jpt/common/utility/tests/internal/closure/JptCommonUtilityClosureTests.java @@ -20,7 +20,9 @@ public class JptCommonUtilityClosureTests { public static Test suite() { TestSuite suite = new TestSuite(JptCommonUtilityClosureTests.class.getPackage().getName()); + suite.addTestSuite(BiClosureToolsTests.class); suite.addTestSuite(BooleanClosureTests.class); + suite.addTestSuite(ClosureToolsTests.class); suite.addTestSuite(NullableBooleanClosureTests.class); return suite; -- cgit v1.2.3