package com.ufund.api.ufundapi.persistence; import java.io.File; import java.io.IOException; import java.util.Map; import java.util.TreeMap; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import com.fasterxml.jackson.databind.ObjectMapper; import com.ufund.api.ufundapi.model.User; @Component public class UserFileDAO implements UserDAO { private final Map users; // cache private final ObjectMapper objectMapper; private final String filename; public UserFileDAO(@Value("${users.file}") String filename, ObjectMapper objectMapper) throws IOException { this.filename = filename; this.objectMapper = objectMapper; users = new TreeMap<>(); load(); // load the users from the file } /** * Load changes from the json file * * @throws IOException Any IO issue with the file */ private void load() throws IOException { users.clear(); User[] usersArray = objectMapper.readValue(new File(filename), User[].class); for (User user : usersArray) { users.put(user.getUsername(), user); } } /** * Saves the needs to json * * @return True if the save was successful, false otherwise * @throws IOException If there was an IO issue saving the file */ private boolean save() throws IOException { User[] userArray = getUserArray(); objectMapper.writeValue(new File(filename), userArray); return true; } /** * Return an array of the needs * * @return An array of all the needs */ private User[] getUserArray() { return users.values().toArray(User[]::new); } @Override public User[] getUsers() throws IOException { synchronized (users) { return getUserArray(); } } /** * Return the user with the String name name or null otherwise * * @param username Name of desired user * * @return Desired user, null otherwise * @throws IOException If there was an IO issue saving the file */ @Override public User getUser(String username) throws IOException { synchronized (users) { return users.getOrDefault(username, null); } } /** * Create a User user * * @param user User to create * * @return Desired created user * @throws IOException If there was an IO issue saving the file */ @Override public User addUser(User user) throws IOException { synchronized (users) { var res = users.putIfAbsent(user.getUsername(), user); save(); return res; } } /** * Update a user that matches the supplied name * * @param name The name of the user * @param newUser New user data * * @return Desired user, null otherwise * @throws IOException If there was an IO issue saving the file */ @Override public User updateUser(User newUser, String name) throws IOException { synchronized (users) { if (users.containsKey(name)) { users.put(name, newUser); save(); return newUser; } else { return null; } } } /** * Delete a user matching the name * * @param username The name of the user * * @return True if deleted, false otherwise * @throws IOException If there was an IO issue saving the file */ @Override public boolean deleteUser(String username) throws IOException { synchronized (users) { if (users.containsKey(username)) { users.remove(username); return save(); } else { return false; } } } }