All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.intellij.openapi.util.AsyncResult Maven / Gradle / Ivy

Go to download

A packaging of the IntelliJ Community Edition core-api library. This is release number 1 of trunk branch 142.

The newest version!
/*
 * Copyright 2000-2013 JetBrains s.r.o.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.intellij.openapi.util;

import com.intellij.openapi.diagnostic.Logger;
import com.intellij.util.Consumer;
import com.intellij.util.Function;
import com.intellij.util.PairConsumer;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.Collections;
import java.util.List;

public class AsyncResult extends ActionCallback {
  private static final Logger LOG = Logger.getInstance(AsyncResult.class);

  private static final AsyncResult REJECTED = new Rejected();
  private static final AsyncResult DONE_LIST = new Done(Collections.EMPTY_LIST);

  protected T myResult;

  public AsyncResult() {
  }

  AsyncResult(int countToDone, @Nullable T result) {
    super(countToDone);

    myResult = result;
  }

  @NotNull
  public AsyncResult setDone(T result) {
    myResult = result;
    setDone();
    return this;
  }

  @NotNull
  public AsyncResult setRejected(T result) {
    myResult = result;
    setRejected();
    return this;
  }

  @NotNull
  public  AsyncResult subResult(@NotNull Function doneHandler) {
    return subResult(new AsyncResult(), doneHandler);
  }

  @NotNull
  public > SubAsyncResult subResult(@NotNull SubAsyncResult subResult,
                                                                                             @NotNull Function doneHandler) {
    doWhenDone(new SubResultDoneCallback(subResult, doneHandler)).notifyWhenRejected(subResult);
    return subResult;
  }

  @NotNull
  public ActionCallback subCallback(@NotNull Consumer doneHandler) {
    ActionCallback subCallback = new ActionCallback();
    doWhenDone(new SubCallbackDoneCallback(subCallback, doneHandler)).notifyWhenRejected(subCallback);
    return subCallback;
  }

  @NotNull
  @Deprecated
  /**
   * @deprecated Use {@link #doWhenDone(com.intellij.util.Consumer)} (to remove in IDEA 16)
   */
  public AsyncResult doWhenDone(@SuppressWarnings("deprecation") @NotNull final Handler handler) {
    doWhenDone(new Runnable() {
      @Override
      public void run() {
        handler.run(myResult);
      }
    });
    return this;
  }

  @NotNull
  public AsyncResult doWhenDone(@NotNull final Consumer consumer) {
    doWhenDone(new Runnable() {
      @Override
      public void run() {
        consumer.consume(myResult);
      }
    });
    return this;
  }

  @NotNull
  @Deprecated
  /**
   * @deprecated Use {@link #doWhenRejected(com.intellij.util.Consumer)} (to remove in IDEA 16)
   */
  public AsyncResult doWhenRejected(@SuppressWarnings("deprecation") @NotNull final Handler handler) {
    doWhenRejected(new Runnable() {
      @Override
      public void run() {
        handler.run(myResult);
      }
    });
    return this;
  }

  @NotNull
  public AsyncResult doWhenRejected(@NotNull final PairConsumer consumer) {
    doWhenRejected(new Runnable() {
      @Override
      public void run() {
        consumer.consume(myResult, myError);
      }
    });
    return this;
  }

  @Override
  @NotNull
  public final AsyncResult notify(@NotNull final ActionCallback child) {
    super.notify(child);
    return this;
  }

  public T getResult() {
    return myResult;
  }

  public T getResultSync() {
    return getResultSync(-1);
  }

  @Nullable
  public T getResultSync(long msTimeout) {
    waitFor(msTimeout);
    return myResult;
  }

  @NotNull
  public final ActionCallback doWhenProcessed(@NotNull final Consumer consumer) {
    doWhenDone(consumer);
    doWhenRejected(new PairConsumer() {
      @Override
      public void consume(T result, String error) {
        consumer.consume(result);
      }
    });
    return this;
  }

  @Deprecated
  /**
   * @deprecated Use {@link com.intellij.util.Consumer} (to remove in IDEA 16)
   */
  public interface Handler {
    void run(T t);
  }

  public static class Done extends AsyncResult {
    public Done(T value) {
      setDone(value);
    }
  }

  public static class Rejected extends AsyncResult {
    public Rejected() {
      setRejected();
    }

    public Rejected(T value) {
      setRejected(value);
    }
  }

  @NotNull
  public static  AsyncResult rejected() {
    //noinspection unchecked
    return REJECTED;
  }

  @NotNull
  public static  AsyncResult rejected(@NotNull String errorMessage) {
    AsyncResult result = new AsyncResult();
    result.reject(errorMessage);
    return result;
  }

  @NotNull
  public static  AsyncResult done(@Nullable R result) {
    return new AsyncResult().setDone(result);
  }

  @NotNull
  public static  AsyncResult doneList() {
    //noinspection unchecked
    return DONE_LIST;
  }

  // we don't use inner class, avoid memory leak, we don't want to hold this result while dependent is computing
  private static class SubResultDoneCallback> implements Consumer {
    private final AsyncSubResult subResult;
    private final Function doneHandler;

    public SubResultDoneCallback(AsyncSubResult subResult, Function doneHandler) {
      this.subResult = subResult;
      this.doneHandler = doneHandler;
    }

    @Override
    public void consume(Result result) {
      SubResult v;
      try {
        v = doneHandler.fun(result);
      }
      catch (Throwable e) {
        subResult.reject(e.getMessage());
        LOG.error(e);
        return;
      }
      subResult.setDone(v);
    }
  }

  private static class SubCallbackDoneCallback implements Consumer {
    private final ActionCallback subResult;
    private final Consumer doneHandler;

    public SubCallbackDoneCallback(ActionCallback subResult, Consumer doneHandler) {
      this.subResult = subResult;
      this.doneHandler = doneHandler;
    }

    @Override
    public void consume(Result result) {
      try {
        doneHandler.consume(result);
      }
      catch (Throwable e) {
        subResult.reject(e.getMessage());
        LOG.error(e);
        return;
      }
      subResult.setDone();
    }
  }
}