package org.rzats.jsonschema;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectWriter;
import com.github.fge.jackson.JsonLoader;
import com.github.fge.jsonschema.core.exceptions.ProcessingException;
import com.github.fge.jsonschema.core.report.ProcessingReport;
import com.github.fge.jsonschema.main.JsonSchema;
import com.github.fge.jsonschema.main.JsonSchemaFactory;
import org.rocksdb.Options;
import org.rocksdb.RocksDB;
import org.rocksdb.RocksDBException;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;
import java.nio.file.Paths;

@RestController
public class JsonValidatorController {
    private static final String JSON_CONTENT_TYPE = "application/json";

    private static Options createDatabaseOptions() {
        return new Options().setCreateIfMissing(true);
    }

    private static RocksDB createDatabaseConnection(Options databaseOptions) throws RocksDBException {
        return RocksDB.open(databaseOptions, Paths.get("").toAbsolutePath().toString() + "/rocksdb");
    }

    @RequestMapping(value = "/error")
    public JsonValidatorResponse error() {
        return new JsonValidatorResponse(null, null, "error", "errorString");
    }

    @RequestMapping(method=RequestMethod.GET, value="/schema/{SCHEMAID}", produces=JSON_CONTENT_TYPE)
    public String downloadSchema(@PathVariable(value = "SCHEMAID") String id) {
        try (Options databaseOptions = createDatabaseOptions();
        RocksDB databaseConnection = createDatabaseConnection(databaseOptions)){
            byte[] schema = databaseConnection.get(id.getBytes());
            String schemaString = new String(schema);
            return schemaString;
        } catch (RocksDBException e) {
            JsonValidatorResponse response = new JsonValidatorResponse("downloadSchema", id, "success", null);
            ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter();
            String json = null;
            try {
                json = ow.writeValueAsString(response);
            } catch (JsonProcessingException e1) {
                e1.printStackTrace();
            }
            return json;
        }

    }

    @RequestMapping(method= RequestMethod.POST, value="/schema/{SCHEMAID}", consumes = JSON_CONTENT_TYPE,produces=JSON_CONTENT_TYPE)
    public JsonValidatorResponse uploadSchema(@PathVariable(value = "SCHEMAID") String id, @RequestBody String schema) {
        try (Options databaseOptions = createDatabaseOptions();
             RocksDB databaseConnection = createDatabaseConnection(databaseOptions)){
            databaseConnection.put(id.getBytes(), schema.getBytes());
            return new JsonValidatorResponse("uploadSchema", id, "success", null);
        } catch (RocksDBException e) {
            e.printStackTrace();
        }
        return null;
    }

    @RequestMapping(method= RequestMethod.POST, value="/validate/{SCHEMAID}", consumes=JSON_CONTENT_TYPE, produces=JSON_CONTENT_TYPE)
    public JsonValidatorResponse validateDocument(@PathVariable(value = "SCHEMAID") String id, @RequestBody String json) {
        try (Options databaseOptions = createDatabaseOptions();
             RocksDB databaseConnection = createDatabaseConnection(databaseOptions)){
            byte[] schemaBytes = databaseConnection.get(id.getBytes());
            String schemaString = new String(schemaBytes);
            JsonNode schemaNode = JsonLoader.fromString(schemaString);
            JsonNode documentNode = JsonLoader.fromString(json);

            JsonSchemaFactory factory = JsonSchemaFactory.byDefault();

            JsonSchema schema = factory.getJsonSchema(schemaNode);
            ProcessingReport report = schema.validate(documentNode);

            if (report.isSuccess()) {
                return new JsonValidatorResponse("validateDocument", id, "success", null);
            } else {
                return new JsonValidatorResponse("validateDocument", id, "error", report.toString());
            }
        } catch (RocksDBException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ProcessingException e) {
            e.printStackTrace();
        }
        return new JsonValidatorResponse("validateDocument", id, "success", json);

    }
}

@@ -517,16 +517,84 @@
 actory;%0A
+import org.apache.catalina.servlet4preview.http.HttpServletRequest;%0A
 import o
@@ -694,46 +694,395 @@
 rg.s
-pringframework.web.bind.annotation.*;%0A
+lf4j.Logger;%0Aimport org.slf4j.LoggerFactory;%0Aimport org.springframework.boot.autoconfigure.web.ErrorController;%0Aimport org.springframework.web.bind.annotation.*;%0Aimport org.springframework.web.context.request.RequestAttributes;%0Aimport org.springframework.web.context.request.ServletRequestAttributes;%0A%0Aimport javax.servlet.http.HttpServlet;%0Aimport javax.servlet.http.HttpServletResponse;
 %0Aimp
@@ -1133,16 +1133,38 @@
 e.Paths;
+%0Aimport java.util.Map;
 %0A%0A@RestC
@@ -1210,16 +1210,42 @@
 troller 
+implements ErrorController
 %7B%0A    pr
@@ -1267,52 +1267,324 @@
 nal 
-String JSON_CONTENT_TYPE = %22application/json
+Logger logger = LoggerFactory.getLogger(JsonValidatorController.class);%0A    private static final String JSON_CONTENT_TYPE = %22application/json%22;%0A    private static final String ERROR_PATH = %22/error%22;%0A    private static final String SCHEMA_PATH = %22/schema/%22;%0A    private static final String VALIDATE_PATH = %22/validate/
 %22;%0A%0A
@@ -1938,24 +1938,26 @@
 value = 
-%22/error%22
+ERROR_PATH
 )%0A    pu
@@ -1989,16 +1989,44 @@
 e error(
+HttpServletResponse response
 ) %7B%0A    
@@ -2086,22 +2086,111 @@
 or%22,
- %22errorString%22
+%0A                String.format(%22Invalid request (error code %25s)%22, String.valueOf(response.getStatus()))
 );%0A 
@@ -2243,33 +2243,40 @@
 .GET, value=
-%22/schema/
+ SCHEMA_PATH + %22
 %7BSCHEMAID%7D%22,
@@ -3225,25 +3225,32 @@
 , value=
-%22/schema/
+ SCHEMA_PATH + %22
 %7BSCHEMAI
@@ -3899,27 +3899,33 @@
 , value=
-%22/validate/
+VALIDATE_PATH + %22
 %7BSCHEMAI
@@ -5314,11 +5314,96 @@
 ;%0A%0A    %7D
+%0A%0A    @Override%0A    public String getErrorPath() %7B%0A        return ERROR_PATH;%0A    %7D%0A%0A
 %0A%7D%0A

Add basic error handling (invalid request)