package org.openbel.belnetwork.api.util;

import com.fasterxml.jackson.databind.JsonNode;
import com.github.fge.jsonschema.core.report.ProcessingMessage;
import com.github.fge.jsonschema.core.report.ProcessingReport;

import java.util.Map;

/**
 * {@link FormatUtility} provides convenience methods for serializing / de-serializing
 * JSON Graph Format content.
 */
public class FormatUtility {

    /**
     * Return {@code value} as a {@link String} or {@code ""} if {@code key}
     * is not in {@code map}.
     *
     * @param key the {@link String} key
     * @param map the {@link Map} of {@link String} key / {@link Object} value;
     * cannot be {@code null}
     * @return {@code value} as a {@link String} or {@code ""}
     * @throws java.lang.NullPointerException when {@code map} is {@code null}
     */
    public static String getOrEmptyString(String key, Map<String, Object> map) {
        if (map == null) throw new NullPointerException("map cannot be null");

        Object value = map.get(key);

        return (value == null ? "" : value.toString());
    }

    /**
     * Return {@code value} as an {@link Integer} or {@code 0} if {@code key}
     * is not in {@code map}.
     *
     * @param key the {@link String} key
     * @param map the {@link Map} of {@link String} key / {@link Object} value;
     * cannot be {@code null}
     * @return {@code value} as an {@link Integer} or {@code 0}
     * @throws java.lang.NullPointerException when {@code map} is {@code null}
     */
    public static Integer getOrZero(String key, Map<String, Object> map) {
        if (map == null) throw new NullPointerException("map cannot be null");

        Object value = map.get(key);
        return (value == null ? 0 : (Integer) value);
    }

    /**
     * Return a {@link String} representing all schema validation messages.
     *
     * @param report the {@link ProcessingReport}; cannot be {@code null}
     * @return the {@link String} including all schema errors
     * @throws java.lang.NullPointerException when {@code report} is {@code null}
     */
    public static String getSchemaMessages(ProcessingReport report) {
        final StringBuilder b = new StringBuilder();

        for (ProcessingMessage m : report) {
            JsonNode data = m.asJson();
            for (JsonNode n : data.findValues("message")) {
                b.append(n.textValue()).append("\n");
            }
        }
        return b.toString();
    }

    private FormatUtility() {
        //static accessors only
    }
}

@@ -83,16 +83,70 @@
 onNode;%0A
+import com.fasterxml.jackson.databind.node.ArrayNode;%0A
 import c
@@ -265,16 +265,43 @@
 eport;%0A%0A
+import java.util.Iterator;%0A
 import j
@@ -2375,109 +2375,854 @@
     
-for (JsonNode n : data.findValues(%22message%22)) %7B%0A                b.append(n.textValue()).append(%22%5Cn%22);
+Iterator%3CMap.Entry%3CString, JsonNode%3E%3E entries = data.get(%22reports%22).fields();%0A            while(entries.hasNext()) %7B%0A                Map.Entry%3CString, JsonNode%3E entry = entries.next();%0A                String path = entry.getKey();%0A                if (!(entry.getValue() instanceof ArrayNode)) continue;%0A%0A                Iterator%3CJsonNode%3E items = entry.getValue().elements();%0A                while (items.hasNext()) %7B%0A                    JsonNode valNode = items.next();%0A                    if (valNode.has(%22instance%22) && valNode.get(%22instance%22).has(%22pointer%22)) %7B%0A                        path += valNode.get(%22instance%22).get(%22pointer%22).asText();%0A                    %7D%0A                    b.append(%22JSON Path: %22).append(path).append(%22%5Cn%22);%0A                    b.append(%22    %22).append(valNode.get(%22message%22).asText()).append(%22%5Cn%22);%0A                %7D
 %0A   

include JSON pointer with error messages