wiki:harjoitustyo/malliliitos
Last modified 3 years ago Last modified on 2015-03-26 08:46:34

Ohjelmointi 2 / malliharjoitustyö 2014, harrastusten nimet relaatiolla

Liitos Harrastusten nimet liitoksella versionhallinta kerho.jar

Alkuperäisessä mallissa Jasen ja Harrastusluokan suhde on 1:n. Eli jokaisella jäsenelle voi olla monta harrastusta, mutta samaa harrastusta ei ole monella eri jäsenellä. Tämä johtaa siihen, että jos joku muukin laiskottelee, niin sana laiskottele toistuu useita kertoja ja esim. sen väärinkirjoituksen tapauksessa kaikki paikat pitää erikseen korjata.

"Oikeampi" tapa olisi liittää esim. harrastuksen nimi harrastukseen relaatiolla. Tässä olevassa malliratkaisussa on myös luovuttu tarkenteiden merkityksestä ja eri kerhot tallennetaan eri hakemistoihin (esim. kelmit/nimet.dat).

1. Talletustiedostot

nimet.dat - henkilöiden tiedot:

Kelmien kerho
50
;jid|sukunimi etunimi   |sotu       |katuosoite  |postinumero|postiosoite|kotipuhelin|työpuhelin|
 1  |Ankka Aku          |010245-123U|Ankkakuja 6 |12345      |ANKKALINNA |12-12324   |          |
 2  |Susi Sepe          |020347-123T|            |12555      |Takametsä  |           |          |
 4  |Ponteva Veli       |030455-3333|            |12555      |Takametsä  |           |          |

harrastukset.dat - harrastukset relaation avulla, samoin harrastuksen ala relaatiolla:

;hid|jid |aid |aloit |viikossa
  1 | 1  | 1  | 1955 | 20
  2 | 1  | 2  | 1950 | 20
  3 | 2  | 3  | 1962 |  2
  4 | 1  | 4  | 1952 | 40
  5 | 2  | 5  | 1954 | 20
  6 | 4  | 6  | 1956 | 15
  7 | 2  | 2  | 1954 | 25

harrastustenNimet.dat - harrastukset nimet (=aiheet/alat, siksi aid)

;aid| teksti
  1 | kalastus 
  2 | laiskottelu              
  3 | kelmien kerho  
  4 | työn pakoilu   
  5 | possujen jahtaaminen 
  6 | susiansojen rakentaminen

Jos esimerkiksi sanaa "laiskottelu" nyt muutetaan, niin teksti vaihtuu sekä Aku Ankalle että Sepe Sudelle

Tässä yhden harrastuksen kohdalle on tietoa (ks yllä oleva harrastukset.dat):

 6 | 4  | 6  | 1956 | 15
Selitys:
 - 6: juokseva numero harrastukselle (jos siihen joskus viitattaisiin)
 - 4: jäsenen id-numero (Ponteva Veli)
 - 6: harrastuksen "alan" id-numero (susiansojen rakentaminen)
 - 1956: aloitusvuosi
 - 15: montako tuntia viikossa

Tässä tämä 1956 liittyy nimenomaan Veli Pontevan "tapaan harrastaa" tätä harrastusta. Siksi luontevin paikka tälle tiedolle on nimenomaan tässä yhteydessä.

Hyvin monessa tapauksessa "liimataan" yhteen muuten toistaan riippumattomia tietoja. Esimerkiksi jos haluttaisiin liittää yhteen pelkän jäsenen tiedot ja harrastusten alat, niin liitostiedosto voisi olla jopa pelkästään:

;jid |aid
 1  | 1  
 1  | 2  
 2  | 3  
 1  | 4  
 2  | 5  
 4  | 6  
 2  | 2  

Eli tässä esimerkissä liittäminen on jopa "hieman vaikeampaa" kuin tuossa yleisessä tilanteessa. Jos omassa työssä on tuollaisia kahden numeron pareja, niin silloin ottamalla ideaa tästä mallista ja karsimalla tuo ylimääräiset tiedot pois, pääsee jo hyvin jyvälle.

