123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217 |
- import { Geometry } from 'ol/geom';
- import {
- FrameGeometrySource,
- FrameGeometrySourceMode,
- FieldMatcher,
- getFieldMatcher,
- FieldMatcherID,
- DataFrame,
- Field,
- getFieldDisplayName,
- FieldType,
- } from '@grafana/data';
- import { getGeoFieldFromGazetteer, pointFieldFromGeohash, pointFieldFromLonLat } from '../format/utils';
- import { getGazetteer, Gazetteer } from '../gazetteer/gazetteer';
- export type FieldFinder = (frame: DataFrame) => Field | undefined;
- function getFieldFinder(matcher: FieldMatcher): FieldFinder {
- return (frame: DataFrame) => {
- for (const field of frame.fields) {
- if (matcher(field, frame, [])) {
- return field;
- }
- }
- return undefined;
- };
- }
- function matchLowerNames(names: Set<string>): FieldFinder {
- return (frame: DataFrame) => {
- for (const field of frame.fields) {
- if (names.has(field.name.toLowerCase())) {
- return field;
- }
- const disp = getFieldDisplayName(field, frame);
- if (names.has(disp)) {
- return field;
- }
- }
- return undefined;
- };
- }
- export interface LocationFieldMatchers {
- mode: FrameGeometrySourceMode;
- // Field mappings
- geohash: FieldFinder;
- latitude: FieldFinder;
- longitude: FieldFinder;
- h3: FieldFinder;
- wkt: FieldFinder;
- lookup: FieldFinder;
- geo: FieldFinder;
- gazetteer?: Gazetteer;
- }
- const defaultMatchers: LocationFieldMatchers = {
- mode: FrameGeometrySourceMode.Auto,
- geohash: matchLowerNames(new Set(['geohash'])),
- latitude: matchLowerNames(new Set(['latitude', 'lat'])),
- longitude: matchLowerNames(new Set(['longitude', 'lon', 'lng'])),
- h3: matchLowerNames(new Set(['h3'])),
- wkt: matchLowerNames(new Set(['wkt'])),
- lookup: matchLowerNames(new Set(['lookup'])),
- geo: (frame: DataFrame) => frame.fields.find((f) => f.type === FieldType.geo),
- };
- export async function getLocationMatchers(src?: FrameGeometrySource): Promise<LocationFieldMatchers> {
- const info: LocationFieldMatchers = {
- ...defaultMatchers,
- mode: src?.mode ?? FrameGeometrySourceMode.Auto,
- };
- switch (info.mode) {
- case FrameGeometrySourceMode.Geohash:
- if (src?.geohash) {
- info.geohash = getFieldFinder(getFieldMatcher({ id: FieldMatcherID.byName, options: src.geohash }));
- }
- break;
- case FrameGeometrySourceMode.Lookup:
- if (src?.lookup) {
- info.lookup = getFieldFinder(getFieldMatcher({ id: FieldMatcherID.byName, options: src.lookup }));
- }
- info.gazetteer = await getGazetteer(src?.gazetteer);
- break;
- case FrameGeometrySourceMode.Coords:
- if (src?.latitude) {
- info.latitude = getFieldFinder(getFieldMatcher({ id: FieldMatcherID.byName, options: src.latitude }));
- }
- if (src?.longitude) {
- info.longitude = getFieldFinder(getFieldMatcher({ id: FieldMatcherID.byName, options: src.longitude }));
- }
- break;
- }
- return info;
- }
- export interface LocationFields {
- mode: FrameGeometrySourceMode;
- // Field mappings
- geohash?: Field;
- latitude?: Field;
- longitude?: Field;
- h3?: Field;
- wkt?: Field;
- lookup?: Field;
- geo?: Field<Geometry>;
- }
- export function getLocationFields(frame: DataFrame, location: LocationFieldMatchers): LocationFields {
- const fields: LocationFields = {
- mode: location.mode ?? FrameGeometrySourceMode.Auto,
- };
- // Find the best option
- if (fields.mode === FrameGeometrySourceMode.Auto) {
- fields.geo = location.geo(frame);
- if (fields.geo) {
- return fields;
- }
- fields.latitude = location.latitude(frame);
- fields.longitude = location.longitude(frame);
- if (fields.latitude && fields.longitude) {
- fields.mode = FrameGeometrySourceMode.Coords;
- return fields;
- }
- fields.geohash = location.geohash(frame);
- if (fields.geohash) {
- fields.mode = FrameGeometrySourceMode.Geohash;
- return fields;
- }
- fields.lookup = location.geohash(frame);
- if (fields.lookup) {
- fields.mode = FrameGeometrySourceMode.Lookup;
- return fields;
- }
- }
- switch (fields.mode) {
- case FrameGeometrySourceMode.Coords:
- fields.latitude = location.latitude(frame);
- fields.longitude = location.longitude(frame);
- break;
- case FrameGeometrySourceMode.Geohash:
- fields.geohash = location.geohash(frame);
- break;
- case FrameGeometrySourceMode.Lookup:
- fields.lookup = location.lookup(frame);
- break;
- }
- return fields;
- }
- export interface FrameGeometryField {
- field?: Field<Geometry | undefined>;
- warning?: string;
- derived?: boolean;
- }
- export function getGeometryField(frame: DataFrame, location: LocationFieldMatchers): FrameGeometryField {
- const fields = getLocationFields(frame, location);
- switch (fields.mode) {
- case FrameGeometrySourceMode.Auto:
- if (fields.geo) {
- return {
- field: fields.geo,
- };
- }
- return {
- warning: 'Unable to find location fields',
- };
- case FrameGeometrySourceMode.Coords:
- if (fields.latitude && fields.longitude) {
- return {
- field: pointFieldFromLonLat(fields.longitude, fields.latitude),
- derived: true,
- };
- }
- return {
- warning: 'Missing latitude/longitude fields',
- };
- case FrameGeometrySourceMode.Geohash:
- if (fields.geohash) {
- return {
- field: pointFieldFromGeohash(fields.geohash),
- derived: true,
- };
- }
- return {
- warning: 'Missing geohash field',
- };
- case FrameGeometrySourceMode.Lookup:
- if (fields.lookup) {
- if (location.gazetteer) {
- return {
- field: getGeoFieldFromGazetteer(location.gazetteer, fields.lookup),
- derived: true,
- };
- }
- return {
- warning: 'Gazetteer not found',
- };
- }
- return {
- warning: 'Missing lookup field',
- };
- }
- return { warning: 'unable to find geometry' };
- }
|