-
Notifications
You must be signed in to change notification settings - Fork 0
CacheManager
Relevant source files
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. For the file format specification of cache.json, see Configuration Files.
Sources: src/io/github/samera2022/mouse_macros/manager/CacheManager.java L1-L86
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
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<String,String> 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
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<String, String> | Maps window names to size strings (e.g., "800x600") | Empty HashMap |
Sources: src/io/github/samera2022/mouse_macros/manager/CacheManager.java L19-L23
The cache file is stored at: <LocalStoragePath>/cache.json
Where LocalStoragePath is determined by FileUtil.getLocalStoragePath(), typically resolving to:
-
Windows:
%USERPROFILE%/AppData/MouseMacros/cache.json -
Cross-platform: Uses
FileUtilto ensure consistent path resolution
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, src/io/github/samera2022/mouse_macros/util/FileUtil.java
CacheManager uses Google's Gson library with pretty-printing enabled for human-readable JSON output:
// From CacheManager.java:16
private static final Gson gson = new GsonBuilder().setPrettyPrinting().create();Example cache.json structure:
{
"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
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
The loadCache() method:
- Constructs the cache file path using
Paths.get(CACHE_PATH) - Checks if the file exists with
Files.exists(cachePath) - If exists, reads the file content as UTF-8 encoded bytes
- Deserializes JSON to
FileChooserCacheusing Gson - If missing or error occurs, returns a new default
FileChooserCacheinstance
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
// 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:
- Creates parent directory structure if needed using
Files.createDirectories() - Serializes the
FileChooserCacheobject to JSON - Writes JSON as UTF-8 encoded bytes to the cache file
- Handles
IOExceptiongracefully with error logging
Sources: src/io/github/samera2022/mouse_macros/manager/CacheManager.java L37-L47
| 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
| 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 "<width>x<height>" (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
flowchart TD
MainFrame["MainFrame"]
SettingsDialog["SettingsDialog"]
MacroSettingsDialog["MacroSettingsDialog"]
HotkeyDialog["HotkeyDialog"]
MacroManager["MacroManager"]
CacheManager["CacheManager<br>(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, README.md L63-L79
- Window Size Restoration: UI components retrieve cached dimensions on initialization and save new dimensions on window close
- File Chooser State: MacroManager queries last directories when displaying save/load dialogs and updates cache after successful file operations
-
Configuration Override: When
ConfigManager.config.enableDefaultStorageistrue, thedefaultMmcStoragePathoverrides cached directory values
Sources: README.md L77-L78
flowchart TD
ConfigManager["ConfigManager<br>config.cfg"]
CacheManager["CacheManager<br>cache.json"]
LongTerm["Long-term Settings<br>- Language<br>- Hotkeys<br>- Dark mode<br>- Default paths"]
ShortTerm["Transient State<br>- Last directories<br>- 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, src/io/github/samera2022/mouse_macros/manager/CacheManager.java L1-L86, README.md L77-L78
| 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, src/io/github/samera2022/mouse_macros/manager/CacheManager.java L13-L60
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
CacheManager implements defensive programming practices:
-
Null Safety: All getter methods check for null
windowSizeMapand initialize if needed -
Exception Suppression: File I/O exceptions are caught and logged to
System.errbut do not propagate -
Graceful Degradation: If cache.json is corrupt or missing, returns default
FileChooserCacheinstance - 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, src/io/github/samera2022/mouse_macros/manager/CacheManager.java L77-L85
CacheManager uses the static singleton pattern with lazy initialization:
// 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
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
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