Domain Layer
Relevant source files
The following files were used as context for generating this wiki page:
- app/src/main/java/com/musagenius/ocrapp/domain/model/ScanResult.kt
- app/src/main/java/com/musagenius/ocrapp/domain/model/OCRConfig.kt
- app/src/main/java/com/musagenius/ocrapp/domain/repository/ScanRepository.kt
- app/src/main/java/com/musagenius/ocrapp/domain/service/OCRService.kt
- app/src/main/java/com/musagenius/ocrapp/domain/usecase/DeleteLanguageUseCase.kt
- README.md
- TODO.md
- app/src/main/java/com/musagenius/ocrapp/presentation/viewmodel/OCRViewModel.kt
The Domain Layer is the core of the application, encapsulating the business logic and rules. It is designed to be independent of other layers, such as presentation (UI) and data (database, network), following the principles of Clean Architecture. This separation ensures that the application's business logic is testable, maintainable, and agnostic of implementation details like the UI framework or data storage mechanism.
This layer defines the essential components of the OCR application: what a "scan" is, how OCR should be configured, and the specific actions (use cases) a user can perform, like processing an image or deleting a language pack. It achieves this through domain models, repository interfaces, service interfaces, and use cases.
Sources: README.md:31-39, TODO.md:68-83
Architecture Overview
The Domain Layer sits at the center of the application's architecture. It has no dependencies on outer layers (like Presentation or Data). Instead, outer layers depend on it. This is achieved through dependency inversion, where the Domain Layer defines interfaces (contracts) that the Data Layer must implement.
The diagram below illustrates the dependency flow in the application's clean architecture.
This diagram shows that both the Presentation and Data layers depend on the Domain Layer, which contains the core business logic and models.
Sources: README.md:31-44
Domain Models
Domain models are plain Kotlin data classes that represent the core entities of the application. They are free from any platform-specific annotations or dependencies.
ScanResult
This model represents a single, completed OCR scan. It holds all the information related to a scanned document, including the image, extracted text, and metadata.
// app/src/main/java/com/musagenius/ocrapp/domain/model/ScanResult.kt:8-20
data class ScanResult(
val id: Long = 0,
val timestamp: Date,
val imageUri: Uri,
val extractedText: String,
val language: String,
val confidenceScore: Float,
val title: String = "",
val tags: List<String> = emptyList(),
val notes: String = "",
val isFavorite: Boolean = false,
val modifiedTimestamp: Date = timestamp
)
| Property | Type | Description |
|---|---|---|
id | Long | Unique identifier for the scan, auto-generated by the database. |
timestamp | Date | The date and time when the scan was originally created. |
imageUri | Uri | The URI of the source image that was scanned. |
extractedText | String | The text content extracted by the OCR engine. |
language | String | The language code (e.g., "eng") used for OCR. |
confidenceScore | Float | A score from 0.0 to 1.0 indicating the OCR engine's confidence in the result. |
title | String | A user-defined or auto-generated title for the scan. |
tags | List<String> | A list of tags for organizing scans. |
notes | String | Additional user notes about the scan. |
isFavorite | Boolean | A flag to mark the scan as a favorite. |
modifiedTimestamp | Date | The timestamp of the last modification. Defaults to the creation timestamp. |
The ScanResult class also includes several helper functions for convenience:
getTextPreview(maxLength: Int): Returns a truncated preview of the extracted text.hasHighConfidence(threshold: Float): Checks if the confidence score is above a certain threshold.getConfidencePercentage(): Formats the confidence score as a percentage string.isModified(): Checks if the scan has been modified since its creation.getWordCount(): Returns the word count of the extracted text.hasTag(tag: String): Checks if the scan has a specific tag.
Sources: app/src/main/java/com/musagenius/ocrapp/domain/model/ScanResult.kt:8-55
OCRConfig
This model defines the configuration parameters for an OCR processing job. It allows the application to control how the Tesseract engine behaves for each scan.
| Property | Type | Default Value | Description |
|---|---|---|---|
language | String | "eng" | The language code for the OCR engine. |
pageSegmentationMode | PageSegMode | PageSegMode.AUTO | Defines how Tesseract segments the image into lines and words. |
engineMode | EngineMode | EngineMode.DEFAULT | Specifies which Tesseract engine to use (e.g., Legacy, LSTM, or both). |
preprocessImage | Boolean | true | If true, the image will be preprocessed (e.g., grayscaled, scaled) before OCR to improve accuracy. |
maxImageDimension | Int | 2000 | The maximum width or height in pixels for image scaling during preprocessing. |
enableAutoRotation | Boolean | false | If true, the engine will attempt to auto-rotate the image. |
Sources: app/src/main/java/com/musagenius/ocrapp/domain/model/OCRConfig.kt:5-12
PageSegMode Enum
This enum corresponds to Tesseract's Page Segmentation Modes, which instruct the engine on how to interpret the layout of the image.
| Value | Description |
|---|---|
OSD_ONLY | Orientation and script detection only. |
AUTO | Fully automatic page segmentation (default). |
SINGLE_LINE | Treat the image as a single text line. |
SPARSE_TEXT | Find as much text as possible in no particular order. |
| (...and others) | See source for the full list. |
Sources: app/src/main/java/com/musagenius/ocrapp/domain/model/OCRConfig.kt:19-32
EngineMode Enum
This enum specifies which Tesseract engine version to use for recognition.
| Value | Description |
|---|---|
TESSERACT_ONLY | Legacy engine only. |
LSTM_ONLY | Neural nets (LSTM) engine only. |
TESSERACT_LSTM | Both legacy and LSTM engines. |
DEFAULT | Default engine based on what is available. |
Sources: app/src/main/java/com/musagenius/ocrapp/domain/model/OCRConfig.kt:37-42
Model Relationships
The following diagram shows the primary domain models and their composition.
This class diagram illustrates the ScanResult and OCRConfig data classes, along with the enums they utilize.
Sources: app/src/main/java/com/musagenius/ocrapp/domain/model/ScanResult.kt, app/src/main/java/com/musagenius/ocrapp/domain/model/OCRConfig.kt
Repositories and Services (Abstractions)
The Domain Layer defines interfaces that act as contracts for the Data Layer. These abstractions decouple the business logic from the data sources.
ScanRepository Interface
This interface defines the contract for all data operations related to ScanResult objects. The implementation (in the Data Layer) will handle the actual database interactions, but the Domain Layer is only concerned with the available operations.
| Method | Return Type | Description |
|---|---|---|
insert(scan: ScanResult) | kotlin.Result<Long> | Inserts a new scan and returns its generated ID. |
getById(id: Long) | kotlin.Result<ScanResult> | Retrieves a single scan by its ID. |
getAll() | Flow<Result<List<ScanResult>>> | Retrieves all scans as a Flow, emitting updates on data changes. |
delete(id: Long) | kotlin.Result<Unit> | Deletes a scan by its ID. |
search(query: String) | Flow<Result<List<ScanResult>>> | Searches for scans containing the query text. |
Note: This is a representative subset of methods. The actual interface may contain more.
Sources: app/src/main/java/com/musagenius/ocrapp/domain/repository/ScanRepository.kt (Note: file not present in context, methods inferred from ScanRepositoryImplTest.kt and OCRViewModel.kt)
OCRService Interface
This interface defines the contract for the OCR engine. It abstracts the underlying implementation (Tesseract) and provides a clear API for performing text recognition.
| Method | Return Type | Description |
|---|---|---|
initialize(config: OCRConfig) | Result<Unit> | Initializes the OCR engine with a given configuration. |
recognizeText(...) | suspend Result<OCRResult> | Performs OCR on a bitmap and returns the result. |
recognizeTextWithProgress(...) | Flow<Result<OCRProgress>> | Performs OCR and emits progress updates. |
isLanguageAvailable(lang: String) | Boolean | Checks if a specific language pack is installed. |
getAvailableLanguages() | List<String> | Returns a list of all installed language codes. |
stop() | Unit | Stops any ongoing OCR processing. |
cleanup() | Unit | Releases all resources used by the OCR engine. |
getVersion() | String | Gets the version of the underlying OCR engine. |
Sources: app/src/main/java/com/musagenius/ocrapp/domain/service/OCRService.kt:10-48
Use Cases
Use cases represent single, discrete business operations. They are classes that contain the logic for a specific task, orchestrated by fetching data from repositories and executing actions.
DeleteLanguageUseCase
This use case encapsulates the logic for deleting downloaded Tesseract language data files to free up storage.
Key functionalities:
- Single Deletion: The primary
invokeoperator allows deleting a single language file by its code (e.g., "fra"). It prevents the deletion of the default "eng" language. - Multiple Deletions: The
deleteMultiplefunction can delete a list of language files. - Size Calculation: Includes helpers like
getTotalLanguageFilesSizeandgetLanguageFileSizeto query the storage impact of language packs. - Error Handling: Wraps file operations in
try-catchblocks and returns aResultobject, clearly indicating success or failure.
The following sequence diagram shows how this use case might be called from a ViewModel to delete a language file.
This diagram shows the DeleteLanguageUseCase handling a request from a ViewModel, interacting with the file system on a background thread, and returning a Result.
Sources: app/src/main/java/com/musagenius/ocrapp/domain/usecase/DeleteLanguageUseCase.kt:12-97
Use Case Interaction Flow
Use cases are the bridge between the Presentation layer's intent and the application's business logic. A ViewModel will typically inject and call a use case to perform an action. The use case, in turn, may use one or more repository or service interfaces to fulfill the request.
The diagram below shows the typical flow for processing an image.
This sequence shows the OCRViewModel initiating an action, the ProcessImageUseCase orchestrating the logic, and the OCRService interface being used to perform the actual text recognition.
Sources: app/src/main/java/com/musagenius/ocrapp/presentation/viewmodel/OCRViewModel.kt:78-83, app/src/main/java/com/musagenius/ocrapp/domain/service/OCRService.kt:21-25
Conclusion
The Domain Layer is the architectural heart of the OCR application. By defining platform-agnostic models, abstractions (interfaces), and business logic (use cases), it creates a robust, scalable, and highly testable foundation. This clean separation of concerns allows the UI and data-access technologies to be modified or replaced with minimal impact on the core functionality of the app.