11package com .park .utmstack .util .chart_builder .elasticsearch_dsl .responses .impl .coordinate_map ;
22
3+ import com .fasterxml .jackson .databind .JsonNode ;
34import com .fasterxml .jackson .databind .node .ObjectNode ;
45import com .park .utmstack .domain .chart_builder .UtmVisualization ;
56import com .park .utmstack .domain .chart_builder .types .aggregation .AggregationType ;
67import com .park .utmstack .domain .chart_builder .types .aggregation .Bucket ;
78import com .park .utmstack .domain .chart_builder .types .aggregation .Metric ;
8- import com .park .utmstack .domain .ip_info .GeoIp ;
9- import com .park .utmstack .service .ip_info .IpInfoService ;
9+ import com .park .utmstack .util .chart_builder .elasticsearch_dsl .requests .RequestDsl ;
1010import com .park .utmstack .util .chart_builder .elasticsearch_dsl .responses .ResponseParser ;
11- import com .park .utmstack .util .exceptions .UtmIpInfoException ;
1211import com .utmstack .opensearch_connector .parsers .TermAggregateParser ;
1312import com .utmstack .opensearch_connector .types .BucketAggregation ;
1413import com .utmstack .opensearch_connector .types .SearchSqlResponse ;
14+ import org .opensearch .client .opensearch ._types .aggregations .Aggregate ;
15+ import org .opensearch .client .opensearch ._types .aggregations .TopHitsAggregate ;
1516import org .opensearch .client .opensearch .core .SearchResponse ;
1617import org .slf4j .Logger ;
1718import org .slf4j .LoggerFactory ;
2728@ Component
2829public class ResponseParserForCoordinateMapChart implements ResponseParser <CoordinateMapChartResult > {
2930 private static final String CLASSNAME = "ResponseParserForCoordinateMapChart" ;
31+ private static final List <String > GEO_PREFIXES = List .of ("origin" , "source" , "destination" );
3032
3133 private final Logger log = LoggerFactory .getLogger (ResponseParserForCoordinateMapChart .class );
3234
33- private final IpInfoService ipInfoService ;
34-
35- public ResponseParserForCoordinateMapChart (IpInfoService ipInfoService ) {
36- this .ipInfoService = ipInfoService ;
37- }
38-
3935 @ Override
4036 public List <CoordinateMapChartResult > parse (UtmVisualization visualization , SearchResponse <ObjectNode > result ) {
4137 final String ctx = CLASSNAME + ".parse" ;
@@ -53,20 +49,13 @@ public List<CoordinateMapChartResult> parse(UtmVisualization visualization, Sear
5349
5450
5551 for (BucketAggregation entry : entries ) {
56- GeoIp ipV4Info ;
57- try {
58- ipV4Info = ipInfoService .getIpInfo (entry .getKey ());
59-
60- if (ipV4Info == null )
61- continue ;
62- } catch (UtmIpInfoException e ) {
63- log .error (e .getMessage ());
52+ Double [] latLon = extractLatLongFromTopHits (entry .getSubAggregations ());
53+ if (latLon == null )
6454 continue ;
65- }
6655
6756 CoordinateMapChartResult value = new CoordinateMapChartResult ();
6857 value .setName (entry .getKey ());
69- value .addLatitude (ipV4Info . getLatitude ()) .addLongitude (ipV4Info . getLongitude () );
58+ value .addLatitude (latLon [ 0 ]) .addLongitude (latLon [ 1 ] );
7059
7160 switch (metric .getAggregation ()) {
7261 case COUNT :
@@ -140,20 +129,14 @@ public List<CoordinateMapChartResult> parse(UtmVisualization visualization, Sear
140129 }
141130 if (!StringUtils .hasText (ip )) continue ;
142131
143- GeoIp ipInfo ;
144- try {
145- ipInfo = ipInfoService .getIpInfo (ip );
146- if (ipInfo == null ) continue ;
147- } catch (UtmIpInfoException e ) {
148- log .error (e .getMessage ());
149- continue ;
150- }
132+ Double [] latLon = extractLatLongFromRow (row );
133+ if (latLon == null ) continue ;
151134
152135 CoordinateMapChartResult chartResult = new CoordinateMapChartResult ();
153136 chartResult .setName (ip );
154137 chartResult .setValue (new Double [] {
155- ipInfo . getLatitude () ,
156- ipInfo . getLongitude () ,
138+ latLon [ 0 ] ,
139+ latLon [ 1 ] ,
157140 (double ) i
158141 });
159142
@@ -165,4 +148,59 @@ public List<CoordinateMapChartResult> parse(UtmVisualization visualization, Sear
165148 throw new RuntimeException (ctx + ": " + e .getMessage (), e );
166149 }
167150 }
151+
152+ private Double [] extractLatLongFromTopHits (Map <String , Aggregate > subAggs ) {
153+ if (subAggs == null ) return null ;
154+ Aggregate geoAgg = subAggs .get (RequestDsl .GEO_HIT_AGG );
155+ if (geoAgg == null || !geoAgg .isTopHits ()) return null ;
156+ TopHitsAggregate topHits = geoAgg .topHits ();
157+ if (topHits .hits () == null || topHits .hits ().hits ().isEmpty ()) return null ;
158+ var hit = topHits .hits ().hits ().get (0 );
159+ if (hit .source () == null ) return null ;
160+ try {
161+ ObjectNode source = hit .source ().to (ObjectNode .class );
162+ return extractLatLongFromJson (source );
163+ } catch (Exception e ) {
164+ log .warn ("Failed to deserialize top_hits source for geolocation: {}" , e .getMessage ());
165+ return null ;
166+ }
167+ }
168+
169+ private Double [] extractLatLongFromJson (ObjectNode source ) {
170+ if (source == null ) return null ;
171+ for (String prefix : GEO_PREFIXES ) {
172+ JsonNode geo = source .path (prefix ).path ("geolocation" );
173+ JsonNode lat = geo .path ("latitude" );
174+ JsonNode lon = geo .path ("longitude" );
175+ if (lat .isNumber () && lon .isNumber ()) {
176+ return new Double []{lat .asDouble (), lon .asDouble ()};
177+ }
178+ }
179+ return null ;
180+ }
181+
182+ private Double [] extractLatLongFromRow (Map <String , Object > row ) {
183+ Double lat = null ;
184+ Double lon = null ;
185+ for (Map .Entry <String , Object > e : row .entrySet ()) {
186+ if (e .getValue () == null ) continue ;
187+ String key = e .getKey ();
188+ if (lat == null && (key .endsWith (".geolocation.latitude" ) || key .equals ("latitude" ))) {
189+ lat = toDouble (e .getValue ());
190+ } else if (lon == null && (key .endsWith (".geolocation.longitude" ) || key .equals ("longitude" ))) {
191+ lon = toDouble (e .getValue ());
192+ }
193+ }
194+ if (lat == null || lon == null ) return null ;
195+ return new Double []{lat , lon };
196+ }
197+
198+ private Double toDouble (Object val ) {
199+ if (val instanceof Number ) return ((Number ) val ).doubleValue ();
200+ try {
201+ return Double .parseDouble (val .toString ());
202+ } catch (NumberFormatException e ) {
203+ return null ;
204+ }
205+ }
168206}
0 commit comments