1   package demo12;
2   
3   import java.io.*;
4   import java.util.Iterator;
5   import java.util.Map;
6   import java.util.Set;
7   import java.util.TreeMap;
8   import java.util.Map.Entry;
9   
10  
11  
12  import fi.jyu.mit.ohj2.*;
13  
14  /**
15   * Ohjelmalla vaihdetaan valuuttoja
16   * Versioon 1.1 lis?tty Valuutat -luokan rajapintaa
17   * uusia metodeja, mm. getVaihdettuMaara, getValuutat
18   * @author Vesa Lappalainen
19   * @version 1.0, 15.03.2003
20   * @version 1.1, 09.04.2003
21   * 
22   * 
23   * 
24   * Tietorakenne treemapiksi, demo12 teht. 1-2
25   * 
26   * 
27   * @author Antti My?h?nen
28   */
29  public class ValuuttaMuunnos {
30      // #DYNAMICIMPORT
31  
32      /**
33       * Muunnetaan valuuttaa
34       * @param args ei k?yt?ss?
35       * @throws IOException jos jokin menee pieleen tiedoston luvussa
36       */
37      public static void main(String[] args) throws IOException {
38          Valuutat valuutat = new Valuutat();
39          /*
40              valuutat.lisaa(1.0,"mk");
41              valuutat.lisaa(5.7,"$");
42              valuutat.lisaa(5.9,"EUROA");
43              valuutat.lisaa(0.6,"SKr");
44          */
45          if (!valuutat.lue()) {
46              System.out.println("Valuuttoja ei saa luettua");
47              return;
48          }
49  
50          ValuuttaNaytto naytto = new ValuuttaNaytto(valuutat);
51  
52          while (naytto.kysy()) {
53              naytto.tulosta();
54          }
55  
56      }
57  
58      /**
59       * Luokka yhdelle valuutalle ja sen muunnoskertoimelle
60       * @author Vesa Lappalainen
61       * @version 1.0, 15.03.2003
62       */
63      public static class Valuutta {
64          private double maara;
65  
66          private String valuutannimi;
67  
68          /**
69           * Alustetaan valuutta
70           * @param maara valuutan m??r?
71           * @param valuutannimi yksikk?
72           * @example
73           * <pre name="test">
74           * Valuutta val = new Valuutta(2,"lati");
75           * val.toString() === "2.00 lati";
76           * </pre>
77           */
78          public Valuutta(double maara, String valuutannimi) {
79              this.maara = maara;
80              this.valuutannimi = valuutannimi;
81          }
82  
83          /**
84           * Alustetaan jonolla joka on muotoa 10  SKr
85           * @param jono josta valuutan tiedot etsit??n.
86           * @example
87           * <pre name="test">
88           * Valuutta val = new Valuutta("10 SKr"); // NOPMD
89           * val.toString() === "10.00 SKr";
90           * </pre>
91           */
92          public Valuutta(String jono) {
93              parse(jono);
94          }
95  
96          /**
97           * Otetaan valuutan tiedot jonosta jonka muoto on 10 SKr
98           * @param jono josta valuutan tiedot etsit??n. 
99           * <pre name="test">
100          * Valuutta val = new Valuutta("");
101          * val.parse("10     SKr");
102          * val.toString() === "10.00 SKr";
103          * </pre>
104          */
105         public final void parse(String jono) {
106             StringBuffer sb = new StringBuffer(jono);
107             maara = Mjonot.erotaDouble(sb, maara);
108             valuutannimi = Mjonot.erota(sb, '|', valuutannimi);
109         }
110 
111         /**
112          * @return valuutan tiedot muodossa 10.00 SKr 
113          */
114         @Override
115         public String toString() {
116             return Mjonot.fmt(maara, 4, 2) + " " + valuutannimi;
117         }
118 
119         /**
120          * Verrataan vastaako valuutta hakumaskia.
121          * Hakumaskin alkuosan pit?? t?sm?t?. 
122          * @param maski Hakumaski
123          * @return true jos vastaa
124          * <pre name="test">
125          * Valuutta val = new Valuutta("10 SKr");
126          * val.onko("SKr") === true;               // NOPMD
127          * val.onko("s")   === true;
128          * val.onko("Dkr") === false;
129          * val.onko("kr")  === false;
130          * val.onko(".kr") === true;
131          * val.onko("$")   === false;
132          * Valuutta val2 = new Valuutta("1.6 $");
133          * val2.onko("$") === true;
134          * val2.onko("s") === false;
135          * </pre>
136          */
137         public boolean onko(String maski) {
138             String umaski = maski.toUpperCase().replaceAll("\\$", "\\\\\\$")
139                     + ".*";
140             String val = valuutannimi.toUpperCase();
141             return val.matches(umaski);
142         }
143 
144         /**
145          * Vertaa onko parametrina tuodussa valuutassa sama yksikk?
146          * @param obj verrattava valuutta 
147          * @return true jos sama valuuttajono 
148          * <pre name="test">
149          * Valuutta val = new Valuutta("10 SKr");
150          * Valuutta val2 = new Valuutta(0,"s");
151          * Valuutta val3 = new Valuutta(0,"$");
152          * val.onko(val2)  === true;
153          * val.onko(val3)  === false;
154          * </pre>
155          */
156         public boolean onko(Object obj) {
157             if (obj instanceof String)
158                 return onko((String) obj);
159             if (obj instanceof StringBuffer)
160                 return onko(((StringBuffer) obj).toString());
161             if (!(obj instanceof Valuutta))
162                 return false;
163             return onko(((Valuutta) obj).valuutannimi);
164         }
165 
166         /** @return valuutan kerroin (sama kuin m??r?) */
167         public double getKerroin() {
168             return maara;
169         }
170 
171         /** @return valuutan m??r?                     */
172         public double getMaara() {
173             return maara;
174         }
175 
176         /** @return Valuutan yksikk?                   */
177         public String getValuutannimi() {
178             return valuutannimi;
179         }
180 
181         /**
182          * Asetetaan valuutan yksikk?
183          * @param valuutannimi asetettava yksikk?
184          */
185         public void setValuutta(String valuutannimi) {
186             this.valuutannimi = valuutannimi;
187         }
188 
189     }
190 
191     /**
192      * Luokka valuuttojen tallentamiselle
193      * @author Vesa Lappalainen
194      * @version 1.0, 15.03.2003
195      */
196     public static class Valuutat {
197         //private int lkm = 0;
198         private Valuutta ekaValuutta;
199         
200         private Map<String, Valuutta> alkiot = new TreeMap<String, Valuutta>();
201         
202 
203         /**
204          * Lis?t??n tietorakenteeseen uusi valuutta.
205          * @param val lis?tt?v? valuutta.
206          * @example
207          * <pre name="test">
208          * Valuutat valuutat = new Valuutat();
209          * Valuutta skr = new Valuutta("10 SKr");
210          * valuutat.lisaa(new Valuutta("1 e"));
211          * valuutat.lisaa(skr);
212          * valuutat.lisaa(new Valuutta("1.6 $"));
213          * valuutat.ekanValuutannimi() === "e";
214          * valuutat.getKerroin("$") ~~~ 1.6;
215          * valuutat.get("s") === skr;
216          * valuutat.get("$") == skr === false;
217          * </pre>
218          */
219         public void lisaa(Valuutta val) {
220             alkiot.put(val.getValuutannimi(), val);
221             if (getAlkiotSize() == 1) ekaValuutta = val; 
222         }
223 
224         /**
225          * Lis?t??n tietorakenteeseen uusi valuutta.
226          * @param kerroin lis?tt?v?n valuutan kerroin
227          * @param valuutta listt?v?n valuutan yksikk?
228          * @example
229          * <pre name="test">
230          * Valuutat valuutat = new Valuutat();
231          * valuutat.lisaa(1,"e");
232          * valuutat.lisaa(10,"SKr");
233          * valuutat.lisaa(1.6,"$");
234          * valuutat.ekanValuutannimi() === "e";
235          * valuutat.getKerroin("$") ~~~ 1.6;
236          * valuutat.get("s").getValuutannimi() === "SKr";
237          * valuutat.getValuutannimi("s") === "SKr";
238          * </pre>
239          */
240         public void lisaa(double kerroin, String valuutta) { 
241             lisaa(new Valuutta(kerroin, valuutta)); 
242         }
243         
244         
245         /**
246          * Palauttaa valuuttatietojen lukum??r?n
247          * @return    valuuttatietojen lukum??r?
248          */
249         public int getAlkiotSize() {
250             return alkiot.size();
251         }
252         
253         
254         /**
255          * Palautetaan ensimm?isen tietorakenteessa olevan
256          * valuutan yksikk?.
257          * @return ensimm?isen valuutan yksikk?
258          */
259         public String ekanValuutannimi() {
260             if (getAlkiotSize() <= 0)
261                 return "";
262             return ekaValuutta.getValuutannimi();
263             
264         }
265 
266         /**
267          * Etsit??n hakujonoa vastaava valuutta
268          * @param valuutannimi etsitt?v?n valuutan yksikk?
269          * @return null jos ei l?ydy, muuten l?ytynyt valuutta.
270          */
271         public Valuutta get(String valuutannimi) {
272             //if (alkiot.get(valuutannimi) != null) return alkiot.get(valuutannimi); 
273             
274             Set<Map.Entry<String, Valuutta>> entrySet = alkiot.entrySet();
275             Iterator<Entry<String, Valuutta>> iteraattori = entrySet.iterator();
276             
277             while ( iteraattori.hasNext() ) {
278                 Valuutta temp = iteraattori.next().getValue();
279                 if ( temp.onko(valuutannimi) ) return temp;
280             }
281             return null;
282         }
283 
284         /**
285          * Etsit??n hakujonoa vastaavan valuutan kerroin.
286          * @param valuutannimi etsitt?v?n valuutan yksikk?
287          * @return valuutan kerroin tai 1.0 jo ei l?ydy.
288          */
289         public double getKerroin(String valuutannimi) {
290             Valuutta val = get(valuutannimi);
291             if (val == null)
292                 return 1.0;
293             return val.getKerroin();
294         }
295 
296         /**
297          * Etsit??n hakujonoa vastaavan valuutan kerroin.
298          * @param valuutta etsitt?v? valuutan hakujono valuutassa
299          * @return valuutan kerroin tai 1.0 jo ei l?ydy.
300          */
301         public double getKerroin(Valuutta valuutta) {
302             return getKerroin(valuutta.getValuutannimi());
303         }
304 
305         /**
306          * Etsit??n hakujonoa vastaavan valuutan yksikk?
307          * @param valuutannimi etsitt?v?n valuutan yksikk?
308          * @return valuutan kerroin tai 1.0 jo ei l?ydy.
309          */
310         public String getValuutannimi(String valuutannimi) {
311             Valuutta val = get(valuutannimi);
312             if (val == null)
313                 return "";
314             return val.getValuutannimi();
315         }
316 
317         /**
318          * Etsit??n hakujonoa vastaavan valuutan yksikk?
319          * @param valuutta etsitt?v? valuutan hakujono valuutassa
320          * @return valuutan kerroin tai 1.0 jo ei l?ydy.
321          */
322         public String getValuutta(Valuutta valuutta) {
323             return getValuutannimi(valuutta.getValuutannimi());
324         }
325 
326         /**
327          * Luetaan valuutat.dat nimesest? tiedostosta valuutat.
328          * @return true jos lukeminen onnistui false jos tiedosto ei aukea.
329          * @throws IOException  jos jokin menee pieleen tiedoston k?sittelyss?.
330          */
331         public boolean lue() throws IOException {
332             BufferedReader fi = Tiedosto.avaa_lukemista_varten("valuutat.dat");
333             if (fi == null)
334                 return false;
335 
336             try {
337                 String jono;
338                 while ((jono = fi.readLine()) != null) {
339                     if ("".equals(jono))
340                         continue;
341                     lisaa(new Valuutta(jono)); // NOPMD - pakko luoda silmukassa
342                 }
343             } finally {
344                 fi.close();
345             }
346 
347             return true;
348         }
349 
350         /**
351          * Palautetaan haettavaa valuuttaa vastaava summa kantavaluutassa.
352          * @param nimi  haettavan valuutan hakujono
353          * @param maara raham??r? joka muutetaan kantavaluuttaan.
354          * @return raham??r? muutettuna kantavaluuttaan.
355          */
356         public double getVaihdettuMaara(String nimi, double maara) {
357             return getKerroin(nimi) * maara;
358         }
359 
360         /**
361          * Palautetaan valuutassa olevaa hakujonoa vastaava valuutta-olio
362          * kantavaluuttana.
363          * @param val valuutta jossa on hakujono ja m??r? joka muutetaan kantavaluuttaan.
364          * @return tiedot kantavaluuttana
365          * @example
366          * <pre name="test">
367          * Valuutat valuutat = new Valuutat();
368          * valuutat.lisaa(1,"e");
369          * valuutat.lisaa(10,"SKr");
370          * valuutat.lisaa(1.6,"$");
371          * valuutat.getVaihdettuMaara("s",3.0) ~~~ 30.0;
372          * valuutat.getVaihdettu(new Valuutta(3.0,"s")).toString() === "30.00 e";
373          * valuutat.getVaihdettu(new Valuutta(3.0,"$")).toString() === "4.80 e";
374          * </pre>
375          */
376         public Valuutta getVaihdettu(Valuutta val) {
377             double vaihdettu_maara = getVaihdettuMaara(val.getValuutannimi(),
378                     val.getMaara());
379             return new Valuutta(vaihdettu_maara, ekanValuutannimi());
380         }
381 
382         /**
383          * Palautetaan merkkijonotaulukkona kaikkien valuuttojen nimet
384          * @return valuuttojen nimet merkkijonotaulukossa.
385          * @example
386          * <pre name="test">
387          * Valuutat valuutat = new Valuutat();
388          * valuutat.lisaa(1,"e");
389          * valuutat.lisaa(10,"SKr");
390          * valuutat.lisaa(1.6,"$");
391          * String nimet[] = valuutat.getValuuttojenNimet();
392          * nimet.length === 3;
393          * nimet[0] === "e";
394          * nimet[1] === "SKr";
395          * nimet[2] === "$";
396          * </pre>
397          */
398         public String[] getValuuttojenNimet() {
399             String nimet[] = new String[getAlkiotSize()];
400             
401             Set<Map.Entry<String, Valuutta>> entrySet = alkiot.entrySet();
402             Iterator<Entry<String, Valuutta>> iteraattori = entrySet.iterator();
403             
404             for (int i = 0; i < getAlkiotSize(); i++)
405                 nimet[i] = iteraattori.next().getKey();
406             return nimet;
407         }
408 
409     }
410 
411     /**
412      * N?ytt?luokka valuuttojen k?ytt?miseksi konsolisovelluksesta.
413      * @author Vesa Lappalainen
414      * @version 1.0, 15.03.2003
415      * 
416      * @example
417      * <pre name="test">
418      * @example
419      * <pre name="test">
420      * #import fi.jyu.mit.ohj2.Suuntaaja;
421      *     
422      * Valuutat valuutat = new Valuutat();
423      * valuutat.lisaa(1,"e");
424      * valuutat.lisaa(10,"SKr");
425      * valuutat.lisaa(1.6,"$");
426      * ValuuttaNaytto naytto = new ValuuttaNaytto(valuutat);
427      * 
428      * Suuntaaja.StringInput si = new Suuntaaja.StringInput();  
429      * Suuntaaja.StringOutput so = new Suuntaaja.StringOutput();
430      *
431      * si.input("");       naytto.kysy() === false; 
432      * si.input("loppu");  naytto.kysy() === false;
433      * so.reset(); 
434      * si.input("3 s");    naytto.kysy() === true;
435      * so.reset(); naytto.tulosta(); so.ero("3.00 SKr on 30.00 e\n") === null; 
436      * si.input("3 $");    naytto.kysy() === true;
437      * so.reset(); naytto.tulosta(); so.ero("3.00 $ on 4.80 e\n") === null; 
438      * si.input("2");      naytto.kysy() === true;
439      * so.reset(); naytto.tulosta(); so.ero("2.00 $ on 3.20 e\n") === null; 
440      * si.input("k lati"); naytto.kysy() === true; // Yksikk?? ei l?ydy
441      * so.reset(); naytto.tulosta(); so.ero("2.00  on 2.00 e\n") === null; 
442      * si.input("");       naytto.kysy() === false; 
443      * 
444      * si.palauta(); so.palauta();
445      * 
446      * </pre>
447      * </pre>
448      */
449     public static class ValuuttaNaytto {
450         private final Valuutat valuutat;
451         
452         private final Valuutta valuutta = new Valuutta("");
453 
454         /**
455          * Alustetaan n?ytt? k?ytt?m??n valuuttataulukkoa.
456          * @param valuutat valuuttataulukko jota k?ytet??n.
457          */
458         public ValuuttaNaytto(Valuutat valuutat) {
459             this.valuutat = valuutat;
460         }
461 
462         /**
463          * Kysyt??n valuutan tietoja.
464          * @return true jos kysely onnistui.
465          */
466         public boolean kysy() {
467             String jono = Syotto.kysy("M??r? ja valuutta");
468 
469             if ("".equals(jono))
470                 return false;
471             if ("loppu".equals(jono))
472                 return false;
473 
474             valuutta.parse(jono);
475             String val = valuutat.getValuutta(valuutta);
476             valuutta.setValuutta(val);
477 
478             return true;
479         }
480 
481         /**
482          * Tulostetaan kysytyn valuutan tiedot.
483          */
484         public void tulosta() {
485            
486             Valuutta vaihdettu = valuutat.getVaihdettu(valuutta);
487             System.out.println(valuutta + " on " + vaihdettu);
488         }
489 
490     }
491 
492 }