0ba40aab1c692a8d3e470c3b93ccb53b2d08b009
[idea/community.git] / platform / core-api / src / com / intellij / openapi / util / AsyncResult.java
1 /*
2  * Copyright 2000-2016 JetBrains s.r.o.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.intellij.openapi.util;
17
18 import com.intellij.openapi.diagnostic.Logger;
19 import com.intellij.util.Consumer;
20 import com.intellij.util.Function;
21 import com.intellij.util.PairConsumer;
22 import org.jetbrains.annotations.NotNull;
23 import org.jetbrains.annotations.Nullable;
24
25 import java.util.Collections;
26 import java.util.List;
27
28 public class AsyncResult<T> extends ActionCallback {
29   private static final Logger LOG = Logger.getInstance(AsyncResult.class);
30
31   protected T myResult;
32
33   public AsyncResult() {
34   }
35
36   AsyncResult(int countToDone, @Nullable T result) {
37     super(countToDone);
38
39     myResult = result;
40   }
41
42   @NotNull
43   public AsyncResult<T> setDone(T result) {
44     myResult = result;
45     setDone();
46     return this;
47   }
48
49   @NotNull
50   public AsyncResult<T> setRejected(T result) {
51     myResult = result;
52     setRejected();
53     return this;
54   }
55
56   @NotNull
57   public <DependentResult> AsyncResult<DependentResult> subResult(@NotNull Function<T, DependentResult> doneHandler) {
58     return subResult(new AsyncResult<DependentResult>(), doneHandler);
59   }
60
61   @NotNull
62   public <SubResult, SubAsyncResult extends AsyncResult<SubResult>> SubAsyncResult subResult(@NotNull SubAsyncResult subResult,
63                                                                                              @NotNull Function<T, SubResult> doneHandler) {
64     doWhenDone(new SubResultDoneCallback<T, SubResult, SubAsyncResult>(subResult, doneHandler)).notifyWhenRejected(subResult);
65     return subResult;
66   }
67
68   /**
69    * @deprecated Don't use AsyncResult - use Promise instead.
70    */
71   @SuppressWarnings("unused")
72   @NotNull
73   @Deprecated
74   public ActionCallback subCallback(@NotNull Consumer<T> doneHandler) {
75     ActionCallback subCallback = new ActionCallback();
76     doWhenDone(new SubCallbackDoneCallback<T>(subCallback, doneHandler)).notifyWhenRejected(subCallback);
77     return subCallback;
78   }
79
80   /**
81    * @deprecated Use {@link #doWhenDone(com.intellij.util.Consumer)} (to remove in IDEA 16)
82    */
83   @NotNull
84   @Deprecated
85   public AsyncResult<T> doWhenDone(@SuppressWarnings("deprecation") @NotNull final Handler<T> handler) {
86     doWhenDone(new Runnable() {
87       @Override
88       public void run() {
89         handler.run(myResult);
90       }
91     });
92     return this;
93   }
94
95   @NotNull
96   public AsyncResult<T> doWhenDone(@NotNull final Consumer<T> consumer) {
97     doWhenDone(new Runnable() {
98       @Override
99       public void run() {
100         consumer.consume(myResult);
101       }
102     });
103     return this;
104   }
105
106   @NotNull
107   public AsyncResult<T> doWhenRejected(@NotNull final PairConsumer<T, String> consumer) {
108     doWhenRejected(new Runnable() {
109       @Override
110       public void run() {
111         consumer.consume(myResult, myError);
112       }
113     });
114     return this;
115   }
116
117   @Override
118   @NotNull
119   public final AsyncResult<T> notify(@NotNull final ActionCallback child) {
120     super.notify(child);
121     return this;
122   }
123
124   public T getResult() {
125     return myResult;
126   }
127
128   public T getResultSync() {
129     return getResultSync(-1);
130   }
131
132   @Nullable
133   public T getResultSync(long msTimeout) {
134     waitFor(msTimeout);
135     return myResult;
136   }
137
138   @NotNull
139   public final ActionCallback doWhenProcessed(@NotNull final Consumer<T> consumer) {
140     doWhenDone(consumer);
141     doWhenRejected(new PairConsumer<T, String>() {
142       @Override
143       public void consume(T result, String error) {
144         consumer.consume(result);
145       }
146     });
147     return this;
148   }
149
150   /**
151    * @deprecated Use {@link com.intellij.util.Consumer} (to remove in IDEA 16)
152    */
153   @Deprecated
154   public interface Handler<T> {
155     void run(T t);
156   }
157
158   /**
159    * @deprecated Don't use AsyncResult - use Promise instead.
160    */
161   @Deprecated
162   public static class Done<T> extends AsyncResult<T> {
163     public Done(T value) {
164       setDone(value);
165     }
166   }
167
168   /**
169    * @deprecated Don't use AsyncResult - use Promise instead.
170    */
171   @Deprecated
172   public static class Rejected<T> extends AsyncResult<T> {
173     public Rejected() {
174       setRejected();
175     }
176
177     public Rejected(T value) {
178       setRejected(value);
179     }
180   }
181
182   /**
183    * @deprecated Don't use AsyncResult - use Promise instead.
184    */
185   @NotNull
186   @Deprecated
187   public static <R> AsyncResult<R> rejected() {
188     //noinspection unchecked,deprecation
189     return new Rejected();
190   }
191
192   /**
193    * @deprecated Don't use AsyncResult - use Promise instead.
194    */
195   @NotNull
196   @Deprecated
197   public static <R> AsyncResult<R> rejected(@NotNull String errorMessage) {
198     AsyncResult<R> result = new AsyncResult<R>();
199     result.reject(errorMessage);
200     return result;
201   }
202
203   @NotNull
204   public static <R> AsyncResult<R> done(@Nullable R result) {
205     return new AsyncResult<R>().setDone(result);
206   }
207
208   /**
209    * @deprecated Don't use AsyncResult - use Promise instead.
210    */
211   @NotNull
212   @Deprecated
213   public static <R extends List> AsyncResult<R> doneList() {
214     //noinspection unchecked
215     return done((R)Collections.emptyList());
216   }
217
218   // we don't use inner class, avoid memory leak, we don't want to hold this result while dependent is computing
219   private static class SubResultDoneCallback<Result, SubResult, AsyncSubResult extends AsyncResult<SubResult>> implements Consumer<Result> {
220     private final AsyncSubResult subResult;
221     private final Function<Result, SubResult> doneHandler;
222
223     public SubResultDoneCallback(AsyncSubResult subResult, Function<Result, SubResult> doneHandler) {
224       this.subResult = subResult;
225       this.doneHandler = doneHandler;
226     }
227
228     @Override
229     public void consume(Result result) {
230       SubResult v;
231       try {
232         v = doneHandler.fun(result);
233       }
234       catch (Throwable e) {
235         subResult.reject(e.getMessage());
236         LOG.error(e);
237         return;
238       }
239       subResult.setDone(v);
240     }
241   }
242
243   private static class SubCallbackDoneCallback<Result> implements Consumer<Result> {
244     private final ActionCallback subResult;
245     private final Consumer<Result> doneHandler;
246
247     public SubCallbackDoneCallback(ActionCallback subResult, Consumer<Result> doneHandler) {
248       this.subResult = subResult;
249       this.doneHandler = doneHandler;
250     }
251
252     @Override
253     public void consume(Result result) {
254       try {
255         doneHandler.consume(result);
256       }
257       catch (Throwable e) {
258         subResult.reject(e.getMessage());
259         LOG.error(e);
260         return;
261       }
262       subResult.setDone();
263     }
264   }
265 }