How Ossie Defines and Resolves Relationships Between Logical Datasets in a Semantic Model

Ossie defines relationships between logical datasets as structured maps linking source and target entities through column-level criteria, then resolves them bidirectionally via RelationshipMappingHandler to validate references, reconstruct join conditions, apply default metadata, and preserve unsupported extensions.

Apache Ossie represents relationships between logical datasets in a semantic model as explicit objects stored within dataset definitions. These objects describe entity-to-entity links with parallel column mappings, enabling the framework to convert between Ossie's internal format and Salesforce semantic models without data loss. The conversion pipeline relies on constants defined in ConverterConstants.java and orchestrated handlers in DatasetMappingHandler.java and RelationshipMappingHandler.java to manage these relationships.

Relationship Constants and Structure in ConverterConstants.java

Ossie stores each relationship as a map using standardized keys defined in converters/salesforce/src/main/java/org/apache/ossie/converter/ConverterConstants.java. The RELATIONSHIPS key holds the list of Ossie-format relationship objects attached to a dataset, while SEMANTIC_RELATIONSHIPS stores the Salesforce-format counterpart.

Each relationship object contains:

  • FROM / TO — The API names of the source and target entities.
  • FROM_COLUMNS / TO_COLUMNS — Parallel lists of column names participating in the join.
  • CRITERIA — An array of objects with LEFT_SEMANTIC_FIELD_API_NAME and RIGHT_SEMANTIC_FIELD_API_NAME describing column-to-column mappings.
  • LEFT_SEMANTIC_DEFINITION_API_NAME / RIGHT_SEMANTIC_DEFINITION_API_NAME — Salesforce fields holding the FROM / TO entity names.
  • CARDINALITY, IS_ENABLED, JOIN_TYPE — Optional metadata that receives default values when omitted.

The DatasetMappingHandler, implemented in converters/salesforce/src/main/java/org/apache/ossie/converter/DatasetMappingHandler.java, creates these relationship objects when converting datasets to the semantic model. Later, the RelationshipMappingHandler processes them during bidirectional conversion.

Resolving Relationships with RelationshipMappingHandler

The RelationshipMappingHandler.java file in converters/salesforce/src/main/java/org/apache/ossie/converter/ serves as the core engine for resolving relationships between logical datasets. It receives a ConversionDirection flag and delegates to the appropriate method for the requested transformation.

Ossie-to-Salesforce Mapping (mapOsiToSalesforce)

When converting from Ossie to Salesforce, the handler performs the following steps:

  1. Retrieval — Fetches the list of OSSIE relationships using the RELATIONSHIPS key.
  2. Validation and FilteringvalidateAndFilterRelationships checks that referenced entities and columns exist in the target semanticDataObjects. Invalid relationships are dropped.
  3. Generic MappingMappingUtils.filterMappingsByPrefix isolates relationship-specific rules, then GenericMappingEngine.applyMappings converts properties.
  4. Criteria ReconstructionreconstructCriteria populates the Salesforce criteria array from the parallel FROM_COLUMNS / TO_COLUMNS lists.
  5. Default ApplicationapplyDefaults adds standard values for CARDINALITY, IS_ENABLED, and JOIN_TYPE when these fields are absent.
  6. Extension RestorationcustomExtensionHandler.restoreCustomExtensionsAtLevel reattaches any temporarily removed custom extensions.
// Inside mapOsiToSalesforce()
List<Object> osiRelationships = getList(sourceData, RELATIONSHIPS);
Map<String, String> relationshipMappings = MappingUtils.filterMappingsByPrefix(mappings, RELATIONSHIPS);
Map<String, Object> mappedData = GenericMappingEngine.applyMappings(sourceData, relationshipMappings);
outputData.putAll(mappedData);
reconstructCriteria(osiRelationships, sfRelationships); // builds the criteria array
applyDefaults(sfRelationships); // adds CARDINALITY, IS_ENABLED, etc.

Salesforce-to-Ossie Reverse Mapping (mapSalesforceToOsi)

For the reverse direction, the handler extracts the semanticRelationships array and transforms it back into Ossie's format:

  1. Filtering — Relationships containing unsupported field types, such as Formula or SemanticField, are separated and stored in the top-level custom_extensions via storeUnsupportedRelationshipsAtModelLevel.
  2. Criteria Deconstruction — For supported relationships, deconstructCriteria converts the Salesforce criteria array back into parallel FROM_COLUMNS / TO_COLUMNS lists while writing the FROM / TO entity names.
  3. Unmapped Property PreservationcustomExtensionHandler.storeUnmappedProperties saves any Salesforce properties that lack direct Ossie counterparts.
