Download Download
archive
here
OpenFuture

Euro-Conversion

Version 1.1a, 27.11.2000
Status: complete

Index

1. Introduction

1.1 The package magie.currency
1.2 Requirements
1.3 Usage
1.4 Structure
1.5 Application specific solutions

2. Domain Classes

2.1 Currency
2.2 CurrencyUnit
2.3 Currency Conversion
2.4 Arithmetic Operations
2.5 Rounding Differences
2.6 Exceptions

3. Currency Input Field

3.1 Bean Properties
3.2 Model and Display Currency
3.3 Event Handling

4. Example/Test Application

4.1 Automated Tests
4.2 Test Application

5. Changes

6. References

Goto Start


1. Introduction

1.1 The package magie.currency

The package magie.currency and all its sub-packages and extensions is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the

Free Software Foundation, Inc.,
59 Temple Place,
Suite 330, Boston,
MA 02111-1307
USA

Or visit http://www.gnu.org/copyleft/lesser.html.

1.2 Requirements

The legal requirements are defined in the EC Guideline No. 1103/97, Article 4, 5 (see [2]). The most important legal requirements include:

The package uses the following EUR-Currencies and exchange rates:

Unit Country Rate Digits
ATSAustria13.76032
BEFBelgium40.33992
DEMGermany1.955832
ESPSpain166.3862
FIMFinland5.945732
FRFFrance6.559572
IEPIreland0.7875642
ITLItaly1936.270
LUFLuxembourg40.33992
NLGNetherlands2.203712
PTEPortugal200.4822
EUREuropean Union1.000002

1.3 Usage

The library, which consists of two core parts, can be used in the following way:

1.4 Structure

The following table provides an overview about the packages of the magie.currency library and its objectives:

package description
magie.currency The domain classes for the currency library: Currency, currency units and the required exceptions.
magie.currency.ui The classes of the CurrencyField bean, including events, bean property editors and bean icons
magie.currency.testcase A JUnit test class to test the domain classes
magie.currency.ui.test The Currency Test Application

1.5 Application specific solutions

Non-EUR Currencies are not provided, nor mechanisms to perform currency conversion. In order to extend the package, the abstract Currency Unit classes may be subclassed to implement this behavior.

In addition, all application systems are responsible for

Goto Start


2. Domain Classes

The core business functionality of the Euro converter is done within the classes of the currency domain package magie.currency. The following class diagram shows the classes of this package, the attributes and the business methods.

Class Diagram

Figure 1: Class diagram domain classes

2.1 Currency

The class Currency, defined in the package magie.currency, is the model for monetary amounts used in the application's domain. It replaces objects of the type Double, which may be used in single currency unit application, in order to make monetary amounts dependent on their currency unit. Therefor the class Currency is composed of two attributes,

Field Description
private double amount; the monetary value of the currency
private CurrencyUnit unit; the unit of the currency

In addition, the Currency class provides and encapsulates the business behavior for the domain related to monetary values, as there are:

Method Functionality
Currency() construction
roundedToScale() round to the defined scale
add() add a Currency to 'nother
substract() subtract a Currency from another
multiply() multiply Currency with a factor
divide() divide Currency by a factor or another Currency
converted() convert one currency to another unit; delegates to the currency unit of the Currency object to perform the conversion
toString() provide a formatted String representation
displayString() provide another formatted String representation (without Currency Unit)
compareTo() compare two Currencies

2.2 CurrencyUnit

Class CurrencyUnit is used as unit for Currency objects. There are two different Currency Unit implementation available within the magie.currency package:

The implementation of these classes encapsulates the EUR currencies and its rates and scales. This is done with the private method

 /**
  * create all required instances of the currency units
  * and save them into the dictionary
  */
  private static void initializeEurUnits() {
    currencyUnits = new Hashtable();
    currencyUnits.put("ATS", new EurCurrencyUnit("ATS", 13.7603d));
    currencyUnits.put("BEF", new EurCurrencyUnit("BEF", 40.3399d));
    currencyUnits.put("DEM", new EurCurrencyUnit("DEM", 1.95583d));
    currencyUnits.put("ESP", new EurCurrencyUnit("ESP", 166.386d));
    currencyUnits.put("FIM", new EurCurrencyUnit("FIM", 5.94573d));
    currencyUnits.put("FRF", new EurCurrencyUnit("FRF", 6.55957d));
    currencyUnits.put("IEP", new EurCurrencyUnit("IEP", 0.787564d));
    currencyUnits.put("ITL", new EurCurrencyUnit("ITL", 1936.27d, 0));
    currencyUnits.put("LUF", new EurCurrencyUnit("LUF", 40.3399d));
    currencyUnits.put("NLG", new EurCurrencyUnit("NLG", 2.20371d));
    currencyUnits.put("PTE", new EurCurrencyUnit("PTE", 200.482d));
    currencyUnits.put("EUR", new EurCurrencyUnit("EUR", 1.00000d));
  }

