Skip to content

Commit d505523

Browse files
committed
[elm] Add support for oneOf
And add additional test for composable types.
1 parent 2b36383 commit d505523

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+1647
-233
lines changed

bin/openapi3/elm-all.sh

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#!/bin/sh
2+
3+
./bin/openapi3/elm-petstore.sh
4+
./bin/openapi3/elm-composition.sh
5+

bin/openapi3/elm-composition.sh

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#!/bin/sh
2+
3+
SCRIPT="$0"
4+
echo "# START SCRIPT: $SCRIPT"
5+
6+
while [ -h "$SCRIPT" ] ; do
7+
ls=`ls -ld "$SCRIPT"`
8+
link=`expr "$ls" : '.*-> \(.*\)$'`
9+
if expr "$link" : '/.*' > /dev/null; then
10+
SCRIPT="$link"
11+
else
12+
SCRIPT=`dirname "$SCRIPT"`/"$link"
13+
fi
14+
done
15+
16+
if [ ! -d "${APP_DIR}" ]; then
17+
APP_DIR=`dirname "$SCRIPT"`/..
18+
APP_DIR=`cd "${APP_DIR}"; pwd`
19+
fi
20+
21+
executable="./modules/openapi-generator-cli/target/openapi-generator-cli.jar"
22+
23+
if [ ! -f "$executable" ]
24+
then
25+
mvn -B clean package
26+
fi
27+
28+
# auto format elm code using elm-format
29+
export ELM_POST_PROCESS_FILE="/usr/bin/env elm-format --elm-version=0.19 --yes"
30+
31+
# if you've executed sbt assembly previously it will use that instead.
32+
export JAVA_OPTS="${JAVA_OPTS} -Xmx1024M -DloggerPath=conf/log4j.properties"
33+
ags="generate -i modules/openapi-generator/src/test/resources/3_0/composition.yaml -g elm -t modules/openapi-generator/src/main/resources/elm -o samples/openapi3/client/composition/elm --enable-post-process-file $@"
34+
35+
java $JAVA_OPTS -jar $executable $ags

modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ElmClientCodegen.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -373,7 +373,13 @@ public int compare(CodegenModel cm1, CodegenModel cm2) {
373373
elmImports.add(elmImport);
374374
}
375375
}
376-
if (cm.discriminator != null) {
376+
if (cm.oneOf != null) {
377+
for (String variant : cm.oneOf) {
378+
final ElmImport elmImport = createImport(variant);
379+
elmImports.add(elmImport);
380+
}
381+
}
382+
if (cm.discriminator != null && cm.children != null) {
377383
for (CodegenModel child : cm.children) {
378384
// add child imports
379385
final ElmImport elmImport = createImport(child.classname);

modules/openapi-generator/src/main/resources/elm/model.mustache

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{{>licenseInfo}}
22

3-
module Data.{{classname}} exposing ({{#models}}{{#model}}{{classname}}{{#hasChildren}}(..){{/hasChildren}}{{#isEnum}}(..){{/isEnum}}{{^isEnum}}{{#vars}}{{#isEnum}}, {{vendorExtensions.elmCustomType}}(..){{/isEnum}}{{/vars}}{{/isEnum}}, decoder, encode, toString{{/model}}{{/models}})
3+
module Data.{{classname}} exposing ({{#models}}{{#model}}{{classname}}{{#hasChildren}}(..){{/hasChildren}}{{#isEnum}}(..){{/isEnum}}{{^isEnum}}{{#vars}}{{#isEnum}}, {{vendorExtensions.elmCustomType}}(..){{/isEnum}}{{/vars}}{{/isEnum}}, decoder, encode{{^isEnum}}{{^discriminator}}{{^oneOf}}, encodeWithTag{{/oneOf}}{{/discriminator}}{{/isEnum}}, toString{{/model}}{{/models}})
44

55
{{>imports}}import Dict exposing (Dict)
66
import Json.Decode as Decode exposing (Decoder)
@@ -14,7 +14,7 @@ import Json.Encode as Encode
1414
{-| {{{description}}}
1515
-}
1616
{{/description}}
17-
{{#isEnum}}{{>modelTypeCustom}}{{/isEnum}}{{^isEnum}}{{#discriminator}}{{>modelTypeDiscriminator}}{{/discriminator}}{{^discriminator}}{{#isAlias}}{{>modelTypePrimitive}}{{/isAlias}}{{^isAlias}}{{#isArrayModel}}{{>modelTypeArray}}{{/isArrayModel}}{{^isArrayModel}}{{>modelTypeRecord}}{{/isArrayModel}}{{/isAlias}}{{/discriminator}}{{/isEnum}}
17+
{{#isEnum}}{{>modelTypeCustom}}{{/isEnum}}{{^isEnum}}{{#discriminator}}{{>modelTypeDiscriminator}}{{/discriminator}}{{^discriminator}}{{#oneOf}}{{#-first}}{{>modelTypeDiscriminator}}{{/-first}}{{/oneOf}}{{^oneOf}}{{#isAlias}}{{>modelTypePrimitive}}{{/isAlias}}{{^isAlias}}{{#isArrayModel}}{{>modelTypeArray}}{{/isArrayModel}}{{^isArrayModel}}{{>modelTypeRecord}}{{/isArrayModel}}{{/isAlias}}{{/oneOf}}{{/discriminator}}{{/isEnum}}
1818

1919
{{/model}}
2020
{{/models}}

modules/openapi-generator/src/main/resources/elm/modelTypeDiscriminator.mustache

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,22 @@
11
type {{classname}}
2-
{{#mappedModels}}
2+
{{^discriminator}}{{#oneOf}}
3+
{{#-first}}={{/-first}}{{^-first}}|{{/-first}} {{{.}}}Type {{{.}}}
4+
{{/oneOf}}{{/discriminator}}
5+
{{#discriminator}}{{#mappedModels}}
36
{{#-first}}={{/-first}}{{^-first}}|{{/-first}} {{modelName}}Type {{modelName}}
4-
{{/mappedModels}}
7+
{{/mappedModels}}{{/discriminator}}
58

69

710
decoder : Decoder {{classname}}
811
decoder =
12+
{{^discriminator}}
13+
Decode.oneOf
14+
{{#oneOf}}
15+
{{#-first}}[{{/-first}}{{^-first}},{{/-first}} Decode.map {{{.}}}Type {{{.}}}.decoder
16+
{{/oneOf}}
17+
]
18+
{{/discriminator}}
19+
{{#discriminator}}
920
Decode.field "{{{discriminator.propertyName}}}" Decode.string
1021
|> Decode.andThen {{classVarName}}Decoder
1122

@@ -19,17 +30,25 @@ decoder =
1930

2031
{{/mappedModels}}
2132
_ ->
22-
Decode.fail <| "Trying to decode {{classname}}, but {{{discriminatorName}}} " ++ tag ++ " is not supported."
33+
Decode.fail <| "Trying to decode {{classname}}, but {{{discriminatorName}}} '" ++ tag ++ "' is not supported."
34+
{{/discriminator}}
2335

2436

2537
encode : {{classname}} -> Encode.Value
2638
encode model =
2739
case model of
40+
{{^discriminator}}{{#oneOf}}
41+
{{{.}}}Type subModel ->
42+
{{{.}}}.encode subModel
43+
44+
{{/oneOf}}{{/discriminator}}
45+
{{#discriminator}}
2846
{{#mappedModels}}
2947
{{modelName}}Type subModel ->
30-
{{modelName}}.encode "{{mappingName}}" subModel
48+
{{modelName}}.encodeWithTag ("{{discriminatorName}}", "{{mappingName}}") subModel
3149

3250
{{/mappedModels}}
51+
{{/discriminator}}
3352

3453

3554
toString : {{classname}} -> String

modules/openapi-generator/src/main/resources/elm/modelTypeRecord.mustache

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ type alias {{classname}} =
1818

1919
toString : {{classname}} -> String
2020
toString =
21-
Encode.encode 0 << encode{{#vendorExtensions.discriminatorName}} ""{{/vendorExtensions.discriminatorName}}
21+
Encode.encode 0 << encode
2222

2323

2424
{{#vars}}
Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,16 @@
1-
encode : {{#vendorExtensions.discriminatorName}}String -> {{/vendorExtensions.discriminatorName}}{{classname}} -> Encode.Value
2-
encode {{#vendorExtensions.discriminatorName}}tag {{/vendorExtensions.discriminatorName}}model =
3-
Encode.object
1+
encode : {{classname}} -> Encode.Value
2+
encode =
3+
Encode.object << encodePairs
4+
5+
6+
encodeWithTag : ( String, String ) -> {{classname}} -> Encode.Value
7+
encodeWithTag (tagField, tag) model =
8+
Encode.object <| encodePairs model ++ [ ( tagField, Encode.string tag ) ]
9+
10+
11+
encodePairs : {{classname}} -> List (String, Encode.Value)
12+
encodePairs model =
413
{{#allVars}}
5-
{{#-first}}[{{/-first}}{{^-first}},{{/-first}} {{>recordFieldEncoder}}
6-
{{/allVars}}{{#vendorExtensions.discriminatorName}} , ( "{{{vendorExtensions.discriminatorName}}}", Encode.string tag ){{/vendorExtensions.discriminatorName}}
7-
]
14+
{{#-first}}[{{/-first}}{{^-first}},{{/-first}} {{>recordFieldEncoder}}
15+
{{/allVars}}
16+
]
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
openapi: 3.0.0
2+
info:
3+
title: Composition and Inheritence (Polymorphism)
4+
version: 1.0.0
5+
paths:
6+
/oneOf:
7+
post:
8+
summary: One of
9+
responses:
10+
200:
11+
description: Response
12+
content:
13+
application/json:
14+
schema:
15+
$ref: '#/components/schemas/OneOf'
16+
/oneOfWithDiscriminator:
17+
post:
18+
summary: One of with discriminator
19+
responses:
20+
200:
21+
description: Response
22+
content:
23+
application/json:
24+
schema:
25+
$ref: '#/components/schemas/OneOfWithDiscriminator'
26+
/oneOfWithAllOfDiscriminator:
27+
post:
28+
summary: One of with discriminator from all of
29+
responses:
30+
200:
31+
description: Response
32+
content:
33+
application/json:
34+
schema:
35+
$ref: '#/components/schemas/OneOfWithAllOfDiscriminator'
36+
/allOf:
37+
post:
38+
summary: All of
39+
responses:
40+
200:
41+
description: Response
42+
content:
43+
application/json:
44+
schema:
45+
$ref: '#/components/schemas/AllOf'
46+
/allOfWithDiscriminator:
47+
post:
48+
summary: All of with discriminator
49+
responses:
50+
200:
51+
description: Response
52+
content:
53+
application/json:
54+
schema:
55+
$ref: '#/components/schemas/BaseObject'
56+
components:
57+
schemas:
58+
OneOf:
59+
oneOf:
60+
- $ref: "#/components/schemas/ObjectA"
61+
- $ref: "#/components/schemas/ObjectB"
62+
OneOfWithDiscriminator:
63+
oneOf:
64+
- $ref: "#/components/schemas/ObjectA"
65+
- $ref: "#/components/schemas/ObjectB"
66+
discriminator:
67+
propertyName: objectType
68+
mapping:
69+
a: "#/components/schemas/ObjectA"
70+
b: "#/components/schemas/ObjectB"
71+
OneOfWithAllOfDiscriminator:
72+
oneOf:
73+
- $ref: "#/components/schemas/SubObjectA"
74+
- $ref: "#/components/schemas/SubObjectB"
75+
AllOf:
76+
allOf:
77+
- $ref: "#/components/schemas/ObjectA"
78+
- $ref: "#/components/schemas/ObjectB"
79+
BaseObject:
80+
required:
81+
- objectType
82+
- value
83+
properties:
84+
objectType:
85+
type: string
86+
value:
87+
type: boolean
88+
discriminator:
89+
propertyName: objectType
90+
ObjectA:
91+
type: object
92+
required:
93+
- objectType
94+
properties:
95+
objectType:
96+
type: string
97+
valueA:
98+
type: string
99+
ObjectB:
100+
type: object
101+
required:
102+
- objectType
103+
properties:
104+
objectType:
105+
type: string
106+
valueB:
107+
type: number
108+
SubObjectA:
109+
allOf:
110+
- $ref: "#/components/schemas/BaseObject"
111+
- type: object
112+
properties:
113+
valueA:
114+
type: string
115+
SubObjectB:
116+
allOf:
117+
- $ref: "#/components/schemas/BaseObject"
118+
- type: object
119+
properties:
120+
valueB:
121+
type: number

samples/client/petstore/elm-0.18/src/Data/ApiResponse.elm

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
-}
1111

1212

13-
module Data.ApiResponse exposing (ApiResponse, decoder, encode, toString)
13+
module Data.ApiResponse exposing (ApiResponse, decoder, encode, encodeWithTag, toString)
1414

1515
import Dict exposing (Dict)
1616
import Json.Decode as Decode exposing (Decoder)
@@ -36,12 +36,21 @@ decoder =
3636

3737

3838
encode : ApiResponse -> Encode.Value
39-
encode model =
40-
Encode.object
41-
[ ( "code", Maybe.withDefault Encode.null (Maybe.map Encode.int model.code) )
42-
, ( "type", Maybe.withDefault Encode.null (Maybe.map Encode.string model.type_) )
43-
, ( "message", Maybe.withDefault Encode.null (Maybe.map Encode.string model.message) )
44-
]
39+
encode =
40+
Encode.object << encodePairs
41+
42+
43+
encodeWithTag : ( String, String ) -> ApiResponse -> Encode.Value
44+
encodeWithTag ( tagField, tag ) model =
45+
Encode.object <| encodePairs model ++ [ ( tagField, Encode.string tag ) ]
46+
47+
48+
encodePairs : ApiResponse -> List ( String, Encode.Value )
49+
encodePairs model =
50+
[ ( "code", Maybe.withDefault Encode.null (Maybe.map Encode.int model.code) )
51+
, ( "type", Maybe.withDefault Encode.null (Maybe.map Encode.string model.type_) )
52+
, ( "message", Maybe.withDefault Encode.null (Maybe.map Encode.string model.message) )
53+
]
4554

4655

4756
toString : ApiResponse -> String

samples/client/petstore/elm-0.18/src/Data/Category.elm

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
-}
1111

1212

13-
module Data.Category exposing (Category, decoder, encode, toString)
13+
module Data.Category exposing (Category, decoder, encode, encodeWithTag, toString)
1414

1515
import Dict exposing (Dict)
1616
import Json.Decode as Decode exposing (Decoder)
@@ -34,11 +34,20 @@ decoder =
3434

3535

3636
encode : Category -> Encode.Value
37-
encode model =
38-
Encode.object
39-
[ ( "id", Maybe.withDefault Encode.null (Maybe.map Encode.int model.id) )
40-
, ( "name", Maybe.withDefault Encode.null (Maybe.map Encode.string model.name) )
41-
]
37+
encode =
38+
Encode.object << encodePairs
39+
40+
41+
encodeWithTag : ( String, String ) -> Category -> Encode.Value
42+
encodeWithTag ( tagField, tag ) model =
43+
Encode.object <| encodePairs model ++ [ ( tagField, Encode.string tag ) ]
44+
45+
46+
encodePairs : Category -> List ( String, Encode.Value )
47+
encodePairs model =
48+
[ ( "id", Maybe.withDefault Encode.null (Maybe.map Encode.int model.id) )
49+
, ( "name", Maybe.withDefault Encode.null (Maybe.map Encode.string model.name) )
50+
]
4251

4352

4453
toString : Category -> String

samples/client/petstore/elm-0.18/src/Data/Order_.elm

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
-}
1111

1212

13-
module Data.Order_ exposing (Order_, Status(..), decoder, encode, toString)
13+
module Data.Order_ exposing (Order_, Status(..), decoder, encode, encodeWithTag, toString)
1414

1515
import DateTime exposing (DateTime)
1616
import Dict exposing (Dict)
@@ -49,15 +49,24 @@ decoder =
4949

5050

5151
encode : Order_ -> Encode.Value
52-
encode model =
53-
Encode.object
54-
[ ( "id", Maybe.withDefault Encode.null (Maybe.map Encode.int model.id) )
55-
, ( "petId", Maybe.withDefault Encode.null (Maybe.map Encode.int model.petId) )
56-
, ( "quantity", Maybe.withDefault Encode.null (Maybe.map Encode.int model.quantity) )
57-
, ( "shipDate", Maybe.withDefault Encode.null (Maybe.map DateTime.encode model.shipDate) )
58-
, ( "status", Maybe.withDefault Encode.null (Maybe.map encodeStatus model.status) )
59-
, ( "complete", Maybe.withDefault Encode.null (Maybe.map Encode.bool model.complete) )
60-
]
52+
encode =
53+
Encode.object << encodePairs
54+
55+
56+
encodeWithTag : ( String, String ) -> Order_ -> Encode.Value
57+
encodeWithTag ( tagField, tag ) model =
58+
Encode.object <| encodePairs model ++ [ ( tagField, Encode.string tag ) ]
59+
60+
61+
encodePairs : Order_ -> List ( String, Encode.Value )
62+
encodePairs model =
63+
[ ( "id", Maybe.withDefault Encode.null (Maybe.map Encode.int model.id) )
64+
, ( "petId", Maybe.withDefault Encode.null (Maybe.map Encode.int model.petId) )
65+
, ( "quantity", Maybe.withDefault Encode.null (Maybe.map Encode.int model.quantity) )
66+
, ( "shipDate", Maybe.withDefault Encode.null (Maybe.map DateTime.encode model.shipDate) )
67+
, ( "status", Maybe.withDefault Encode.null (Maybe.map encodeStatus model.status) )
68+
, ( "complete", Maybe.withDefault Encode.null (Maybe.map Encode.bool model.complete) )
69+
]
6170

6271

6372
toString : Order_ -> String

0 commit comments

Comments
 (0)