NEW - bug 409063: Support ICU4J 50+ and before 
https://bugs.eclipse.org/bugs/show_bug.cgi?id=409063
diff --git a/bundles/org.eclipse.uomo.business.tests/src/org/eclipse/uomo/business/money/SmokeTests.java b/bundles/org.eclipse.uomo.business.tests/src/org/eclipse/uomo/business/money/SmokeTests.java
new file mode 100644
index 0000000..75fdf9d
--- /dev/null
+++ b/bundles/org.eclipse.uomo.business.tests/src/org/eclipse/uomo/business/money/SmokeTests.java
@@ -0,0 +1,61 @@
+/**

+ * Copyright (c) 2005, 2013, Werner Keil and others.

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v1.0

+ * which accompanies this distribution, and is available at

+ * http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *    Werner Keil and others - initial API and implementation

+ */

+

+package org.eclipse.uomo.business.money;

+

+import static org.junit.Assert.assertEquals;

+import static org.junit.Assert.assertNotNull;

+

+import org.eclipse.uomo.business.internal.CurrencyUnit;

+import org.eclipse.uomo.business.internal.ExchangeRate;

+import org.eclipse.uomo.business.internal.ExchangeRateType;

+import org.eclipse.uomo.business.internal.MonetaryAmount;

+import org.eclipse.uomo.business.types.IMoney;

+

+import java.math.RoundingMode;

+import java.util.Locale;

+

+import org.junit.Test;

+import java.util.logging.Logger;

+

+public class SmokeTests {

+	private static final Logger LOGGER = Logger.getLogger(SmokeTests.class.getName());

+

+	private static final ExchangeRateType RATE_TYPE = ExchangeRateType

+			.of("EZB");

+

+	@Test

+	public void testCreateAmounts() {

+		// Creating one

+		CurrencyUnit currency = MoneyUnit.of("CHF");

+		MonetaryAmount amount1 = MoneyAmount.of(1.0d, currency);

+		MonetaryAmount amount2 = MoneyAmount.of(1.0d, currency);

+		MonetaryAmount amount3 = amount1.add(amount2);

+		LOGGER.fine(amount1 + " + " + amount2 + " = " + amount3);

+		assertEquals("ISO-4217", currency.getNamespace());

+		assertEquals(1.0d, amount1.doubleValue(), 0);

+		assertEquals(1.0d, amount2.doubleValue(), 0);

+		assertEquals(2.0d, amount3.doubleValue(), 0);

+	}

+

+	@Test

+	public void testCreateIMoney() {

+		// Creating one

+		IMoney amount1 = MoneyAmount.of("CHF", 1.0d);

+		IMoney amount2 = MoneyAmount.of("CHF", 1.0d);

+		IMoney amount3 = (IMoney) amount1.add(amount2);

+		LOGGER.fine(amount1 + " + " + amount2 + " = " + amount3);

+		assertEquals(1.0d, amount1.value().doubleValue(), 0);

+		assertEquals(1.0d, amount2.value().doubleValue(), 0);

+		assertEquals(2.0d, amount3.value().doubleValue(), 0);

+	}

+}

+

diff --git a/bundles/org.eclipse.uomo.business/src/main/java/org/eclipse/uomo/business/internal/ExchangeRateType.java b/bundles/org.eclipse.uomo.business/src/main/java/org/eclipse/uomo/business/internal/ExchangeRateType.java
index 27f5518..8b8c6ee 100644
--- a/bundles/org.eclipse.uomo.business/src/main/java/org/eclipse/uomo/business/internal/ExchangeRateType.java
+++ b/bundles/org.eclipse.uomo.business/src/main/java/org/eclipse/uomo/business/internal/ExchangeRateType.java
@@ -3,6 +3,11 @@
  */

 package org.eclipse.uomo.business.internal;

 

+import java.io.Serializable;

+import java.util.Collection;

+import java.util.Map;

+import java.util.concurrent.ConcurrentHashMap;

+

 

 /**

  * This class models the type of a given exchange rate as immutable value type.

@@ -14,13 +19,121 @@
  * @author Werner Keil

  * @deprecated stub

  */