The core methods are listed in the following table:

Method Functionality
CurrencyUnit() construction
getCurrencyUnit() static method to retrieve an instance of CurrencyUnit for a given ID (String)
registerCurrencyUnit() static method to add additional instances to the list of available currency units

Note, that you are not able to add additional EUR Currencies here!

convert() this method performs the Euro-conversion. It uses the following two (protected) methods to perform the conversion
convertedToEUR() convert a given Currency to EUR
convertedFromEUR() convert a given Currency from EUR

2.3 Currency Conversion

The Euro-Conversion is performed in a two-step-procedure

  1. convert source Currency to EUR
  2. convert EUR to target currency

The following method definition illustrates the implementation of this approach:

 /**
  * convert Currency aCurrency into the given CurrencyUnit
  *
  * @param  aCurrency (Currency) Currency to be converted
  * @param  newCurrencyUnit (Type) destination CurrencyUnit
  * @return (Currency) the converted Currency
  */
  public Currency convert(Currency aCurrency, CurrencyUnit newCurrencyUnit)
                        throws CurrencyConversionException {

    Currency curr = aCurrency;
    // 1. convert currency to EUR
    if(!curr.getUnit().isEUR()) {
      curr = convertedToEUR(curr);
    }
    // 2. convert EUR to target currency
    if(!newCurrencyUnit.isEUR()) {
      curr = newCurrencyUnit.convertedFromEUR(curr);
    }
    return curr;
  }

I'd like to discuss some special behavior here:

2.4 Arithmetic Operations

The arithmetic operations of the Currency class are based on some general rules:

2.5 Rounding Differences

In the available library release the tracking of rounding differences resulting from arithmetic operations and/or conversions is not implemented. This fact is important especially for the addition of converted Currencies: Keep in mind, that the sum of converted currencies might be different from the converted sum of the currencies! The application using the library is responsible for the correct use of the classes by itself.

2.6 Exceptions

For passing error states to the applications, that uses the library, two Exception subclasses have been provided:

Goto Start


3. Currency Input Field

The CurrencyField is a subclass of JTextField which is aimed to edit Currency instances directly. Therefor the widget references a Currency object, to which it is connected. Applications can access this Currency object with the getCurrency() and setCurrency() methods of the field.

3.1 Bean Properties

The CurrencyField is implemented as JavaBean, adding several properties to customise the field according to application requirements.

Property Description
showUnit Indicates if the currency unit is displayed
resetInvalidEntry If set to true, display is cleared after invalid entry
displayCurrency CurrencyUnit in which the currency is displayed
modelCurrency CurrencyUnit into which new currencies are converted

In order to define the properties at built-time, for the properties showUnit and resetInvalidEntry are supported by two Property Editors, the classes ResetInvalidEntryEditor and ShowUnitEditor, which simply subclass PropertyEditorSupport.

3.2 Model and Display Currency

Two CurrencyUnits can be passed to the CurrencyField to control its behavior with regards of conversion of currencies:

The Model Currency can thus be used to ensure, that inputs of monetary amounts are assigned with the right currency unit. For example, when the Model Currency of all Currency Fields is set to a system currency, all currencies in the system are processed in this currency unit. The Model Currency should be the "target" Currency Unit, e.g. the unit in which the data are stored in a database. The currency property f the Currency Field is converted to the Model Currency unit when the setModelCurrency() is called. After a focusLost() call of the Currency Field the input value is parsed, a Currency is instantiated and the result is converted to the Model Currency.

The Display Currency enables the end user of the library to display currencies in a preferred Currency Unit. For example, the user can select the Display Currency from a Choice within his application and all monetary amounts are displayed in this Currency Unit without impacting the Currency Unit, in which the data are stored or processed.

