66import gov .nih .nci .bento .service .ESService ;
77import gov .nih .nci .bento .utility .TypeChecker ;
88import gov .nih .nci .bento_ri .service .InsESService ;
9+
910import graphql .schema .idl .RuntimeWiring ;
11+
1012import org .apache .logging .log4j .LogManager ;
1113import org .apache .logging .log4j .Logger ;
1214import org .opensearch .client .Request ;
15+ import org .springframework .beans .factory .annotation .Value ;
1316import org .springframework .stereotype .Component ;
1417
1518import com .google .gson .JsonArray ;
@@ -27,13 +30,17 @@ public class PrivateESDataFetcher extends AbstractPrivateESDataFetcher {
2730 private final YamlQueryFactory yamlQueryFactory ;
2831 private InsESService insEsService ;
2932
33+ @ Value ("${aws.cloudfront.url:#{environment.AWS_CLOUDFRONT_URL}}" )
34+ private String cloudFrontUrl ;
35+
3036 // parameters used in queries
3137 final String PAGE_SIZE = "first" ;
3238 final String OFFSET = "offset" ;
3339 final String ORDER_BY = "order_by" ;
3440 final String SORT_DIRECTION = "sort_direction" ;
3541
3642 final String DATASETS_END_POINT = "/datasets/_search" ;
43+ final String FILES_END_POINT = "/files/_search" ;
3744 final String GRANTS_END_POINT = "/grants/_search" ;
3845 final String PROGRAMS_END_POINT = "/programs/_search" ;
3946 final String PROJECTS_END_POINT = "/projects/_search" ;
@@ -127,6 +134,10 @@ public RuntimeWiring buildRuntimeWiring() throws IOException {
127134 Map <String , Object > args = env .getArguments ();
128135 return datasetDetails (args );
129136 })
137+ .dataFetcher ("getDatasetFiles" , env -> {
138+ Map <String , Object > args = env .getArguments ();
139+ return getDatasetFiles (args );
140+ })
130141 .dataFetcher ("programDetails" , env -> {
131142 Map <String , Object > args = env .getArguments ();
132143 return programDetails (args );
@@ -826,6 +837,83 @@ private Map<String, Object> datasetDetails(Map<String, Object> params) throws IO
826837 return dataset ;
827838 }
828839
840+ /**
841+ * Gets the files for a single Dataset record
842+ *
843+ * @param params The filters applied
844+ * @return A list of the Dataset's files
845+ * @throws IOException
846+ */
847+ private List <Map <String , Object >> getDatasetFiles (Map <String , Object > params ) throws IOException {
848+ List <Map <String , Object >> files ;
849+
850+ final String [][] PROPERTIES = new String [][]{
851+ new String []{"dataset_source_id" , "dataset_source_id" },
852+ new String []{"file_url_repo_prefix" , "file_url_repo_prefix" },
853+ new String []{"file_id" , "file_id" },
854+ new String []{"file_name" , "file_name" },
855+ new String []{"file_type" , "file_type" },
856+ new String []{"file_url" , "file_url" },
857+ new String []{"access_level" , "access_level" }
858+ };
859+
860+ Map <String , String > mapping = Map .ofEntries (
861+ Map .entry ("dataset_source_id" , "dataset_source_id.sort" ),
862+ Map .entry ("file_url_repo_prefix" , "file_url_repo_prefix.sort" ),
863+ Map .entry ("file_id" , "file_id.sort" ),
864+ Map .entry ("file_name" , "file_name.sort" ),
865+ Map .entry ("file_type" , "file_type.sort" ),
866+ Map .entry ("file_url" , "file_url.sort" ),
867+ Map .entry ("access_level" , "access_level.sort" )
868+ );
869+
870+ // Create a new params object rather than mutating the input
871+ Map <String , Object > queryParams = new HashMap <>(params );
872+
873+ // Rename 'accessTypes' to 'access_level'
874+ queryParams .put ("access_level.search" , queryParams .remove ("accessTypes" ));
875+
876+ // Turn dataset_source_id into a list
877+ queryParams .put ("dataset_source_id.search" , List .of (queryParams .remove ("dataset_source_id" )));
878+
879+ // Turn filters into lowercase
880+ for (String key : queryParams .keySet ()) {
881+ @ SuppressWarnings ("unchecked" )
882+ List <String > list = (List <String >) queryParams .get (key );
883+ List <String > lowerCaseList = new ArrayList <String >();
884+ list .forEach (s -> lowerCaseList .add (s .toLowerCase ()));
885+ queryParams .put (key , lowerCaseList );
886+ }
887+
888+ // Add missing sorting params if not present
889+ queryParams .putIfAbsent (ORDER_BY , "file_name" );
890+ queryParams .putIfAbsent (SORT_DIRECTION , "ASC" );
891+ queryParams .putIfAbsent (PAGE_SIZE , InsESService .MAX_ES_SIZE ); // use MAX_ES_SIZE for maximum files per request
892+ queryParams .putIfAbsent (OFFSET , 0 );
893+
894+ files = overview (FILES_END_POINT , queryParams , PROPERTIES , "file_name" , mapping , REGULAR_PARAMS , "nested_filters" , "files" );
895+
896+ // Form URLs for download
897+ for (Map <String , Object > file : files ) {
898+ String prefix = (String ) file .get ("file_url_repo_prefix" );
899+ String fileUrl = (String ) file .get ("file_url" ); // Required property, guaranteed by ETL
900+
901+ // Compose downloadUrl, handling extra slashes
902+ String url = cloudFrontUrl .endsWith ("/" ) ? cloudFrontUrl .substring (0 , cloudFrontUrl .length () - 1 ) : cloudFrontUrl ;
903+ url += "/" + (prefix != null ? prefix : "" );
904+ if (!url .endsWith ("/" ) && !fileUrl .startsWith ("/" )) {
905+ url += "/" ;
906+ }
907+ url += fileUrl ;
908+
909+ file .put ("downloadUrl" , url );
910+ file .remove ("file_url_repo_prefix" );
911+ file .remove ("file_url" );
912+ }
913+
914+ return files ;
915+ }
916+
829917 /**
830918 * Gets the details for a single Program record
831919 *
0 commit comments