3

I used the VDM generator to create client classes for a custom OData service in S/4. I'm trying to use the generated *Service class to get information from an Entity Set, using custom $filter and $expand parameters, but there doesn't seem to be a way to do so. (The FluentHelperRead class doesn't have any method for defining custom parameters, like the ODataQueryBuilder has).

Right now this is what I'm using (it works):

/**
 * Query the I_MaintenancePlan entity set filtered by a list of Maint.Plan IDs
 * (The navigation property to_CallHistory will be preloaded via $expand)
 */
public List<MaintenancePlan> getMaintenancePlansById(final Iterable<String> maintPlanIds)
    throws ODataException {

  // Build lightweight $filter with the IDs
  String[] filterParts = StreamSupport.stream(maintPlanIds.spliterator(), false)
    .map(e -> String.format("MaintenancePlan eq '%s'", StringUtils.urlEncode(e)))
    .toArray(String[]::new);
  if (filterParts.length == 0)
    return new ArrayList<>(0);

  String filter = String.join(" or ", filterParts);

  ErpConfigContext erpConfig = new ErpConfigContext(DESTINATION_NAME);

  List<MaintenancePlan> result = ODataQueryBuilder.withEntity(ZCUSTOMODATASRVService.DEFAULT_SERVICE_PATH, "I_MaintenancePlan")
      .withoutMetadata()
      .expand("to_CallHistory")
      .param("$filter", filter)
      .withHeader("sap-client", erpConfig.getSapClient().getValue())
      .withHeader("sap-language", erpConfig.getLocale().getLanguage())
      .build()
      .execute(erpConfig)
      .asList(MaintenancePlan.class);

  return result;      
}

(ZCUSTOMODATASRVService and MaintenancePlan are generated VDM classes)

This is what I would like to use (using only the VDM classes):

ZCUSTOMODATASRVService service = new DefaultZCUSTOMODATASRVService();

List<MaintenancePlan> result = service.getAllMaintenancePlan()
        .param("$filter", filter)
        .param("$expand", "to_CallHistory")
        .execute(erpConfig);

Is there any way to do this?

Sander Wozniak
  • 650
  • 8
  • 27

1 Answers1

0

Given your metadata, your VDM call could look like this:

List<MaintenancePlan> = 
    new DefaultZCUSTOMODATASRVService()
        .getAllMaintenancePlan()
        .filter(MaintenancePlan.CALL_HORIZON.eq("xyz"))
        .select(MaintenancePlan.TO_CALL_HISTORY)
        .execute(erpConfig);

You could expand further or reduce the projection via nested selects:

List<MaintenancePlan> result = 
      new DefaultZCUSTOMODATASRVService()
          .getAllMaintenancePlan()
          .filter(MaintenancePlan.CALL_HORIZON.eq("xyz"))
          .select(MaintenancePlan.TO_CALL_HISTORY
                  .select(MaintenancePlanCallHistory.INDICATOR,
                          MaintenancePlanCallHistory.MAINTENANCE_PLAN
                   )
           )
           .execute(erpConfig);
Philipp Herzig
  • 350
  • 6
  • 10
  • Here's my service metadata: https://pastebin.com/8YxpjWwy In my scenario this solution would work if I could do several individual reads (one for each Id I need) in a $batch request, but I also don't know it that's possible with VDM. – Guilherme Maeda Nov 16 '18 at 02:47
  • Thanks. I've changed my answer based on your concrete metadata. This is how you can retrieve multiple MaintenancePlans at a time. What do you mean by `one for each id` in a batch request? Do you mean instead of writing a query, you would like to retrieve simply multiple MaintenancePlans by ID in one batch? – Philipp Herzig Nov 16 '18 at 06:59
  • Thanks for that, it's good to know how I can do multi-level selects with VDM. Answering your question: Yes, I have several MaintenancePlan IDs I need to read. If I have let's say 100 IDs, it's not practical to create a filter tree that deep and send it in a query (I might even have problems with URLs being cropped). Ideally it would be a $batch request with 100 individual reads inside. – Guilherme Maeda Nov 16 '18 at 16:19
  • Please watch the release notes for updates on this matter. If the other answer was helpful, kindly ask you to accept the answer. – Philipp Herzig Nov 16 '18 at 19:49