diff --git a/simpleexample/README.md b/simpleexample/README.md new file mode 100644 index 0000000000000000000000000000000000000000..ee1f95d1436f69965461df3d91b63fe99e7384d6 --- /dev/null +++ b/simpleexample/README.md @@ -0,0 +1,34 @@ +# Simpleexample + +Dette prosjektet er et eksempel på en nokså minimalistisk trelagsapplikasjon, altså med et domenelag, brukergrensesnitt (UI) og persistens (lagring). Prosjektet inneholder tester for alle lagene, med rimelig god dekningsgrad. Prosjektet er konfigurert med gradle som byggesystem. + +## Organisering av koden + +Prosjektet er organisert med 2 * 2 = 4 kildekodemapper, kode og ressurser for henholdsvis applikasjonen selv og testene: + +- **src/main/java** for koden til applikasjonen +- **src/main/resources** for tilhørende ressurser, f.eks. data-filer og FXML-filer, som brukes av applikasjonen. +- **src/test/java** for testkoden +- **src/test/resources** for tilhørende ressurser, f.eks. data-filer og FXML-filer, som brukes av testene. + +Dette er en vanlig organisering for prosjekter som bygges med gradle (og maven). + +## Domenelaget + +Domenelaget inneholder alle klasser og logikk knyttet til dataene som applikasjonen handler om og håndterer. Dette laget skal være helt uavhengig av brukergrensesnittet eller lagingsteknikken som brukes. + +Vår app handler om samlinger av såkalte geo-lokasjoner, altså steder identifisert med lengde- og breddegrader. Domenelaget inneholder klasser for å representere og håndtere slike, og disse finnes i **[simpleex.core](src/main/java/simpleex/core/README.md)**-pakken. + +## Brukergrensesnittlaget + +Brukergrensesnittlaget inneholder alle klasser og logikk knyttet til visning og handlinger på dataene i domenelaget. Brukergrensesnittet til vår app viser frem en liste av geo-lokasjoner, den som velges vises på et kart. En flytte og legge til geo-lokasjoner. Samlingen med geo-lokasjoner kan lagres og evt. leses inn igjen. + +Brukergrensesnittet er laget med JavaFX og FXML og finnes i **[simpleex.ui](src/main/java/simpleex/ui/README.md)**-pakken (JavaFX-koden i **src/main/java** og FXML-filen i **src/main/resources**) + +## Persistenslaget + +Persistenslaget inneholder alle klasser og logikk for lagring (skriving og lesing) av dataene i domenelaget. Vårt persistenslag implementerer fillagring med JSON-syntaks. + +Persistenslaget finnes i **[simpleex.json](src/main/java/simpleex/json/README.md)**-pakken. + +## Bygging med gradle diff --git a/simpleexample/src/main/java/simpleex/core/README.md b/simpleexample/src/main/java/simpleex/core/README.md index 834b0e8c9b764b22b851ef9d201a5c6d5bcec881..c49c61ac1b36d020f77a4836e7eee24ecfe35a91 100644 --- a/simpleexample/src/main/java/simpleex/core/README.md +++ b/simpleexample/src/main/java/simpleex/core/README.md @@ -1 +1,15 @@ -# Source package for core code \ No newline at end of file +# Kildekode for domenelaget + +Domenelaget utgjøres av en samling av geo-lokasjoner representert vha. to klasse: + +- LatLong - en geo-lokasjon, representert vha. lengde og breddegrad +- LatLongs - en samling LatLong-objekter + +```plantuml +class LatLong { + double latitude + double longitude +} +class LatLongs +LatLongs *--> "*" LatLong: "latLongs" +``` diff --git a/simpleexample/src/main/java/simpleex/json/JacksonConfigurator.java b/simpleexample/src/main/java/simpleex/json/JacksonConfigurator.java new file mode 100644 index 0000000000000000000000000000000000000000..8d4fe46aca8b05b99d08316e01a55e11fff8f5d0 --- /dev/null +++ b/simpleexample/src/main/java/simpleex/json/JacksonConfigurator.java @@ -0,0 +1,33 @@ +package simpleex.json; + +import com.fasterxml.jackson.databind.Module; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.module.SimpleModule; +import simpleex.core.LatLong; +import simpleex.core.LatLongs; + +public class JacksonConfigurator { + + public ObjectMapper createObjectMapper() { + final ObjectMapper objectMapper = new ObjectMapper(); + configureObjectMapper(objectMapper); + return objectMapper; + } + + public void configureObjectMapper(final ObjectMapper objectMapper) { + objectMapper.registerModule(createModule()); + } + + public Module createModule() { + final SimpleModule module = new SimpleModule(); + configureModule(module); + return module; + } + + public void configureModule(final SimpleModule module) { + module.addSerializer(LatLong.class, new LatLongSerializer()); + module.addSerializer(LatLongs.class, new LatLongsSerializer()); + module.addDeserializer(LatLong.class, new LatLongDeserializer()); + module.addDeserializer(LatLongs.class, new LatLongsDeserializer()); + } +} diff --git a/simpleexample/src/main/java/simpleex/json/README.md b/simpleexample/src/main/java/simpleex/json/README.md index eb7378f5a08b201e32c2acac522d060cdc3df28c..b3e4cbd394cf1c76f71403db172e3404cd96ed06 100644 --- a/simpleexample/src/main/java/simpleex/json/README.md +++ b/simpleexample/src/main/java/simpleex/json/README.md @@ -1 +1,5 @@ -# Resources used by the web server code \ No newline at end of file +# Kildekode for persistenslaget + +Persistenslaget bruker [Jackson-biblioteket](https://github.com/FasterXML/jackson) for å serialisere objekter til [JSON](https://www.json.org). + +For hver [domeneklasse](../core/README.md) finnes tilsvarende klasser for serialisering (konvertering av domeneobjekter til tekststrøm) og deserialisering (parsing av tekststrøm og opprettelse av tilsvarende domeneobjekter). I tillegg finnes det en klasse, **JacksonConfigurator**, som inneholder diverse metoder for å lage og konfigurere **ObjectMapper**- og **SimpleModule**-objektene som trengs for å serialisere og deserialisere objekter. diff --git a/simpleexample/src/main/java/simpleex/ui/FxAppController.java b/simpleexample/src/main/java/simpleex/ui/FxAppController.java index 1795682f192c923fce6376358cd19cb195da7a7b..366cbef37f4c918643d3fb05bce9132ca774d453 100644 --- a/simpleexample/src/main/java/simpleex/ui/FxAppController.java +++ b/simpleexample/src/main/java/simpleex/ui/FxAppController.java @@ -1,7 +1,6 @@ package simpleex.ui; import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.module.SimpleModule; import fxmapcontrol.Location; import fxmapcontrol.MapBase; import fxmapcontrol.MapItemsControl; @@ -27,10 +26,7 @@ import javafx.scene.control.Slider; import javafx.stage.FileChooser; import simpleex.core.LatLong; import simpleex.core.LatLongs; -import simpleex.json.LatLongDeserializer; -import simpleex.json.LatLongSerializer; -import simpleex.json.LatLongsDeserializer; -import simpleex.json.LatLongsSerializer; +import simpleex.json.JacksonConfigurator; public class FxAppController { @@ -193,13 +189,7 @@ public class FxAppController { public ObjectMapper getObjectMapper() { if (objectMapper == null) { - final SimpleModule module = new SimpleModule(); - module.addSerializer(LatLong.class, new LatLongSerializer()); - module.addSerializer(LatLongs.class, new LatLongsSerializer()); - module.addDeserializer(LatLong.class, new LatLongDeserializer()); - module.addDeserializer(LatLongs.class, new LatLongsDeserializer()); - objectMapper = new ObjectMapper(); - objectMapper.registerModule(module); + objectMapper = new JacksonConfigurator().createObjectMapper(); } return objectMapper; } diff --git a/simpleexample/src/main/java/simpleex/ui/README.md b/simpleexample/src/main/java/simpleex/ui/README.md index 9b8ca7943de735a79f4661ae89a93f8aac366bc6..4351884fdc28b99a12d5f8479e581c4aeecbbf8c 100644 --- a/simpleexample/src/main/java/simpleex/ui/README.md +++ b/simpleexample/src/main/java/simpleex/ui/README.md @@ -1 +1,9 @@ -# The UI source code, a minimal JavaFX/FXML UI \ No newline at end of file +# Kildekode for brukergrensesnittet + +Brukergrensesnittet er laget med JavaFX og FXML. + +Brukergrensesnittet er enkelt og består av en liste og et kart. Lista viser innholdet i et **LatLongs**-objekt, altså en samling **LatLong**-objekter. Når man velger et element, så vises det elementet som et punkt på kartet. En kan flytte punktet, forskyve kartet, zoome inn og ut og opprette nye **LatLong**-objekter. + +Kartet implementeres av ([FxMapControl](https://github.com/ClemensFischer/FX-Map-Control), og siden biblioteket ikke er tilgjengelig i et sentral repository, så har vi bygget og lagt ved jar-filen. + +I tillegg kan en lagre og lese inn **LatLongs**-objektet fra **Open...**- og **Save...**-aksjoner i en **File**-meny. diff --git a/simpleexample/src/main/resources/simpleex/ui/README.md b/simpleexample/src/main/resources/simpleex/ui/README.md new file mode 100644 index 0000000000000000000000000000000000000000..72bf916c136978d42303004ff93a8ade81030f13 --- /dev/null +++ b/simpleexample/src/main/resources/simpleex/ui/README.md @@ -0,0 +1,3 @@ +# Ressurser for brukergrensesnittet + +Brukergrensesnittet er laget med JavaFX og FXML, og her ligger FXML-fila som brukes. diff --git a/simpleexample/src/test/java/simpleex/core/README.md b/simpleexample/src/test/java/simpleex/core/README.md new file mode 100644 index 0000000000000000000000000000000000000000..5eaccc223c7fa8cb0a7c73124c16712ed68f5800 --- /dev/null +++ b/simpleexample/src/test/java/simpleex/core/README.md @@ -0,0 +1 @@ +# Testkode for domenelaget diff --git a/simpleexample/src/test/java/simpleex/json/AbstractJsonTest.java b/simpleexample/src/test/java/simpleex/json/AbstractJsonTest.java index a9c32bdadd84ca9576bc83d31e295350cbca0d9f..ab75ac0c1973460cc785702417fd41b1d2970bf9 100644 --- a/simpleexample/src/test/java/simpleex/json/AbstractJsonTest.java +++ b/simpleexample/src/test/java/simpleex/json/AbstractJsonTest.java @@ -1,49 +1,18 @@ package simpleex.json; -import com.fasterxml.jackson.core.JsonParseException; -import com.fasterxml.jackson.databind.JsonDeserializer; -import com.fasterxml.jackson.databind.JsonMappingException; -import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.module.SimpleModule; -import java.io.IOException; import org.junit.Assert; public abstract class AbstractJsonTest { - private ObjectMapper objectMapper; + private final ObjectMapper objectMapper = new JacksonConfigurator().createObjectMapper(); public ObjectMapper getObjectMapper() { return objectMapper; } - protected void setUp() { - objectMapper = createObjectMapper(); - } - - protected abstract ObjectMapper createObjectMapper(); - - protected <T> ObjectMapper createObjectMapper(final Class<T> clazz, - final JsonSerializer<T> serializer, final JsonDeserializer<T> deserializer) { - return new ObjectMapper().registerModule(createSimpleModule(clazz, serializer, deserializer)); - } - - protected <T> SimpleModule createSimpleModule(final Class<T> clazz, - final JsonSerializer<T> serializer, final JsonDeserializer<T> deserializer) { - return new SimpleModule().addSerializer(clazz, serializer).addDeserializer(clazz, deserializer); - } - protected void assertEqualsIgnoreWhitespace(final String expected, final String actual) throws Exception { Assert.assertEquals(expected, actual.replaceAll("\\s+", "")); } - - protected void assertWriteValue(final String expected, final Object value) throws Exception { - assertEqualsIgnoreWhitespace(expected, getObjectMapper().writeValueAsString(value)); - } - - protected <T> T readValue(final String s, final Class<T> clazz) - throws IOException, JsonParseException, JsonMappingException { - return getObjectMapper().readValue(s, clazz); - } } diff --git a/simpleexample/src/test/java/simpleex/json/LatLongJsonTest.java b/simpleexample/src/test/java/simpleex/json/LatLongJsonTest.java index a3c6d4a0cb40073ac120b2aed031936f0bca5f1e..3e87fa7646eadcf5617b37d2832e36def692694c 100644 --- a/simpleexample/src/test/java/simpleex/json/LatLongJsonTest.java +++ b/simpleexample/src/test/java/simpleex/json/LatLongJsonTest.java @@ -1,37 +1,24 @@ package simpleex.json; -import com.fasterxml.jackson.databind.ObjectMapper; import org.junit.Assert; -import org.junit.Before; import org.junit.Test; import simpleex.core.LatLong; public class LatLongJsonTest extends AbstractJsonTest { - @Before - @Override - public void setUp() { - super.setUp(); - } - - @Override - protected ObjectMapper createObjectMapper() { - return createObjectMapper(LatLong.class, new LatLongSerializer(), new LatLongDeserializer()); - } - @Test public void testLatLongSerialization() throws Exception { - assertWriteValue("{\"latitude\":63.1,\"longitude\":12.3}", new LatLong(63.1, 12.3)); + assertEqualsIgnoreWhitespace("{\"latitude\":63.1,\"longitude\":12.3}", getObjectMapper().writeValueAsString(new LatLong(63.1, 12.3))); } @Test public void testLatLongObjectDeserialization() throws Exception { Assert.assertEquals(new LatLong(63.1, 12.3), - readValue("{\"latitude\":63.1,\"longitude\":12.3}", LatLong.class)); + getObjectMapper().readValue("{\"latitude\":63.1,\"longitude\":12.3}", LatLong.class)); } @Test public void testLatLongArrayDeserialization() throws Exception { - Assert.assertEquals(new LatLong(63.1, 12.3), readValue("[ 63.1, 12.3 ]", LatLong.class)); + Assert.assertEquals(new LatLong(63.1, 12.3), getObjectMapper().readValue("[ 63.1, 12.3 ]", LatLong.class)); } } diff --git a/simpleexample/src/test/java/simpleex/json/LatLongsJsonTest.java b/simpleexample/src/test/java/simpleex/json/LatLongsJsonTest.java index 37f1479f8a9805cfa71707e192b28d39b7ec5c8b..46bb9fbf93a970effd5009cb256a135db52c98d1 100644 --- a/simpleexample/src/test/java/simpleex/json/LatLongsJsonTest.java +++ b/simpleexample/src/test/java/simpleex/json/LatLongsJsonTest.java @@ -1,41 +1,23 @@ package simpleex.json; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.module.SimpleModule; import org.junit.Assert; -import org.junit.Before; import org.junit.Test; import simpleex.core.LatLong; import simpleex.core.LatLongs; public class LatLongsJsonTest extends AbstractJsonTest { - @Before - @Override - public void setUp() { - super.setUp(); - } - - @Override - protected ObjectMapper createObjectMapper() { - final SimpleModule module = - createSimpleModule(LatLong.class, new LatLongSerializer(), new LatLongDeserializer()); - module.addSerializer(LatLongs.class, new LatLongsSerializer()); - module.addDeserializer(LatLongs.class, new LatLongsDeserializer()); - return new ObjectMapper().registerModule(module); - } - @Test public void testLatLongsSerialization() throws Exception { - assertWriteValue( + assertEqualsIgnoreWhitespace( "[{\"latitude\":63.1,\"longitude\":12.3},{\"latitude\":63.0,\"longitude\":12.4}]", - new LatLongs(new LatLong(63.1, 12.3), new LatLong(63.0, 12.4))); + getObjectMapper().writeValueAsString(new LatLongs(new LatLong(63.1, 12.3), new LatLong(63.0, 12.4)))); } @Test public void testLatLongsDeserialization() throws Exception { final LatLongs latLongs = - readValue("[{\"latitude\":63.1,\"longitude\":12.3}, [63.0,12.4]]", LatLongs.class); + getObjectMapper().readValue("[{\"latitude\":63.1,\"longitude\":12.3}, [63.0,12.4]]", LatLongs.class); Assert.assertEquals(2, latLongs.getLatLongCount()); Assert.assertEquals(new LatLong(63.1, 12.3), latLongs.getLatLong(0)); Assert.assertEquals(new LatLong(63.0, 12.4), latLongs.getLatLong(1)); diff --git a/simpleexample/src/test/java/simpleex/json/README.md b/simpleexample/src/test/java/simpleex/json/README.md new file mode 100644 index 0000000000000000000000000000000000000000..9a62d5ea7e4ad81749e497741faf5a5064325f0f --- /dev/null +++ b/simpleexample/src/test/java/simpleex/json/README.md @@ -0,0 +1 @@ +# Testkode for persistenslaget diff --git a/simpleexample/src/test/java/simpleex/ui/README.md b/simpleexample/src/test/java/simpleex/ui/README.md new file mode 100644 index 0000000000000000000000000000000000000000..5244c0323b90835965a84752d6d99fecee2e037c --- /dev/null +++ b/simpleexample/src/test/java/simpleex/ui/README.md @@ -0,0 +1 @@ +# Testkode for brukergrensesnittet