module JSONSchema.Draft4.Spec where
import Import
import Data.Maybe (fromMaybe)
import Data.Profunctor (Profunctor(..))
import JSONSchema.Draft4.Failure
import JSONSchema.Draft4.Schema (Schema(..),
emptySchema)
import JSONSchema.Fetch (SchemaWithURI(..),
URISchemaMap(..))
import qualified JSONSchema.Fetch as FE
import JSONSchema.Types (Spec(..))
import qualified JSONSchema.Types as JT
import JSONSchema.Validator.Draft4
import JSONSchema.Validator.Reference (BaseURI(..),
Scope(..),
updateResolutionScope)
embedded :: Schema -> ([Schema], [Schema])
embedded s =
JT.embedded (d4Spec mempty mempty (Scope s Nothing (BaseURI Nothing))) s
specValidate
:: URISchemaMap Schema
-> SchemaWithURI Schema
-> Value
-> [ValidatorFailure]
specValidate schemaMap sw =
JT.validate (d4Spec schemaMap visited scope) (_swSchema sw)
where
visited :: VisitedSchemas
visited = VisitedSchemas [(Nothing, Nothing)]
scope :: Scope Schema
scope = Scope
{ _topLevelDocument = _swSchema sw
, _documentURI = _swURI sw
, _currentBaseURI = updateResolutionScope (BaseURI (_swURI sw))
(_schemaId (_swSchema sw))
}
validateSubschema
:: URISchemaMap Schema
-> VisitedSchemas
-> Scope Schema
-> Schema
-> Value
-> [ValidatorFailure]
validateSubschema schemaMap visited scope schema =
JT.validate (d4Spec schemaMap visited newScope) schema
where
newScope :: Scope Schema
newScope = scope
{ _currentBaseURI = updateResolutionScope (_currentBaseURI scope)
(_schemaId schema)
}
d4Spec
:: URISchemaMap Schema
-> VisitedSchemas
-> Scope Schema
-> Spec Schema ValidatorFailure
d4Spec schemaMap visited scope = Spec $
[ dimap
(fmap Ref . _schemaRef)
FailureRef
(refValidator (FE.getReference schemaMap) updateScope valRef visited scope)
]
<> fmap (lmap disableIfRefPresent)
[ dimap (fmap MultipleOf . _schemaMultipleOf) FailureMultipleOf multipleOfValidator
, dimap
(\s -> Maximum (fromMaybe False (_schemaExclusiveMaximum s)) <$> _schemaMaximum s)
FailureMaximum
maximumValidator
, dimap
(\s -> Minimum (fromMaybe False (_schemaExclusiveMinimum s)) <$> _schemaMinimum s)
FailureMinimum
minimumValidator
, dimap (fmap MaxLength . _schemaMaxLength) FailureMaxLength maxLengthValidator
, dimap (fmap MinLength . _schemaMinLength) FailureMinLength minLengthValidator
, dimap (fmap PatternValidator . _schemaPattern) FailurePattern patternValidator
, dimap (fmap MaxItems . _schemaMaxItems) FailureMaxItems maxItemsValidator
, dimap (fmap MinItems . _schemaMinItems) FailureMinItems minItemsValidator
, dimap (fmap UniqueItems . _schemaUniqueItems) FailureUniqueItems uniqueItemsValidator
, dimap
(\s -> ItemsRelated
{ _irItems = _schemaItems s
, _irAdditional = _schemaAdditionalItems s
})
(\err -> case err of
IRInvalidItems e -> FailureItems e
IRInvalidAdditional e -> FailureAdditionalItems e)
(itemsRelatedValidator descend)
, lmap (fmap Definitions . _schemaDefinitions) definitionsEmbedded
, dimap
(fmap MaxProperties . _schemaMaxProperties)
FailureMaxProperties
maxPropertiesValidator
, dimap
(fmap MinProperties . _schemaMinProperties)
FailureMinProperties
minPropertiesValidator
, dimap (fmap Required . _schemaRequired) FailureRequired requiredValidator
, dimap
(fmap DependenciesValidator . _schemaDependencies)
FailureDependencies
(dependenciesValidator descend)
, dimap
(\s -> PropertiesRelated
{ _propProperties = _schemaProperties s
, _propPattern = _schemaPatternProperties s
, _propAdditional = _schemaAdditionalProperties s
})
FailurePropertiesRelated
(propertiesRelatedValidator descend)
, dimap (fmap EnumValidator . _schemaEnum) FailureEnum enumValidator
, dimap (fmap TypeContext . _schemaType) FailureType typeValidator
, dimap (fmap AllOf . _schemaAllOf) FailureAllOf (allOfValidator lateral)
, dimap (fmap AnyOf . _schemaAnyOf) FailureAnyOf (anyOfValidator lateral)
, dimap (fmap OneOf . _schemaOneOf) FailureOneOf (oneOfValidator lateral)
, dimap (fmap NotValidator . _schemaNot) FailureNot (notValidator lateral)
]
where
disableIfRefPresent :: Schema -> Schema
disableIfRefPresent schema =
case _schemaRef schema of
Nothing -> schema
Just _ -> emptySchema
updateScope :: BaseURI -> Schema -> BaseURI
updateScope uri schema = updateResolutionScope uri (_schemaId schema)
valRef
:: VisitedSchemas
-> Scope Schema
-> Schema
-> Value
-> [ValidatorFailure]
valRef vis sc = JT.validate (d4Spec schemaMap vis sc)
descend :: Schema -> Value -> [ValidatorFailure]
descend = validateSubschema schemaMap mempty scope
lateral :: Schema -> Value -> [ValidatorFailure]
lateral = validateSubschema schemaMap visited scope