@Override
  public S merge(@Nullable S parentType) {
    if (parentType == null) {
      //noinspection unchecked
      return (S) this;
    }

    super.merge(parentType);

    if (_minimum == null) {
      _minimum = parentType.getMinimum();
    }

    if (_minimumExclusive == null) {
      _minimumExclusive = parentType.getMinimumExclusive();
    }

    if (_maximum == null) {
      _maximum = parentType.getMaximum();
    }

    if (_maximumExclusive == null) {
      _maximumExclusive = parentType.getMaximumExclusive();
    }

    if (_divisibleBy == null) {
      _divisibleBy = parentType.getDivisibleBy();
    }

    //noinspection unchecked
    return (S) this;
  }
  @Override
  public void validate(JSONSchema schema, Object obj, String path, ValidationResults results) {
    super.validate(schema, obj, path, results);

    Number number = (Number) obj;
    if (_minimum != null) {
      int result = NumberComparator.INSTANCE.compare(number, _minimum);
      if (isMinimumExclusive()) {
        if (!(result > 0)) {
          results.addResult(
              new ValidationResult()
                  .type(ResultType.CONSTRAINT_VIOLATION)
                  .path(path)
                  .message("Value must be > " + _minimum + ": " + number));
        }
      } else {
        if (!(result >= 0)) {
          results.addResult(
              new ValidationResult()
                  .type(ResultType.CONSTRAINT_VIOLATION)
                  .path(path)
                  .message("Value must be >= " + _minimum + ": " + number));
        }
      }
    }

    if (_maximum != null) {
      int result = NumberComparator.INSTANCE.compare(number, _maximum);
      if (isMaximumExclusive()) {
        if (!(result < 0)) {
          results.addResult(
              new ValidationResult()
                  .type(ResultType.CONSTRAINT_VIOLATION)
                  .path(path)
                  .message("Value must be < " + _maximum + ": " + number));
        }
      } else {
        if (!(result <= 0)) {
          results.addResult(
              new ValidationResult()
                  .type(ResultType.CONSTRAINT_VIOLATION)
                  .path(path)
                  .message("Value must be <= " + _maximum + ": " + number));
        }
      }
    }

    if (_divisibleBy != null) {
      if (_divisibleBy instanceof Integer && number instanceof Integer) {
        int divInt = _divisibleBy.intValue();
        int valueInt = number.intValue();
        if (valueInt % divInt != 0) {
          results.addResult(
              new ValidationResult()
                  .type(ResultType.CONSTRAINT_VIOLATION)
                  .path(path)
                  .message("Value must be divisible by " + _divisibleBy + ": " + number));
        }
      } else {
        double divDouble = _divisibleBy.doubleValue();
        double valueDouble = number.doubleValue();
        double result = valueDouble / divDouble;
        if (Math.floor(result) != result) {
          results.addResult(
              new ValidationResult()
                  .type(ResultType.CONSTRAINT_VIOLATION)
                  .path(path)
                  .message("Value must be divisible by " + _divisibleBy + ": " + number));
        }
      }
    }
  }