Skip to content

Commit d79e137

Browse files
committed
initial commit
0 parents  commit d79e137

14 files changed

Lines changed: 1643 additions & 0 deletions

.gitignore

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
.idea
2+
*.iml
3+
target
4+
*.ipr
5+
*.iws
6+
*.ids
7+
.settings
8+
.classpath
9+
.project
10+
*.class
11+
*.log

README.md

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# DeferredJava
2+
=======================
3+
4+
**`DeferredJava`** is a thread safe non-blocking `deferred/promise` implementation for `Java`. It provides an easy to use fluent `deferred/promise` API that can be used to manage complex flow of asynchronus operations easily.
5+
6+
## Usage
7+
-------------------
8+
9+
Both `deferred` and `promise` means the same thing a `promise` that represents the result of a `asynchronus operation` that is not completed. The difference is that `deferred` provides a `interface` that can access to the `promise object` to change its state where as `promise` provides an interface that cannot.
10+
11+
It is not very easy to controll a complex flow of asynchronus operations specially where there are many asynchronus operations needs to be done and one or more operations depands on another one or some other operations to complete and those other operations may wait for other operations to complete. Promise helps us to establish a callback chain that can be used to maintain any cmplex flow of asynchronus operations easily.
12+
13+
## Features
14+
-------------------
15+
16+
* Thread safe and non-blocking
17+
* Easy to use fluent API
18+
* `deferred = DeferredFactory.createDeferred()
19+
deferred.then(success).fail(fail).notify(update)`
20+
* `aDeferred.then(success,fail,notify)`
21+
* `aDeferred.resolve(aResolvedValue)`
22+
* Provides both deferred and promise interface
23+
* `aDeferred.then(success)`
24+
* `aDeferred.promise().then(success)`
25+
* Supports promise chaining
26+
* `aDeferred.then(success,fail,notify)
27+
.then(success,fail,notify)
28+
.then(success,fail,notify)`
29+
* Supports downward streaming
30+
* `aDeferred.then(success).then(success)
31+
.notify(notify).fail(fail)`
32+
* Provides a `Thenable` interface for better interoperability between `promise` and `non-promise` system.
33+
* Supports when
34+
* `Deferred.when(promise1).then(success)`
35+
* `Deferred.when(promise1,promise2,promise3)
36+
.then(success).then(fail)`
37+
* Asynchronus task execution
38+
* Has built in container for asynchronus task execution
39+
* `DeferredFactory.createNewContainer()`
40+
* `DeferredContainer.getContainer().stop()`
41+
* Asynchronus task with callables
42+
* `when(callable1).then(...)`
43+
* `when(callable1,callable2,callable3).then(...)`
44+
* After finish of a callable the deferred object will be automatically resolved by the return value. However, `RunnableDeferred` class can be used to controll when the deferred is resolved.
45+
46+
## Quick Examples
47+
----------------------
48+
49+
TODO
50+

