diff --git a/Kirjalista.jar b/Kirjalista.jar index 8463797545d1e1cab93946687893a8335db33d9e..efec7402fef9b585d65eceb0e90b8d3e390fa6cd 100644 Binary files a/Kirjalista.jar and b/Kirjalista.jar differ diff --git a/build.xml b/build.xml index 3ccde9eee5da3105024fb5cafe85e6e189955cad..76ad47b82dc62876fcddfcbe86969775f2620dae 100644 --- a/build.xml +++ b/build.xml @@ -17,7 +17,7 @@ <zipfileset excludes="META-INF/*.SF" src="C:/devel/jar/Ali.jar"/> <zipfileset excludes="META-INF/*.SF" src="C:/devel/jar/fxgui.jar"/> <zipfileset excludes="META-INF/*.SF" src="C:/devel/jar/Graphics.jar"/> - <zipfileset excludes="META-INF/*.SF" src="C:/devel/jar/Music.jar"/> + <zipfileset excludes="META-INF/*.SF" src="C:/Users/omistaja/Ohjelmointi/Java-projektit/Jarreja/Tietorakenne.jar"/> </jar> </target> </project> diff --git a/src/Kirjalista/Genre.java b/src/Kirjalista/Genre.java index ce75905182ac803bec0dbc2e0cc9df91888564d9..6aaa9ab1f12d9b014875d7781c5bd94cb73aaa7b 100644 --- a/src/Kirjalista/Genre.java +++ b/src/Kirjalista/Genre.java @@ -1,5 +1,7 @@ package Kirjalista; +import java.io.PrintStream; +import java.util.Random; /** * Genre-luokka @@ -17,7 +19,7 @@ public class Genre { /** * Ottaa merkkijonon ja muuttaa sen genren tiedoiksi, poistaa turhat völilyönnit ja muuttaa * syötteen pieniksi kirjaimiksi - * @param mjono Merkkijono, josta kirjan tiedot saadaan + * @param mjono Merkkijono, josta genren tiedot saadaan * <pre name="test"> * Genre g = new Genre(); * g.parse("fantasia"); @@ -58,6 +60,25 @@ public class Genre { } + + private String[] esim = {"Fantasia", "Sci-fi", "Kauhu"}; + /** + * Asettaa genreksi jonkun ylläolevista + * TODO poista + */ + public void esimerkkiGenre() { + Random rand = new Random(); + this.nimi = esim[rand.nextInt(3)]; + } + + + /** + * @return Genren nimi + */ + public String getNimi() { + return this.nimi; + } + /** * palauttaa genren id:n * @return Genren id @@ -65,4 +86,25 @@ public class Genre { public int getId() { return this.id; } + + + /** + * Tulostaa genren tiedot + * @param out Tietovirta johon tulostetaan + */ + public void tulosta(PrintStream out) { + out.println(this.id + " " + this.nimi); + } + + + /** + * Asettaa id:lle annetun arvon + * @param id arvo, joka asetetaan id:ksi + * Tämä olemassa, koska tietyllä genrellä on aina tietty id ja ilman tätä aliohjelmaa tulisi + * ongelmia sellaisten lisättyjen kirjojen kanssa, joiden genre on jo "tietokannassa." Ilman tätä + * kyseisten genrejen id olisi 0 ja ohjelma ei osaisi hakea niitä + */ + public void setId(int id) { + this.id = id; + } } diff --git a/src/Kirjalista/GenreRelaatio.java b/src/Kirjalista/GenreRelaatio.java index 8cb4e5f7b31d80a356e8b0f99c23a01e38d967ef..8a2ef37adaf92669f47b0299c165be829bf98077 100644 --- a/src/Kirjalista/GenreRelaatio.java +++ b/src/Kirjalista/GenreRelaatio.java @@ -28,15 +28,29 @@ public class GenreRelaatio { * esim. palauttaa kaikkien kirjojen id:t, joiden genre on fantasia * @param genreId Genren id, jonka perusteella haetaan kirjojen id:itä * @return Kaikkien niiden kirjojen id:t, joiden genren id on genreId + * TODO testit + * <pre name="test"> + * GenreRelaatio gr = new GenreRelaatio(); + * gr.lisaa(new KirjanGenre(1, 2)); + * int[] t = gr.haeKirjat(2); + * t[0] === 1; + * TODO lisää testejä + * </pre> */ public ArrayList<Integer> haeKirjat(int genreId) { + //if (alkiot.length() <= 0) throw new IndexOutOfBoundsException(); ArrayList<Integer> kirjojenIdt = new ArrayList<Integer>(); + + alkiot.iter = alkiot.getEka(); + for (int i = 0; i < alkiot.length(); i++) { - KirjanGenre alkio = alkiot.getByIndex(i); + KirjanGenre alkio = alkiot.iter.getSisalto(); if (alkio.getGenreId() == genreId) { - kirjojenIdt.add(alkio.getKirjaId()); + kirjojenIdt.add(alkio.getGenreId()); } + alkiot.iter = alkiot.iter.getNext(); } + return kirjojenIdt; } @@ -46,15 +60,22 @@ public class GenreRelaatio { * eli toisin sanoen palauttaa tietyn kirjan kaikkien genrejen id:t * @param kirjaId Kirjan id, jonka perusteella haetaan genrejen id:itä * @return Kaikkien niiden genrejen id:t, joiden kirjan id on kirjaId + * TODO testit */ public ArrayList<Integer> haeGenret(int kirjaId) { + //if (alkiot.length() <= 0) throw new IndexOutOfBoundsException(); ??? tämä ei mahdollista ArrayList<Integer> genrejenIdt = new ArrayList<Integer>(); + + alkiot.iter = alkiot.getEka(); + for (int i = 0; i < alkiot.length(); i++) { - KirjanGenre alkio = alkiot.getByIndex(i); + KirjanGenre alkio = alkiot.iter.getSisalto(); if (alkio.getKirjaId() == kirjaId) { genrejenIdt.add(alkio.getGenreId()); } + alkiot.iter = alkiot.iter.getNext(); } + return genrejenIdt; } diff --git a/src/Kirjalista/Genret.java b/src/Kirjalista/Genret.java new file mode 100644 index 0000000000000000000000000000000000000000..c852475ed788d56f380795b3005d6512b14d14d7 --- /dev/null +++ b/src/Kirjalista/Genret.java @@ -0,0 +1,84 @@ +package Kirjalista; + +import java.util.ArrayList; +import java.util.NoSuchElementException; + +/** + * Monikkoluokka genreille + * - Sisältää listan genreistä + * - Lisää ja poistaa kirjoja + * - Lukee ja kirjoittaa tiedostoon + * - Etsii ja lajittelee + */ +public class Genret { + private ArrayList<Genre> alkiot = new ArrayList<Genre>(); + + + /** + * Lisää genren listaan, jos samannimistä genreä ei ole olemassa + * @param genre Lisättävä genre + */ + public void lisaa(Genre genre) { + if (onOlemassa(genre.getNimi())) { + genre.setId(haeIdNimella(genre.getNimi())); + return; + } + genre.rekisteroi(); + alkiot.add(genre); + } + + + private int haeIdNimella(String nimi) { + for (int i = 0; i < alkiot.size(); i++) { + if (alkiot.get(i).getNimi() == nimi) return alkiot.get(i).getId(); + } + return -1; + } + + + /** + * Poistaa genren annetulla id:llä + * @param id Id, jonka perusteella genre poistetaan + * TODO testit + */ + public void poista(int id) { + for (int i = 0; i < alkiot.size(); i++) { + if (alkiot.get(i).getId() == id) { + alkiot.remove(i); + return; + } + } + throw new NoSuchElementException("Genreä id:llä " + id + " ei löydy."); + } + + + /** + * Tarkistaa, onko tietyn nimistä genreä olemassa + * @param nimi Genren nimi + * @return True, jos genre on olemassa + */ + public boolean onOlemassa(String nimi) { + for (int i = 0; i < alkiot.size(); i++) { + if (alkiot.get(i).getNimi() == nimi) { + return true; + } + } + return false; + } + + + /** + * Hakee genren nimen id:n perusteella + * @param id haettavan genren id + * @return Viite genreen halutulla id:llä + * TODO testit + */ + public Genre hae(int id) { + for (int i = 0; i < alkiot.size(); i++) { + if (alkiot.get(i).getId() == id) return alkiot.get(i); + } + + throw new NoSuchElementException("Genreä id:llä " + id + " ei löydy!"); + } + +} diff --git a/src/Kirjalista/KirjanGenre.java b/src/Kirjalista/KirjanGenre.java index 5e786c7821b1353a8369a96cf1b81f7cc844baea..3b593751ed4f33cbfb58f85d6cd325321d490bb5 100644 --- a/src/Kirjalista/KirjanGenre.java +++ b/src/Kirjalista/KirjanGenre.java @@ -11,15 +11,12 @@ public class KirjanGenre { /** * Luo olion - * @param kirjaId Kirjan id - * @param genreId Genren id - * <pre name="test"> - - * </pre> + * @param kirja Kirja + * @param genre Genre */ - public KirjanGenre(int kirjaId, int genreId) { - this.kirjaId = kirjaId; - this.genreId = genreId; + public KirjanGenre(Kirja kirja, Genre genre) { + this.kirjaId = kirja.getId(); + this.genreId = genre.getId(); } diff --git a/src/Kirjalista/Kirjasto.java b/src/Kirjalista/Kirjasto.java index 03475a8cde8b0718bc9b3bf20bf15e3ecbf10f13..aaca4953e65767a0a2b3384e2ef2f47ade4fb106 100644 --- a/src/Kirjalista/Kirjasto.java +++ b/src/Kirjalista/Kirjasto.java @@ -1,6 +1,7 @@ package Kirjalista; - +import java.util.ArrayList; +import java.util.NoSuchElementException; /** * Luokka, joka keskustelee käyttöliittymän kanssa @@ -8,8 +9,8 @@ package Kirjalista; */ public class Kirjasto { private Kirjat kirjat = new Kirjat(); - private GenreRelaatio genreRelaatio; - //private Genret genret; + private GenreRelaatio genreRelaatio = new GenreRelaatio(); + private Genret genret = new Genret(); @@ -23,25 +24,50 @@ public class Kirjasto { /** - * Ottaa taulukollisen genreId:itä ja liima ne kirjan id:n kanssa yhteen. Lisää lopuksi listaan - * @param kirjaId Kirjan id - * @param genreId Taulukko kaikista kirjan genrejen id:istä + * Lisää genret, jos sen nimisiä ei vielä ole olemassa + * @param genre Lisättävät genret */ - public void lisaaGenreRelaatio(int kirjaId, int[] genreId) { - for (int i = 0; i < genreId.length; i++) { - genreRelaatio.lisaa(new KirjanGenre(kirjaId, genreId[i])); + public void lisaaGenre(Genre[] genre) { + for (int i = 0; i < genre.length; i++) { + genret.lisaa(genre[i]); } } - // TODO haku ja poisto genreRelaatioille + /** + * Ottaa taulukollisen genrejä ja liima ne kirjan id:n kanssa yhteen + * @param kirja Kirja + * @param kirjanGenret Taulukko kaikista kirjan genreistä + */ + public void lisaaGenreRelaatio(Kirja kirja, Genre[] kirjanGenret) { + for (int i = 0; i < kirjanGenret.length; i++) { + genreRelaatio.lisaa(new KirjanGenre(kirja, kirjanGenret[i])); + } + } + + // TODO haku ja poisto genreRelaatioille ??? /** - * @param indeksi Indeksipaikka, josta kirja haetaan + * @param idnro Haettavan kirjan id * @return Kirja annetussa indeksipaikassa - * @throws IndexOutOfBoundsException Jos indeksi laiton + * @throws NoSuchElementException Jos id laiton */ - public Kirja haeKirja(int indeksi) throws IndexOutOfBoundsException { - return kirjat.hae(indeksi); + public Kirja haeKirja(int idnro) throws NoSuchElementException { + return kirjat.hae(idnro); + } + + + /** + * Hakee taulukon kirjan genreistä kirjan id:n perusteella + * @param kirjaId Sen kirjan id, jonka genrejä haetaan + * @return Kaikki kirjan genret taulukossa + */ + public Genre[] haeGenret(int kirjaId) { + ArrayList<Integer> idt = genreRelaatio.haeGenret(kirjaId); + Genre[] palautettava = new Genre[idt.size()]; + for (int i = 0; i < idt.size(); i++) { + palautettava[i] = genret.hae(idt.get(i)); + } + return palautettava; } @@ -51,9 +77,14 @@ public class Kirjasto { public int getKirjaLkm() { return this.kirjat.getLkm(); } - /* - public Genre haeGenre(Kirja kirja) { - GenreRelaatio.haeGenret(); + + + /** + * Hakee kirjan indeksin perusteella + * @param ind Indeksipaikka, josta kirja haetaan + * @return Kirja annetussa indeksipaikassa + */ + public Kirja haeKirjaIndeksilla(int ind) { + return kirjat.haeIndeksilla(ind); } - */ } diff --git a/src/Kirjalista/Kirjat.java b/src/Kirjalista/Kirjat.java index 27f9f8941c89fca5edd0c516af0bbef8e57effca..8f5695515b6808c17321114aa88f9a62b8ebe0f0 100644 --- a/src/Kirjalista/Kirjat.java +++ b/src/Kirjalista/Kirjat.java @@ -1,5 +1,6 @@ package Kirjalista; +import java.util.NoSuchElementException; /** * Monikkoluokka kirjoille. @@ -10,7 +11,7 @@ package Kirjalista; */ public class Kirjat { private int maxLkm = 8; - private int lkm; + private int lkm = 0; private Kirja[] alkiot = new Kirja[maxLkm]; @@ -21,24 +22,59 @@ public class Kirjat { public void lisaa(Kirja kirja) throws SailoException { if (this.lkm >= this.alkiot.length) throw new SailoException("Liikaa alkioita"); this.alkiot[this.lkm] = kirja; + kirja.rekisteroi(); this.lkm++; } + /** + * Poistaa kirjan annetulla id:llä + * @param id Poistettavan kirjan id + * @throws NoSuchElementException Jos id:tä vastaavaa kirjaa ei löydy + * TODO testit + */ + public void poista(int id) throws NoSuchElementException { + for (int i = 0; i < alkiot.length; i++) { + if (alkiot[i].getId() == id) { + for (int j = i; j < alkiot.length - 1; j++) { + alkiot[j] = alkiot[j + 1]; + } + alkiot[alkiot.length] = null; + this.lkm--; + return; + } + } + throw new NoSuchElementException("Kirjaa id:llä " + id + " ei löydy."); + } /** - * Hakee kirjan indeksipaikassa i - * @param i Halutun kirjan indeksi - * @return viite kirjaan, jonka indeksi on i - * @throws IndexOutOfBoundsException jos indeksi liian suuri tai pieni + * Hakee kirjan id:n perusteella + * @param id Halutun kirjan id + * @return Viite kirjaan halutulla id:llä + * @throws NoSuchElementException + * TODO testit */ - public Kirja hae(int i) throws IndexOutOfBoundsException { - if (i < 0 || this.lkm <= i) - throw new IndexOutOfBoundsException("Laiton indeksi: " + i); - return this.alkiot[i]; + public Kirja hae(int id) throws NoSuchElementException { + + for (int i = 0; i < alkiot.length; i++) { + if (alkiot[i].getId() == id) return alkiot[i]; + } + + throw new NoSuchElementException("Kirjaa id:llä " + id + " ei löytynyt."); } + /** + * Hakee kirjan indeksin perusteella + * @param ind Indeksipaikka, josta kirja haetaan + * @return Kirja annetussa indeksipaikassa + */ + public Kirja haeIndeksilla(int ind) { + if (ind < 0 || ind >= this.lkm) throw new NullPointerException("Laiton indeksi"); + return alkiot[ind]; + } + + /** * Palauttaa kirjojen lukumäärän * @return kirjojen lukumäärä diff --git a/src/Kirjalista/test/GenreRelaatioTest.java b/src/Kirjalista/test/GenreRelaatioTest.java new file mode 100644 index 0000000000000000000000000000000000000000..e0049becadcd7d508b1305bd67f930c0b22433a6 --- /dev/null +++ b/src/Kirjalista/test/GenreRelaatioTest.java @@ -0,0 +1,28 @@ +package Kirjalista.test; +// Generated by ComTest BEGIN +import static org.junit.Assert.*; +import org.junit.*; +import Kirjalista.*; +// Generated by ComTest END +import tietorakenne.LinkattuLista; + +/** + * Test class made by ComTest + * @version 2025.03.05 22:52:50 // Generated by ComTest + * + */ +@SuppressWarnings({ "all" }) +public class GenreRelaatioTest { + + + + // Generated by ComTest BEGIN + /** testHaeKirjat33 */ + @Test + public void testHaeKirjat33() { // GenreRelaatio: 33 + GenreRelaatio gr = new GenreRelaatio(); + gr.lisaa(new KirjanGenre(1, 2)); + int[] t = gr.haeKirjat(2); + assertEquals("From: GenreRelaatio line: 37", 1, t[0]); + } // Generated by ComTest END +} \ No newline at end of file diff --git a/src/Kirjalista/test/KirjanGenreTest.java b/src/Kirjalista/test/KirjanGenreTest.java index 4034012091d731828d9e31c9df49423712b5f307..67e68bcb584a6167fae63671217725ebdcc56e84 100644 --- a/src/Kirjalista/test/KirjanGenreTest.java +++ b/src/Kirjalista/test/KirjanGenreTest.java @@ -2,41 +2,16 @@ package Kirjalista.test; // Generated by ComTest BEGIN import static org.junit.Assert.*; import org.junit.*; - -import Kirjalista.Genre; -import Kirjalista.Kirja; -import Kirjalista.KirjanGenre; +import Kirjalista.*; +// Generated by ComTest END + * @version 2025.03.10 18:15:06 // Generated by ComTest +package Kirjalista.test; /** * Test class made by ComTest - * @version 2025.02.24 13:51:58 // Generated by ComTest + * @version 2025.03.10 18:15:06 // Generated by ComTest * */ @SuppressWarnings({ "all" }) public class KirjanGenreTest { - - - - // Generated by ComTest BEGIN - /** testKirjanGenre16 */ - @Test - public void testKirjanGenre16() { // KirjanGenre: 16 - Kirja k = new Kirja(); - k.rekisteroi(); - Kirja k1 = new Kirja(); - k1.rekisteroi(); - Genre g = new Genre(); - g.rekisteroi(); - Genre g1 = new Genre(); - g1.rekisteroi(); - KirjanGenre kg = new KirjanGenre(k, g); - KirjanGenre kg1 = new KirjanGenre(k1, g1); - KirjanGenre kg2 = new KirjanGenre(k, g1); - assertEquals("From: KirjanGenre line: 31", k.getId(), kg.getKirjaId()); - assertEquals("From: KirjanGenre line: 32", k1.getId(), kg1.getKirjaId()); - assertEquals("From: KirjanGenre line: 33", k.getId(), kg2.getKirjaId()); - assertEquals("From: KirjanGenre line: 35", g.getId(), kg.getGenreId()); - assertEquals("From: KirjanGenre line: 36", g1.getId(), kg1.getGenreId()); - assertEquals("From: KirjanGenre line: 37", g1.getId(), kg2.getGenreId()); - } // Generated by ComTest END } \ No newline at end of file diff --git a/src/fxKirjalista/KirjalistaGUIController.java b/src/fxKirjalista/KirjalistaGUIController.java index 2f096cfa6339192e21f54a7a089f9ec57a208c93..02452b2eb314ce4cd23a306d26e0e128abf2326b 100644 --- a/src/fxKirjalista/KirjalistaGUIController.java +++ b/src/fxKirjalista/KirjalistaGUIController.java @@ -5,6 +5,7 @@ import java.net.URL; import java.util.Optional; import java.util.ResourceBundle; +import Kirjalista.Genre; import Kirjalista.Kirja; import Kirjalista.Kirjasto; import fi.jyu.mit.fxgui.Dialogs; @@ -171,7 +172,7 @@ public class KirjalistaGUIController implements Initializable { int index = 0; for (int i = 0; i < kirjasto.getKirjaLkm(); i++) { - Kirja kirja = kirjasto.haeKirja(i); + Kirja kirja = kirjasto.haeKirjaIndeksilla(i); if (kirja.getId() == idnro) index = i; chooserKirjat.add(kirja.getNimi(), kirja); } @@ -191,6 +192,10 @@ public class KirjalistaGUIController implements Initializable { areaKirja.setText(""); try (PrintStream os = TextAreaOutputStream.getTextPrintStream(areaKirja)) { valittuKirja.tulosta(os); + os.println("========================================="); + for (Genre g : kirjasto.haeGenret(valittuKirja.getId())) { + g.tulosta(os); + } } } diff --git a/src/fxKirjalista/LisaaController.java b/src/fxKirjalista/LisaaController.java index e8dcd8c2a7a9cc4a7c6e8acd2cfcab40ae68387e..ef0e32120db5526f7ffd251b45d84679bbe1248c 100644 --- a/src/fxKirjalista/LisaaController.java +++ b/src/fxKirjalista/LisaaController.java @@ -1,5 +1,6 @@ package fxKirjalista; +import Kirjalista.Genre; import Kirjalista.Kirja; import Kirjalista.Kirjasto; import Kirjalista.SailoException; @@ -73,15 +74,51 @@ public class LisaaController { * taulukkoon ja antaa virheen, jos ei onnistu. */ protected void uusiKirja() { + /* Lopullisessa versiossa käyttöliittymästä tulisi + * tekstiä, josta parsetaan kirjan tiedot ja tekstiä, josta + * parsetaan genret. + */ + + Kirja uusi = new Kirja(); + Genre genre1 = new Genre(); + Genre genre2 = new Genre(); + Genre genre3 = new Genre(); + // uusi.parse( käyttöliittymästä tullut teksti ); + // + // String[] genreStr = teksti.split("|"); + // Genre[] genret = new Genre[genreStr.length]; + // for (int i = 0; i < genreStr.length; i++) { + // genre g = new Genre(); + // genret[i] = g.parse(genreStr[i]); + // } + // kirjasto.lisaaGenre(genret); + // + // kirjasto.lisaaGenreRelaatio(uusi, genret); + // + // ^^^^ näin sitten toimivassa ohjelmassa ^^^^ + + + uusi.esimerkkiKirja(); - uusi.rekisteroi(); + genre1.esimerkkiGenre(); + genre2.esimerkkiGenre(); + genre3.esimerkkiGenre(); + + + Genre[] g = {genre1, genre2, genre3}; + + kirjasto.lisaaGenre(g); + try { kirjasto.lisaaKirja(uusi); } catch (SailoException e) { Dialogs.showMessageDialog("Ongelma " + e.getMessage()); return; } + + kirjasto.lisaaGenreRelaatio(uusi, g); + isanta.hae(uusi.getId()); }