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.

External definitions

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#>.
        

Shape type constructors

The set of defined types forms a type construction language with RDF-based atomic terms and ADTs (Algebraic Data Types).
      typedef (
        ResourceShape
        or LiteralShape
        or RecordShape
        or AnyOfShape
        or OptionalShape
        or SetShape
        or ListShape
        or MapShape
      ) Shape;
      

ShapeID

Shapes are referenced by ShapeID.

          typedef (NamedNode or BlankNode) ShapeID;
        

ShapeBase

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 type

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 interface

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 type

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 type

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 interface

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 type

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 type

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 type

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 type

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 type

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 interface

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;
          };
          

Property paths

PropertyPath interface

PropertyPath describes a property path in RDF graph.

        typedef (
          PredicatePath or
          SequencePath or
          InversePath or
          AlternativePath or
          ZeroOrMorePath or
          ZeroOrOnePath or
          OneOrMorePath
        ) PropertyPath;
        

PredicatePath path kind

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 path kind

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 path kind

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 path kind

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 path kind

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 path kind

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 path kind

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;
          };
          

Workflow operations

The specification of operations on the described data types includes the following methods:
      [Exposed] interface RamOperations {
        sequence<unknown> frame(FrameParams params);
        sequence<Quad> flatten(FlattenParams params);
        ConstructQuery generateQuery(GenerateQueryParams params);
        /* TODO: ValidationReport validate(ValidateParams params); */
      };
      

frame() operation

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.

Frame matching mode

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:

In 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 interface

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);
          };
          

Framing algorithm

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:

  1. Let rootCandidates be a set of all NamedNode and BlankNode terms from graph

  2. For M of FrameShape( rootShape, rootCandidates, rootStrict) match M:

Frame( Shape shape, FrameCandidates candidates, boolean strict ):

  1. Let required be strict unless shape is lenient.

  2. For M of FrameS( shape, candidates, required) where S is a type of shape, match M:

Frame (ResourceShape or LiteralShape)( shape, candidates, strict):

  1. For candidate of candidates:

    1. If shape matches term candidate:

      TODO

Frame RecordShape( shape, candidates, strict):

TODO

Frame AnyOfShape( shape, candidates, strict):

TODO

  1. Let unmatched be an empty set

  2. 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() operation

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() operation

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.

Errors

CyclicMatch, ShapeMismatch.

Shapes for RAMP shapes

RAMP shape definitions for this specification can be found here: schema.ramp.ttl.