Skip to content

Commit 2caae61

Browse files
committed
simplified RestStructure
1 parent 63848f1 commit 2caae61

File tree

4 files changed

+62
-63
lines changed

4 files changed

+62
-63
lines changed

commons-core/src/main/scala/com/avsystem/commons/rest/DefaultRestApiCompanion.scala

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ abstract class RestDataCompanion[T](implicit
3434
) extends {
3535
implicit lazy val codec: GenCodec[T] = instances(DefaultRestImplicits, this).codec
3636
implicit lazy val restStructure: RestStructure[T] = instances(DefaultRestImplicits, this).structure
37-
implicit lazy val restSchema: RestSchema[T] = restStructure.standaloneSchema // lazy on restStructure
37+
implicit lazy val restSchema: RestSchema[T] = RestSchema.lazySchema(restStructure.standaloneSchema)
3838
}
3939

4040
trait ClientInstances[Real] {
@@ -53,7 +53,7 @@ trait OpenApiInstances[Real] {
5353
trait OpenApiServerInstances[Real] extends ServerInstances[Real] with OpenApiInstances[Real]
5454
trait OpenApiFullInstances[Real] extends FullInstances[Real] with OpenApiInstances[Real]
5555

56-
/** @see [[RestApiCompanion]] */
56+
/** @see [[RestApiCompanion]]*/
5757
abstract class RestClientApiCompanion[Implicits, Real](protected val implicits: Implicits)(
5858
implicit inst: MacroInstances[Implicits, ClientInstances[Real]]
5959
) {
@@ -64,7 +64,7 @@ abstract class RestClientApiCompanion[Implicits, Real](protected val implicits:
6464
RawRest.fromHandleRequest(handleRequest)
6565
}
6666

67-
/** @see [[RestApiCompanion]] */
67+
/** @see [[RestApiCompanion]]*/
6868
abstract class RestServerApiCompanion[Implicits, Real](protected val implicits: Implicits)(
6969
implicit inst: MacroInstances[Implicits, ServerInstances[Real]]
7070
) {
@@ -75,7 +75,7 @@ abstract class RestServerApiCompanion[Implicits, Real](protected val implicits:
7575
RawRest.asHandleRequest(real)
7676
}
7777

78-
/** @see [[RestApiCompanion]] */
78+
/** @see [[RestApiCompanion]]*/
7979
abstract class RestServerOpenApiCompanion[Implicits, Real](protected val implicits: Implicits)(
8080
implicit inst: MacroInstances[Implicits, OpenApiServerInstances[Real]]
8181
) {
@@ -107,7 +107,7 @@ abstract class RestApiCompanion[Implicits, Real](protected val implicits: Implic
107107
RawRest.asHandleRequest(real)
108108
}
109109

110-
/** @see [[RestApiCompanion]] */
110+
/** @see [[RestApiCompanion]]*/
111111
abstract class RestOpenApiCompanion[Implicits, Real](protected val implicits: Implicits)(
112112
implicit inst: MacroInstances[Implicits, OpenApiFullInstances[Real]]
113113
) {

commons-core/src/main/scala/com/avsystem/commons/rest/openapi/RestSchema.scala

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,13 @@ object RestSchema {
4040
def ref[T](refstr: String): RestSchema[T] =
4141
RestSchema.create(_ => RefOr.ref(refstr))
4242

43+
def lazySchema[T](actual: => RestSchema[T]): RestSchema[T] =
44+
new RestSchema[T] {
45+
private lazy val actualSchema = actual
46+
def createSchema(resolver: SchemaResolver): RefOr[Schema] = actualSchema.createSchema(resolver)
47+
def name: Opt[String] = actualSchema.name
48+
}
49+
4350
implicit lazy val NothingSchema: RestSchema[Nothing] =
4451
RestSchema.create(_ => throw new NotImplementedError("RestSchema[Nothing]"))
4552

commons-core/src/main/scala/com/avsystem/commons/rest/openapi/RestStructure.scala

Lines changed: 47 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -11,74 +11,36 @@ import com.avsystem.commons.serialization._
1111

1212
sealed trait RestStructure[T] extends TypedMetadata[T] {
1313
def schemaAdjusters: List[SchemaAdjuster]
14+
def standaloneSchema: RestSchema[T]
1415
def info: GenInfo[T]
1516

1617
protected def applyAdjusters(schema: Schema): Schema =
1718
schemaAdjusters.foldRight(schema)(_ adjustSchema _)
1819
}
1920
object RestStructure extends AdtMetadataCompanion[RestStructure] {
20-
implicit class LazyRestStructureOps[T](restStructure: => RestStructure[T]) {
21-
def standaloneSchema: RestSchema[T] = new RestSchema[T] {
22-
def createSchema(resolver: SchemaResolver): RefOr[Schema] = restStructure match {
23-
case union: Union[T] => union.createSchema(resolver)
24-
case record: Record[T] => record.createSchema(resolver, Opt.Empty)
25-
case singleton: Singleton[T] => singleton.createSchema(resolver, Opt.Empty)
26-
}
27-
def name: Opt[String] = restStructure match {
28-
case _: Singleton[_] => Opt.Empty
29-
case s => s.info.rawName.opt
30-
}
31-
}
32-
}
33-
3421
@positioned(positioned.here) case class Union[T](
3522
@multi @reifyAnnot schemaAdjusters: List[SchemaAdjuster],
3623
@adtCaseMetadata @multi cases: List[Case[_]],
3724
@composite info: GenUnionInfo[T]
3825
) extends RestStructure[T] {
3926

40-
def createSchema(resolver: SchemaResolver): RefOr[Schema] = {
27+
def standaloneSchema: RestSchema[T] =
28+
RestSchema.create(createSchema, info.rawName)
29+
30+
private def createSchema(resolver: SchemaResolver): RefOr[Schema] = {
4131
val caseFieldOpt = info.flatten.map(_.caseFieldName)
42-
val caseSchemas = caseFieldOpt match {
43-
case Opt(caseFieldName) => cases.map { cs =>
44-
val caseName = cs.info.rawName
45-
val caseRestSchema = cs match {
46-
case record: Record[_] => RestSchema.create(record.createSchema(_, caseFieldOpt), caseName)
47-
case singleton: Singleton[_] => RestSchema.create(singleton.createSchema(_, caseFieldOpt), caseName)
48-
case custom: CustomCase[_] =>
49-
val caseFieldSchema = RefOr(Schema.enumOf(List(caseName)))
50-
custom.restSchema.map({
51-
case RefOr.Value(caseSchema) => caseSchema.copy(
52-
properties = caseSchema.properties + (caseFieldName -> caseFieldSchema),
53-
required = caseFieldName :: caseSchema.required
54-
)
55-
case ref => Schema(allOf = List(RefOr(Schema(
56-
`type` = DataType.Object,
57-
properties = Mapping(caseFieldName -> caseFieldSchema),
58-
required = List(caseFieldName)
59-
)), ref))
60-
}, custom.taggedName)
61-
}
62-
resolver.resolve(caseRestSchema)
63-
}
64-
case Opt.Empty => cases.map { cs =>
65-
val caseName = cs.info.rawName
66-
val caseSchema = cs match {
67-
case record: Record[_] => record.createSchema(resolver, Opt.Empty)
68-
case singleton: Singleton[_] => singleton.createSchema(resolver, Opt.Empty)
69-
case custom: CustomCase[_] => resolver.resolve(custom.restSchema)
70-
}
71-
RefOr(Schema(
72-
`type` = DataType.Object,
73-
properties = Mapping(caseName -> caseSchema),
74-
required = List(caseName)
75-
))
76-
}
32+
val caseSchemas = cases.map { c =>
33+
val baseSchema = resolver.resolve(c.caseSchema(caseFieldOpt))
34+
if (caseFieldOpt.nonEmpty) baseSchema
35+
else RefOr(Schema(
36+
`type` = DataType.Object,
37+
properties = Mapping(c.info.rawName -> baseSchema),
38+
required = List(c.info.rawName)
39+
))
7740
}
7841
val disc = caseFieldOpt.map { caseFieldName =>
79-
val mapping = Mapping(cases.collect {
80-
case custom: CustomCase[_] if custom.taggedName != custom.info.rawName =>
81-
(custom.info.rawName, custom.taggedName)
42+
val mapping = Mapping((cases zip caseSchemas).collect {
43+
case (c, RefOr.Ref(ref)) => (c.info.rawName, ref)
8244
})
8345
Discriminator(caseFieldName, mapping)
8446
}
@@ -89,6 +51,7 @@ object RestStructure extends AdtMetadataCompanion[RestStructure] {
8951

9052
sealed trait Case[T] extends TypedMetadata[T] {
9153
def info: GenCaseInfo[T]
54+
def caseSchema(caseFieldName: Opt[String]): RestSchema[T]
9255
}
9356
object Case extends AdtMetadataCompanion[Case]
9457

@@ -99,9 +62,24 @@ object RestStructure extends AdtMetadataCompanion[RestStructure] {
9962
@checked @infer restSchema: RestSchema[T],
10063
@composite info: GenCaseInfo[T]
10164
) extends Case[T] {
102-
def taggedName: String =
103-
if (restSchema.name.contains(info.rawName)) s"tagged${info.rawName}"
104-
else info.rawName
65+
def caseSchema(caseFieldName: Opt[String]): RestSchema[T] =
66+
caseFieldName.fold(restSchema) { cfn =>
67+
val caseFieldSchema = RefOr(Schema.enumOf(List(info.rawName)))
68+
val taggedName =
69+
if (restSchema.name.contains(info.rawName)) s"tagged${info.rawName}"
70+
else info.rawName
71+
restSchema.map({
72+
case RefOr.Value(caseSchema) => caseSchema.copy(
73+
properties = caseSchema.properties + (cfn -> caseFieldSchema),
74+
required = cfn :: caseSchema.required
75+
)
76+
case ref => Schema(allOf = List(RefOr(Schema(
77+
`type` = DataType.Object,
78+
properties = Mapping(cfn -> caseFieldSchema),
79+
required = List(cfn)
80+
)), ref))
81+
}, taggedName)
82+
}
10583
}
10684

10785
/**
@@ -113,7 +91,13 @@ object RestStructure extends AdtMetadataCompanion[RestStructure] {
11391
@composite info: GenCaseInfo[T]
11492
) extends RestStructure[T] with Case[T] {
11593

116-
def createSchema(resolver: SchemaResolver, caseFieldName: Opt[String]): RefOr[Schema] =
94+
def standaloneSchema: RestSchema[T] =
95+
RestSchema.create(createSchema(_, Opt.Empty), info.rawName)
96+
97+
def caseSchema(caseFieldName: Opt[String]): RestSchema[T] =
98+
RestSchema.create(createSchema(_, caseFieldName), caseFieldName.map(_ => info.rawName).toOptArg)
99+
100+
private def createSchema(resolver: SchemaResolver, caseFieldName: Opt[String]): RefOr[Schema] =
117101
(fields, caseFieldName) match {
118102
case (single :: Nil, Opt.Empty) if info.transparent =>
119103
SchemaAdjuster.adjustRef(schemaAdjusters, resolver.resolve(single.restSchema))
@@ -139,6 +123,12 @@ object RestStructure extends AdtMetadataCompanion[RestStructure] {
139123
@composite info: GenCaseInfo[T]
140124
) extends RestStructure[T] with Case[T] {
141125

126+
def standaloneSchema: RestSchema[T] =
127+
RestSchema.create(createSchema(_, Opt.Empty))
128+
129+
def caseSchema(caseFieldName: Opt[String]): RestSchema[T] =
130+
RestSchema.create(createSchema(_, caseFieldName), caseFieldName.map(_ => info.rawName).toOptArg)
131+
142132
def createSchema(resolver: SchemaResolver, caseFieldName: Opt[String]): RefOr[Schema] =
143133
RefOr(applyAdjusters(Schema(`type` = DataType.Object,
144134
properties = Mapping(caseFieldName.map(cfn => (cfn, RefOr(Schema.enumOf(List(info.rawName))))).toList),

commons-core/src/test/scala/com/avsystem/commons/rest/openapi/OpenApiGenerationTest.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -538,7 +538,9 @@ class OpenApiGenerationTest extends FunSuite {
538538
| "discriminator": {
539539
| "propertyName": "_case",
540540
| "mapping": {
541-
| "RestEntity": "taggedRestEntity"
541+
| "RestEntity": "#/components/schemas/taggedRestEntity",
542+
| "RestOtherEntity": "#/components/schemas/RestOtherEntity",
543+
| "SingletonEntity": "#/components/schemas/SingletonEntity"
542544
| }
543545
| }
544546
| },

0 commit comments

Comments
 (0)