// Inside mapSalesforceToOsi()
List<Object> sfRelationships = getList(sourceData, SEMANTIC_RELATIONSHIPS);
deconstructCriteria(sfRelationships, osiRelationships); // extracts columns
customExtensionHandler.storeUnmappedProperties(...);   // preserves extras

Preserving Unmapped Data in Custom Extensions

During both conversion directions, Ossie ensures no data loss through a custom extensions mechanism. Unsupported relationships, formula fields, and unmapped Salesforce properties are stored in a custom_extensions block rather than discarded. This design guarantees round-trip fidelity when converting between Ossie's logical datasets and external semantic models.

Constructing a Relationship in the Ossie Logical Model

Developers can define a relationship between logical datasets by creating a map with the required constant keys and attaching it to the dataset's relationship list. The following example demonstrates an Ossie relationship linking an Account entity to a Contact entity:

// Example of an OSSIE relationship (source side)
Map<String, Object> rel = new LinkedHashMap<>();
rel.put(ConverterConstants.FROM, "Account");
rel.put(ConverterConstants.TO, "Contact");
rel.put(ConverterConstants.FROM_COLUMNS, List.of("Id"));
rel.put(ConverterConstants.TO_COLUMNS, List.of("AccountId"));
rel.put(ConverterConstants.NAME, "Account_Contact_Rel");

// Add to the dataset's relationship list
List<Object> relationships = new ArrayList<>();
relationships.add(rel);
sourceDataset.put(ConverterConstants.RELATIONSHIPS, relationships);

This map structure is the foundation that RelationshipMappingHandler transforms during semantic model conversion.

Summary

  • Ossie defines relationships between logical datasets as structured maps using keys from ConverterConstants.java, linking entities via parallel FROM_COLUMNS and TO_COLUMNS lists and a CRITERIA array.
  • The RelationshipMappingHandler.java class resolves these relationships bidirectionally, delegating to mapOsiToSalesforce or mapSalesforceToOsi based on the ConversionDirection.
  • Validation occurs through validateAndFilterRelationships, which drops invalid references before mapping to ensure target entity and column integrity.
  • Criteria are reconstructed with reconstructCriteria during Ossie-to-Salesforce conversion and deconstructed with deconstructCriteria during the reverse trip.
  • Default metadata such as CARDINALITY, IS_ENABLED, and JOIN_TYPE are applied automatically when omitted.
  • Unmapped or unsupported properties—including Formula and SemanticField relationships—are preserved in custom_extensions to guarantee lossless round-trip conversion.

Frequently Asked Questions

What constants does Ossie use to define semantic model relationships?

Ossie defines relationship keys in ConverterConstants.java, including RELATIONSHIPS for the Ossie-format list, SEMANTIC_RELATIONSHIPS for the Salesforce-format list, FROM / TO for entity names, FROM_COLUMNS / TO_COLUMNS for participating columns, and CRITERIA for the column-to-column mapping array. Optional keys such as CARDINALITY, IS_ENABLED, and JOIN_TYPE provide additional join metadata.

How does RelationshipMappingHandler validate relationships during conversion?

During Ossie-to-Salesforce conversion, the handler calls validateAndFilterRelationships to verify that every referenced entity and column exists in the target semanticDataObjects. Relationships that fail this validation are removed from the mapping process, ensuring only valid semantic links reach the output model.

What happens to unsupported relationships when converting Salesforce to Ossie?

When mapSalesforceToOsi encounters relationships with unsupported field types—such as Formula or SemanticField—it invokes storeUnsupportedRelationshipsAtModelLevel to move them into a top-level custom_extensions block. This prevents data loss while keeping the core semantic model clean.

Where does Ossie store default metadata like cardinality and join type?

If optional fields are omitted from the source relationship object, RelationshipMappingHandler invokes applyDefaults during Ossie-to-Salesforce mapping to populate standard values for CARDINALITY, IS_ENABLED, and JOIN_TYPE. These defaults ensure the resulting semantic model remains complete without requiring explicit input for every metadata field.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →