IriMapping constructor

const IriMapping([
  1. String? template
])

Creates an IRI mapping template for property-specific IRI generation.

Use this constructor to customize how a specific property should be transformed into an IRI term in the RDF graph.

Template System

The template supports a powerful placeholder system:

  • Property placeholders: {propertyName} - replaced with the property value
  • Context variables: {+contextVar} or {contextVar} - resolved from providers
  • Reserved expansion: Use {+variable} to preserve URI structure (like /)

Context variables are resolved from:

  • Global providers in initRdfMapper() (e.g., baseUriProvider: () => 'https://api.example.com')
  • Class properties annotated with @RdfProvides('variableName')
  • Parent resource's IRI, when the parent's IriStrategy specifies providedAs parameter

Important: This constructor is only designed for properties of type String. For non-String types (like value objects or domain-specific types), you have two options:

  1. Use one of the mapper constructors: .namedMapper(), .mapper(), or .mapperInstance()
  2. Annotate the value class itself with @RdfIri and implement the template logic there

Collection Item IRI Mapping

Critical Rule: When using IriMapping for collection properties, template placeholders must exactly match the property name that contains the collection.

For collections (List<String>, Set<String>, Iterable<String>), each item in the collection becomes a separate IRI using the template:

@RdfLocalResource()
class BookCollection {
  /// Each author ID becomes an IRI: https://example.org/author/[authorId]
  @RdfProperty(
    SchemaBook.author,
    iri: IriMapping('{+baseUri}/author/{authorIds}'), // ← matches property name
  )
  final List<String> authorIds; // ← property name matches placeholder

  /// Combined with collection structure
  @RdfProperty(
    SchemaBook.contributors,
    collection: rdfList, // Ordered list structure
    iri: IriMapping('{+baseUri}/contributor/{contributorIds}'), // ← matches property name
  )
  final List<String> contributorIds; // ← property name matches placeholder
}

Common Mistake: Using arbitrary placeholder names that don't match the property:

// ❌ WRONG: Placeholder doesn't match property name
@RdfProperty(
  MyVocab.items,
  iri: IriMapping('{+baseUri}/item/{itemId}'), // ← 'itemId' doesn't exist
)
final List<String> itemsList; // ← property name is 'itemsList', not 'itemId'

// ✅ CORRECT: Placeholder matches property name exactly
@RdfProperty(
  MyVocab.items,
  iri: IriMapping('{+baseUri}/item/{itemsList}'), // ← matches property name
)
final List<String> itemsList;

Template Patterns

  • Property only: IriMapping('http://example.org/users/{userId}')
  • With context: IriMapping('{+baseUri}/users/{userId}')
  • Direct value: IriMapping() - uses the property value directly as the IRI

This approach enables flexible, context-aware IRI generation for individual properties while maintaining clear separation from global mapping configurations.

Examples:

// For String properties - using template is fine:
@RdfProperty(
  Dcterms.source,
  iri: IriMapping('urn:isbn:{isbn}')
)
final String isbn; // Will be mapped to an IRI like "urn:isbn:9780123456789"

// Option 1: For value types - use custom mapper:
@RdfProperty(
  SchemaPerson.identifier,
  iri: IriMapping.mapper(UserIdMapper)
)
final UserId userId; // Will use UserIdMapper for conversion

// Option 2: For value types - annotate the value class with @RdfIri:
@RdfProperty(SchemaPerson.identifier)
final UserId userId; // The UserId class is annotated with @RdfIri

// Definition of the UserId class:
@RdfIri('https://example.org/users/{value}')
class UserId {
  @RdfIriPart()
  final String value;

  UserId(this.value);
}

Implementation

const IriMapping([this.template])
    : fragmentTemplate = null,
      super();