diff options
18 files changed, 167 insertions, 306 deletions
diff --git a/data/personaldb.json b/data/personaldb.json index 10dd8bb..4e42e0d 100644 --- a/data/personaldb.json +++ b/data/personaldb.json @@ -101,12 +101,12 @@ } ], "currentHoleIndex": 2, + "totalSwings": 5, + "totalDistance": 1108.0, "currentHole": { "number": 3, "par": 4 - }, - "totalSwings": 5, - "totalDistance": 1108.0 + } }, { "course": 1, @@ -137,12 +137,12 @@ } ], "currentHoleIndex": 9, + "totalSwings": 1, + "totalDistance": 204.0, "currentHole": { "number": 10, "par": 3 - }, - "totalSwings": 1, - "totalDistance": 204.0 + } } ], "invites": [] @@ -150,9 +150,9 @@ { "clubs": [], "nextClubId": 1, - "username": "GUYHERE2", - "passwordHash": 3556498, - "fullName": "GUYHERE2", + "username": "sowgro", + "passwordHash": -896456343, + "fullName": "sowgro", "courses": [], "rounds": [], "invites": [] 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<String, DataHandler> 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); + } +} + + @@ -17,7 +17,7 @@ "fullName": "GUYHERE", "courses": [], "rounds": [], - "invites" : [] + "invites": [] }, { "clubs": [], @@ -111,8 +111,8 @@ } ], "currentHoleIndex": 2, - "totalDistance": 1108.0, "totalSwings": 5, + "totalDistance": 1108.0, "currentHole": { "number": 3, "par": 4 @@ -147,8 +147,8 @@ } ], "currentHoleIndex": 9, - "totalDistance": 204.0, "totalSwings": 1, + "totalDistance": 204.0, "currentHole": { "number": 10, "par": 3 @@ -156,5 +156,15 @@ } ], "invites": [] + }, + { + "clubs": [], + "nextClubId": 1, + "username": "sowgro", + "passwordHash": -896456343, + "fullName": "sowgro", + "courses": [], + "rounds": [], + "invites": [] } ]
\ No newline at end of file diff --git a/test.xml b/test.xml deleted file mode 100644 index df8f0c6..0000000 --- a/test.xml +++ /dev/null @@ -1,6 +0,0 @@ -<ArrayNode> - <nextClubId>1</nextClubId> - <username>test</username> - <passwordHash>3556498</passwordHash> - <fullName>test</fullName> -</ArrayNode> diff --git a/test2.xml b/test2.xml deleted file mode 100644 index 74e2c6a..0000000 --- a/test2.xml +++ /dev/null @@ -1,121 +0,0 @@ -<ObjectNode> - <golfer> - <nextClubId>1</nextClubId> - <username>test</username> - <passwordHash>3556498</passwordHash> - <fullName>test</fullName> - </golfer> - <golfer> - <nextClubId>1</nextClubId> - <username>GUYHERE</username> - <passwordHash>3556498</passwordHash> - <fullName>GUYHERE</fullName> - </golfer> - <golfer> - <clubs> - <id>1</id> - <manufacture>Bobby</manufacture> - <nickname>swen 261</nickname> - <clubType>DRIVER</clubType> - </clubs> - <clubs> - <id>2</id> - <manufacture>Bobby</manufacture> - <nickname>swen 262</nickname> - <clubType>PUTTER</clubType> - </clubs> - <clubs> - <id>3</id> - <manufacture>sowclub</manufacture> - <nickname>man</nickname> - <clubType>WOOD</clubType> - </clubs> - <nextClubId>4</nextClubId> - <username>john_doe</username> - <passwordHash>46792755</passwordHash> - <fullName>John Doe</fullName> - <courses>2</courses> - <courses>1</courses> - <rounds> - <course>1</course> - <dateTime>2025</dateTime> - <dateTime>10</dateTime> - <dateTime>7</dateTime> - <dateTime>13</dateTime> - <dateTime>54</dateTime> - <dateTime>37</dateTime> - <dateTime>429963500</dateTime> - <startingHole> - <number>1</number> - <par>5</par> - </startingHole> - <plays> - <holeNumber>1</holeNumber> - <swings> - <distance>100</distance> - <clubUsed>1</clubUsed> - </swings> - <swings> - <distance>5</distance> - <clubUsed>2</clubUsed> - </swings> - <swings> - <distance>1</distance> - <clubUsed>2</clubUsed> - </swings> - <swingCount>3</swingCount> - <distance>106</distance> - </plays> - <plays> - <holeNumber>2</holeNumber> - <swings> - <distance>1000</distance> - <clubUsed>1</clubUsed> - </swings> - <swings> - <distance>2</distance> - <clubUsed>1</clubUsed> - </swings> - <swingCount>2</swingCount> - <distance>1002</distance> - </plays> - <currentHoleIndex>2</currentHoleIndex> - <totalDistance>1108.0</totalDistance> - <currentHole> - <number>3</number> - <par>4</par> - </currentHole> - <totalSwings>5</totalSwings> - </rounds> - <rounds> - <course>1</course> - <dateTime>2025</dateTime> - <dateTime>10</dateTime> - <dateTime>8</dateTime> - <dateTime>20</dateTime> - <dateTime>19</dateTime> - <dateTime>38</dateTime> - <dateTime>968996400</dateTime> - <startingHole> - <number>9</number> - <par>3</par> - </startingHole> - <plays> - <holeNumber>9</holeNumber> - <swings> - <distance>204</distance> - <clubUsed>1</clubUsed> - </swings> - <swingCount>1</swingCount> - <distance>204</distance> - </plays> - <currentHoleIndex>9</currentHoleIndex> - <totalDistance>204.0</totalDistance> - <currentHole> - <number>10</number> - <par>3</par> - </currentHole> - <totalSwings>1</totalSwings> - </rounds> - </golfer> -</ObjectNode> |
