diff --git a/smithy-model/src/main/java/software/amazon/smithy/model/loader/Prelude.java b/smithy-model/src/main/java/software/amazon/smithy/model/loader/Prelude.java index e7cb43c8435..d11ef52c4cb 100644 --- a/smithy-model/src/main/java/software/amazon/smithy/model/loader/Prelude.java +++ b/smithy-model/src/main/java/software/amazon/smithy/model/loader/Prelude.java @@ -15,88 +15,9 @@ package software.amazon.smithy.model.loader; -import java.util.List; -import java.util.Set; -import java.util.stream.Collectors; import software.amazon.smithy.model.Model; -import software.amazon.smithy.model.shapes.BigDecimalShape; -import software.amazon.smithy.model.shapes.BigIntegerShape; -import software.amazon.smithy.model.shapes.BlobShape; -import software.amazon.smithy.model.shapes.BooleanShape; -import software.amazon.smithy.model.shapes.ByteShape; -import software.amazon.smithy.model.shapes.DocumentShape; -import software.amazon.smithy.model.shapes.DoubleShape; -import software.amazon.smithy.model.shapes.FloatShape; -import software.amazon.smithy.model.shapes.IntegerShape; -import software.amazon.smithy.model.shapes.LongShape; -import software.amazon.smithy.model.shapes.Shape; -import software.amazon.smithy.model.shapes.ShapeId; -import software.amazon.smithy.model.shapes.ShortShape; -import software.amazon.smithy.model.shapes.StringShape; -import software.amazon.smithy.model.shapes.TimestampShape; import software.amazon.smithy.model.shapes.ToShapeId; -import software.amazon.smithy.model.traits.AuthDefinitionTrait; -import software.amazon.smithy.model.traits.AuthTrait; -import software.amazon.smithy.model.traits.BoxTrait; -import software.amazon.smithy.model.traits.CorsTrait; -import software.amazon.smithy.model.traits.DeprecatedTrait; -import software.amazon.smithy.model.traits.DocumentationTrait; -import software.amazon.smithy.model.traits.EndpointTrait; -import software.amazon.smithy.model.traits.EnumTrait; -import software.amazon.smithy.model.traits.ErrorTrait; -import software.amazon.smithy.model.traits.EventHeaderTrait; -import software.amazon.smithy.model.traits.EventPayloadTrait; -import software.amazon.smithy.model.traits.ExamplesTrait; -import software.amazon.smithy.model.traits.ExternalDocumentationTrait; -import software.amazon.smithy.model.traits.HostLabelTrait; -import software.amazon.smithy.model.traits.HttpApiKeyAuthTrait; -import software.amazon.smithy.model.traits.HttpBasicAuthTrait; -import software.amazon.smithy.model.traits.HttpBearerAuthTrait; -import software.amazon.smithy.model.traits.HttpChecksumRequiredTrait; -import software.amazon.smithy.model.traits.HttpDigestAuthTrait; -import software.amazon.smithy.model.traits.HttpErrorTrait; -import software.amazon.smithy.model.traits.HttpHeaderTrait; -import software.amazon.smithy.model.traits.HttpLabelTrait; -import software.amazon.smithy.model.traits.HttpPayloadTrait; -import software.amazon.smithy.model.traits.HttpPrefixHeadersTrait; -import software.amazon.smithy.model.traits.HttpQueryTrait; -import software.amazon.smithy.model.traits.HttpTrait; -import software.amazon.smithy.model.traits.IdRefTrait; -import software.amazon.smithy.model.traits.IdempotencyTokenTrait; -import software.amazon.smithy.model.traits.IdempotentTrait; -import software.amazon.smithy.model.traits.JsonNameTrait; -import software.amazon.smithy.model.traits.LengthTrait; -import software.amazon.smithy.model.traits.MediaTypeTrait; -import software.amazon.smithy.model.traits.NoReplaceTrait; -import software.amazon.smithy.model.traits.OptionalAuthTrait; -import software.amazon.smithy.model.traits.PaginatedTrait; -import software.amazon.smithy.model.traits.PatternTrait; import software.amazon.smithy.model.traits.PrivateTrait; -import software.amazon.smithy.model.traits.ProtocolDefinitionTrait; -import software.amazon.smithy.model.traits.RangeTrait; -import software.amazon.smithy.model.traits.ReadonlyTrait; -import software.amazon.smithy.model.traits.ReferencesTrait; -import software.amazon.smithy.model.traits.RequiredTrait; -import software.amazon.smithy.model.traits.RequiresLengthTrait; -import software.amazon.smithy.model.traits.ResourceIdentifierTrait; -import software.amazon.smithy.model.traits.RetryableTrait; -import software.amazon.smithy.model.traits.SensitiveTrait; -import software.amazon.smithy.model.traits.SinceTrait; -import software.amazon.smithy.model.traits.StreamingTrait; -import software.amazon.smithy.model.traits.SuppressTrait; -import software.amazon.smithy.model.traits.TagsTrait; -import software.amazon.smithy.model.traits.TimestampFormatTrait; -import software.amazon.smithy.model.traits.TitleTrait; -import software.amazon.smithy.model.traits.TraitDefinition; -import software.amazon.smithy.model.traits.TraitFactory; -import software.amazon.smithy.model.traits.UniqueItemsTrait; -import software.amazon.smithy.model.traits.UnstableTrait; -import software.amazon.smithy.model.traits.XmlAttributeTrait; -import software.amazon.smithy.model.traits.XmlFlattenedTrait; -import software.amazon.smithy.model.traits.XmlNameTrait; -import software.amazon.smithy.model.traits.XmlNamespaceTrait; -import software.amazon.smithy.utils.ListUtils; -import software.amazon.smithy.utils.SetUtils; /** * Represents the prelude model available to every Smithy model. @@ -110,110 +31,10 @@ * result in infinite recursion while loading the prelude model. */ public final class Prelude { + /** The Smithy prelude namespace. */ public static final String NAMESPACE = "smithy.api"; - private static final List PUBLIC_PRELUDE_SHAPES = ListUtils.of( - StringShape.builder().id(NAMESPACE + "#String").build(), - BlobShape.builder().id(NAMESPACE + "#Blob").build(), - BigIntegerShape.builder().id(NAMESPACE + "#BigInteger").build(), - BigDecimalShape.builder().id(NAMESPACE + "#BigDecimal").build(), - TimestampShape.builder().id(NAMESPACE + "#Timestamp").build(), - DocumentShape.builder().id(NAMESPACE + "#Document").build(), - BooleanShape.builder().id(NAMESPACE + "#Boolean").addTrait(new BoxTrait()).build(), - BooleanShape.builder().id(NAMESPACE + "#PrimitiveBoolean").build(), - ByteShape.builder().id(NAMESPACE + "#Byte").addTrait(new BoxTrait()).build(), - ByteShape.builder().id(NAMESPACE + "#PrimitiveByte").build(), - ShortShape.builder().id(NAMESPACE + "#Short").addTrait(new BoxTrait()).build(), - ShortShape.builder().id(NAMESPACE + "#PrimitiveShort").build(), - IntegerShape.builder().id(NAMESPACE + "#Integer").addTrait(new BoxTrait()).build(), - IntegerShape.builder().id(NAMESPACE + "#PrimitiveInteger").build(), - LongShape.builder().id(NAMESPACE + "#Long").addTrait(new BoxTrait()).build(), - LongShape.builder().id(NAMESPACE + "#PrimitiveLong").build(), - FloatShape.builder().id(NAMESPACE + "#Float").addTrait(new BoxTrait()).build(), - FloatShape.builder().id(NAMESPACE + "#PrimitiveFloat").build(), - DoubleShape.builder().id(NAMESPACE + "#Double").addTrait(new BoxTrait()).build(), - DoubleShape.builder().id(NAMESPACE + "#PrimitiveDouble").build()); - - /** - * This list of public prelude traits is manually maintained and must match the - * public prelude traits defined in prelude-traits.smithy. The Prelude itself - * cannot refer to the loaded model because the Prelude abstraction is queried - * while loading the prelude model. - * - *

A check is made each time the prelude is first loaded to ensure that the - * actual traits defined in the prelude match the traits in this list. As long - * as changes are tested before releasing, they should never get out of sync. - */ - private static final Set PRELUDE_TRAITS = SetUtils.of( - AuthTrait.ID, - BoxTrait.ID, - CorsTrait.ID, - DeprecatedTrait.ID, - DocumentationTrait.ID, - EndpointTrait.ID, - EnumTrait.ID, - ErrorTrait.ID, - EventHeaderTrait.ID, - EventPayloadTrait.ID, - ExamplesTrait.ID, - ExternalDocumentationTrait.ID, - HostLabelTrait.ID, - HttpChecksumRequiredTrait.ID, - HttpErrorTrait.ID, - HttpHeaderTrait.ID, - HttpLabelTrait.ID, - HttpPayloadTrait.ID, - HttpPrefixHeadersTrait.ID, - HttpQueryTrait.ID, - HttpTrait.ID, - IdRefTrait.ID, - IdempotencyTokenTrait.ID, - IdempotentTrait.ID, - JsonNameTrait.ID, - LengthTrait.ID, - NoReplaceTrait.ID, - MediaTypeTrait.ID, - PaginatedTrait.ID, - PatternTrait.ID, - PrivateTrait.ID, - ProtocolDefinitionTrait.ID, - AuthDefinitionTrait.ID, - HttpApiKeyAuthTrait.ID, - HttpBasicAuthTrait.ID, - HttpDigestAuthTrait.ID, - HttpBearerAuthTrait.ID, - OptionalAuthTrait.ID, - RangeTrait.ID, - ReadonlyTrait.ID, - ReferencesTrait.ID, - RequiresLengthTrait.ID, - RequiredTrait.ID, - ResourceIdentifierTrait.ID, - RetryableTrait.ID, - SensitiveTrait.ID, - SinceTrait.ID, - StreamingTrait.ID, - SuppressTrait.ID, - TagsTrait.ID, - TimestampFormatTrait.ID, - TitleTrait.ID, - TraitDefinition.ID, - UniqueItemsTrait.ID, - UnstableTrait.ID, - XmlAttributeTrait.ID, - XmlFlattenedTrait.ID, - XmlNameTrait.ID, - XmlNamespaceTrait.ID); - - private static final Set PUBLIC_PRELUDE_SHAPE_IDS; - - static { - PUBLIC_PRELUDE_SHAPE_IDS = PUBLIC_PRELUDE_SHAPES.stream() - .map(Shape::getId) - .collect(SetUtils.toUnmodifiableSet()); - } - private Prelude() {} /** @@ -237,8 +58,9 @@ public static boolean isPreludeShape(ToShapeId id) { * @return Returns true if the shape is a public prelude shape. */ public static boolean isPublicPreludeShape(ToShapeId id) { - ShapeId toId = id.toShapeId(); - return PUBLIC_PRELUDE_SHAPE_IDS.contains(toId) || PRELUDE_TRAITS.contains(toId); + return getPreludeModel().getShape(id.toShapeId()) + .filter(shape -> !shape.hasTrait(PrivateTrait.class)) + .isPresent(); } // Used by the ModelAssembler to load the prelude into another visitor. @@ -251,33 +73,12 @@ private static final class PreludeHolder { private static final Model PRELUDE = loadPrelude(); private static Model loadPrelude() { - TraitFactory traitFactory = ModelAssembler.LazyTraitFactoryHolder.INSTANCE; - ModelAssembler assembler = Model.assembler() + return Model.assembler() .disablePrelude() - .traitFactory(traitFactory) - .addImport(Prelude.class.getResource("prelude-traits.smithy")); - - for (Shape shape : PUBLIC_PRELUDE_SHAPES) { - assembler.addShape(shape); - } - - Model preludeModel = assembler.assemble().unwrap(); - - // Sanity check to ensure that the prelude model and the tracked prelude traits are consistent. - // TODO: Can this be moved to a build step in Gradle? - for (Shape trait : preludeModel.getShapesWithTrait(TraitDefinition.class)) { - if (!PRELUDE_TRAITS.contains(trait.getId())) { - throw new IllegalStateException( - "PRELUDE_TRAITS property of prelude is inconsistent with the traits defined in the " - + "prelude-traits.smithy file. This property MUST be kept consistent with the file. " - + PRELUDE_TRAITS + " in PRELUDE_TRAITS vs " - + preludeModel.getShapesWithTrait(TraitDefinition.class).stream() - .map(Shape::getId) - .collect(Collectors.toList())); - } - } - - return preludeModel; + .traitFactory(ModelAssembler.LazyTraitFactoryHolder.INSTANCE) + .addImport(Prelude.class.getResource("prelude.smithy")) + .assemble() + .unwrap(); } } } diff --git a/smithy-model/src/main/resources/software/amazon/smithy/model/loader/prelude-traits.smithy b/smithy-model/src/main/resources/software/amazon/smithy/model/loader/prelude.smithy similarity index 97% rename from smithy-model/src/main/resources/software/amazon/smithy/model/loader/prelude-traits.smithy rename to smithy-model/src/main/resources/software/amazon/smithy/model/loader/prelude.smithy index 89aa0ceee57..807b55059c5 100644 --- a/smithy-model/src/main/resources/software/amazon/smithy/model/loader/prelude-traits.smithy +++ b/smithy-model/src/main/resources/software/amazon/smithy/model/loader/prelude.smithy @@ -2,6 +2,57 @@ $version: "1.0" namespace smithy.api +// ------ Prelude shapes + +string String + +blob Blob + +bigInteger BigInteger + +bigDecimal BigDecimal + +timestamp Timestamp + +document Document + +@box +boolean Boolean + +boolean PrimitiveBoolean + +@box +byte Byte + +byte PrimitiveByte + +@box +short Short + +short PrimitiveShort + +@box +integer Integer + +integer PrimitiveInteger + +@box +long Long + +long PrimitiveLong + +@box +float Float + +float PrimitiveFloat + +@box +double Double + +double PrimitiveDouble + +// ------ Prelude traits + /// Makes a shape a trait. @trait(selector: ":is(simpleType, list, map, set, structure, union)") @tags(["diff.error.add", "diff.error.remove"])