pom.xml

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
2+
<modelVersion>4.0.0</modelVersion>
3+
<groupId>org.djava</groupId>
4+
<artifactId>deferredjava</artifactId>
5+
<version>0.1-SNAPSHOT</version>
6+
<name>deferredjava</name>
7+
8+
<dependencies>
9+
<dependency>
10+
<groupId>junit</groupId>
11+
<artifactId>junit</artifactId>
12+
<version>4.11</version>
13+
<scope>test</scope>
14+
</dependency>
15+
</dependencies>
16+
17+
<build>
18+
<plugins>
19+
<plugin>
20+
<artifactId>maven-compiler-plugin</artifactId>
21+
<version>3.1</version>
22+
<configuration>
23+
<encoding>UTF-8</encoding>
24+
<source>1.7</source>
25+
<target>1.7</target>
26+
</configuration>
27+
</plugin>
28+
<plugin>
29+
<groupId>org.apache.maven.plugins</groupId>
30+
<artifactId>maven-source-plugin</artifactId>
31+
<version>2.2.1</version>
32+
<executions>
33+
<execution>
34+
<id>attach-sources</id>
35+
<goals>
36+
<goal>jar</goal>
37+
</goals>
38+
</execution>
39+
</executions>
40+
</plugin>
41+
<plugin>
42+
<groupId>org.apache.maven.plugins</groupId>
43+
<artifactId>maven-surefire-plugin</artifactId>
44+
<version>2.16</version>
45+
</plugin>
46+
</plugins>
47+
</build>
48+
</project>
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
package org.djava.async;
2+
3+
import org.djava.async.util.VoidType;
4+
5+
public class Callbacks {
6+
7+
public static enum CallBackType {
8+
SUCCESS, FAILURE, NOTIFICATION;
9+
10+
public boolean isSuccess() {
11+
return SUCCESS.equals(this);
12+
}
13+
14+
public boolean isFailure() {
15+
return FAILURE.equals(this);
16+
}
17+
18+
public boolean isNotification() {
19+
return NOTIFICATION.equals(this);
20+
}
21+
}
22+
23+
public static class NotificationEvent {
24+
25+
private Promise<?> src;
26+
27+
public NotificationEvent(Promise<?> src) {
28+
this.src = src;
29+
}
30+
31+
public Promise<?> getSrc() {
32+
return src;
33+
}
34+
}
35+
36+
public static interface CallBack<R, A> {
37+
R call(A arg);
38+
CallBackType getType();
39+
}
40+
41+
public abstract static class SuccessCallBack<F, A> implements CallBack<Object, A> {
42+
43+
protected int index;
44+
45+
public SuccessCallBack() {
46+
47+
}
48+
49+
public SuccessCallBack(int index) {
50+
this.index = index;
51+
}
52+
53+
@Override
54+
public abstract Object call(A arg);
55+
56+
@Override
57+
public CallBackType getType() {
58+
return CallBackType.SUCCESS;
59+
}
60+
}
61+
62+
public abstract static class FailureCallBack implements CallBack<VoidType, Exception> {
63+
64+
@Override
65+
public abstract VoidType call(Exception arg);
66+
67+
@Override
68+
public CallBackType getType() {
69+
return CallBackType.FAILURE;
70+
}
71+
}
72+
73+
public abstract static class NotificationCallBack implements CallBack<VoidType, NotificationEvent> {
74+
75+
@Override
76+
public abstract VoidType call(NotificationEvent event);
77+
78+
@Override
79+
public CallBackType getType() {
80+
return CallBackType.NOTIFICATION;
81+
}
82+
}
83+
84+
}
Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
package org.djava.async;
2+
3+
import java.util.Arrays;
4+
import java.util.List;
5+
import java.util.concurrent.Callable;
6+
import java.util.concurrent.atomic.AtomicInteger;
7+
8+
import org.djava.async.Callbacks.FailureCallBack;
9+
import org.djava.async.Callbacks.NotificationCallBack;
10+
import org.djava.async.Callbacks.NotificationEvent;
11+
import org.djava.async.Callbacks.SuccessCallBack;
12+
import org.djava.async.util.DeferredContainer;
13+
import org.djava.async.util.VoidType;
14+
import org.djava.async.util.DeferredContainer.DeferredTask;
15+
import org.djava.async.util.DeferredContainer.RunnableDeffered;
16+
17+
/**
18+
* Unrestricted interface to access the deferred object. The interface should not be
19+
* supplied to a consumer who should not change the promise's state. Use {@link Promise} for
20+
* restricted access.
21+
*
22+
* <p>
23+
* Use {@link DeferredFactory} to create a deferred object.
24+
* </p>
25+
*
26+
* @author Prasun Paul
27+
*
28+
* @param <R> the resolved value type of the promise
29+
*/
30+
@SuppressWarnings("unchecked")
31+
public abstract class Deferred<R> extends Promise<R> {
32+
33+
public abstract Promise<R> promise();
34+
35+
public abstract void resolve(R value);
36+
37+
public abstract void reject(Exception ex);
38+
39+
public abstract void notify(NotificationEvent event);
40+
41+
/**
42+
* Gets the current deferred object.
43+
*
44+
* @return the deferred object
45+
*/
46+
public Deferred<R> get() {
47+
return this;
48+
}
49+
50+
/**
51+
* The when method.
52+
*
53+
* <p>
54+
* When all of the promises are done the next pending promise will be
55+
* resolved. The resolve value will be list of resolve values of the promises. The
56+
* list order is maintained how the promises appear in when arguments.
57+
* </p>
58+
*
59+
* @param promises the array of promises
60+
*
61+
* @return a new <tt>promise</tt>
62+
*/
63+
public static <T> Promise<List<T>> when(Promise<T>... promises) {
64+
final Deferred<List<T>> deferred = DeferredFactory.createDeferred();
65+
66+
if(promises == null || promises.length == 0) {
67+
deferred.resolve(null);
68+
return deferred.promise();
69+
}
70+
71+
final T[] result = (T[]) new Object[promises.length];
72+
final AtomicInteger completionRemainCount = new AtomicInteger(promises.length);
73+
74+
for(int i = 0; i < promises.length; i++) {
75+
promises[i].then(new SuccessCallBack<Object, T>(i) {
76+
@Override
77+
public Object call(T value) {
78+
result[index] = value;
79+
if(completionRemainCount.decrementAndGet() == 0) {
80+
deferred.resolve(Arrays.asList(result));
81+
}
82+
return VoidType.NOTHING;
83+
}
84+
}, new FailureCallBack() {
85+
@Override
86+
public VoidType call(Exception reason) {
87+
deferred.reject(reason);
88+
return VoidType.NOTHING;
89+
}
90+
}, new NotificationCallBack() {
91+
@Override
92+
public VoidType call(NotificationEvent event) {
93+
deferred.notify(event);
94+
return VoidType.NOTHING;
95+
}
96+
});
97+
}
98+
99+
return deferred.promise();
100+
}
101+
102+
/**
103+
* The when method. A useful helper method when there is only one promise
104+
* to resolve compare to multiple promise version.
105+
*
106+
* @param promise the promise
107+
*
108+
* @return a new promise
109+
*/
110+
public static <P> Promise<P> when(Promise<P> promise) {
111+
112+
final Deferred<P> deferred = DeferredFactory.createDeferred();
113+
promise.then(new SuccessCallBack<P, P>() {
114+
@Override
115+
public Object call(P value) {
116+
deferred.resolve(value);
117+
return VoidType.NOTHING;
118+
}
119+
}, new FailureCallBack() {
120+
@Override
121+
public VoidType call(Exception reason) {
122+
deferred.reject(reason);
123+
return VoidType.NOTHING;
124+
}
125+
}, new NotificationCallBack() {
126+
@Override
127+
public VoidType call(NotificationEvent event) {
128+
deferred.notify(event);
129+
return VoidType.NOTHING;
130+
}
131+
});
132+
133+
return deferred.promise();
134+
}
135+
136+
/**
137+
* When method for a callable. The callable will be converted to a <tt>deferred</tt>
138+
* task. The task will be submitted to the deferred container for execution. Deferred promise
139+
* of the task will be returned.
140+
*
141+
* @see DeferredTask
142+
* @see DeferredContainer
143+
*
144+
* @param callable the callable
145+
*
146+
* @return the promise
147+
*/
148+
public static <T> Promise<T> when(Callable<T> callable) {
149+
RunnableDeffered<T> rp = DeferredFactory.promisify(callable);
150+
rp.submit();
151+
return rp.promise();
152+
}
153+
154+
/**
155+
* The when method for multiple callables. All of the callables will be converted to its
156+
* deferred task. When all of the deferred tasks are completed next pending promise will
157+
* be resolved.
158+
*
159+
* @see DeferredTask
160+
* @see DeferredContainer
161+
*
162+
* @param callables the array of callables
163+
*
164+
* @return a new promise
165+
*/
166+
public static <T> Promise<List<T>> when(Callable<T>... callables) {
167+
Promise<T>[] promises = (Promise<T>[]) new Promise<?>[callables.length];
168+
for(int i = 0; i < callables.length; i++) {
169+
promises[i] = when(callables[i]);
170+
}
171+
return when(promises);
172+
}
173+
174+
}

0 commit comments

Comments
 (0)