-
Notifications
You must be signed in to change notification settings - Fork 14
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adds writers for SchemaDocument and types (#294)
- Loading branch information
Showing
6 changed files
with
372 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
43 changes: 43 additions & 0 deletions
43
ion-schema/src/main/kotlin/com/amazon/ionschema/writer/internal/IonSchemaWriterV2_0.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
package com.amazon.ionschema.writer.internal | ||
|
||
import com.amazon.ion.IonWriter | ||
import com.amazon.ionschema.IonSchemaVersion | ||
import com.amazon.ionschema.internal.util.islRequire | ||
import com.amazon.ionschema.model.ExperimentalIonSchemaModel | ||
import com.amazon.ionschema.model.NamedTypeDefinition | ||
import com.amazon.ionschema.model.SchemaDocument | ||
import com.amazon.ionschema.model.SchemaFooter | ||
import com.amazon.ionschema.model.SchemaHeader | ||
import com.amazon.ionschema.model.TypeDefinition | ||
|
||
@ExperimentalIonSchemaModel | ||
internal object IonSchemaWriterV2_0 : VersionedIonSchemaWriter { | ||
|
||
private val headerWriter = HeaderWriter | ||
private val typeWriter = TypeWriterV2_0 | ||
private val footerWriter = FooterWriter | ||
|
||
override fun writeSchema(ionWriter: IonWriter, schemaDocument: SchemaDocument) { | ||
islRequire(schemaDocument.ionSchemaVersion == IonSchemaVersion.v2_0) { "IonSchemaWriterV2_0 only supports ISL 2.0" } | ||
ionWriter.writeSymbol("\$ion_schema_2_0") | ||
for (item in schemaDocument.items) { | ||
when (item) { | ||
is SchemaHeader -> headerWriter.writeHeader(ionWriter, item) | ||
is NamedTypeDefinition -> writeNamedType(ionWriter, item) | ||
is SchemaFooter -> footerWriter.writeFooter(ionWriter, item) | ||
is SchemaDocument.OpenContent -> item.value.writeTo(ionWriter) | ||
} | ||
} | ||
} | ||
|
||
override fun writeType(ionWriter: IonWriter, typeDefinition: TypeDefinition) { | ||
typeWriter.writeOrphanedTypeDefinition(ionWriter, typeDefinition) | ||
} | ||
|
||
override fun writeNamedType(ionWriter: IonWriter, namedTypeDefinition: NamedTypeDefinition) { | ||
typeWriter.writeNamedTypeDefinition(ionWriter, namedTypeDefinition) | ||
} | ||
} |
125 changes: 125 additions & 0 deletions
125
ion-schema/src/main/kotlin/com/amazon/ionschema/writer/internal/TypeWriterV2_0.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
package com.amazon.ionschema.writer.internal | ||
|
||
import com.amazon.ion.IonWriter | ||
import com.amazon.ionschema.IonSchemaVersion | ||
import com.amazon.ionschema.model.Constraint | ||
import com.amazon.ionschema.model.DiscreteIntRange | ||
import com.amazon.ionschema.model.ExperimentalIonSchemaModel | ||
import com.amazon.ionschema.model.NamedTypeDefinition | ||
import com.amazon.ionschema.model.OpenContentFields | ||
import com.amazon.ionschema.model.TypeArgument | ||
import com.amazon.ionschema.model.TypeDefinition | ||
import com.amazon.ionschema.model.VariablyOccurringTypeArgument | ||
import com.amazon.ionschema.writer.internal.constraints.AnnotationsV2Writer | ||
import com.amazon.ionschema.writer.internal.constraints.ContainsWriter | ||
import com.amazon.ionschema.writer.internal.constraints.ElementWriter | ||
import com.amazon.ionschema.writer.internal.constraints.ExponentWriter | ||
import com.amazon.ionschema.writer.internal.constraints.FieldNamesWriter | ||
import com.amazon.ionschema.writer.internal.constraints.FieldsWriter | ||
import com.amazon.ionschema.writer.internal.constraints.Ieee754FloatWriter | ||
import com.amazon.ionschema.writer.internal.constraints.LengthConstraintsWriter | ||
import com.amazon.ionschema.writer.internal.constraints.LogicConstraintsWriter | ||
import com.amazon.ionschema.writer.internal.constraints.OrderedElementsWriter | ||
import com.amazon.ionschema.writer.internal.constraints.PrecisionWriter | ||
import com.amazon.ionschema.writer.internal.constraints.RegexWriter | ||
import com.amazon.ionschema.writer.internal.constraints.TimestampOffsetWriter | ||
import com.amazon.ionschema.writer.internal.constraints.TimestampPrecisionWriter | ||
import com.amazon.ionschema.writer.internal.constraints.ValidValuesWriter | ||
|
||
@ExperimentalIonSchemaModel | ||
internal object TypeWriterV2_0 : TypeWriter { | ||
private val constraintWriters = listOf( | ||
AnnotationsV2Writer(this), | ||
ContainsWriter, | ||
ElementWriter(this, IonSchemaVersion.v2_0), | ||
ExponentWriter, | ||
FieldNamesWriter(this), | ||
FieldsWriter(this, IonSchemaVersion.v2_0), | ||
Ieee754FloatWriter, | ||
LengthConstraintsWriter, | ||
LogicConstraintsWriter(this), | ||
OrderedElementsWriter(this), | ||
PrecisionWriter, | ||
RegexWriter, | ||
TimestampOffsetWriter, | ||
TimestampPrecisionWriter, | ||
ValidValuesWriter, | ||
).flatMap { w -> w.supportedClasses.map { it to w } } | ||
.toMap() | ||
|
||
override fun writeNamedTypeDefinition(ionWriter: IonWriter, namedTypeDefinition: NamedTypeDefinition) { | ||
ionWriter.setTypeAnnotations("type") | ||
ionWriter.writeStruct { | ||
ionWriter.setFieldName("name") | ||
ionWriter.writeSymbol(namedTypeDefinition.typeName) | ||
writeConstraints(ionWriter, namedTypeDefinition.typeDefinition.constraints) | ||
writeOpenContent(ionWriter, namedTypeDefinition.typeDefinition.openContent) | ||
} | ||
} | ||
|
||
override fun writeTypeArg(ionWriter: IonWriter, typeArg: TypeArgument) { | ||
if (typeArg.nullability == TypeArgument.Nullability.OrNull) { | ||
ionWriter.addTypeAnnotation("\$null_or") | ||
} | ||
|
||
when (typeArg) { | ||
is TypeArgument.Import -> ionWriter.writeStruct { | ||
ionWriter.setFieldName("id") | ||
ionWriter.writeString(typeArg.schemaId) | ||
ionWriter.setFieldName("type") | ||
ionWriter.writeSymbol(typeArg.typeName) | ||
} | ||
is TypeArgument.InlineType -> ionWriter.writeStruct { | ||
writeConstraints(ionWriter, typeArg.typeDefinition.constraints) | ||
writeOpenContent(ionWriter, typeArg.typeDefinition.openContent) | ||
} | ||
is TypeArgument.Reference -> ionWriter.writeSymbol(typeArg.typeName) | ||
} | ||
} | ||
|
||
override fun writeVariablyOccurringTypeArg(ionWriter: IonWriter, varTypeArg: VariablyOccurringTypeArgument, elideOccursValue: DiscreteIntRange) { | ||
if (varTypeArg.occurs == elideOccursValue) { | ||
writeTypeArg(ionWriter, varTypeArg.typeArg) | ||
} else { | ||
ionWriter.writeStruct { | ||
setFieldName("occurs") | ||
writeRange(varTypeArg.occurs) | ||
if (varTypeArg.typeArg.nullability == TypeArgument.Nullability.None && varTypeArg.typeArg is TypeArgument.InlineType) { | ||
writeConstraints(ionWriter, varTypeArg.typeArg.typeDefinition.constraints) | ||
writeOpenContent(ionWriter, varTypeArg.typeArg.typeDefinition.openContent) | ||
} else { | ||
setFieldName("type") | ||
writeTypeArg(ionWriter, varTypeArg.typeArg) | ||
} | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* Writes a type that exists outside the context of any schema. | ||
*/ | ||
fun writeOrphanedTypeDefinition(ionWriter: IonWriter, typeDefinition: TypeDefinition) { | ||
ionWriter.setTypeAnnotations("type") | ||
ionWriter.writeStruct { | ||
writeConstraints(ionWriter, typeDefinition.constraints) | ||
writeOpenContent(ionWriter, typeDefinition.openContent) | ||
} | ||
} | ||
|
||
private fun writeOpenContent(ionWriter: IonWriter, openContentFields: OpenContentFields) { | ||
for ((fieldName, fieldValue) in openContentFields) { | ||
ionWriter.setFieldName(fieldName) | ||
fieldValue.writeTo(ionWriter) | ||
} | ||
} | ||
|
||
private fun writeConstraints(ionWriter: IonWriter, constraints: Set<Constraint>) { | ||
for (c in constraints) { | ||
constraintWriters[c::class]?.writeTo(ionWriter, c) | ||
?: TODO("Constraint not supported in Ion Schema 2.0: ${c::class}") | ||
} | ||
} | ||
} |
28 changes: 28 additions & 0 deletions
28
ion-schema/src/main/kotlin/com/amazon/ionschema/writer/internal/VersionedIonSchemaWriter.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
package com.amazon.ionschema.writer.internal | ||
|
||
import com.amazon.ion.IonWriter | ||
import com.amazon.ionschema.model.ExperimentalIonSchemaModel | ||
import com.amazon.ionschema.model.NamedTypeDefinition | ||
import com.amazon.ionschema.model.SchemaDocument | ||
import com.amazon.ionschema.model.TypeDefinition | ||
|
||
@OptIn(ExperimentalIonSchemaModel::class) | ||
interface VersionedIonSchemaWriter { | ||
/** | ||
* Writes a [SchemaDocument]. | ||
*/ | ||
fun writeSchema(ionWriter: IonWriter, schemaDocument: SchemaDocument) | ||
|
||
/** | ||
* Writes an orphaned [TypeDefinition]—that is an anonymous type definition that does not belong to any schema. | ||
*/ | ||
fun writeType(ionWriter: IonWriter, typeDefinition: TypeDefinition) | ||
|
||
/** | ||
* Writes a [NamedTypeDefinition]. | ||
*/ | ||
fun writeNamedType(ionWriter: IonWriter, namedTypeDefinition: NamedTypeDefinition) | ||
} |
36 changes: 36 additions & 0 deletions
36
ion-schema/src/test/kotlin/com/amazon/ionschema/writer/IonSchemaWriterTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
package com.amazon.ionschema.writer | ||
|
||
import com.amazon.ionschema.ION | ||
import com.amazon.ionschema.IonSchemaVersion | ||
import com.amazon.ionschema.assertEqualIon | ||
import com.amazon.ionschema.model.ExperimentalIonSchemaModel | ||
import com.amazon.ionschema.model.SchemaDocument | ||
import org.junit.jupiter.api.Test | ||
import org.junit.jupiter.api.assertThrows | ||
|
||
@OptIn(ExperimentalIonSchemaModel::class) | ||
class IonSchemaWriterTest { | ||
// The purpose of these tests is just to check that it delegates to the correct writer implementation. | ||
// Testing the actual serialization is done in WriterTests.kt | ||
|
||
@Test | ||
fun `IonSchemaWriter throw UnsupportedOperationException for ISL 1 0`() { | ||
val writer = ION.newTextWriter(StringBuilder()) | ||
val schema = SchemaDocument("schema.isl", IonSchemaVersion.v1_0, emptyList()) | ||
assertThrows<NotImplementedError> { | ||
IonSchemaWriter.writeSchema(writer, schema) | ||
} | ||
} | ||
|
||
@Test | ||
fun `IonSchemaWriter writes a schema document for ISL 2 0`() { | ||
val schema = SchemaDocument("schema.isl", IonSchemaVersion.v2_0, emptyList()) | ||
// Since there's no content added to the schema, we expect just a version marker | ||
assertEqualIon("\$ion_schema_2_0 ") { | ||
IonSchemaWriter.writeSchema(it, schema) | ||
} | ||
} | ||
} |
Oops, something went wrong.