2 * fcplib - HighLevelCallback.java -
3 * Copyright © 2008 David Roden
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 package net.pterodactylus.fcp.highlevel;
22 import java.util.ArrayList;
23 import java.util.Collections;
24 import java.util.List;
27 * A callback is used to notify users of the {@link HighLevelClient} that an
28 * operation was completed.
31 * The type of the high-level operation result
32 * @author David ‘Bombe’ Roden <bombe@freenetproject.org>
35 public class HighLevelCallback<R extends HighLevelResult> {
37 /** Object used for synchronization. */
38 private final Object syncObject = new Object();
40 /** The list of callback listeners. */
41 private final List<HighLevelCallbackListener<R>> highLevelCallbackListeners = Collections.synchronizedList(new ArrayList<HighLevelCallbackListener<R>>());
43 /** Whether the result is complete. */
44 private boolean resultComplete = false;
46 /** The result of the operation. */
47 private R result = null;
50 * Package-private construtor.
56 * Adds a callback listener to this callback. The callback listener will be
57 * called as soon as the result of the operation is known. If the result is
58 * already known, the listener will be called immediately. Also, as soon as
59 * a listener was notified the listener is automatically removed from this
62 * @param highLevelCallbackListener
65 public void addHighLevelCallbackListener(HighLevelCallbackListener<R> highLevelCallbackListener) {
66 highLevelCallbackListeners.add(highLevelCallbackListener);
73 * Removes a callback listener from this callback.
75 * @param highLevelCallbackListener
76 * The listener to remove
78 public void removeHighLevelCallbackListener(HighLevelCallbackListener<R> highLevelCallbackListener) {
79 highLevelCallbackListeners.remove(highLevelCallbackListener);
83 * Notifies all listeners that the result of the operation is now known.
85 * @see HighLevelCallbackListener#gotResult(HighLevelCallback)
87 private synchronized void fireGotResult() {
88 for (HighLevelCallbackListener<R> highLevelCallbackListener: highLevelCallbackListeners) {
89 highLevelCallbackListeners.remove(highLevelCallbackListener);
90 highLevelCallbackListener.gotResult(this);
95 * Returns whether the result of the operation is already known. If the
96 * result is already known a call to {@link #getResult()} will not block.
98 * @return <code>true</code> if the result is already known,
99 * <code>false</code> otherwise
101 public boolean isDone() {
102 synchronized (syncObject) {
103 return resultComplete;
108 * Returns the result of the operation, blocking until it is known.
110 * @return The result of the operation
111 * @throws InterruptedException
112 * if {@link Object#wait()} was interrupted
114 public R getResult() throws InterruptedException {
119 * Returns the result of the operation, blocking until it is known or the
120 * given time (in milliseconds) has passed.
123 * The time to wait for a result
124 * @return The result of the operation, or <code>null</code> if the result
125 * is still not known after <code>waitTime</code> milliseconds
127 * @throws InterruptedException
128 * if {@link Object#wait()} is interrupted
130 public R getResult(long waitTime) throws InterruptedException {
131 synchronized (syncObject) {
132 if (!resultComplete) {
133 syncObject.wait(waitTime);
140 * Sets the complete result of the operation. Calling this method will
141 * result in all listeners being notified.
143 * @see #fireGotResult()
145 * The result of the operation
147 void setResult(R result) {
148 setResult(result, true);
152 * Sets the result of the operation. Depending on the <code>notify</code>
153 * parameter the listeners are notified. You have to call this method with
154 * <code>notify = true</code> after your result is completed, otherwise
155 * clients will block endlessly!
158 * The result of the operation
160 * <code>true</code> to finalize the result and notify all
161 * listeners, <code>false</code> if something in the result
164 void setResult(R result, boolean notify) {
165 synchronized (syncObject) {
166 this.result = result;
168 resultComplete = true;
169 syncObject.notifyAll();
178 * Returns the result even if it is not yet complete.
180 * @return The result of the operation
182 R getIntermediaryResult() {
183 synchronized (syncObject) {
189 * Marks the result given in with
190 * {@link #setResult(HighLevelResult, boolean)} as complete and notify the
191 * listeners. If the result was already complete, nothing will be done.
194 synchronized (syncObject) {
195 if (resultComplete) {
198 resultComplete = true;