PerusTietue.java |
1 package kanta; 2 3 import java.io.*; 4 5 import fi.jyu.mit.ohj2.Mjonot; 6 7 /** 8 * Tietue joka osaa mm. itse huolehtia tunnus_nro:staan. 9 * Oikean tietueen tekemiseksi tämä on perittävä ja lisättävä mm. 10 * Kentta-taulukko. 0's kenttä on aina id-numero. 11 * 12 * @author Vesa Lappalainen 13 * @version 1.0, 22.02.2003 14 * @version 1.1, 23.02.2012 15 * @example 16 * <pre name="testJAVA"> 17 * public static class Harrastus extends PerusTietue { 18 * private Kentta kentat[] = { 19 * new IntKentta("id"), 20 * new IntKentta("jäsenId"), 21 * new JonoKentta("ala"), 22 * new IntKentta("aloitusvuosi"), 23 * new IntKentta("h/vko") 24 * }; 25 * private static int seuraavaNro = 1; 26 * @Override public int ekaKentta() { return 2; } 27 * @Override public Kentta[] getKentat() { return kentat; } 28 * @Override public int getSeuraavaNro() { return seuraavaNro; } 29 * @Override protected void setSeuraavaNro(int i) { seuraavaNro = i; } 30 * @Override protected void setKentat(Kentta[] kentat) { this.kentat = kentat; } 31 * @Override public Harrastus clone() throws CloneNotSupportedException {return (Harrastus)super.clone(); } 32 * public int getJasenNro() { return ((IntKentta)getKentta(1)).getValue(); } 33 * } 34 * </pre> 35 */ 36 public abstract class PerusTietue implements Cloneable,Tietue { 37 38 /** 39 * @param i seuraava id-numero jota tästä lähiten käytetään 40 */ 41 abstract protected void setSeuraavaNro(int i); 42 43 44 /** 45 * Asetetaan kentät. Käytetään lähinnä kloonaamisessa 46 * @param kentat uudet kentät tietueelle 47 */ 48 abstract protected void setKentat(Kentta[] kentat); 49 50 51 /** 52 * @return tietueen kenttien lukumäärä 53 * @example 54 * <pre name="test"> 55 * Harrastus har = new Harrastus(); 56 * har.getKenttia() === 5; 57 * </pre> 58 */ 59 @Override 60 public int getKenttia() { 61 return getKentat().length; 62 } 63 64 65 /** 66 * @return ensimmäinen käyttäjän syötettävän kentän indeksi 67 * @example 68 * <pre name="test"> 69 * Harrastus har = new Harrastus(); 70 * har.ekaKentta() === 2; 71 * </pre> 72 */ 73 @Override 74 public int ekaKentta() { 75 return 1; 76 } 77 78 79 /** 80 * @param k Mikä kenttä halutaan 81 * @return k.s kenttä 82 * @example 83 * <pre name="test"> 84 * Harrastus har = new Harrastus(); 85 * har.parse(" 2 | 10 | Kalastus | 1949 | 22 t "); 86 * IntKentta kentta = (IntKentta)har.getKentta(3); 87 * kentta.getValue() === 1949; 88 * </pre> 89 */ 90 @Override 91 public Kentta getKentta(int k) { 92 return getKentat()[k]; 93 } 94 95 96 /** 97 * @param k minkä kentän kysymys halutaan 98 * @return valitun kentän kysymysteksti 99 * @example 100 * <pre name="test"> 101 * Harrastus har = new Harrastus(); 102 * har.getKysymys(2) === "ala"; 103 * </pre> 104 */ 105 @Override 106 public String getKysymys(int k) { 107 try { 108 return getKentta(k).getKysymys(); 109 } catch (Exception ex) { 110 return "Ääliö"; 111 } 112 } 113 114 115 /** 116 * @return kaikkien näytettävien kysymysten otsikot merkkijonotaulukkona 117 * @example 118 * <pre name="test"> 119 * #import java.util.Arrays; 120 * Harrastus har = new Harrastus(); 121 * Arrays.toString(har.getOtsikot()) =R= "\\[ala, aloitusvuosi, h/vko.*"; 122 * </pre> 123 */ 124 @Override 125 public String[] getOtsikot() { 126 int n = getKenttia() - ekaKentta(); 127 String[] otsikot = new String[n]; 128 for (int i=0,k=ekaKentta(); i<n; i++,k++) 129 otsikot[i] = getKysymys(k); 130 return otsikot; 131 } 132 133 134 /** 135 * @param k Minkä kentän sisältö halutaan 136 * @return valitun kentän sisältö 137 * @example 138 * <pre name="test"> 139 * Harrastus har = new Harrastus(); 140 * har.parse(" 2 | 10 | Kalastus | 1949 | 22 t "); 141 * har.anna(0) === "2"; 142 * har.anna(1) === "10"; 143 * har.anna(2) === "Kalastus"; 144 * har.anna(3) === "1949"; 145 * har.anna(4) === "22"; 146 * </pre> 147 */ 148 @Override 149 public String anna(int k) { 150 try { 151 return getKentta(k).toString(); 152 } catch (Exception ex) { 153 return ""; 154 } 155 } 156 157 158 /** 159 * Kentän sisältö kokonaislukuna. Jos ei ole IntKentta, 160 * niin -1. 161 * @param k Minkä kentän sisältö halutaan 162 * @return valitun kentän sisältö kokonaislukuna. 163 * @example 164 * <pre name="test"> 165 * Harrastus har = new Harrastus(); 166 * har.parse(" 2 | 10 | Kalastus | 1949 | 22 t "); 167 * har.annaInt(0) === 2; 168 * har.annaInt(1) === 10; 169 * har.annaInt(2) === -1; 170 * har.annaInt(3) === 1949; 171 * har.annaInt(4) === 22; 172 * </pre> 173 */ 174 @Override 175 public int annaInt(int k) { 176 Kentta kentta = getKentta(k); 177 if ( !(kentta instanceof IntKentta) ) return -1; 178 return ((IntKentta)kentta).getValue(); 179 } 180 181 182 183 /** 184 * Asetetaan valitun kentän sisältö. Mikäli asettaminen onnistuu, 185 * palautetaan null, muutoin virheteksti. 186 * @param k minkä kentän sisältö asetetaan 187 * @param s asetettava sisältö merkkijonona 188 * @return null jos ok, muuten virheteksti 189 * @example 190 * <pre name="test"> 191 * Harrastus har = new Harrastus(); 192 * har.aseta(3,"kissa") === "aloitusvuosi: Ei kokonaisluku (kissa)"; 193 * har.aseta(3,"1940") === null; 194 * har.aseta(4,"kissa") === "h/vko: Ei kokonaisluku (kissa)"; 195 * har.aseta(4,"20") === null; 196 * </pre> 197 */ 198 @Override 199 public String aseta(int k, String s) { 200 try { 201 String virhe = getKentta(k).aseta(s.trim()); 202 if ( virhe == null && k == 0 ) setTunnusNro(getTunnusNro()); 203 if ( virhe == null ) return virhe; 204 return getKysymys(k) +": " + virhe; 205 } catch (Exception ex) { 206 return "Virhe: " + ex.getMessage(); 207 } 208 } 209 210 211 /** 212 * Tehdään identtinen klooni tietueesta 213 * @return Object kloonattu tietue 214 * @example 215 * <pre name="test"> 216 * #THROWS CloneNotSupportedException 217 * Harrastus har = new Harrastus(); 218 * har.parse(" 2 | 10 | Kalastus | 1949 | 22 t "); 219 * Harrastus kopio = har.clone(); 220 * kopio.toString() === har.toString(); 221 * har.parse(" 1 | 11 | Uinti | 1949 | 22 t "); 222 * kopio.toString().equals(har.toString()) === false; 223 * kopio instanceof Harrastus === true; 224 * </pre> 225 */ 226 @Override 227 public Tietue clone() throws CloneNotSupportedException { // NOPMD 228 PerusTietue uusi; 229 uusi = (PerusTietue)super.clone(); 230 uusi.setKentat(getKentat().clone()); 231 232 for (int k = 0; k < getKenttia(); k++) 233 uusi.getKentat()[k] = getKentta(k).clone(); 234 return uusi; 235 } 236 237 238 /** 239 * Tulostetaan tietueen tiedot 240 * @param out tietovirta johon tulostetaan 241 */ 242 @Override 243 public void tulosta(PrintWriter out) { 244 String erotin = ""; 245 for (int k=ekaKentta(); k<getKenttia(); k++) { 246 out.print(erotin + anna(k)); 247 erotin = " "; 248 } 249 out.println(); 250 } 251 252 253 /** 254 * Tulostetaan tietueen tiedot 255 * @param os tietovirta johon tulostetaan 256 */ 257 @Override 258 public void tulosta(OutputStream os) { 259 tulosta(new PrintStream(os)); 260 } 261 262 263 /** 264 * Tulostetaan tietueen tiedot 265 * @param out tietovirta johon tulostetaan 266 */ 267 @Override 268 public void tulosta(PrintStream out) { 269 tulosta(new PrintWriter(out, true)); // ilman autoflushia ei mitään 270 // tulostu! 271 } 272 273 274 /** 275 * Antaa tietueelle seuraavan rekisterinumeron 276 * @return tietueen uusi tunnus_nro 277 * @example 278 * <pre name="test"> 279 * Harrastus pitsi1 = new Harrastus(); 280 * pitsi1.getTunnusNro() === 0; 281 * pitsi1.rekisteroi(); 282 * int n1 = pitsi1.getTunnusNro(); 283 * Harrastus pitsi2 = new Harrastus(); 284 * pitsi2.rekisteroi() === n1 + 1; 285 * int n2 = pitsi2.getTunnusNro(); 286 * n1 === n2-1; 287 * </pre> 288 */ 289 @Override 290 public int rekisteroi() { 291 return setTunnusNro(getSeuraavaNro()); 292 } 293 294 295 /** 296 * Palautetaan tietueen oma id 297 * @return tietueen id 298 * @example 299 * <pre name="test"> 300 * Harrastus harrastus = new Harrastus(); 301 * harrastus.parse(" 2 | 10 | Kalastus | 1949 | 22 t "); 302 * harrastus.getTunnusNro() === 2; 303 * </pre> 304 */ 305 @Override 306 public int getTunnusNro() { 307 return ((IntKentta)(getKentta(0))).getValue(); 308 } 309 310 311 /** 312 * Asettaa tunnusnumeron ja samalla varmistaa että 313 * seuraava numero on aina suurempi kuin tähän mennessä suurin. 314 * @param nr asetettava tunnusnumero 315 */ 316 private int setTunnusNro(int nr) { 317 IntKentta k = ((IntKentta)(getKentta(0))); 318 k.setValue(nr); 319 if (nr >= getSeuraavaNro()) setSeuraavaNro(nr + 1); 320 return k.getValue(); 321 } 322 323 324 /** 325 * Palauttaa tietueen tiedot merkkijonona jonka voi tallentaa tiedostoon. 326 * @return tietue tolppaeroteltuna merkkijonona 327 * @example 328 * <pre name="test"> 329 * Harrastus harrastus = new Harrastus(); 330 * harrastus.parse(" 2 | 10 | Kalastus | 1949 | 22 t "); 331 * harrastus.toString() =R= "2\\|10\\|Kalastus\\|1949\\|22.*"; 332 * </pre> 333 */ 334 @Override 335 public String toString() { 336 StringBuffer sb = new StringBuffer(""); 337 String erotin = ""; 338 for (int k = 0; k < getKenttia(); k++) { 339 sb.append(erotin); 340 sb.append(anna(k)); 341 erotin = "|"; 342 } 343 return sb.toString(); 344 } 345 346 347 /** 348 * Selvittää tietueen tiedot | erotellusta merkkijonosta. 349 * Pitää huolen että seuraavaNro on suurempi kuin tuleva tunnusnro. 350 * @param rivi josta harrastuksen tiedot otetaan 351 * @example 352 * <pre name="test"> 353 * Harrastus harrastus = new Harrastus(); 354 * harrastus.parse(" 2 | 10 | Kalastus | 1949 | 22 t "); 355 * harrastus.getJasenNro() === 10; 356 * harrastus.toString() =R= "2\\|10\\|Kalastus\\|1949\\|22.*"; 357 * 358 * harrastus.rekisteroi(); 359 * int n = harrastus.getTunnusNro(); 360 * harrastus.parse(""+(n+20)); 361 * harrastus.rekisteroi(); 362 * harrastus.getTunnusNro() === n+20+1; 363 * harrastus.toString() =R= "" + (n+20+1) + "\\|10\\|\\|1949\\|22.*"; 364 * </pre> 365 */ 366 @Override 367 public void parse(String rivi) { 368 StringBuffer sb = new StringBuffer(rivi); 369 for (int k = 0; k < getKenttia(); k++) 370 aseta(k, Mjonot.erota(sb, '|')); 371 } 372 373 374 /** 375 * Antaa k:n kentän sisällön avain-merkkijonona 376 * jonka perusteella voi lajitella 377 * @param k monenenko kentän sisältö palautetaan 378 * @return kentän sisältö merkkijonona 379 * 380 * @example 381 * <pre name="test"> 382 * Harrastus har = new Harrastus(); 383 * har.parse(" 2 | 10 | Kalastus | 1949 | 22 t "); 384 * har.getAvain(0) === " 2"; 385 * har.getAvain(1) === " 10"; 386 * har.getAvain(2) === "KALASTUS"; 387 * har.getAvain(20) === ""; 388 * </pre> 389 */ 390 @Override 391 public String getAvain(int k) { 392 try { 393 return getKentta(k).getAvain(); 394 } catch (Exception ex) { 395 return ""; 396 } 397 } 398 399 400 /** 401 * Tutkii onko tietueen tiedot samat kuin parametrina tuodun tietueen tiedot 402 * @param tietue johon verrataan 403 * @return true jos kaikki tiedot samat, false muuten 404 * @example 405 * <pre name="test"> 406 * Harrastus har1 = new Harrastus(); 407 * har1.parse(" 2 | 10 | Kalastus | 1949 | 22 t "); 408 * Harrastus har2 = new Harrastus(); 409 * har2.parse(" 2 | 10 | Kalastus | 1949 | 22 t "); 410 * Harrastus har3 = new Harrastus(); 411 * har3.parse(" 3 | 12 | Kalastus | 1949 | 22 t "); 412 * 413 * 414 * har1.equals(har2) === true; 415 * har2.equals(har1) === true; 416 * har1.equals(har3) === false; 417 * har3.equals(har2) === false; 418 * </pre> 419 */ 420 @Override 421 public boolean equals(Tietue tietue) { 422 if ( getKenttia() != tietue.getKenttia() ) return false; 423 for (int k = 0; k < getKenttia(); k++) 424 if (!anna(k).equals(tietue.anna(k))) return false; 425 return true; 426 } 427 428 } 429