Miksi edes yksittäisiä sanoja kannattaa liittää "näin monimutkaisesti"? Siksi että voi olla että sanaan "kalastus" haluttaisiin myöhemmin liittää lisämääreitä, kuten kuvausta ja yleiseen kalastukseen liittyviä www-linkkejä. Näin tehtynä nuo lisämääreet kulkisivat automaattisesti jokaisen harrastajan mukana ja jos harrastuksen selitystä muokataan, se muokkaantuu kaikilla harrastajilla automaattisesti.

2. Oliokuva

Sama oliokuvana (missä Naytto koostuu oikeassa ohjelmassa useammasta tiedostosta kuten alkuperäisessäkin mallissa, esim KerhoGUI ja KerhoSwing).

https://svn.cc.jyu.fi/srv/svn/ohj2k13/vesal/branches/harrastusLiitoksella/kuvat/kerhohar.png

3. Käyttöliittymä

Tässä mallissa käyttöliittymä on tehty niin, että se ymmärtää että käytössä oleva harrastusten nimet ovat erikoisasemassa ja ne on laitettu omaan listaansa ikkunan oikeaan reunaan.

https://svn.cc.jyu.fi/srv/svn/ohj2k13/vesal/branches/harrastusLiitoksella/kuvat/paaikkuna.png

  • harrastusta lisättäessä valitaan harrastuksen "aihe" oikealla olevasta listasta ja silloin lisätään uusi harrastus keskellä olevaan taulukkoon.
  • erikseen voi lisätä harrastusten nimiä oikealla olevaan listaan
  • jos taulukkoon kirjoittaa harrastuksen nimeä, haetaan vastaavaa tekstiä oikealla olevasta listasta ja jos taulukon solusta poistutaan (esim. Enter näppäimellä), otetaan kirjoitetun tekstin tilalle oikealla oleva harrastuksen nimi. Jos mikään nimi ei vastaa kirjoitettua sanaa, kysytään uuden lisäämistä. Näin käyttäjä voi käyttää taulukko-osaa melkein kuten edellisessä versiossa.
  • harrastusten nimilistaa voi rajoittaa listan yläpuolella olevalla hakuehdolla
  • jäsen etsinnän komboboxiin on lisätty myös harrastukset jolloin kirjoitettua sanaa etsitään harrastusten nimilistasta ja sitten etsitään kaikki ne jäsenet, joilla on liitettynä tämä harrastus.

4. Toteutuksesta koodissa

Vaikka nämä malliversiot on tehty siitä "ei tarvitse ymmärtää kanttä.taulukosta", olisi ylemmät luokat samanlaisia, vaikka noiden alimpien luokkien (Selite, Harrastus ja Jasen) toteutus olisi "tyhmempikin". Pääsin vain näin itse nopeammin eteenpäin kun voi käyttää geneerisyyttä tallennusrakenteissa.

Seuraavassa on pieniä leikkeitä itse koodista selityksen helpottamiseksi. Koodiin liittyvät rivinumerot voivat todellisessa koodissa olla erilaiset muutosten seurauksena. Mutta suuntaa antavia paikannäyttäjiä ne ovat.

4.1 Selite

Koska tässä harrastuksen nimi on vain id:n ja merkkijonon yhdiste, on tehty yleinen luokka Selite.java, joka kelpaa käytettäväksi kaikissa vastaavissa tapauksissa. Luokan tehtävänä on ylläpitää vain tuota id-numeroa (juoksevasti kuten jäsenenkin) ja vastaavaa tekstiä. Samalla luokalla voitaisiin liittää esimerkiksi jäseniin "titteleitä" jos sellaisia haluttaisiin käyttää (samat "tittelit" toistuisivat usealla jäsenellä).

4.2 KerhoSwing

KerhoSwing.java

