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