import type { FileLayer } from '@elastic/ems-client' ; import { getEmsFileLayers } from '../util' ; export interface SampleValuesConfig { sampleValues ? : Array < string | number > ; sampleValuesColumnName ? : string ; } export interface EMSTermJoinConfig { layerId : string ; field : string ; } interface UniqueMatch { config : EMSTermJoinConfig ; count : number ; } interface FileLayerFieldShim { id : string ; values ? : string [ ] ; regex ? : string ; alias ? : string [ ] ; } export async function suggestEMSTermJoinConfig ( sampleValuesConfig ) { const matches = [ ] ; if ( sampleValuesConfig . sampleValuesColumnName ) { const matchesBasedOnColumnName = await suggestByName ( sampleValuesConfig . sampleValuesColumnName , sampleValuesConfig . sampleValues ) ; matches . push ( ... matchesBasedOnColumnName ) ; } if ( sampleValuesConfig . sampleValues && sampleValuesConfig . sampleValues . length ) { const matchesBasedOnIds = await suggestByIdValues ( sampleValuesConfig . sampleValues ) ; matches . push ( ... matchesBasedOnIds ) ; } const uniqMatches = matches . reduce ( ( accum , match ) => { const found = accum . find ( ( m ) => { return m . config . layerId === match . layerId && m . config . field === match . layerId ; } ) ; if ( found ) { found . count += 1 ; } else { accum . push ( { config : match , count : 1 , } ) ; } return accum ; } , [ ] ) ; uniqMatches . sort ( ( a , b ) => { return b . count - a . count ; } ) ; return uniqMatches . length ? uniqMatches [ 0 ] . config : null ; } async function suggestByName ( columnName , sampleValues ? ) { const fileLayers = await getEmsFileLayers ( ) ; const matches = [ ] ; fileLayers . forEach ( ( fileLayer ) => { const emsFields = fileLayer . getFields ( ) ; emsFields . forEach ( ( emsField ) => { if ( ! emsField . alias || ! emsField . alias . length ) { return ; } const emsConfig = { layerId : fileLayer . getId ( ) , field : emsField . id , } ; emsField . alias . forEach ( ( alias ) => { const regex = new RegExp ( alias , 'i' ) ; const nameMatchesAlias = ! ! columnName . match ( regex ) ; let isMatch ; if ( sampleValues ) { if ( emsField . values && emsField . values . length ) { isMatch = nameMatchesAlias && allSamplesMatch ( sampleValues , emsField . values ) ; } else { isMatch = false ; } } else { isMatch = nameMatchesAlias ; } if ( isMatch ) { matches . push ( emsConfig ) ; } } ) ; } ) ; } ) ; return matches ; } function allSamplesMatch ( sampleValues , ids ) { for ( let j = 0 ; j < sampleValues . length ; j ++ ) { const sampleValue = sampleValues [ j ] . toString ( ) ; if ( ! ids . includes ( sampleValue ) ) { return false ; } } return true ; } async function suggestByIdValues ( sampleValues ) { const matches = [ ] ; const fileLayers = await getEmsFileLayers ( ) ; fileLayers . forEach ( ( fileLayer ) => { const emsFields = fileLayer . getFields ( ) ; emsFields . forEach ( ( emsField ) => { if ( ! emsField . values || ! emsField . values . length ) { return ; } const emsConfig = { layerId : fileLayer . getId ( ) , field : emsField . id , } ; if ( allSamplesMatch ( sampleValues , emsField . values ) ) { matches . push ( emsConfig ) ; } } ) ; } ) ; return matches ; }