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