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