2024-02-23 13:30:05 +01:00
package eu.eudat.service.externalfetcher ;
2024-02-12 16:43:41 +01:00
import com.fasterxml.jackson.databind.JsonNode ;
import com.fasterxml.jackson.databind.ObjectMapper ;
import com.jayway.jsonpath.DocumentContext ;
import com.jayway.jsonpath.JsonPath ;
2024-02-16 16:42:01 +01:00
import com.jayway.jsonpath.PathNotFoundException ;
2024-02-19 14:50:01 +01:00
import eu.eudat.commons.JsonHandlingService ;
2024-02-26 18:47:20 +01:00
import eu.eudat.commons.enums.ExternalFetcherSourceType ;
2024-02-12 16:43:41 +01:00
import eu.eudat.convention.ConventionService ;
2024-02-13 11:22:11 +01:00
import eu.eudat.data.ReferenceEntity ;
2024-02-13 14:54:28 +01:00
import eu.eudat.model.Reference ;
import eu.eudat.model.referencedefinition.Field ;
2024-02-23 13:30:05 +01:00
import eu.eudat.service.externalfetcher.config.entities.* ;
import eu.eudat.service.externalfetcher.models.ExternalDataResult ;
import eu.eudat.service.externalfetcher.criteria.ExternalReferenceCriteria ;
2024-02-12 16:43:41 +01:00
import gr.cite.tools.exception.MyApplicationException ;
2024-02-28 17:48:46 +01:00
import io.netty.handler.ssl.SslContext ;
import io.netty.handler.ssl.SslContextBuilder ;
import io.netty.handler.ssl.util.InsecureTrustManagerFactory ;
2024-02-12 16:43:41 +01:00
import net.minidev.json.JSONArray ;
import org.slf4j.Logger ;
import org.slf4j.LoggerFactory ;
import org.springframework.beans.factory.annotation.Autowired ;
import org.springframework.core.ParameterizedTypeReference ;
import org.springframework.http.* ;
import org.springframework.http.client.reactive.ReactorClientHttpConnector ;
import org.springframework.http.codec.json.Jackson2JsonDecoder ;
import org.springframework.stereotype.Service ;
import org.springframework.web.reactive.function.client.WebClient ;
import reactor.netty.http.client.HttpClient ;
2024-02-28 17:48:46 +01:00
import javax.net.ssl.SSLException ;
2024-02-12 16:43:41 +01:00
import java.util.* ;
import java.util.stream.Collectors ;
@Service
2024-02-23 13:30:05 +01:00
public class ExternalFetcherServiceImpl implements ExternalFetcherService {
private static final Logger logger = LoggerFactory . getLogger ( ExternalFetcherServiceImpl . class ) ;
2024-02-12 16:43:41 +01:00
private WebClient webClient ;
private final ConventionService conventionService ;
2024-02-19 14:50:01 +01:00
private final JsonHandlingService jsonHandlingService ;
2024-02-12 16:43:41 +01:00
@Autowired
2024-02-23 13:30:05 +01:00
public ExternalFetcherServiceImpl ( ConventionService conventionService , JsonHandlingService jsonHandlingService ) {
2024-02-12 16:43:41 +01:00
this . conventionService = conventionService ;
2024-02-19 14:50:01 +01:00
this . jsonHandlingService = jsonHandlingService ;
2024-02-12 16:43:41 +01:00
}
2024-02-28 17:48:46 +01:00
private WebClient getWebClient ( ) {
2024-02-12 16:43:41 +01:00
if ( this . webClient = = null ) {
this . webClient = WebClient . builder ( ) . codecs ( clientCodecConfigurer - > {
clientCodecConfigurer . defaultCodecs ( ) . jackson2JsonDecoder ( new Jackson2JsonDecoder ( new ObjectMapper ( ) , MediaType . APPLICATION_JSON ) ) ;
clientCodecConfigurer . defaultCodecs ( ) . maxInMemorySize ( 2 * ( ( int ) Math . pow ( 1024 , 3 ) ) ) ; //GK: Why here???
}
) . clientConnector ( new ReactorClientHttpConnector ( HttpClient . create ( ) . followRedirect ( true ) ) ) . build ( ) ;
}
return webClient ;
}
@Override
2024-02-19 17:10:34 +01:00
public ExternalDataResult getExternalData ( List < SourceBaseConfiguration > sources , ExternalReferenceCriteria externalReferenceCriteria , String key ) {
2024-02-13 11:22:11 +01:00
List < SourceBaseConfiguration > apiSourcesToUse = sources ;
2024-02-12 16:43:41 +01:00
if ( ! this . conventionService . isNullOrEmpty ( key ) ) {
2024-02-28 17:48:46 +01:00
apiSourcesToUse = sources . stream ( ) . filter ( x - > x . getKey ( ) . equals ( key ) ) . collect ( Collectors . toList ( ) ) ;
2024-02-12 16:43:41 +01:00
}
if ( this . conventionService . isListNullOrEmpty ( apiSourcesToUse ) ) return new ExternalDataResult ( ) ;
apiSourcesToUse . sort ( Comparator . comparing ( SourceBaseConfiguration : : getOrdinal ) ) ;
2024-02-19 17:10:34 +01:00
return this . queryExternalData ( sources , externalReferenceCriteria ) ;
2024-02-12 16:43:41 +01:00
}
@Override
public Integer countExternalData ( List < SourceBaseConfiguration > sources , ExternalReferenceCriteria externalReferenceCriteria , String key ) {
2024-02-19 17:10:34 +01:00
return getExternalData ( sources , externalReferenceCriteria , key ) . getResults ( ) . size ( ) ;
2024-02-12 16:43:41 +01:00
}
2024-02-19 17:10:34 +01:00
private ExternalDataResult queryExternalData ( List < SourceBaseConfiguration > sources , ExternalReferenceCriteria externalReferenceCriteria ) {
2024-02-12 16:43:41 +01:00
ExternalDataResult results = new ExternalDataResult ( ) ;
if ( this . conventionService . isListNullOrEmpty ( sources ) ) return new ExternalDataResult ( ) ;
for ( SourceBaseConfiguration source : sources ) {
2024-02-26 18:47:20 +01:00
if ( source . getType ( ) = = null | | source . getType ( ) . equals ( ExternalFetcherSourceType . API ) ) {
2024-02-12 16:43:41 +01:00
try {
2024-02-13 14:54:28 +01:00
SourceExternalApiConfiguration < ResultsConfiguration < ResultFieldsMappingConfiguration > , AuthenticationConfiguration , QueryConfig < QueryCaseConfig > > apiSource = ( SourceExternalApiConfiguration ) source ;
// this.applyFunderToQuery(apiSource, externalReferenceCriteria);
2024-02-12 16:43:41 +01:00
String auth = null ;
2024-02-15 17:36:46 +01:00
if ( apiSource . getAuth ( ) ! = null & & apiSource . getAuth ( ) . getEnabled ( ) ! = null & & apiSource . getAuth ( ) . getEnabled ( ) ) {
2024-02-12 16:43:41 +01:00
auth = this . buildAuthentication ( apiSource . getAuth ( ) ) ;
}
2024-02-19 17:10:34 +01:00
results . addAll ( this . queryExternalData ( apiSource , externalReferenceCriteria , auth ) ) ;
2024-02-12 16:43:41 +01:00
} catch ( Exception e ) {
logger . error ( e . getLocalizedMessage ( ) , e ) ;
}
2024-02-26 18:47:20 +01:00
} else if ( source . getType ( ) ! = null & & source . getType ( ) . equals ( ExternalFetcherSourceType . STATIC ) ) {
2024-02-12 16:43:41 +01:00
SourceStaticOptionConfiguration < StaticOption > staticSource = ( SourceStaticOptionConfiguration ) source ;
2024-02-13 11:22:11 +01:00
results . addAll ( queryStaticData ( staticSource , externalReferenceCriteria ) ) ;
2024-02-12 16:43:41 +01:00
}
}
return results ;
}
2024-02-13 11:22:11 +01:00
private ExternalDataResult queryStaticData ( SourceStaticOptionConfiguration < StaticOption > staticSource , ExternalReferenceCriteria externalReferenceCriteria ) {
Map < String , String > result = new HashMap < > ( ) ;
Map < String , Object > rawData = new HashMap < > ( ) ;
for ( StaticOption staticOption : staticSource . getOptions ( ) ) {
if ( ! this . conventionService . isNullOrEmpty ( externalReferenceCriteria . getLike ( ) ) & & ! externalReferenceCriteria . getLike ( ) . toUpperCase ( ) . contains ( staticOption . getValue ( ) ) ) continue ;
result . put ( staticOption . getCode ( ) , staticOption . getValue ( ) ) ;
rawData . put ( staticOption . getCode ( ) , staticOption . getValue ( ) ) ;
result . put ( ReferenceEntity . KnownFields . SourceLabel , staticSource . getLabel ( ) ) ;
result . put ( ReferenceEntity . KnownFields . Key , staticSource . getKey ( ) ) ;
}
ExternalDataResult externalDataResult = new ExternalDataResult ( ) ;
externalDataResult . setRawData ( new ArrayList < > ( ) ) ;
externalDataResult . setResults ( new ArrayList < > ( ) ) ;
externalDataResult . getRawData ( ) . add ( rawData ) ;
externalDataResult . getResults ( ) . add ( result ) ;
return externalDataResult ;
}
2024-02-12 16:43:41 +01:00
private String buildAuthentication ( AuthenticationConfiguration authenticationConfiguration ) {
HttpMethod method ;
switch ( authenticationConfiguration . getAuthMethod ( ) ) {
case GET - > method = HttpMethod . GET ;
case POST - > method = HttpMethod . POST ;
default - > throw new MyApplicationException ( " unrecognized type " + authenticationConfiguration . getAuthMethod ( ) ) ;
}
Map < String , Object > response = this . getWebClient ( ) . method ( method ) . uri ( authenticationConfiguration . getAuthUrl ( ) )
. contentType ( MediaType . APPLICATION_JSON )
. bodyValue ( this . parseBodyString ( authenticationConfiguration . getAuthRequestBody ( ) ) )
. exchangeToMono ( mono - > mono . bodyToMono ( new ParameterizedTypeReference < Map < String , Object > > ( ) {
} ) ) . block ( ) ;
if ( response = = null ) throw new MyApplicationException ( " Authentication " + authenticationConfiguration . getAuthUrl ( ) + " failed " ) ;
return authenticationConfiguration . getType ( ) + " " + response . getOrDefault ( authenticationConfiguration . getAuthTokenPath ( ) , null ) ;
}
2024-02-13 14:54:28 +01:00
private String replaceLookupFieldQuery ( String query , ExternalReferenceCriteria externalReferenceCriteria , List < QueryConfig < QueryCaseConfig > > queryConfigs ) {
String finalQuery = query ;
String likeValue = this . conventionService . isNullOrEmpty ( externalReferenceCriteria . getLike ( ) ) ? " " : externalReferenceCriteria . getLike ( ) ;
List < Reference > referenceList = this . conventionService . isListNullOrEmpty ( externalReferenceCriteria . getDependencyReferences ( ) ) ? new ArrayList < > ( ) : externalReferenceCriteria . getDependencyReferences ( ) . stream ( )
. filter ( x - > x . getDefinition ( ) ! = null & & x . getType ( ) ! = null & & ! this . conventionService . isListNullOrEmpty ( x . getDefinition ( ) . getFields ( ) ) ) . toList ( ) ;
if ( this . conventionService . isListNullOrEmpty ( queryConfigs ) ) return query ;
for ( QueryConfig < ? > queryConfig : queryConfigs ) {
2024-02-13 17:16:59 +01:00
Comparator < QueryCaseConfig > queryCaseConfigcomparator = Comparator . comparing ( x - > x . getReferenceTypeId ( ) = = null ? 0 : 1 ) ; //Reference QueryCaseConfig are more important
QueryCaseConfig caseConfig = this . conventionService . isListNullOrEmpty ( queryConfig . getCases ( ) ) ? null : queryConfig . getCases ( ) . stream ( ) . filter ( x - >
( this . conventionService . isNullOrEmpty ( x . getLikePattern ( ) ) | | likeValue . matches ( x . getLikePattern ( ) ) )
& & ( ( x . getReferenceTypeId ( ) = = null & & this . conventionService . isNullOrEmpty ( x . getReferenceTypeSourceKey ( ) ) ) | | referenceList . stream ( ) . anyMatch ( y - > Objects . equals ( y . getType ( ) . getId ( ) , x . getReferenceTypeId ( ) ) & & Objects . equals ( y . getSource ( ) , x . getReferenceTypeSourceKey ( ) ) ) )
) . max ( queryCaseConfigcomparator ) . orElse ( null ) ;
2024-02-13 14:54:28 +01:00
String filterValue = queryConfig . getDefaultValue ( ) ;
if ( caseConfig ! = null ) {
filterValue = caseConfig . getValue ( ) ;
if ( caseConfig . getReferenceTypeId ( ) ! = null & & ! this . conventionService . isNullOrEmpty ( caseConfig . getReferenceTypeSourceKey ( ) ) ) {
Reference dependencyReference = referenceList . stream ( )
. filter ( x - > Objects . equals ( x . getType ( ) . getId ( ) , caseConfig . getReferenceTypeId ( ) ) & & Objects . equals ( x . getSource ( ) , caseConfig . getReferenceTypeSourceKey ( ) ) ) . findFirst ( ) . orElse ( null ) ;
if ( dependencyReference ! = null ) {
2024-02-13 17:16:59 +01:00
2024-02-13 14:54:28 +01:00
for ( Field field : dependencyReference . getDefinition ( ) . getFields ( ) ) {
filterValue = filterValue . replaceAll ( " { " + field . getCode ( ) + " } " , field . getValue ( ) ) ;
}
}
2024-02-13 17:16:59 +01:00
} else if ( ! this . conventionService . isNullOrEmpty ( likeValue ) ) {
if ( caseConfig . getSeparator ( ) ! = null ) {
String [ ] likes = likeValue . split ( caseConfig . getSeparator ( ) ) ;
for ( int i = 0 ; i < likes . length ; i + + ) {
filterValue = filterValue . replaceAll ( " \\ {like " + ( i + 1 ) + " } " , likes [ i ] ) ;
}
} else {
filterValue = filterValue . replaceAll ( " \\ {like} " , likeValue ) ;
2024-02-13 14:54:28 +01:00
}
} else {
2024-02-16 10:48:56 +01:00
filterValue = queryConfig . getDefaultValue ( ) = = null ? " " : queryConfig . getDefaultValue ( ) ;
2024-02-13 14:54:28 +01:00
}
2024-02-12 16:43:41 +01:00
}
2024-02-16 10:48:56 +01:00
finalQuery = finalQuery . replaceAll ( " \\ { " + queryConfig . getName ( ) + " } " , filterValue ) ;
2024-02-12 16:43:41 +01:00
}
2024-02-13 14:54:28 +01:00
2024-02-12 16:43:41 +01:00
return finalQuery ;
}
2024-02-13 14:54:28 +01:00
protected String replaceLookupFields ( String path , final SourceExternalApiConfiguration < ResultsConfiguration < ResultFieldsMappingConfiguration > , AuthenticationConfiguration , QueryConfig < QueryCaseConfig > > apiSource , ExternalReferenceCriteria externalReferenceCriteria ) {
2024-02-16 10:48:56 +01:00
if ( this . conventionService . isNullOrEmpty ( path ) ) return path ;
2024-02-12 16:43:41 +01:00
String completedPath = path ;
2024-02-16 10:48:56 +01:00
if ( ! this . conventionService . isListNullOrEmpty ( apiSource . getQueries ( ) ) ) {
completedPath = this . replaceLookupFieldQuery ( completedPath , externalReferenceCriteria , apiSource . getQueries ( ) ) ;
2024-02-12 16:43:41 +01:00
}
if ( ! this . conventionService . isNullOrEmpty ( externalReferenceCriteria . getPage ( ) ) ) completedPath = completedPath . replace ( " {page} " , externalReferenceCriteria . getPage ( ) ) ;
2024-02-13 14:54:28 +01:00
else if ( ! this . conventionService . isNullOrEmpty ( apiSource . getFirstPage ( ) ) ) completedPath = completedPath . replace ( " {page} " , apiSource . getFirstPage ( ) ) ;
2024-02-12 16:43:41 +01:00
else completedPath = completedPath . replace ( " {page} " , " 1 " ) ;
completedPath = completedPath . replace ( " {pageSize} " , ! this . conventionService . isNullOrEmpty ( externalReferenceCriteria . getPageSize ( ) ) ? externalReferenceCriteria . getPageSize ( ) : " 60 " ) ;
completedPath = completedPath . replace ( " {host} " , ! this . conventionService . isNullOrEmpty ( externalReferenceCriteria . getHost ( ) ) ? externalReferenceCriteria . getHost ( ) : " " ) ;
completedPath = completedPath . replace ( " {path} " , ! this . conventionService . isNullOrEmpty ( externalReferenceCriteria . getPath ( ) ) ? externalReferenceCriteria . getPath ( ) : " " ) ;
return completedPath ;
}
2024-02-19 17:10:34 +01:00
private ExternalDataResult queryExternalData ( final SourceExternalApiConfiguration < ResultsConfiguration < ResultFieldsMappingConfiguration > , AuthenticationConfiguration , QueryConfig < QueryCaseConfig > > apiSource , ExternalReferenceCriteria externalReferenceCriteria , String auth ) throws Exception {
2024-02-13 14:54:28 +01:00
String replacedPath = replaceLookupFields ( apiSource . getUrl ( ) , apiSource , externalReferenceCriteria ) ;
String replacedBody = replaceLookupFields ( apiSource . getRequestBody ( ) , apiSource , externalReferenceCriteria ) ;
2024-02-12 16:43:41 +01:00
ExternalDataResult externalDataResult = this . getExternalDataResults ( replacedPath , apiSource , replacedBody , auth ) ;
if ( externalDataResult ! = null ) {
if ( apiSource . getFilterType ( ) ! = null & & apiSource . getFilterType ( ) . equals ( " local " ) & & ( externalReferenceCriteria . getLike ( ) ! = null & & ! externalReferenceCriteria . getLike ( ) . isEmpty ( ) ) ) {
externalDataResult . setResults ( externalDataResult . getResults ( ) . stream ( )
2024-02-21 17:38:28 +01:00
. filter ( r - > r . get ( ReferenceEntity . KnownFields . Label ) . toLowerCase ( ) . contains ( externalReferenceCriteria . getLike ( ) . toLowerCase ( ) ) )
2024-02-12 16:43:41 +01:00
. collect ( Collectors . toList ( ) ) ) ;
}
2024-02-13 11:22:11 +01:00
externalDataResult . setResults ( externalDataResult . getResults ( ) . stream ( ) . peek ( x - > x . put ( ReferenceEntity . KnownFields . SourceLabel , apiSource . getLabel ( ) ) ) . peek ( x - > x . put ( ReferenceEntity . KnownFields . Key , apiSource . getKey ( ) ) ) . toList ( ) ) ;
2024-02-12 16:43:41 +01:00
return externalDataResult ;
}
else {
return new ExternalDataResult ( ) ;
}
}
2024-02-13 14:54:28 +01:00
protected ExternalDataResult getExternalDataResults ( String urlString , final SourceExternalApiConfiguration < ResultsConfiguration < ResultFieldsMappingConfiguration > , AuthenticationConfiguration , QueryConfig < QueryCaseConfig > > apiSource , String requestBody , String auth ) {
2024-02-12 16:43:41 +01:00
try {
JsonNode jsonBody = new ObjectMapper ( ) . readTree ( requestBody ) ;
HttpMethod method ;
switch ( apiSource . getHttpMethod ( ) ) {
case GET - > method = HttpMethod . GET ;
case POST - > method = HttpMethod . POST ;
default - > throw new MyApplicationException ( " unrecognized type " + apiSource . getHttpMethod ( ) ) ;
}
ResponseEntity < String > response = this . getWebClient ( ) . method ( method ) . uri ( urlString ) . headers ( httpHeaders - > {
if ( this . conventionService . isNullOrEmpty ( apiSource . getContentType ( ) ) ) {
httpHeaders . setAccept ( Collections . singletonList ( MediaType . valueOf ( apiSource . getContentType ( ) ) ) ) ;
httpHeaders . setContentType ( MediaType . valueOf ( apiSource . getContentType ( ) ) ) ;
}
if ( auth ! = null ) {
httpHeaders . set ( " Authorization " , auth ) ;
}
} ) . bodyValue ( jsonBody ) . retrieve ( ) . toEntity ( String . class ) . block ( ) ;
if ( response = = null | | ! response . getStatusCode ( ) . isSameCodeAs ( HttpStatus . OK ) | | ! response . hasBody ( ) | | response . getBody ( ) = = null ) return null ;
//do here all the parsing
List < String > responseContentTypeHeader = response . getHeaders ( ) . getOrDefault ( " Content-Type " , null ) ;
String responseContentType = ! this . conventionService . isListNullOrEmpty ( responseContentTypeHeader ) & & responseContentTypeHeader . getFirst ( ) ! = null ? responseContentTypeHeader . getFirst ( ) : " " ;
if ( responseContentType . contains ( " json " ) ) {
DocumentContext jsonContext = JsonPath . parse ( response . getBody ( ) ) ;
2024-02-13 11:22:11 +01:00
return this . jsonToExternalDataResult ( jsonContext , apiSource . getResults ( ) ) ;
2024-02-12 16:43:41 +01:00
} else {
throw new MyApplicationException ( " Unsupported response type " + responseContentType ) ;
}
} catch ( Exception exception ) {
logger . error ( exception . getMessage ( ) , exception ) ;
}
return null ;
}
2024-02-13 11:22:11 +01:00
private ExternalDataResult jsonToExternalDataResult ( DocumentContext jsonContext , ResultsConfiguration < ResultFieldsMappingConfiguration > resultsConfigurationEntity ) {
2024-02-12 16:43:41 +01:00
ExternalDataResult result = new ExternalDataResult ( ) ;
if ( this . conventionService . isNullOrEmpty ( resultsConfigurationEntity . getResultsArrayPath ( ) ) ) return new ExternalDataResult ( ) ;
List < Map < String , Object > > rawData = jsonContext . read ( resultsConfigurationEntity . getResultsArrayPath ( ) ) ;
result . setRawData ( rawData ) ;
if ( this . conventionService . isListNullOrEmpty ( rawData ) | | this . conventionService . isListNullOrEmpty ( resultsConfigurationEntity . getFieldsMapping ( ) ) ) return new ExternalDataResult ( ) ;
2024-02-13 11:22:11 +01:00
List < Object > results = jsonContext . read ( resultsConfigurationEntity . getResultsArrayPath ( ) ) ;
2024-02-12 16:43:41 +01:00
List < Map < String , String > > parsedData = new ArrayList < > ( ) ;
2024-02-13 11:22:11 +01:00
for ( Object resultItem : results ) {
2024-02-12 16:43:41 +01:00
Map < String , String > map = new HashMap < > ( ) ;
2024-02-19 17:10:34 +01:00
boolean isValid = true ;
2024-02-13 11:22:11 +01:00
for ( ResultFieldsMappingConfiguration field : resultsConfigurationEntity . getFieldsMapping ( ) ) {
2024-02-13 14:54:28 +01:00
if ( this . conventionService . isNullOrEmpty ( field . getResponsePath ( ) ) | | this . conventionService . isNullOrEmpty ( field . getCode ( ) ) ) continue ;
2024-02-16 16:42:01 +01:00
try {
Object value = JsonPath . parse ( resultItem ) . read ( field . getResponsePath ( ) ) ;
map . put ( field . getCode ( ) , normalizeJsonValue ( value ) ) ;
} catch ( PathNotFoundException e ) {
2024-02-19 14:50:01 +01:00
logger . debug ( " Json Path Error: " + e . getMessage ( ) + " on source " + jsonHandlingService . toJsonSafe ( resultItem ) ) ;
2024-02-19 17:10:34 +01:00
if ( ReferenceEntity . KnownFields . ReferenceId . equals ( field . getCode ( ) ) ) {
isValid = false ;
break ;
}
2024-02-16 16:42:01 +01:00
}
2024-02-12 16:43:41 +01:00
}
2024-02-19 17:10:34 +01:00
if ( this . conventionService . isNullOrEmpty ( map . getOrDefault ( ReferenceEntity . KnownFields . ReferenceId , null ) ) ) {
logger . warn ( " Invalid reference on source " + jsonHandlingService . toJsonSafe ( resultItem ) ) ;
}
if ( isValid ) parsedData . add ( map ) ;
2024-02-12 16:43:41 +01:00
}
2024-02-13 11:22:11 +01:00
2024-02-12 16:43:41 +01:00
result . setResults ( parsedData ) ;
return result ;
}
2024-02-13 11:22:11 +01:00
private static String normalizeJsonValue ( Object value ) {
2024-02-12 16:43:41 +01:00
if ( value instanceof JSONArray jsonArray ) {
if ( ! jsonArray . isEmpty ( ) & & jsonArray . getFirst ( ) instanceof String ) {
return jsonArray . getFirst ( ) . toString ( ) ;
} else {
for ( Object o : jsonArray ) {
if ( ( o instanceof Map ) & & ( ( Map < ? , ? > ) o ) . containsKey ( " content " ) ) {
try {
2024-02-13 11:22:11 +01:00
return String . valueOf ( ( ( Map < ? , ? > ) o ) . get ( " content " ) ) ;
2024-02-12 16:43:41 +01:00
}
catch ( ClassCastException e ) {
if ( ( ( Map < ? , ? > ) o ) . get ( " content " ) instanceof Integer ) {
return String . valueOf ( ( ( Map < ? , ? > ) o ) . get ( " content " ) ) ;
}
return null ;
}
}
}
}
} else if ( value instanceof Map ) {
2024-02-13 11:22:11 +01:00
String key = ( ( Map < ? , ? > ) value ) . containsKey ( " $ " ) ? " $ " : " content " ;
return String . valueOf ( ( ( Map < ? , ? > ) value ) . get ( key ) ) ;
2024-02-12 16:43:41 +01:00
}
return value ! = null ? value . toString ( ) : null ;
}
private String parseBodyString ( String bodyString ) {
String finalBodyString = bodyString ;
if ( bodyString . contains ( " {env: " ) ) {
int index = bodyString . indexOf ( " {env: " ) ;
while ( index > = 0 ) {
int endIndex = bodyString . indexOf ( " } " , index + 6 ) ;
String envName = bodyString . substring ( index + 6 , endIndex ) ;
finalBodyString = finalBodyString . replace ( " {env: " + envName + " } " , System . getenv ( envName ) ) ;
index = bodyString . indexOf ( " {env: " , index + 6 ) ;
}
}
return finalBodyString ;
}
}