Example #1
0
  @Override
  public boolean matches(JsonValue value) throws Exception {
    if (!(value instanceof JsonRecord)) {
      return false;
    }
    JsonRecord rec = (JsonRecord) value;

    // assumption: field names are sorted
    int nr = rec.size(); // number of fields in record
    int ns = fieldsByName.length; // number of fields in schema
    int pr = 0; // current field in record
    int ps = 0; // current field in schema

    // zip join
    Iterator<Entry<JsonString, JsonValue>> recIt = rec.iteratorSorted();
    Entry<JsonString, JsonValue> recEntry = null;
    if (nr > 0) recEntry = recIt.next();
    while (pr < nr && ps < ns) {
      Field schemaField = fieldsByName[ps];
      JsonString recordFieldName = recEntry.getKey();

      // compare
      int cmp = schemaField.getName().compareTo(recordFieldName);

      if (cmp < 0) {
        // field is in schema but not in record
        if (!schemaField.isOptional) {
          return false;
        }
        ps++;
      } else if (cmp == 0) {
        // field is schema and in record
        if (!schemaField.getSchema().matches(recEntry.getValue())) {
          return false;
        }
        ps++;
        pr++;
        if (pr < nr) {
          assert recIt.hasNext();
          recEntry = recIt.next();
        }
      } else {
        // field is not in schema but in record
        if (additional == null || !additional.matches(recEntry.getValue())) {
          return false;
        }
        pr++;
        if (pr < nr) {
          assert recIt.hasNext();
          recEntry = recIt.next();
        }
      }
    }

    // only one of them still has fields, i.e., the while loops are exclusive
    while (pr < nr) {
      // there are fields left in the record
      if (additional == null || !additional.matches(recEntry.getValue())) {
        return false;
      }
      pr++;
      if (pr < nr) {
        assert recIt.hasNext();
        recEntry = recIt.next();
      }
    }
    assert !recIt.hasNext();
    while (ps < ns) {
      // therea are fields left in the schema
      if (!fieldsByName[ps].isOptional) {
        return false;
      }
      ps++;
    }

    // everything ok
    return true;
  }