| Jasen.java |
1 package kerho;
2
3 import java.io.*;
4 import java.util.Comparator;
5 import fi.jyu.mit.ohj2.Mjonot;
6 import kanta.*;
7
8 /**
9 * Kerhon jäsen joka osaa mm. itse huolehtia tunnusNro:staan.
10 * Jäsenen käsittely kenttätaulukon avulla.
11 * Jäsen osaa palautta i:n kentän arvon ja kysymyksen.
12 *
13 * @author Vesa Lappalainen
14 * @version 1.0, 22.02.2003
15 * @version 1.3, 02.04.2003
16 * @version 1.4, 01.04.2008
17 * @version 1.5, 01.01.2011
18 */
19 public class Jasen implements Cloneable {
20 private Kentta kentat[] = { // valitettavasti ei voi olla final
21 // vaikka pitäisi, clone estää tämän :-(
22 new IntKentta("id"),
23 new JonoKentta("nimi"),
24 new HetuKentta("hetu", new HetuTarkistus()),
25 new JonoKentta("katuosoite"),
26 new JonoKentta("postinumero", new SisaltaaTarkistaja(SisaltaaTarkistaja.NUMEROT)),
27 new JonoKentta("postiosoite"),
28 new PuhelinKentta("kotipuhelin"),
29 new PuhelinKentta("työpuhelin"),
30 new JonoKentta("autopuhelin", new RegExpTarkistaja("[- 0-9]*")),
31 new IntKentta("liittymisvuosi"),
32 new RahaKentta("jäsenmaksu"),
33 new RahaKentta("maksettumaksu"),
34 new JonoKentta("lisätietoja"),
35 new JonoKentta("email"),
36 };
37
38 private static int seuraavaNro = 1;
39
40
41 /**
42 * @return jäsenen nimi
43 * @example
44 * <pre name="test">
45 * Jasen aku = new Jasen();
46 * aku.vastaaAkuAnkka();
47 * aku.getNimi() =R= "Ankka Aku .*"
48 * </pre>
49 */
50 public String getNimi() {
51 return anna(1);
52 }
53
54 /**
55 * Luokka joka vertaa kahta jäsentä keskenään
56 */
57 public static class Vertailija implements Comparator<Jasen> {
58
59 private final int kenttanro;
60
61
62 /**
63 * Alustetaan vertailija vertailemaan tietyn kentän perusteella
64 * @param k vertailtavan kentän indeksi.
65 */
66 public Vertailija(int k) {
67 this.kenttanro = k;
68 }
69
70
71 /**
72 * Verrataana kahta jäsentä keskenään.
73 * @param j1 1. verrattava jäsen
74 * @param j2 2. verrattava jäsen
75 * @return <0 jos j1 < j2, == 0 jos j1 == j2 ja muuten >0
76 */
77 @Override
78 public int compare(Jasen j1, Jasen j2) {
79 String s1 = j1.getAvain(kenttanro);
80 String s2 = j2.getAvain(kenttanro);
81
82 return s1.compareTo(s2);
83
84 }
85
86 }
87
88
89 /**
90 * Palauttaa jäsenen kenttien lukumäärän
91 * @return kenttien lukumäärä
92 */
93 public int getKenttia() {
94 return kentat.length;
95 }
96
97
98 /**
99 * Eka kenttä joka on mielekäs kysyttäväksi
100 * @return eknn kentän indeksi
101 */
102 public int ekaKentta() {
103 return 1;
104 }
105
106
107 /**
108 * Alustetaan jäsenen merkkijono-attribuuti tyhjiksi jonoiksi
109 * ja tunnusnro = 0.
110 */
111 public Jasen() {
112 // Toistaiseksi ei tarvita mitään
113 }
114
115
116 /**
117 * Antaa k:n kentän sisällön merkkijonona
118 * @param k monenenko kentän sisältö palautetaan
119 * @return kentän sisältö merkkijonona
120 */
121 public String anna(int k) {
122 try {
123 return kentat[k].toString();
124 } catch (Exception ex) {
125 return "";
126 }
127 }
128
129
130 /**
131 * Antaa k:n kentän sisällön avain-merkkijonona
132 * jonka perusteella voi lajitella
133 * @param k monenenko kentän sisältö palautetaan
134 * @return kentän sisältö merkkijonona
135 *
136 * @example
137 * <pre name="test">
138 * Jasen aku = new Jasen();
139 * aku.parse(" 1 | Ankka Aku | 030201-111C");
140 * aku.getAvain(0) === " 1";
141 * aku.getAvain(1) === "ANKKA AKU";
142 * aku.getAvain(2) === "010203-111C";
143 * aku.getAvain(20) === "";
144 * </pre>
145 */
146 public String getAvain(int k) {
147 try {
148 return kentat[k].getAvain();
149 } catch (Exception ex) {
150 return "";
151 }
152 }
153
154
155 /**
156 * Asettaa k:n kentän arvoksi parametrina tuodun merkkijonon arvon
157 * @param k kuinka monennen kentän arvo asetetaan
158 * @param jono jonoa joka asetetaan kentän arvoksi
159 * @return null jos asettaminen onnistuu, muuten vastaava virheilmoitus.
160 * @example
161 * <pre name="test">
162 * Jasen jasen = new Jasen();
163 * jasen.aseta(1,"Ankka Aku") === null;
164 * jasen.aseta(2,"kissa") =R= "Hetu liian lyhyt"
165 * jasen.aseta(2,"030201-1111") === "Tarkistusmerkin kuuluisi olla C";
166 * </pre>
167 */
168 public String aseta(int k, String jono) {
169 try {
170 return kentat[k].aseta(jono.trim());
171 } catch (Exception ex) {
172 return "Virhe: " + ex.getMessage();
173 }
174 }
175
176
177 /**
178 * Palauttaa k:tta jäsenen kenttää vastaavan kysymyksen
179 * @param k kuinka monennen kentän kysymys palautetaan (0-alkuinen)
180 * @return k:netta kenttää vastaava kysymys
181 * <pre name="test">
182 * Jasen jasen = new Jasen();
183 * jasen.getKysymys(1) === "nimi";
184 * jasen.getKysymys(2) === "hetu";
185 * </pre>
186 */
187 public String getKysymys(int k) {
188 try {
189 return kentat[k].getKysymys();
190 } catch (Exception ex) {
191 return "Ääliö";
192 }
193 }
194
195
196 /**
197 * Arvotaan satunnainen kokonaisluku välille [ala,yla]
198 * @param ala arvonnan alaraja
199 * @param yla arvonnan yläraja
200 * @return satunnainen luku väliltä [ala,yla]
201 */
202 public static int rand(int ala, int yla) {
203 double n = (yla - ala) * Math.random() + ala;
204 return (int)Math.round(n);
205 }
206
207
208 /**
209 * Apumetodi, jolla saadaan täytettyä testiarvot jäsenelle.
210 * @param apuhetu hetu joka annetaan henkilölle
211 */
212 public void vastaaAkuAnkka(String apuhetu) {
213 /*
214 nimi = "Ankka Aku";
215 hetu = apuhetu;
216 katuosoite = "Ankkakuja 6";
217 postinumero = "12345";
218 postiosoite = "ANKKALINNA";
219 kotipuhelin = "12-1234";
220 tyopuhelin = "";
221 autopuhelin = "";
222 liittymisvuosi = 1996;
223 jmaksu = 50.00;
224 maksu = 30.00;
225 lisatietoja = "Velkaa Roopelle";
226 */
227 kentat[1].aseta("Ankka Aku " + kanta.HetuTarkistus.rand(1000, 9999));
228 kentat[2].aseta(apuhetu);
229 kentat[3].aseta("Ankkakuja 6");
230 kentat[4].aseta("12345");
231 kentat[5].aseta("ANKKALINNA");
232 kentat[6].aseta("12-1234");
233 kentat[7].aseta("");
234 kentat[8].aseta("");
235 kentat[9].aseta("1996");
236 kentat[10].aseta("50");
237 kentat[11].aseta("30");
238 kentat[12].aseta("Velkaa Roopelle");
239 }
240
241
242 /**
243 * Apumetodi, jolla saadaan täytettyä testiarvot jäsenelle.
244 * Henkilötunnus arvotaan, jotta kahdella jäsenellä ei olisi
245 * samoja tietoja.
246 */
247 public void vastaaAkuAnkka() {
248 String apuhetu = kanta.HetuTarkistus.arvoHetu();
249 vastaaAkuAnkka(apuhetu);
250 }
251
252
253 /**
254 * Tulostetaan henkilön tiedot
255 * @param out tietovirta johon tulostetaan
256 */
257 public void tulosta(PrintWriter out) {
258 int pisin = 0;
259 for (Kentta kentta : kentat)
260 if (kentta.getKysymys().length() > pisin)
261 pisin = kentta.getKysymys().length();
262
263 for (Kentta kentta : kentat)
264 out.println(Mjonot.fmt(kentta.getKysymys(), -pisin - 1) +
265 ": " + kentta.toString());
266 /*
267 out.println(Mjonot.fmt(tunnusnro,3,'0')+ " " + nimi + " " + hetu);
268 out.println(" " + katuosoite + " " + postinumero + " " + postiosoite);
269 out.println(" k: " + kotipuhelin +
270 " t: " + tyopuhelin +
271 " a: " + autopuhelin);
272 out.print(" Liittynyt " + liittymisvuosi + ".");
273 out.println(" Jäsenmaksu " + Mjonot.fmt(jmaksu,4,2) + " mk." +
274 " Maksettu " + Mjonot.fmt(maksu,4,2) + " mk.");
275 out.println(" " + lisatietoja);
276 */
277 }
278
279
280 /**
281 * Tulostetaan henkilön tiedot
282 * @param os tietovirta johon tulostetaan
283 */
284 public void tulosta(OutputStream os) {
285 tulosta(new PrintStream(os));
286 }
287
288
289 /**
290 * Tulostetaan henkilön tiedot
291 * @param out tietovirta johon tulostetaan
292 */
293 public void tulosta(PrintStream out) {
294 tulosta(new PrintWriter(out, true)); // ilman autoflushia ei mitään
295 // tulostu!
296 }
297
298
299 /**
300 * Antaa jäsenelle seuraavan rekisterinumeron.
301 * @return jäsenen uusi tunnusNro
302 * @example
303 * <pre name="test">
304 * Jasen aku1 = new Jasen();
305 * aku1.getTunnusnro() === 0;
306 * aku1.rekisteroi();
307 * Jasen aku2 = new Jasen();
308 * aku2.rekisteroi();
309 * int n1 = aku1.getTunnusnro();
310 * int n2 = aku2.getTunnusnro();
311 * n1 === n2-1;
312 * </pre>
313 */
314 public int rekisteroi() {
315 ((IntKentta)(kentat[0])).setValue(seuraavaNro);
316 seuraavaNro++;
317 return getTunnusnro();
318 }
319
320
321 /**
322 * Palauttaa jäsenen tunnusnumeron.
323 * @return jäsenen tunnusnumero
324 */
325 public int getTunnusnro() {
326 return ((IntKentta)(kentat[0])).getValue();
327 }
328
329
330 /**
331 * Palauttaa jäsenen tiedot merkkijonona jonka voi tallentaa tiedostoon.
332 * @return jäsen tolppaeroteltuna merkkijonona
333 * @example
334 * <pre name="test">
335 * Jasen jasen = new Jasen();
336 * jasen.parse(" 3 | Ankka Aku | 030201-111C");
337 * jasen.toString().startsWith("3|Ankka Aku|030201-111C|") === true; // on enemmäkin kuin 3 kenttää, siksi loppu |
338 * </pre>
339 */
340 @Override
341 public String toString() {
342 StringBuffer sb = new StringBuffer("");
343 String erotin = "";
344 for (int k = 0; k < getKenttia(); k++) {
345 sb.append(erotin);
346 sb.append(anna(k));
347 erotin = "|";
348 }
349 return sb.toString();
350 }
351
352
353 /**
354 * Selvittää jäsenen tiedot | erotellusta merkkijonosta
355 * Pitää huolen että seuraavaNro on suurempi kuin tuleva tunnusNro.
356 * @param rivi josta jäsenen tiedot otetaan
357 *
358 * @example
359 * <pre name="test">
360 * Jasen jasen = new Jasen();
361 * jasen.parse(" 3 | Ankka Aku | 030201-111C");
362 * jasen.getTunnusnro() === 3;
363 * jasen.toString().startsWith("3|Ankka Aku|030201-111C|") === true; // on enemmäkin kuin 3 kenttää, siksi loppu |
364 *
365 * jasen.rekisteroi();
366 * int n = jasen.getTunnusnro();
367 * jasen.parse(""+(n+20)); // Otetaan merkkijonosta vain tunnusnumero
368 * jasen.rekisteroi(); // ja tarkistetaan että seuraavalla kertaa tulee yhtä isompi
369 * jasen.getTunnusnro() === n+20+1;
370 *
371 * </pre>
372 */
373 public void parse(String rivi) {
374 StringBuffer sb = new StringBuffer(rivi);
375 for (int k = 0; k < getKenttia(); k++)
376 aseta(k, Mjonot.erota(sb, '|'));
377 if (getTunnusnro() >= seuraavaNro) seuraavaNro = getTunnusnro() + 1;
378 }
379
380
381 /**
382 * Tehdään identtinen klooni jäsenestä
383 * @return Object kloonattu jäsen
384 * @example
385 * <pre name="test">
386 * #THROWS CloneNotSupportedException
387 * Jasen jasen = new Jasen();
388 * jasen.parse(" 3 | Ankka Aku | 123");
389 * Jasen kopio = jasen.clone();
390 * kopio.toString() === jasen.toString();
391 * jasen.parse(" 4 | Ankka Tupu | 123");
392 * kopio.toString().equals(jasen.toString()) === false;
393 * </pre>
394 */
395 @Override
396 public Jasen clone() throws CloneNotSupportedException { // NOPMD
397 Jasen uusi;
398 uusi = (Jasen)super.clone();
399 uusi.kentat = kentat.clone();
400
401 for (int k = 0; k < getKenttia(); k++)
402 uusi.kentat[k] = kentat[k].clone();
403 return uusi;
404 }
405
406
407 /**
408 * Tutkii onko jäsenen tiedot samat kuin parametrina tuodun jäsenen tiedot
409 * @param jasen jäsen johon verrataan
410 * @return true jos kaikki tiedot samat, false muuten
411 * @example
412 * <pre name="test">
413 * Jasen jasen1 = new Jasen();
414 * jasen1.parse(" 3 | Ankka Aku | 030201-111C");
415 * Jasen jasen2 = new Jasen();
416 * jasen2.parse(" 3 | Ankka Aku | 030201-111C");
417 * Jasen jasen3 = new Jasen();
418 * jasen3.parse(" 3 | Ankka Aku | 030201-115H");
419 *
420 * jasen1.equals(jasen2) === true;
421 * jasen2.equals(jasen1) === true;
422 * jasen1.equals(jasen3) === false;
423 * jasen3.equals(jasen2) === false;
424 * </pre>
425 */
426 public boolean equals(Jasen jasen) { // NOPMD
427 for (int k = 0; k < getKenttia(); k++)
428 if (!anna(k).equals(jasen.anna(k))) return false;
429 return true;
430 }
431
432
433 /**
434 * @see java.lang.Object#equals(java.lang.Object)
435 * @example
436 * <pre name="test">
437 * Jasen jasen1 = new Jasen();
438 * jasen1.parse(" 3 | Ankka Aku | 030201-111C");
439 * jasen1.equals("kissa") === false;
440 * </pre>
441 */
442 @Override
443 public boolean equals(Object o) {
444 if (o instanceof Jasen) return equals((Jasen)o);
445 return false;
446 }
447
448
449 /**
450 * @see java.lang.Object#hashCode()
451 */
452 @Override
453 public int hashCode() {
454 return anna(ekaKentta()).hashCode();
455 }
456
457
458 /**
459 * Testiohjelma jäsenelle.
460 * @param args ei käytössä
461 */
462 public static void main(String args[]) {
463 Jasen aku = new Jasen(), aku2 = new Jasen();
464 aku.rekisteroi();
465 aku2.rekisteroi();
466 aku.tulosta(System.out);
467 aku.vastaaAkuAnkka();
468 aku.tulosta(System.out);
469
470 aku2.vastaaAkuAnkka();
471 aku2.tulosta(System.out);
472
473 aku2.vastaaAkuAnkka();
474 aku2.tulosta(System.out);
475 }
476
477 }
478