1   package kerho;
2   
3   import java.io.*;
4   
5   import kanta.IntKentta;
6   import kanta.JonoKentta;
7   import kanta.Kentta;
8   
9   import fi.jyu.mit.ohj2.Mjonot;
10  import static kanta.HetuTarkistus.rand;
11  
12  /**
13   * Harrastus joka osaa mm. itse huolehtia tunnus_nro:staan.
14   *
15   * @author Vesa Lappalainen
16   * @version 1.0, 22.02.2003
17   */
18  public class Harrastus implements Cloneable {
19      private Kentta     kentat[]    = { 
20         new IntKentta("id"),
21         new IntKentta("jäsenId"),
22         new JonoKentta("ala"),
23         new IntKentta("aloitusvuosi"),
24         new IntKentta("h/vko")
25  //       new RahaKentta("kulut")
26      };
27         
28      private static int seuraavaNro = 1;
29  
30  
31      /**
32       * Alustetaan harrastus.  Toistaiseksi ei tarvitse tehdä mitään
33       */
34      public Harrastus() {
35          // Vielä ei tarvita mitään
36      }
37  
38      
39      private IntKentta getJasenNroKentta() {
40          return (IntKentta)(kentat[1]);
41      }
42      
43  
44      /**
45       * Alustetaan tietyn jäsenen harrastus.  
46       * @param jasenNro jäsenen viitenumero 
47       */
48      public Harrastus(int jasenNro) {
49          getJasenNroKentta().setValue(jasenNro);
50      }
51  
52      
53      /**
54       * @return harrastukse kenttien lukumäärä
55       */
56      public int getKenttia() {
57          return kentat.length;
58      }
59  
60  
61      /**
62       * @return ensimmäinen käyttäjän syötettävän kentän indeksi
63       */
64      public int ekaKentta() {
65          return 2;
66      }
67  
68      
69      /**
70       * @param k Mikä kenttä halutaan
71       * @return k.s kenttä
72       */
73      public Kentta getKentta(int k) {
74          return kentat[k];
75      }
76  
77      
78      /**
79       * @param k minkä kentän kysymys halutaan
80       * @return valitun kentän kysymysteksti
81       */
82      public String getKysymys(int k) {
83          try {
84              return kentat[k].getKysymys();
85          } catch (Exception ex) {
86              return "Ääliö";
87          }
88      }
89  
90  
91      /**
92       * @return kaikkien näytettävien kysymysten otsikot merkkijonotaulukkona
93       * @example
94       * <pre name="test">
95       * #import java.util.Arrays;
96       *   Harrastus har = new Harrastus();
97       *   Arrays.toString(har.getOtsikot()) =R= "\\[ala, aloitusvuosi, h/vko.*";
98       * </pre>
99       */
100     public String[] getOtsikot() {
101         int n = getKenttia() - ekaKentta();
102         String[] otsikot = new String[n];
103         for (int i=0,k=ekaKentta(); i<n; i++,k++) 
104             otsikot[i] = getKysymys(k);
105         return otsikot;        
106     }
107     
108     
109     /**
110      * @param k Minkä kentän sisältö halutaan
111      * @return valitun kentän sisältö
112      * @example
113      * <pre name="test">
114      *   Harrastus har = new Harrastus();
115      *   har.parse("   2   |  10  |   Kalastus  | 1949 | 22 t ");
116      *   har.anna(0) === "2";   
117      *   har.anna(1) === "10";   
118      *   har.anna(2) === "Kalastus";   
119      *   har.anna(3) === "1949";   
120      *   har.anna(4) === "22";   
121      *   
122      * </pre>
123      */
124     public String anna(int k) {
125         try {
126             return kentat[k].toString();
127         } catch (Exception ex) {
128             return "";
129         }
130     }
131 
132 
133     /**
134      * Asetetaan valitun kentän sisältö.  Mikäli asettaminen onnistuu,
135      * palautetaan null, muutoin virheteksti.
136      * @param k minkä kentän sisältö asetetaan
137      * @param s asetettava sisältö merkkijonona
138      * @return null jos ok, muuten virheteksti
139      * @example
140      * <pre name="test">
141      *   Harrastus har = new Harrastus();
142      *   har.aseta(3,"kissa") === "aloitusvuosi: Ei kokonaisluku (kissa)";
143      *   har.aseta(3,"1940")  === null;
144      *   har.aseta(4,"kissa") === "h/vko: Ei kokonaisluku (kissa)";
145      *   har.aseta(4,"20")    === null;
146      * </pre>
147      */
148     public String aseta(int k, String s) {
149         try {
150             String virhe = kentat[k].aseta(s.trim());
151             if ( virhe == null && k == 0 ) setTunnusNro(getTunnusNro());
152             if ( virhe == null ) return virhe;
153             return getKysymys(k) +": " + virhe;
154         } catch (Exception ex) {
155             return "Virhe: " + ex.getMessage();
156         }
157     }
158 
159 
160     /**
161      * Tehdään identtinen klooni jäsenestä
162      * @return Object kloonattu jäsen
163      * @example
164      * <pre name="test">
165      * #THROWS CloneNotSupportedException 
166      *   Harrastus har = new Harrastus();
167      *   har.parse("   2   |  10  |   Kalastus  | 1949 | 22 t ");
168      *   Harrastus kopio = har.clone();
169      *   kopio.toString() === har.toString();
170      *   har.parse("   1   |  11  |   Uinti  | 1949 | 22 t ");
171      *   kopio.toString().equals(har.toString()) === false;
172      * </pre>
173      */
174     @Override
175     public Harrastus clone() throws CloneNotSupportedException { // NOPMD
176         Harrastus uusi;
177         uusi = (Harrastus)super.clone();
178         uusi.kentat = kentat.clone();
179 
180         for (int k = 0; k < getKenttia(); k++)
181             uusi.kentat[k] = kentat[k].clone();
182         return uusi;
183     }
184     
185 
186     /**
187      * Apumetodi, jolla saadaan täytettyä testiarvot Harrastukselle.
188      * Aloitusvuosi arvotaan, jotta kahdella harrastuksella ei olisi
189      * samoja tietoja.
190      * @param nro viite henkilöön, jonka harrastuksesta on kyse
191      */
192     public void vastaaPitsinNyplays(int nro) {
193         aseta(1,""+nro);
194         aseta(2,"Pitsin nypläys");
195         aseta(3,""+ rand(1900, 2000));
196         aseta(4,""+rand(0, 60));
197     }
198 
199 
200     /**
201      * Tulostetaan harrastuksen tiedot
202      * @param out tietovirta johon tulostetaan
203      */
204     public void tulosta(PrintWriter out) {
205         String erotin = "";
206         for (int k=ekaKentta(); k<getKenttia(); k++) {
207             out.print(erotin + anna(k));
208             erotin = " ";
209         }
210         out.println();
211     }
212 
213 
214     /**
215      * Tulostetaan harrastuksen tiedot
216      * @param os tietovirta johon tulostetaan
217      */
218     public void tulosta(OutputStream os) {
219         tulosta(new PrintStream(os));
220     }
221     
222 
223     /**
224      * Tulostetaan harrastuksen tiedot
225      * @param out tietovirta johon tulostetaan
226      */
227     public void tulosta(PrintStream out) {
228         tulosta(new PrintWriter(out, true)); // ilman autoflushia ei mitään
229                                              // tulostu!
230     }
231 
232     
233     /**
234      * Antaa harrastukselle seuraavan rekisterinumeron.
235      * @return harrastuksen uusi tunnus_nro
236      * @example
237      * <pre name="test">
238      *   Harrastus pitsi1 = new Harrastus();
239      *   pitsi1.getTunnusNro() === 0;
240      *   pitsi1.rekisteroi();
241      *   Harrastus pitsi2 = new Harrastus();
242      *   pitsi2.rekisteroi();
243      *   int n1 = pitsi1.getTunnusNro();
244      *   int n2 = pitsi2.getTunnusNro();
245      *   n1 === n2-1;
246      * </pre>
247      */
248     public int rekisteroi() {
249         return setTunnusNro(seuraavaNro);
250     }
251 
252 
253     /**
254      * Palautetaan harrastuksen oma id
255      * @return harrastuksen id
256      */
257     public int getTunnusNro() {
258         return ((IntKentta)(kentat[0])).getValue();
259     }
260 
261 
262     /**
263      * Asettaa tunnusnumeron ja samalla varmistaa että
264      * seuraava numero on aina suurempi kuin tähän mennessä suurin.
265      * @param nr asetettava tunnusnumero
266      */
267     private int setTunnusNro(int nr) {
268         IntKentta k = ((IntKentta)(kentat[0]));
269         k.setValue(nr);
270         if (nr >= seuraavaNro) seuraavaNro = nr + 1;
271         return k.getValue();
272     }
273     
274 
275     /**
276      * Palautetaan mille jäsenelle harrastus kuuluu
277      * @return jäsenen id
278      */
279     public int getJasenNro() {
280         return getJasenNroKentta().getValue();
281     }
282 
283     
284     /**
285      * Palauttaa harrastuksen tiedot merkkijonona jonka voi tallentaa tiedostoon.
286      * @return harrastus tolppaeroteltuna merkkijonona 
287      * @example
288      * <pre name="test">
289      *   Harrastus harrastus = new Harrastus();
290      *   harrastus.parse("   2   |  10  |   Kalastus  | 1949 | 22 t ");
291      *   harrastus.toString()    =R= "2\\|10\\|Kalastus\\|1949\\|22.*";
292      * </pre>
293      */
294     @Override
295     public String toString() {
296         StringBuffer sb = new StringBuffer("");
297         String erotin = "";
298         for (int k = 0; k < getKenttia(); k++) {
299             sb.append(erotin);
300             sb.append(anna(k));
301             erotin = "|";
302         }
303         return sb.toString();
304      }
305 
306 
307     /**
308      * Selvitää harrastuksen tiedot | erotellusta merkkijonosta.
309      * Pitää huolen että seuraavaNro on suurempi kuin tuleva tunnusnro.
310      * @param rivi josta harrastuksen tiedot otetaan
311      * @example
312      * <pre name="test">
313      *   Harrastus harrastus = new Harrastus();
314      *   harrastus.parse("   2   |  10  |   Kalastus  | 1949 | 22 t ");
315      *   harrastus.getJasenNro() === 10;
316      *   harrastus.toString()     =R= "2\\|10\\|Kalastus\\|1949\\|22.*";
317      *   
318      *   harrastus.rekisteroi();
319      *   int n = harrastus.getTunnusNro();
320      *   harrastus.parse(""+(n+20));
321      *   harrastus.rekisteroi();
322      *   harrastus.getTunnusNro() === n+20+1;
323      *   harrastus.toString()     =R= "" + (n+20+1) + "\\|10\\|\\|1949\\|22.*";
324      * </pre>
325      */
326     public void parse(String rivi) {
327         StringBuffer sb = new StringBuffer(rivi);
328         for (int k = 0; k < getKenttia(); k++)
329             aseta(k, Mjonot.erota(sb, '|'));
330     }
331 
332 
333     /**
334      * Testiohjelma Harrastukselle.
335      * @param args ei käytössä
336      */
337     public static void main(String[] args) {
338         Harrastus har = new Harrastus();
339         har.vastaaPitsinNyplays(2);
340         har.tulosta(System.out);
341     }
342 }
343