Fát építünk

Fát építünkAz adatok strukturális és könnyen értelmezhető formában való megjelenítése egy szoftver felhasználói felületén átgondolt tervezést igényel. Az adatokhoz hozzá kell jutni, ki kell választani a megfelelő grafikus komponenst, a mögötte lévő adatmodellt, össze kell ezeket kötni. Gyakran előforduló feladat, hogy táblázatosan is ábrázolható adatokból – felhasználva az adatok közötti összefüggéseket és kapcsolatokat – csoportosítva jelenítsünk meg hierarchikusan, fa struktúrában, kinyitható-becsukható formában, ahogyan ezt a felhasználók jól ismerik a fájl- és menürendszereket használva.

Fát építünk kétféleképpen

Adatbázisból, az Oracle HR sémából lekérdezünk két összetartozó nevet: részleg és alkalmazott. A lekérdezés során figyelünk a megfelelő sorrendre, ami a későbbi feldolgozást megkönnyíti. Adatainkat részlegnév szerint növekvő, azon belül alkalmazott neve szerint is növekvő – ábécé szerinti – sorrendbe rendezzük. A vezérlő rétegben két függvényt írunk, amely a modell rétegtől jut hozzá az adatokat tartalmazó generikus listához – átvett paraméterként –, és a visszaadott érték a nézet réteghez kerül.

A csoportváltás algoritmust használjuk, amely 5 blokkból épül fel. A külső ciklus előtti 1. blokk és utáni 5. blokk egyszer hajtódik végre, az előkészítő és lezáró tevékenységek tartoznak ide. A külső ciklus elején és végén található 2. és 4. blokk a belső cikluson kívül fut le, csoportonként, kategóriánként, részlegenként egyszer (most összesen 11-szer mindkettő). A 3. blokk a belső cikluson belül található, és alkalmazottanként egyszer hajtódik végre (most összesen 106-szor).

Háromszintű fát építünk: a gyökérbe (0. szint) fix, beégetett szövegként kerül a cég neve és a teljes létszám. Az 1. szinten jelennek meg a részlegek nevei és a hozzájuk tartozó létszámok. A 2. szint az alkalmazottak neveiből áll.

1. megoldás

A megoldás faKeszit1() függvénye szöveges adatot eredményez. Ez jól használható teszteléshez: megvan-e az összes adat, megfelelő-e a részlegek sorrendje azon belül az alkalmazottak sorrendje, működik-e a csoportosítás, rendben van-e a megszámolás?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public String faKeszit1(ArrayList<Alkalmazott> lista) {
  //1
  StringBuilder faGyoker=new StringBuilder("Cég ("+lista.size()+" fő)");
  int i=0;
  while(i<lista.size()) {
    //2
    String aktReszleg=lista.get(i).getReszleg();
    ArrayList<String> faReszlegAlkalmazott=new ArrayList<>();
    while(i<lista.size() && lista.get(i).getReszleg().equals(aktReszleg)) {
      //3
      faReszlegAlkalmazott.add(lista.get(i).getNev());
      i++;
    }
    //4
    String faReszleg="\n "+aktReszleg+" ("+faReszlegAlkalmazott.size()+
      " fő)\n ";
    faGyoker.append(faReszleg+" "+String.join("\n  ",faReszlegAlkalmazott));
  }
  //5
  return faGyoker.toString();
}

 
A faKeszit1() függvény egy sok lépésben összefűzött (konkatenált) szöveget ad vissza. Az 1. blokkban előkészítjük a fa gyökerét, ami StringBuilder típusú, hiszen sokszor manipuláljuk és inicializáljuk a lista indexelésére használt i ciklusváltozót. A 2. blokkban megjegyezzük az aktuális részleget és előkészítjük az ehhez tartozó alkalmazottak nevét tároló generikus listát (faReszlegAlkalmazott). Az aktReszleg-hez tartozó alkalmazottak neveit összegyűjtjük a 3. blokkban. Egy részleg feldolgozását a 4. blokkban fejezzük be a fa aktuális 1. és 2. szinten lévő elemeinek szövegbe való beszúrásával. A belső ciklushoz kötődően megszámolást nem kell alkalmaznunk, hiszen az adott részlegben dolgozó alkalmazottak száma a generikus listától elkérhető (size()). Építünk arra, hogy a külső ciklusból nézve az egymás után végrehajtódó 2. és 4. blokkban az aktReszleg nem változik meg. A 2. blokkban még nem tudjuk a fa aktuális 1. szintjét hozzáfűzni a szöveghez, hiszen a létszám csak a belső ciklusban felépülő kollekciótól kérhető el utólag. Szükséges némi késleltetés, hiszen a szöveg összefűzése és lényegesen egyszerűbb (mint utólag manipulálni megfelelő helyeken). Az 5. blokkban a csoportváltás algoritmushoz kötődő tevékenységünk nincs.

Az 1. megoldás eredménye

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
Cég (106 fő)
 Accounting (2 fő)
  Shelley Higgins
  William Gietz
 Administration (1 fő)
  Jennifer Whalen
 Executive (3 fő)
  Lex De Haan
  Neena Kochhar
  Steven King
 Finance (6 fő)
  Daniel Faviet
  Ismael Sciarra
  John Chen
  Jose Manuel Urman
  Luis Popp
  Nancy Greenberg
 Human Resources (1 fő)
  Susan Mavris
 IT (5 fő)
  Alexander Hunold
  Bruce Ernst
  David Austin
  Diana Lorentz
  Valli Pataballa
 Marketing (2 fő)
  Michael Hartstein
  Pat Fay
 Public Relations (1 fő)
  Hermann Baer
 Purchasing (6 fő)
  Alexander Khoo
  Den Raphaely
  Guy Himuro
  Karen Colmenares
  Shelli Baida
  Sigal Tobias
 Sales (34 fő)
  Alberto Errazuriz
  Allan McEwen
  Alyssa Hutton
  Amit Banda
  Charles Johnson
  Christopher Olsen
  Clara Vishney
  Danielle Greene
  David Bernstein
  David Lee
  Eleni Zlotkey
  Elizabeth Bates
  Ellen Abel
  Gerald Cambrault
  Harrison Bloom
  Jack Livingston
  Janette King
  John Russell
  Jonathon Taylor
  Karen Partners
  Lindsey Smith
  Lisa Ozer
  Louise Doran
  Mattea Marvins
  Nanette Cambrault
  Oliver Tuvault
  Patrick Sully
  Peter Hall
  Peter Tucker
  Sarath Sewall
  Sundar Ande
  Sundita Kumar
  Tayler Fox
  William Smith
 Shipping (45 fő)
  Adam Fripp
  Alana Walsh
  Alexis Bull
  Anthony Cabrio
  Britney Everett
  Curtis Davies
  Donald OConnell
  Douglas Grant
  Girard Geoni
  Hazel Philtanker
  Irene Mikkilineni
  James Landry
  James Marlow
  Jason Mallin
  Jean Fleaur
  Jennifer Dilly
  John Seo
  Joshua Patel
  Julia Dellinger
  Julia Nayer
  Kelly Chung
  Kevin Feeney
  Kevin Mourgos
  Ki Gee
  Laura Bissot
  Martha Sullivan
  Matthew Weiss
  Michael Rogers
  Mozhe Atkinson
  Nandita Sarchand
  Payam Kaufling
  Peter Vargas
  Randall Matos
  Randall Perkins
  Renske Ladwig
  Samuel McCain
  Sarah Bell
  Shanta Vollman
  Stephen Stiles
  Steven Markle
  Timothy Gates
  TJ Olson
  Trenna Rajs
  Vance Jones
  Winston Taylor

2. megoldás

A faKeszit2() függvénynél alkalmazkodunk ahhoz, hogy a JTree vizuális komponenshez DefaultTreeModel observable típusú modell szükséges, így ezzel térünk vissza (faModell). A fa csomópontjai DefaultMutableTreeNode osztályú objektumok lesznek, amelyeknek a userObject tulajdonsága szükség esetén manipulálható. Az 1 blokkban beszúrjuk a fa gyökerét (faGyoker), amihez a későbbiekben csatlakozik a fa többi eleme. A 2. blokkban megjegyezzük az aktuális részleget és előkészítjük – megjelenítendő szöveg nélkül – a faReszleg csomópontot. A 3. blokkban fabeli csomópontként a fa 1. szintjén megjelenő részleghez névtelenül hozzáadjuk a fa 2. szintjére kerülő – aktuális részleghez tartozó – alkalmazottak nevét. A 4. blokkban utólag módosítjuk a faReszleg csomópont megjelenítendő szövegét. Az aktuális részleg létszámát itt sem kell külön megszámolni, mert a faReszleg-től elkérhető (getChildCount()). Az 5. blokkban itt sincs különösebb teendőnk. 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public DefaultTreeModel faKeszit2(ArrayList<Alkalmazott> lista) {
  //1
  DefaultMutableTreeNode faGyoker=
    new DefaultMutableTreeNode("Cég ("+lista.size()+" fő)");
  DefaultTreeModel faModell=new DefaultTreeModel(faGyoker);
  int i=0;
  while(i<lista.size()) {
    //2
    String aktReszleg=lista.get(i).getReszleg();
    DefaultMutableTreeNode faReszleg=new DefaultMutableTreeNode();
    while(i<lista.size() && lista.get(i).getReszleg().equals(aktReszleg)) {
      //3
      faReszleg.add(new DefaultMutableTreeNode(lista.get(i).getNev()));
      i++;
    }
    //4
    faReszleg.setUserObject(
      aktReszleg+" ("+faReszleg.getChildCount()+" fő)");
    faGyoker.add(faReszleg);
  }
  //5
  return faModell;
}

A 2. megoldás eredménye

Fát építünk, képernyőkép

A bejegyzéshez tartozó teljes forráskódot ILIAS e-learning tananyagban tesszük elérhetővé tanfolyamaink résztvevői számára.

Attól függően, hogyan jutunk hozzá a megjelenítéshez szükséges adatokhoz, több tanfolyamunkhoz is kapcsolódik a feladat és a modell rétegben mindig másképpen tervezünk és implementálunk:

  • A Java SE szoftverfejlesztő tanfolyam 45-48. óra: Adatbázis-kezelés JDBC alapon, 1. rész alkalmán hagyományos SQL lekérdező utasítást készítünk JDBC környezetben.
  • A Java EE szoftverfejlesztő tanfolyam 25-32. óra: Adatbázis-kezelés JPA alapon alkalommal a perzisztencia szolgáltatásait vetjük be.
  • A Java adatbázis-kezelő tanfolyam 13-16. óra: Konzolos kliensalkalmazás fejlesztése JDBC alapon, 1. rész, 33-36. óra: Grafikus kliensalkalmazás fejlesztése JDBC alapon, 2. rész alkalmain hierarchikus lekérdezéseket használunk.

Szólj hozzá!