Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: add example specs for custom adapters #323

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

ronaldtse
Copy link
Contributor

This is for #322 .

This PR provides two sample custom serialization adapter implementations (in pseudocode):

The BibTeX implementation is more complete. The vObject implementation does parse simple vCards but as the vObject schema is much more complex it is incomplete.

Custom serialization adapter implementation

The user is meant to provide the following:

  • Mapping class that stores a set of mappings for the serialization format
  • MappingRule class, that defines how the mappings work to the target format's elements (e.g. BibTeX has "field", "citekey" and "type key". vObject has "component", "property", "value", etc)
  • Document class (an instance of raw data to parse, e.g. we have JsonDocument) (user can also specify smaller components
  • Adapter class that links the Document and Mapping and to register the {type} do #... block
  • A format may also provide its own set of Value Types, e.g. vObject defines a series of its own value types.

The following content is AI-generated that describes from the content the requirements I've listed above.

BibTeX adapter

spec/lutaml/model/custom_bibtex_adapter_spec.rb

This extension adds support for BibTeX format serialization and deserialization to Lutaml::Model. While BibTeX is traditionally used for academic citations, its structured format makes it suitable for storing various types of information models.

Key Benefits of BibTeX Format

  • Built-in support for structured data with fields and values
  • Natural handling of collections (like authors, dependencies, ingredients)
  • Familiar citation key system for unique identification
  • Human-readable text format for easy version control
  • Extensive tooling support for parsing and manipulation

Basic Setup

To use BibTeX format in your model:

  1. Include necessary field classes based on your needs:

    • BibtexFieldAuthor - For handling names (authors, maintainers, manufacturers)
    • BibtexFieldYear - For handling dates and ranges
    • BibtexFieldPage - For handling numeric ranges
  2. Define your model class inheriting from Lutaml::Model::Serializable

  3. Register BibTeX format:

Lutaml::Model::Config.register_format(
  :bibtex,
  mapping_class: BibtexMapping,
  adapter_class: BibtexAdapter
)
  1. Define BibTeX mappings using the bibtex do block:
bibtex do
  map_entry_type to: :entry_type     # Maps entry type (e.g., @article, @book)
  map_citekey to: :citekey           # Maps unique identifier
  map_field "author", to: :author    # Maps fields to model attributes
  map_field "title", to: :title
  # Add other field mappings as needed
end

Mapping Methods

The bibtex block supports these mapping methods:

  • map_entry_type: Maps the entry type (e.g., @Article, @book)
  • map_citekey: Maps the unique identifier
  • map_field: Maps fields to model attributes
    Options:
    • to: Target attribute name
    • render_nil: Whether to render nil values (default: false)

Examples

1. Traditional Academic Citation

class Publication < Lutaml::Model::Serializable
  attribute :entry_type, :string, values: %w[article book inproceedings]
  attribute :citekey, :string
  attribute :author, BibtexFieldAuthor
  attribute :title, :string
  attribute :journal, :string
  attribute :year, BibtexFieldYear

  bibtex do
    map_entry_type to: :entry_type
    map_citekey to: :citekey
    map_field "author", to: :author
    map_field "title", to: :title
    map_field "journal", to: :journal
    map_field "year", to: :year
  end
end

Usage:

entry = Publication.from_bibtex(bibtex_string)
bibtex_string = entry.to_bibtex

2. Software Components Registry

BibTeX's structured format works well for tracking software components:

class Component < Lutaml::Model::Serializable
  attribute :entry_type, :string, values: %w[library framework tool service]
  attribute :citekey, :string  # Unique identifier
  attribute :name, :string
  attribute :maintainers, BibtexFieldAuthor, collection: true
  attribute :version, :string
  attribute :dependencies, :string, collection: true
  attribute :license, :string

  bibtex do
    map_entry_type to: :entry_type
    map_citekey to: :citekey
    map_field "name", to: :name
    map_field "maintainers", to: :maintainers
    map_field "version", to: :version
    map_field "dependencies", to: :dependencies
    map_field "license", to: :license
  end
end

3. Equipment Inventory

class Equipment < Lutaml::Model::Serializable
  attribute :entry_type, :string, values: %w[machine tool vehicle equipment]
  attribute :citekey, :string  # Asset ID
  attribute :model, :string
  attribute :manufacturer, BibtexFieldAuthor
  attribute :purchase_date, BibtexFieldYear
  attribute :location, :string
  attribute :maintenance_history, :string, collection: true

  bibtex do
    map_entry_type to: :entry_type
    map_citekey to: :citekey
    map_field "model", to: :model
    map_field "manufacturer", to: :manufacturer
    map_field "purchase_date", to: :purchase_date
    map_field "location", to: :location
    map_field "maintenance_history", to: :maintenance_history
  end
end

4. Recipe Database

class Recipe < Lutaml::Model::Serializable
  attribute :entry_type, :string, values: %w[appetizer main dessert beverage]
  attribute :citekey, :string  # Recipe ID
  attribute :name, :string
  attribute :chef, BibtexFieldAuthor
  attribute :prep_time, :string
  attribute :ingredients, :string, collection: true
  attribute :instructions, :string, collection: true
  attribute :servings, :string

  bibtex do
    map_entry_type to: :entry_type
    map_citekey to: :citekey
    map_field "name", to: :name
    map_field "chef", to: :chef
    map_field "prep_time", to: :prep_time
    map_field "ingredients", to: :ingredients
    map_field "instructions", to: :instructions
    map_field "servings", to: :servings
  end
end

vObject adapter

spec/lutaml/model/custom_vobject_adapter_spec.rb

This module provides support for serializing and deserializing models to/from vObject format, a text-based data format used by standards like vCard and iCalendar.

Basic Usage

To use vObject serialization in your models:

class MyModel < Lutaml::Model::Serializable
  attribute :field1, :string
  attribute :field2, :string

  vobject do
    type :component          # Declare as component (like VCARD, VCALENDAR)
    component_root "MYCOMP"  # Root component name

    # Map vObject properties to model attributes
    map_property "PROP1", to: :field1
    map_property "PROP2", to: :field2
  end
end

Creating Custom Components

For non-standardized vObject components:

class MyCustomComponent < Lutaml::Model::Serializable
  attribute :name, :string
  attribute :details, MyCustomDetails

  vobject do
    type :component
    component_root "X-CUSTOM"  # Use X- prefix for custom components

    map_property "X-NAME", to: :name
    map_property "X-DETAILS", to: :details, type: :structured
  end
end

Custom Properties

Define custom properties with parameters:

class MyCustomProperty < Lutaml::Model::Serializable
  attribute :value, :string
  attribute :param1, :string
  attribute :param2, :integer

  vobject do
    type :property
    property_name "X-CUSTOM-PROP"

    map_value to: :value
    map_property "PARAM1", to: :param1
    map_property "PARAM2", to: :param2
  end
end

Value Types

Support for different value types:

  • Text (default)
  • URI
  • Binary (Base64)
  • Boolean
  • Integer
  • Float
  • UTC-Offset
  • Language-Tag
  • IsoDateAndOrTime

Custom Value Types

Create custom value types by extending VobjectValueType::Base:

class MyCustomValue < VobjectValueType::Base
  def valid?
    # Add validation logic
  end
end

Structured Values

For properties with multiple fields:

vobject do
  type :property
  property_name "X-STRUCTURED"

  map_field_set count: 3, item_type: :list
  map_field 0, to: :first_field
  map_field 1, to: :second_field
  map_field 2, to: :third_field
end

Registration

Register your custom format:

Lutaml::Model::Config.register_format(
  :vobject,
  mapping_class: YourMapping,
  adapter_class: YourAdapter
)

Component Types

Four types of elements are supported:

  • :component - Container components like VCARD
  • :property - Properties with values and parameters
  • :property_parameter - Parameters for properties
  • :property_group - Grouping of related properties

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants