187171a079b902b98c4e039ece68e79dc8c6de74
[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 public class AsyncResult<T> extends ActionCallback {
26   private static final Logger LOG = Logger.getInstance(AsyncResult.class);
27
28   protected T myResult;
29
30   public AsyncResult() {
31   }
32
33   AsyncResult(int countToDone, @Nullable T result) {
34     super(countToDone);
35
36     myResult = result;
37   }
38
39   @NotNull
40   public AsyncResult<T> setDone(T result) {
41     myResult = result;
42     setDone();
43     return this;
44   }
45
46   @NotNull
47   public AsyncResult<T> setRejected(T result) {
48     myResult = result;
49     setRejected();
50     return this;
51   }
52
53   @NotNull
54   public <DependentResult> AsyncResult<DependentResult> subResult(@NotNull Function<T, DependentResult> doneHandler) {
55     return subResult(new AsyncResult<DependentResult>(), doneHandler);
56   }
57
58   @NotNull
59   public <SubResult, SubAsyncResult extends AsyncResult<SubResult>> SubAsyncResult subResult(@NotNull SubAsyncResult subResult,
60                                                                                              @NotNull Function<T, SubResult> doneHandler) {
61     doWhenDone(new SubResultDoneCallback<T, SubResult, SubAsyncResult>(subResult, doneHandler)).notifyWhenRejected(subResult);
62     return subResult;
63   }
64
65   /**
66    * @deprecated Don't use AsyncResult - use Promise instead.
67    */
68   @SuppressWarnings("unused")
69   @NotNull
70   @Deprecated
71   public ActionCallback subCallback(@NotNull Consumer<T> doneHandler) {
72     ActionCallback subCallback = new ActionCallback();
73     doWhenDone(new SubCallbackDoneCallback<T>(subCallback, doneHandler)).notifyWhenRejected(subCallback);
74     return subCallback;
75   }
76
77   /**
78    * @deprecated Use {@link #doWhenDone(com.intellij.util.Consumer)} (to remove in IDEA 16)
79    */
80   @NotNull
81   @Deprecated
82   public AsyncResult<T> doWhenDone(@SuppressWarnings("deprecation") @NotNull final Handler<T> handler) {
83     doWhenDone(new Runnable() {
84       @Override
85       public void run() {
86         handler.run(myResult);
87       }
88     });
89     return this;
90   }
91
92   @NotNull
93   public AsyncResult<T> doWhenDone(@NotNull final Consumer<T> consumer) {
94     doWhenDone(new Runnable() {
95       @Override
96       public void run() {
97         consumer.consume(myResult);
98       }
99     });
100     return this;
101   }
102
103   @NotNull
104   public AsyncResult<T> doWhenRejected(@NotNull final PairConsumer<T, String> consumer) {
105     doWhenRejected(new Runnable() {
106       @Override
107       public void run() {
108         consumer.consume(myResult, myError);
109       }
110     });
111     return this;
112   }
113
114   @Override
115   @NotNull
116   public final AsyncResult<T> notify(@NotNull final ActionCallback child) {
117     super.notify(child);
118     return this;
119   }
120
121   public T getResult() {
122     return myResult;
123   }
124
125   public T getResultSync() {
126     return getResultSync(-1);
127   }
128
129   @Nullable
130   public T getResultSync(long msTimeout) {
131     waitFor(msTimeout);
132     return myResult;
133   }
134
135   @NotNull
136   public final ActionCallback doWhenProcessed(@NotNull final Consumer<T> consumer) {
137     doWhenDone(consumer);
138     doWhenRejected(new PairConsumer<T, String>() {
139       @Override
140       public void consume(T result, String error) {
141         consumer.consume(result);
142       }
143     });
144     return this;
145   }
146
147   /**
148    * @deprecated Use {@link com.intellij.util.Consumer} (to remove in IDEA 16)
149    */
150   @Deprecated
151   public interface Handler<T> {
152     void run(T t);
153   }
154
155   /**
156    * @deprecated Don't use AsyncResult - use Promise instead.
157    */
158   @Deprecated
159   public static class Done<T> extends AsyncResult<T> {
160     public Done(T value) {
161       setDone(value);
162     }
163   }
164
165   /**
166    * @deprecated Don't use AsyncResult - use Promise instead.
167    */
168   @Deprecated
169   public static class Rejected<T> extends AsyncResult<T> {
170     public Rejected() {
171       setRejected();
172     }
173
174     public Rejected(T value) {
175       setRejected(value);
176     }
177   }
178
179   /**
180    * @deprecated Don't use AsyncResult - use Promise instead.
181    */
182   @NotNull
183   @Deprecated
184   public static <R> AsyncResult<R> rejected() {
185     //noinspection unchecked,deprecation
186     return new Rejected();
187   }
188
189   /**
190    * @deprecated Don't use AsyncResult - use Promise instead.
191    */
192   @NotNull
193   @Deprecated
194   public static <R> AsyncResult<R> rejected(@NotNull String errorMessage) {
195     AsyncResult<R> result = new AsyncResult<R>();
196     result.reject(errorMessage);
197     return result;
198   }
199
200   @NotNull
201   public static <R> AsyncResult<R> done(@Nullable R result) {
202     return new AsyncResult<R>().setDone(result);
203   }
204
205   // we don't use inner class, avoid memory leak, we don't want to hold this result while dependent is computing
206   private static class SubResultDoneCallback<Result, SubResult, AsyncSubResult extends AsyncResult<SubResult>> implements Consumer<Result> {
207     private final AsyncSubResult subResult;
208     private final Function<Result, SubResult> doneHandler;
209
210     public SubResultDoneCallback(AsyncSubResult subResult, Function<Result, SubResult> doneHandler) {
211       this.subResult = subResult;
212       this.doneHandler = doneHandler;
213     }
214
215     @Override
216     public void consume(Result result) {
217       SubResult v;
218       try {
219         v = doneHandler.fun(result);
220       }
221       catch (Throwable e) {
222         subResult.reject(e.getMessage());
223         LOG.error(e);
224         return;
225       }
226       subResult.setDone(v);
227     }
228   }
229
230   private static class SubCallbackDoneCallback<Result> implements Consumer<Result> {
231     private final ActionCallback subResult;
232     private final Consumer<Result> doneHandler;
233
234     public SubCallbackDoneCallback(ActionCallback subResult, Consumer<Result> doneHandler) {
235       this.subResult = subResult;
236       this.doneHandler = doneHandler;
237     }
238
239     @Override
240     public void consume(Result result) {
241       try {
242         doneHandler.consume(result);
243       }
244       catch (Throwable e) {
245         subResult.reject(e.getMessage());
246         LOG.error(e);
247         return;
248       }
249       subResult.setDone();
250     }
251   }
252 }