Skip to content

Commit

Permalink
Suffix nullable types with question-mark (#80)
Browse files Browse the repository at this point in the history
Suffix type of nullable terms and properties with a question mark
  • Loading branch information
ralfhandl authored Oct 15, 2020
1 parent 851faaf commit 3132940
Show file tree
Hide file tree
Showing 10 changed files with 488 additions and 362 deletions.
428 changes: 214 additions & 214 deletions docs/annotation-cheat-sheet-json.md

Large diffs are not rendered by default.

7 changes: 6 additions & 1 deletion lib/csdl2markdown.js
Original file line number Diff line number Diff line change
Expand Up @@ -529,7 +529,7 @@ module.exports.csdl2markdown = function (filename, csdl, referenced = {}) {

let customFile = '';
if (url) {
// guess file name from from reference URL
// guess file name from reference URL
const lastSegment = url.substring(url.lastIndexOf('/') + 1);
if (lastSegment.startsWith(index.namespace[np.qualifier] + '.'))
customFile = index.namespace[np.qualifier] + '.md';
Expand All @@ -548,6 +548,7 @@ module.exports.csdl2markdown = function (filename, csdl, referenced = {}) {
+ (customType ? np.name
: (modelElement[voc.Core.IsURL] ? 'URL'
: (modelElement[voc.Core.IsMediaType] ? 'MediaType' : np.name)))
+ (modelElement.$Nullable ? '?' : '')
+ (customType ? '](' + customFile + '#' + np.name + ')' : '')
+ (modelElement.$Collection ? '\\]' : '');
}
Expand Down Expand Up @@ -586,6 +587,10 @@ module.exports.csdl2markdown = function (filename, csdl, referenced = {}) {
Core: ['Description', 'Example', 'IsMediaType', 'IsURL', 'LongDescription', 'Revisions'],
Validation: ['AllowedValues', 'ApplicableTerms', 'Exclusive', 'Maximum', 'Minimum', 'Pattern']
};
alias.Common = alias.Common || 'com.sap.vocabularies.Common.v1';
alias.Core = alias.Core || 'Org.OData.Core.V1';
alias.Validation = alias.Validation || 'Org.OData.Validation.V1';

const v = {};

Object.keys(terms).forEach(vocab => {
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "odata-vocabularies",
"version": "0.3.0",
"version": "0.4.0",
"description": "Convert OData vocabularies in CSDL XML or CSDL JSON to GitHub Flavored Markdown",
"homepage": "https://github.com/oasis-tcs/odata-vocabularies/blob/master/lib/README.md",
"bugs": "https://github.com/oasis-tcs/odata-vocabularies/issues",
Expand Down
121 changes: 121 additions & 0 deletions test/csdl2markdown.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,127 @@ describe('OASIS Vocabularies', function () {

})

describe('Non-OASIS Vocabularies', function () {

it('Non-OASIS Vocabulary referencing an OASIS Vocabulary', function () {
const filename = 'Other.xml'
const vocabulary = {
$Version: '4.01',
$Reference: {
'https://oasis-tcs.github.io/odata-vocabularies/vocabularies/Org.OData.Core.V1.json': {
$Include: [{
$Namespace: 'Org.OData.Core.V1'
}]
},
'Another.xml': {
$Include: [{
$Namespace: 'com.acme.Another.v42',
$Alias: 'Another'
}]
}
},
'com.acme.Other.v42': {
$Alias: 'Other',
'@Org.OData.Core.V1.Description': 'Other terms',
Foo: {
$Kind: 'Term',
$Type: 'Org.OData.Core.V1.Tag',
'@Org.OData.Core.V1.Revisions': [
{
Kind: 'Deprecated',
Description: 'Use term `Foo` from the OASIS Core vocabulary instead'
}
]
},
Bar: {
$Kind: 'Term',
$Type: 'Another.Type'
}
}
}
const expectedMarkdown = [
'# Other Vocabulary',
'**Namespace: [com.acme.Other.v42](Other.xml)**',
'',
'Other terms',
'',
'',
'## Terms',
'',
'Term|Type|Description',
':---|:---|:----------',
'Foo *(Deprecated)*|[Tag](https://github.com/oasis-tcs/odata-vocabularies/blob/master/vocabularies/Org.OData.Core.V1.md#Tag)|<a name=\"Foo\"></a>Use term `Foo` from the OASIS Core vocabulary instead',
'Bar|[Type](Another.md#Type)|<a name=\"Bar\"></a>',
''
]
const markdown = lib.csdl2markdown(filename, vocabulary);
assert.deepStrictEqual(markdown, expectedMarkdown);
})

it('No references to other vocabularies', function () {
const filename = 'Selfcontained.xml'
const vocabulary = {
$Version: '4.01',
'com.acme.Selfcontained.v0': {
Foo: {
$Kind: 'Term',
$Type: 'com.acme.Selfcontained.v0.Bar'
}
}
}
const expectedMarkdown = [
'# Selfcontained Vocabulary',
'**Namespace: [com.acme.Selfcontained.v0](Selfcontained.xml)**',
'',
undefined, // No Core.Description for vocabulary
'',
'',
'## Terms',
'',
'Term|Type|Description',
':---|:---|:----------',
'Foo|[Bar](#Bar)|<a name="Foo"></a>',
''
]
const markdown = lib.csdl2markdown(filename, vocabulary);
assert.deepStrictEqual(markdown, expectedMarkdown);
})

it('Reference without Include', function () {
const filename = 'Funny.json'
const vocabulary = {
$Version: '4.01',
$Reference: {
'': {}
},
'Funny.v0': {
Foo: {
$Kind: 'Term',
$Type: 'Edm.String',
'@com.sap.vocabularies.Common.v1.Experimental': true
}
}
}
const expectedMarkdown = [
'# Funny Vocabulary',
'**Namespace: [Funny.v0](Funny.json)**',
'',
undefined, // No Core.Description for vocabulary
'',
'',
'## Terms',
'',
'Term|Type|Description',
':---|:---|:----------',
'Foo *([Experimental](Common.md#Experimental))*|String|<a name="Foo"></a>',
''
]
const markdown = lib.csdl2markdown(filename, vocabulary);
assert.deepStrictEqual(markdown, expectedMarkdown);
})

})

function check(actual, expected) {
assert.deepStrictEqual(actual, expected.split(/\r\n|\r|\n/g), 'Markdown');
}
46 changes: 23 additions & 23 deletions vocabularies/Org.OData.Aggregation.V1.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,23 @@ Terms to describe which data in a given entity model can be aggregated, and how.

Term|Type|Description
:---|:---|:----------
[ApplySupported](Org.OData.Aggregation.V1.xml#L73)|[ApplySupportedType](#ApplySupportedType)|<a name="ApplySupported"></a>This structured type or entity container supports the $apply system query option
[Groupable](Org.OData.Aggregation.V1.xml#L114)|[Tag](Org.OData.Core.V1.md#Tag)|<a name="Groupable"></a>This property can be used in the groupby transformation
[Aggregatable](Org.OData.Aggregation.V1.xml#L118)|[Tag](Org.OData.Core.V1.md#Tag)|<a name="Aggregatable"></a>This property can be used in the aggregate transformation
[CustomAggregate](Org.OData.Aggregation.V1.xml#L122)|String|<a name="CustomAggregate"></a>Dynamic property that can be used in the aggregate transformation<p>This term MUST be applied with a Qualifier, the Qualifier value is the name of the dynamic property. The value of the annotation MUST be the qualified name of a primitive type. The aggregated values will be of that type.</p>
[ApplySupported](Org.OData.Aggregation.V1.xml#L73)|[ApplySupportedType?](#ApplySupportedType)|<a name="ApplySupported"></a>This structured type or entity container supports the $apply system query option
[Groupable](Org.OData.Aggregation.V1.xml#L114)|[Tag?](Org.OData.Core.V1.md#Tag)|<a name="Groupable"></a>This property can be used in the groupby transformation
[Aggregatable](Org.OData.Aggregation.V1.xml#L118)|[Tag?](Org.OData.Core.V1.md#Tag)|<a name="Aggregatable"></a>This property can be used in the aggregate transformation
[CustomAggregate](Org.OData.Aggregation.V1.xml#L122)|String?|<a name="CustomAggregate"></a>Dynamic property that can be used in the aggregate transformation<p>This term MUST be applied with a Qualifier, the Qualifier value is the name of the dynamic property. The value of the annotation MUST be the qualified name of a primitive type. The aggregated values will be of that type.</p>
[ContextDefiningProperties](Org.OData.Aggregation.V1.xml#L128)|\[PropertyPath\]|<a name="ContextDefiningProperties"></a>The annotated property or custom aggregate is only well-defined in the context of these properties<p>The context-defining properties need either be part of the result entities, or be restricted to a single value by a pre-filter operation. Examples are postal codes within a country, or monetary amounts whose context is the unit of currency.</p>
[LeveledHierarchy](Org.OData.Aggregation.V1.xml#L136)|\[PropertyPath\]|<a name="LeveledHierarchy"></a>Defines a leveled hierarchy by defining an ordered list of properties in the hierarchy
[RecursiveHierarchy](Org.OData.Aggregation.V1.xml#L141)|[RecursiveHierarchyType](#RecursiveHierarchyType)|<a name="RecursiveHierarchy"></a>Defines a recursive hierarchy.
[AvailableOnAggregates](Org.OData.Aggregation.V1.xml#L206)|[AvailableOnAggregatesType](#AvailableOnAggregatesType)|<a name="AvailableOnAggregates"></a>This action or function is available on aggregated entities if the RequiredProperties are still defined
[RecursiveHierarchy](Org.OData.Aggregation.V1.xml#L141)|[RecursiveHierarchyType?](#RecursiveHierarchyType)|<a name="RecursiveHierarchy"></a>Defines a recursive hierarchy.
[AvailableOnAggregates](Org.OData.Aggregation.V1.xml#L206)|[AvailableOnAggregatesType?](#AvailableOnAggregatesType)|<a name="AvailableOnAggregates"></a>This action or function is available on aggregated entities if the RequiredProperties are still defined


## Functions

Function|Signature|Description
:-------|:--------|:----------
[isroot](Org.OData.Aggregation.V1.xml#L161)|Entity:&nbsp;EntityType, Hierarchy:&nbsp;String &rarr;&nbsp;Boolean|<a name="isroot"></a>Returns true, if and only if the value of the node property of the specified hierarchy is the root of the hierarchy
[isdescendant](Org.OData.Aggregation.V1.xml#L169)|Entity:&nbsp;EntityType, Hierarchy:&nbsp;String, Node:&nbsp;PrimitiveType, MaxDistance:&nbsp;Int16 &rarr;&nbsp;Boolean|<a name="isdescendant"></a>Returns true, if and only if the value of the node property of the specified hierarchy is a descendant of the given parent node with a distance of less than or equal to the optionally specified maximum distance
[isancestor](Org.OData.Aggregation.V1.xml#L179)|Entity:&nbsp;EntityType, Hierarchy:&nbsp;String, Node:&nbsp;PrimitiveType, MaxDistance:&nbsp;Int16 &rarr;&nbsp;Boolean|<a name="isancestor"></a>Returns true, if and only if the value of the node property of the specified hierarchy is an ancestor of the given child node with a distance of less than or equal to the optionally specified maximum distance
[isdescendant](Org.OData.Aggregation.V1.xml#L169)|Entity:&nbsp;EntityType, Hierarchy:&nbsp;String, Node:&nbsp;PrimitiveType, MaxDistance:&nbsp;Int16? &rarr;&nbsp;Boolean|<a name="isdescendant"></a>Returns true, if and only if the value of the node property of the specified hierarchy is a descendant of the given parent node with a distance of less than or equal to the optionally specified maximum distance
[isancestor](Org.OData.Aggregation.V1.xml#L179)|Entity:&nbsp;EntityType, Hierarchy:&nbsp;String, Node:&nbsp;PrimitiveType, MaxDistance:&nbsp;Int16? &rarr;&nbsp;Boolean|<a name="isancestor"></a>Returns true, if and only if the value of the node property of the specified hierarchy is an ancestor of the given child node with a distance of less than or equal to the optionally specified maximum distance
[issibling](Org.OData.Aggregation.V1.xml#L189)|Entity:&nbsp;EntityType, Hierarchy:&nbsp;String, Node:&nbsp;PrimitiveType &rarr;&nbsp;Boolean|<a name="issibling"></a>Returns true, if and only if the value of the node property of the specified hierarchy has the same parent node as the specified node
[isleaf](Org.OData.Aggregation.V1.xml#L198)|Entity:&nbsp;EntityType, Hierarchy:&nbsp;String &rarr;&nbsp;Boolean|<a name="isleaf"></a>Returns true, if and only if the value of the node property of the specified hierarchy has no descendants

Expand Down Expand Up @@ -56,8 +56,8 @@ Property|Type|Description
:-------|:---|:----------
[NodeProperty](Org.OData.Aggregation.V1.xml#L146)|PropertyPath|Property holding the hierarchy node value
[ParentNavigationProperty](Org.OData.Aggregation.V1.xml#L149)|NavigationPropertyPath|Property for navigating to the parent node
[DistanceFromRootProperty](Org.OData.Aggregation.V1.xml#L152)|PropertyPath|Property holding the number of edges between the node and the root node
[IsLeafProperty](Org.OData.Aggregation.V1.xml#L155)|PropertyPath|Property indicating whether the node is a leaf of the hierarchy
[DistanceFromRootProperty](Org.OData.Aggregation.V1.xml#L152)|PropertyPath?|Property holding the number of edges between the node and the root node
[IsLeafProperty](Org.OData.Aggregation.V1.xml#L155)|PropertyPath?|Property indicating whether the node is a leaf of the hierarchy

## <a name="AvailableOnAggregatesType"></a>[AvailableOnAggregatesType](Org.OData.Aggregation.V1.xml#L210)

Expand All @@ -71,24 +71,24 @@ Aggregation capabilities on a navigation path

Property|Type|Description
:-------|:---|:----------
[*NavigationProperty*](Org.OData.Capabilities.V1.xml#L250)|NavigationPropertyPath|Navigation properties can be navigated
[*Navigability*](Org.OData.Capabilities.V1.xml#L253)|[NavigationType](Org.OData.Capabilities.V1.md#NavigationType)|Supported navigability of this navigation property
[*NavigationProperty*](Org.OData.Capabilities.V1.xml#L250)|NavigationPropertyPath?|Navigation properties can be navigated
[*Navigability*](Org.OData.Capabilities.V1.xml#L253)|[NavigationType?](Org.OData.Capabilities.V1.md#NavigationType)|Supported navigability of this navigation property
[*FilterFunctions*](Org.OData.Capabilities.V1.xml#L256)|\[String\]|List of functions and operators supported in filter expressions<p>If not specified, null, or empty, all functions and operators may be attempted.</p>
[*FilterRestrictions*](Org.OData.Capabilities.V1.xml#L261)|[FilterRestrictionsType](Org.OData.Capabilities.V1.md#FilterRestrictionsType)|Restrictions on filter expressions
[*SearchRestrictions*](Org.OData.Capabilities.V1.xml#L264)|[SearchRestrictionsType](Org.OData.Capabilities.V1.md#SearchRestrictionsType)|Restrictions on search expressions
[*SortRestrictions*](Org.OData.Capabilities.V1.xml#L267)|[SortRestrictionsType](Org.OData.Capabilities.V1.md#SortRestrictionsType)|Restrictions on orderby expressions
[*FilterRestrictions*](Org.OData.Capabilities.V1.xml#L261)|[FilterRestrictionsType?](Org.OData.Capabilities.V1.md#FilterRestrictionsType)|Restrictions on filter expressions
[*SearchRestrictions*](Org.OData.Capabilities.V1.xml#L264)|[SearchRestrictionsType?](Org.OData.Capabilities.V1.md#SearchRestrictionsType)|Restrictions on search expressions
[*SortRestrictions*](Org.OData.Capabilities.V1.xml#L267)|[SortRestrictionsType?](Org.OData.Capabilities.V1.md#SortRestrictionsType)|Restrictions on orderby expressions
[*TopSupported*](Org.OData.Capabilities.V1.xml#L270)|Boolean|Supports $top
[*SkipSupported*](Org.OData.Capabilities.V1.xml#L273)|Boolean|Supports $skip
[*SelectSupport*](Org.OData.Capabilities.V1.xml#L276)|[SelectSupportType](Org.OData.Capabilities.V1.md#SelectSupportType)|Support for $select
[*SelectSupport*](Org.OData.Capabilities.V1.xml#L276)|[SelectSupportType?](Org.OData.Capabilities.V1.md#SelectSupportType)|Support for $select
[*IndexableByKey*](Org.OData.Capabilities.V1.xml#L279)|Boolean|Supports key values according to OData URL conventions
[*InsertRestrictions*](Org.OData.Capabilities.V1.xml#L282)|[InsertRestrictionsType](Org.OData.Capabilities.V1.md#InsertRestrictionsType)|Restrictions on insert operations
[*DeepInsertSupport*](Org.OData.Capabilities.V1.xml#L285)|[DeepInsertSupportType](Org.OData.Capabilities.V1.md#DeepInsertSupportType)|Deep Insert Support of the annotated resource (the whole service, an entity set, or a collection-valued resource)
[*UpdateRestrictions*](Org.OData.Capabilities.V1.xml#L289)|[UpdateRestrictionsType](Org.OData.Capabilities.V1.md#UpdateRestrictionsType)|Restrictions on update operations
[*DeepUpdateSupport*](Org.OData.Capabilities.V1.xml#L292)|[DeepUpdateSupportType](Org.OData.Capabilities.V1.md#DeepUpdateSupportType)|Deep Update Support of the annotated resource (the whole service, an entity set, or a collection-valued resource)
[*DeleteRestrictions*](Org.OData.Capabilities.V1.xml#L296)|[DeleteRestrictionsType](Org.OData.Capabilities.V1.md#DeleteRestrictionsType)|Restrictions on delete operations
[*InsertRestrictions*](Org.OData.Capabilities.V1.xml#L282)|[InsertRestrictionsType?](Org.OData.Capabilities.V1.md#InsertRestrictionsType)|Restrictions on insert operations
[*DeepInsertSupport*](Org.OData.Capabilities.V1.xml#L285)|[DeepInsertSupportType?](Org.OData.Capabilities.V1.md#DeepInsertSupportType)|Deep Insert Support of the annotated resource (the whole service, an entity set, or a collection-valued resource)
[*UpdateRestrictions*](Org.OData.Capabilities.V1.xml#L289)|[UpdateRestrictionsType?](Org.OData.Capabilities.V1.md#UpdateRestrictionsType)|Restrictions on update operations
[*DeepUpdateSupport*](Org.OData.Capabilities.V1.xml#L292)|[DeepUpdateSupportType?](Org.OData.Capabilities.V1.md#DeepUpdateSupportType)|Deep Update Support of the annotated resource (the whole service, an entity set, or a collection-valued resource)
[*DeleteRestrictions*](Org.OData.Capabilities.V1.xml#L296)|[DeleteRestrictionsType?](Org.OData.Capabilities.V1.md#DeleteRestrictionsType)|Restrictions on delete operations
[*OptimisticConcurrencyControl*](Org.OData.Capabilities.V1.xml#L299)|Boolean|Data modification (including insert) along this navigation property requires the use of ETags
[*ReadRestrictions*](Org.OData.Capabilities.V1.xml#L303)|[ReadRestrictionsType](Org.OData.Capabilities.V1.md#ReadRestrictionsType)|Restrictions for retrieving entities
[ApplySupported](Org.OData.Aggregation.V1.xml#L218)|[ApplySupportedType](#ApplySupportedType)|Support for $apply
[*ReadRestrictions*](Org.OData.Capabilities.V1.xml#L303)|[ReadRestrictionsType?](Org.OData.Capabilities.V1.md#ReadRestrictionsType)|Restrictions for retrieving entities
[ApplySupported](Org.OData.Aggregation.V1.xml#L218)|[ApplySupportedType?](#ApplySupportedType)|Support for $apply
[CustomAggregates](Org.OData.Aggregation.V1.xml#L221)|\[[CustomAggregateType](#CustomAggregateType)\]|Supported custom aggregates

## <a name="CustomAggregateType"></a>[CustomAggregateType](Org.OData.Aggregation.V1.xml#L226)
Expand Down
Loading

0 comments on commit 3132940

Please sign in to comment.