Apache Ossie Converters

July 30, 2026 · View on GitHub

Overview

An Ossie Converter translates between the Ossie semantic model format and a specific vendor's semantic implementation. This enables teams to author a semantic model once in the Ossie standard and then generate the corresponding vendor-specific representation automatically.

Hub-and-Spoke Model

Ossie converters follow a hub-and-spoke architecture:

  • Hub: The Ossie core specification acts as the central, vendor-neutral format.
  • Spokes: Each converter handles translation to or from a specific vendor format.
                  ┌─────────────┐
                  │  Snowflake  │
                  └──────┬──────┘

┌─────────────┐    ┌─────┴─────┐    ┌─────────────┐
│     dbt     ├────┤   Ossie   ├────┤  Salesforce │
└─────────────┘    └─────┬─────┘    └─────────────┘

                  ┌──────┴──────┐
                  │  Databricks │
                  └─────────────┘

This approach avoids the need for point-to-point converters between every pair of vendors. With N vendors, a point-to-point strategy would require N*(N-1) converters. With Ossie as the hub, only 2*N converters are needed (one import and one export per vendor), and interoperability with all other vendors comes for free.

Converter Responsibilities

A converter handles two directions of translation:

Export (Apache Ossie → Vendor)

Read an Ossie semantic model and produce the equivalent vendor-specific representation. For example:

  • Ossie → Snowflake semantic model definition
  • Ossie → dbt semantic_models YAML
  • Ossie → Tableau data source / Salesforce semantic layer
  • Ossie → Databricks semantic layer definition

Import (Vendor → Apache Ossie)

Read a vendor-specific semantic model and produce a valid Ossie model, including mapping vendor-specific metadata into custom_extensions.

Supported Vendors

The Ossie specification currently defines extensions for the following vendors:

VendorDescription
SNOWFLAKESnowflake semantic model
SALESFORCESalesforce / Tableau semantic layer
DBTdbt semantic models
DATABRICKSDatabricks semantic layer
OMNIOmni semantic model
WISDOMWisdomAI domain
NVIDIA_GSFNVIDIA Generative Semantic Fabric standalone YAML

Each vendor may define custom extensions (via the custom_extensions field in the Ossie spec) to carry vendor-specific metadata that does not have an equivalent in the core specification.

Mapping Core Constructs

The following table shows how each Ossie construct maps conceptually to vendor equivalents. A converter must handle each of these:

Semantic Model

The top-level container. Maps to the root object in each vendor's format.

Ossie FieldDescriptionConverter Consideration
nameModel identifierMap to vendor's model/project name
descriptionHuman-readable descriptionMost vendors support a description field
ai_contextInstructions, synonyms for AI toolsMap if vendor supports AI/LLM annotations
datasetsLogical datasets (fact/dimension tables)See dataset mapping below
relationshipsForeign key connectionsSee relationship mapping below
metricsAggregate measuresSee metric mapping below
custom_extensionsVendor-specific metadataExtract extensions matching the target vendor

Datasets

Datasets represent logical tables (fact or dimension tables). They contain fields and define the structure of the data.

Ossie FieldDescriptionConverter Consideration
nameDataset identifierMap to table/entity/model name
sourcePhysical table reference (e.g., database.schema.table)Parse into vendor-specific catalog/schema/table components
primary_keySingle or composite primary keyMap to vendor's PK syntax; note composite keys use arrays like [order_id, line_number]
unique_keysAlternative unique identifiersMap if vendor supports unique constraints
fieldsRow-level attributes (columns)See field mapping below
ai_contextSynonyms and context for AIMap if vendor supports semantic annotations
custom_extensionsVendor-specific metadataExtract extensions matching the target vendor

Fields

Fields represent row-level attributes. They can be simple column references or computed expressions.

Note: datatype (on Field and Metric) declares a field's logical data type; dimension.is_time is an independent temporal-role marker. A field may carry both, either, or neither. Use datatype for data-type questions (casting, serialization); use is_time for role questions (classifying time dimensions). When is_time is unset it defaults to true if datatype is one of Date, Time, DateTime, DateTimeTz, and false otherwise. Explicit is_time always wins.

