class NestedMetadata {

  public static ObjectNode attributesToMetadataPayload(Map<String, String> attributes) {
    final String namespace = attributes.get(Attribute.DOCUMENT_NAMESPACE);
    // Currently, every entry in metadata is a Map<String, String>, but we keep Object as the
    // value type to support future evolution of the metadata structure to include fields that
    // are not specifically Map<String, String>.
    ObjectNode metadata = Json.createObjectNode();
    metadata.set(GEO, geoFromAttributes(attributes));
    metadata.set(ISP, ispFromAttributes(attributes));
    metadata.set(Attribute.USER_AGENT, userAgentFromAttributes(attributes));
    metadata.set(HEADER, headersFromAttributes(attributes));
    if (Namespace.TELEMETRY.equals(namespace)) {
      metadata.set(Attribute.URI, uriFromAttributes(attributes));
    }
    IDENTIFYING_FIELDS.forEach(name -> Optional //
        .ofNullable(attributes.get(name)) //
        .ifPresent(value -> metadata.put(name, value)));
    ObjectNode payload = Json.createObjectNode();
    payload.set(FieldName.METADATA, metadata);
    TOP_LEVEL_STRING_FIELDS.forEach(name -> Optional //
        .ofNullable(attributes.get(name)) //
        .ifPresent(value -> payload.put(name, value)));
    TOP_LEVEL_INT_FIELDS.forEach(name -> Optional //
        .ofNullable(attributes.get(name)) //
        .flatMap(value -> {
          try {
            return Optional.of(Integer.parseInt(value));
          } catch (NumberFormatException e) {
            return Optional.empty();
          }
        }) //
        .ifPresent(value -> payload.put(name, value)));
    return payload;
  }

  private  NestedMetadata();

}