diff --git a/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/core/App.java b/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/core/App.java index defe620ce876081d95e6852dc0e453bc1a830285..cf24b4022bad5f2646f4f4d74e9e603875e18d1e 100644 --- a/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/core/App.java +++ b/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/core/App.java @@ -4,6 +4,7 @@ import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; +import java.io.InputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -77,8 +78,8 @@ public class App { private IDocumentPersistence<Collection<GeoLocations>, File> documentPersistence = new IDocumentPersistence<Collection<GeoLocations>, File>() { @Override - public Collection<GeoLocations> loadDocument(File documentLocation) throws Exception { - return geoLocationsLoader.loadLocations(new FileInputStream(documentLocation)); + public Collection<GeoLocations> loadDocument(InputStream inputStream) throws Exception { + return geoLocationsLoader.loadLocations(inputStream); } @Override @@ -106,20 +107,24 @@ public class App { return new ArrayList<GeoLocations>(); } - public Collection<GeoLocations> loadDocument(File documentLocation) throws Exception { - return documentPersistence.loadDocument(documentLocation); + protected InputStream toInputStream(File storage) throws IOException { + return new FileInputStream(storage); + } + + public Collection<GeoLocations> loadDocument(InputStream inputStream) throws Exception { + return documentPersistence.loadDocument(inputStream); } public void saveDocument(Collection<GeoLocations> document, File documentLocation) throws Exception { documentPersistence.saveDocument(document, documentLocation); } - public Collection<IDocumentImporter<File>> getDocumentImporters() { - return documentLoaders.stream().map(loader -> new IDocumentImporter<File>() { + public Collection<IDocumentImporter> getDocumentImporters() { + return documentLoaders.stream().map(loader -> new IDocumentImporter() { @Override - public void importDocument(File file) throws IOException { + public void importDocument(InputStream inputStream) throws IOException { try { - setDocumentAndLocation(loader.loadDocument(file), null); + setDocumentAndLocation(loader.loadDocument(inputStream), null); } catch (Exception e) { throw new IOException(e); } @@ -132,17 +137,17 @@ public class App { return documentStorage; } - private Collection<IDocumentLoader<Collection<GeoLocations>, File>> documentLoaders = Arrays.asList( - new IDocumentLoader<Collection<GeoLocations>, File>() { + private Collection<IDocumentLoader<Collection<GeoLocations>>> documentLoaders = Arrays.asList( + new IDocumentLoader<Collection<GeoLocations>>() { private GpxDocumentConverter gpxConverter = new GpxDocumentConverter(); @Override - public Collection<GeoLocations> loadDocument(File documentLocation) throws Exception { - return gpxConverter.loadDocument(documentLocation); + public Collection<GeoLocations> loadDocument(InputStream inputStream) throws Exception { + return gpxConverter.loadDocument(inputStream); } } ); - public Iterable<IDocumentLoader<Collection<GeoLocations>, File>> getDocumentLoaders() { + public Iterable<IDocumentLoader<Collection<GeoLocations>>> getDocumentLoaders() { return documentLoaders; } } diff --git a/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/doc/DocumentStorageImpl.java b/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/doc/DocumentStorageImpl.java index 6a104a6bd96db82210a2bbad3a8fd39625bd10ca..f8aee013f0aa7b15ec16aefc37cac9754fb82f7e 100644 --- a/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/doc/DocumentStorageImpl.java +++ b/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/doc/DocumentStorageImpl.java @@ -1,6 +1,7 @@ package tdt4140.gr1800.app.doc; import java.io.IOException; +import java.io.InputStream; import java.util.ArrayList; import java.util.Collection; @@ -60,11 +61,13 @@ public abstract class DocumentStorageImpl<D, L> implements IDocumentStorage<L>, public void newDocument() { setDocumentAndLocation(createDocument(), null); } + + protected abstract InputStream toInputStream(L storage) throws IOException; @Override public void openDocument(L storage) throws IOException { try { - setDocumentAndLocation(loadDocument(storage), storage); + setDocumentAndLocation(loadDocument(toInputStream(storage)), storage); } catch (Exception e) { throw new IOException(e); } diff --git a/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/doc/IDocumentImporter.java b/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/doc/IDocumentImporter.java index ba8b8ec2aa68702c1400a09032ab41c6f6140b23..2b9327b74773afe7409a67f0048ca17a7820aa7f 100644 --- a/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/doc/IDocumentImporter.java +++ b/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/doc/IDocumentImporter.java @@ -1,7 +1,8 @@ package tdt4140.gr1800.app.doc; import java.io.IOException; +import java.io.InputStream; -public interface IDocumentImporter<L> { - public void importDocument(L documentLocation) throws IOException; +public interface IDocumentImporter { + public void importDocument(InputStream inputStream) throws IOException; } diff --git a/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/doc/IDocumentLoader.java b/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/doc/IDocumentLoader.java index ecb029b5d7668f17d9024a2599c94d70475689f8..8c719fe9720e03adc8ca65d2555f2babc07e66db 100644 --- a/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/doc/IDocumentLoader.java +++ b/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/doc/IDocumentLoader.java @@ -1,5 +1,7 @@ package tdt4140.gr1800.app.doc; -public interface IDocumentLoader<D, L> { - public D loadDocument(L documentLocation) throws Exception; +import java.io.InputStream; + +public interface IDocumentLoader<D> { + public D loadDocument(InputStream inputStream) throws Exception; } diff --git a/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/doc/IDocumentPersistence.java b/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/doc/IDocumentPersistence.java index 9fbd23a7f7d04405e7b678fc7ab2ce448c46f9f8..0da1f8d2939a5fc079d0ade8f3b392e9b338fb71 100644 --- a/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/doc/IDocumentPersistence.java +++ b/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/doc/IDocumentPersistence.java @@ -1,4 +1,4 @@ package tdt4140.gr1800.app.doc; -public interface IDocumentPersistence<D, L> extends IDocumentLoader<D, L>, IDocumentSaver<D, L> { +public interface IDocumentPersistence<D, L> extends IDocumentLoader<D>, IDocumentSaver<D, L> { } diff --git a/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/doc/IDocumentStorage.java b/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/doc/IDocumentStorage.java index a037c42a38494ed0736c191f44a40f0e1dd03661..1f30c37808e5eaaab146f93a2d931af16683b03a 100644 --- a/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/doc/IDocumentStorage.java +++ b/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/doc/IDocumentStorage.java @@ -14,5 +14,5 @@ public interface IDocumentStorage<L> { public void openDocument(L documentLocation) throws IOException; public void saveDocument() throws IOException; - public Collection<IDocumentImporter<L>> getDocumentImporters(); + public Collection<IDocumentImporter> getDocumentImporters(); } diff --git a/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/gpx/GpxDocumentConverter.java b/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/gpx/GpxDocumentConverter.java index 7324eb5c112618c1ebbc5413155c696d727b8858..7c1f2d915f5f77cbc5a0f77899fc735a432d6bcc 100644 --- a/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/gpx/GpxDocumentConverter.java +++ b/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/gpx/GpxDocumentConverter.java @@ -1,6 +1,6 @@ package tdt4140.gr1800.app.gpx; -import java.io.File; +import java.io.InputStream; import java.util.ArrayList; import java.util.Collection; import java.util.stream.Collectors; @@ -14,13 +14,13 @@ import tdt4140.gr1800.app.core.GeoLocations; import tdt4140.gr1800.app.core.LatLong; import tdt4140.gr1800.app.doc.IDocumentLoader; -public class GpxDocumentConverter implements IDocumentLoader<Collection<GeoLocations>, File> { +public class GpxDocumentConverter implements IDocumentLoader<Collection<GeoLocations>> { private GpxDocumentLoader gpxLoader = new GpxDocumentLoader(); @Override - public Collection<GeoLocations> loadDocument(File documentLocation) throws Exception { - GPX gpx = gpxLoader.loadDocument(documentLocation.toURI().toURL()); + public Collection<GeoLocations> loadDocument(InputStream inputStream) throws Exception { + GPX gpx = gpxLoader.loadDocument(inputStream); return convert(gpx); } diff --git a/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/gpx/GpxDocumentLoader.java b/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/gpx/GpxDocumentLoader.java index b7dcb43a46239d18a34e3b1dce828ce2a803d0b0..0f520d3f17ae9dc235f72c89cb1f564a2454ec6c 100644 --- a/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/gpx/GpxDocumentLoader.java +++ b/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/gpx/GpxDocumentLoader.java @@ -1,19 +1,14 @@ package tdt4140.gr1800.app.gpx; import java.io.InputStream; -import java.net.URL; import io.jenetics.jpx.GPX; import tdt4140.gr1800.app.doc.IDocumentLoader; -public class GpxDocumentLoader implements IDocumentLoader<GPX, URL> { - - public GPX loadDocument(InputStream inputStream) throws Exception { - return GPX.read(inputStream, true); - } +public class GpxDocumentLoader implements IDocumentLoader<GPX> { @Override - public GPX loadDocument(URL documentLocation) throws Exception { - return loadDocument(documentLocation.openStream()); + public GPX loadDocument(InputStream inputStream) throws Exception { + return GPX.read(inputStream, true); } } diff --git a/tdt4140-gr1800/app.core/src/test/java/tdt4140/gr1800/app/core/GeoLocationsPersistenceTest.java b/tdt4140-gr1800/app.core/src/test/java/tdt4140/gr1800/app/core/GeoLocationsPersistenceTest.java index 73a426f00181d39a7dca1c71e00d64e50d0d89c6..7f2fc277192000846ea1eead52fba3e5653b74d0 100644 --- a/tdt4140-gr1800/app.core/src/test/java/tdt4140/gr1800/app/core/GeoLocationsPersistenceTest.java +++ b/tdt4140-gr1800/app.core/src/test/java/tdt4140/gr1800/app/core/GeoLocationsPersistenceTest.java @@ -2,7 +2,6 @@ package tdt4140.gr1800.app.core; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; -import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Iterator; diff --git a/tdt4140-gr1800/app.core/src/test/java/tdt4140/gr1800/app/core/GpxPersistenceTest.java b/tdt4140-gr1800/app.core/src/test/java/tdt4140/gr1800/app/core/GpxPersistenceTest.java index 2850cc91b0733bb934bb7541809a4ad34d507b66..67a6fb87b40eec0f9e4cbba8b98875a593492a59 100644 --- a/tdt4140-gr1800/app.core/src/test/java/tdt4140/gr1800/app/core/GpxPersistenceTest.java +++ b/tdt4140-gr1800/app.core/src/test/java/tdt4140/gr1800/app/core/GpxPersistenceTest.java @@ -25,7 +25,7 @@ public class GpxPersistenceTest { @Test public void testLoadDocument() { try { - GPX gpx = loader.loadDocument(getClass().getResource("sample1.gpx")); + GPX gpx = loader.loadDocument(getClass().getResourceAsStream("sample1.gpx")); Assert.assertEquals(1, gpx.getTracks().size()); Assert.assertEquals(1, gpx.getTracks().get(0).getSegments().size()); Assert.assertEquals(3, gpx.getTracks().get(0).getSegments().get(0).getPoints().size()); @@ -37,7 +37,7 @@ public class GpxPersistenceTest { @Test public void testConvertSample1() { try { - GPX gpx = loader.loadDocument(getClass().getResource("sample1.gpx")); + GPX gpx = loader.loadDocument(getClass().getResourceAsStream("sample1.gpx")); Collection<GeoLocations> geoLocations = converter.convert(gpx); Assert.assertEquals(1, geoLocations.size()); GeoLocations track = geoLocations.iterator().next(); @@ -53,7 +53,7 @@ public class GpxPersistenceTest { @Test public void testConvertAchterbroekRoute() { try { - GPX gpx = loader.loadDocument(getClass().getResource("Achterbroek-route.gpx")); + GPX gpx = loader.loadDocument(getClass().getResourceAsStream("Achterbroek-route.gpx")); Collection<GeoLocations> geoLocations = converter.convert(gpx); Assert.assertEquals(2, geoLocations.size()); Iterator<GeoLocations> iterator = geoLocations.iterator(); @@ -74,7 +74,7 @@ public class GpxPersistenceTest { @Test public void testConvertAchterbroekTrack() { try { - GPX gpx = loader.loadDocument(getClass().getResource("Achterbroek-track.gpx")); + GPX gpx = loader.loadDocument(getClass().getResourceAsStream("Achterbroek-track.gpx")); Collection<GeoLocations> geoLocations = converter.convert(gpx); Assert.assertEquals(2, geoLocations.size()); Iterator<GeoLocations> iterator = geoLocations.iterator(); diff --git a/tdt4140-gr1800/app.ui/src/main/java/tdt4140/gr1800/app/ui/FileMenuController.java b/tdt4140-gr1800/app.ui/src/main/java/tdt4140/gr1800/app/ui/FileMenuController.java index 9eb8409bd6d79ea7f9a9eba6c405d788f60864fb..d3e590495be7d4f0330bba1391f8f79242e004a9 100644 --- a/tdt4140-gr1800/app.ui/src/main/java/tdt4140/gr1800/app/ui/FileMenuController.java +++ b/tdt4140-gr1800/app.ui/src/main/java/tdt4140/gr1800/app/ui/FileMenuController.java @@ -1,14 +1,19 @@ package tdt4140.gr1800.app.ui; import java.io.File; +import java.io.FileInputStream; import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; import java.util.ArrayList; import java.util.List; +import java.util.Optional; import javafx.event.ActionEvent; import javafx.fxml.FXML; import javafx.scene.control.Menu; import javafx.scene.control.MenuItem; +import javafx.scene.control.TextInputDialog; import javafx.stage.FileChooser; import tdt4140.gr1800.app.doc.IDocumentImporter; import tdt4140.gr1800.app.doc.IDocumentStorage; @@ -130,22 +135,65 @@ public class FileMenuController { } @FXML - public void handleImportAction() { + public void handleFileImportAction() { FileChooser fileChooser = getFileChooser(); File selection = fileChooser.showOpenDialog(null); // String path = selection.getPath(); // int pos = path.lastIndexOf('.'); // String ext = (pos > 0 ? path.substring(pos + 1) : null); - handleImportAction(selection); + handleFileImportAction(selection); } - void handleImportAction(File selection) { - for (IDocumentImporter<File> importer : documentStorage.getDocumentImporters()) { + void handleFileImportAction(File selection) { + for (IDocumentImporter importer : documentStorage.getDocumentImporters()) { try { - importer.importDocument(selection); + importer.importDocument(new FileInputStream(selection)); break; } catch (Exception e) { } } } + + private TextInputDialog inputDialog; + + @FXML + public void handleURLImportAction() { + if (inputDialog == null) { + inputDialog = new TextInputDialog(); + } + inputDialog.setTitle("Import from URL"); + inputDialog.setHeaderText("Enter URL to import from"); + inputDialog.setContentText("Enter URL: "); + // https://developer.garmin.com/downloads/connect-api/sample_file.gpx + URL url = null; + while (url == null) { + Optional<String> result = inputDialog.showAndWait(); + if (! result.isPresent()) { + return; + } + try { + url = new URL(result.get()); + if (handleURLImportAction(url)) { + return; + } + url = null; + inputDialog.setHeaderText("Problems reading it..."); + inputDialog.setContentText("Enter another URL: "); + } catch (MalformedURLException e1) { + inputDialog.setContentText("Enter a valid URL: "); + } + } + } + + boolean handleURLImportAction(URL url) { + for (IDocumentImporter importer : documentStorage.getDocumentImporters()) { + try { + importer.importDocument(url.openStream()); + return true; + } catch (Exception e) { + System.err.println(e.getMessage()); + } + } + return false; + } } diff --git a/tdt4140-gr1800/app.ui/src/main/resources/tdt4140/gr1800/app/ui/FileMenu.fxml b/tdt4140-gr1800/app.ui/src/main/resources/tdt4140/gr1800/app/ui/FileMenu.fxml index 5de3493684996e64d7318ffeb16707366da68b04..a9c97faf32a2f7546dabf083e35cd568b6076a53 100644 --- a/tdt4140-gr1800/app.ui/src/main/resources/tdt4140/gr1800/app/ui/FileMenu.fxml +++ b/tdt4140-gr1800/app.ui/src/main/resources/tdt4140/gr1800/app/ui/FileMenu.fxml @@ -15,6 +15,9 @@ <MenuItem text="Save As..." onAction="#handleSaveAsAction"/> <MenuItem text="Save Copy As..." onAction="#handleSaveCopyAsAction"/> <SeparatorMenuItem/> - <MenuItem text="Import..." onAction="#handleImportAction"/> + <Menu text="Import"> + <MenuItem text="File..." onAction="#handleFileImportAction"/> + <MenuItem text="URL..." onAction="#handleURLImportAction"/> + </Menu> </items> </Menu>