From 58c4432815d0dbe2173dbb1a4aed4c6683a10e1a Mon Sep 17 00:00:00 2001 From: WillemDalton Date: Mon, 10 Nov 2025 19:47:15 -0500 Subject: a bit more progress on the menu for import export --- .../userinput/menus/ImportExportMenu.java | 25 ++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) (limited to 'src/main') diff --git a/src/main/java/design/controller/userinput/menus/ImportExportMenu.java b/src/main/java/design/controller/userinput/menus/ImportExportMenu.java index ed313d7..43970ea 100644 --- a/src/main/java/design/controller/userinput/menus/ImportExportMenu.java +++ b/src/main/java/design/controller/userinput/menus/ImportExportMenu.java @@ -2,10 +2,16 @@ package design.controller.userinput.menus; import design.controller.userinput.Menu; import design.controller.userinput.MenuOption; +import design.persistence.JSONPersonalDatabase; +import design.persistence.XMLParser; import java.util.List; public class ImportExportMenu extends Menu { + + String currentFormat = "JSON"; + XMLParser xmlParser = new XMLParser(); + @Override public String getTitle() { return "import export menu"; @@ -15,17 +21,24 @@ public class ImportExportMenu extends Menu { public List getMenuOptions() { List opts = new java.util.ArrayList<>(); + opts.add(new MenuOption("return to main menu", () -> new MainMenu().present())); - opts.add(new MenuOption("set to XML", () -> new MainMenu().present())); - opts.add(new MenuOption("set to JSON", () -> new MainMenu().present())); + opts.add(new MenuOption("set to XML", () -> {currentFormat = "XML";})); + opts.add(new MenuOption("set to JSON", () -> {currentFormat = "JSON";})); - opts.add(new MenuOption("import league...", () -> { - })); + // TO DO: think of better solution for menus...i don't want to layer them deeply but saving format in a string is kind of a dumb solution. + opts.add(new MenuOption("import league...", () -> {})); opts.add(new MenuOption("export league...", () -> {})); - opts.add(new MenuOption("import personal profile...", () -> {})); - opts.add(new MenuOption("export personal profile...", () -> {})); + opts.add(new MenuOption("import personal profile...", () -> { + // if(currentFormat == "JSON") + // { + // JSONPersonalDatabase.instance().importData(null); + // } + })); + opts.add(new MenuOption("export personal profile...", () -> { + })); return opts; } -- cgit v1.2.3 From f7102fd39b266b3d31fe72448b5d64d139648dee Mon Sep 17 00:00:00 2001 From: WillemDalton Date: Tue, 11 Nov 2025 08:50:31 -0500 Subject: progress on import/export --- .../userinput/menus/ImportExportMenu.java | 70 ++++++++++++++++------ src/main/java/design/model/DataHandler.java | 11 ++++ src/main/java/design/persistence/XMLParser.java | 26 +++++--- 3 files changed, 83 insertions(+), 24 deletions(-) create mode 100644 src/main/java/design/model/DataHandler.java (limited to 'src/main') diff --git a/src/main/java/design/controller/userinput/menus/ImportExportMenu.java b/src/main/java/design/controller/userinput/menus/ImportExportMenu.java index 43970ea..4c7df00 100644 --- a/src/main/java/design/controller/userinput/menus/ImportExportMenu.java +++ b/src/main/java/design/controller/userinput/menus/ImportExportMenu.java @@ -5,13 +5,26 @@ import design.controller.userinput.MenuOption; import design.persistence.JSONPersonalDatabase; import design.persistence.XMLParser; +import java.io.File; +import java.io.IOException; import java.util.List; +import java.util.Map; +import java.util.Scanner; public class ImportExportMenu extends Menu { - - String currentFormat = "JSON"; XMLParser xmlParser = new XMLParser(); + private static final Map> handlers = Map.of( + "json", Map.of( + true, new PersonalJsonHandler(), + false, new LeagueJsonHandler() + ), + "csv", Map.of( + true, new PersonalCsvHandler(), + false, new LeagueCsvHandler() + )); + + @Override public String getTitle() { return "import export menu"; @@ -24,23 +37,46 @@ public class ImportExportMenu extends Menu { opts.add(new MenuOption("return to main menu", () -> new MainMenu().present())); - opts.add(new MenuOption("set to XML", () -> {currentFormat = "XML";})); - opts.add(new MenuOption("set to JSON", () -> {currentFormat = "JSON";})); + opts.add(new MenuOption("import league...", () -> promptForPath(true, false))); + opts.add(new MenuOption("export league...", () -> promptForPath(false, false))); + opts.add(new MenuOption("import personal profile...", () -> promptForPath(true, true))); + opts.add(new MenuOption("export personal profile...", () -> promptForPath(false, true))); + return opts; + } - // TO DO: think of better solution for menus...i don't want to layer them deeply but saving format in a string is kind of a dumb solution. - opts.add(new MenuOption("import league...", () -> {})); - opts.add(new MenuOption("export league...", () -> {})); - opts.add(new MenuOption("import personal profile...", () -> { - // if(currentFormat == "JSON") - // { - // JSONPersonalDatabase.instance().importData(null); - // } - })); - opts.add(new MenuOption("export personal profile...", () -> { - })); + private void promptForPath(boolean isImporting, boolean isPersonalProfile) + { + System.out.println("Enter file path: "); + Scanner sc = new Scanner(System.in); + String path = sc.nextLine(); + File file = new File(path); - return opts; + String ext = getExtension(path); + Map map = handlers.get(ext); + if (map == null) { + System.out.println("Unsupported file type: " + ext); + return; + } + + DataHandler handler = map.get(isPersonalProfile); + if (handler == null) { + System.out.println("No handler for this profile type."); + return; + } + + try { + if (isImporting) + handler.importData(file); + else + handler.exportData(file); + } catch (IOException e) { + System.err.println("I/O error: " + e.getMessage()); + } } -} \ No newline at end of file + private static String getExtension(String fileName) { + int i = fileName.lastIndexOf('.'); + return (i >= 0) ? fileName.substring(i + 1).toLowerCase() : ""; + } +} diff --git a/src/main/java/design/model/DataHandler.java b/src/main/java/design/model/DataHandler.java new file mode 100644 index 0000000..e7dda33 --- /dev/null +++ b/src/main/java/design/model/DataHandler.java @@ -0,0 +1,11 @@ +package design.model; + +import java.io.File; +import java.io.IOException; + +public interface DataHandler { + void importPersonalData(File file) throws IOException; + void exportPersonalData(File file) throws IOException; + void importLeagueData(File file) throws IOException; + void exportLeagueData(File file) throws IOException; +} \ No newline at end of file diff --git a/src/main/java/design/persistence/XMLParser.java b/src/main/java/design/persistence/XMLParser.java index 472931a..3d04a03 100644 --- a/src/main/java/design/persistence/XMLParser.java +++ b/src/main/java/design/persistence/XMLParser.java @@ -1,6 +1,7 @@ package design.persistence; import java.io.File; import java.io.IOException; +import design.model.DataHandler; import com.fasterxml.jackson.databind.ObjectMapper; @@ -9,24 +10,35 @@ import com.fasterxml.jackson.dataformat.xml.XmlMapper; -public class XMLParser { - +public class XMLParser implements DataHandler +{ private final ObjectMapper jsonMapper = new ObjectMapper(); private final XmlMapper xmlMapper = new XmlMapper(); - public File exportData() throws IOException { + public void exportPersonalData(File fileName) throws IOException { File jsonData = JSONPersonalDatabase.instance().exportData(); Golfer[] golfers = jsonMapper.readValue(jsonData, Golfer[].class); - File xmlFile = new File("data/data.xml"); + File xmlFile = new File(fileName + ".xml"); xmlMapper.writerWithDefaultPrettyPrinter().writeValue(xmlFile, golfers); - return xmlFile; } - public void importData(File xmlFile) throws IOException { - Golfer[] golfers = xmlMapper.readValue(xmlFile, Golfer[].class); + public void importPersonalData(File fileName) throws IOException { + Golfer[] golfers = xmlMapper.readValue(fileName, Golfer[].class); File tempJson = File.createTempFile("imported", ".json"); jsonMapper.writerWithDefaultPrettyPrinter().writeValue(tempJson, golfers); JSONPersonalDatabase.instance().importData(tempJson); tempJson.delete(); } + + public void exportLeagueData(File fileName) + { + // TO DO: exporting league data + } + + public void importLeagueData(File fileName) + { + // TO DO: importing league data + } } + + -- cgit v1.2.3 From 94ac731c00da6022909bbb96c835d7c63204da73 Mon Sep 17 00:00:00 2001 From: WillemDalton Date: Tue, 11 Nov 2025 09:01:01 -0500 Subject: progress on importing exporting --- .../userinput/menus/ImportExportMenu.java | 52 ++++++++++------------ .../controller/userinput/menus/UserSettings.java | 9 +--- src/main/java/design/persistence/JSONHandler.java | 28 ++++++++++++ src/main/java/design/persistence/XMLHandler.java | 44 ++++++++++++++++++ src/main/java/design/persistence/XMLParser.java | 44 ------------------ 5 files changed, 97 insertions(+), 80 deletions(-) create mode 100644 src/main/java/design/persistence/JSONHandler.java create mode 100644 src/main/java/design/persistence/XMLHandler.java delete mode 100644 src/main/java/design/persistence/XMLParser.java (limited to 'src/main') diff --git a/src/main/java/design/controller/userinput/menus/ImportExportMenu.java b/src/main/java/design/controller/userinput/menus/ImportExportMenu.java index 4c7df00..db861c5 100644 --- a/src/main/java/design/controller/userinput/menus/ImportExportMenu.java +++ b/src/main/java/design/controller/userinput/menus/ImportExportMenu.java @@ -2,8 +2,8 @@ package design.controller.userinput.menus; import design.controller.userinput.Menu; import design.controller.userinput.MenuOption; -import design.persistence.JSONPersonalDatabase; -import design.persistence.XMLParser; +import design.persistence.JSONHandler; +import design.persistence.XMLHandler; import java.io.File; import java.io.IOException; @@ -11,20 +11,14 @@ import java.util.List; import java.util.Map; import java.util.Scanner; -public class ImportExportMenu extends Menu { - XMLParser xmlParser = new XMLParser(); +import design.model.DataHandler; - private static final Map> handlers = Map.of( - "json", Map.of( - true, new PersonalJsonHandler(), - false, new LeagueJsonHandler() - ), - "csv", Map.of( - true, new PersonalCsvHandler(), - false, new LeagueCsvHandler() - )); +public class ImportExportMenu extends Menu { + private static final Map handlers = Map.of( + "xml", new XMLHandler(), + "json", new JSONHandler() + ); - @Override public String getTitle() { return "import export menu"; @@ -49,27 +43,29 @@ public class ImportExportMenu extends Menu { { System.out.println("Enter file path: "); Scanner sc = new Scanner(System.in); - String path = sc.nextLine(); - File file = new File(path); + String filePath = sc.nextLine(); + File file = new File(filePath); - String ext = getExtension(path); - Map map = handlers.get(ext); - if (map == null) { - System.out.println("Unsupported file type: " + ext); - return; - } + String ext = getExtension(filePath); + DataHandler handler = handlers.get(ext); - DataHandler handler = map.get(isPersonalProfile); if (handler == null) { - System.out.println("No handler for this profile type."); + System.out.println("Unsupported file type: " + ext); return; } try { - if (isImporting) - handler.importData(file); - else - handler.exportData(file); + if (isImporting) { + if (isPersonalProfile) + handler.importPersonalData(file); + else + handler.importLeagueData(file); + } else { + if (isPersonalProfile) + handler.exportPersonalData(file); + else + handler.exportLeagueData(file); + } } catch (IOException e) { System.err.println("I/O error: " + e.getMessage()); } diff --git a/src/main/java/design/controller/userinput/menus/UserSettings.java b/src/main/java/design/controller/userinput/menus/UserSettings.java index d029e45..865b00d 100644 --- a/src/main/java/design/controller/userinput/menus/UserSettings.java +++ b/src/main/java/design/controller/userinput/menus/UserSettings.java @@ -60,15 +60,8 @@ public class UserSettings extends Menu { this.present(); })); - - opts.add(new MenuOption("import...", () -> { - - })); + opts.add(new MenuOption("manage data...", () -> new ImportExportMenu().present())); - opts.add(new MenuOption("export...", () -> { - - this.present(); - })); return opts; } diff --git a/src/main/java/design/persistence/JSONHandler.java b/src/main/java/design/persistence/JSONHandler.java new file mode 100644 index 0000000..06ed202 --- /dev/null +++ b/src/main/java/design/persistence/JSONHandler.java @@ -0,0 +1,28 @@ +package design.persistence; +import java.io.File; +import java.io.IOException; +import design.model.DataHandler; + +public class JSONHandler implements DataHandler +{ + + public void exportPersonalData(File fileName) throws IOException { + JSONPersonalDatabase.instance().exportData(); // fix this + } + + public void importPersonalData(File fileName) throws IOException { + JSONPersonalDatabase.instance().importData(fileName); + } + + public void exportLeagueData(File fileName) + { + // TO DO: exporting league data + } + + public void importLeagueData(File fileName) + { + // TO DO: importing league data + } +} + + diff --git a/src/main/java/design/persistence/XMLHandler.java b/src/main/java/design/persistence/XMLHandler.java new file mode 100644 index 0000000..413defc --- /dev/null +++ b/src/main/java/design/persistence/XMLHandler.java @@ -0,0 +1,44 @@ +package design.persistence; +import java.io.File; +import java.io.IOException; +import design.model.DataHandler; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import design.model.Golfer; +import com.fasterxml.jackson.dataformat.xml.XmlMapper; + + + +public class XMLHandler implements DataHandler +{ + private final ObjectMapper jsonMapper = new ObjectMapper(); + private final XmlMapper xmlMapper = new XmlMapper(); + + public void exportPersonalData(File fileName) throws IOException { + File jsonData = JSONPersonalDatabase.instance().exportData(); + Golfer[] golfers = jsonMapper.readValue(jsonData, Golfer[].class); + File xmlFile = new File(fileName + ".xml"); + xmlMapper.writerWithDefaultPrettyPrinter().writeValue(xmlFile, golfers); + } + + public void importPersonalData(File fileName) throws IOException { + Golfer[] golfers = xmlMapper.readValue(fileName, Golfer[].class); + File tempJson = File.createTempFile("imported", ".json"); + jsonMapper.writerWithDefaultPrettyPrinter().writeValue(tempJson, golfers); + JSONPersonalDatabase.instance().importData(tempJson); + tempJson.delete(); + } + + public void exportLeagueData(File fileName) + { + // TO DO: exporting league data + } + + public void importLeagueData(File fileName) + { + // TO DO: importing league data + } +} + + diff --git a/src/main/java/design/persistence/XMLParser.java b/src/main/java/design/persistence/XMLParser.java deleted file mode 100644 index 3d04a03..0000000 --- a/src/main/java/design/persistence/XMLParser.java +++ /dev/null @@ -1,44 +0,0 @@ -package design.persistence; -import java.io.File; -import java.io.IOException; -import design.model.DataHandler; - -import com.fasterxml.jackson.databind.ObjectMapper; - -import design.model.Golfer; -import com.fasterxml.jackson.dataformat.xml.XmlMapper; - - - -public class XMLParser implements DataHandler -{ - private final ObjectMapper jsonMapper = new ObjectMapper(); - private final XmlMapper xmlMapper = new XmlMapper(); - - public void exportPersonalData(File fileName) throws IOException { - File jsonData = JSONPersonalDatabase.instance().exportData(); - Golfer[] golfers = jsonMapper.readValue(jsonData, Golfer[].class); - File xmlFile = new File(fileName + ".xml"); - xmlMapper.writerWithDefaultPrettyPrinter().writeValue(xmlFile, golfers); - } - - public void importPersonalData(File fileName) throws IOException { - Golfer[] golfers = xmlMapper.readValue(fileName, Golfer[].class); - File tempJson = File.createTempFile("imported", ".json"); - jsonMapper.writerWithDefaultPrettyPrinter().writeValue(tempJson, golfers); - JSONPersonalDatabase.instance().importData(tempJson); - tempJson.delete(); - } - - public void exportLeagueData(File fileName) - { - // TO DO: exporting league data - } - - public void importLeagueData(File fileName) - { - // TO DO: importing league data - } -} - - -- cgit v1.2.3 From d29548bd7d04375578361f6a75659c046a270b75 Mon Sep 17 00:00:00 2001 From: WillemDalton Date: Tue, 11 Nov 2025 16:42:39 -0500 Subject: fixed exporting xml --- .../design/controller/userinput/menus/ImportExportMenu.java | 2 ++ src/main/java/design/persistence/JSONHandler.java | 2 +- src/main/java/design/persistence/JSONPersonalDatabase.java | 11 ++++++----- src/main/java/design/persistence/PersonalDatabase.java | 4 ---- src/main/java/design/persistence/XMLHandler.java | 11 +++++++---- 5 files changed, 16 insertions(+), 14 deletions(-) (limited to 'src/main') diff --git a/src/main/java/design/controller/userinput/menus/ImportExportMenu.java b/src/main/java/design/controller/userinput/menus/ImportExportMenu.java index db861c5..dbad0e3 100644 --- a/src/main/java/design/controller/userinput/menus/ImportExportMenu.java +++ b/src/main/java/design/controller/userinput/menus/ImportExportMenu.java @@ -69,6 +69,8 @@ public class ImportExportMenu extends Menu { } catch (IOException e) { System.err.println("I/O error: " + e.getMessage()); } + + new ImportExportMenu().present(); } private static String getExtension(String fileName) { diff --git a/src/main/java/design/persistence/JSONHandler.java b/src/main/java/design/persistence/JSONHandler.java index 06ed202..419d080 100644 --- a/src/main/java/design/persistence/JSONHandler.java +++ b/src/main/java/design/persistence/JSONHandler.java @@ -7,7 +7,7 @@ public class JSONHandler implements DataHandler { public void exportPersonalData(File fileName) throws IOException { - JSONPersonalDatabase.instance().exportData(); // fix this + JSONPersonalDatabase.instance().exportData(fileName); // fix this } public void importPersonalData(File fileName) throws IOException { diff --git a/src/main/java/design/persistence/JSONPersonalDatabase.java b/src/main/java/design/persistence/JSONPersonalDatabase.java index 2f003cb..8d263fc 100644 --- a/src/main/java/design/persistence/JSONPersonalDatabase.java +++ b/src/main/java/design/persistence/JSONPersonalDatabase.java @@ -13,6 +13,8 @@ import design.model.League; import java.io.File; import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.StandardCopyOption; import java.util.HashMap; import java.util.Map; @@ -99,13 +101,12 @@ public class JSONPersonalDatabase implements PersonalDatabase { save(); } - @Override - public File exportData() throws IOException{ - save(); - return file; + + public File exportData(File newFile) throws IOException{ + Files.copy(file.toPath(), newFile.toPath(), StandardCopyOption.REPLACE_EXISTING); + return newFile; } - @Override public void importData(File newFile) throws IOException { Golfer[] newGolfers = mapper.readValue(newFile, Golfer[].class); cache.clear(); diff --git a/src/main/java/design/persistence/PersonalDatabase.java b/src/main/java/design/persistence/PersonalDatabase.java index 186474e..63f9182 100644 --- a/src/main/java/design/persistence/PersonalDatabase.java +++ b/src/main/java/design/persistence/PersonalDatabase.java @@ -19,8 +19,4 @@ public interface PersonalDatabase { void removeGolfer(Golfer golfer) throws IOException; void updateGolfer(Golfer golfer) throws IOException; - - void importData(File newFile) throws IOException; - - File exportData() throws IOException; } diff --git a/src/main/java/design/persistence/XMLHandler.java b/src/main/java/design/persistence/XMLHandler.java index 413defc..dc67687 100644 --- a/src/main/java/design/persistence/XMLHandler.java +++ b/src/main/java/design/persistence/XMLHandler.java @@ -3,7 +3,9 @@ import java.io.File; import java.io.IOException; import design.model.DataHandler; +import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; import design.model.Golfer; import com.fasterxml.jackson.dataformat.xml.XmlMapper; @@ -16,10 +18,11 @@ public class XMLHandler implements DataHandler private final XmlMapper xmlMapper = new XmlMapper(); public void exportPersonalData(File fileName) throws IOException { - File jsonData = JSONPersonalDatabase.instance().exportData(); - Golfer[] golfers = jsonMapper.readValue(jsonData, Golfer[].class); - File xmlFile = new File(fileName + ".xml"); - xmlMapper.writerWithDefaultPrettyPrinter().writeValue(xmlFile, golfers); + File jsonData = JSONPersonalDatabase.instance().exportData(fileName); + JsonNode golfersNode = jsonMapper.readTree(jsonData); + ObjectNode root = xmlMapper.createObjectNode(); + root.set("golfers", golfersNode); + xmlMapper.writerWithDefaultPrettyPrinter().writeValue(fileName, root); } public void importPersonalData(File fileName) throws IOException { -- cgit v1.2.3 From 7de856cbb656d8b5fa88fed62380a8d4611060a1 Mon Sep 17 00:00:00 2001 From: WillemDalton Date: Tue, 11 Nov 2025 17:51:31 -0500 Subject: working on XML formatting --- src/main/java/design/model/Golfer.java | 3 +++ src/main/java/design/persistence/JSONHandler.java | 12 +++++------ src/main/java/design/persistence/XMLHandler.java | 25 +++++++++++++++-------- 3 files changed, 26 insertions(+), 14 deletions(-) (limited to 'src/main') diff --git a/src/main/java/design/model/Golfer.java b/src/main/java/design/model/Golfer.java index 960568f..1c4e669 100644 --- a/src/main/java/design/model/Golfer.java +++ b/src/main/java/design/model/Golfer.java @@ -1,6 +1,7 @@ package design.model; import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonPropertyOrder; import java.util.ArrayList; @@ -17,6 +18,8 @@ public class Golfer { private int nextClubId; private final List invites; + + @JsonCreator private Golfer(String username, int passwordHash, String fullName, List courses, List rounds, List clubs, List invites) { diff --git a/src/main/java/design/persistence/JSONHandler.java b/src/main/java/design/persistence/JSONHandler.java index 419d080..a8967d2 100644 --- a/src/main/java/design/persistence/JSONHandler.java +++ b/src/main/java/design/persistence/JSONHandler.java @@ -6,20 +6,20 @@ import design.model.DataHandler; public class JSONHandler implements DataHandler { - public void exportPersonalData(File fileName) throws IOException { - JSONPersonalDatabase.instance().exportData(fileName); // fix this + public void exportPersonalData(File file) throws IOException { + JSONPersonalDatabase.instance().exportData(file); } - public void importPersonalData(File fileName) throws IOException { - JSONPersonalDatabase.instance().importData(fileName); + public void importPersonalData(File file) throws IOException { + JSONPersonalDatabase.instance().importData(file); } - public void exportLeagueData(File fileName) + public void exportLeagueData(File file) { // TO DO: exporting league data } - public void importLeagueData(File fileName) + public void importLeagueData(File file) { // TO DO: importing league data } diff --git a/src/main/java/design/persistence/XMLHandler.java b/src/main/java/design/persistence/XMLHandler.java index dc67687..c71712b 100644 --- a/src/main/java/design/persistence/XMLHandler.java +++ b/src/main/java/design/persistence/XMLHandler.java @@ -17,28 +17,37 @@ public class XMLHandler implements DataHandler private final ObjectMapper jsonMapper = new ObjectMapper(); private final XmlMapper xmlMapper = new XmlMapper(); - public void exportPersonalData(File fileName) throws IOException { - File jsonData = JSONPersonalDatabase.instance().exportData(fileName); + public void exportPersonalData(File file) throws IOException { + // get our json data + File jsonData = JSONPersonalDatabase.instance().exportData(file); + + // read the top tree node (the array) JsonNode golfersNode = jsonMapper.readTree(jsonData); + + // map it to an object node (not sure if im gonna use this) ObjectNode root = xmlMapper.createObjectNode(); - root.set("golfers", golfersNode); - xmlMapper.writerWithDefaultPrettyPrinter().writeValue(fileName, root); + root.set("golfer", golfersNode); + xmlMapper.writerWithDefaultPrettyPrinter().writeValue(file, root); } - public void importPersonalData(File fileName) throws IOException { - Golfer[] golfers = xmlMapper.readValue(fileName, Golfer[].class); + public void importPersonalData(File file) throws IOException { + + // get our root node + JsonNode root = xmlMapper.readTree(file); + Golfer[] golfers = xmlMapper.treeToValue(root, Golfer[].class); + File tempJson = File.createTempFile("imported", ".json"); jsonMapper.writerWithDefaultPrettyPrinter().writeValue(tempJson, golfers); JSONPersonalDatabase.instance().importData(tempJson); tempJson.delete(); } - public void exportLeagueData(File fileName) + public void exportLeagueData(File file) { // TO DO: exporting league data } - public void importLeagueData(File fileName) + public void importLeagueData(File file) { // TO DO: importing league data } -- cgit v1.2.3 From 0efa0586e27c173211153b186ae08eb3b7c8d588 Mon Sep 17 00:00:00 2001 From: WillemDalton Date: Thu, 13 Nov 2025 08:28:18 -0500 Subject: added league JSON import/export, still working with XML import --- src/main/java/design/persistence/JSONHandler.java | 8 +++--- .../design/persistence/JSONLeagueDatabase.java | 17 ++++++++++++ .../design/persistence/JSONPersonalDatabase.java | 1 - src/main/java/design/persistence/XMLHandler.java | 31 +++++++++++++--------- 4 files changed, 40 insertions(+), 17 deletions(-) (limited to 'src/main') diff --git a/src/main/java/design/persistence/JSONHandler.java b/src/main/java/design/persistence/JSONHandler.java index a8967d2..77ec987 100644 --- a/src/main/java/design/persistence/JSONHandler.java +++ b/src/main/java/design/persistence/JSONHandler.java @@ -14,14 +14,14 @@ public class JSONHandler implements DataHandler JSONPersonalDatabase.instance().importData(file); } - public void exportLeagueData(File file) + public void exportLeagueData(File file) throws IOException { - // TO DO: exporting league data + JSONLeagueDatabase.instance().importData(file); } - public void importLeagueData(File file) + public void importLeagueData(File file) throws IOException { - // TO DO: importing league data + JSONLeagueDatabase.instance().exportData(file); } } diff --git a/src/main/java/design/persistence/JSONLeagueDatabase.java b/src/main/java/design/persistence/JSONLeagueDatabase.java index 8b201e6..edc649b 100644 --- a/src/main/java/design/persistence/JSONLeagueDatabase.java +++ b/src/main/java/design/persistence/JSONLeagueDatabase.java @@ -13,6 +13,8 @@ import design.model.League; import java.io.File; import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.StandardCopyOption; import java.util.Arrays; import java.util.HashMap; import java.util.Map; @@ -97,4 +99,19 @@ public class JSONLeagueDatabase implements LeagueDatabase { cache.put(league.getId(), league); save(); } + + public File exportData(File newFile) throws IOException{ + Files.copy(file.toPath(), newFile.toPath(), StandardCopyOption.REPLACE_EXISTING); + return newFile; + } + + public void importData(File newFile) throws IOException { + League[] newLeagues = mapper.readValue(newFile, League[].class); + cache.clear(); + for (League l: newLeagues) { + cache.put(l.getId(), l); + } + save(); + } + } diff --git a/src/main/java/design/persistence/JSONPersonalDatabase.java b/src/main/java/design/persistence/JSONPersonalDatabase.java index 8d263fc..3fc5cab 100644 --- a/src/main/java/design/persistence/JSONPersonalDatabase.java +++ b/src/main/java/design/persistence/JSONPersonalDatabase.java @@ -113,7 +113,6 @@ public class JSONPersonalDatabase implements PersonalDatabase { for (Golfer g : newGolfers) { cache.put(g.getUsername(), g); } - save(); } } diff --git a/src/main/java/design/persistence/XMLHandler.java b/src/main/java/design/persistence/XMLHandler.java index c71712b..eaae811 100644 --- a/src/main/java/design/persistence/XMLHandler.java +++ b/src/main/java/design/persistence/XMLHandler.java @@ -20,11 +20,9 @@ public class XMLHandler implements DataHandler public void exportPersonalData(File file) throws IOException { // get our json data File jsonData = JSONPersonalDatabase.instance().exportData(file); - // read the top tree node (the array) JsonNode golfersNode = jsonMapper.readTree(jsonData); - - // map it to an object node (not sure if im gonna use this) + // map it to an object node ObjectNode root = xmlMapper.createObjectNode(); root.set("golfer", golfersNode); xmlMapper.writerWithDefaultPrettyPrinter().writeValue(file, root); @@ -32,22 +30,31 @@ public class XMLHandler implements DataHandler public void importPersonalData(File file) throws IOException { - // get our root node - JsonNode root = xmlMapper.readTree(file); - Golfer[] golfers = xmlMapper.treeToValue(root, Golfer[].class); + JsonNode root = xmlMapper.readTree(file); + JsonNode golfersNode = root.get("golfer"); + if (golfersNode == null) { + throw new IOException("Expected 'golfer' element in XML root, but none found"); + } + if (!golfersNode.isArray()) { + golfersNode = xmlMapper.createArrayNode().add(golfersNode); + } + + Golfer[] golfers = xmlMapper.treeToValue(golfersNode, Golfer[].class); - File tempJson = File.createTempFile("imported", ".json"); - jsonMapper.writerWithDefaultPrettyPrinter().writeValue(tempJson, golfers); - JSONPersonalDatabase.instance().importData(tempJson); - tempJson.delete(); + File tempJson = File.createTempFile("imported", ".json"); + jsonMapper.writerWithDefaultPrettyPrinter().writeValue(tempJson, golfers); + JSONPersonalDatabase.instance().importData(tempJson); + tempJson.delete(); } - public void exportLeagueData(File file) + + + public void exportLeagueData(File file) throws IOException { // TO DO: exporting league data } - public void importLeagueData(File file) + public void importLeagueData(File file) throws IOException { // TO DO: importing league data } -- cgit v1.2.3 From 18a142e6d76288ae9bc6a597461e06a5ee02f6ad Mon Sep 17 00:00:00 2001 From: WillemDalton Date: Thu, 13 Nov 2025 09:00:56 -0500 Subject: more work on adapting to XML --- src/main/java/design/persistence/XMLHandler.java | 28 ++++++++---------------- 1 file changed, 9 insertions(+), 19 deletions(-) (limited to 'src/main') diff --git a/src/main/java/design/persistence/XMLHandler.java b/src/main/java/design/persistence/XMLHandler.java index eaae811..174407a 100644 --- a/src/main/java/design/persistence/XMLHandler.java +++ b/src/main/java/design/persistence/XMLHandler.java @@ -23,28 +23,18 @@ public class XMLHandler implements DataHandler // read the top tree node (the array) JsonNode golfersNode = jsonMapper.readTree(jsonData); // map it to an object node - ObjectNode root = xmlMapper.createObjectNode(); - root.set("golfer", golfersNode); - xmlMapper.writerWithDefaultPrettyPrinter().writeValue(file, root); + xmlMapper.writerWithDefaultPrettyPrinter().writeValue(file, golfersNode); } public void importPersonalData(File file) throws IOException { - - JsonNode root = xmlMapper.readTree(file); - JsonNode golfersNode = root.get("golfer"); - if (golfersNode == null) { - throw new IOException("Expected 'golfer' element in XML root, but none found"); - } - if (!golfersNode.isArray()) { - golfersNode = xmlMapper.createArrayNode().add(golfersNode); - } - - Golfer[] golfers = xmlMapper.treeToValue(golfersNode, Golfer[].class); - - File tempJson = File.createTempFile("imported", ".json"); - jsonMapper.writerWithDefaultPrettyPrinter().writeValue(tempJson, golfers); - JSONPersonalDatabase.instance().importData(tempJson); - tempJson.delete(); + JsonNode root = xmlMapper.readTree(file); + + System.out.println(root.toPrettyString()); + Golfer[] golfers = xmlMapper.treeToValue(root, Golfer[].class); + File tempJson = File.createTempFile("imported", ".json"); + jsonMapper.writerWithDefaultPrettyPrinter().writeValue(tempJson, golfers); + JSONPersonalDatabase.instance().importData(tempJson); + tempJson.delete(); } -- cgit v1.2.3 From 38aacc304d5bc55a8e5705f9eb378ca18fc5a4a7 Mon Sep 17 00:00:00 2001 From: WillemDalton Date: Thu, 13 Nov 2025 09:05:29 -0500 Subject: added comments to adapter --- src/main/java/design/persistence/XMLHandler.java | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) (limited to 'src/main') diff --git a/src/main/java/design/persistence/XMLHandler.java b/src/main/java/design/persistence/XMLHandler.java index 174407a..706dabd 100644 --- a/src/main/java/design/persistence/XMLHandler.java +++ b/src/main/java/design/persistence/XMLHandler.java @@ -18,19 +18,32 @@ public class XMLHandler implements DataHandler private final XmlMapper xmlMapper = new XmlMapper(); public void exportPersonalData(File file) throws IOException { - // get our json data + // get our json data just from the JSON database File jsonData = JSONPersonalDatabase.instance().exportData(file); - // read the top tree node (the array) + + // read the the data from the JSON, as a JsonNode. JsonNode golfersNode = jsonMapper.readTree(jsonData); - // map it to an object node - xmlMapper.writerWithDefaultPrettyPrinter().writeValue(file, golfersNode); + + // XML requires a parent node, we can't just throw the golfersnode into the xml or else it will only produce the first element + ObjectNode root = xmlMapper.createObjectNode(); + root.set("golfer", golfersNode); + + //write to the xml file. + xmlMapper.writerWithDefaultPrettyPrinter().writeValue(file, root); } public void importPersonalData(File file) throws IOException { + + // read our root, the object node JsonNode root = xmlMapper.readTree(file); + // debug print line System.out.println(root.toPrettyString()); + + // !!! here is where it's failing...our root is not serializable to an array of golfers. !!! Golfer[] golfers = xmlMapper.treeToValue(root, Golfer[].class); + + // from here out should be good File tempJson = File.createTempFile("imported", ".json"); jsonMapper.writerWithDefaultPrettyPrinter().writeValue(tempJson, golfers); JSONPersonalDatabase.instance().importData(tempJson); -- cgit v1.2.3 From 9adc51f8d74577b5c4ae9c1f88341252f2c22939 Mon Sep 17 00:00:00 2001 From: sowgro Date: Thu, 13 Nov 2025 20:05:25 -0500 Subject: export almost working --- .../userinput/menus/ImportExportMenu.java | 58 +++++++++---------- .../controller/userinput/menus/MainMenu.java | 3 +- .../controller/userinput/menus/UserSettings.java | 3 - src/main/java/design/model/DataHandler.java | 11 ---- src/main/java/design/persistence/JSONHandler.java | 28 --------- .../design/persistence/JSONLeagueDatabase.java | 21 ++++--- .../design/persistence/JSONPersonalDatabase.java | 27 ++++----- .../java/design/persistence/LeagueDatabase.java | 3 +- .../java/design/persistence/PersonalDatabase.java | 5 +- src/main/java/design/persistence/XMLHandler.java | 66 ---------------------- .../persistence/importexport/DataHandler.java | 11 ++++ .../persistence/importexport/DataSource.java | 12 ++++ .../persistence/importexport/JSONHandler.java | 30 ++++++++++ .../persistence/importexport/XMLHandler.java | 34 +++++++++++ 14 files changed, 145 insertions(+), 167 deletions(-) delete mode 100644 src/main/java/design/model/DataHandler.java delete mode 100644 src/main/java/design/persistence/JSONHandler.java delete mode 100644 src/main/java/design/persistence/XMLHandler.java create mode 100644 src/main/java/design/persistence/importexport/DataHandler.java create mode 100644 src/main/java/design/persistence/importexport/DataSource.java create mode 100644 src/main/java/design/persistence/importexport/JSONHandler.java create mode 100644 src/main/java/design/persistence/importexport/XMLHandler.java (limited to 'src/main') diff --git a/src/main/java/design/controller/userinput/menus/ImportExportMenu.java b/src/main/java/design/controller/userinput/menus/ImportExportMenu.java index dbad0e3..dda465f 100644 --- a/src/main/java/design/controller/userinput/menus/ImportExportMenu.java +++ b/src/main/java/design/controller/userinput/menus/ImportExportMenu.java @@ -2,22 +2,18 @@ package design.controller.userinput.menus; import design.controller.userinput.Menu; import design.controller.userinput.MenuOption; -import design.persistence.JSONHandler; -import design.persistence.XMLHandler; +import design.persistence.*; +import design.persistence.importexport.DataHandler; +import design.persistence.importexport.DataSource; +import design.persistence.importexport.JSONHandler; +import design.persistence.importexport.XMLHandler; import java.io.File; import java.io.IOException; import java.util.List; -import java.util.Map; import java.util.Scanner; -import design.model.DataHandler; - public class ImportExportMenu extends Menu { - private static final Map handlers = Map.of( - "xml", new XMLHandler(), - "json", new JSONHandler() - ); @Override public String getTitle() { @@ -31,46 +27,50 @@ public class ImportExportMenu extends Menu { opts.add(new MenuOption("return to main menu", () -> new MainMenu().present())); - opts.add(new MenuOption("import league...", () -> promptForPath(true, false))); - opts.add(new MenuOption("export league...", () -> promptForPath(false, false))); - opts.add(new MenuOption("import personal profile...", () -> promptForPath(true, true))); - opts.add(new MenuOption("export personal profile...", () -> promptForPath(false, true))); + opts.add(new MenuOption("import leagues...", () -> promptForPath(true, false))); + opts.add(new MenuOption("export leagues...", () -> promptForPath(false, false))); + opts.add(new MenuOption("import profiles...", () -> promptForPath(true, true))); + opts.add(new MenuOption("export profiles...", () -> promptForPath(false, true))); return opts; } private void promptForPath(boolean isImporting, boolean isPersonalProfile) { - System.out.println("Enter file path: "); + System.out.print("Enter file path: "); Scanner sc = new Scanner(System.in); String filePath = sc.nextLine(); File file = new File(filePath); - String ext = getExtension(filePath); - DataHandler handler = handlers.get(ext); + DataSource source; + if (isPersonalProfile) { + source = PersonalDatabase.instance(); + } else { + source = LeagueDatabase.instance(); + } - if (handler == null) { - System.out.println("Unsupported file type: " + ext); - return; + DataHandler handler; + String ext = getExtension(filePath); + switch (ext) { + case "json" -> handler = new JSONHandler(source); + case "xml" -> handler = new XMLHandler(source); + default -> { + System.out.println("Unsupported file type: " + ext); + return; + } } try { if (isImporting) { - if (isPersonalProfile) - handler.importPersonalData(file); - else - handler.importLeagueData(file); + handler.importData(file); } else { - if (isPersonalProfile) - handler.exportPersonalData(file); - else - handler.exportLeagueData(file); + handler.exportData(file); } } catch (IOException e) { - System.err.println("I/O error: " + e.getMessage()); + throw new RuntimeException(e); } - new ImportExportMenu().present(); + this.present(); } private static String getExtension(String fileName) { diff --git a/src/main/java/design/controller/userinput/menus/MainMenu.java b/src/main/java/design/controller/userinput/menus/MainMenu.java index 7522ceb..9d5204f 100644 --- a/src/main/java/design/controller/userinput/menus/MainMenu.java +++ b/src/main/java/design/controller/userinput/menus/MainMenu.java @@ -19,7 +19,8 @@ public class MainMenu extends Menu { new MenuOption("manage courses...", () -> new ManageCourses().present()), new MenuOption("manage clubs...", () -> new ManageClubs().present()), new MenuOption("statistics...", () -> new StatisticsMenu().present()), - new MenuOption("log round...", () -> new HolePlayMenu().present()) + new MenuOption("log round...", () -> new HolePlayMenu().present()), + new MenuOption("manage data...", () -> new ImportExportMenu().present()) ); } } diff --git a/src/main/java/design/controller/userinput/menus/UserSettings.java b/src/main/java/design/controller/userinput/menus/UserSettings.java index 865b00d..47b0a5b 100644 --- a/src/main/java/design/controller/userinput/menus/UserSettings.java +++ b/src/main/java/design/controller/userinput/menus/UserSettings.java @@ -60,9 +60,6 @@ public class UserSettings extends Menu { this.present(); })); - opts.add(new MenuOption("manage data...", () -> new ImportExportMenu().present())); - - return opts; } } diff --git a/src/main/java/design/model/DataHandler.java b/src/main/java/design/model/DataHandler.java deleted file mode 100644 index e7dda33..0000000 --- a/src/main/java/design/model/DataHandler.java +++ /dev/null @@ -1,11 +0,0 @@ -package design.model; - -import java.io.File; -import java.io.IOException; - -public interface DataHandler { - void importPersonalData(File file) throws IOException; - void exportPersonalData(File file) throws IOException; - void importLeagueData(File file) throws IOException; - void exportLeagueData(File file) throws IOException; -} \ No newline at end of file diff --git a/src/main/java/design/persistence/JSONHandler.java b/src/main/java/design/persistence/JSONHandler.java deleted file mode 100644 index 77ec987..0000000 --- a/src/main/java/design/persistence/JSONHandler.java +++ /dev/null @@ -1,28 +0,0 @@ -package design.persistence; -import java.io.File; -import java.io.IOException; -import design.model.DataHandler; - -public class JSONHandler implements DataHandler -{ - - public void exportPersonalData(File file) throws IOException { - JSONPersonalDatabase.instance().exportData(file); - } - - public void importPersonalData(File file) throws IOException { - JSONPersonalDatabase.instance().importData(file); - } - - public void exportLeagueData(File file) throws IOException - { - JSONLeagueDatabase.instance().importData(file); - } - - public void importLeagueData(File file) throws IOException - { - JSONLeagueDatabase.instance().exportData(file); - } -} - - diff --git a/src/main/java/design/persistence/JSONLeagueDatabase.java b/src/main/java/design/persistence/JSONLeagueDatabase.java index edc649b..795c582 100644 --- a/src/main/java/design/persistence/JSONLeagueDatabase.java +++ b/src/main/java/design/persistence/JSONLeagueDatabase.java @@ -13,8 +13,6 @@ import design.model.League; import java.io.File; import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.StandardCopyOption; import java.util.Arrays; import java.util.HashMap; import java.util.Map; @@ -100,18 +98,19 @@ public class JSONLeagueDatabase implements LeagueDatabase { save(); } - public File exportData(File newFile) throws IOException{ - Files.copy(file.toPath(), newFile.toPath(), StandardCopyOption.REPLACE_EXISTING); - return newFile; - } - - public void importData(File newFile) throws IOException { - League[] newLeagues = mapper.readValue(newFile, League[].class); + @Override + public void importData(JsonNode tree) throws IOException { + League[] data = mapper.treeToValue(tree, League[].class); cache.clear(); - for (League l: newLeagues) { - cache.put(l.getId(), l); + for (League league : data) { + cache.put(league.getId(), league); } save(); } + @Override + public JsonNode exportData() { + Object[] data = cache.values().toArray(); + return mapper.valueToTree(data); + } } diff --git a/src/main/java/design/persistence/JSONPersonalDatabase.java b/src/main/java/design/persistence/JSONPersonalDatabase.java index 3fc5cab..3e70629 100644 --- a/src/main/java/design/persistence/JSONPersonalDatabase.java +++ b/src/main/java/design/persistence/JSONPersonalDatabase.java @@ -13,8 +13,6 @@ import design.model.League; import java.io.File; import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.StandardCopyOption; import java.util.HashMap; import java.util.Map; @@ -38,9 +36,6 @@ public class JSONPersonalDatabase implements PersonalDatabase { this.cache = new HashMap<>(); this.mapper = new ObjectMapper(); - // TODO: Once the saved JSON matches the model, consider removing. - // TEMP: tolerate unknown props while the model stabilizes - mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); SimpleModule module = new SimpleModule(); module.addDeserializer(Course.class, new Serializers.CourseIdDeserializer()); @@ -48,6 +43,7 @@ public class JSONPersonalDatabase implements PersonalDatabase { module.addSerializer(League.class, new Serializers.LeagueIDSerializer()); module.addDeserializer(League.class, new Serializers.LeagueIDDeserializer()); mapper.registerModule(module); + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY); mapper.registerModule(new ParameterNamesModule(JsonCreator.Mode.PROPERTIES)); mapper.registerModule(new JavaTimeModule()); @@ -101,18 +97,19 @@ public class JSONPersonalDatabase implements PersonalDatabase { save(); } - - public File exportData(File newFile) throws IOException{ - Files.copy(file.toPath(), newFile.toPath(), StandardCopyOption.REPLACE_EXISTING); - return newFile; - } - - public void importData(File newFile) throws IOException { - Golfer[] newGolfers = mapper.readValue(newFile, Golfer[].class); + @Override + public void importData(JsonNode tree) throws IOException { + Golfer[] data = mapper.treeToValue(tree, Golfer[].class); cache.clear(); - for (Golfer g : newGolfers) { - cache.put(g.getUsername(), g); + for (Golfer golfer : data) { + cache.put(golfer.getUsername(), golfer); } save(); } + + @Override + public JsonNode exportData() { + Object[] data = cache.values().toArray(); + return mapper.valueToTree(data); + } } diff --git a/src/main/java/design/persistence/LeagueDatabase.java b/src/main/java/design/persistence/LeagueDatabase.java index 953624d..9f835ff 100644 --- a/src/main/java/design/persistence/LeagueDatabase.java +++ b/src/main/java/design/persistence/LeagueDatabase.java @@ -1,10 +1,11 @@ package design.persistence; import design.model.League; +import design.persistence.importexport.DataSource; import java.io.IOException; -public interface LeagueDatabase { +public interface LeagueDatabase extends DataSource { static LeagueDatabase instance() { return JSONLeagueDatabase.instance(); } diff --git a/src/main/java/design/persistence/PersonalDatabase.java b/src/main/java/design/persistence/PersonalDatabase.java index 63f9182..77e43cc 100644 --- a/src/main/java/design/persistence/PersonalDatabase.java +++ b/src/main/java/design/persistence/PersonalDatabase.java @@ -1,10 +1,11 @@ package design.persistence; import design.model.Golfer; +import design.persistence.importexport.DataSource; + import java.io.IOException; -import java.io.File; -public interface PersonalDatabase { +public interface PersonalDatabase extends DataSource { static PersonalDatabase instance() { return JSONPersonalDatabase.instance(); diff --git a/src/main/java/design/persistence/XMLHandler.java b/src/main/java/design/persistence/XMLHandler.java deleted file mode 100644 index 706dabd..0000000 --- a/src/main/java/design/persistence/XMLHandler.java +++ /dev/null @@ -1,66 +0,0 @@ -package design.persistence; -import java.io.File; -import java.io.IOException; -import design.model.DataHandler; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.node.ObjectNode; - -import design.model.Golfer; -import com.fasterxml.jackson.dataformat.xml.XmlMapper; - - - -public class XMLHandler implements DataHandler -{ - private final ObjectMapper jsonMapper = new ObjectMapper(); - private final XmlMapper xmlMapper = new XmlMapper(); - - public void exportPersonalData(File file) throws IOException { - // get our json data just from the JSON database - File jsonData = JSONPersonalDatabase.instance().exportData(file); - - // read the the data from the JSON, as a JsonNode. - JsonNode golfersNode = jsonMapper.readTree(jsonData); - - // XML requires a parent node, we can't just throw the golfersnode into the xml or else it will only produce the first element - ObjectNode root = xmlMapper.createObjectNode(); - root.set("golfer", golfersNode); - - //write to the xml file. - xmlMapper.writerWithDefaultPrettyPrinter().writeValue(file, root); - } - - public void importPersonalData(File file) throws IOException { - - // read our root, the object node - JsonNode root = xmlMapper.readTree(file); - - // debug print line - System.out.println(root.toPrettyString()); - - // !!! here is where it's failing...our root is not serializable to an array of golfers. !!! - Golfer[] golfers = xmlMapper.treeToValue(root, Golfer[].class); - - // from here out should be good - File tempJson = File.createTempFile("imported", ".json"); - jsonMapper.writerWithDefaultPrettyPrinter().writeValue(tempJson, golfers); - JSONPersonalDatabase.instance().importData(tempJson); - tempJson.delete(); - } - - - - public void exportLeagueData(File file) throws IOException - { - // TO DO: exporting league data - } - - public void importLeagueData(File file) throws IOException - { - // TO DO: importing league data - } -} - - diff --git a/src/main/java/design/persistence/importexport/DataHandler.java b/src/main/java/design/persistence/importexport/DataHandler.java new file mode 100644 index 0000000..59df9be --- /dev/null +++ b/src/main/java/design/persistence/importexport/DataHandler.java @@ -0,0 +1,11 @@ +package design.persistence.importexport; + +import java.io.File; +import java.io.IOException; + +public interface DataHandler { + + void importData(File file) throws IOException; + + void exportData(File file) throws IOException; +} diff --git a/src/main/java/design/persistence/importexport/DataSource.java b/src/main/java/design/persistence/importexport/DataSource.java new file mode 100644 index 0000000..5290e33 --- /dev/null +++ b/src/main/java/design/persistence/importexport/DataSource.java @@ -0,0 +1,12 @@ +package design.persistence.importexport; + +import com.fasterxml.jackson.databind.JsonNode; + +import java.io.IOException; + +public interface DataSource { + + void importData(JsonNode tree) throws IOException; + + JsonNode exportData() throws IOException; +} \ No newline at end of file diff --git a/src/main/java/design/persistence/importexport/JSONHandler.java b/src/main/java/design/persistence/importexport/JSONHandler.java new file mode 100644 index 0000000..239eb6b --- /dev/null +++ b/src/main/java/design/persistence/importexport/JSONHandler.java @@ -0,0 +1,30 @@ +package design.persistence.importexport; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.json.JsonMapper; + +import java.io.File; +import java.io.IOException; + +public class JSONHandler implements DataHandler { + + private final DataSource dataSource; + private final JsonMapper jsonMapper = new JsonMapper(); + + public JSONHandler(DataSource dataSource) { + this.dataSource = dataSource; + } + + @Override + public void importData(File file) throws IOException { + JsonNode tree = jsonMapper.readTree(file); + dataSource.importData(tree); + } + + @Override + public void exportData(File file) throws IOException{ + JsonNode tree = dataSource.exportData(); + jsonMapper.writerWithDefaultPrettyPrinter().writeValue(file, tree); + } +} + + diff --git a/src/main/java/design/persistence/importexport/XMLHandler.java b/src/main/java/design/persistence/importexport/XMLHandler.java new file mode 100644 index 0000000..1a16b90 --- /dev/null +++ b/src/main/java/design/persistence/importexport/XMLHandler.java @@ -0,0 +1,34 @@ +package design.persistence.importexport; +import java.io.File; +import java.io.IOException; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.fasterxml.jackson.dataformat.xml.XmlMapper; + +public class XMLHandler implements DataHandler { + + private final DataSource dataSource; + private final XmlMapper xmlMapper = new XmlMapper(); + + public XMLHandler(DataSource dataSource) { + this.dataSource = dataSource; + } + + @Override + public void importData(File file) throws IOException { + JsonNode tree = xmlMapper.readTree(file); + JsonNode unwrapped = tree.get("items"); + dataSource.importData(unwrapped); + } + + @Override + public void exportData(File file) throws IOException { + JsonNode tree = dataSource.exportData(); + ObjectNode wrapper = xmlMapper.createObjectNode(); + wrapper.set("items", tree); + xmlMapper.writerWithDefaultPrettyPrinter().withRootName("export").writeValue(file, wrapper); + } +} + + -- cgit v1.2.3 From dd60732c456a6e0851f8b2f8e24600cc9eed77d0 Mon Sep 17 00:00:00 2001 From: WillemDalton Date: Fri, 14 Nov 2025 12:27:53 -0500 Subject: finished unit testing for teams and matches --- src/main/java/design/model/Golfer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/main') diff --git a/src/main/java/design/model/Golfer.java b/src/main/java/design/model/Golfer.java index 870b460..6ea9d32 100644 --- a/src/main/java/design/model/Golfer.java +++ b/src/main/java/design/model/Golfer.java @@ -160,5 +160,5 @@ public class Golfer implements Originator { this.clubs.addAll(gm.clubs); this.nextClubId = gm.nextClubId; - } + } } -- cgit v1.2.3 From d2b35ee84843dc74afce87c3fb8b7e5a53cd56a7 Mon Sep 17 00:00:00 2001 From: WillemDalton Date: Fri, 14 Nov 2025 13:15:12 -0500 Subject: finished testing most of JSON personal database --- src/main/java/design/persistence/JSONPersonalDatabase.java | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src/main') diff --git a/src/main/java/design/persistence/JSONPersonalDatabase.java b/src/main/java/design/persistence/JSONPersonalDatabase.java index 30c280a..ed83ef6 100644 --- a/src/main/java/design/persistence/JSONPersonalDatabase.java +++ b/src/main/java/design/persistence/JSONPersonalDatabase.java @@ -29,6 +29,11 @@ public class JSONPersonalDatabase implements PersonalDatabase { return INSTANCE; } + static JSONPersonalDatabase testInstance(String filename) { + INSTANCE = new JSONPersonalDatabase(filename); + return INSTANCE; + } + private final Map cache; private final ObjectMapper mapper; private final File file; -- cgit v1.2.3 From c052f5cb104ff5d4599161cf5fad95545c3be957 Mon Sep 17 00:00:00 2001 From: WillemDalton Date: Fri, 14 Nov 2025 13:36:42 -0500 Subject: progress on league database testing --- src/main/java/design/persistence/JSONLeagueDatabase.java | 6 ++++++ src/main/java/design/persistence/JSONPersonalDatabase.java | 1 + 2 files changed, 7 insertions(+) (limited to 'src/main') diff --git a/src/main/java/design/persistence/JSONLeagueDatabase.java b/src/main/java/design/persistence/JSONLeagueDatabase.java index 8a55065..42fa000 100644 --- a/src/main/java/design/persistence/JSONLeagueDatabase.java +++ b/src/main/java/design/persistence/JSONLeagueDatabase.java @@ -30,6 +30,12 @@ public class JSONLeagueDatabase implements LeagueDatabase { return INSTANCE; } + // static instance strictly for testing, to not add data to leaguedb.json + static JSONLeagueDatabase testInstance(String filename) { + INSTANCE = new JSONLeagueDatabase(filename); + return INSTANCE; + } + private final Map cache; private final ObjectMapper mapper; private final File file; diff --git a/src/main/java/design/persistence/JSONPersonalDatabase.java b/src/main/java/design/persistence/JSONPersonalDatabase.java index ed83ef6..7f55f78 100644 --- a/src/main/java/design/persistence/JSONPersonalDatabase.java +++ b/src/main/java/design/persistence/JSONPersonalDatabase.java @@ -29,6 +29,7 @@ public class JSONPersonalDatabase implements PersonalDatabase { return INSTANCE; } + // static instance strictly for testing, to not add data to personaldb.json static JSONPersonalDatabase testInstance(String filename) { INSTANCE = new JSONPersonalDatabase(filename); return INSTANCE; -- cgit v1.2.3 From 0c614ec078ea6d46b85d5032835cb98f9dc28c6c Mon Sep 17 00:00:00 2001 From: WillemDalton Date: Sat, 15 Nov 2025 14:21:14 -0500 Subject: finished work on unit testing for npw --- src/main/java/design/model/ScrambleLeague.java | 1 - 1 file changed, 1 deletion(-) (limited to 'src/main') diff --git a/src/main/java/design/model/ScrambleLeague.java b/src/main/java/design/model/ScrambleLeague.java index d372264..b0d65f8 100644 --- a/src/main/java/design/model/ScrambleLeague.java +++ b/src/main/java/design/model/ScrambleLeague.java @@ -4,7 +4,6 @@ import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonTypeName; import java.util.ArrayList; -import java.util.Arrays; import java.util.Date; import java.util.List; -- cgit v1.2.3 From 73cb1c77c99330360313bb07fcbc3c23a2516680 Mon Sep 17 00:00:00 2001 From: sowgro Date: Sat, 15 Nov 2025 23:27:40 -0500 Subject: fix nulls --- .../java/design/controller/userinput/menus/ImportExportMenu.java | 3 ++- src/main/java/design/persistence/JSONLeagueDatabase.java | 6 +++--- src/main/java/design/persistence/JSONPersonalDatabase.java | 6 +++--- 3 files changed, 8 insertions(+), 7 deletions(-) (limited to 'src/main') diff --git a/src/main/java/design/controller/userinput/menus/ImportExportMenu.java b/src/main/java/design/controller/userinput/menus/ImportExportMenu.java index dda465f..21ffa6c 100644 --- a/src/main/java/design/controller/userinput/menus/ImportExportMenu.java +++ b/src/main/java/design/controller/userinput/menus/ImportExportMenu.java @@ -56,6 +56,7 @@ public class ImportExportMenu extends Menu { case "xml" -> handler = new XMLHandler(source); default -> { System.out.println("Unsupported file type: " + ext); + this.present(); return; } } @@ -75,6 +76,6 @@ public class ImportExportMenu extends Menu { private static String getExtension(String fileName) { int i = fileName.lastIndexOf('.'); - return (i >= 0) ? fileName.substring(i + 1).toLowerCase() : ""; + return (i >= 0) ? fileName.substring(i + 1).toLowerCase() : "unknown"; } } diff --git a/src/main/java/design/persistence/JSONLeagueDatabase.java b/src/main/java/design/persistence/JSONLeagueDatabase.java index 795c582..81a4913 100644 --- a/src/main/java/design/persistence/JSONLeagueDatabase.java +++ b/src/main/java/design/persistence/JSONLeagueDatabase.java @@ -1,8 +1,6 @@ package design.persistence; -import com.fasterxml.jackson.annotation.JsonAutoDetect; -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.module.SimpleModule; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; @@ -15,6 +13,7 @@ import java.io.File; import java.io.IOException; import java.util.Arrays; import java.util.HashMap; +import java.util.List; import java.util.Map; public class JSONLeagueDatabase implements LeagueDatabase { @@ -48,6 +47,7 @@ public class JSONLeagueDatabase implements LeagueDatabase { mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY); mapper.registerModule(new ParameterNamesModule(JsonCreator.Mode.PROPERTIES)); mapper.registerModule(new JavaTimeModule()); + mapper.configOverride(List.class).setSetterInfo(JsonSetter.Value.forValueNulls(Nulls.AS_EMPTY)); try { load(); diff --git a/src/main/java/design/persistence/JSONPersonalDatabase.java b/src/main/java/design/persistence/JSONPersonalDatabase.java index 3e70629..a5a4795 100644 --- a/src/main/java/design/persistence/JSONPersonalDatabase.java +++ b/src/main/java/design/persistence/JSONPersonalDatabase.java @@ -1,8 +1,6 @@ package design.persistence; -import com.fasterxml.jackson.annotation.JsonAutoDetect; -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.module.SimpleModule; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; @@ -14,6 +12,7 @@ import design.model.League; import java.io.File; import java.io.IOException; import java.util.HashMap; +import java.util.List; import java.util.Map; public class JSONPersonalDatabase implements PersonalDatabase { @@ -47,6 +46,7 @@ public class JSONPersonalDatabase implements PersonalDatabase { mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY); mapper.registerModule(new ParameterNamesModule(JsonCreator.Mode.PROPERTIES)); mapper.registerModule(new JavaTimeModule()); + mapper.configOverride(List.class).setSetterInfo(JsonSetter.Value.forValueNulls(Nulls.AS_EMPTY)); try { load(); -- cgit v1.2.3 From 4ac38e80c2442e085c53986f5717d44f9d2d821a Mon Sep 17 00:00:00 2001 From: sowgro Date: Sun, 16 Nov 2025 00:22:00 -0500 Subject: fix datetime issue --- src/main/java/design/persistence/JSONLeagueDatabase.java | 4 +++- src/main/java/design/persistence/JSONPersonalDatabase.java | 4 +++- src/main/java/design/persistence/Serializers.java | 9 +++++++++ 3 files changed, 15 insertions(+), 2 deletions(-) (limited to 'src/main') diff --git a/src/main/java/design/persistence/JSONLeagueDatabase.java b/src/main/java/design/persistence/JSONLeagueDatabase.java index 81a4913..0891551 100644 --- a/src/main/java/design/persistence/JSONLeagueDatabase.java +++ b/src/main/java/design/persistence/JSONLeagueDatabase.java @@ -11,6 +11,7 @@ import design.model.League; import java.io.File; import java.io.IOException; +import java.time.LocalDateTime; import java.util.Arrays; import java.util.HashMap; import java.util.List; @@ -42,11 +43,12 @@ public class JSONLeagueDatabase implements LeagueDatabase { module.addSerializer(Course.class, new Serializers.CourseIdSerializer()); module.addDeserializer(Golfer.class, new Serializers.GolferUsernameDeserializer()); module.addSerializer(Golfer.class, new Serializers.GolferUsernameSerializer()); + module.addSerializer(LocalDateTime.class, new Serializers.DateTimeStringSerializer()); mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); - mapper.registerModule(module); mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY); mapper.registerModule(new ParameterNamesModule(JsonCreator.Mode.PROPERTIES)); mapper.registerModule(new JavaTimeModule()); + mapper.registerModule(module); mapper.configOverride(List.class).setSetterInfo(JsonSetter.Value.forValueNulls(Nulls.AS_EMPTY)); try { diff --git a/src/main/java/design/persistence/JSONPersonalDatabase.java b/src/main/java/design/persistence/JSONPersonalDatabase.java index a5a4795..bf0dda9 100644 --- a/src/main/java/design/persistence/JSONPersonalDatabase.java +++ b/src/main/java/design/persistence/JSONPersonalDatabase.java @@ -11,6 +11,7 @@ import design.model.League; import java.io.File; import java.io.IOException; +import java.time.LocalDateTime; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -41,11 +42,12 @@ public class JSONPersonalDatabase implements PersonalDatabase { module.addSerializer(Course.class, new Serializers.CourseIdSerializer()); module.addSerializer(League.class, new Serializers.LeagueIDSerializer()); module.addDeserializer(League.class, new Serializers.LeagueIDDeserializer()); - mapper.registerModule(module); + module.addSerializer(LocalDateTime.class, new Serializers.DateTimeStringSerializer()); mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY); mapper.registerModule(new ParameterNamesModule(JsonCreator.Mode.PROPERTIES)); mapper.registerModule(new JavaTimeModule()); + mapper.registerModule(module); mapper.configOverride(List.class).setSetterInfo(JsonSetter.Value.forValueNulls(Nulls.AS_EMPTY)); try { diff --git a/src/main/java/design/persistence/Serializers.java b/src/main/java/design/persistence/Serializers.java index 3940b44..2f2b208 100644 --- a/src/main/java/design/persistence/Serializers.java +++ b/src/main/java/design/persistence/Serializers.java @@ -8,11 +8,13 @@ import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; import design.model.Course; import design.model.Golfer; import design.model.League; import java.io.IOException; +import java.time.LocalDateTime; public class Serializers { public static class CustomPrettyPrinter extends DefaultPrettyPrinter { @@ -76,4 +78,11 @@ public class Serializers { return personalDB.getGolfer(username); } } + + public static class DateTimeStringSerializer extends JsonSerializer { + @Override + public void serialize(LocalDateTime value, JsonGenerator gen, SerializerProvider serializers) throws IOException { + gen.writeString(value.toString()); + } + } } -- cgit v1.2.3 From cf59d52cba70742f1d4098c38b4c7a798b3d89fa Mon Sep 17 00:00:00 2001 From: sowgro Date: Sun, 16 Nov 2025 01:56:27 -0500 Subject: IMPORT-EXPORT WORKING!!!!!!!!!!!!!!!!!!!!!!!!!! --- .../design/persistence/JSONLeagueDatabase.java | 45 ++++++++++----------- .../design/persistence/JSONPersonalDatabase.java | 46 +++++++++++----------- .../java/design/persistence/LeagueDatabase.java | 6 +++ .../java/design/persistence/PersonalDatabase.java | 6 +++ src/main/java/design/persistence/Serializers.java | 18 ++++++--- .../persistence/importexport/DataSource.java | 10 +++-- .../persistence/importexport/JSONHandler.java | 17 +++++--- .../persistence/importexport/XMLHandler.java | 22 ++++++----- 8 files changed, 102 insertions(+), 68 deletions(-) (limited to 'src/main') diff --git a/src/main/java/design/persistence/JSONLeagueDatabase.java b/src/main/java/design/persistence/JSONLeagueDatabase.java index 0891551..977e162 100644 --- a/src/main/java/design/persistence/JSONLeagueDatabase.java +++ b/src/main/java/design/persistence/JSONLeagueDatabase.java @@ -1,20 +1,15 @@ package design.persistence; -import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.module.SimpleModule; -import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; -import com.fasterxml.jackson.module.paramnames.ParameterNamesModule; import design.model.Course; import design.model.Golfer; import design.model.League; import java.io.File; import java.io.IOException; -import java.time.LocalDateTime; import java.util.Arrays; import java.util.HashMap; -import java.util.List; import java.util.Map; public class JSONLeagueDatabase implements LeagueDatabase { @@ -38,18 +33,8 @@ public class JSONLeagueDatabase implements LeagueDatabase { this.cache = new HashMap<>(); this.mapper = new ObjectMapper(); - SimpleModule module = new SimpleModule(); - module.addDeserializer(Course.class, new Serializers.CourseIdDeserializer()); - module.addSerializer(Course.class, new Serializers.CourseIdSerializer()); - module.addDeserializer(Golfer.class, new Serializers.GolferUsernameDeserializer()); - module.addSerializer(Golfer.class, new Serializers.GolferUsernameSerializer()); - module.addSerializer(LocalDateTime.class, new Serializers.DateTimeStringSerializer()); - mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); - mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY); - mapper.registerModule(new ParameterNamesModule(JsonCreator.Mode.PROPERTIES)); - mapper.registerModule(new JavaTimeModule()); - mapper.registerModule(module); - mapper.configOverride(List.class).setSetterInfo(JsonSetter.Value.forValueNulls(Nulls.AS_EMPTY)); + Serializers.configureMapper(mapper); + mapper.registerModule(this.getJacksonModule()); try { load(); @@ -101,8 +86,10 @@ public class JSONLeagueDatabase implements LeagueDatabase { } @Override - public void importData(JsonNode tree) throws IOException { - League[] data = mapper.treeToValue(tree, League[].class); + public void importData(Object rawData) throws IOException { + if (!(rawData instanceof League[] data)) { + throw new ClassCastException(); + } cache.clear(); for (League league : data) { cache.put(league.getId(), league); @@ -111,8 +98,22 @@ public class JSONLeagueDatabase implements LeagueDatabase { } @Override - public JsonNode exportData() { - Object[] data = cache.values().toArray(); - return mapper.valueToTree(data); + public League[] exportData() { + return getLeagues(); + } + + @Override + public SimpleModule getJacksonModule() { + SimpleModule module = new SimpleModule(); + module.addDeserializer(Course.class, new Serializers.CourseIdDeserializer()); + module.addSerializer(Course.class, new Serializers.CourseIdSerializer()); + module.addDeserializer(Golfer.class, new Serializers.GolferUsernameDeserializer()); + module.addSerializer(Golfer.class, new Serializers.GolferUsernameSerializer()); + return module; + } + + @Override + public Class getTargetClass() { + return League[].class; } } diff --git a/src/main/java/design/persistence/JSONPersonalDatabase.java b/src/main/java/design/persistence/JSONPersonalDatabase.java index bf0dda9..b92dddf 100644 --- a/src/main/java/design/persistence/JSONPersonalDatabase.java +++ b/src/main/java/design/persistence/JSONPersonalDatabase.java @@ -1,19 +1,14 @@ package design.persistence; -import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.module.SimpleModule; -import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; -import com.fasterxml.jackson.module.paramnames.ParameterNamesModule; import design.model.Course; import design.model.Golfer; import design.model.League; import java.io.File; import java.io.IOException; -import java.time.LocalDateTime; import java.util.HashMap; -import java.util.List; import java.util.Map; public class JSONPersonalDatabase implements PersonalDatabase { @@ -36,19 +31,8 @@ public class JSONPersonalDatabase implements PersonalDatabase { this.cache = new HashMap<>(); this.mapper = new ObjectMapper(); - - SimpleModule module = new SimpleModule(); - module.addDeserializer(Course.class, new Serializers.CourseIdDeserializer()); - module.addSerializer(Course.class, new Serializers.CourseIdSerializer()); - module.addSerializer(League.class, new Serializers.LeagueIDSerializer()); - module.addDeserializer(League.class, new Serializers.LeagueIDDeserializer()); - module.addSerializer(LocalDateTime.class, new Serializers.DateTimeStringSerializer()); - mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); - mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY); - mapper.registerModule(new ParameterNamesModule(JsonCreator.Mode.PROPERTIES)); - mapper.registerModule(new JavaTimeModule()); - mapper.registerModule(module); - mapper.configOverride(List.class).setSetterInfo(JsonSetter.Value.forValueNulls(Nulls.AS_EMPTY)); + Serializers.configureMapper(mapper); + mapper.registerModule(this.getJacksonModule()); try { load(); @@ -100,8 +84,10 @@ public class JSONPersonalDatabase implements PersonalDatabase { } @Override - public void importData(JsonNode tree) throws IOException { - Golfer[] data = mapper.treeToValue(tree, Golfer[].class); + public void importData(Object rawData) throws IOException { + if (!(rawData instanceof Golfer[] data)) { + throw new ClassCastException(); + } cache.clear(); for (Golfer golfer : data) { cache.put(golfer.getUsername(), golfer); @@ -110,8 +96,22 @@ public class JSONPersonalDatabase implements PersonalDatabase { } @Override - public JsonNode exportData() { - Object[] data = cache.values().toArray(); - return mapper.valueToTree(data); + public Golfer[] exportData() { + return getGolfers(); + } + + @Override + public SimpleModule getJacksonModule() { + SimpleModule module = new SimpleModule(); + module.addDeserializer(Course.class, new Serializers.CourseIdDeserializer()); + module.addSerializer(Course.class, new Serializers.CourseIdSerializer()); + module.addSerializer(League.class, new Serializers.LeagueIDSerializer()); + module.addDeserializer(League.class, new Serializers.LeagueIDDeserializer()); + return module; + } + + @Override + public Class getTargetClass() { + return Golfer[].class; } } diff --git a/src/main/java/design/persistence/LeagueDatabase.java b/src/main/java/design/persistence/LeagueDatabase.java index 9f835ff..ed6ddae 100644 --- a/src/main/java/design/persistence/LeagueDatabase.java +++ b/src/main/java/design/persistence/LeagueDatabase.java @@ -19,4 +19,10 @@ public interface LeagueDatabase extends DataSource { void removeLeague(League league) throws IOException; void updateLeague(League league) throws IOException; + + @Override + void importData(Object data) throws IOException; + + @Override + Object exportData() throws IOException; } diff --git a/src/main/java/design/persistence/PersonalDatabase.java b/src/main/java/design/persistence/PersonalDatabase.java index 77e43cc..70dd37d 100644 --- a/src/main/java/design/persistence/PersonalDatabase.java +++ b/src/main/java/design/persistence/PersonalDatabase.java @@ -20,4 +20,10 @@ public interface PersonalDatabase extends DataSource { void removeGolfer(Golfer golfer) throws IOException; void updateGolfer(Golfer golfer) throws IOException; + + @Override + void importData(Object data) throws IOException; + + @Override + Object exportData() throws IOException; } diff --git a/src/main/java/design/persistence/Serializers.java b/src/main/java/design/persistence/Serializers.java index 2f2b208..246dbf1 100644 --- a/src/main/java/design/persistence/Serializers.java +++ b/src/main/java/design/persistence/Serializers.java @@ -1,20 +1,20 @@ package design.persistence; +import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.util.DefaultIndenter; import com.fasterxml.jackson.core.util.DefaultPrettyPrinter; -import com.fasterxml.jackson.databind.DeserializationContext; -import com.fasterxml.jackson.databind.JsonDeserializer; -import com.fasterxml.jackson.databind.JsonSerializer; -import com.fasterxml.jackson.databind.SerializerProvider; -import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; +import com.fasterxml.jackson.databind.*; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import com.fasterxml.jackson.module.paramnames.ParameterNamesModule; import design.model.Course; import design.model.Golfer; import design.model.League; import java.io.IOException; import java.time.LocalDateTime; +import java.util.List; public class Serializers { public static class CustomPrettyPrinter extends DefaultPrettyPrinter { @@ -85,4 +85,12 @@ public class Serializers { gen.writeString(value.toString()); } } + + public static void configureMapper(ObjectMapper mapper) { + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY); + mapper.registerModule(new ParameterNamesModule(JsonCreator.Mode.PROPERTIES)); + mapper.registerModule(new JavaTimeModule()); + mapper.configOverride(List.class).setSetterInfo(JsonSetter.Value.forValueNulls(Nulls.AS_EMPTY)); + } } diff --git a/src/main/java/design/persistence/importexport/DataSource.java b/src/main/java/design/persistence/importexport/DataSource.java index 5290e33..e735c7e 100644 --- a/src/main/java/design/persistence/importexport/DataSource.java +++ b/src/main/java/design/persistence/importexport/DataSource.java @@ -1,12 +1,16 @@ package design.persistence.importexport; -import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.module.SimpleModule; import java.io.IOException; public interface DataSource { - void importData(JsonNode tree) throws IOException; + void importData(Object data) throws IOException; - JsonNode exportData() throws IOException; + Object exportData() throws IOException; + + SimpleModule getJacksonModule(); + + Class getTargetClass(); } \ No newline at end of file diff --git a/src/main/java/design/persistence/importexport/JSONHandler.java b/src/main/java/design/persistence/importexport/JSONHandler.java index 239eb6b..9c04281 100644 --- a/src/main/java/design/persistence/importexport/JSONHandler.java +++ b/src/main/java/design/persistence/importexport/JSONHandler.java @@ -1,6 +1,7 @@ package design.persistence.importexport; -import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.json.JsonMapper; +import design.persistence.Serializers; import java.io.File; import java.io.IOException; @@ -8,22 +9,26 @@ import java.io.IOException; public class JSONHandler implements DataHandler { private final DataSource dataSource; - private final JsonMapper jsonMapper = new JsonMapper(); + private final ObjectMapper jsonMapper = new JsonMapper(); public JSONHandler(DataSource dataSource) { this.dataSource = dataSource; + + Serializers.configureMapper(jsonMapper); + jsonMapper.registerModule(dataSource.getJacksonModule()); } @Override public void importData(File file) throws IOException { - JsonNode tree = jsonMapper.readTree(file); - dataSource.importData(tree); + Object data = jsonMapper.readValue(file, dataSource.getTargetClass()); + dataSource.importData(data); } @Override public void exportData(File file) throws IOException{ - JsonNode tree = dataSource.exportData(); - jsonMapper.writerWithDefaultPrettyPrinter().writeValue(file, tree); + Object data = dataSource.exportData(); + jsonMapper.writer(new Serializers.CustomPrettyPrinter()) + .writeValue(file, data); } } diff --git a/src/main/java/design/persistence/importexport/XMLHandler.java b/src/main/java/design/persistence/importexport/XMLHandler.java index 1a16b90..0a07d6e 100644 --- a/src/main/java/design/persistence/importexport/XMLHandler.java +++ b/src/main/java/design/persistence/importexport/XMLHandler.java @@ -1,10 +1,11 @@ package design.persistence.importexport; import java.io.File; import java.io.IOException; +import java.time.LocalDateTime; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.node.ObjectNode; +import com.fasterxml.jackson.databind.module.SimpleModule; import com.fasterxml.jackson.dataformat.xml.XmlMapper; +import design.persistence.Serializers; public class XMLHandler implements DataHandler { @@ -13,21 +14,24 @@ public class XMLHandler implements DataHandler { public XMLHandler(DataSource dataSource) { this.dataSource = dataSource; + + Serializers.configureMapper(xmlMapper); + SimpleModule module = dataSource.getJacksonModule(); + module.addSerializer(LocalDateTime.class, new Serializers.DateTimeStringSerializer()); + xmlMapper.registerModule(module); } @Override public void importData(File file) throws IOException { - JsonNode tree = xmlMapper.readTree(file); - JsonNode unwrapped = tree.get("items"); - dataSource.importData(unwrapped); + Object data = xmlMapper.readValue(file, dataSource.getTargetClass()); + dataSource.importData(data); } @Override public void exportData(File file) throws IOException { - JsonNode tree = dataSource.exportData(); - ObjectNode wrapper = xmlMapper.createObjectNode(); - wrapper.set("items", tree); - xmlMapper.writerWithDefaultPrettyPrinter().withRootName("export").writeValue(file, wrapper); + Object data = dataSource.exportData(); + xmlMapper.writerWithDefaultPrettyPrinter() + .writeValue(file, data); } } -- cgit v1.2.3 From b5d46c7701716bcb2dd6127aeb97f8fcdb7774fc Mon Sep 17 00:00:00 2001 From: sowgro Date: Sun, 16 Nov 2025 02:12:47 -0500 Subject: tweak main menu --- .../controller/userinput/menus/HistoryMenu.java | 30 +++++++++++++++++ .../controller/userinput/menus/MainMenu.java | 39 ++++++++-------------- 2 files changed, 43 insertions(+), 26 deletions(-) create mode 100644 src/main/java/design/controller/userinput/menus/HistoryMenu.java (limited to 'src/main') diff --git a/src/main/java/design/controller/userinput/menus/HistoryMenu.java b/src/main/java/design/controller/userinput/menus/HistoryMenu.java new file mode 100644 index 0000000..226b331 --- /dev/null +++ b/src/main/java/design/controller/userinput/menus/HistoryMenu.java @@ -0,0 +1,30 @@ +package design.controller.userinput.menus; + +import design.controller.userinput.Menu; +import design.controller.userinput.MenuOption; +import design.controller.userinput.UndoActions; + +import java.util.List; + +public class HistoryMenu extends Menu { + + @Override + public String getTitle() { + return "History"; + } + + @Override + public List getMenuOptions() { + return List.of( + new MenuOption("return to main menu", () -> new MainMenu().present()), + new MenuOption("undo", () -> { + UndoActions.undoWithSave(); + this.present(); + }), + new MenuOption("redo", () -> { + UndoActions.redoWithSave(); + this.present(); + }) + ); + } +} diff --git a/src/main/java/design/controller/userinput/menus/MainMenu.java b/src/main/java/design/controller/userinput/menus/MainMenu.java index 75ad88f..4331e56 100644 --- a/src/main/java/design/controller/userinput/menus/MainMenu.java +++ b/src/main/java/design/controller/userinput/menus/MainMenu.java @@ -2,7 +2,6 @@ package design.controller.userinput.menus; import design.controller.userinput.Menu; import design.controller.userinput.MenuOption; -import design.controller.userinput.UndoActions; import design.runtime.Session; import java.util.List; @@ -15,32 +14,20 @@ public class MainMenu extends Menu { @Override public List getMenuOptions() { - boolean guest = Session.isGuest(); - if (guest) { - return List.of( - new MenuOption("quit", () -> System.exit(0)), - new MenuOption("guest settings...", () -> new UserSettings().present()), - new MenuOption("browse courses...", () -> new SearchMenu().present()) - - ); + List options = new java.util.ArrayList<>(); + options.add(new MenuOption("quit", () -> System.exit(0))); + if (Session.isGuest()) { + options.add(new MenuOption("guest settings...", () -> new UserSettings().present())); + options.add(new MenuOption("browse courses...", () -> new SearchMenu().present())); } else { - return List.of( - new MenuOption("quit", () -> System.exit(0)), - new MenuOption("undo", () -> { - UndoActions.undoWithSave(); - this.present(); - }), - new MenuOption("redo", () -> { - UndoActions.redoWithSave(); - this.present(); - }), - new MenuOption("user settings...", () -> new UserSettings().present()), - new MenuOption("manage courses...", () -> new ManageCourses().present()), - new MenuOption("manage clubs...", () -> new ManageClubs().present()), - new MenuOption("statistics...", () -> new StatisticsMenu().present()), - new MenuOption("log round...", () -> new HolePlayMenu().present()), - new MenuOption("League play...", () -> new SelectLeague().present()) - ); + options.add(new MenuOption("manage history...", () -> new HistoryMenu().present())); + options.add(new MenuOption("user settings...", () -> new UserSettings().present())); + options.add(new MenuOption("manage courses...", () -> new ManageCourses().present())); + options.add(new MenuOption("manage clubs...", () -> new ManageClubs().present())); + options.add(new MenuOption("statistics...", () -> new StatisticsMenu().present())); + options.add(new MenuOption("log round...", () -> new HolePlayMenu().present())); + options.add(new MenuOption("league play...", () -> new SelectLeague().present())); } + return options; } } -- cgit v1.2.3