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 withLEFT_SEMANTIC_FIELD_API_NAMEandRIGHT_SEMANTIC_FIELD_API_NAMEdescribing column-to-column mappings.LEFT_SEMANTIC_DEFINITION_API_NAME/RIGHT_SEMANTIC_DEFINITION_API_NAME— Salesforce fields holding theFROM/TOentity 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:
- Retrieval — Fetches the list of OSSIE relationships using the
RELATIONSHIPSkey. - Validation and Filtering —
validateAndFilterRelationshipschecks that referenced entities and columns exist in the targetsemanticDataObjects. Invalid relationships are dropped. - Generic Mapping —
MappingUtils.filterMappingsByPrefixisolates relationship-specific rules, thenGenericMappingEngine.applyMappingsconverts properties. - Criteria Reconstruction —
reconstructCriteriapopulates the Salesforcecriteriaarray from the parallelFROM_COLUMNS/TO_COLUMNSlists. - Default Application —
applyDefaultsadds standard values forCARDINALITY,IS_ENABLED, andJOIN_TYPEwhen these fields are absent. - Extension Restoration —
customExtensionHandler.restoreCustomExtensionsAtLevelreattaches 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:
- Filtering — Relationships containing unsupported field types, such as Formula or SemanticField, are separated and stored in the top-level
custom_extensionsviastoreUnsupportedRelationshipsAtModelLevel. - Criteria Deconstruction — For supported relationships,
deconstructCriteriaconverts the Salesforcecriteriaarray back into parallelFROM_COLUMNS/TO_COLUMNSlists while writing theFROM/TOentity names. - Unmapped Property Preservation —
customExtensionHandler.storeUnmappedPropertiessaves 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 parallelFROM_COLUMNSandTO_COLUMNSlists and aCRITERIAarray. - The
RelationshipMappingHandler.javaclass resolves these relationships bidirectionally, delegating tomapOsiToSalesforceormapSalesforceToOsibased on theConversionDirection. - Validation occurs through
validateAndFilterRelationships, which drops invalid references before mapping to ensure target entity and column integrity. - Criteria are reconstructed with
reconstructCriteriaduring Ossie-to-Salesforce conversion and deconstructed withdeconstructCriteriaduring the reverse trip. - Default metadata such as
CARDINALITY,IS_ENABLED, andJOIN_TYPEare applied automatically when omitted. - Unmapped or unsupported properties—including Formula and SemanticField relationships—are preserved in
custom_extensionsto 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →