| Jasenet.java |
1 package kerho;
2
3 import java.io.BufferedReader;
4 import java.io.IOException;
5 import java.io.PrintWriter;
6 import java.io.File;
7 import java.util.ArrayList;
8 import java.util.Collection;
9 import java.util.Collections;
10 import java.util.Comparator;
11 import java.util.Iterator;
12 import java.util.NoSuchElementException;
13
14 import fi.jyu.mit.ohj2.Tiedosto;
15 import fi.jyu.mit.ohj2.WildChars;
16
17
18 /**
19 * Kerhon jäsenistö joka osaa mm. lisätä uuden jäsenen
20 *
21 * @author Vesa Lappalainen
22 * @version 1.0, 22.02.2003
23 */
24 public class Jasenet implements Iterable<Jasen> {
25 private boolean muutettu = false;
26 private String tiedostonPerusNimi = "";
27 private String kokoNimi = "";
28
29 private static final int MAX_JASENIA = 5;
30 private int lkm = 0;
31
32 /**
33 * Taulukko jäsenistä
34 */
35 private Jasen alkiot[] = new Jasen[MAX_JASENIA];
36
37
38 /**
39 * Oletusmuodostaja
40 */
41 public Jasenet() {
42 // Attribuuttien oma alustus riittää
43 }
44
45
46 /**
47 * Lisää uuden jäsenen tietorakenteeseen. Ottaa jäsenen omistukseensa.
48 * @param jasen lisätäävän jäsenen viite. Huom tietorakenne muuttuu omistajaksi
49 * @throws SailoException jos tietorakenne on jo täynnä
50 * @example
51 * <pre name="test">
52 * #THROWS SailoException
53 * #PACKAGEIMPORT
54 * Jasenet jasenet = new Jasenet();
55 * Jasen aku1 = new Jasen(), aku2 = new Jasen();
56 * jasenet.getLkm() === 0;
57 * jasenet.lisaa(aku1); jasenet.getLkm() === 1;
58 * jasenet.lisaa(aku2); jasenet.getLkm() === 2;
59 * jasenet.lisaa(aku1); jasenet.getLkm() === 3;
60 * jasenet.anna(0) === aku1;
61 * jasenet.anna(1) === aku2;
62 * jasenet.anna(2) === aku1;
63 * jasenet.anna(1) == aku1 === false;
64 * jasenet.anna(1) == aku2 === true;
65 * jasenet.anna(3) === aku1; #THROWS IndexOutOfBoundsException
66 * jasenet.lisaa(aku1); jasenet.getLkm() === 4;
67 * jasenet.lisaa(aku1); jasenet.getLkm() === 5;
68 * jasenet.lisaa(aku1); #THROWS SailoException
69 * </pre>
70 */
71 public void lisaa(Jasen jasen) throws SailoException {
72 muutettu = true;
73 if ( lkm >= alkiot.length ) throw new SailoException("Liikaa alkioita");
74 alkiot[lkm] = jasen;
75 lkm++;
76 }
77
78
79 /**
80 * Palauttaa viitteen i:teen jäseneen.
81 * @param i monennenko jäsenen viite halutaan
82 * @return viite jäseneen, jonka indeksi on i
83 * @throws IndexOutOfBoundsException jos i ei ole sallitulla alueella
84 */
85 public Jasen anna(int i) throws IndexOutOfBoundsException {
86 if ( i < 0 || lkm <= i ) throw new IndexOutOfBoundsException("Laiton indeksi: " + i);
87 return alkiot[i];
88 }
89
90
91 /**
92 * Lukee jäsenistön tiedostosta. Kesken.
93 * @param tied tiedoston nimen alkuosa
94 * @throws SailoException jos lukeminen epäonnistuu
95 *
96 * @example
97 * <pre name="test">
98 * #THROWS SailoException
99 * #import java.io.File;
100 *
101 * Jasenet jasenet = new Jasenet();
102 * Jasen aku1 = new Jasen(), aku2 = new Jasen();
103 * aku1.vastaaAkuAnkka();
104 * aku2.vastaaAkuAnkka();
105 * String tiedNimi = "testikelmit";
106 * File ftied = new File(tiedNimi+".dat");
107 * ftied.delete();
108 * jasenet.lueTiedostosta(tiedNimi); #THROWS SailoException
109 * jasenet.lisaa(aku1);
110 * jasenet.lisaa(aku2);
111 * jasenet.talleta();
112 * jasenet = new Jasenet(); // Poistetaan vanhat luomalla uusi
113 * jasenet.lueTiedostosta(tiedNimi); // johon ladataan tiedot tiedostosta.
114 * Iterator<Jasen> i = jasenet.iterator();
115 * i.next().toString() === aku1.toString();
116 * i.next().toString() === aku2.toString();
117 * i.hasNext() === false;
118 * jasenet.lisaa(aku2);
119 * jasenet.talleta();
120 * ftied.delete() === true;
121 * File fbak = new File(tiedNimi+".bak");
122 * fbak.delete() === true;
123 * </pre>
124 */
125 public void lueTiedostosta(String tied) throws SailoException {
126 setTiedostonPerusNimi(tied);
127 BufferedReader fi = Tiedosto.avaa_lukemista_varten(getTiedostonNimi());
128 if ( fi == null ) throw new SailoException("Tiedosto " + getTiedostonNimi() + " ei aukea");
129
130 try {
131 kokoNimi = fi.readLine();
132 if ( kokoNimi == null ) throw new SailoException("Kerhon nimi puuttuu");
133 String rivi = fi.readLine();
134 if ( rivi == null ) throw new SailoException("Maksimikoko puuttuu");
135 // int maxKoko = Mjonot.erotaInt(rivi,10); // tehdään jotakin
136
137 while ( ( rivi = fi.readLine() ) != null ) {
138 rivi = rivi.trim();
139 if ( "".equals(rivi) || rivi.charAt(0) == ';') continue;
140 Jasen jasen = new Jasen(); // NOPMD, pakko luoda täällä
141 jasen.parse(rivi); // voisi olla virhekäsittely
142 lisaa(jasen);
143 }
144 muutettu = false;
145
146
147 } catch ( IOException e ) {
148 throw new SailoException("Ongelmia tiedoston kanssa: " + e.getMessage()); // NOPMD
149 } finally {
150 try {
151 fi.close();
152 } catch (IOException e) {
153 throw new SailoException("Tiedoston sulkeminen ei onnistu: " + e.getMessage()); // NOPMD
154 }
155 }
156 }
157
158
159 /**
160 * Tallentaa jäsenistön tiedostoon.
161 * Tiedoston muoto:
162 * <pre>
163 * Kelmien kerho
164 * 20
165 * ; kommenttirivi
166 * 2|Ankka Aku|121103-706Y|Ankkakuja 6|12345|ANKKALINNA|12-1234|||1996|50.0|30.0|Velkaa Roopelle
167 * 3|Ankka Tupu|121153-706Y|Ankkakuja 6|12345|ANKKALINNA|12-1234|||1996|50.0|30.0|Velkaa Roopelle
168 * </pre>
169 * @throws SailoException jos talletus epäonnistuu
170 */
171 public void talleta() throws SailoException {
172 if ( !muutettu ) return;
173
174 File fbak = new File(getBakNimi());
175 File ftied = new File(getTiedostonNimi());
176 fbak.delete(); // if .. System.err.println("Ei voi tuhota");
177 ftied.renameTo(fbak); // if .. System.err.println("Ei voi nimetä");
178
179 PrintWriter fo = Tiedosto.avaa_kirjoittamista_varten(ftied.getName());
180 if ( fo == null ) throw new SailoException("Tiedosto " + ftied.getName() + "ei aukea");
181 try {
182 fo.println(getKokoNimi());
183 fo.println(alkiot.length);
184 for (Jasen jasen:this) {
185 fo.println(jasen.toString());
186 }
187 //} catch ( IOException e ) { // ei heitä poikkeusta
188 // throw new SailoException("Tallettamisessa ongelmia: " + e.getMessage()); // NOPMD
189 } finally {
190 fo.close();
191 }
192
193 muutettu = false;
194 }
195
196 /**
197 * Palauttaa Kerhon koko nimen
198 * @return Kerhon koko nimi merkkijononna
199 */
200 public String getKokoNimi() { return kokoNimi; }
201
202
203 /**
204 * Palauttaa kerhon jäsenten lukumäärän
205 * @return jäsenten lukumäärä
206 */
207 public int getLkm() { return lkm; }
208
209
210 /**
211 * Asettaa tiedoston perusnimen ilan tarkenninta
212 * @param tied tallennustiedoston perusnimi
213 */
214 public void setTiedostonPerusNimi(String tied) { tiedostonPerusNimi = tied; }
215
216
217 /**
218 * Palauttaa tiedoston nimen, jota käytetään tallennukseen
219 * @return tallennustiedoston nimi
220 */
221 public String getTiedostonPerusNimi() { return tiedostonPerusNimi; }
222
223
224 /**
225 * Palauttaa tiedoston nimen, jota käytetään tallennukseen
226 * @return tallennustiedoston nimi
227 */
228 public String getTiedostonNimi() { return tiedostonPerusNimi + ".dat"; }
229
230
231 /**
232 * Palauttaa varakopiotiedoston nimen
233 * @return varakopiotiedoston nimi
234 */
235 public String getBakNimi() { return tiedostonPerusNimi + ".bak"; }
236
237
238
239 /**
240 * Luokka jäsenten iteroimiseksi.
241 * @example
242 * <pre name="test">
243 * #THROWS SailoException
244 * #PACKAGEIMPORT
245 * #import java.util.*;
246 *
247 * Jasenet jasenet = new Jasenet();
248 * Jasen aku1 = new Jasen(), aku2 = new Jasen();
249 * aku1.rekisteroi(); aku2.rekisteroi();
250 *
251 * jasenet.lisaa(aku1);
252 * jasenet.lisaa(aku2);
253 * jasenet.lisaa(aku1);
254 *
255 * StringBuffer ids = new StringBuffer(30);
256 * for (Jasen jasen:jasenet) // Kokeillaan for-silmukan toimintaa
257 * ids.append(" "+jasen.getTunnusnro()); // NOPMD
258 *
259 * String tulos = " " + aku1.getTunnusnro() + " " + aku2.getTunnusnro() + " " + aku1.getTunnusnro();
260 *
261 * ids.toString() === tulos;
262 *
263 * ids = new StringBuffer(30);
264 * for (Iterator<Jasen> i=jasenet.iterator(); i.hasNext(); ) { // ja iteraattorin toimintaa
265 * Jasen jasen = i.next();
266 * ids.append(" "+jasen.getTunnusnro()); // NOPMD
267 * }
268 *
269 * ids.toString() === tulos;
270 *
271 * Iterator<Jasen> i=jasenet.iterator();
272 * i.next() == aku1 === true;
273 * i.next() == aku2 === true;
274 * i.next() == aku1 === true;
275 *
276 * i.next(); #THROWS NoSuchElementException
277 *
278 * </pre>
279 */
280 public class JasenetIterator implements Iterator<Jasen> {
281 private int kohdalla = -1;
282
283 /**
284 * Onko olemassa vielä seuraavaa jäsentä
285 * @see java.util.Iterator#hasNext()
286 * @return true jos on vielä jäseniä
287 */
288 public boolean hasNext() {
289 // if ( kohdalla + 1 >= lkm ) return false;
290 // return true;
291 return kohdalla + 1 < lkm;
292 }
293
294
295 /**
296 * Annetaan seuraava jäsen
297 * @return seuraava jäsen
298 * @throws NoSuchElementException jos seuraava alkiota ei enää ole
299 * @see java.util.Iterator#next()
300 */
301 public Jasen next() throws NoSuchElementException {
302 if ( !hasNext() ) throw new NoSuchElementException("Ei oo");
303 kohdalla++;
304 return alkiot[kohdalla];
305 }
306
307
308
309 /**
310 * Tuhoamista ei ole toteutettu
311 * @throws UnsupportedOperationException aina
312 * @see java.util.Iterator#remove()
313 */
314 public void remove() throws UnsupportedOperationException {
315 throw new UnsupportedOperationException("Me ei poisteta");
316 }
317 }
318
319 /**
320 * Palautetaan iteraattori jäsenistöön.
321 * @return jäsen iteraattori
322 */
323 public Iterator<Jasen> iterator() {
324 // return alkiot.iterator();
325 return new JasenetIterator();
326 }
327
328
329 /**
330 * Testiohjelma jäsenistölle
331 * @param args ei käytössä
332 */
333 public static void main(String args[]) {
334 Jasenet jasenet = new Jasenet();
335
336 Jasen aku = new Jasen(), aku2 = new Jasen();
337 aku.rekisteroi(); aku.vastaaAkuAnkka();
338 aku2.rekisteroi(); aku2.vastaaAkuAnkka();
339
340 try {
341 jasenet.lisaa(aku);
342 jasenet.lisaa(aku2);
343
344 System.out.println("============= Jäsenet testi =================");
345
346 for (Iterator<Jasen> i=jasenet.iterator(); i.hasNext(); ) {
347 // Jasen jasen = jasenet.anna(i);
348 // System.out.println("Jäsen nro: " + i);
349 Jasen jasen = i.next();
350 jasen.tulosta(System.out);
351 }
352 jasenet.anna(100);
353
354 } catch ( IndexOutOfBoundsException ex ) {
355 System.out.println(ex.getMessage());
356 } catch ( SailoException ex ) {
357 System.out.println(ex.getMessage());
358 }
359 }
360
361
362 /**
363 * Luokka joka vertaa kahta jäsentä keskenään
364 */
365 public static class JasenVertailija implements Comparator<Jasen> {
366
367 /**
368 * Verrataana kahta jäsentä keskenään.
369 * @param j1 1. verrattava jäsen
370 * @param j2 2. verrattava jäsen
371 * @return <0 jos j1 < j2, == 0 jos j1 == j2 ja muuten >0
372 */
373 public int compare(Jasen j1, Jasen j2) {
374 String s1 = j1.anna(1);
375 String s2 = j2.anna(1);
376
377 return s1.compareTo(s2);
378
379 }
380
381 }
382
383
384 /**
385 * Etsii jäsenet listaan
386 * @param hakuehto etsittävä jäsen
387 * @param k kenttä jonka mukaan etsitään
388 * @return lista löytyneistä jäsenistä
389 */
390 public Collection<Jasen> etsi(String hakuehto, int k) {
391 ArrayList<Jasen> loytyneet = new ArrayList<Jasen>();
392 //String haku = "*"+hakuehto+"*";
393 for ( Jasen jasen:this) {
394 if ( WildChars.onkoSamat(jasen.anna(k),hakuehto) )
395 loytyneet.add(jasen);
396 }
397
398 //Collections.sort(loytyneet,new JasenVertailija());
399 Collections.sort(loytyneet,new Jasen.Vertailija(k));
400 return loytyneet;
401 }
402
403 }
404
405
406