/*
 * Copyright (c) 2015-2017, Statens vegvesen
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 *    list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package no.vegvesen.nvdbapi.client.exceptions;

import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;

public final class JsonExceptionParser {
    private static final Logger LOG = LoggerFactory.getLogger(JsonExceptionParser.class);

    private JsonExceptionParser() {
    }

    public static ApiError parseFirst(String json) {
        List<ApiError> errors = parse(json);
        return errors.isEmpty() ? null : errors.get(0);
    }

    public static List<ApiError> parse(String json) {
        JsonArray errors;
        try {
            errors = JsonParser.parseString(json).getAsJsonArray();
        } catch (Exception ex) {
            LOG.warn("Could not parse '{}' as json (exception: {})", json, ex.getClass().getName());
            throw ex;
        }
        List<ApiError> apiErrors = new ArrayList<>();
        errors.forEach(n -> {
            Integer errorCode = readInt(n, "code");
            String message = readText(n, "message");
            String details = readText(n, "message_detailed");
            String helpUrl = readText(n, "help_url");
            apiErrors.add(new ApiError(errorCode, message, details, helpUrl));
        });
        return apiErrors;
    }

    private static Integer readInt(JsonElement e, String name) {
        return Optional.ofNullable(e)
                .map(JsonElement::getAsJsonObject)
                .filter(JsonExceptionParser::isNonNull)
                .map(o -> o.get(name))
                .filter(JsonExceptionParser::isNonNull)
                .map(JsonElement::getAsInt).orElse(null);
    }

    private static String readText(JsonElement e, String name) {
        return Optional.ofNullable(e)
                .map(JsonElement::getAsJsonObject)
                .filter(JsonExceptionParser::isNonNull)
                .map(o -> o.get(name))
                .filter(JsonExceptionParser::isNonNull)
                .map(JsonElement::getAsString).orElse(null);
    }

    private static boolean isNonNull(JsonElement elem) {
        return !elem.isJsonNull();
    }
}

@@ -1423,42 +1423,8 @@
 s;%0A%0A
-import com.google.gson.JsonArray;%0A
 impo
@@ -1552,36 +1552,8 @@
 y;%0A%0A
-import java.util.ArrayList;%0A
 impo
@@ -1627,16 +1627,91 @@
 ptional;
+%0Aimport java.util.stream.Collectors;%0Aimport java.util.stream.StreamSupport;
 %0A%0Apublic
@@ -2106,241 +2106,353 @@
     
-JsonArray errors;%0A        try %7B%0A            errors = JsonParser.parseString(json).getAsJsonArray();%0A        %7D catch (Exception ex) %7B%0A            LOG.warn(%22Could not parse '%7B%7D' as json (exception: %7B%7D)%22, json, ex.getClass().getName());
+if(json.contains(%22%3Chtml%3E%22)) %7B%0A            return Collections.singletonList(%0A                new ApiError(504,%0A                    %22Server did not respond correctly%22,%0A                    json, %22%22));%0A        %7D%0A        try %7B%0A            return StreamSupport.stream(%0A                JsonParser.parseString(json).getAsJsonArray().spliterator(), false
 %0A   
@@ -2464,17 +2464,9 @@
     
-throw ex;
+)
 %0A   
@@ -2470,26 +2470,24 @@
         
-%7D%0A
         
 List%3CApi
@@ -2482,115 +2482,51 @@
     
-List%3CApiError%3E apiErrors = new ArrayList%3C%3E();%0A        errors.forEach(n -%3E %7B%0A            Integer errorCode =
+.map(n -%3E new ApiError(%0A                   
  rea
@@ -2540,17 +2540,17 @@
  %22code%22)
-;
+,
 %0A       
@@ -2558,24 +2558,15 @@
     
-String message =
+       
  rea
@@ -2584,17 +2584,17 @@
 essage%22)
-;
+,
 %0A       
@@ -2602,24 +2602,15 @@
     
-String details =
+       
  rea
@@ -2637,17 +2637,17 @@
 tailed%22)
-;
+,
 %0A       
@@ -2655,24 +2655,15 @@
     
-String helpUrl =
+       
  rea
@@ -2686,126 +2686,240 @@
 rl%22)
-;%0A            apiErrors.add(new ApiError(errorCode, message, details, helpUrl));%0A        %7D);%0A        return apiErrors;
+%0A                ))%0A                .collect(Collectors.toList());%0A        %7D catch (Exception ex) %7B%0A            LOG.warn(%22Could not parse '%7B%7D' as json (exception: %7B%7D)%22, json, ex.getClass().getName());%0A            throw ex;%0A        %7D
 %0A   

Handle html response like «504 server did not respond in time»