Ossie FieldDescriptionConverter Consideration
nameField identifierMap to column/attribute name
expression.dialectsMulti-dialect SQL expressionsSelect the dialect matching the target vendor; fall back to ANSI_SQL
datatypeLogical data type of the field (one of String, Integer, Decimal, Float, Boolean, Date, Time, DateTime, DateTimeTz, Opaque).Converters SHOULD consult datatype for the field's logical data type. Decimal is exact base-10 with unspecified precision and scale; Float is approximate. Prefer the temporal members (Date, Time, DateTime, DateTimeTz) to classify time dimensions. Omit datatype when unknown; use Opaque + custom_extensions for a known type outside the portable vocabulary.
dimension.is_timeTemporal-role marker. When true, the field should be treated as a time dimension regardless of its datatype (e.g. an Integer year grain, a String month name, or a Date column). When unset, defaults to true for temporal datatypes (Date, Time, DateTime, DateTimeTz) and false otherwise.Map to vendor-specific time dimension markers. Converters SHOULD classify as a time dimension when is_time resolves to true (either explicit or defaulted from a temporal datatype). An explicit is_time: false suppresses the time-dimension classification even on temporal-typed columns.
labelCategorization labelMap if vendor supports field labels/tags
descriptionHuman-readable descriptionMost vendors support field descriptions
ai_contextSynonyms and business contextMap if vendor supports semantic annotations

Expression dialect selection: A field may provide expressions in multiple dialects. For example:

expression:
  dialects:
    - dialect: ANSI_SQL
      expression: LOWER(email)
    - dialect: SNOWFLAKE
      expression: LOWER(email)::VARCHAR

A Snowflake converter should pick the SNOWFLAKE dialect when available, and fall back to ANSI_SQL otherwise.

Relationships

Relationships define foreign key connections between datasets. They support both simple and composite keys.

Ossie FieldDescriptionConverter Consideration
nameRelationship identifierMap to vendor's join/relationship name
fromMany-side datasetMap to the referencing table
toOne-side datasetMap to the referenced table
from_columnsForeign key columns (array)Positional correspondence with to_columns; handle composite keys
to_columnsPrimary/unique key columns (array)Must have same cardinality as from_columns

Composite key example: A composite relationship like:

from_columns: [product_id, variant_id]
to_columns: [id, variant_id]

means from.product_id = to.id AND from.variant_id = to.variant_id. The converter must generate the equivalent multi-column join in the target vendor format.

Metrics

Metrics are aggregate measures defined at the semantic model level. They can span multiple datasets via relationships.

Ossie FieldDescriptionConverter Consideration
nameMetric identifierMap to vendor's measure/KPI name
expression.dialectsMulti-dialect aggregate expressionsSelect the appropriate dialect; fall back to ANSI_SQL
datatypeLogical data type of the metric result (one of String, Integer, Decimal, Float, Boolean, Date, Time, DateTime, DateTimeTz, Opaque).Converters SHOULD consult datatype to declare the result type of the aggregation. Numeric measures should distinguish exact Decimal or Integer results from approximate Float results. Omit datatype when unknown; use Opaque + custom_extensions for a known type outside the portable vocabulary.
descriptionWhat the metric measuresMost vendors support descriptions
ai_contextSynonyms and business contextMap if vendor supports semantic annotations

Cross-dataset metric example:

- name: customer_lifetime_value
  expression:
    dialects:
      - dialect: ANSI_SQL
        expression: SUM(store_sales.ss_ext_sales_price) / COUNT(DISTINCT customer.c_customer_sk)

The converter must ensure that the dataset references (store_sales, customer) are resolved correctly in the target vendor's format and that any required joins are established.

Custom Extensions

Custom extensions carry vendor-specific metadata as a JSON string. A converter should:

  1. On export (Ossie → Vendor): Extract extensions where vendor_name matches the target vendor, parse the data JSON, and apply the vendor-specific settings.
  2. On import (Vendor → Ossie): Capture vendor-specific settings that have no Ossie core equivalent and store them as a custom_extension entry.

Example: A Snowflake export converter would extract:

custom_extensions:
  - vendor_name: SNOWFLAKE
    data: '{"warehouse": "ANALYTICS_WH", "database": "PROD", "schema": "PUBLIC"}'

and apply warehouse, database, and schema to the appropriate places in the Snowflake model definition.

AI Context

The ai_context field appears at every level (model, dataset, field, relationship, metric). It can be a simple string or a structured object:

# Simple string
ai_context: "orders, purchases, sales"

