| Jasenet.java |
1 package kerho;
2
3 import java.io.BufferedReader;
4 import java.io.IOException;
5 import java.io.PrintWriter;
6 import java.io.File;
7 import java.util.ArrayList;
8 import java.util.Collection;
9 import java.util.Collections;
10 import java.util.Iterator;
11 import java.util.List;
12 import java.util.NoSuchElementException;
13 import fi.jyu.mit.ohj2.Tiedosto;
14 import fi.jyu.mit.ohj2.WildChars;
15
16 /**
17 * Kerhon jäsenistä joka osaa mm. lisätä uuden jäsenen
18 *
19 * @author Vesa Lappalainen
20 * @version 1.0, 22.02.2003
21 */
22 public class Jasenet implements Iterable<Jasen> {
23 private boolean muutettu = false;
24 private String tiedostonPerusNimi = "";
25 private String kokoNimi = "";
26
27 private static final int MAX_JASENIA = 50;
28 private int lkm = 0;
29
30 /**
31 * Taulukko jäsenistä
32 */
33 private Jasen alkiot[] = new Jasen[MAX_JASENIA];
34
35
36 /**
37 * Oletusmuodostaja
38 */
39 public Jasenet() {
40 // Attribuuttien oma alustus riittää
41 }
42
43
44 /**
45 * Muodostaja jolla maxkoko voidaan asettaa
46 * @param koko jäsenistön maxkoko
47 *
48 */
49 public Jasenet(int koko) {
50 alkiot = new Jasen[koko];
51 }
52
53
54 /**
55 * Lisää uuden jäsenen tietorakenteeseen. Ottaa jäsenen omistukseensa.
56 * @param jasen lisätäävän jäsenen viite. Huom tietorakenne muuttuu omistajaksi
57 * @throws SailoException jos tietorakenne on jo täynnä
58 * @example
59 * <pre name="test">
60 * #THROWS SailoException
61 * #PACKAGEIMPORT
62 * Jasenet jasenet = new Jasenet(5);
63 * Jasen aku1 = new Jasen(), aku2 = new Jasen();
64 * aku1.rekisteroi(); aku2.rekisteroi();
65 * jasenet.getLkm() === 0;
66 * jasenet.lisaa(aku1); jasenet.getLkm() === 1;
67 * jasenet.lisaa(aku2); jasenet.getLkm() === 2;
68 * jasenet.lisaa(aku1); jasenet.getLkm() === 3;
69 * jasenet.anna(0) === aku1;
70 * jasenet.anna(1) === aku2;
71 * jasenet.anna(2) === aku1;
72 * jasenet.anna(1) == aku1 === false;
73 * jasenet.anna(1) == aku2 === true;
74 * jasenet.anna(3) === aku1; #THROWS IndexOutOfBoundsException
75 * jasenet.lisaa(aku1); jasenet.getLkm() === 4;
76 * jasenet.lisaa(aku1); jasenet.getLkm() === 5;
77 * jasenet.lisaa(aku1); #THROWS SailoException
78 * </pre>
79 */
80 public void lisaa(Jasen jasen) throws SailoException {
81 muutettu = true;
82 if (lkm >= alkiot.length) throw new SailoException("Liikaa alkioita");
83 alkiot[lkm] = jasen;
84 lkm++;
85 }
86
87
88 /**
89 * Poistaa jäsenen jolla on valittu tunnusnumero
90 * @param id poistettavan jäsenen tunnusnumero
91 * @return 1 jos poistettiin, 0 jos ei löydy
92 * @example
93 * <pre name="test">
94 * #THROWS SailoException
95 * Jasenet jasenet = new Jasenet(5);
96 * Jasen aku1 = new Jasen(), aku2 = new Jasen(), aku3 = new Jasen();
97 * aku1.rekisteroi(); aku2.rekisteroi(); aku3.rekisteroi();
98 * int id1 = aku1.getTunnusnro();
99 * jasenet.lisaa(aku1); jasenet.lisaa(aku2); jasenet.lisaa(aku3);
100 * jasenet.poista(id1+1) === 1;
101 * jasenet.etsiId(id1+1) === -1; jasenet.getLkm() === 2;
102 * jasenet.poista(id1) === 1; jasenet.getLkm() === 1;
103 * jasenet.poista(id1+3) === 0; jasenet.getLkm() === 1;
104 * </pre>
105 *
106 */
107 public int poista(int id) {
108 int ind = etsiId(id);
109 if (ind < 0) return 0;
110 lkm--;
111 for (int i = ind; i < lkm; i++)
112 alkiot[i] = alkiot[i + 1];
113 alkiot[lkm] = null;
114 muutettu = true;
115 return 1;
116 }
117
118
119 /**
120 * Korvaa jäsenen tietorakenteessa. Ottaa jäsenen omistukseensa.
121 * Etsitään samalla tunnusnumerolla oleva jäsen. Jos ei läydy,
122 * niin lisätään uutena jäsenenä.
123 * @param jasen lisätäävän jäsenen viite. Huom tietorakenne muuttuu omistajaksi
124 * @throws SailoException jos tietorakennen on jo täynnä
125 * <pre name="test">
126 * #THROWS SailoException,CloneNotSupportedException
127 * #PACKAGEIMPORT
128 * Jasenet jasenet = new Jasenet();
129 * Jasen aku1 = new Jasen(), aku2 = new Jasen();
130 * aku1.rekisteroi(); aku2.rekisteroi();
131 * jasenet.getLkm() === 0;
132 * jasenet.korvaaTaiLisaa(aku1); jasenet.getLkm() === 1;
133 * jasenet.korvaaTaiLisaa(aku2); jasenet.getLkm() === 2;
134 * Jasen aku3 = aku1.clone();
135 * aku3.aseta(3,"kkk");
136 * jasenet.anna(0) == aku1 === true;
137 * jasenet.korvaaTaiLisaa(aku3); jasenet.getLkm() === 2;
138 * jasenet.anna(0) === aku3;
139 * jasenet.anna(0) == aku3 === true;
140 * jasenet.anna(0) == aku1 === false;
141 * </pre>
142 */
143 public void korvaaTaiLisaa(Jasen jasen) throws SailoException {
144 int id = jasen.getTunnusnro();
145 for (int i = 0; i < lkm; i++) {
146 if (alkiot[i].getTunnusnro() == id) {
147 alkiot[i] = jasen;
148 muutettu = true;
149 return;
150 }
151 }
152 lisaa(jasen);
153 }
154
155
156 /**
157 * Palauttaa viitteen i:teen jäseneen.
158 * @param i monennenko jäsenen viite halutaan
159 * @return viite jäseneen, jonka indeksi on i
160 * @throws IndexOutOfBoundsException jos i ei ole sallitulla alueella
161 */
162 public Jasen anna(int i) throws IndexOutOfBoundsException {
163 if (i < 0 || lkm <= i) throw new IndexOutOfBoundsException("Laiton indeksi: " + i);
164 return alkiot[i];
165 }
166
167
168 /**
169 * Palauttaa viitteen i:teen jäseneen.
170 * @param i monennenko jäsenen viite halutaan
171 * @return viite jäseneen, jonka indeksi on i
172 * @throws IndexOutOfBoundsException jos i ei ole sallitulla alueella
173 */
174 public Object annaObj(int i) throws IndexOutOfBoundsException {
175 if (i < 0 || lkm <= i) throw new IndexOutOfBoundsException("Laiton indeksi: " + i);
176 return alkiot[i];
177 }
178
179
180 /*
181 private void koe() {
182 Object eka = annaObj(0);
183 if ( eka instanceof Jasen ) {
184 Jasen jasen = (Jasen)eka;
185 }
186 }
187 */
188
189 /**
190 * Lukee jäsenistön tiedostosta.
191 * @param tied tiedoston nimen alkuosa
192 * @throws SailoException jos lukeminen epäonnistuu
193 *
194 * @example
195 * <pre name="test">
196 * #THROWS SailoException
197 * #import java.io.File;
198 *
199 * Jasenet jasenet = new Jasenet();
200 * Jasen aku1 = new Jasen(), aku2 = new Jasen();
201 * aku1.vastaaAkuAnkka();
202 * aku2.vastaaAkuAnkka();
203 * String tiedNimi = "testikelmit";
204 * File ftied = new File(tiedNimi+".dat");
205 * ftied.delete();
206 * jasenet.lueTiedostosta(tiedNimi); #THROWS SailoException
207 * jasenet.lisaa(aku1);
208 * jasenet.lisaa(aku2);
209 * jasenet.talleta();
210 * jasenet = new Jasenet(); // Poistetaan vanhat luomalla uusi
211 * jasenet.lueTiedostosta(tiedNimi); // johon ladataan tiedot tiedostosta.
212 * Iterator<Jasen> i = jasenet.iterator();
213 * i.next().toString() === aku1.toString();
214 * i.next().toString() === aku2.toString();
215 * i.hasNext() === false;
216 * jasenet.lisaa(aku2);
217 * jasenet.talleta();
218 * ftied.delete() === true;
219 * File fbak = new File(tiedNimi+".bak");
220 * fbak.delete() === true;
221 * </pre>
222 */
223 public void lueTiedostosta(String tied) throws SailoException {
224 setTiedostonPerusNimi(tied);
225 BufferedReader fi = Tiedosto.avaa_lukemista_varten(getTiedostonNimi());
226 if (fi == null) throw new SailoException("Tiedosto " + getTiedostonNimi() + " ei aukea");
227
228 try {
229 kokoNimi = fi.readLine();
230 if (kokoNimi == null) throw new SailoException("Kerhon nimi puuttuu");
231 String rivi = fi.readLine();
232 if (rivi == null) throw new SailoException("Maksimikoko puuttuu");
233 // int maxKoko = Mjonot.erotaInt(rivi,10); // tehdään jotakin
234
235 while ((rivi = fi.readLine()) != null) { // NOPMD
236 rivi = rivi.trim();
237 if ("".equals(rivi) || rivi.charAt(0) == ';') continue;
238 Jasen jasen = new Jasen(); // NOPMD, pakko luoda täällä
239 jasen.parse(rivi); // voisi olla virhekäsittely
240 lisaa(jasen);
241 }
242 muutettu = false;
243
244 } catch (IOException e) {
245 throw new SailoException("Ongelmia tiedoston kanssa: " + e.getMessage()); // NOPMD
246 } finally {
247 try {
248 fi.close();
249 } catch (IOException e) {
250 throw new SailoException("Tiedoston sulkeminen ei onnistu: " + e.getMessage()); // NOPMD
251 }
252 }
253 }
254
255
256 /**
257 * Tallentaa jäsenistän tiedostoon.
258 * Tiedoston muoto:
259 * <pre>
260 * Kelmien kerho
261 * 20
262 * ; kommenttirivi
263 * 2|Ankka Aku|121103-706Y|Ankkakuja 6|12345|ANKKALINNA|12-1234|||1996|50.0|30.0|Velkaa Roopelle
264 * 3|Ankka Tupu|121153-706Y|Ankkakuja 6|12345|ANKKALINNA|12-1234|||1996|50.0|30.0|Velkaa Roopelle
265 * </pre>
266 * @throws SailoException jos talletus epäonnistuu
267 */
268 public void talleta() throws SailoException {
269 if (!muutettu) return;
270
271 File fbak = new File(getBakNimi());
272 File ftied = new File(getTiedostonNimi());
273 fbak.delete(); // if .. System.err.println("Ei voi tuhota");
274 ftied.renameTo(fbak); // if .. System.err.println("Ei voi nimetä");
275
276 PrintWriter fo = Tiedosto.avaa_kirjoittamista_varten(ftied.getName());
277 if (fo == null) throw new SailoException("Tiedosto " + ftied.getName() + " ei aukea");
278 try {
279 fo.println(getKokoNimi());
280 fo.println(alkiot.length);
281 for (Jasen jasen : this) {
282 fo.println(jasen.toString());
283 }
284 //} catch ( IOException e ) { // ei heitä poikkeusta
285 // throw new SailoException("Tallettamisessa ongelmia: " + e.getMessage()); // NOPMD
286 } finally {
287 fo.close();
288 }
289
290 muutettu = false;
291 }
292
293
294 /**
295 * Palauttaa Kerhon koko nimen
296 * @return Kerhon koko nimi merkkijononna
297 */
298 public String getKokoNimi() {
299 return kokoNimi;
300 }
301
302
303 /**
304 * Palauttaa kerhon jäsenten lukumäärän
305 * @return jäsenten lukumäärä
306 */
307 public int getLkm() {
308 return lkm;
309 }
310
311
312 /**
313 * Asettaa tiedoston perusnimen ilan tarkenninta
314 * @param tied tallennustiedoston perusnimi
315 */
316 public void setTiedostonPerusNimi(String tied) {
317 tiedostonPerusNimi = tied;
318 }
319
320
321 /**
322 * Palauttaa tiedoston nimen, jota käytetään tallennukseen
323 * @return tallennustiedoston nimi
324 */
325 public String getTiedostonPerusNimi() {
326 return tiedostonPerusNimi;
327 }
328
329
330 /**
331 * Palauttaa tiedoston nimen, jota käytetään tallennukseen
332 * @return tallennustiedoston nimi
333 */
334 public String getTiedostonNimi() {
335 return tiedostonPerusNimi + ".dat";
336 }
337
338
339 /**
340 * Palauttaa varakopiotiedoston nimen
341 * @return varakopiotiedoston nimi
342 */
343 public String getBakNimi() {
344 return tiedostonPerusNimi + ".bak";
345 }
346
347 /**
348 * Luokka jäsenten iteroimiseksi.
349 * @example
350 * <pre name="test">
351 * #THROWS SailoException
352 * #PACKAGEIMPORT
353 * #import java.util.*;
354 *
355 * Jasenet jasenet = new Jasenet();
356 * Jasen aku1 = new Jasen(), aku2 = new Jasen();
357 * aku1.rekisteroi(); aku2.rekisteroi();
358 *
359 * jasenet.lisaa(aku1);
360 * jasenet.lisaa(aku2);
361 * jasenet.lisaa(aku1);
362 *
363 * StringBuffer ids = new StringBuffer(30);
364 * for (Jasen jasen:jasenet) // Kokeillaan for-silmukan toimintaa
365 * ids.append(" "+jasen.getTunnusnro()); // NOPMD
366 *
367 * String tulos = " " + aku1.getTunnusnro() + " " + aku2.getTunnusnro() + " " + aku1.getTunnusnro();
368 *
369 * ids.toString() === tulos;
370 *
371 * ids = new StringBuffer(30);
372 * for (Iterator<Jasen> i=jasenet.iterator(); i.hasNext(); ) { // ja iteraattorin toimintaa
373 * Jasen jasen = i.next();
374 * ids.append(" "+jasen.getTunnusnro()); // NOPMD
375 * }
376 *
377 * ids.toString() === tulos;
378 *
379 * Iterator<Jasen> i=jasenet.iterator();
380 * i.next() == aku1 === true;
381 * i.next() == aku2 === true;
382 * i.next() == aku1 === true;
383 *
384 * i.next(); #THROWS NoSuchElementException
385 *
386 * </pre>
387 */
388 public class JasenetIterator implements Iterator<Jasen> {
389 private int kohdalla = -1;
390
391
392 /**
393 * Onko olemassa vielä seuraavaa jäsentä
394 * @see java.util.Iterator#hasNext()
395 * @return true jos on vielä jäseniä
396 */
397 @Override
398 public boolean hasNext() {
399 // if ( kohdalla + 1 >= lkm ) return false;
400 // return true;
401 return kohdalla + 1 < getLkm();
402 }
403
404
405 /**
406 * Annetaan seuraava jäsen
407 * @return seuraava jäsen
408 * @throws NoSuchElementException jos seuraava alkiota ei enää ole
409 * @see java.util.Iterator#next()
410 */
411 @Override
412 public Jasen next() throws NoSuchElementException {
413 if (!hasNext()) throw new NoSuchElementException("Ei oo");
414 kohdalla++;
415 return anna(kohdalla);
416 }
417
418
419 /**
420 * Tuhoamista ei ole toteutettu
421 * @throws UnsupportedOperationException aina
422 * @see java.util.Iterator#remove()
423 */
424 @Override
425 public void remove() throws UnsupportedOperationException {
426 throw new UnsupportedOperationException("Me ei poisteta");
427 }
428 }
429
430
431 /**
432 * Palautetaan iteraattori jäsenistään.
433 * @return jäsen iteraattori
434 */
435 @Override
436 public Iterator<Jasen> iterator() {
437 // return alkiot.iterator();
438 return new JasenetIterator();
439 }
440
441
442
443
444 /**
445 * Palauttaa "taulukossa" hakuehtoon vastaavien jäsenten viitteet
446 * @param hakuehto hakuehto
447 * @param k etsittävän kentän indeksi
448 * @return tietorakenteen löytyneistä jäsenistä
449 * @example
450 * <pre name="test">
451 * #THROWS SailoException
452 * Jasenet jasenet = new Jasenet();
453 * Jasen jasen1 = new Jasen(); jasen1.parse("1|Ankka Aku|030201-115H|Ankkakuja 6|");
454 * Jasen jasen2 = new Jasen(); jasen2.parse("2|Ankka Tupu||030552-123B|");
455 * Jasen jasen3 = new Jasen(); jasen3.parse("3|Susi Sepe|121237-121V||131313|Perämetsä");
456 * Jasen jasen4 = new Jasen(); jasen4.parse("4|Ankka Iines|030245-115V|Ankkakuja 9");
457 * Jasen jasen5 = new Jasen(); jasen5.parse("5|Ankka Roope|091007-408U|Ankkakuja 12");
458 * jasenet.lisaa(jasen1); jasenet.lisaa(jasen2); jasenet.lisaa(jasen3); jasenet.lisaa(jasen4); jasenet.lisaa(jasen5);
459 * List<Jasen> loytyneet;
460 * loytyneet = (List<Jasen>)jasenet.etsi("*s*",1);
461 * loytyneet.size() === 2;
462 * loytyneet.get(0) == jasen4 === true;
463 * loytyneet.get(1) == jasen3 === true;
464 *
465 * loytyneet = (List<Jasen>)jasenet.etsi("*7-*",2);
466 * loytyneet.size() === 2;
467 * loytyneet.get(0) == jasen5 === true;
468 * loytyneet.get(1) == jasen3 === true;
469 * </pre>
470 */
471 public Collection<Jasen> etsi(String hakuehto, int k) {
472 List<Jasen> loytyneet = new ArrayList<Jasen>();
473 for (Jasen jasen : this) {
474 // if ( jasen.getNimi().toUpperCase().startsWith(hakuehto.toUpperCase()) ) loytyneet.add(jasen); // NOPMD
475 // if ( jasen.anna(k).toUpperCase().startsWith(hakuehto.toUpperCase()) ) loytyneet.add(jasen); // NOPMD
476 if (WildChars.onkoSamat(jasen.anna(k), hakuehto)) loytyneet.add(jasen); // NOPMD
477 }
478 Collections.sort(loytyneet, new Jasen.Vertailija(k));
479 return loytyneet;
480 }
481
482
483
484 /**
485 * Etsii jäsenen id:n perusteella
486 * @param id tunnusnumero, jonka mukaan etsitään
487 * @return jäsen jolla etsittävä id tai null
488 * <pre name="test">
489 * #THROWS SailoException
490 * Jasenet jasenet = new Jasenet(5);
491 * Jasen aku1 = new Jasen(), aku2 = new Jasen(), aku3 = new Jasen();
492 * aku1.rekisteroi(); aku2.rekisteroi(); aku3.rekisteroi();
493 * int id1 = aku1.getTunnusnro();
494 * jasenet.lisaa(aku1); jasenet.lisaa(aku2); jasenet.lisaa(aku3);
495 * jasenet.annaId(id1 ) == aku1 === true;
496 * jasenet.annaId(id1+1) == aku2 === true;
497 * jasenet.annaId(id1+2) == aku3 === true;
498 * </pre>
499 */
500 public Jasen annaId(int id) {
501 for (Jasen jasen : this) {
502 if (id == jasen.getTunnusnro()) return jasen;
503 }
504 return null;
505 }
506
507
508 /**
509 * Etsii jäsenen id:n perusteella
510 * @param id tunnusnumero, jonka mukaan etsitään
511 * @return löytyneen jäsenen indeksi tai -1 jos ei löydy
512 * <pre name="test">
513 * #THROWS SailoException
514 * Jasenet jasenet = new Jasenet(5);
515 * Jasen aku1 = new Jasen(), aku2 = new Jasen(), aku3 = new Jasen();
516 * aku1.rekisteroi(); aku2.rekisteroi(); aku3.rekisteroi();
517 * int id1 = aku1.getTunnusnro();
518 * jasenet.lisaa(aku1); jasenet.lisaa(aku2); jasenet.lisaa(aku3);
519 * jasenet.etsiId(id1+1) === 1;
520 * jasenet.etsiId(id1+2) === 2;
521 * </pre>
522 */
523 public int etsiId(int id) {
524 for (int i = 0; i < lkm; i++)
525 if (id == alkiot[i].getTunnusnro()) return i;
526 return -1;
527 }
528
529
530 /**
531 * Testiohjelma jäseniställe
532 * @param args ei käytässä
533 */
534 public static void main(String args[]) {
535 Jasenet jasenet = new Jasenet();
536
537 Jasen aku = new Jasen(), aku2 = new Jasen();
538 aku.rekisteroi();
539 aku.vastaaAkuAnkka();
540 aku2.rekisteroi();
541 aku2.vastaaAkuAnkka();
542
543 try {
544 jasenet.lisaa(aku);
545 jasenet.lisaa(aku2);
546
547 System.out.println("============= Jäsenet testi =================");
548
549 for (Iterator<Jasen> i = jasenet.iterator(); i.hasNext();) {
550 // Jasen jasen = jasenet.anna(i);
551 // System.out.println("Jäsen nro: " + i);
552 Jasen jasen = i.next();
553 jasen.tulosta(System.out);
554 }
555 jasenet.anna(100);
556
557 } catch (IndexOutOfBoundsException ex) {
558 System.out.println(ex.getMessage());
559 } catch (SailoException ex) {
560 System.out.println(ex.getMessage());
561 }
562 }
563
564 }
565