Ejemplo n.º 1
0
 public static JsonArray<Workspace> createMultipleAsWorkspace(int mocks) {
   JsonArray<Workspace> workspaces = JsonCollections.createArray();
   for (int i = 0; i < mocks; i++) {
     workspaces.add(StubWorkspaceInfo.make().asWorkspace());
   }
   return workspaces;
 }
Ejemplo n.º 2
0
/**
 * An adapter for {@link DocumentParser.Listener} that performs only async parsing while collecting
 * some line-dependent data.
 */
public abstract class AsyncParser<T extends AsyncParser.LineAware>
    implements DocumentParser.Listener {

  /**
   * Data item base interface. It is important that they are associated with lines because we clear
   * data for lines that are invalidated and need to be parsed again.
   */
  public static interface LineAware {

    /** @return line number this data belongs to */
    int getLineNumber();
  }

  /** Called before parsing has started. */
  protected void onBeforeParse() {}

  /**
   * Called when the data parsed earlier is discarded. Implementations should clear everything
   * associated with this data. This method may be called on any time and should not depend on
   * parsing cycle state.
   *
   * @param cleanedData data items that will be deleted
   */
  protected void onCleanup(JsonArray<T> cleanedData) {}

  /**
   * Called when a line is being parsed. This is guaranteed to be called after {@link
   * #onBeforeParse} and before {@link #onAfterParse}.
   *
   * @param line line being parsed
   * @param lineNumber line number being parsed
   * @param tokens tokens collected on the line
   */
  protected void onParseLine(Line line, int lineNumber, JsonArray<Token> tokens) {}

  /**
   * Called just after chunk parsing has finished. This does not mean that parsing for the whole
   * file has finished. You have to use what you get here.
   *
   * @param nodes resulting array of all nodes collected so far for the whole file
   */
  protected void onAfterParse(JsonArray<T> nodes) {}

  /** Flag that prevents work after instance was cleaned. */
  private boolean detached;

  /** Flag indicating that block of lines is being parsed */
  private boolean iterating;

  /**
   * Array of data items.
   *
   * <p>When new block of lines is parsed, this list is truncated.
   */
  private JsonArray<T> nodes = JsonCollections.createArray();

  @Override
  public final void onDocumentLineParsed(
      Line line, int lineNumber, @Nonnull JsonArray<Token> tokens) {
    if (detached) {
      return;
    }
    if (!iterating) {
      return;
    }
    onParseLine(line, lineNumber, tokens);
  }

  @Override
  public final void onIterationFinish() {
    Preconditions.checkState(iterating);
    if (detached) {
      return;
    }
    iterating = false;
    onAfterParse(nodes);
  }

  @Override
  public final void onIterationStart(int lineNumber) {
    Preconditions.checkState(!iterating);
    if (detached) {
      return;
    }
    iterating = true;
    cutTail(lineNumber);
    onBeforeParse();
  }

  /**
   * Adds given data to collected set while parsing.
   *
   * @param dataNode data to add
   */
  protected final void addData(T dataNode) {
    nodes.add(dataNode);
  }

  private void cutTail(int lineNumber) {
    if (nodes.size() != 0) {
      int cutTailIndex = findCutTailIndex(nodes, lineNumber);
      if (cutTailIndex < nodes.size()) {
        JsonArray<T> tail = nodes.splice(cutTailIndex, nodes.size() - cutTailIndex);
        onCleanup(tail);
      }
    }
  }

  /**
   * Find index for tail truncation in nodes array.
   *
   * <p>We support nodes array sorted by line number. Now we use that property in modified binary
   * search.
   */
  @VisibleForTesting
  public static <T extends LineAware> int findCutTailIndex(JsonArray<T> nodes, int lineNumber) {
    int low = 0;
    int high = nodes.size() - 1;

    while (low <= high) {
      int mid = (low + high) >>> 1;
      if (lineNumber > nodes.get(mid).getLineNumber()) {
        low = mid + 1;
      } else {
        high = mid - 1;
      }
    }
    return low;
  }

  /**
   * Cleanup object. Overriding implementations should call this method before any custom cleanup.
   *
   * <p>After cleanup is invoked this instance should never be used.
   */
  public void cleanup() {
    cutTail(0);
    detached = true;
  }
}