oasis-tcs / odata-openapi

OASIS OData TC: Tools for producing API descriptions for OData services that adhere to the OpenAPI Specification
https://oasis-tcs.github.io/odata-openapi/
Other
196 stars 80 forks source link

Support of com.sap.vocabularies.Common.v1.ValueList annotation planned? #13

Closed ttrapp closed 6 years ago

ttrapp commented 6 years ago

IMHO one of the biggest issue with OData services V2 are missing enumeration types. This makes interfaces very hard to use. Therefore I would like to ask, whether a support of the com.sap.vocabularies.Common.v1.ValueList annotation is planned. Maybe those values could be transformed to OData V4 enumeration type and exported as Open API enum.

ralfhandl commented 6 years ago

Common.ValueList is sort of a glorified hyperlink to an entity set (of the same service) that can be queried at run-time for a list of allowed values. It covers both static and dynamic value lists and makes the API rather easy to use if you "explore" it with a Fiori Elements UI 😉 However it does not translate well into OpenAPI enumeration values which are static by nature and need to be known at design-time.

What would translate well into OpenAPI enumeration values and can be used with V2 services is the annotation Validation.AllowedValues. However OpenAPI currently does not allow having descriptions for enumeration values, see https://github.com/OAI/OpenAPI-Specification/issues/348 and https://github.com/OAI/OpenAPI-Specification/issues/681, which somewhat reduces the value of having a list of values: Rating:{enum:[1,2,3]} - is 1 better than 3 or worse? Which is why I haven't considered this annotation yet in the transformation.

ttrapp commented 6 years ago

I would like to try it out. Can you point me to an example in OData V2?

Yes, descriptions are not specified in OpenAPI. I think commentaries would help.

ralfhandl commented 6 years ago

Attached is a somewhat silly metadata example with two entity sets, one for flights, one for currencies. The currencies set is the value list for the currency property in the flights entity set.

However this is not translated into OpenAPI at all as I have no idea how to represent it. The actual currencies are only known at run-time, and the list of funny currencies in my test system will most likely differ from the list of real currencies in your production system even though the API structure can be identical.

zrha_flight_cds.zip

I'm curious where you want to go with this.

ttrapp commented 6 years ago

Thank you, this is exactly what I have in mind. For the certain element you define in the collection path the entityset which is probably a CDS view containing currencies. I could be translated into something like that:

currency: type: string enum:

Why I find it reasonable?

1.) As you told every SAP system might have a different customizing. So two services have different types of interface contracts. One service might accept EUR and USD, another one only EUR f.e. This means that the client applications that use the OData services in the landscape of your test system behave differently than the ones in the landscape of your production system. The documentation would make this behavior transparent. It would be even an improvement if above documentation would be included as comment. 2.) Every SAP system has a change management. A change in customizing is the result of a change process and afterwards the system behavior is different. So after a change the documentation should be regenerated.

IMHO in a software solution with lots of enumeration types defined by customzing above solution is the only way to make it possible to use the services.

I am well aware that the change is not trivial since one has to call the entityset and include the XML file into the transformation.

ralfhandl commented 6 years ago

The scope of this project is transforming $metadata into OpenAPI JSON. Data access is definitely out of scope.

Even if I were that ambitious: how should I distinguish a "currencies" value list from a "customers" value list? From an OData perspective they are indistinguishable, both are entity sets. And while I wish to have millions of customers, I don't wish to have their IDs and names in an OpenAPI description 😅

From an OData perspective the ValueList annotation in $metadata is sufficient: it describes that at run-time you can get a list of allowed values for a certain property from some other entity set in the same service.

ttrapp commented 6 years ago

I don't think it will be a problem to distinguish between master data and customizing since the metadata are within the data dictionary.

But Ok, I will try to solve it on my own. Can you give me a hint in which XSLT template I should enhance?

ralfhandl commented 6 years ago

For a start you need a preprocessing step that analyzes $metadata and then fires GET requests for all value-list entity sets.

Which is tricky, because $metadata doesn’t tell you anything about the underlying data source - intentionally, because even SAP has OData services not implemented in ABAP ;-) So you need to invent your own mechanism for identifying/annotating entity sets that you want to “flatten” out into the OpenAPI description.

Then you’d have to figure out how to access multiple input files from XSLT - should be possible, but I’ve never tried it.

A future obstacle is that you might want your extractor to work with V2 and V4 services and their different formats: Atom or JSON with V2, mostly only JSON with V4, so you need to harmonize that, likely into your own XML dialect if you want to stick with XSLT.

Which is another sore point for me: XSLT was the obvious choice for simple “one XML file in, one JSON text out“. As of now the transformation is no longer simple, and having multiple input files violates the last of the initial boundary conditions. In short: better start from scratch with a language more appropriate for this larger problem. Given that all possible input files ($metadata, V2 data, V4 data) is now available in JSON, Node.js and JavaScript seem to be the obvious choice.