RAMP (RDF ADT Mapping) is a type construction language, specification and an implementation of mapping operations between RDF graphs and structured data types.
Changes to this document may be tracked at https://github.com/ramp-shapes/ramp-shapes.github.io .
This draft is implemented by ram-shapes@0.10.0
NPM package.
Commonly used types and values from ECMAScript include string, number, boolean, null (and null type), undefined, unknown.
The specification references [[[WebIDL]]] spec: Exposed.
The specification references the following RDF types defined in [[!rdfjs]] spec: Term, NamedNode, BlankNode, Literal, Quad.
The specification references the following types from [[!rdfjs-dataset]]: Dataset.
The specification references the following types from [[!SPARQL.js]] query AST: ConstructQuery.
The specification uses the following prefix definitions for examples:
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>. @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>. @prefix xsd: <http://www.w3.org/2001/XMLSchema#>. @prefix owl: <http://www.w3.org/2002/07/owl#>. @prefix dctypes: <http://purl.org/dc/dcmitype/>. @prefix sc: <http://iiif.io/api/presentation/2#>. @prefix ramp: <http://ramp-shapes.github.io/schema#>. @prefix ex: <http://example.com/shapes#>.
typedef ( ResourceShape or LiteralShape or RecordShape or AnyOfShape or OptionalShape or SetShape or ListShape or MapShape ) Shape;
Shapes are referenced by ShapeID.
typedef (NamedNode or BlankNode) ShapeID;
Basic shapes properties are id and lenient.
lenient property sets non-strict matching mode for shape. See frame() for matching mode description.
[Exposed] interface ShapeBase { readonly attribute ShapeID id; readonly attribute boolean? lenient; };
ResourceShape describes an RDF resource term, which is either an IRI or a blank node:
If onlyNamed flag is set then the shape will only match NamedNode but not BlankNode.
[Exposed] interface ResourceShape : ShapeBase { /** type == "resource" */ readonly attribute string type; readonly attribute boolean? onlyNamed; readonly attribute (NamedNode or BlankNode)? value; readonly attribute Vocabulary? vocabulary; };
Vocabulary describes a mapping between NamedNode terms and string keys. The mapping allows to refer to RDF resources by short names in by matching against terms dictionary.
[Exposed] interface Vocabulary { getter record<DOMString, NamedNode> terms(); };
LiteralShape describes an RDF literal term with its specified datatype,
language (if the datatype is rdf:langString
) and
value:
[Exposed] interface LiteralShape : ShapeBase { /** type == "literal" */ readonly attribute string type; readonly attribute NamedNode? datatype; readonly attribute string? language; readonly attribute Literal? value; };
RecordShape describes a product type of heterogeneous types accessible through named properties. Both typeProperties and properties define properties for a shape and the difference is when a candidate term must match given record shape if and only if all typeProperties matches, which allows to produce better diagnostic reports if typeProperties match but some of the properties does not.
[Exposed] interface RecordShape : ShapeBase { /** type == "record" */ readonly attribute string type; getter sequence<Property> typeProperties(); getter sequence<Property> properties(); };
Property describes a named property in a record type. It is specified by its name string, property path and value shape. A property with zero-length path allows to embed a different representation of the same subject, e.g. the subject IRI itself.
If transient flag is set then in frame() the framing result will be discarded; in flatten() the value for valueShape will be synthesized or an error will be thrown if it is not possible.
[Exposed] interface Property { readonly attribute string name; readonly attribute PropertyPath path; readonly attribute ShapeID valueShape; readonly attribute boolean? transient; };
AnyOfShape describes a sum (coproduct) type of several types. The variants are unordered, which means matching operations may produce results in arbitrary order when the same candidate term matches multiple variant types.
[Exposed] interface AnyOfShape : ShapeBase { /** type == "union" */ readonly attribute string type; getter sequence<ShapeID> variants(); };
OptionalShape describes a sum type of an empty unit type and a single type itemShape.
Although this type could also be represented as
a AnyOfShape by introducing a Nothing
unit type like
null in C-like languages, the optional type more closely resembles
the semantics of programming languages with either no explicit nothing
type or multiple such types instead (e.g. null and undefined
in ECMAScript).
[Exposed] interface OptionalShape : ShapeBase { /** type == "optional" */ readonly attribute string type; readonly attribute ShapeID itemShape; readonly attribute nullType? emptyValue; };
SetShape describes an unordered set of a single type itemShape.
If minCount or maxCount is specified then the shape will match only if matching set contains equal or more items than minCount and equal or less items than maxCount.
[Exposed] interface SetShape : ShapeBase { /** type == "set" */ readonly attribute string type; readonly attribute ShapeID itemShape; readonly attribute number? minCount; readonly attribute number? maxCount; };
ListShape describes an ordered set (sequence) of a single type itemShape.
By default a ListShape represents RDF list structures, however it is possible to override headPath, or tailPath property paths and nil term to describe other kinds of ordered structures.
[Exposed] interface ListShape : ShapeBase { /** type == "list" */ readonly attribute string type; readonly attribute ShapeID itemShape; /** @default rdf:first */ readonly attribute PropertyPath? headPath; /** @default rdf:rest */ readonly attribute PropertyPath? tailPath; /** @default rdf:nil */ readonly attribute NamedNode? nil; };
MapShape describes an unordered set (record) of items with type itemShape indexed by a key and (optionally) value.
Any nested shape value, datatype or language may be chosen as the key. When MapShape includes a nested map value with the same key, the key always refers to the innermost map shape. A key shape may be limited to non-composite types depending on the implementation.
[Exposed] interface MapShape : ShapeBase { /** type == "map" */ readonly attribute string type; readonly attribute ShapeReference key; readonly attribute ShapeReference? value; readonly attribute ShapeID itemShape; };
ShapeReference describes a reference to a candidate term matched by target Shape. A reference may target whole Term value or a specific part such as language or datatype of a Literal.
[Exposed] interface ShapeReference { readonly attribute ShapeID target; /** part in ("value" or "datatype" or "language") */ readonly attribute string? part; };
PropertyPath describes a property path in RDF graph.
typedef ( PredicatePath or SequencePath or InversePath or AlternativePath or ZeroOrMorePath or ZeroOrOnePath or OneOrMorePath ) PropertyPath;
PredicatePath describes a property path represented by a single NamedNode predicate.
[Exposed] interface PredicatePath { /** type == "predicate" */ readonly attribute string type; readonly attribute NamedNode predicate; };
SequencePath describes a property path which is an ordered sequence of PropertyPath elements.
[Exposed] interface SequencePath { /** type == "sequence" */ readonly attribute string type; getter sequence<PropertyPath> sequence_(); };
InversePath describes a property path which is an inverse of another PropertyPath.
[Exposed] interface InversePath { /** type == "inverse" */ readonly attribute string type; readonly attribute PropertyPath inverse; };
AlternativePath describes a property path which is a union of alternative PropertyPath elements.
[Exposed] interface AlternativePath { /** type == "alternative" */ readonly attribute string type; getter sequence<PropertyPath> alternatives(); };
ZeroOrMorePath describes a property path which is a zero or more repetitions of another PropertyPath.
[Exposed] interface ZeroOrMorePath { /** type == "zeroOrMore" */ readonly attribute string type; readonly attribute PropertyPath zeroOrMore; };
ZeroOrOnePath describes a property path which is a zero or one repetition of another PropertyPath.
[Exposed] interface ZeroOrOnePath { /** type == "zeroOrOne" */ readonly attribute string type; readonly attribute PropertyPath zeroOrOne; };
OneOrMorePath describes a property path which is a one or more repetitions of another PropertyPath.
[Exposed] interface OneOrMorePath { /** type == "oneOrMore" */ readonly attribute string type; readonly attribute PropertyPath oneOrMore; };
[Exposed] interface RamOperations { sequence<unknown> frame(FrameParams params); sequence<Quad> flatten(FlattenParams params); ConstructQuery generateQuery(GenerateQueryParams params); /* TODO: ValidationReport validate(ValidateParams params); */ };
frame() matches RDF dataset into values from entry shape shape and forms data structures corresponding to these shapes. This operation is usually referred to as RDF lowering (see [[!!XSPARQL]]).
dictionary FrameParams { required ShapeID shape; required Dataset dataset; ValueMapper? mapper; };
Returns: sequence<unknown>
— all found matches
where each one is an instance of shape.
The matching for each shape may operate in either strict
or
lenient
mode. The mode initializes as lenient
and propagates
downwards from shape, changing at these points:
strict
when matching other
properties.
true
then the mode switches to lenient
starting from that shape.
strict
mode a non-matching candidate term will be considered an error
which is reported to the caller. In lenient
mode non-matching candidate
terms are ignored and produce no matches for given shape.
ValueMapper describes two-way mapping between atomic RDF terms and "leaf"
data structures such as primitive types (number
, string
,
DataTime
, etc) for frame() and
flatten().
[Exposed] interface ValueMapper { unknown fromRdf(unknown value, Shape shape); unknown toRdf(unknown value, Shape shape); };
This section is a work-in-progress
Define type FrameCandidates to be sequence<Term>.
Define structure FrameMismatch ().
Define structure FrameCyclic ().
Define structure FrameMatch( unknown value, (FrameCandidates or null) candidate).
To determine the result of framing a Dataset graph into Shape rootShape in matching mode boolean rootStrict, the following algorithm is applied:
Let rootCandidates be a set of all NamedNode and BlankNode terms from graph
For M of FrameShape( rootShape, rootCandidates, rootStrict) match M:
On FrameMismatch continue the iteration.
On FrameCyclic throw Errors.CyclicMatch error.
On FrameMatch(value, _) yield value.
Frame( Shape shape, FrameCandidates candidates, boolean strict ):
Let required be strict unless shape is lenient.
For M of FrameS( shape, candidates, required) where S is a type of shape, match M:
On FrameMismatch:
If shape is lenient then yield FrameMismatch else throw Errors.ShapeMismatch error.
On FrameCyclic yield M.
On FrameMatch yield M.
Frame (ResourceShape or LiteralShape)( shape, candidates, strict):
For candidate of candidates:
If shape matches term candidate:
TODO
Frame RecordShape( shape, candidates, strict):
TODO
Frame AnyOfShape( shape, candidates, strict):
TODO
Let unmatched be an empty set
Add each candidate from candidates to unmatched
TODO
Frame OptionalShape( shape, candidates, strict):
TODO
Frame SetShape( shape, candidates, strict):
TODO
Frame ListShape( shape, candidates, strict):
TODO
Frame MapShape( shape, candidates, strict):
TODO
flatten() generates RDF dataset from value which must be an instance of shape entry point. This operation is usually referred to as RDF lifting (see [[XSPARQL]]).
dictionary FlattenParams { required ShapeID shape; required unknown value; ValueMapper? mapper; };
Returns: sequence<Quad>
— generated RDF dataset
content which may contain duplicate quads.
generateQuery() generates SPARQL CONSTRUCT query to fetch a subset of RDF graph data necessary to match given shape.
dictionary GenerateQueryParams { required ShapeID shape; NamedNode? base; record<DOMString, string>? prefixes; };
Returns: ConstructQuery
— generated query in [[SPARQL.js]]
query AST representation with specified base and prefixes for
graph terms.
CyclicMatch, ShapeMismatch.
RAMP shape definitions for this specification can be found here: schema.ramp.ttl.