Skip to content

Commit 9dc10eb

Browse files
committed
Add example for flag enum
1 parent 10d1589 commit 9dc10eb

File tree

1 file changed

+190
-12
lines changed

1 file changed

+190
-12
lines changed

graph/patterns/evolvable-enums.md

Lines changed: 190 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -26,27 +26,29 @@ The solution here is to add a 'sentinel' member named ```unknownFutureValue``` a
2626

2727
---
2828

29-
An enum member with the name of ```unknownFutureValue``` **must** only be used as a sentinel value, an API producer **must** not include a member named ```unknownFutureValue``` in an enum for any other purpose.
29+
- An enum member with the name of ```unknownFutureValue``` **must** only be used as a sentinel value, an API producer **must** not include a member named ```unknownFutureValue``` in an enum for any other purpose.
3030

31-
The value (i.e. position) of the ```unknownFutureValue``` sentinel member can only be changed when a new major version of Graph (e.g. 2.0) is released.
31+
- Changing the value (i.e. position) of the ```unknownFutureValue``` sentinel member is considered a breaking change, and must follow the [deprecation](../deprecation.md) process.
3232

33-
Enum Types can have multiple members with the same numeric value to allow for aliasing enum members, ```unknownFutureValue``` **must** not be aliased to any other enum member.
33+
- Enum Types can have multiple members with the same numeric value to allow for aliasing enum members, ```unknownFutureValue``` **must** not be aliased to any other enum member.
3434

35-
There is no ability for a client to indicate that it can handle a subset of unknown enum members, instead that can only specify either that they can not handle any unknown enum members, or they can handle any unknown enum members.
35+
- There is no ability for a client to indicate that it can handle a subset of unknown enum members, instead that can only specify either that they can not handle any unknown enum members, or they can handle any unknown enum members.
3636

37-
The ```Prefer: include-unknown-enum-members``` header applies to all included enums in the request/response, there is no way for an API consumer to apply the behavior to only a subset of enum types.
37+
- The ```Prefer: include-unknown-enum-members``` header applies to all included enums in the request/response, there is no way for an API consumer to apply the behavior to only a subset of enum types.
3838

39-
New values **must** not be inserted into the enum before ```unknownFutureValue```, implementers are recommended to make the numeric value of ```unknownFutureValue``` one greater than the last known enum member to ensure there are no gaps into which a new member could be inadvertently added. The exception to this is the case of flagged enums in which case the value of ```unknownFutureValue``` should be be next power of 2 value.
39+
- New values **must** not be inserted into the enum before ```unknownFutureValue```, implementers are recommended to make the numeric value of ```unknownFutureValue``` one greater than the last known enum member to ensure there are no gaps into which a new member could be inadvertently added. The exception to this is the case of flagged enums in which case the value of ```unknownFutureValue``` should be be next power of 2 value.
4040

41-
For flagged enums care should be exercised to ensure that ```unknownFutureValue``` is not included in any enum members that represent a combination of other enum members.
41+
- For flagged enums care should be exercised to ensure that ```unknownFutureValue``` is not included in any enum members that represent a combination of other enum members.
4242

43-
If an API consumer specifies ```unknownFutureValue``` for the value of a property in a ```POST```/```PUT``` request or as parameter of an action or function the API producer must reject the request with a ```400 Bad Request``` HTTP status.
43+
- If the value of a property containing a flag enum contains multiple unknown values they should all be replaced with a single ```unknownFutureValue``` value (i.e. there should not have multiple ```unknownFutureValue``` values returned).
4444

45-
If an API consumer specifies ```unknownFutureValue``` for the value of a property in a ```PATCH``` request the API producer must treat the property as if it were absent (i.e. the existing value should not be changed). For the case where the API producer treats ```PATCH``` as an upsert the call **must** be rejected with a ```400 Bad Request``` HTTP status.
45+
- If an API consumer specifies ```unknownFutureValue``` for the value of a property in a ```POST```/```PUT``` request or as parameter of an action or function the API producer must reject the request with a ```400 Bad Request``` HTTP status.
4646

