Skip to content

Commit

Permalink
MODINVSTOR-1266 Append bounded items to invetory-view instances response
Browse files Browse the repository at this point in the history
  • Loading branch information
illia-borysenko committed Oct 25, 2024
1 parent ba1a4ce commit 7d60e26
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 6 deletions.
6 changes: 6 additions & 0 deletions ramls/inventory-view.raml
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,9 @@ resourceTypes:
description: Get instances by id with their holdings and items
is: [pageable, searchable: {description: "using CQL",
example: "title=\"*uproot*\""}]
queryParameters:
withBoundedRecords:
description: Add "items" anf "holdingsRecords" that bounded for the parent instance
type: boolean
required: false
default: false
71 changes: 71 additions & 0 deletions src/main/java/org/folio/persist/InstanceRepository.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import static org.folio.rest.impl.ItemStorageApi.ITEM_TABLE;
import static org.folio.rest.persist.PgUtil.postgresClient;

import com.fasterxml.jackson.core.JsonProcessingException;
import io.vertx.core.Context;
import io.vertx.core.Future;
import io.vertx.sqlclient.Row;
Expand All @@ -16,8 +17,10 @@
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.folio.cql2pgjson.CQL2PgJSON;
import org.folio.dbschema.ObjectMapperTool;
import org.folio.rest.exceptions.BadRequestException;
import org.folio.rest.jaxrs.model.Instance;
import org.folio.rest.jaxrs.model.ResultInfo;
import org.folio.rest.persist.SQLConnection;
import org.folio.rest.persist.cql.CQLQueryValidationException;
import org.folio.rest.persist.cql.CQLWrapper;
Expand Down Expand Up @@ -140,4 +143,72 @@ public Future<List<Map<String, Object>>> getReindexInstances(String fromId, Stri
return resultList;
});
}

public Future<Response> getInventoryViewInstancesWithBoundedItems(int offset, int limit, String query) {
try {
var sql = new StringBuilder("SELECT JSONB_BUILD_OBJECT('instanceId', instance.id, 'instance', instance.jsonb, ");
sql.append("'holdingsRecords', (SELECT jsonb_agg(jsonb) FROM ");
sql.append(postgresClientFuturized.getFullTableName(HOLDINGS_RECORD_TABLE));
sql.append(" WHERE holdings_record.instanceId = instance.id),");
sql.append(" 'items', (SELECT jsonb_agg(combined_items.jsonb) FROM ("
+ "SELECT item.jsonb FROM ");
sql.append(postgresClientFuturized.getFullTableName(HOLDINGS_RECORD_TABLE));
sql.append(" as hr JOIN ");
sql.append(postgresClientFuturized.getFullTableName(ITEM_TABLE));
sql.append(" ON item.holdingsRecordId = hr.id AND hr.instanceId = instance.id");
sql.append(" UNION SELECT item.jsonb FROM ");
sql.append(postgresClientFuturized.getFullTableName(ITEM_TABLE));
sql.append(" JOIN ");
sql.append(postgresClientFuturized.getFullTableName(BOUND_WITH_TABLE));
sql.append(" as bwp ON item.id = bwp.itemid JOIN ");
sql.append(postgresClientFuturized.getFullTableName(HOLDINGS_RECORD_TABLE));
sql.append(" as hr ON hr.id = bwp.holdingsrecordid AND hr.instanceId = instance.id) as combined_items),");
sql.append(" 'isBoundWith', (SELECT EXISTS(SELECT 1 FROM ");
sql.append(postgresClientFuturized.getFullTableName(BOUND_WITH_TABLE));
sql.append(" as bw JOIN ");
sql.append(postgresClientFuturized.getFullTableName(ITEM_TABLE));
sql.append(" as it ON it.id = bw.itemid JOIN ");
sql.append(postgresClientFuturized.getFullTableName(HOLDINGS_RECORD_TABLE));
sql.append(" as hr ON hr.id = bw.holdingsrecordid WHERE hr.instanceId = instance.id LIMIT 1))");
sql.append(" ) AS jsonb FROM ");
sql.append(postgresClientFuturized.getFullTableName(INSTANCE_TABLE)).append(" ");

var field = new CQL2PgJSON(INSTANCE_TABLE + ".jsonb");
var cqlWrapper = new CQLWrapper(field, query, limit, offset, "none");
sql.append(cqlWrapper);

return postgresClient.select(sql.toString())
.map(rowSet -> {
try {
StringBuilder json = new StringBuilder("{\"instances\":[\n");
boolean first = true;
for (Row row : rowSet) {
if (first) {
first = false;
} else {
json.append(",\n");
}
json.append(row.getJsonObject(0).toString());
}
json.append("\n],\n");
json.append("\"totalRecords\": " + rowSet.size() + ",\n");
var resultInfo = ObjectMapperTool.getMapper().writeValueAsString(
new ResultInfo().withTotalRecords(rowSet.size()));
json.append("\"resultInfo\": " + resultInfo);
json.append("\n}");
return Response.ok(json.toString(), MediaType.APPLICATION_JSON_TYPE)
.build();
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
});

} catch (CQLQueryValidationException e) {
return Future.failedFuture(new BadRequestException(e.getMessage()));
} catch (Exception e) {
return Future.failedFuture(e);
}
}


}
24 changes: 18 additions & 6 deletions src/main/java/org/folio/rest/impl/InventoryViewApi.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,27 @@
import org.folio.rest.annotations.Validate;
import org.folio.rest.jaxrs.model.InventoryViewInstance;
import org.folio.rest.jaxrs.resource.InventoryViewInstances;
import org.folio.rest.support.EndpointHandler;
import org.folio.services.instance.InstanceService;

public class InventoryViewApi implements InventoryViewInstances {
@Validate
@Override
public void getInventoryViewInstances(String totalRecords, int offset, int limit, String query,
RoutingContext routingContext, Map<String, String> okapiHeaders,
Handler<AsyncResult<Response>> asyncResultHandler, Context vertxContext) {

streamGet("instance_holdings_item_view", InventoryViewInstance.class, query,
offset, limit, null, "instances", routingContext, okapiHeaders, vertxContext);
public void getInventoryViewInstances(boolean withBoundedRecords,
String totalRecords, int offset, int limit,
String query, RoutingContext routingContext,
Map<String, String> okapiHeaders,
Handler<AsyncResult<Response>> asyncResultHandler, Context vertxContext) {
if (withBoundedRecords) {
new InstanceService(vertxContext, okapiHeaders)
.getInventoryViewInstancesWithBoundedItems(offset, limit, query)
.onComplete(EndpointHandler.handle(asyncResultHandler));
} else {
streamGet("instance_holdings_item_view", InventoryViewInstance.class,
query,
offset, limit, null, "instances", routingContext, okapiHeaders,
vertxContext);
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,10 @@ public Future<Response> getInstanceSet(boolean instance, boolean holdingsRecords
offset, limit, query);
}

public Future<Response> getInventoryViewInstancesWithBoundedItems(int offset, int limit, String query) {
return instanceRepository.getInventoryViewInstancesWithBoundedItems(offset, limit, query);
}

public Future<Response> createInstance(Instance entity) {
entity.setStatusUpdatedDate(generateStatusUpdatedDate());
return hridManager.populateHrid(entity)
Expand Down

0 comments on commit 7d60e26

Please sign in to comment.