1.1 --- a/samples/openfixed/nbproject/project.properties Sun Mar 20 08:12:26 2011 +0100
1.2 +++ b/samples/openfixed/nbproject/project.properties Sun Mar 20 18:52:47 2011 +0100
1.3 @@ -25,6 +25,7 @@
1.4 dist.jar=${dist.dir}/openfixed.jar
1.5 dist.javadoc.dir=${dist.dir}/javadoc
1.6 excludes=
1.7 +file.reference.junit-4.4.jar=../libs/dist/junit-4.4.jar
1.8 includes=**
1.9 jar.compress=false
1.10 javac.classpath=
1.11 @@ -37,7 +38,8 @@
1.12 javac.target=1.6
1.13 javac.test.classpath=\
1.14 ${javac.classpath}:\
1.15 - ${build.classes.dir}
1.16 + ${build.classes.dir}:\
1.17 + ${file.reference.junit-4.4.jar}
1.18 javac.test.processorpath=\
1.19 ${javac.test.classpath}
1.20 javadoc.additionalparam=
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2.2 +++ b/samples/openfixed/src/org/apidesign/openfixed/AsyncEventSupport.java Sun Mar 20 18:52:47 2011 +0100
2.3 @@ -0,0 +1,50 @@
2.4 +package org.apidesign.openfixed;
2.5 +
2.6 +import java.util.List;
2.7 +import java.util.concurrent.CopyOnWriteArrayList;
2.8 +import java.util.concurrent.Executor;
2.9 +import java.util.concurrent.Executors;
2.10 +
2.11 +/**
2.12 + *
2.13 + * @author Jaroslav Tulach <jtulach@netbeans.org>
2.14 + */
2.15 +final class AsyncEventSupport implements EventSupport {
2.16 + private final List<ModificationListener> listeners = new CopyOnWriteArrayList<ModificationListener>();
2.17 + private static final Executor EXEC = Executors.newSingleThreadExecutor();
2.18 +
2.19 + AsyncEventSupport() {
2.20 + }
2.21 +
2.22 + @Override
2.23 + public void fireModificationEvent(ModificationEvent ev) {
2.24 + EXEC.execute(new Deliverable(ev, listeners.toArray(new ModificationListener[0])));
2.25 + }
2.26 +
2.27 + @Override
2.28 + public void add(ModificationListener l) {
2.29 + listeners.add(l);
2.30 + }
2.31 +
2.32 + @Override
2.33 + public void remove(ModificationListener l) {
2.34 + listeners.remove(l);
2.35 + }
2.36 +
2.37 + private static class Deliverable implements Runnable {
2.38 + final ModificationEvent ev;
2.39 + final ModificationListener[] listeners;
2.40 +
2.41 + public Deliverable(ModificationEvent ev, ModificationListener[] listeners) {
2.42 + this.ev = ev;
2.43 + this.listeners = listeners;
2.44 + }
2.45 +
2.46 + @Override
2.47 + public void run() {
2.48 + for (ModificationListener l : listeners) {
2.49 + l.modification(ev);
2.50 + }
2.51 + }
2.52 + }
2.53 +}
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3.2 +++ b/samples/openfixed/src/org/apidesign/openfixed/Calculator.java Sun Mar 20 18:52:47 2011 +0100
3.3 @@ -0,0 +1,49 @@
3.4 +package org.apidesign.openfixed;
3.5 +
3.6 +/** Sample bean using the {@link ModificationListener}
3.7 + * to <b>add</b> numbers.
3.8 + *
3.9 + * @author Jaroslav Tulach <jtulach@netbeans.org>
3.10 + */
3.11 +public final class Calculator {
3.12 + private final EventSupport listeners;
3.13 + private int sum;
3.14 +
3.15 + private Calculator(EventSupport listeners) {
3.16 + this.listeners = listeners;
3.17 + }
3.18 +
3.19 + public static Calculator create() {
3.20 + return new Calculator(new TrivialEventSupport());
3.21 + }
3.22 +
3.23 + public static Calculator createAsynch() {
3.24 + return new Calculator(new AsyncEventSupport());
3.25 + }
3.26 +
3.27 + /** @since 2.0 */
3.28 + public static Calculator createPending() {
3.29 + return new Calculator(new PendingEventSupport());
3.30 + }
3.31 +
3.32 + /** @since 3.0 */
3.33 + public static Calculator createBatch() {
3.34 + return new Calculator(new PostEventSupport());
3.35 + }
3.36 +
3.37 + public synchronized void add(int add) {
3.38 + sum += add;
3.39 + listeners.fireModificationEvent(new ModificationEvent(this, add));
3.40 + }
3.41 +
3.42 + public synchronized int getSum() {
3.43 + return sum;
3.44 + }
3.45 +
3.46 + public void addModificationListener(ModificationListener l) {
3.47 + listeners.add(l);
3.48 + }
3.49 + public void removeModificationListener(ModificationListener l) {
3.50 + listeners.remove(l);
3.51 + }
3.52 +}
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2 +++ b/samples/openfixed/src/org/apidesign/openfixed/EventSupport.java Sun Mar 20 18:52:47 2011 +0100
4.3 @@ -0,0 +1,19 @@
4.4 +/*
4.5 + * To change this template, choose Tools | Templates
4.6 + * and open the template in the editor.
4.7 + */
4.8 +package org.apidesign.openfixed;
4.9 +
4.10 +/**
4.11 + *
4.12 + * @author Jaroslav Tulach <jtulach@netbeans.org>
4.13 + */
4.14 +interface EventSupport {
4.15 +
4.16 + public void fireModificationEvent(ModificationEvent ev);
4.17 +
4.18 + public void add(ModificationListener l);
4.19 +
4.20 + public void remove(ModificationListener l);
4.21 +
4.22 +}
5.1 --- a/samples/openfixed/src/org/apidesign/openfixed/Growable.java Sun Mar 20 08:12:26 2011 +0100
5.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
5.3 @@ -1,19 +0,0 @@
5.4 -package org.apidesign.openfixed;
5.5 -
5.6 -import java.util.List;
5.7 -import java.util.concurrent.CopyOnWriteArrayList;
5.8 -
5.9 -/** Sample bean using the {@link GrowingListener}.
5.10 - *
5.11 - * @author Jaroslav Tulach <jtulach@netbeans.org>
5.12 - */
5.13 -public final class Growable {
5.14 - private List<GrowingListener> listeners = new CopyOnWriteArrayList<GrowingListener>();
5.15 -
5.16 - public void addGrowingListener(GrowingListener l) {
5.17 - listeners.add(l);
5.18 - }
5.19 - public void removeGrowingListener(GrowingListener l) {
5.20 - listeners.remove(l);
5.21 - }
5.22 -}
6.1 --- a/samples/openfixed/src/org/apidesign/openfixed/GrowingEvent.java Sun Mar 20 08:12:26 2011 +0100
6.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
6.3 @@ -1,25 +0,0 @@
6.4 -package org.apidesign.openfixed;
6.5 -
6.6 -import java.util.EventObject;
6.7 -
6.8 -// BEGIN: openfixed.event
6.9 -public final class GrowingEvent extends EventObject {
6.10 - public GrowingEvent(Object source) {
6.11 - super(source);
6.12 - }
6.13 -// FINISH: openfixed.event
6.14 -
6.15 -// BEGIN: openfixed.addgetter
6.16 - private int index;
6.17 - /** @since 2.0 */
6.18 - public GrowingEvent(Object source, int index) {
6.19 - super(source);
6.20 - this.index = index;
6.21 - }
6.22 -
6.23 - /** @since 2.0 */
6.24 - public int getIndex() {
6.25 - return index;
6.26 - }
6.27 -// END: openfixed.addgetter
6.28 -}
7.1 --- a/samples/openfixed/src/org/apidesign/openfixed/GrowingListener.java Sun Mar 20 08:12:26 2011 +0100
7.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
7.3 @@ -1,9 +0,0 @@
7.4 -package org.apidesign.openfixed;
7.5 -
7.6 -import java.util.EventListener;
7.7 -
7.8 -// BEGIN: openfixed.listener
7.9 -public interface GrowingListener extends EventListener {
7.10 - public void response(GrowingEvent ev);
7.11 -}
7.12 -// FINISH: openfixed.listener
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
8.2 +++ b/samples/openfixed/src/org/apidesign/openfixed/ModificationEvent.java Sun Mar 20 18:52:47 2011 +0100
8.3 @@ -0,0 +1,35 @@
8.4 +package org.apidesign.openfixed;
8.5 +
8.6 +import java.util.Collection;
8.7 +import java.util.EventObject;
8.8 +
8.9 +// BEGIN: openfixed.event
8.10 +public final class ModificationEvent extends EventObject {
8.11 + private final int delta;
8.12 + ModificationEvent(Object source, int delta) {
8.13 + super(source);
8.14 + this.delta = delta;
8.15 + }
8.16 +
8.17 + public int getChange() {
8.18 + return delta;
8.19 + }
8.20 +
8.21 +// FINISH: openfixed.event
8.22 +
8.23 +// BEGIN: openfixed.addgetter
8.24 + int pending;
8.25 + /** @since 2.0 */
8.26 + public int getPending() {
8.27 + return pending;
8.28 + }
8.29 +// END: openfixed.addgetter
8.30 +
8.31 +// BEGIN: openfixed.mount
8.32 + Collection<PostModificationListener> posts;
8.33 + /** @since 3.0 */
8.34 + public void postProcess(PostModificationListener p) {
8.35 + posts.add(p);
8.36 + }
8.37 +// END: openfixed.mount
8.38 +}
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
9.2 +++ b/samples/openfixed/src/org/apidesign/openfixed/ModificationListener.java Sun Mar 20 18:52:47 2011 +0100
9.3 @@ -0,0 +1,9 @@
9.4 +package org.apidesign.openfixed;
9.5 +
9.6 +import java.util.EventListener;
9.7 +
9.8 +// BEGIN: openfixed.listener
9.9 +public interface ModificationListener extends EventListener {
9.10 + public void modification(ModificationEvent ev);
9.11 +}
9.12 +// FINISH: openfixed.listener
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
10.2 +++ b/samples/openfixed/src/org/apidesign/openfixed/PendingEventSupport.java Sun Mar 20 18:52:47 2011 +0100
10.3 @@ -0,0 +1,67 @@
10.4 +package org.apidesign.openfixed;
10.5 +
10.6 +import java.util.List;
10.7 +import java.util.concurrent.CopyOnWriteArrayList;
10.8 +import java.util.concurrent.Executor;
10.9 +import java.util.concurrent.Executors;
10.10 +
10.11 +/**
10.12 + *
10.13 + * @author Jaroslav Tulach <jtulach@netbeans.org>
10.14 + */
10.15 +final class PendingEventSupport implements EventSupport, Runnable {
10.16 + private final List<ModificationListener> listeners = new CopyOnWriteArrayList<ModificationListener>();
10.17 + private final List<Deliverable> deliverables = new CopyOnWriteArrayList<Deliverable>();
10.18 + private static final Executor EXEC = Executors.newSingleThreadExecutor();
10.19 +
10.20 + PendingEventSupport() {
10.21 + }
10.22 +
10.23 + @Override
10.24 + public void fireModificationEvent(ModificationEvent ev) {
10.25 + synchronized (deliverables) {
10.26 + final Deliverable d = new Deliverable(ev, listeners.toArray(new ModificationListener[0]));
10.27 + deliverables.add(d);
10.28 + EXEC.execute(this);
10.29 + }
10.30 + }
10.31 +
10.32 + @Override
10.33 + public void add(ModificationListener l) {
10.34 + listeners.add(l);
10.35 + }
10.36 +
10.37 + @Override
10.38 + public void remove(ModificationListener l) {
10.39 + listeners.remove(l);
10.40 + }
10.41 +
10.42 + @Override
10.43 + public void run() {
10.44 + Deliverable[] pending;
10.45 + synchronized (deliverables) {
10.46 + if (deliverables.isEmpty()) {
10.47 + return;
10.48 + }
10.49 + pending = deliverables.toArray(new Deliverable[0]);
10.50 + deliverables.clear();
10.51 + }
10.52 + int pendingCount = pending.length;
10.53 + for (Deliverable d : pending) {
10.54 + d.ev.pending = --pendingCount;
10.55 + for (ModificationListener l : d.listeners) {
10.56 + l.modification(d.ev);
10.57 + }
10.58 + }
10.59 + }
10.60 +
10.61 + private static class Deliverable {
10.62 + final ModificationEvent ev;
10.63 + final ModificationListener[] listeners;
10.64 +
10.65 + public Deliverable(ModificationEvent ev, ModificationListener[] listeners) {
10.66 + this.ev = ev;
10.67 + this.listeners = listeners;
10.68 + }
10.69 + }
10.70 +}
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
11.2 +++ b/samples/openfixed/src/org/apidesign/openfixed/PostEventSupport.java Sun Mar 20 18:52:47 2011 +0100
11.3 @@ -0,0 +1,78 @@
11.4 +package org.apidesign.openfixed;
11.5 +
11.6 +import java.util.HashSet;
11.7 +import java.util.List;
11.8 +import java.util.Set;
11.9 +import java.util.concurrent.CopyOnWriteArrayList;
11.10 +import java.util.concurrent.Executor;
11.11 +import java.util.concurrent.Executors;
11.12 +
11.13 +/**
11.14 + *
11.15 + * @author Jaroslav Tulach <jtulach@netbeans.org>
11.16 + */
11.17 +final class PostEventSupport implements EventSupport, Runnable {
11.18 + private final List<ModificationListener> listeners = new CopyOnWriteArrayList<ModificationListener>();
11.19 + private final List<Deliverable> deliverables = new CopyOnWriteArrayList<Deliverable>();
11.20 + private static final Executor EXEC = Executors.newSingleThreadExecutor();
11.21 +
11.22 + PostEventSupport() {
11.23 + }
11.24 +
11.25 + @Override
11.26 + public void fireModificationEvent(ModificationEvent ev) {
11.27 + synchronized (deliverables) {
11.28 + final Deliverable d = new Deliverable(ev, listeners.toArray(new ModificationListener[0]));
11.29 + deliverables.add(d);
11.30 + EXEC.execute(this);
11.31 + }
11.32 + }
11.33 +
11.34 + @Override
11.35 + public void add(ModificationListener l) {
11.36 + listeners.add(l);
11.37 + }
11.38 +
11.39 + @Override
11.40 + public void remove(ModificationListener l) {
11.41 + listeners.remove(l);
11.42 + }
11.43 +
11.44 + @Override
11.45 + public void run() {
11.46 + Deliverable[] pending;
11.47 + synchronized (deliverables) {
11.48 + if (deliverables.isEmpty()) {
11.49 + return;
11.50 + }
11.51 + pending = deliverables.toArray(new Deliverable[0]);
11.52 + deliverables.clear();
11.53 + }
11.54 + Calculator calc = null;
11.55 + Set<PostModificationListener> notify = new HashSet<PostModificationListener>();
11.56 + int pendingCount = pending.length;
11.57 + for (Deliverable d : pending) {
11.58 + calc = (Calculator)d.ev.getSource();
11.59 + d.ev.pending = --pendingCount;
11.60 + d.ev.posts = notify;
11.61 + for (ModificationListener l : d.listeners) {
11.62 + l.modification(d.ev);
11.63 + }
11.64 + d.ev.posts = null;
11.65 + }
11.66 +
11.67 + for (PostModificationListener pml : notify) {
11.68 + pml.postProcess(new PostModificationEvent(calc));
11.69 + }
11.70 + }
11.71 +
11.72 + private static class Deliverable {
11.73 + final ModificationEvent ev;
11.74 + final ModificationListener[] listeners;
11.75 +
11.76 + public Deliverable(ModificationEvent ev, ModificationListener[] listeners) {
11.77 + this.ev = ev;
11.78 + this.listeners = listeners;
11.79 + }
11.80 + }
11.81 +}
12.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
12.2 +++ b/samples/openfixed/src/org/apidesign/openfixed/PostModificationEvent.java Sun Mar 20 18:52:47 2011 +0100
12.3 @@ -0,0 +1,14 @@
12.4 +/*
12.5 + * To change this template, choose Tools | Templates
12.6 + * and open the template in the editor.
12.7 + */
12.8 +package org.apidesign.openfixed;
12.9 +
12.10 +import java.util.EventObject;
12.11 +// BEGIN: openfixed.postevent
12.12 +public final class PostModificationEvent extends EventObject {
12.13 + PostModificationEvent(Calculator calc) {
12.14 + super(calc);
12.15 + }
12.16 +}
12.17 +// END: openfixed.postevent
13.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
13.2 +++ b/samples/openfixed/src/org/apidesign/openfixed/PostModificationListener.java Sun Mar 20 18:52:47 2011 +0100
13.3 @@ -0,0 +1,9 @@
13.4 +package org.apidesign.openfixed;
13.5 +
13.6 +import java.util.EventListener;
13.7 +
13.8 +// BEGIN: openfixed.postprocessor
13.9 +public interface PostModificationListener extends EventListener {
13.10 + public void postProcess(PostModificationEvent ev);
13.11 +}
13.12 +// END: openfixed.postprocessor
14.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
14.2 +++ b/samples/openfixed/src/org/apidesign/openfixed/TrivialEventSupport.java Sun Mar 20 18:52:47 2011 +0100
14.3 @@ -0,0 +1,37 @@
14.4 +/*
14.5 + * To change this template, choose Tools | Templates
14.6 + * and open the template in the editor.
14.7 + */
14.8 +package org.apidesign.openfixed;
14.9 +
14.10 +import java.util.List;
14.11 +import java.util.concurrent.CopyOnWriteArrayList;
14.12 +
14.13 +/**
14.14 + *
14.15 + * @author Jaroslav Tulach <jtulach@netbeans.org>
14.16 + */
14.17 +final class TrivialEventSupport implements EventSupport {
14.18 + List<ModificationListener> listener = new CopyOnWriteArrayList<ModificationListener>();
14.19 +
14.20 + TrivialEventSupport() {
14.21 + }
14.22 +
14.23 + @Override
14.24 + public void fireModificationEvent(ModificationEvent ev) {
14.25 + for (ModificationListener l : listener) {
14.26 + l.modification(ev);
14.27 + }
14.28 + }
14.29 +
14.30 + @Override
14.31 + public void add(ModificationListener l) {
14.32 + listener.add(l);
14.33 + }
14.34 +
14.35 + @Override
14.36 + public void remove(ModificationListener l) {
14.37 + listener.remove(l);
14.38 + }
14.39 +
14.40 +}
15.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
15.2 +++ b/samples/openfixed/test/org/apidesign/openfixed/AsyncTest.java Sun Mar 20 18:52:47 2011 +0100
15.3 @@ -0,0 +1,18 @@
15.4 +package org.apidesign.openfixed;
15.5 +
15.6 +/** Test the Calculator.createAsynch() behavior.
15.7 + *
15.8 + * @author Jaroslav Tulach <jtulach@netbeans.org>
15.9 + */
15.10 +public final class AsyncTest extends CalculatorBase {
15.11 +
15.12 + public AsyncTest(String testName) {
15.13 + super(testName);
15.14 + }
15.15 +
15.16 + @Override
15.17 + protected Calculator create() {
15.18 + return Calculator.createAsynch();
15.19 + }
15.20 +
15.21 +}
16.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
16.2 +++ b/samples/openfixed/test/org/apidesign/openfixed/BasicTest.java Sun Mar 20 18:52:47 2011 +0100
16.3 @@ -0,0 +1,16 @@
16.4 +package org.apidesign.openfixed;
16.5 +
16.6 +/** Test the Calculator.create() behavior.
16.7 + *
16.8 + * @author Jaroslav Tulach <jtulach@netbeans.org>
16.9 + */
16.10 +public final class BasicTest extends CalculatorBase {
16.11 + public BasicTest(String testName) {
16.12 + super(testName);
16.13 + }
16.14 +
16.15 + @Override
16.16 + protected Calculator create() {
16.17 + return Calculator.create();
16.18 + }
16.19 +}
17.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
17.2 +++ b/samples/openfixed/test/org/apidesign/openfixed/CalculatorBase.java Sun Mar 20 18:52:47 2011 +0100
17.3 @@ -0,0 +1,64 @@
17.4 +package org.apidesign.openfixed;
17.5 +
17.6 +import java.util.ArrayList;
17.7 +import java.util.List;
17.8 +import junit.framework.TestCase;
17.9 +
17.10 +public abstract class CalculatorBase extends TestCase {
17.11 +
17.12 + public CalculatorBase(String testName) {
17.13 + super(testName);
17.14 + }
17.15 +
17.16 + protected abstract Calculator create();
17.17 +
17.18 + public void testSumAndListeners() throws Exception {
17.19 + Calculator a = create();
17.20 + MockListener l = new MockListener();
17.21 + a.addModificationListener(l);
17.22 + a.add(5);
17.23 + a.add(10);
17.24 + a.add(20);
17.25 + int ch = allChanges(l.assertEvents("Three changes", 3));
17.26 + assertEquals("35 was the change", 35, ch);
17.27 + assertEquals("Current value", 35, a.getSum());
17.28 + a.add(-5);
17.29 + int ch2 = allChanges(l.assertEvents("One change", 1));
17.30 + assertEquals("minus five was the change", -5, ch2);
17.31 + assertEquals("Final value", 30, a.getSum());
17.32 + }
17.33 +
17.34 + private static int allChanges(List<ModificationEvent> events) {
17.35 + int changes = 0;
17.36 + for (ModificationEvent me : events) {
17.37 + changes += me.getChange();
17.38 + }
17.39 + return changes;
17.40 + }
17.41 +
17.42 + public static class MockListener implements ModificationListener {
17.43 + private List<ModificationEvent> events;
17.44 +
17.45 + @Override
17.46 + public synchronized void modification(ModificationEvent ev) {
17.47 + if (events == null) {
17.48 + events = new ArrayList<ModificationEvent>();
17.49 + }
17.50 + events.add(ev);
17.51 + }
17.52 +
17.53 + public synchronized List<ModificationEvent> assertEvents(String msg, int cnt)
17.54 + throws InterruptedException {
17.55 + for (int i = 0; i < 10; i++) {
17.56 + if (events != null && events.size() >= cnt) {
17.57 + break;
17.58 + }
17.59 + wait(1000);
17.60 + }
17.61 + assertEquals(msg + ":\n" + events, cnt, events.size());
17.62 + List<ModificationEvent> res = events;
17.63 + events = null;
17.64 + return res;
17.65 + }
17.66 + } // end of ModificationListener
17.67 +}
18.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
18.2 +++ b/samples/openfixed/test/org/apidesign/openfixed/PendingTest.java Sun Mar 20 18:52:47 2011 +0100
18.3 @@ -0,0 +1,60 @@
18.4 +package org.apidesign.openfixed;
18.5 +
18.6 +import java.util.List;
18.7 +import java.util.concurrent.CountDownLatch;
18.8 +
18.9 +/** Test the Calculator.createPending() behavior.
18.10 + *
18.11 + * @author Jaroslav Tulach <jtulach@netbeans.org>
18.12 + */
18.13 +public class PendingTest extends CalculatorBase {
18.14 +
18.15 + public PendingTest(String testName) {
18.16 + super(testName);
18.17 + }
18.18 +
18.19 + @Override
18.20 + protected Calculator create() {
18.21 + return Calculator.createPending();
18.22 + }
18.23 +
18.24 + public void testPendingEvents() throws Exception {
18.25 + BlockingListener bl = new BlockingListener();
18.26 +
18.27 + Calculator calc = create();
18.28 + calc.addModificationListener(bl);
18.29 +
18.30 + calc.add(10);
18.31 + bl.first.await();
18.32 +
18.33 + calc.add(1);
18.34 + calc.add(2);
18.35 + calc.add(3);
18.36 +
18.37 + bl.cdl.countDown();
18.38 +
18.39 + List<ModificationEvent> events = bl.assertEvents("Four changes together", 4);
18.40 +
18.41 + assertEquals("No pending events for first event", 0, events.get(0).getPending());
18.42 + assertEquals("Group of three, two remaining", 2, events.get(1).getPending());
18.43 + assertEquals("Group of three, one remaining", 1, events.get(2).getPending());
18.44 + assertEquals("Group of three, last one", 0, events.get(3).getPending());
18.45 + }
18.46 +
18.47 + static class BlockingListener extends MockListener {
18.48 + CountDownLatch first = new CountDownLatch(1);
18.49 + CountDownLatch cdl = new CountDownLatch(1);
18.50 +
18.51 + @Override
18.52 + public synchronized void modification(ModificationEvent ev) {
18.53 + try {
18.54 + first.countDown();
18.55 + cdl.await();
18.56 + } catch (InterruptedException ex) {
18.57 + throw new IllegalStateException(ex);
18.58 + }
18.59 + super.modification(ev);
18.60 + }
18.61 + }
18.62 +
18.63 +}
19.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
19.2 +++ b/samples/openfixed/test/org/apidesign/openfixed/PostTest.java Sun Mar 20 18:52:47 2011 +0100
19.3 @@ -0,0 +1,62 @@
19.4 +package org.apidesign.openfixed;
19.5 +
19.6 +import java.util.concurrent.CountDownLatch;
19.7 +
19.8 +/** Test the Calculator.createPending() behavior.
19.9 + *
19.10 + * @author Jaroslav Tulach <jtulach@netbeans.org>
19.11 + */
19.12 +public final class PostTest extends PendingTest {
19.13 +
19.14 + public PostTest(String testName) {
19.15 + super(testName);
19.16 + }
19.17 +
19.18 + @Override
19.19 + protected Calculator create() {
19.20 + return Calculator.createBatch();
19.21 + }
19.22 +
19.23 + public void testPostModificationEvents() throws Exception {
19.24 + class PostListener extends BlockingListener implements PostModificationListener {
19.25 + int cnt;
19.26 +
19.27 + @Override
19.28 + public synchronized void modification(ModificationEvent ev) {
19.29 + // registers for callback when batch processing is over:
19.30 + ev.postProcess(this);
19.31 + super.modification(ev);
19.32 + }
19.33 +
19.34 + @Override
19.35 + public synchronized void postProcess(PostModificationEvent ev) {
19.36 + cnt++;
19.37 + }
19.38 +
19.39 + public synchronized void assertPostProcess(String msg, int expected) throws InterruptedException {
19.40 + for (int i = 0; i < 10; i++) {
19.41 + if (cnt >= expected) {
19.42 + break;
19.43 + }
19.44 + wait(1000);
19.45 + }
19.46 + assertEquals(msg, expected, cnt);
19.47 + cnt = 0;
19.48 + }
19.49 + }
19.50 + PostListener bl = new PostListener();
19.51 +
19.52 + Calculator calc = create();
19.53 + calc.addModificationListener(bl);
19.54 +
19.55 + calc.add(10);
19.56 + bl.first.await();
19.57 +
19.58 + calc.add(1);
19.59 + calc.add(2);
19.60 + calc.add(3);
19.61 +
19.62 + bl.cdl.countDown();
19.63 + bl.assertPostProcess("Two postprocessings (one for 10), then for the rest", 2);
19.64 + }
19.65 +}