Both Currency Units may be set to null. The following table indicates, which behavior is gained with all possible use cases:

Model Currency Display Currency Display Currency
null null Currency is displayed as is. If no Currency Unit is entered, Currencies are parsed using the Currency Unit of the edited Currency
a valid
EurCurrencyUnit
null Currency is displayed in Model Currency Currencies are created in the Model Currency. If a Currency Unit is entered the Currency is converted to the Model Currency.
a valid
EurCurrencyUnit
the same
EurCurrencyUnit
Currency is displayed in Model/Display Currency ditto.
a valid
EurCurrencyUnit
another valid
EurCurrencyUnit
Currency is displayed in Display Currency ditto.
null a valid
EurCurrencyUnit
Currency is displayed in the Display Currency ditto.
a CurrencyUnit a valid
EurCurrencyUnit
Currency can not be displayed converted

Currency is displayed in Model Currency, red and always with unit

Currencies are created in Model Currency. If a Currency Unit other than the Model Currency unit is entered, the input is not accepted.
a valid
EurCurrencyUnit
a CurrencyUnit Currency can not be displayed converted

Currency is displayed in Model Currency, red and always with unit

ditto.

3.3 Event Handling

The CurrencyField defines its own event to notify its CUrrencyChangeListeners about changes of the edited Currency. Therefore the following methods are used:

Method Functionality
addCurrencyChangeListener assign a CurrencyChangeListener to the field
removeCurrencyChangeListener removes a CurrencyChangeListener from the field
fireCurrencyChange notifies listeners about currency change

For this event notification the interface CurrencyChangeListener, extending the EventListener interface, was introduced. It simply defines one method, the currencyChanged() method, which uses a CurrencyEvent, another extension of the class AWTEvent, as argument.

Goto Start


4. Example/Test Application

4.1 Automated Tests

To test the Euro-Converter library a JUnit test case was implemented. The test case can be found in the package magie.currency.testcase in the class CurrencyTestCase. This class extends the class TestCase of the JUnit testing framework. For all tests a testing method is implemented as Java code. The table shows, what is being tested. See source code for further details!

Test method Description
testCurrencyCreation Tests the creation (construction and parsing) of Currencies
testCalculation Tests the arithmetic operations
testConversion Tests the currency conversion
testRoundedToScale Tests the rounding to the appropriate scale
testLargeAmounts Tests for correct processing or large amounts
testNonEuroCurrencies Tests for Exceptions converting none-EUR currencies
testCurrencyCreationException Tests for Exceptions occurring on bad Currency creation
testCalculationException Tests for Exceptions occurring on bad use of arithmetic operations

4.2 Test Application

To test the Currency Input Field bean and to demonstrate the usage of the classes the class CurrencyTestApplication in the package magie.currency.ui.test is used.

The core widget of the little test application is the CurrencyField, labelled "A Currency". This can be used to enter monetary amounts and display them. The display field labelled "The Model" provides a toString() representation of the Currency object edited by the CurrencyField. All bean properties as listed in the above can be changed by the Checkboxes and the Choices in the frame:

Currency Test Application

Figure 2: Currency Test Application

The frame itself is implemented as CurrencyChangeListener in order to be notified on Currency change. Here the currencyChanged() method displays the edited Currency in the display field.

The CurrencyField's handleException() method is overridden by an anonymous inner class, which simply outputs Exceptions, which are thrown by the Currency class to the CurrencyField (and usually caught and handled by the widget). With this mechanisms application specific behavior can be added to the bean, e.g. to notify the user about an invalid entry, using the application specific message handling mechanisms.

Goto Start


5. Changes:

1.0

Creation

1.0a

Euro currency hierarchy introduced in order to provide flexibility to use non-Euro currencies

1.0b

Currency conversion is now delegated to the class EurCurrencyUnit

1.1

urrency now works with BigDecimal amounts to increase precision

1.1a

Arithmethic methods changed to BigDecimal arithmetic; Package info updated

Goto Start


6. References

[R1] GNU Lesser General Public License

[R2] Verordnung (EG) Nr. 1103/97 des Rates vom 17. Juni über bestimmte Vorschriften im Zusammenhang mit der Einführung des Euro

[R3] JUnit Documentation http://www.armaties.com/extreme.htm

[R4] Download Sources here.

Goto Start


Author: Markus Giebeler
Last Update: 27.11.2000 - 09:24