package com.algolia.search.saas;

import org.json.JSONObject;

import java.util.ArrayList;
import java.util.List;

import static junit.framework.Assert.fail;

/**
 * This class helps coping with assertions in callbacks.
 * As AssertionErrors are thrown silently when an assertion fails in a callback,
 * this class wraps a CompletionHandler to check if an assert failed and expose the error through {@link AssertCompletionHandler#checkAssertions()}.
 */
abstract class AssertCompletionHandler implements CompletionHandler {
    private AssertionError error;
    private final CompletionHandler handler;
    private final List<AssertCompletionHandler> innerHandlers = new ArrayList<>();

    public AssertCompletionHandler() {
        this.handler = new CompletionHandler() {
            @Override public void requestCompleted(JSONObject content, AlgoliaException error) {
                doRequestCompleted(content, error);
            }
        };
    }

    abstract public void doRequestCompleted(JSONObject content, AlgoliaException error);

    /**
     * Add an inner handler to be checked as well in {@link AssertCompletionHandler#checkAssertions()}.
     */
    public void addInnerHandler(AssertCompletionHandler handler) {
        innerHandlers.add(handler);
    }

    /**
     * Fail if the handler encountered at least one AssertionError.
     */
    public void checkAssertions() {
        if (error != null) {
            fail("At least one assertion failed: " + error);
        }
        for (AssertCompletionHandler h : innerHandlers) {
            h.checkAssertions();
        }
    }

    @Override final public void requestCompleted(JSONObject content, AlgoliaException error) {
        try {
            handler.requestCompleted(content, error);
        } catch (AssertionError e) {
            this.error = e;
        }
    }
}

@@ -112,52 +112,8 @@
 t;%0A%0A
-import static junit.framework.Assert.fail;%0A%0A
 /**%0A
@@ -632,24 +632,258 @@
 yList%3C%3E();%0A%0A
+    /**%0A     * Global registry of all created completion handlers. It is cleared when the static %60checkAllHandlers()%60 method is%0A     * called.%0A     */%0A    private static List%3CAssertCompletionHandler%3E allHandlers = new ArrayList%3C%3E();%0A%0A
     public A
@@ -1132,16 +1132,116 @@
      %7D;%0A
+        synchronized (AssertCompletionHandler.class) %7B%0A            allHandlers.add(this);%0A        %7D%0A
     %7D%0A%0A 
@@ -1724,66 +1724,554 @@
     
-fail(%22At least one assertion failed: %22 + error);%0A        %7D
+// Throwing the original exception maintains the stack trace... though I am not entirely sure why. =:)%0A            // (An alternative would be to chain the exception.)%0A            throw error;%0A        %7D%0A        for (AssertCompletionHandler h : innerHandlers) %7B%0A            h.checkAssertions();%0A        %7D%0A    %7D%0A%0A    /**%0A     * Check assertions on all handlers created since the last call to this method (or since the beginning of the%0A     * process if this method was never called).%0A     */%0A    public synchronized static void checkAllHandlers() %7B
 %0A   
@@ -2301,32 +2301,36 @@
 ionHandler h
- : inner
+andler : all
 Handlers) %7B%0A
@@ -2334,32 +2334,38 @@
  %7B%0A            h
+andler
 .checkAssertions
@@ -2370,32 +2370,61 @@
 ns();%0A        %7D%0A
+        allHandlers.clear();%0A
     %7D%0A%0A    @Over

Add global registry for assertion completion handlers