# Structured object
ai_context:
  instructions: "Use this for sales analysis"
  synonyms:
    - "orders"
    - "purchases"
  examples:
    - "Show total sales last month"

A converter should map ai_context when the target vendor supports equivalent constructs (e.g., LLM instructions, column descriptions with business terms). When the target vendor does not support AI annotations natively, the converter may encode them in custom_extensions on import to avoid data loss.

Writing a Converter

Step-by-Step Guide

  1. Validate input: Use the Ossie JSON Schema and the validation script to ensure the source Ossie model is valid before conversion.

  2. Parse the Ossie model: Load the YAML file and iterate over the top-level semantic_model entries.

  3. Map datasets: For each dataset, translate the name, source, primary_key, unique_keys, and fields to the vendor's format. Parse the source string (typically database.schema.table) into the vendor's catalog structure.

  4. Map fields with dialect selection: For each field, select the expression dialect that matches the target vendor. Implement a fallback chain:

    • Prefer the vendor-specific dialect (e.g., SNOWFLAKE for a Snowflake converter)
    • Fall back to ANSI_SQL if the vendor dialect is not available
    • Raise a warning or error if neither is available
  5. Map relationships: Translate relationship definitions into the vendor's join syntax. Ensure composite key column ordering is preserved.

  6. Map metrics: Translate metric expressions using the same dialect selection logic as fields. Resolve dataset references (e.g., store_sales.ss_ext_sales_price) into the vendor's qualified column format.

  7. Apply custom extensions: Extract custom_extensions entries matching the target vendor_name and apply vendor-specific settings to the output.

  8. Preserve AI context: Map ai_context to vendor-equivalent annotations where supported.

  9. Validate output: Verify the generated vendor model is valid according to the vendor's own schema or tooling.

Handling Edge Cases

ScenarioRecommended Approach
Missing vendor-specific dialect for a field/metricFall back to ANSI_SQL; log a warning
Computed fields with vendor-specific SQL syntaxRequire the vendor dialect in the source Ossie model; error if neither vendor nor ANSI dialect is available
Composite primary keysEnsure the vendor format supports composite keys; if not, flatten or document the limitation
Cross-dataset metrics referencing multiple tablesEnsure all referenced datasets exist and relationships are defined; resolve qualified column names
Custom extensions with unknown vendorIgnore (do not discard) — preserve for round-tripping
ai_context on a vendor that doesn't support itStore in a custom_extension with vendor_name: COMMON to preserve for round-tripping

Round-Trip Fidelity

A well-implemented converter pair (import + export) should preserve as much information as possible during round-tripping:

Vendor A model → [Import] → Ossie model → [Export] → Vendor A model

To achieve this:

  • Never discard information silently. If a vendor-specific attribute has no Ossie core equivalent, store it in custom_extensions.
  • Preserve field ordering where possible, as some vendors are sensitive to declaration order.
  • Preserve custom_extensions for all vendors, not just the target vendor. This allows a model to carry metadata for multiple vendors simultaneously (e.g., a single Ossie model with both Snowflake and dbt extensions).

Example: Conceptual Conversion Flow

Given the TPC-DS example included in this repository, a Snowflake export converter would:

  1. Read the tpcds_retail_model semantic model.
  2. Create a Snowflake semantic model with name tpcds_retail_model.
  3. Map each dataset (store_sales, date_dim, customer, item, store) to Snowflake table references, parsing source values like tpcds.public.store_sales into Snowflake's database.schema.table format.
  4. For each field, select the ANSI_SQL dialect expression (since no SNOWFLAKE dialect is provided in this example).
  5. Translate relationships into Snowflake join definitions, mapping from_columns and to_columns pairs.
  6. Translate metrics like total_sales (SUM(store_sales.ss_ext_sales_price)) into Snowflake metric definitions.
  7. Extract the SALESFORCE and DBT custom extensions — these would not be applied to the Snowflake output but should be preserved if the model is later imported back to Ossie.

Contributing a New Converter

To add support for a new vendor:

  1. Use a stable vendor_name string in each custom extension emitted by the converter.
  2. Define the custom extension schema for the vendor (what vendor-specific metadata fields are supported in the data JSON).
  3. Implement the export converter (Ossie → Vendor).
  4. Implement the import converter (Vendor → Ossie).
  5. Add tests using the TPC-DS example model as a baseline.
  6. Document any limitations or unsupported constructs.