# CacheManager > **Relevant source files** > * [src/io/github/samera2022/mouse_macros/manager/CacheManager.java](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/manager/CacheManager.java) > * [src/io/github/samera2022/mouse_macros/ui/frame/ExitDialog.java](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/ExitDialog.java) ## Purpose and Scope CacheManager is responsible for managing transient session state in the MouseMacros application. It persists user preferences that change frequently during normal usage, such as file chooser directories and window dimensions, to a JSON file (`cache.json`). This page documents the CacheManager class, its data structures, persistence mechanisms, and integration points. For long-term user configuration settings (language, hotkeys, dark mode), see [ConfigManager](ConfigManager). For the file format specification of cache.json, see [Configuration Files](Configuration-Files-and-Settings). **Sources:** [src/io/github/samera2022/mouse_macros/manager/CacheManager.java L1-L86](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/manager/CacheManager.java#L1-L86) --- ## Overview CacheManager provides a centralized mechanism for storing and retrieving ephemeral application state that should persist across sessions but is not considered core configuration. The primary use cases are: * **Directory Memory**: Remembering the last directory used for saving/loading macro files * **Window Size Caching**: Storing window dimensions for each dialog/frame to restore user preferences * **Session Continuity**: Providing a seamless user experience by restoring UI state The manager uses a static singleton pattern with lazy initialization, ensuring a single cache instance throughout the application lifecycle. **Sources:** [src/io/github/samera2022/mouse_macros/manager/CacheManager.java L13-L60](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/manager/CacheManager.java#L13-L60) --- ## Class Structure and Data Model ```mermaid classDiagram class CacheManager { -String CACHE_PATH -Gson gson -FileChooserCache cache +FileChooserCache getCache() +void reloadCache() +void saveCache() +void saveCache(FileChooserCache) +FileChooserCache loadCache() +String getLastLoadDirectory() +void setLastLoadDirectory(String) +String getLastSaveDirectory() +void setLastSaveDirectory(String) +String getWindowSize(String) +void setWindowSize(String, String) } class FileChooserCache { +String lastLoadDirectory +String lastSaveDirectory +Map windowSizeMap } class Gson { } class FileUtil { } FileChooserCache --o CacheManager : contains CacheManager ..> Gson : uses CacheManager ..> FileUtil : uses ``` **Sources:** [src/io/github/samera2022/mouse_macros/manager/CacheManager.java L13-L86](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/manager/CacheManager.java#L13-L86) ### FileChooserCache Structure The `FileChooserCache` inner class defines the JSON schema for the cache file: | Field | Type | Purpose | Default Value | | --- | --- | --- | --- | | `lastLoadDirectory` | String | Last directory used when loading .mmc files | `""` (empty) | | `lastSaveDirectory` | String | Last directory used when saving .mmc files | `""` (empty) | | `windowSizeMap` | Map | Maps window names to size strings (e.g., "800x600") | Empty HashMap | **Sources:** [src/io/github/samera2022/mouse_macros/manager/CacheManager.java L19-L23](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/manager/CacheManager.java#L19-L23) --- ## File Location and Persistence ### Cache File Path The cache file is stored at: `/cache.json` Where `LocalStoragePath` is determined by `FileUtil.getLocalStoragePath()`, typically resolving to: * **Windows**: `%USERPROFILE%/AppData/MouseMacros/cache.json` * **Cross-platform**: Uses `FileUtil` to ensure consistent path resolution ```mermaid flowchart TD FileUtil["FileUtil.getLocalStoragePath()"] CACHE_PATH["CACHE_PATH constant"] File["cache.json file"] FileUtil --> CACHE_PATH CACHE_PATH --> File ``` **Sources:** [src/io/github/samera2022/mouse_macros/manager/CacheManager.java L15](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/manager/CacheManager.java#L15-L15), [src/io/github/samera2022/mouse_macros/util/FileUtil.java](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/util/FileUtil.java) ### Serialization Format CacheManager uses Google's Gson library with pretty-printing enabled for human-readable JSON output: ```java // From CacheManager.java:16 private static final Gson gson = new GsonBuilder().setPrettyPrinting().create(); ``` Example cache.json structure: ```json { "lastLoadDirectory": "C:/Users/Example/Documents/Macros", "lastSaveDirectory": "C:/Users/Example/Documents/Macros", "windowSizeMap": { "MainFrame": "800x600", "SettingsDialog": "600x400", "MacroSettingsDialog": "500x300" } } ``` **Sources:** [src/io/github/samera2022/mouse_macros/manager/CacheManager.java L16](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/manager/CacheManager.java#L16-L16) --- ## API Methods ### Core Cache Operations #### Loading Cache ```mermaid sequenceDiagram participant Application participant CacheManager participant File System participant Gson Library Application->>CacheManager: loadCache() CacheManager->>CacheManager: Paths.get(CACHE_PATH) CacheManager->>File System: Files.exists(cachePath) loop [Cache file exists] File System-->>CacheManager: true CacheManager->>File System: Files.readAllBytes(cachePath) File System-->>CacheManager: JSON bytes CacheManager->>Gson Library: fromJson(json, FileChooserCache.class) Gson Library-->>CacheManager: FileChooserCache object CacheManager-->>Application: FileChooserCache instance File System-->>CacheManager: false CacheManager->>CacheManager: new FileChooserCache() CacheManager-->>Application: Default instance end ``` **Sources:** [src/io/github/samera2022/mouse_macros/manager/CacheManager.java L49-L60](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/manager/CacheManager.java#L49-L60) The `loadCache()` method: 1. Constructs the cache file path using `Paths.get(CACHE_PATH)` 2. Checks if the file exists with `Files.exists(cachePath)` 3. If exists, reads the file content as UTF-8 encoded bytes 4. Deserializes JSON to `FileChooserCache` using Gson 5. If missing or error occurs, returns a new default `FileChooserCache` instance Error handling prints to `System.err` but does not throw exceptions, ensuring graceful degradation. **Sources:** [src/io/github/samera2022/mouse_macros/manager/CacheManager.java L49-L60](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/manager/CacheManager.java#L49-L60) #### Saving Cache ``` // From CacheManager.java:37-47 public static void saveCache(FileChooserCache c) { try { Path cachePath = Paths.get(CACHE_PATH); // Ensure parent directory exists if (cachePath.getParent() != null) Files.createDirectories(cachePath.getParent()); String json = gson.toJson(c); Files.write(cachePath, json.getBytes(StandardCharsets.UTF_8)); } catch (IOException e) { System.err.println("Failed to save cache: " + e.getMessage()); } } ``` The save operation: 1. Creates parent directory structure if needed using `Files.createDirectories()` 2. Serializes the `FileChooserCache` object to JSON 3. Writes JSON as UTF-8 encoded bytes to the cache file 4. Handles `IOException` gracefully with error logging **Sources:** [src/io/github/samera2022/mouse_macros/manager/CacheManager.java L37-L47](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/manager/CacheManager.java#L37-L47) ### Directory Management Methods | Method | Parameters | Return | Purpose | | --- | --- | --- | --- | | `getLastLoadDirectory()` | None | String | Returns the last directory used for loading macros | | `setLastLoadDirectory(String dir)` | dir: String | void | Sets last load directory and persists cache | | `getLastSaveDirectory()` | None | String | Returns the last directory used for saving macros | | `setLastSaveDirectory(String dir)` | dir: String | void | Sets last save directory and persists cache | **Key Implementation Detail:** All setter methods automatically call `saveCache()` to persist changes immediately, ensuring no data loss if the application terminates unexpectedly. **Sources:** [src/io/github/samera2022/mouse_macros/manager/CacheManager.java L62-L75](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/manager/CacheManager.java#L62-L75) ### Window Size Management Methods | Method | Parameters | Return | Purpose | | --- | --- | --- | --- | | `getWindowSize(String windowName)` | windowName: String | String | Retrieves cached size for the specified window | | `setWindowSize(String windowName, String size)` | windowName: String, size: String | void | Stores window size and persists cache | The window size format is typically `"x"` (e.g., `"800x600"`), though the manager does not enforce this format. **Implementation Note:** Both getter and setter perform null-safety checks on `cache.windowSizeMap`, initializing it to a new `HashMap` if null. **Sources:** [src/io/github/samera2022/mouse_macros/manager/CacheManager.java L77-L85](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/manager/CacheManager.java#L77-L85) --- ## Integration with Application Components ```mermaid flowchart TD MainFrame["MainFrame"] SettingsDialog["SettingsDialog"] MacroSettingsDialog["MacroSettingsDialog"] HotkeyDialog["HotkeyDialog"] MacroManager["MacroManager"] CacheManager["CacheManager
(static singleton)"] FileChooser["JFileChooser instances"] WindowClosingAdapters["WindowClosingAdapter instances"] MainFrame --> CacheManager SettingsDialog --> CacheManager MacroSettingsDialog --> CacheManager HotkeyDialog --> CacheManager MacroManager --> CacheManager MacroManager --> CacheManager FileChooser --> MacroManager WindowClosingAdapters --> MainFrame WindowClosingAdapters --> SettingsDialog WindowClosingAdapters --> MacroSettingsDialog WindowClosingAdapters --> HotkeyDialog ``` **Sources:** [src/io/github/samera2022/mouse_macros/manager/CacheManager.java L1-L86](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/manager/CacheManager.java#L1-L86), [README.md L63-L79](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/README.md#L63-L79) ### Usage Patterns 1. **Window Size Restoration**: UI components retrieve cached dimensions on initialization and save new dimensions on window close 2. **File Chooser State**: MacroManager queries last directories when displaying save/load dialogs and updates cache after successful file operations 3. **Configuration Override**: When `ConfigManager.config.enableDefaultStorage` is `true`, the `defaultMmcStoragePath` overrides cached directory values **Sources:** [README.md L77-L78](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/README.md#L77-L78) --- ## Relationship to ConfigManager ```mermaid flowchart TD ConfigManager["ConfigManager
config.cfg"] CacheManager["CacheManager
cache.json"] LongTerm["Long-term Settings
- Language
- Hotkeys
- Dark mode
- Default paths"] ShortTerm["Transient State
- Last directories
- Window sizes"] ConfigManager --> LongTerm CacheManager --> ShortTerm subgraph subGraph1 ["Data Classification"] LongTerm ShortTerm end subgraph subGraph0 ["Configuration Management"] ConfigManager CacheManager ConfigManager --> CacheManager end ``` **Sources:** [src/io/github/samera2022/mouse_macros/manager/ConfigManager.java L1-L121](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/manager/ConfigManager.java#L1-L121), [src/io/github/samera2022/mouse_macros/manager/CacheManager.java L1-L86](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/manager/CacheManager.java#L1-L86), [README.md L77-L78](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/README.md#L77-L78) ### Comparison Table | Aspect | ConfigManager | CacheManager | | --- | --- | --- | | **File** | config.cfg | cache.json | | **Purpose** | Long-term user preferences | Transient session state | | **Update Frequency** | Infrequent (user-initiated) | Frequent (automatic) | | **Contents** | Language, hotkeys, dark mode, custom settings | Last directories, window sizes | | **Initialization** | Static block loads on class load | Static field loads on first access | | **Reload Method** | `ConfigManager.reloadConfig()` | `CacheManager.reloadCache()` | | **Storage Location** | Same directory | Same directory | **Sources:** [src/io/github/samera2022/mouse_macros/manager/ConfigManager.java L14-L50](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/manager/ConfigManager.java#L14-L50), [src/io/github/samera2022/mouse_macros/manager/CacheManager.java L13-L60](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/manager/CacheManager.java#L13-L60) --- ## Data Flow Example: Save Macro Operation ```mermaid sequenceDiagram participant User participant MainFrame participant MacroManager participant JFileChooser participant CacheManager participant File System User->>MainFrame: Click "Save Macro" button MainFrame->>MacroManager: saveMacro() MacroManager->>CacheManager: getLastSaveDirectory() CacheManager-->>MacroManager: "/path/to/last/dir" MacroManager->>JFileChooser: new JFileChooser(lastDir) MacroManager->>JFileChooser: showSaveDialog() User->>JFileChooser: Select file and confirm JFileChooser-->>MacroManager: Selected file path MacroManager->>File System: Write macro to file File System-->>MacroManager: Success MacroManager->>CacheManager: setLastSaveDirectory(newDir) CacheManager->>CacheManager: cache.lastSaveDirectory = newDir CacheManager->>CacheManager: saveCache() CacheManager->>File System: Write cache.json ``` **Sources:** [src/io/github/samera2022/mouse_macros/manager/CacheManager.java L69-L74](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/manager/CacheManager.java#L69-L74) --- ## Error Handling and Resilience CacheManager implements defensive programming practices: 1. **Null Safety**: All getter methods check for null `windowSizeMap` and initialize if needed 2. **Exception Suppression**: File I/O exceptions are caught and logged to `System.err` but do not propagate 3. **Graceful Degradation**: If cache.json is corrupt or missing, returns default `FileChooserCache` instance 4. **Automatic Recovery**: Missing parent directories are created automatically during save operations This design ensures the cache system never causes application crashes, even when the file system is in an unexpected state. **Sources:** [src/io/github/samera2022/mouse_macros/manager/CacheManager.java L37-L60](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/manager/CacheManager.java#L37-L60), [src/io/github/samera2022/mouse_macros/manager/CacheManager.java L77-L85](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/manager/CacheManager.java#L77-L85) --- ## Implementation Notes ### Singleton Pattern CacheManager uses the static singleton pattern with lazy initialization: ```java // From CacheManager.java:17 private static FileChooserCache cache = loadCache(); ``` The cache is loaded once when the class is first accessed by the JVM, ensuring a single shared instance across the application. **Sources:** [src/io/github/samera2022/mouse_macros/manager/CacheManager.java L17](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/manager/CacheManager.java#L17-L17) ### Thread Safety **Important**: CacheManager is not thread-safe. All methods are static and operate on shared mutable state without synchronization. However, this is acceptable for MouseMacros because: * The application is single-threaded (Swing EDT) * Cache operations occur sequentially during user interactions * No concurrent access to cache methods occurs in practice **Sources:** [src/io/github/samera2022/mouse_macros/manager/CacheManager.java L13-L86](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/manager/CacheManager.java#L13-L86) ### Manual Reload Support The `reloadCache()` method allows explicit cache refresh from disk: ``` // From CacheManager.java:29-31 public static void reloadCache() { cache = loadCache(); } ``` This is primarily intended for development/debugging scenarios where the cache file may be manually edited while the application is running. **Sources:** [src/io/github/samera2022/mouse_macros/manager/CacheManager.java L29-L31](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/manager/CacheManager.java#L29-L31)