Uutta harrastusta lisättäessä on jo etukäeen valittu listasta joku Jasen ja toisesta joku Selite. Sitten pitää luoda näitä yhdistävä Harrastus-olio. Tämä voidaan jättää Kerhon tehtäväksi, koska se tietää mikä on eri luokkien välinen suhde ja id-numeroiden merkitys:

394    /**
395     * Tekee uuden tyhjän harrastuksen editointia varten
396     */
397    public void uusiHarrastus() {
398        if ( jasenKohdalla == null ) return;
399        Selite selite = listHarrastustenNimet.getSelectedObject();
400        if ( selite == null ) return;
401        tarkistaMuutos(jasenKohdalla.getTunnusNro());
402        Harrastus harrastus = kerho.luoHarrastus(jasenKohdalla,selite);
403        if ( uusiDialogilla ) 
404            if ( !TietueDialog.kysyTietue(harrastus, "Anna " + selite.getTeksti() + " tiedot", 200) )  return; 
405        harrastus.rekisteroi(); 
406        kerho.lisaa(harrastus);
407        naytaHarrastukset();
408        int r = tableHarrastukset.getRowCount();
409        tableHarrastukset.selectCell(r,lisat.length);
410    }

Esimerkki miten näytetään harrastukset kun itse Harrastus luokassa ei ole harrastuksen nimeä. Eli ensin haetaan harrastuksia vastaavat tietueet, joista sitten kerho osaa antaa vastaavan harrastuksen nimen kerho.getAla(har):

413    /**
414     * Näytetään harrastukset taulukkoon.  Tyhjennetään ensin taulukko ja sitten
415     * lisätään siihen kaikki harrastukset
416     */
417    protected void naytaHarrastukset() {
418        if ( jasenKohdalla == null ) return;
419        int oldr = tableHarrastukset.getSelectedRow();
420        int oldc = tableHarrastukset.getSelectedColumn();
421        tableHarrastukset.clear();
422        tableHarrastukset.getTable().getColumnModel().getColumn(0).setMinWidth(100);
423        
424        List<Harrastus> harrastukset = kerho.annaHarrastukset(jasenKohdalla);
425        for (Harrastus har : harrastukset) {
426            int r = tableHarrastukset.addRow();
427            tableHarrastukset.setObjectAt(har, r);
428            tableHarrastukset.setValueAtModel(kerho.getAla(har), r, 0); // linkitetyt kentät
429            for (int i=lisat.length,k = har.ekaKentta(); k < har.getKenttia() && i < tableHarrastukset.getColumnCount(); i++,k++) { 
430                tableHarrastukset.setValueAtModel(har.getKentta(k), r, i);
431            }
432        }
433        tableHarrastukset.selectCell(oldr, oldc);
434    }

4.3 Kerho

Kerho.java

Kerhon tehtävän on luoda uusi Harrastus-olio, jolla liitetään Jasen ja Selite toisiinsa.

490     public Harrastus luoHarrastus(Jasen jasen, Selite selite) {
491         return new Harrastus(jasen.getTunnusNro(),selite.getTunnusNro());
492     }

Mielenkiintoinen on etsiä niitä jäseniä, jotka harrastavat tiettyä harrastusta:

546     public Collection<Jasen> etsiHarrastuksista(String ehto) {
547         List<Jasen> loytyneet = new ArrayList<Jasen>();
548         List<Selite> harrastusnimet = harrastustenNimet.etsi(ehto, 1);
549         List<Harrastus> harrasteet = new ArrayList<Harrastus>();
550         for (Selite selite : harrastusnimet) {
551             int id = selite.getTunnusNro();
552             harrasteet.addAll(harrastukset.etsi(""+id,2));
553         }
554         for ( Harrastus har : harrasteet ) {
555             int jid = har.getJasenNro();
556             Jasen jasen = jasenet.annaId(jid);
557             if ( jasen == null ) continue;
558             if ( !loytyneet.contains(jasen) )
559               loytyneet.add(jasen);
560         }
561         Collections.sort(loytyneet, new TietueVertailija(1));  
562         return loytyneet;
563     }