22
33import static io .github .jpmorganchase .fusion .filter .DatasetFilter .filterDatasets ;
44
5+ import com .google .gson .Gson ;
6+ import com .google .gson .JsonArray ;
7+ import com .google .gson .JsonObject ;
8+ import com .google .gson .JsonParser ;
59import io .github .jpmorganchase .fusion .api .APIManager ;
610import io .github .jpmorganchase .fusion .api .FusionAPIManager ;
711import io .github .jpmorganchase .fusion .api .exception .APICallException ;
1115import io .github .jpmorganchase .fusion .builders .APIConfiguredBuilders ;
1216import io .github .jpmorganchase .fusion .builders .Builders ;
1317import io .github .jpmorganchase .fusion .http .Client ;
18+ import io .github .jpmorganchase .fusion .http .HttpResponse ;
1419import io .github .jpmorganchase .fusion .http .JdkClient ;
1520import io .github .jpmorganchase .fusion .model .*;
1621import io .github .jpmorganchase .fusion .oauth .credential .BearerTokenCredentials ;
@@ -195,6 +200,72 @@ private Map<String, Map<String, Object>> callForMap(String url) {
195200 return responseParser .parseResourcesUntyped (json );
196201 }
197202
203+ /**
204+ * Makes paginated API calls and aggregates all results transparently.
205+ * This method handles the pagination logic internally, making multiple API calls
206+ * as needed and combining the results into a single response string.
207+ *
208+ * @param url the API endpoint URL
209+ * @param pageSize the number of items per page (null to use API default)
210+ * @return aggregated JSON response containing all pages of data
211+ */
212+ private String callAPIWithPagination (String url , Integer pageSize ) {
213+ Map <String , String > headers = new HashMap <>();
214+ headers .put ("x-jpmc-paginate" , "true" );
215+ if (pageSize != null ) {
216+ headers .put ("x-jpmc-page-size" , String .valueOf (pageSize ));
217+ }
218+
219+ Gson gson = new Gson ();
220+ JsonArray aggregatedResources = new JsonArray ();
221+ String nextToken = null ;
222+
223+ do {
224+ if (nextToken != null ) {
225+ headers .put ("x-next-token" , nextToken );
226+ }
227+
228+ HttpResponse <String > response = this .api .callAPIWithResponse (url , headers );
229+ String pageJson = response .getBody ();
230+
231+ JsonObject pageObject = JsonParser .parseString (pageJson ).getAsJsonObject ();
232+ if (pageObject .has ("resources" ) && pageObject .get ("resources" ).isJsonArray ()) {
233+ JsonArray pageResources = pageObject .getAsJsonArray ("resources" );
234+ pageResources .forEach (aggregatedResources ::add );
235+ }
236+
237+ nextToken = getHeaderValue (response .getHeaders (), "x-next-token" );
238+
239+ } while (nextToken != null && !nextToken .isEmpty ());
240+
241+ JsonObject result = new JsonObject ();
242+ result .add ("resources" , aggregatedResources );
243+ return gson .toJson (result );
244+ }
245+
246+ /**
247+ * Gets a header value from the response headers map (case-insensitive).
248+ *
249+ * @param headers the response headers map
250+ * @param headerName the header name to look for
251+ * @return the header value, or null if not found
252+ */
253+ private String getHeaderValue (Map <String , java .util .List <String >> headers , String headerName ) {
254+ if (headers == null || headerName == null ) {
255+ return null ;
256+ }
257+
258+ for (Map .Entry <String , java .util .List <String >> entry : headers .entrySet ()) {
259+ if (entry .getKey () != null && entry .getKey ().equalsIgnoreCase (headerName )) {
260+ java .util .List <String > values = entry .getValue ();
261+ if (values != null && !values .isEmpty ()) {
262+ return values .get (0 );
263+ }
264+ }
265+ }
266+ return null ;
267+ }
268+
198269 /**
199270 * Get a list of the catalogs available to the API account.
200271 *
@@ -223,7 +294,7 @@ public Map<String, Map<String, Object>> catalogResources(String catalogName) {
223294 /**
224295 * Get a filtered list of the data products in the specified catalog
225296 * <p>
226- * Note that as of current version this search capability is not yet implemented
297+ * Note that as of the current version, this search capability is not yet implemented
227298 *
228299 * @param catalogName identifier of the catalog to be queried
229300 * @param contains a search keyword.
@@ -235,7 +306,7 @@ public Map<String, Map<String, Object>> catalogResources(String catalogName) {
235306 public Map <String , DataProduct > listProducts (String catalogName , String contains , boolean idContains ) {
236307 // TODO: unimplemented logic implied by the method parameters
237308 String url = String .format ("%1scatalogs/%2s/products" , this .rootURL , catalogName );
238- String json = this . api . callAPI (url );
309+ String json = callAPIWithPagination (url , null );
239310 return responseParser .parseDataProductResponse (json );
240311 }
241312
@@ -266,7 +337,7 @@ public Map<String, DataProduct> listProducts() {
266337 /**
267338 * Get a filtered list of the datasets in the specified catalog
268339 * <p>
269- * Note that as of current version this search capability is not yet implemented
340+ * Note that as of the current version, this search capability is not yet implemented
270341 *
271342 * @param catalogName identifier of the catalog to be queried
272343 * @param contains a search keyword.
@@ -277,7 +348,7 @@ public Map<String, DataProduct> listProducts() {
277348 */
278349 public Map <String , Dataset > listDatasets (String catalogName , String contains , boolean idContains ) {
279350 String url = String .format ("%1scatalogs/%2s/datasets" , this .rootURL , catalogName );
280- String json = this . api . callAPI (url );
351+ String json = callAPIWithPagination (url , null );
281352 return filterDatasets (responseParser .parseDatasetResponse (json , catalogName ), contains , idContains );
282353 }
283354
@@ -421,7 +492,7 @@ public Map<String, Map<String, Object>> datasetMemberResources(String dataset, S
421492 */
422493 public Map <String , Attribute > listAttributes (String catalogName , String dataset ) {
423494 String url = String .format ("%1scatalogs/%2s/datasets/%3s/attributes" , this .rootURL , catalogName , dataset );
424- String json = this . api . callAPI (url );
495+ String json = callAPIWithPagination (url , null );
425496 return responseParser .parseAttributeResponse (json , catalogName , dataset );
426497 }
427498
0 commit comments