1   package kerho;
2   import java.io.*;
3   import java.util.Comparator;
4   
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   */
18  public class Jasen { 
19    private static final HetuTarkistus  hetutarkistus = new HetuTarkistus();  
20      
21    private final Kentta kentat[] = {
22      new IntKentta("id"),
23      new JonoKentta("nimi"),
24      new JonoKentta("hetu",hetutarkistus), /// HetuKentta
25      new JonoKentta("katuosoite"),
26      new JonoKentta("postinumero"),
27      new JonoKentta("postiosoite"),
28      new JonoKentta("kotipuhelin"),
29      new JonoKentta("tyopuhelin"),
30      new JonoKentta("autopuhelin"),
31      new IntKentta("liittymisvuosi"),
32      new RahaKentta("jäsenmaksu"),
33      new RahaKentta("maksettumaksu"),
34      new JonoKentta("lisätietoja")
35  //    new IntKentta("varpaanväli")
36    };
37      
38    private static int seuraavaNro = 1;
39   
40    
41    /**
42     * Palauttaa jäsenen kenttien lukumäärän
43     * @return kenttien lukumäärä
44     */
45    public int getKenttia() { return kentat.length; }
46  
47    
48    /**
49     * Eka kenttä joka on mielekäs kysyttäväksi
50     * @return eknn kentän indeksi
51     */
52    public int ekaKentta()  { return 1;  }
53    
54    
55    
56    /**
57     * Luokka joka vertaa kahta jäsentä keskenään
58     */
59    public static class Vertailija implements Comparator<Jasen> {
60  
61        private final int kenttanro;
62        
63        /**
64         * Alustetaan vertailija vertailemaan tietyn kentän perusteella
65         * @param k vertailtavan kentän indeksi.
66         */
67        public Vertailija(int k) {
68            this.kenttanro = k;
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        public int compare(Jasen j1, Jasen j2) {
78          String s1 = j1.getAvain(kenttanro);
79          String s2 = j2.getAvain(kenttanro);
80          //String s1 = j1.anna(kenttanro);
81          //String s2 = j2.anna(kenttanro);
82  
83          return s1.compareTo(s2);
84  
85        }
86  
87      }
88    
89    
90    
91    /**
92     * Alustetaan jäsenen merkkijono-attribuuti tyhjiksi jonoiksi
93     * ja tunnusnro = 0.
94     */
95    public Jasen() {
96        // Toistaiseksi ei tarvita mitään
97    }
98    
99    private String getAvain(int kenttanro) {
100     return kentat[kenttanro].getAvain();
101   }
102 
103 
104 /**
105    * Antaa k:n kentän sisällön merkkijonona
106    * @param k monenenko kentän sisältö palautetaan
107    * @return kentän sisältö merkkijonona
108    */
109   public String anna(int k) {
110     try {
111       return kentat[k].toString();
112     } catch (Exception ex) {
113       return "";
114     }
115   }
116 
117   
118   /**
119    * Asettaa k:n kentän arvoksi parametrina tuodun merkkijonon arvon
120    * @param k kuinka monennen kentän arvo asetetaan
121    * @param jono jonoa joka asetetaan kentän arvoksi
122    * @return null jos asettaminen onnistuu, muuten vastaava virheilmoitus.
123    */
124   public String aseta(int k,String jono) {
125     try {
126       return kentat[k].aseta(jono.trim());
127     } catch (Exception ex) {
128       return "Virhe: " + ex.getMessage();
129     }
130   }
131 
132   
133   /**
134    * Palauttaa k:tta jäsenen kenttää vastaavan kysymyksen
135    * @param k kuinka monennen kentän kysymys palautetaan (0-alkuinen)
136    * @return k:netta kenttää vastaava kysymys
137    */
138   public String getKysymys(int k) {
139     try {
140       return kentat[k].getKysymys();
141     } catch (Exception ex) {
142       return "Ääliö";
143     }
144   }
145 
146   
147   /**
148    * Arvotaan satunnainen kokonaisluku välille [ala,yla]
149    * @param ala arvonnan alaraja
150    * @param yla arvonnan yläraja
151    * @return satunnainen luku väliltä [ala,yla]
152    */
153   public static int rand(int ala, int yla) {
154     double n = (yla-ala)*Math.random() + ala;
155     return (int)Math.round(n);
156   }
157 
158   
159   /**
160    * Apumetodi, jolla saadaan täytettyä testiarvot jäsenelle.
161    * @param apuhetu hetu joka annetaan henkilölle 
162    */
163   public void vastaaAkuAnkka(String apuhetu) {
164   /*      
165     nimi           = "Ankka Aku";
166     hetu           = apuhetu;
167     katuosoite     = "Ankkakuja 6";
168     postinumero    = "12345";
169     postiosoite    = "ANKKALINNA";
170     kotipuhelin    = "12-1234";
171     tyopuhelin     = "";
172     autopuhelin    = "";
173     liittymisvuosi = 1996;
174     jmaksu         = 50.00;
175     maksu          = 30.00;
176     lisatietoja    = "Velkaa Roopelle";
177    */ 
178     kentat[1].aseta("Ankka Aku");
179     kentat[2].aseta(apuhetu);
180     kentat[3].aseta("Ankkakuja 6");
181     kentat[4].aseta("12345");
182     kentat[5].aseta("ANKKALINNA");
183     kentat[6].aseta("12-1234");
184     kentat[7].aseta("");
185     kentat[8].aseta("");
186     kentat[9].aseta("1996");
187     kentat[10].aseta("50");
188     kentat[11].aseta("30");
189     kentat[12].aseta("Velkaa Roopelle");
190   }
191 
192   
193   /**
194    * Apumetodi, jolla saadaan täytettyä testiarvot jäsenelle.
195    * Henkilötunnus arvotaan, jotta kahdella jäsenellä ei olisi
196    * samoja tietoja.
197    */
198   public void vastaaAkuAnkka() {
199     String apuhetu = Mjonot.fmt(rand(1,31),2,'0') +
200                      Mjonot.fmt(rand(1,12),2,'0') +
201                      Mjonot.fmt(rand(1,99),2,'0') + "-" +
202                      Mjonot.fmt(rand(1,1000),3,'0') +
203                      ( (char)((int)'A'+rand(0,25)));
204     vastaaAkuAnkka(apuhetu);
205   }
206 
207   
208   /**
209    * Tulostetaan henkilön tiedot
210    * @param out tietovirta johon tulostetaan
211    */
212   public void tulosta(PrintStream out) {
213     int pisin = 0;
214     for (Kentta kentta: kentat)
215       if ( kentta.getKysymys().length() > pisin )
216         pisin = kentta.getKysymys().length();
217 
218     for (Kentta kentta: kentat)
219       out.println(Mjonot.fmt(kentta.getKysymys(),-pisin-1) +
220                   ": " + kentta.toString());
221     /*
222     out.println(Mjonot.fmt(tunnusnro,3,'0')+ "  " + nimi + "  " + hetu);
223     out.println("  " + katuosoite + "  " +  postinumero + " " + postiosoite);
224     out.println("  k: " + kotipuhelin +
225                 " t: " + tyopuhelin  +
226                 " a: " + autopuhelin);
227     out.print("  Liittynyt " + liittymisvuosi + ".");
228     out.println("  Jäsenmaksu " + Mjonot.fmt(jmaksu,4,2) + " mk." +
229                 "  Maksettu "   + Mjonot.fmt(maksu,4,2)  + " mk.");
230     out.println("  " + lisatietoja);
231     */
232   }
233 
234   
235   /**
236    * Tulostetaan henkilön tiedot
237    * @param os tietovirta johon tulostetaan
238    */
239   public void tulosta(OutputStream os) {
240     tulosta(new PrintStream(os));
241   }
242 
243   
244   /**
245    * Antaa jäsenelle seuraavan rekisterinumeron.
246    * @return jäsenen uusi tunnusNro
247    * @example
248    * <pre name="test">
249    *   Jasen aku1 = new Jasen();
250    *   aku1.getTunnusnro() === 0;
251    *   aku1.rekisteroi();
252    *   Jasen aku2 = new Jasen();
253    *   aku2.rekisteroi();
254    *   int n1 = aku1.getTunnusnro();
255    *   int n2 = aku2.getTunnusnro();
256    *   n1 === n2-1;
257    * </pre>
258    */
259   public int  rekisteroi() {
260     ((IntKentta)(kentat[0])).setValue(seuraavaNro);
261     seuraavaNro++;
262     return getTunnusnro();
263   }
264 
265   
266   /**
267    * Palauttaa jäsenen tunnusnumeron.
268    * @return jäsenen tunnusnumero
269    */
270   public int getTunnusnro() { return ((IntKentta)(kentat[0])).getValue(); }
271 
272   
273   /**
274    * Palauttaa jäsenen tiedot merkkijonona jonka voi tallentaa tiedostoon.
275    * @return jäsen tolppaeroteltuna merkkijonona 
276    */
277   @Override
278   public String toString() {
279       StringBuffer sb = new StringBuffer("");
280       String erotin = "";
281       for (int k=0; k<getKenttia(); k++) {
282         sb.append(erotin);  sb.append(anna(k));
283         erotin = "|";
284       }  
285       return sb.toString();  
286   }
287 
288   
289   /**
290    * Selvitää jäsenen tiedot | erotellusta merkkijonosta
291    * Pitää huolen että seuraavaNro on suurempi kuin tuleva tunnusNro.
292    * @param rivi josta jäsenen tiedot otetaan
293    * 
294    * @example
295    * <pre name="test">
296    *   Jasen jasen = new Jasen();
297    *   jasen.parse("   3  |  Ankka Aku   | 123");
298    *   jasen.getTunnusnro() === 3;
299    *   jasen.toString().startsWith("3|Ankka Aku|123|") === true; // on enemmäkin kuin 3 kenttää, siksi loppu |
300    *
301    *   jasen.rekisteroi();
302    *   int n = jasen.getTunnusnro();
303    *   jasen.parse(""+(n+20));       // Otetaan merkkijonosta vain tunnusnumero
304    *   jasen.rekisteroi();           // ja tarkistetaan että seuraavalla kertaa tulee yhtä isompi
305    *   jasen.getTunnusnro() === n+20+1;
306    *     
307    * </pre>
308    */
309   public void parse(String rivi) {
310       StringBuffer sb = new StringBuffer(rivi);
311       for (int k = 0; k < getKenttia(); k++ )
312         aseta(k,Mjonot.erota(sb,'|'));
313       if ( getTunnusnro() >= seuraavaNro ) seuraavaNro = getTunnusnro() + 1;
314   }
315 
316   
317   
318   /**
319    * Testiohjelma jäsenelle.
320    * @param args ei käytössä
321    */
322   public static void main(String args[]) {
323     Jasen aku = new Jasen(), aku2 = new Jasen();
324     aku.rekisteroi();
325     aku2.rekisteroi();
326     aku.tulosta(System.out);
327     aku.vastaaAkuAnkka();
328     aku.tulosta(System.out);
329 
330     aku2.vastaaAkuAnkka();
331     aku2.tulosta(System.out);
332 
333     aku2.vastaaAkuAnkka();
334     aku2.tulosta(System.out);
335   }
336 
337 
338 }
339 
340 
341