public final class ModelAssembler
extends java.lang.Object
Model
from documents, files, shapes, and
other sources.
Validation vents are aggregated into a Set
to ensure that
duplicate events are not emitted.
Smithy models found on the class path can be discovered using
model discovery. Model discovery must be explicitly requested of
a ModelAssembler
by invoking discoverModels()
or
discoverModels(ClassLoader)
.
Model.assembler()
Modifier and Type | Field and Description |
---|---|
static java.lang.String |
ALLOW_UNKNOWN_TRAITS
Allow unknown traits rather than fail.
|
static java.lang.String |
DISABLE_JAR_CACHE
Sets
URLConnection.setUseCaches(boolean) to false. |
Constructor and Description |
---|
ModelAssembler() |
Modifier and Type | Method and Description |
---|---|
ModelAssembler |
addDocumentNode(Node document)
Adds a parsed JSON model file as a
Node to the assembler. |
ModelAssembler |
addImport(java.nio.file.Path importPath)
Adds an import to the assembler.
|
ModelAssembler |
addImport(java.lang.String importPath)
Adds an import to the assembler.
|
ModelAssembler |
addImport(java.net.URL url)
Adds an import to the assembler from a URL.
|
ModelAssembler |
addModel(Model model)
Merges a loaded model into the model assembler.
|
ModelAssembler |
addShape(Shape shape)
Explicitly injects a shape into the assembled model.
|
ModelAssembler |
addShapes(Shape... shapes)
Explicitly injects multiple shapes into the assembled model.
|
ModelAssembler |
addTrait(ShapeId target,
Trait trait)
Explicitly adds a trait to a shape in the assembled model.
|
ModelAssembler |
addUnparsedModel(java.lang.String sourceLocation,
java.lang.String model)
Adds a string containing an unparsed model to the assembler.
|
ModelAssembler |
addValidator(Validator validator)
Registers a validator to be used when validating the model.
|
ValidatedResult<Model> |
assemble()
Assembles the model and returns the validated result.
|
ModelAssembler |
copy()
Creates a copy of the current model assembler.
|
ModelAssembler |
disablePrelude()
Disables automatically loading the prelude models.
|
ModelAssembler |
disableValidation()
Disables additional validation of the model.
|
ModelAssembler |
discoverModels()
Discovers models by merging in all models returns by
ModelDiscovery
manifests using the thread context ClassLoader . |
ModelAssembler |
discoverModels(java.lang.ClassLoader loader)
Discovers models by merging in all models returns by
ModelDiscovery
manifests using the provided ClassLoader . |
ModelAssembler |
putMetadata(java.lang.String name,
Node value)
Adds metadata to the model.
|
ModelAssembler |
putProperty(java.lang.String setting,
java.lang.Object value)
Puts a configuration property on the ModelAssembler.
|
ModelAssembler |
removeProperty(java.lang.String setting)
Removes a setting from the ModelAssembler.
|
ModelAssembler |
reset()
Resets the state of the ModelAssembler.
|
ModelAssembler |
traitFactory(TraitFactory traitFactory)
Uses a custom
TraitFactory to resolve and configure traits. |
ModelAssembler |
validationEventListener(java.util.function.Consumer<ValidationEvent> eventListener)
Sets a listener that is invoked each time a ValidationEvent is encountered
while loading and validating the model.
|
ModelAssembler |
validatorFactory(ValidatorFactory validatorFactory)
Sets a custom
ValidatorFactory used to dynamically resolve
validator definitions. |
public static final java.lang.String ALLOW_UNKNOWN_TRAITS
public static final java.lang.String DISABLE_JAR_CACHE
URLConnection.setUseCaches(boolean)
to false.
When running in a build environment, using caches can cause exceptions like `java.util.zip.ZipException: ZipFile invalid LOC header (bad signature)` because a previously loaded JAR might change between builds. The "assembler.disableJarCache" setting should be set to true when embedding Smithy into an environment where this can occur.
public ModelAssembler copy()
public ModelAssembler reset()
The following properties of the ModelAssembler are cleared when this method is called:
addValidator(software.amazon.smithy.model.validation.Validator)
addImport(java.lang.String)
addDocumentNode(software.amazon.smithy.model.node.Node)
addUnparsedModel(java.lang.String, java.lang.String)
addModel(software.amazon.smithy.model.Model)
addModel(software.amazon.smithy.model.Model)
putMetadata(java.lang.String, software.amazon.smithy.model.node.Node)
validationEventListener(Consumer)
The state of disablePrelude
is reset such that the prelude
is no longer disabled after calling reset
.
public ModelAssembler traitFactory(TraitFactory traitFactory)
TraitFactory
to resolve and configure traits.traitFactory
- Trait factory to use instead of the default.public ModelAssembler validatorFactory(ValidatorFactory validatorFactory)
ValidatorFactory
used to dynamically resolve
validator definitions.
Note that if you do not provide an explicit validatorFactory, a default factory is utilized that uses service discovery.
validatorFactory
- Validator factory to use.public ModelAssembler addValidator(Validator validator)
validator
- Validator to register.public ModelAssembler addUnparsedModel(java.lang.String sourceLocation, java.lang.String model)
The provided sourceLocation
string must end with
".json" or ".smithy" to be parsed correctly.
sourceLocation
- Source location to assume for the unparsed content.model
- Unparsed model source.public ModelAssembler addDocumentNode(Node document)
Node
to the assembler.document
- Parsed document node to add.public ModelAssembler addImport(java.lang.String importPath)
importPath
- Import path to add.addImport(Path)
public ModelAssembler addImport(java.nio.file.Path importPath)
If a directory is found, all ".json" and ".ion" files that contain a "smithy" key-value pair found in the directory and any subdirectories are imported into the model.
importPath
- Import path to add.public ModelAssembler addImport(java.net.URL url)
The provided URL can point to a .json model, .smithy model, or a .jar file that contains Smithy models.
Model model = Model.assembler()
.addImport(getClass().getClassLoader().getResource("model.json"))
.assemble()
.unwrap();
url
- Resource URL to load and add.public ModelAssembler disablePrelude()
public ModelAssembler addShape(Shape shape)
shape
- Shape to add.public ModelAssembler addShapes(Shape... shapes)
shapes
- Shapes to add.public ModelAssembler addTrait(ShapeId target, Trait trait)
target
- Shape to add the trait to.trait
- Trait to add.public ModelAssembler addModel(Model model)
model
- Model to merge in.public ModelAssembler putMetadata(java.lang.String name, Node value)
name
- Metadata key to set.value
- Metadata value to set.public ModelAssembler discoverModels(java.lang.ClassLoader loader)
ModelDiscovery
manifests using the provided ClassLoader
.loader
- Class loader to use to discover models.public ModelAssembler discoverModels()
ModelDiscovery
manifests using the thread context ClassLoader
.public ModelAssembler putProperty(java.lang.String setting, java.lang.Object value)
Any number of properties can be given to the model assembler to
affect how models are loaded. Some properties like ALLOW_UNKNOWN_TRAITS
are built-in properties, while other properties can be custom
properties that are specific to certain ModelLoader
implementations.
The following example configures the ModelAssembler to emit warnings for unknown traits rather than fail:
ModelAssembler assembler = Model.assembler();
assembler.putProperty(ModelAssembler.ALLOW_UNKNOWN_TRAITS, true);
setting
- Name of the property to put.value
- Value to set for the property.public ModelAssembler removeProperty(java.lang.String setting)
setting
- Setting to remove.public ModelAssembler disableValidation()
public ModelAssembler validationEventListener(java.util.function.Consumer<ValidationEvent> eventListener)
The consumer could be invoked simultaneously by multiple threads. It's up to the consumer to perform any necessary synchronization. Providing an event listener is useful for things like CLIs so that events can be streamed to stdout as soon as they are encountered, rather than waiting until the entire model is parsed and validated.
eventListener
- Listener invoked for each ValidationEvent.public ValidatedResult<Model> assemble()
Assembling models is a multi-step process that revolves around
ModelFile
s. ModelFiles are essentially files that contain
localized definitions of shapes and metadata. Some model files use
forward references and can't be fully resolved until all other model
files have been loaded. To achieve this, the assembler first creates a
model file that represents manually added shapes, traits, validators,
etc., and then parses each given import. Parsing an import is used to
create zero or more ModelFiles by parsing .json, .smithy, and
.jar files.
After the parsing phase, each model file returns the metadata
defined in the file using ModelFile.metadata()
and the set of
shape IDs that were defined in the file using ModelFile.shapeIds()
.
The metadata across each file is merged together using the rules
defined in the Smithy specification.
Next, the assembler calls ModelFile.resolveShapes(java.util.Set<software.amazon.smithy.model.shapes.ShapeId>, java.util.function.Function<software.amazon.smithy.model.shapes.ShapeId, software.amazon.smithy.model.shapes.ShapeType>)
on each
ModelFile which resolves any forward references, creates traits, and
returns all of the traits created in the file. The assembler passes in
the set of found shapes IDs along with a function that can be used to
get the ShapeType
of any defined shape (this is used to coerce
annotation trait values into the appropriate type for a trait).
The assembler aggregates and merges the traits applied across all model
files using the merge rules defined in the Smithy specification.
Next, the assembler invokes ModelFile.createShapes(software.amazon.smithy.model.loader.TraitContainer)
, passing
in all of the traits defined across every model file. This method
causes a ModelFile to apply these traits to any shape in the ModelFile,
build each shape, and return the built shapes. The assembler then
aggregates all of the created traits, performs conflict resolution,
and builds a Model
from the shapes and loaded metadata. A shape
is allowed to be defined in multiple model files if the conflicting
shapes are equivalent after all traits have been applied to both
shapes.