# Loading Result API The `LoadingResult` class encapsulates the result of an ontology loading operation, providing access to the merged graph, loaded URIs, errors, warnings, and OWL-specific features. ## Overview After loading an ontology, `OntologyLoader.load_ontology()` returns a `LoadingResult` object that contains: - **Merged graph**: The combined RDF graph containing all loaded ontologies - **Loaded URIs**: Set of successfully loaded ontology URIs - **Errors**: List of errors encountered during loading - **Warnings**: List of warnings encountered during loading - **OWL features**: Lazy-loaded OWL-specific features (validation, consistency, metadata, version management) ## Basic Usage ```python from cleverrdf_lib import OntologyLoader loader = OntologyLoader() result = loader.load_ontology("ontology.ttl") # Check if loading was successful if result.is_successful_for_main_ontology: print("Loading succeeded!") else: print("Loading failed!") for error in result.errors: print(f"Error: {error['message']}") ``` ## Accessing the Merged Graph !!! warning "Graph Access Warning" Direct access to the `merged_graph` property introduces a direct dependency on RDFLib and its SPARQL queries and iterators. For general client applications, prefer using the `class_hierarchy` API for navigating the ontology structure. ```python # Access the merged graph graph = result.merged_graph # NOTE: Direct graph access is discouraged for general client applications # as it introduces a direct dependency on RDFLib and its SPARQL/iterators. # Prefer using the class_hierarchy API instead. ``` ### When to Use the Graph Directly Direct graph access should only be used when: - You need to perform custom SPARQL queries - You need to access RDF triples directly - You need to work with RDFLib-specific features - You are building framework extensions For most use cases, use the `class_hierarchy` API instead. ## Loaded URIs Get the set of successfully loaded ontology URIs: ```python from cleverrdf_lib import OntologyLoader loader = OntologyLoader() result = loader.load_ontology("ontology.ttl") # Get loaded URIs loaded_uris = result.loaded_uris print(f"Loaded {len(loaded_uris)} ontologies:") for uri in loaded_uris: print(f" - {uri}") # Get count count = result.loaded_count print(f"Total loaded: {count}") ``` ## Errors Access errors encountered during loading: ```python from cleverrdf_lib import OntologyLoader loader = OntologyLoader() result = loader.load_ontology("ontology.ttl") # Check for errors if not result.is_successful_for_main_ontology: print("Errors encountered:") for error in result.errors: print(f"URI: {error['uri']}") print(f"Message: {error['message']}") if 'exception' in error: print(f"Exception: {error['exception']}") ``` ### Error Structure Each error is a dictionary: ```python { "uri": str, # The URI that failed to load "message": str, # Human-readable error message "exception": Exception # The underlying exception (if available) } ``` ### Adding Errors You can add errors programmatically (though this is typically done internally): ```python result.add_error({ "uri": "http://example.org/failed.owl", "message": "Failed to load ontology", "exception": some_exception }) ``` ## Warnings Access warnings encountered during loading: ```python from cleverrdf_lib import OntologyLoader loader = OntologyLoader() result = loader.load_ontology("ontology.ttl") # Check for warnings if result.warnings: print("Warnings:") for warning in result.warnings: print(f" - {warning}") ``` ### Adding Warnings Warnings can be added programmatically: ```python result.add_warning("OWL Validation Warning: Circular class definition detected") ``` Warnings are typically added by: - OWL validation (validation warnings) - Consistency checking (consistency warnings) - Build observers (build inconsistency warnings) ## Class Hierarchy Access the class hierarchy (lazy-loaded): ```python from cleverrdf_lib import OntologyLoader loader = OntologyLoader() result = loader.load_ontology("ontology.ttl") # Access the hierarchy (automatically builds if not already built) hierarchy = result.class_hierarchy # Navigate the hierarchy (iterate over dictionary values) for class_node in hierarchy.get_all_classes().values(): print(f"Class: {class_node.iri}") print(f" Parents: {[p.iri for p in class_node.parents]}") print(f" Children: {[c.iri for c in class_node.children]}") ``` The hierarchy is built automatically on first access. See [Class Hierarchy Navigation](class_hierarchy.md) for details. ### Setting Build Observers You can set observers for the class hierarchy build process: ```python from cleverrdf_lib import OntologyLoader from cleverrdf_lib.observers.base_hierarchy_oberver import BaseClassHierarchyBuildObserver class MyBuildObserver(BaseClassHierarchyBuildObserver): def on_build_started(self, iri: str) -> None: print(f"Building hierarchy for: {iri}") def on_build_completed(self, iri: str) -> None: print(f"Hierarchy build completed for: {iri}") loader = OntologyLoader() result = loader.load_ontology("ontology.ttl") # Set observer before accessing hierarchy observer = MyBuildObserver() result.set_class_hierarchy_build_observer(observer) # Or set multiple observers observer1 = MyBuildObserver() observer2 = MyBuildObserver() result.set_class_hierarchy_build_observers([observer1, observer2]) # Now access hierarchy (observer will be notified) hierarchy = result.class_hierarchy ``` ## OWL Features The `LoadingResult` provides lazy-loaded access to OWL-specific features: ### Validation Result ```python from cleverrdf_lib import OntologyLoader loader = OntologyLoader() result = loader.load_ontology("ontology.ttl") # Access validation result (lazy-loaded) validation_result = result.owl_validation_result if validation_result.is_valid: print("Ontology is valid!") else: print("Validation errors:") for error in validation_result.errors: print(f" - {error}") print("Validation warnings:") for warning in validation_result.warnings: print(f" - {warning}") ``` ### Consistency Result ```python from cleverrdf_lib import OntologyLoader loader = OntologyLoader() result = loader.load_ontology("ontology.ttl") # Access consistency result (lazy-loaded) consistency_result = result.owl_consistency_result if consistency_result.is_consistent: print("Ontology is consistent!") else: print("Consistency issues:") for issue in consistency_result.issues: print(f" - {issue.message}") print(f" Element: {issue.element_iri}") ``` ### Metadata ```python from cleverrdf_lib import OntologyLoader loader = OntologyLoader() result = loader.load_ontology("ontology.ttl") # Access metadata (lazy-loaded) metadata = result.owl_metadata print(f"Version IRI: {metadata.get('version_iri')}") print(f"Prior Version: {metadata.get('prior_version')}") print(f"Imports: {metadata.get('imports')}") ``` ### Version Manager ```python from cleverrdf_lib import OntologyLoader loader = OntologyLoader() result = loader.load_ontology("ontology.ttl") # Access version manager (lazy-loaded) version_manager = result.owl_version_manager version_info = version_manager.extract_version_info() print(f"Version: {version_info.version_info}") print(f"Version IRI: {version_info.version_iri}") ``` ## Lazy Loading All OWL features are lazy-loaded, meaning they are only computed when first accessed: ```python from cleverrdf_lib import OntologyLoader loader = OntologyLoader() # Validation is not performed until accessed result = loader.load_ontology("ontology.ttl") # Validation happens here (first access) validation_result = result.owl_validation_result # Subsequent accesses return the cached result validation_result2 = result.owl_validation_result # No recomputation ``` This provides: - **Performance**: Features are only computed when needed - **Flexibility**: You can skip expensive operations if not needed - **Efficiency**: Results are cached after first computation ## Result Properties Summary | Property | Type | Description | |----------|------|-------------| | `merged_graph` | `Graph` | Merged RDF graph (use with caution) | | `loaded_uris` | `set[str]` | Set of loaded ontology URIs | | `loaded_count` | `int` | Number of loaded ontologies | | `errors` | `list[dict]` | List of error dictionaries | | `warnings` | `list[str]` | List of warning messages | | `is_successful_for_all_ontologies` | `bool` | Whether loading succeeded for all ontologies (no errors at all) | | `is_successful_for_main_ontology` | `bool` | Whether the main ontology loaded successfully | | `class_hierarchy` | `ClassHierarchy` | Class hierarchy (lazy-loaded) | | `owl_validation_result` | `OWLValidationResult` | Validation result (lazy-loaded) | | `owl_consistency_result` | `ConsistencyResult` | Consistency result (lazy-loaded) | | `owl_metadata` | `dict` | OWL metadata (lazy-loaded) | | `owl_version_manager` | `VersionManager` | Version manager (lazy-loaded) | ## Success Checking Methods The `LoadingResult` provides two methods for checking loading success: ### `is_successful_for_main_ontology` **Recommended for most use cases.** Checks if the main ontology (the one you requested to load) was successfully loaded. Returns `True` if: - The main ontology URI is in the `loaded_uris` set - There are no errors specifically for the main ontology This is the method you should use in most scenarios, as it verifies that the ontology you requested was successfully loaded, even if some imported ontologies failed to load. ```python if result.is_successful_for_main_ontology: # Main ontology loaded successfully hierarchy = result.class_hierarchy else: # Main ontology failed to load print("Failed to load main ontology") ``` ### `is_successful_for_all_ontologies` Checks if **all** ontologies (main + all imports) loaded successfully. Returns `True` only if: - There are **no errors at all** in the loading process Use this method when you require that all imported ontologies must load successfully. If any import fails, this will return `False` even if the main ontology loaded successfully. ```python if result.is_successful_for_all_ontologies: # All ontologies (main + imports) loaded successfully print("All ontologies loaded") else: # At least one ontology failed to load # Check result.errors to see which ones failed for error in result.errors: print(f"Failed: {error['uri']}") ``` ### When to Use Which - **Use `is_successful_for_main_ontology`** (recommended): When you want to proceed if the main ontology loaded, even if some imports failed - **Use `is_successful_for_all_ontologies`**: When you require all ontologies (including all imports) to load successfully before proceeding ## Best Practices 1. **Check `is_successful_for_main_ontology`**: Always verify loading succeeded before accessing results (recommended for most cases) 2. **Prefer class_hierarchy**: Use the class hierarchy API instead of direct graph access 3. **Handle errors**: Check and handle errors appropriately 4. **Review warnings**: Review warnings to identify potential issues 5. **Lazy loading**: Be aware that OWL features are lazy-loaded ## Next Steps - Learn about [Class Hierarchy Navigation](class_hierarchy.md) - Explore [OWL Extensions and Validation](owl_extensions.md) - Understand [Error Handling](error_handling.md)