47-
If an API consumer specifies an enum member greater than ```unknownFutureValue``` in any request without specifying the ```Prefer: include-unknown-enum-members``` header the API producer must reject the request with a ```400 Bad Request``` HTTP status.
47+
- If an API consumer specifies ```unknownFutureValue``` for the value of a property in a ```PATCH``` request the API producer must treat the property as if it were absent (i.e. the existing value should not be changed). For the case where the API producer treats ```PATCH``` as an upsert the call **must** be rejected with a ```400 Bad Request``` HTTP status.
4848

49-
For details of how the ```unknownFutureValue``` value is handled as part of a ```$filter``` clause please consult the following examples.
49+
- If an API consumer specifies an enum member greater than ```unknownFutureValue``` in any request without specifying the ```Prefer: include-unknown-enum-members``` header the API producer must reject the request with a ```400 Bad Request``` HTTP status.
50+
51+
- For details of how the ```unknownFutureValue``` value is handled as part of a ```$filter``` clause please consult the following examples:
5052

5153
### CSDL
5254

@@ -74,7 +76,7 @@ For details of how the ```unknownFutureValue``` value is handled as part of a ``
7476
| ```enumProperty gt newValue``` | ```400 Bad Request``` | Return entities where enumProperty has a value greater than ```newValue``` |
7577
| ```enumProperty lt newValue``` | ```400 Bad Request``` | Return entities where enumProperty has a value less than ```newValue``` |
7678

77-
If an evolvable enum is included in an ```$orderby``` clause the actual numeric value of the member should be used to order the collection, after sorting the member should then be replaced with ```unknownFutureValue``` when the ```Prefer: include-unknown-enum-members``` header is absent.
79+
- If an evolvable enum is included in an ```$orderby``` clause the actual numeric value of the member should be used to order the collection, after sorting the member should then be replaced with ```unknownFutureValue``` when the ```Prefer: include-unknown-enum-members``` header is absent.
7880

7981
## Examples
8082

@@ -310,3 +312,179 @@ Preference-Applied: include-unknown-enum-members
310312
"processorArchitecture": "quantum"
311313
}
312314
```
315+
316+
## Flag Enum Examples
317+
318+
For the following examples we will consider the ```windowsUniversalAppX``` entity which refers to the ```windowsArchitecture``` flag enum type.
319+
320+
```xml
321+
<!-- Simplified entity for example purposes -->
322+
<EntityType Name="windowsUniversalAppX" BaseType="graph.entity">
323+
<Property Name="displayName" Type="Edm.String" />
324+
<Property Name="applicableArchitectures" Type="graph.windowsArchitecture"/>
325+
</EntityType>
326+
```
327+
328+
When the ```windowsArchitecture``` enum was initially published to Graph it was defined as below:
329+
330+
```xml
331+
<!-- Slightly modified enum for example purposes -->
332+
<EnumType Name="windowsArchitecture" IsFlags="true">
333+
<Member Name="none" Value="0"/>
334+
<Member Name="x86" Value="1"/>
335+
<Member Name="x64" Value="2"/>
336+
<Member Name="arm" Value="4"/>
337+
<Member Name="neutral" Value="8"/>
338+
<Member Name="unknownFutureValue" Value="16" />
339+
</EnumType>
340+
```
341+
342+
The enum was later extended to add a new value of ```quantum``` leading to the below CSDL
343+
344+
```xml
345+
<EnumType Name="windowsArchitecture" IsFlags="true">
346+
<Member Name="none" Value="0"/>
347+
<Member Name="x86" Value="1"/>
348+
<Member Name="x64" Value="2"/>
349+
<Member Name="arm" Value="4"/>
350+
<Member Name="neutral" Value="8"/>
351+
<Member Name="unknownFutureValue" Value="16" />
352+
<Member Name="quantum" Value="32" />
353+
</EnumType>
354+
```
355+
356+
### Flag Enum Default Behavior
357+
358+
```http
359+
GET https://graph.microsoft.com/v1.0/deviceAppManagement/mobileApps?$select=displayName,applicableArchitectures
360+
```
361+
362+
```json
363+
{
364+
"value": [
365+
{
366+
"id": "0",
367+
"displayName": "OneNote",
368+
"applicableArchitectures" : "neutral"
369+
},
370+
{
371+
"id": "1",
372+
"displayName": "Minecraft",
373+
"applicableArchitectures": "x86,x64,arm,unknownFutureValue"
374+
}
375+
{
376+
"id": "2",
377+
"displayName": "Edge",
378+
"applicableArchitectures": "x64,arm,unknownFutureValue"
379+
}
380+
]
381+
}
382+
```
383+
384+
In this case the value of the ```applicableArchitectures``` property includes ```quantum``` however since the client did not request the ```include-unknown-enum-members``` header the value was replaced with ```unknownFutureValue```
385+
386+
### Flag Enum Include opt-in Header
387+
388+
```http
389+
GET https://graph.microsoft.com/v1.0/deviceAppManagement/mobileApps?$select=displayName,applicableArchitectures
390+
391+
Prefer: include-unknown-enum-members
392+
```
393+
394+
```json
395+
Preference-Applied: include-unknown-enum-members
396+
397+
{
398+
"value": [
399+
{
400+
"id": "0",
401+
"displayName": "OneNote",
402+
"applicableArchitectures" : "neutral"
403+
},
404+
{
405+
"id": "1",
406+
"displayName": "Minecraft",
407+
"applicableArchitectures": "x86,x64,arm,quantum"
408+
}
409+
{
410+
"id": "2",
411+
"displayName": "Edge",
412+
"applicableArchitectures": "x64,arm,quantum"
413+
}
414+
]
415+
}
416+
```
417+
418+
### Flag Enum Default Filter Behavior
419+
420+
```http
421+
GET https://graph.microsoft.com/v1.0/deviceAppManagement/mobileApps?$select=displayName,applicableArchitectures&$filter=applicableArchitectures has unknownFutureValue
422+
```
423+
424+
```json
425+
{
426+
"value": [
427+
{
428+
"id": "1",
429+
"displayName": "Minecraft",
430+
"applicableArchitectures": "x86,x64,arm,unknownFutureValue"
431+
}
432+
{
433+
"id": "2",
434+
"displayName": "Edge",
435+
"applicableArchitectures": "x64,arm,unknownFutureValue"
436+
}
437+
]
438+
}
439+
```
440+
441+
### Flag Enum Include opt-in Header Filter Behavior
442+
443+
```http
444+
GET https://graph.microsoft.com/v1.0/deviceAppManagement/mobileApps?$select=displayName,applicableArchitectures&$filter=applicableArchitectures has unknownFutureValue
445+
446+
Prefer: include-unknown-enum-members
447+
```
448+
449+
```json
450+
Preference-Applied: include-unknown-enum-members
451+
452+
{
453+
"value": []
454+
}
455+
```
456+
457+
### Flag Enum Patch Example
458+
459+
```http
460+
PATCH https://graph.microsoft.com/v1.0/deviceAppManagement/mobileApps/1
461+
462+
{
463+
"displayName": "Minecraft 2",
464+
"processorArchitecture": "unknownFutureValue"
465+
}
466+
```
467+
468+
```json
469+
{
470+
"id": "1",
471+
"displayName": "Minecraft 2",
472+
"applicableArchitectures": "unknownFutureValue"
473+
}
474+
```
475+
476+
```http
477+
GET https://graph.microsoft.com/v1.0/deviceAppManagement/mobileApps/1
478+
479+
Prefer: include-unknown-enum-members
480+
```
481+
482+
```json
483+
Preference-Applied: include-unknown-enum-members
484+
485+
{
486+
"id": "1",
487+
"displayName": "Minecraft 2",
488+
"applicableArchitectures": "x86,x64,arm,quantum"
489+
}
490+
```

0 commit comments

Comments
 (0)