-public interface ExchangeRateType {

+public final class ExchangeRateType implements Serializable,

+Comparable<ExchangeRateType> {

+

+	/** The id of this type. */

+	private final String id;

+	/** The cache of types. */

+	private static final Map<String, ExchangeRateType> CACHED_INSTANCES = new ConcurrentHashMap<String, ExchangeRateType>();

 

 	/**

-	 * Get the (non localized) identifier of the {@link ExchangeRateType}.

+	 * Creates a new instance.

+	 * 

+	 * @param id

+	 *            The rate identifier.

+	 * @return The new rate type.

+	 */

+	public static ExchangeRateType of(String id) {

+		if (id == null) {

+			throw new IllegalArgumentException("id required.");

+		}

+		ExchangeRateType instance = CACHED_INSTANCES.get(id);

+		if (instance == null) {

+			instance = new ExchangeRateType(id);

+			CACHED_INSTANCES.put(id, instance);

+		}

+		return instance;

+	}

+

+	/**

+	 * Get all cached rate types.

+	 * 

+	 * @return all cached rate types.

+	 */

+	public static Collection<ExchangeRateType> getTypes() {

+		return CACHED_INSTANCES.values();

+	}

+

+	/**

+	 * Constructs a new instance of an ExchangeRateType..

+	 * 

+	 * @param id

+	 *            The id of this type instance, never null.

+	 */

+	public ExchangeRateType(String id) {

+		if (id == null) {

+			throw new IllegalArgumentException("Id must not be null.");

+		}

+		this.id = id;

+	}

+

+	/**

+	 * Get the identifier of this instance.

 	 * 

 	 * @return The identifier, never null.

 	 */

-	public String getId();

+	public String getId() {

+		return this.id;

+	}

+

+	/*

+	 * (non-Javadoc)

+	 * 

+	 * @see java.lang.Object#hashCode()

+	 */

+	@Override

+	public int hashCode() {

+		final int prime = 31;

+		int result = 1;

+		result = prime * result + ((id == null) ? 0 : id.hashCode());

+		return result;

+	}

+

+	/*

+	 * (non-Javadoc)

+	 * 

+	 * @see java.lang.Object#equals(java.lang.Object)

+	 */

+	@Override

+	public boolean equals(Object obj) {

+		if (this == obj)

+			return true;

+		if (obj == null)

+			return false;

+		if (getClass() != obj.getClass())

+			return false;

+		ExchangeRateType other = (ExchangeRateType) obj;

+		if (id == null) {

+			if (other.id != null)

+				return false;

+		} else if (!id.equals(other.id))

+			return false;

+		return true;

+	}

+

+	/*

+	 * (non-Javadoc)

+	 * 

+	 * @see java.lang.Object#toString()

+	 */

+	@Override

+	public String toString() {

+		return "ExchangeRateType [id=" + id + "]";

+	}

+

+	/*

+	 * (non-Javadoc)

+	 * 

+	 * @see java.lang.Comparable#compareTo(java.lang.Object)

+	 */

+	@Override

+	public int compareTo(ExchangeRateType o) {

+		if (o == null) {

+			return -1;

+		}

+		int compare = id.compareTo(o.id);

+		return compare;

+	}

 

 }

diff --git a/bundles/org.eclipse.uomo.business/src/main/java/org/eclipse/uomo/business/money/MoneyAmount.java b/bundles/org.eclipse.uomo.business/src/main/java/org/eclipse/uomo/business/money/MoneyAmount.java
index a1ed9be..87b94c5 100644
--- a/bundles/org.eclipse.uomo.business/src/main/java/org/eclipse/uomo/business/money/MoneyAmount.java
+++ b/bundles/org.eclipse.uomo.business/src/main/java/org/eclipse/uomo/business/money/MoneyAmount.java
@@ -19,6 +19,7 @@
 import org.eclipse.uomo.business.internal.MonetaryAmount;
 import org.eclipse.uomo.business.internal.MonetaryOperator;
 import org.eclipse.uomo.business.types.IMoney;
+import org.eclipse.uomo.core.UOMoRuntimeException;
 import org.eclipse.uomo.units.AbstractConverter;
 import org.eclipse.uomo.units.IMeasure;
 import org.eclipse.uomo.units.QuantityAmount;
@@ -64,7 +65,7 @@
 	}
 
 	/**
-	 * Returns the money amount corresponding to the specified BigDecimal value
+	 * Returns the money amount corresponding to the specified Number value
 	 * and currency.
 	 * 
 	 * @param value
@@ -74,12 +75,11 @@
 	 * @return the corresponding amount.
 	 */
 	public static MoneyAmount of(Number value, CurrencyUnit currency) {
-		MoneyAmount amount = new MoneyAmount(value, (MoneyUnit)currency);
-		return amount;
+		return new MoneyAmount(value, (MoneyUnit)currency);
 	}
 	
 	/**
-	 * Returns the money amount corresponding to the specified BigDecimal value
+	 * Returns the money amount corresponding to the specified Number value
 	 * and currency.
 	 * 
 	 * @param value
@@ -94,7 +94,7 @@
 //	}
 
 	/**
-	 * Returns the money amount corresponding to the specified BigDecimal value
+	 * Returns the money amount corresponding to the specified Number value
 	 * and currency.
 	 * 
 	 * @param value
@@ -104,8 +104,7 @@
 	 * @return the corresponding amount.
 	 */
 	public static MoneyAmount of(Number value, Unit<?> currency) {
-		MoneyAmount amount = new MoneyAmount(value, (MoneyUnit) currency);
-		return amount;
+		return new MoneyAmount(value, (MoneyUnit) currency);
 	}
 
 	/**
@@ -120,9 +119,8 @@
 	 * @return the corresponding amount.
 	 */
 	public static MoneyAmount of(long value, int cents, Currency currency) {
-		MoneyAmount amount = new MoneyAmount(BigDecimal.valueOf(value * 100
+		return new MoneyAmount(BigDecimal.valueOf(value * 100
 				+ cents, -2), (MoneyUnit) currency);
-		return amount;
 	}
 
 	/**
@@ -142,6 +140,21 @@
 				.doubleValue()), amount.unit().getSystemUnit());
 	}
 
+	
+	/**
+	 * Returns the money amount corresponding to the specified Number value
+	 * and currency code.
+	 * 
+	 * @param value
+	 *            the value stated in the specified currency.
+	 * @param currency
+	 *            the currency in which the value is stated.
+	 * @return the corresponding amount.
+	 */
+	public static MoneyAmount of(String code, Number value) {
+		return new MoneyAmount(value, MoneyUnit.of(code));
+	}
+	
 	/**
 	 * Overrides the default {@link #toString()} to show only the currency
 	 * {@link Currency#getFractionDigits() fraction digits} of the associated
@@ -170,6 +183,12 @@
 	// return MoneyAmount.valueOf(_value.opposite(), getCurrency());
 	// }
 
+	protected MoneyAmount plus(IMoney that) {
+		// Measure<BigDecimal, ?> amount = that.to((Unit) getCurrency());
+		return MoneyAmount.of(this.getNumber().doubleValue()
+				+ that.value().doubleValue(), getCurrency());
+	}
+	
 	protected MoneyAmount plus(MoneyAmount that) {
 		// Measure<BigDecimal, ?> amount = that.to((Unit) getCurrency());
 		return MoneyAmount.of(this.getNumber().doubleValue()
@@ -264,10 +283,6 @@
 		}
 	}
 
-	public IMeasure<IMoney> add(IMeasure<IMoney> that) {
-		return plus((MoneyAmount) that);
-	}
-
 	public IMeasure<IMoney> substract(IMeasure<IMoney> that) {
 		return minus((MoneyAmount) that);
 	}
@@ -328,6 +343,15 @@
 			// value.getClass());
 		}
 	}
+	
+	private final BigDecimal bigNumber() {
+		if (getNumber() instanceof BigDecimal) {
+			return (BigDecimal)getNumber();
+		} else {
+			throw new UOMoRuntimeException(
+					new IllegalArgumentException("Cannot represent as BigDecimal"));
+		}
+	}
 
 	/**
 	 * Generate a 'preference neutral' string from Money value.
@@ -359,13 +383,6 @@
 		return null;
 	}
 
-	 
-	public MonetaryAmount add(MonetaryAmount augend) {
-		// TODO Auto-generated method stub
-		return null;
-	}
-
-	 
 	public MonetaryAmount add(Number augend) {
 		// TODO Auto-generated method stub
 		return null;
@@ -502,75 +519,137 @@
 		return null;
 	}
 
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see MonetaryAmount#getScale()
+	 */
 	public int getScale() {
-		// TODO Auto-generated method stub
-		return 0;
+		return this.bigNumber().scale();
 	}
 
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see MonetaryAmount#getPrecision()
+	 */
 	public int getPrecision() {
-		// TODO Auto-generated method stub
-		return 0;
+		//return bigNumber().precision(); // FIXME in ICU4J 50+
+		return -1;
 	}
 
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see MonetaryAmount#intValue()
+	 */
 	public int intValue() {
-		// TODO Auto-generated method stub
-		return 0;
+		return this.getNumber().intValue();
 	}
 
-	 
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see MonetaryAmount#intValueExact()
+	 */
 	public int intValueExact() {
-		// TODO Auto-generated method stub
-		return 0;
+		return bigNumber().intValueExact();
 	}
 
-	 
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see MonetaryAmount#longValue()
+	 */
 	public long longValue() {
-		// TODO Auto-generated method stub
-		return 0;
+		return this.getNumber().longValue();
 	}
 
-	 
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see MonetaryAmount#longValueExact()
+	 */
 	public long longValueExact() {
-		// TODO Auto-generated method stub
-		return 0;
+		return bigNumber().longValueExact();
 	}
 
-	 
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see MonetaryAmount#floatValue()
+	 */
 	public float floatValue() {
-		// TODO Auto-generated method stub
-		return 0;
+		return this.getNumber().floatValue();
 	}
 
-	 
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see MonetaryAmount#doubleValue()
+	 */
 	public double doubleValue() {
-		// TODO Auto-generated method stub
-		return 0;
+		return this.getNumber().doubleValue();
 	}
 
-	 
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see MonetaryAmount#byteValue()
+	 */
 	public byte byteValue() {
-		// TODO Auto-generated method stub
-		return 0;
+		return this.getNumber().byteValue();
 	}
 
-	 
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see MonetaryAmount#shortValue()
+	 */
 	public short shortValue() {
-		// TODO Auto-generated method stub
-		return 0;
+		return getNumber().shortValue();
 	}
 
-	 
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see MonetaryAmount#shortValueExact()
+	 */
 	public short shortValueExact() {
-		// TODO Auto-generated method stub
-		return 0;
+		return bigNumber().shortValueExact();
 	}
 
-	 
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see MonetaryAmount#signum()
+	 */
+
 	public int signum() {
-		// TODO Auto-generated method stub
-		return 0;
+		return bigNumber().signum();
 	}
 
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see MonetaryAmount#toEngineeringString()
+	 */
+	public String toEngineeringString() {
+		return getCurrency().getCurrencyCode() + ' '
+				//+ bigNumber().toEngineeringString(); // FIXME in ICU4J 50+
+				+ bigNumber().toString();
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see MonetaryAmount#toPlainString()
+	 */
+	public String toPlainString() {
+		return getCurrency().getCurrencyCode() + ' '
+				//+ bigNumber().toPlainString();  // FIXME in ICU4J 50+
+				+ bigNumber().toString();
+	}
 	 
 	public boolean isLessThan(MonetaryAmount amount) {
 		// TODO Auto-generated method stub
@@ -612,11 +691,9 @@
 	}
 
 	public Class<?> getNumberType() {
-		// TODO Auto-generated method stub
 		return getNumber().getClass();
 	}
 
-	 
 	public MoneyAmount multiply(MonetaryAmount multiplicand) {
 		// TODO Auto-generated method stub
 		return null;
@@ -625,4 +702,14 @@
 	public CurrencyUnit getCurrency() {
 		return (CurrencyUnit)unit();
 	}
+
+	@Override
+	public IMoney add(IMeasure<IMoney> that) {
+		return plus((IMoney) that);
+	}
+
+	@Override
+	public MonetaryAmount add(MonetaryAmount augend) {
+		return plus((MoneyAmount) augend);
+	}
 }
\ No newline at end of file
diff --git a/bundles/org.eclipse.uomo.business/src/main/java/org/eclipse/uomo/business/money/MoneyCurrency.java b/bundles/org.eclipse.uomo.business/src/main/java/org/eclipse/uomo/business/money/MoneyCurrency.java
index 52e4ad0..841dfa6 100644
--- a/bundles/org.eclipse.uomo.business/src/main/java/org/eclipse/uomo/business/money/MoneyCurrency.java
+++ b/bundles/org.eclipse.uomo.business/src/main/java/org/eclipse/uomo/business/money/MoneyCurrency.java
@@ -701,4 +701,12 @@
 

 	}

 

+	public String getDisplayName(Locale locale) {

+		return getName(ULocale.forLocale(locale), LONG_NAME, new boolean[1]);

+	}

+

+	public int getNumericCode() {

+		return -1;

+	}

+

 }

diff --git a/bundles/org.eclipse.uomo.business/src/main/java/org/eclipse/uomo/business/money/MoneyExchangeRate.java b/bundles/org.eclipse.uomo.business/src/main/java/org/eclipse/uomo/business/money/MoneyExchangeRate.java
index 9fb6a8a..e4ffd8b 100644
--- a/bundles/org.eclipse.uomo.business/src/main/java/org/eclipse/uomo/business/money/MoneyExchangeRate.java
+++ b/bundles/org.eclipse.uomo.business/src/main/java/org/eclipse/uomo/business/money/MoneyExchangeRate.java
@@ -18,21 +18,13 @@
 import com.ibm.icu.util.Currency;

 

 /**

- * @version 0.2

+ * @version 0.3

  * @author Werner Keil

  * 

  */

 public class MoneyExchangeRate implements ExchangeRate {

 

-	public static enum Type implements ExchangeRateType {

-		DEFAULT;

-

-		public String getId() {

-			return name();

-		}

-	}

-

-	private final Type type;

+	private final ExchangeRateType type;

 

 	private final Currency source;

 

@@ -44,7 +36,7 @@
 		this.source = source;

 		this.target = target;

 		this.factor = factor;

-		type = Type.DEFAULT;

+		type = ExchangeRateType.of("DEFAULT");

 	}

 

 	/*

diff --git a/bundles/org.eclipse.uomo.business/src/main/java/org/eclipse/uomo/business/money/MoneyUnit.java b/bundles/org.eclipse.uomo.business/src/main/java/org/eclipse/uomo/business/money/MoneyUnit.java
index 35bb018..144a9e1 100644
--- a/bundles/org.eclipse.uomo.business/src/main/java/org/eclipse/uomo/business/money/MoneyUnit.java
+++ b/bundles/org.eclipse.uomo.business/src/main/java/org/eclipse/uomo/business/money/MoneyUnit.java
@@ -13,6 +13,7 @@
 import static org.eclipse.uomo.business.money.MonetaryUnits.ISO_NAMESPACE;

 

 import java.math.BigInteger;

+import java.util.Locale;

 import java.util.Map;

 

 import org.eclipse.uomo.units.AbstractConverter;

@@ -477,4 +478,12 @@
 	public static MoneyUnit of(String currencyCode) {

 		return new MoneyUnit(currencyCode);

 	}

+

+	public String getDisplayName(Locale locale) {

+		return getName(ULocale.forLocale(locale), LONG_NAME, new boolean[1]);

+	}

+

+	public int getNumericCode() {

+		return -1;

+	}

 }

diff --git a/bundles/org.eclipse.uomo.units/src/main/java/org/eclipse/uomo/units/QuantityAmount.java b/bundles/org.eclipse.uomo.units/src/main/java/org/eclipse/uomo/units/QuantityAmount.java
index 7b3e4d1..0f5a02e 100644
--- a/bundles/org.eclipse.uomo.units/src/main/java/org/eclipse/uomo/units/QuantityAmount.java
+++ b/bundles/org.eclipse.uomo.units/src/main/java/org/eclipse/uomo/units/QuantityAmount.java
@@ -42,9 +42,8 @@
 	/**

 	 * Holds a dimensionless measure of one (exact).

 	 */

-	@SuppressWarnings("unchecked")

 	public static final Quantity<Dimensionless> ONE =

-			QuantityFactory.getInstance(QuantityAmount.class).create(

+			QuantityFactory.getInstance(Dimensionless.class).create(

 					BigDecimal.ONE, AbstractUnit.ONE);

 	

 	/*