public Optional apply()

in baremaps-core/src/main/java/org/apache/baremaps/iploc/IpLocMapper.java [69:182]


  public Optional<IpLocObject> apply(RpslObject rpslObject) {
    try {
      if (rpslObject.attributes().isEmpty()) {
        return Optional.empty();
      }

      if (!RpslUtils.isInetnum(rpslObject)) {
        return Optional.empty();
      }

      var inetnum = rpslObject.attributes().get(0);
      var ipRange = IpResourceRange.parse(inetnum.value());
      var start = InetAddresses.forString(ipRange.getStart().toString());
      var end = InetAddresses.forString(ipRange.getEnd().toString());
      var inetRange = new InetRange(start, end);

      var attributes = rpslObject.asMap();

      // Use a default name if there is no netname
      var network = String.join(", ", attributes.getOrDefault("netname", List.of("unknown")));
      var geoloc = attributes.containsKey("geoloc")
          ? String.join(", ", attributes.getOrDefault("geoloc", List.of()))
          : null;
      var country = attributes.containsKey("country")
          ? String.join(", ", attributes.getOrDefault("country", List.of()))
          : null;
      var source = attributes.containsKey("source")
          ? String.join(", ", attributes.getOrDefault("source", List.of()))
          : null;

      // If there is a geoloc field, we use the latitude and longitude provided
      if (attributes.containsKey("geoloc")) {
        var location = stringToCoordinate(geoloc);
        if (location.isPresent()) {
          return Optional.of(new IpLocObject(
              geoloc,
              inetRange,
              location.get(),
              network,
              country,
              source,
              IpLocPrecision.GEOLOC));
        }
      }

      // If there is a country, we use that with a cherry-picked list of fields to query the
      // geocoder with confidence to find a relevant precise location,
      // in the worst case the error is within a country
      List<String> searchedFields = List.of("descr", "netname");
      // at least one of a searchedField is present and the country is present.
      if (attributes.keySet().stream().anyMatch(searchedFields::contains)
          && attributes.containsKey("country")) {
        // build a query text string out of the cherry-picked fields
        var queryTextBuilder = new StringBuilder();
        for (String field : searchedFields) {
          var value = attributes.containsKey(field)
              ? String.join(", ", attributes.getOrDefault(field, List.of()))
              : null;
          if (!Strings.isNullOrEmpty(value)) {
            queryTextBuilder.append(attributes.get(field)).append(" ");
          }
        }

        String queryText = queryTextBuilder.toString();
        var location = findLocationInCountry(queryText, country);
        if (location.isPresent()) {
          return Optional.of(new IpLocObject(
              queryText,
              inetRange,
              location.get(),
              network,
              country,
              source,
              IpLocPrecision.GEOCODER));
        }
      }

      // If there is a country get the location of country
      if (attributes.containsKey("country")) {
        var location = findCountryLocation(country);
        if (location.isPresent()) {
          return Optional.of(new IpLocObject(
              country,
              inetRange,
              location.get(),
              network,
              country,
              source,
              IpLocPrecision.COUNTRY));
        }
      }

      return Optional.of(new IpLocObject(
          null,
          inetRange,
          new Coordinate(),
          network,
          null,
          source,
          IpLocPrecision.WORLD));
    } catch (Exception e) {
      logger.warn("Error while mapping RPSL object to IP loc object", e);
      logger.warn("RPSL object attributes:");
      rpslObject.attributes().forEach(attribute -> {
        var name = attribute.name();
        var value = attribute.value();
        if (value.length() > 100) {
          value = value.substring(0, 100).concat("...");
        }
        logger.warn("  {} = {}", name, value);
      });
      return Optional.empty();
    }
  }