Package com.mockey.ui

Source Code of com.mockey.ui.JsonSchemaUtil

package com.mockey.ui;

import java.io.IOException;

import com.fasterxml.jackson.core.JsonLocation;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.github.fge.jsonschema.JsonValidators;
import com.github.fge.jsonschema.constants.ParseError;
import com.github.fge.jsonschema.constants.ValidateResponse;
import com.github.fge.jsonschema.main.JsonValidator;
import com.github.fge.jsonschema.report.ProcessingReport;
import com.github.fge.jsonschema.util.AsJson;
import com.github.fge.jsonschema.util.JsonLoader;
import com.google.common.annotations.VisibleForTesting;
import com.mockey.ServiceException;

public class JsonSchemaUtil {

  public static boolean validData(final String rawSchema, final String rawData) {
    boolean valid = false;
    try {
      final ProcessingReport report = buildReport(rawSchema, rawData, true, false);
      valid = report.isSuccess();
    } catch (ServiceException e) {
      return valid;
    } catch (IOException e) {
      return valid;
    }

    return valid;
  }

  /*
   * Build the response. When we arrive here, we are guaranteed that we have
   * the needed elements.
   */
  @VisibleForTesting
  public static JsonNode buildResult(final String rawSchema,
      final String rawData, final boolean useV3, final boolean useId)
      throws IOException {
    final ObjectNode ret = JsonNodeFactory.instance.objectNode();
    try {
      final ProcessingReport report = buildReport(rawSchema, rawData,
          useV3, useId);
      final boolean success = report.isSuccess();
      ret.put(ValidateResponse.VALID, success);
      ret.put(ValidateResponse.RESULTS, ((AsJson) report).asJson());
      return ret;

    } catch (ServiceException e) {
      return ret;
    }

  }

  private static ProcessingReport buildReport(final String rawSchema,
      final String rawData, final boolean useV3, final boolean useId)
      throws IOException, ServiceException {
    final ObjectNode ret = JsonNodeFactory.instance.objectNode();

    final boolean invalidSchema = fillWithData(ret,
        ValidateResponse.SCHEMA, ValidateResponse.INVALID_SCHEMA,
        rawSchema);
    final boolean invalidData = fillWithData(ret, ValidateResponse.DATA,
        ValidateResponse.INVALID_DATA, rawData);
    if (invalidSchema || invalidData) {
      throw new ServiceException("Schema valid? " + invalidSchema
          + " Data valid?" + invalidData);
    }
    final JsonNode schemaNode = ret.remove(ValidateResponse.SCHEMA);
    final JsonNode data = ret.remove(ValidateResponse.DATA);
    final JsonValidator validator = JsonValidators.withOptions(useV3, useId);
    final ProcessingReport report = validator.validateUnchecked(schemaNode,
        data);

    return report;
  }

  /*
   * We have to use that since Java is not smart enough to detect that
   * sometimes, a variable is initialized in all paths.
   *
   * This returns true if the data is invalid.
   */
  private static boolean fillWithData(final ObjectNode node,
      final String onSuccess, final String onFailure, final String raw)
      throws IOException {
    try {
      node.put(onSuccess, JsonLoader.fromString(raw));
      return false;
    } catch (JsonProcessingException e) {
      node.put(onFailure, buildParsingError(e, raw.contains("\r\n")));
      return true;
    }
  }

  private static JsonNode buildParsingError(final JsonProcessingException e,
      final boolean crlf) {
    final JsonLocation location = e.getLocation();
    final ObjectNode ret = JsonNodeFactory.instance.objectNode();

    /*
     * Unfortunately, for some reason, Jackson botches the column number in
     * its JsonPosition -- I cannot figure out why exactly. However, it does
     * have a correct offset into the buffer.
     *
     * The problem is that if the input has CR/LF line terminators, its
     * offset will be "off" by the number of lines minus 1 with regards to
     * what JavaScript sees as positions in text areas. Make the necessary
     * adjustments so that the caret jumps at the correct position in this
     * case.
     */
    final int lineNr = location.getLineNr();
    int offset = (int) location.getCharOffset();
    if (crlf)
      offset = offset - lineNr + 1;
    ret.put(ParseError.LINE, lineNr);
    ret.put(ParseError.OFFSET, offset);

    // Finally, put the message
    ret.put(ParseError.MESSAGE, e.getOriginalMessage());
    return ret;
  }
}
TOP

Related Classes of com.mockey.ui.JsonSchemaUtil

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.