diff --git a/src/main/java/org/fhir/ucum/BaseUnit.java b/src/main/java/org/fhir/ucum/BaseUnit.java index 300023a..ee577b5 100644 --- a/src/main/java/org/fhir/ucum/BaseUnit.java +++ b/src/main/java/org/fhir/ucum/BaseUnit.java @@ -13,8 +13,9 @@ public class BaseUnit extends Unit { - - /** + private static final long serialVersionUID = 2694895021527732848L; + + /** * abbrevation for property */ private char dim; diff --git a/src/main/java/org/fhir/ucum/Concept.java b/src/main/java/org/fhir/ucum/Concept.java index fb2acd4..ef6fe7f 100644 --- a/src/main/java/org/fhir/ucum/Concept.java +++ b/src/main/java/org/fhir/ucum/Concept.java @@ -11,12 +11,15 @@ package org.fhir.ucum; +import java.io.Serializable; import java.util.ArrayList; import java.util.List; -public class Concept { +public class Concept implements Serializable { - private ConceptKind kind; + private static final long serialVersionUID = 4762687914157070849L; + + private ConceptKind kind; /** * case sensitive code for this concept */ diff --git a/src/main/java/org/fhir/ucum/Decimal.java b/src/main/java/org/fhir/ucum/Decimal.java index f944329..5b26f5b 100644 --- a/src/main/java/org/fhir/ucum/Decimal.java +++ b/src/main/java/org/fhir/ucum/Decimal.java @@ -1,802 +1,806 @@ -package org.fhir.ucum; - -/******************************************************************************* - * Crown Copyright (c) 2006 - 2014, Copyright (c) 2006 - 2014 Kestral Computing & Health Intersections P/L. - * 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: - * Kestral Computing P/L - initial implementation (pascal) - * Health Intersections P/L - port to Java - *******************************************************************************/ - -/** - Precision aware Decimal implementation. Any size number with any number of significant digits is supported. - - Note that operations are precision aware operations. Note that whole numbers are assumed to have - unlimited precision. For example: - 2 x 2 = 4 - 2.0 x 2.0 = 4.0 - 2.00 x 2.0 = 4.0 - and - 10 / 3 = 3.33333333333333333333333333333333333333333333333 - 10.0 / 3 = 3.33 - 10.00 / 3 = 3.333 - 10.00 / 3.0 = 3.3 - 10 / 3.0 = 3.3 - - Addition - 2 + 0.001 = 2.001 - 2.0 + 0.001 = 2.0 - - Note that the string representation is precision limited, but the internal representation - is not. - - - * This class is defined to work around the limitations of Java Big Decimal - * - * @author Grahame - * - */ -public class Decimal { - - private int precision; - private boolean scientific; - private boolean negative; - private String digits; - private int decimal; - - private Decimal() { - super(); - } - - public Decimal(String value) throws UcumException { - super(); - value = value.toLowerCase(); - if (value.contains("e")) - setValueScientific(value); - else - setValueDecimal(value); - } - - /** - * There are a few circumstances where a simple value is known to be correct to a high - * precision. For instance, the unit prefix milli is not ~0.001, it is precisely 0.001 - * to whatever precision you want to specify. This constructor allows you to specify - * an alternative precision than the one implied by the stated string - * - * @param value - a string representation of the value - * @param precision - a - * @throws UcumException - * @ - */ - public Decimal(String value, int precision) throws UcumException { - super(); - value = value.toLowerCase(); - if (value.contains("e")) - setValueScientific(value); - else - setValueDecimal(value); - this.precision = precision; - } - - public Decimal(int i) { - super(); - try { - setValueDecimal(Integer.toString(i)); - } catch (Exception e) { - } - } - - private void setValueDecimal(String value) throws UcumException { - // var - // dec : integer; - // i : integer; - scientific = false; - int dec = -1; - negative = value.startsWith("-"); - if (negative) - value = value.substring(1); - - while (value.startsWith("0") && value.length() > 1) - value = value.substring(1); - - for (int i = 0; i < value.length(); i++) { - if (value.charAt(i) == '.' && dec == -1) - dec = i; - else if (!Character.isDigit(value.charAt(i))) - throw new UcumException("'"+value+"' is not a valid decimal"); - } - - if (dec == -1) { - precision = value.length(); - decimal = value.length(); - digits = value; - } else if (dec == value.length() -1) - throw new UcumException("'"+value+"' is not a valid decimal"); - else { - decimal = dec; - if (allZeros(value, 1)) - precision = value.length() - 1; - else - precision = countSignificants(value); - digits = delete(value, decimal, 1); - if (allZeros(digits, 0)) - precision++; - else - while (digits.charAt(0) == '0') { - digits = digits.substring(1); - decimal--; - } - } - } - - private boolean allZeros(String s, int start) { - boolean result = true; - for (int i = start; i < s.length(); i++) { - if (s.charAt(i) != '0') - result = false; - } - return result; - } - - private int countSignificants(String value) { - int i = value.indexOf("."); - if (i > -1) - value = delete(value, i, 1); - while (value.charAt(0) == '0') - value = value.substring(1); - return value.length(); - } - - private String delete(String value, int offset, int length) { - if (offset == 0) - return value.substring(length); - else - return value.substring(0, offset)+value.substring(offset+length); - } - - private void setValueScientific(String value) throws UcumException { - int i = value.indexOf("e"); - String s = value.substring(0, i); - String e = value.substring(i+1); - - if (Utilities.noString(s) || s.equals("-") || !Utilities.isDecimal(s)) - throw new UcumException("'"+value+"' is not a valid decimal (numeric)"); - if (Utilities.noString(e) || e.equals("-") || !Utilities.isInteger(e)) - throw new UcumException("'"+value+"' is not a valid decimal (exponent)"); - - setValueDecimal(s); - scientific = true; - - // now adjust for exponent - - if (e.charAt(0) == '-') - i = 1; - else - i = 0; - while (i < e.length()) { - if (!Character.isDigit(e.charAt(i))) - throw new UcumException(""+value+"' is not a valid decimal"); - i++; - } - i = Integer.parseInt(e); - decimal = decimal + i; - } - - private String stringMultiply(char c, int i) { - return Utilities.padLeft("", c, i); - } - - private String insert(String ins, String value, int offset) { - if (offset == 0) - return ins+value; - else - return value.substring(0, offset)+ins+value.substring(offset); - } - - @Override - public String toString() { - return asDecimal(); - } - - public Decimal copy() { - Decimal result = new Decimal(); - result.precision = precision; - result.scientific = scientific; - result.negative = negative; - result.digits = digits; - result.decimal = decimal; - return result; - } - - public static Decimal zero() { - try { - return new Decimal("0"); - } catch (Exception e) { - return null; // won't happen - } - } - - public boolean isZero() { - return allZeros(digits, 0); - } - - public static Decimal one() { - try { - return new Decimal("1"); - } catch (Exception e) { - return null; // won't happen - } - } - - public boolean isOne() { - Decimal one = one(); - return comparesTo(one) == 0; - } - - public boolean equals(Decimal other) { - return comparesTo(other) == 0; - } - - public int comparesTo(Decimal other) { - // s1, s2 : AnsiString; - if (other == null) - return 0; - - if (this.negative && !other.negative) - return -1; - else if (!this.negative && other.negative) - return 1; - else { - int max = Math.max(this.decimal, other.decimal); - String s1 = stringMultiply('0', max - this.decimal+1) + this.digits; - String s2 = stringMultiply('0', max - other.decimal+1) + other.digits; - if (s1.length() < s2.length()) - s1 = s1 + stringMultiply('0', s2.length() - s1.length()); - else if (s2.length() < s1.length()) - s2 = s2 + stringMultiply('0', s1.length() - s2.length()); - int result = s1.compareTo(s2); - if (this.negative) - result = -result; - return result; - } - } - - public boolean isWholeNumber() { - return !asDecimal().contains("."); - } - - public String asDecimal() { - String result = digits; - if (decimal != digits.length()) - if (decimal < 0) - result = "0."+stringMultiply('0', 0-decimal)+digits; - else if (decimal < result.length()) - if (decimal == 0) - result = "0."+result; - else - result = insert(".", result, decimal); - else - result = result + stringMultiply('0', decimal - result.length()); - if (negative && !allZeros(result, 0)) - result = "-" + result; - return result; - } - - public int asInteger() throws UcumException { - if (!isWholeNumber()) - throw new UcumException("Unable to represent "+toString()+" as an integer"); - if (comparesTo(new Decimal(Integer.MIN_VALUE)) < 0) - throw new UcumException("Unable to represent "+toString()+" as a signed 8 byte integer"); - if (comparesTo(new Decimal(Integer.MAX_VALUE)) > 0) - throw new UcumException("Unable to represent "+toString()+" as a signed 8 byte integer"); - return Integer.parseInt(asDecimal()); - } - - public String asScientific() { - String result = digits; - boolean zero = allZeros(result, 0); - if (zero) { - if (precision < 2) - result = "0e0"; - else - result = "0."+stringMultiply('0', precision-1)+"e0"; - } else { - if (digits.length() > 1) - result = insert(".", result, 1); - result = result + 'e'+Integer.toString(decimal - 1); - } - if (negative && !zero) - result = '-' + result; - return result; - } - - public Decimal trunc() { - if (decimal < 0) - return zero(); - - Decimal result = copy(); - if (result.digits.length() >= result.decimal) - result.digits = result.digits.substring(0, result.decimal); - if (Utilities.noString(result.digits)) { - result.digits = "0"; - result.decimal = 1; - result.negative = false; - } - return result; - } - - - public Decimal add(Decimal other) { - if (other == null) - return null; - - if (negative == other.negative) { - Decimal result = doAdd(other); - result.negative = negative; - return result; - } else if (negative) - return other.doSubtract(this); - else - return doSubtract(other); - } - - public Decimal subtract(Decimal other) { - if (other == null) - return null; - - Decimal result; - if (negative && !other.negative) { - result = doAdd(other); - result.negative = true; - } else if (!negative && other.negative) { - result = doAdd(other); - } else if (negative && other.negative) { - result = doSubtract(other); - result.negative = !result.negative; - } else { - result = other.doSubtract(this); - result.negative = !result.negative; - } - return result; - } - - - private Decimal doAdd(Decimal other) { - int max = Math.max(decimal, other.decimal); - String s1 = stringMultiply('0', max - decimal+1) + digits; - String s2 = stringMultiply('0', max - other.decimal+1) + other.digits; - if (s1.length() < s2.length()) - s1 = s1 + stringMultiply('0', s2.length() - s1.length()); - else if (s2.length() < s1.length()) - s2 = s2 + stringMultiply('0', s1.length() - s2.length()); - - String s3 = stringAddition(s1, s2); - - if (s3.charAt(0) == '1') - max++; - else - s3 = delete(s3, 0, 1); - - if (max != s3.length()) { - if (max < 0) - throw new Error("Unhandled"); - else if (max < s3.length()) - s3 = insert(".", s3, max); - else - throw new Error("Unhandled"); - } - - Decimal result = new Decimal(); - try { - result.setValueDecimal(s3); - } catch (Exception e) { - // won't happen - } - result.scientific = scientific || other.scientific; - // todo: the problem with this is you have to figure out the absolute precision and take the lower of the two, not the relative one - if (decimal < other.decimal) - result.precision = precision; - else if (other.decimal < decimal) - result.precision = other.precision; - else - result.precision = Math.min(precision, other.precision); - return result; - } - - private int dig(char c) { - return (c) - ('0'); - } - - private char cdig(int i) { - return (char) (i + ('0')); - } - - private Decimal doSubtract(Decimal other) { - int max = Math.max(decimal, other.decimal); - String s1 = stringMultiply('0', max - decimal+1) + digits; - String s2 = stringMultiply('0', max - other.decimal+1) + other.digits; - if (s1.length() < s2.length()) - s1 = s1 + stringMultiply('0', s2.length() - s1.length()); - else if (s2.length() < s1.length()) - s2 = s2 + stringMultiply('0', s1.length() - s2.length()); - - String s3; - boolean neg = (s1.compareTo(s2) < 0); - if (neg) { - s3 = s2; - s2 = s1; - s1 = s3; - } - - s3 = stringSubtraction(s1, s2); - - if (s3.charAt(0) == '1') - max++; - else - s3 = delete(s3, 0, 1); - if (max != s3.length()) { - if (max < 0) - throw new Error("Unhandled"); - else if (max < s3.length()) - s3 = insert(".", s3, max); - else - throw new Error("Unhandled"); - } - - Decimal result = new Decimal(); - try { - result.setValueDecimal(s3); - } catch (Exception e) { - // won't happen - } - result.negative = neg; - result.scientific = scientific || other.scientific; - if (decimal < other.decimal) - result.precision = precision; - else if (other.decimal < decimal) - result.precision = other.precision; - else - result.precision = Math.min(precision, other.precision); - return result; - } - - private String stringAddition(String s1, String s2) { - assert(s1.length() == s2.length()); - char[] result = new char[s2.length()]; - for (int i = 0; i < s2.length(); i++) - result[i] = '0'; - int c = 0; - for (int i = s1.length() - 1; i >= 0; i--) { - int t = c + dig(s1.charAt(i)) + dig(s2.charAt(i)); - result[i] = cdig(t % 10); - c = t / 10; - } - assert(c == 0); - return new String(result); - } - - private String stringSubtraction(String s1, String s2) { -// i, t, c : integer; - assert(s1.length() == s2.length()); - - char[] result = new char[s2.length()]; - for (int i = 0; i < s2.length(); i++) - result[i] = '0'; - - int c = 0; - for (int i = s1.length() - 1; i >= 0; i--) { - int t = c + (dig(s1.charAt(i)) - dig(s2.charAt(i))); - if (t < 0) { - t = t + 10; - if (i == 0) - throw new Error("internal logic error"); - else - s1 = replaceChar(s1, i-1, cdig(dig(s1.charAt(i-1))-1)); - } - result[i] = cdig(t); - } - assert(c == 0); - return new String(result); - } - - private String replaceChar(String s, int offset, char c) { - if (offset == 0) - return String.valueOf(c)+s.substring(1); - else - return s.substring(0, offset)+c+s.substring(offset+1); - } - - - public Decimal multiply(Decimal other) { - if (other == null) - return null; - - if (isZero() || other.isZero()) - return zero(); - - int max = Math.max(decimal, other.decimal); - String s1 = stringMultiply('0', max - decimal+1) + digits; - String s2 = stringMultiply('0', max - other.decimal+1) + other.digits; - if (s1.length() < s2.length()) - s1 = s1 + stringMultiply('0', s2.length() - s1.length()); - else if (s2.length() < s1.length()) - s2 = s2 + stringMultiply('0', s1.length() - s2.length()); - - if (s2.compareTo(s1) > 0) { - String s3 = s1; - s1 = s2; - s2 = s3; - } - String[] s = new String[s2.length()]; - - int t = 0; - for (int i = s2.length()-1; i >= 0; i--) { - s[i] = stringMultiply('0', s2.length()-(i+1)); - int c = 0; - for (int j = s1.length() - 1; j >= 0; j--) { - t = c + (dig(s1.charAt(j)) * dig(s2.charAt(i))); - s[i] = insert(String.valueOf(cdig(t % 10)), s[i], 0); - c = t / 10; - } - while (c > 0) { - s[i] = insert(String.valueOf(cdig(t % 10)), s[i], 0); - c = t / 10; - } - } - - t = 0; - for (String sv : s) - t = Math.max(t, sv.length()); - for (int i = 0; i < s.length; i++) - s[i] = stringMultiply('0', t-s[i].length())+s[i]; - - String res = ""; - int c = 0; - for (int i = t - 1; i>= 0; i--) { - for (int j = 0; j < s.length; j++) - c = c + dig(s[j].charAt(i)); - res = insert(String.valueOf(cdig(c %10)), res, 0); - c = c / 10; - } - - if (c > 0) { - throw new Error("internal logic error"); - // while.. - // s[i-1] = s[i-1] + cdig(t mod 10); - // c = t div 10; - } - - int dec = res.length() - ((s1.length() - (max+1))*2); - - while (!Utilities.noString(res) && !res.equals("0") && res.startsWith("0")) { - res = res.substring(1); - dec--; - } - - int prec = 0; - if (isWholeNumber() && other.isWholeNumber()) - // at least the specified precision, and possibly more - prec = Math.max(Math.max(digits.length(), other.digits.length()), Math.min(precision, other.precision)); - else if (isWholeNumber()) - prec = other.precision; - else if (other.isWholeNumber()) - prec = precision; - else - prec = Math.min(precision, other.precision); - while (res.length() > prec && res.charAt(res.length()-1) == '0') - res = delete(res, res.length()-1, 1); - - Decimal result = new Decimal(); - try { - result.setValueDecimal(res); - } catch (Exception e) { - // won't happen - } - result.precision = prec; - result.decimal = dec; - result.negative = negative != other.negative; - result.scientific = scientific || other.scientific; - return result; - } - - public Decimal divide(Decimal other) throws UcumException { - if (other == null) - return null; - - if (isZero()) - return zero(); - - if (other.isZero()) - throw new UcumException("Attempt to divide "+toString()+" by zero"); - - String s = "0"+other.digits; - int m = Math.max(digits.length(), other.digits.length()) + 40; // max loops we'll do - String[] tens = new String[10]; - tens[0] = stringAddition(stringMultiply('0', s.length()), s); - for (int i = 1; i < 10; i++) - tens[i] = stringAddition(tens[i-1], s); - String v = digits; - String r = ""; - int l = 0; - int d = (digits.length() - decimal + 1) - (other.digits.length() - other.decimal + 1); - - while (v.length() < tens[0].length()) { - v = v + "0"; - d++; - } - - String w; - int vi; - if (v.substring(0, other.digits.length()).compareTo(other.digits) < 0) { - if (v.length() == tens[0].length()) { - v = v + '0'; - d++; - } - w = v.substring(0, other.digits.length()+1); - vi = w.length(); - } else { - w = "0"+v.substring(0, other.digits.length()); - vi = w.length()-1; - } - - boolean handled = false; - boolean proc; - - while (!(handled && ((l > m) || ((vi >= v.length()) && ((Utilities.noString(w) || allZeros(w, 0))))))) { - l++; - handled = true; - proc = false; - for (int i = 8; i >= 0; i--) { - if (tens[i].compareTo(w) <= 0) { - proc = true; - r = r + cdig(i+1); - w = trimLeadingZeros(stringSubtraction(w, tens[i])); - if (!(handled && ((l > m) || ((vi >= v.length()) && ((Utilities.noString(w) || allZeros(w, 0))))))) { - if (vi < v.length()) { - w = w + v.charAt(vi); - vi++; - handled = false; - } else { - w = w + '0'; - d++; - } - while (w.length() < tens[0].length()) - w = '0'+w; - } - break; - } - } - if (!proc) { - assert(w.charAt(0) == '0'); - w = delete(w, 0, 1); - r = r + "0"; - if (!(handled && ((l > m) || ((vi >= v.length()) && ((Utilities.noString(w) || allZeros(w, 0))))))) { - if (vi < v.length()) { - w = w + v.charAt(vi); - vi++; - handled = false; - } else { - w = w + '0'; - d++; - } - while (w.length() < tens[0].length()) - w = '0'+w; - } - } - } - - int prec; - - if (isWholeNumber() && other.isWholeNumber() && (l < m)) { - for (int i = 0; i < d; i++) { - if (r.charAt(r.length()-1) == '0') { - r = delete(r, r.length()-1, 1); - d--; - } - } - prec = 100; - } else { - if (isWholeNumber() && other.isWholeNumber()) - prec = Math.max(digits.length(), other.digits.length()); - else if (isWholeNumber()) - prec = Math.max(other.precision, r.length() - d); - else if (other.isWholeNumber()) - prec = Math.max(precision, r.length() - d); - else - prec = Math.max(Math.min(precision, other.precision), r.length() - d); - if (r.length() > prec) { - d = d - (r.length() - prec); - char dig = r.charAt(prec); - boolean up = dig >= '5'; - if (up) { - char[] rs = r.substring(0, prec).toCharArray(); - int i = rs.length-1; - boolean carry = true; - while (carry && i >= 0) { - char ls = rs[i]; - if (ls == '9') { - rs[i] = '0'; - } else { - ls = (char) (((int) ls) + 1); - rs[i] = ls; - carry = false; - } - i--; - } - if (carry) { - r = "1"+new String(rs); - d++; // cause we added one at the start - } - else - r = new String(rs); - } else - r = r.substring(0, prec); - } - } - - Decimal result = new Decimal(); - result.setValueDecimal(r); - result.decimal = r.length() - d; - result.negative = negative != other.negative; - result.precision = prec; - result.scientific = scientific || other.scientific; - return result; - } - - - private String trimLeadingZeros(String s) { - if (s == null) - return null; - - int i = 0; - while (i < s.length() && s.charAt(i) == '0') - i++; - if (i == s.length()) - return "0"; - else - return s.substring(i); - } - - public Decimal divInt(Decimal other) throws UcumException { - if (other == null) - return null; - Decimal t = divide(other); - return t.trunc(); - } - - public Decimal modulo(Decimal other) throws UcumException { - if (other == null) - return null; - Decimal t = divInt(other); - Decimal t2 = t.multiply(other); - return subtract(t2); - } - - public boolean equals(Decimal value, Decimal maxDifference) { - Decimal diff = this.subtract(value).absolute(); - return diff.comparesTo(maxDifference) <= 0; - } - - private Decimal absolute() { - Decimal d = copy(); - d.negative = false; - return d; - } - - @Override - public boolean equals(Object other) { - if (other instanceof Decimal) - return asDecimal().equals(((Decimal) other).asDecimal()); - else - return super.equals(other); - } - - @Override - public int hashCode() { - return asDecimal().hashCode(); - } -} +package org.fhir.ucum; + +/******************************************************************************* + * Crown Copyright (c) 2006 - 2014, Copyright (c) 2006 - 2014 Kestral Computing & Health Intersections P/L. + * 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: + * Kestral Computing P/L - initial implementation (pascal) + * Health Intersections P/L - port to Java + *******************************************************************************/ + +import java.io.Serializable; + +/** + Precision aware Decimal implementation. Any size number with any number of significant digits is supported. + + Note that operations are precision aware operations. Note that whole numbers are assumed to have + unlimited precision. For example: + 2 x 2 = 4 + 2.0 x 2.0 = 4.0 + 2.00 x 2.0 = 4.0 + and + 10 / 3 = 3.33333333333333333333333333333333333333333333333 + 10.0 / 3 = 3.33 + 10.00 / 3 = 3.333 + 10.00 / 3.0 = 3.3 + 10 / 3.0 = 3.3 + + Addition + 2 + 0.001 = 2.001 + 2.0 + 0.001 = 2.0 + + Note that the string representation is precision limited, but the internal representation + is not. + + + * This class is defined to work around the limitations of Java Big Decimal + * + * @author Grahame + * + */ +public class Decimal implements Serializable { + + private static final long serialVersionUID = 8336134891785919162L; + + private int precision; + private boolean scientific; + private boolean negative; + private String digits; + private int decimal; + + private Decimal() { + super(); + } + + public Decimal(String value) throws UcumException { + super(); + value = value.toLowerCase(); + if (value.contains("e")) + setValueScientific(value); + else + setValueDecimal(value); + } + + /** + * There are a few circumstances where a simple value is known to be correct to a high + * precision. For instance, the unit prefix milli is not ~0.001, it is precisely 0.001 + * to whatever precision you want to specify. This constructor allows you to specify + * an alternative precision than the one implied by the stated string + * + * @param value - a string representation of the value + * @param precision - a + * @throws UcumException + * @ + */ + public Decimal(String value, int precision) throws UcumException { + super(); + value = value.toLowerCase(); + if (value.contains("e")) + setValueScientific(value); + else + setValueDecimal(value); + this.precision = precision; + } + + public Decimal(int i) { + super(); + try { + setValueDecimal(Integer.toString(i)); + } catch (Exception e) { + } + } + + private void setValueDecimal(String value) throws UcumException { + // var + // dec : integer; + // i : integer; + scientific = false; + int dec = -1; + negative = value.startsWith("-"); + if (negative) + value = value.substring(1); + + while (value.startsWith("0") && value.length() > 1) + value = value.substring(1); + + for (int i = 0; i < value.length(); i++) { + if (value.charAt(i) == '.' && dec == -1) + dec = i; + else if (!Character.isDigit(value.charAt(i))) + throw new UcumException("'"+value+"' is not a valid decimal"); + } + + if (dec == -1) { + precision = value.length(); + decimal = value.length(); + digits = value; + } else if (dec == value.length() -1) + throw new UcumException("'"+value+"' is not a valid decimal"); + else { + decimal = dec; + if (allZeros(value, 1)) + precision = value.length() - 1; + else + precision = countSignificants(value); + digits = delete(value, decimal, 1); + if (allZeros(digits, 0)) + precision++; + else + while (digits.charAt(0) == '0') { + digits = digits.substring(1); + decimal--; + } + } + } + + private boolean allZeros(String s, int start) { + boolean result = true; + for (int i = start; i < s.length(); i++) { + if (s.charAt(i) != '0') + result = false; + } + return result; + } + + private int countSignificants(String value) { + int i = value.indexOf("."); + if (i > -1) + value = delete(value, i, 1); + while (value.charAt(0) == '0') + value = value.substring(1); + return value.length(); + } + + private String delete(String value, int offset, int length) { + if (offset == 0) + return value.substring(length); + else + return value.substring(0, offset)+value.substring(offset+length); + } + + private void setValueScientific(String value) throws UcumException { + int i = value.indexOf("e"); + String s = value.substring(0, i); + String e = value.substring(i+1); + + if (Utilities.noString(s) || s.equals("-") || !Utilities.isDecimal(s)) + throw new UcumException("'"+value+"' is not a valid decimal (numeric)"); + if (Utilities.noString(e) || e.equals("-") || !Utilities.isInteger(e)) + throw new UcumException("'"+value+"' is not a valid decimal (exponent)"); + + setValueDecimal(s); + scientific = true; + + // now adjust for exponent + + if (e.charAt(0) == '-') + i = 1; + else + i = 0; + while (i < e.length()) { + if (!Character.isDigit(e.charAt(i))) + throw new UcumException(""+value+"' is not a valid decimal"); + i++; + } + i = Integer.parseInt(e); + decimal = decimal + i; + } + + private String stringMultiply(char c, int i) { + return Utilities.padLeft("", c, i); + } + + private String insert(String ins, String value, int offset) { + if (offset == 0) + return ins+value; + else + return value.substring(0, offset)+ins+value.substring(offset); + } + + @Override + public String toString() { + return asDecimal(); + } + + public Decimal copy() { + Decimal result = new Decimal(); + result.precision = precision; + result.scientific = scientific; + result.negative = negative; + result.digits = digits; + result.decimal = decimal; + return result; + } + + public static Decimal zero() { + try { + return new Decimal("0"); + } catch (Exception e) { + return null; // won't happen + } + } + + public boolean isZero() { + return allZeros(digits, 0); + } + + public static Decimal one() { + try { + return new Decimal("1"); + } catch (Exception e) { + return null; // won't happen + } + } + + public boolean isOne() { + Decimal one = one(); + return comparesTo(one) == 0; + } + + public boolean equals(Decimal other) { + return comparesTo(other) == 0; + } + + public int comparesTo(Decimal other) { + // s1, s2 : AnsiString; + if (other == null) + return 0; + + if (this.negative && !other.negative) + return -1; + else if (!this.negative && other.negative) + return 1; + else { + int max = Math.max(this.decimal, other.decimal); + String s1 = stringMultiply('0', max - this.decimal+1) + this.digits; + String s2 = stringMultiply('0', max - other.decimal+1) + other.digits; + if (s1.length() < s2.length()) + s1 = s1 + stringMultiply('0', s2.length() - s1.length()); + else if (s2.length() < s1.length()) + s2 = s2 + stringMultiply('0', s1.length() - s2.length()); + int result = s1.compareTo(s2); + if (this.negative) + result = -result; + return result; + } + } + + public boolean isWholeNumber() { + return !asDecimal().contains("."); + } + + public String asDecimal() { + String result = digits; + if (decimal != digits.length()) + if (decimal < 0) + result = "0."+stringMultiply('0', 0-decimal)+digits; + else if (decimal < result.length()) + if (decimal == 0) + result = "0."+result; + else + result = insert(".", result, decimal); + else + result = result + stringMultiply('0', decimal - result.length()); + if (negative && !allZeros(result, 0)) + result = "-" + result; + return result; + } + + public int asInteger() throws UcumException { + if (!isWholeNumber()) + throw new UcumException("Unable to represent "+toString()+" as an integer"); + if (comparesTo(new Decimal(Integer.MIN_VALUE)) < 0) + throw new UcumException("Unable to represent "+toString()+" as a signed 8 byte integer"); + if (comparesTo(new Decimal(Integer.MAX_VALUE)) > 0) + throw new UcumException("Unable to represent "+toString()+" as a signed 8 byte integer"); + return Integer.parseInt(asDecimal()); + } + + public String asScientific() { + String result = digits; + boolean zero = allZeros(result, 0); + if (zero) { + if (precision < 2) + result = "0e0"; + else + result = "0."+stringMultiply('0', precision-1)+"e0"; + } else { + if (digits.length() > 1) + result = insert(".", result, 1); + result = result + 'e'+Integer.toString(decimal - 1); + } + if (negative && !zero) + result = '-' + result; + return result; + } + + public Decimal trunc() { + if (decimal < 0) + return zero(); + + Decimal result = copy(); + if (result.digits.length() >= result.decimal) + result.digits = result.digits.substring(0, result.decimal); + if (Utilities.noString(result.digits)) { + result.digits = "0"; + result.decimal = 1; + result.negative = false; + } + return result; + } + + + public Decimal add(Decimal other) { + if (other == null) + return null; + + if (negative == other.negative) { + Decimal result = doAdd(other); + result.negative = negative; + return result; + } else if (negative) + return other.doSubtract(this); + else + return doSubtract(other); + } + + public Decimal subtract(Decimal other) { + if (other == null) + return null; + + Decimal result; + if (negative && !other.negative) { + result = doAdd(other); + result.negative = true; + } else if (!negative && other.negative) { + result = doAdd(other); + } else if (negative && other.negative) { + result = doSubtract(other); + result.negative = !result.negative; + } else { + result = other.doSubtract(this); + result.negative = !result.negative; + } + return result; + } + + + private Decimal doAdd(Decimal other) { + int max = Math.max(decimal, other.decimal); + String s1 = stringMultiply('0', max - decimal+1) + digits; + String s2 = stringMultiply('0', max - other.decimal+1) + other.digits; + if (s1.length() < s2.length()) + s1 = s1 + stringMultiply('0', s2.length() - s1.length()); + else if (s2.length() < s1.length()) + s2 = s2 + stringMultiply('0', s1.length() - s2.length()); + + String s3 = stringAddition(s1, s2); + + if (s3.charAt(0) == '1') + max++; + else + s3 = delete(s3, 0, 1); + + if (max != s3.length()) { + if (max < 0) + throw new Error("Unhandled"); + else if (max < s3.length()) + s3 = insert(".", s3, max); + else + throw new Error("Unhandled"); + } + + Decimal result = new Decimal(); + try { + result.setValueDecimal(s3); + } catch (Exception e) { + // won't happen + } + result.scientific = scientific || other.scientific; + // todo: the problem with this is you have to figure out the absolute precision and take the lower of the two, not the relative one + if (decimal < other.decimal) + result.precision = precision; + else if (other.decimal < decimal) + result.precision = other.precision; + else + result.precision = Math.min(precision, other.precision); + return result; + } + + private int dig(char c) { + return (c) - ('0'); + } + + private char cdig(int i) { + return (char) (i + ('0')); + } + + private Decimal doSubtract(Decimal other) { + int max = Math.max(decimal, other.decimal); + String s1 = stringMultiply('0', max - decimal+1) + digits; + String s2 = stringMultiply('0', max - other.decimal+1) + other.digits; + if (s1.length() < s2.length()) + s1 = s1 + stringMultiply('0', s2.length() - s1.length()); + else if (s2.length() < s1.length()) + s2 = s2 + stringMultiply('0', s1.length() - s2.length()); + + String s3; + boolean neg = (s1.compareTo(s2) < 0); + if (neg) { + s3 = s2; + s2 = s1; + s1 = s3; + } + + s3 = stringSubtraction(s1, s2); + + if (s3.charAt(0) == '1') + max++; + else + s3 = delete(s3, 0, 1); + if (max != s3.length()) { + if (max < 0) + throw new Error("Unhandled"); + else if (max < s3.length()) + s3 = insert(".", s3, max); + else + throw new Error("Unhandled"); + } + + Decimal result = new Decimal(); + try { + result.setValueDecimal(s3); + } catch (Exception e) { + // won't happen + } + result.negative = neg; + result.scientific = scientific || other.scientific; + if (decimal < other.decimal) + result.precision = precision; + else if (other.decimal < decimal) + result.precision = other.precision; + else + result.precision = Math.min(precision, other.precision); + return result; + } + + private String stringAddition(String s1, String s2) { + assert(s1.length() == s2.length()); + char[] result = new char[s2.length()]; + for (int i = 0; i < s2.length(); i++) + result[i] = '0'; + int c = 0; + for (int i = s1.length() - 1; i >= 0; i--) { + int t = c + dig(s1.charAt(i)) + dig(s2.charAt(i)); + result[i] = cdig(t % 10); + c = t / 10; + } + assert(c == 0); + return new String(result); + } + + private String stringSubtraction(String s1, String s2) { +// i, t, c : integer; + assert(s1.length() == s2.length()); + + char[] result = new char[s2.length()]; + for (int i = 0; i < s2.length(); i++) + result[i] = '0'; + + int c = 0; + for (int i = s1.length() - 1; i >= 0; i--) { + int t = c + (dig(s1.charAt(i)) - dig(s2.charAt(i))); + if (t < 0) { + t = t + 10; + if (i == 0) + throw new Error("internal logic error"); + else + s1 = replaceChar(s1, i-1, cdig(dig(s1.charAt(i-1))-1)); + } + result[i] = cdig(t); + } + assert(c == 0); + return new String(result); + } + + private String replaceChar(String s, int offset, char c) { + if (offset == 0) + return String.valueOf(c)+s.substring(1); + else + return s.substring(0, offset)+c+s.substring(offset+1); + } + + + public Decimal multiply(Decimal other) { + if (other == null) + return null; + + if (isZero() || other.isZero()) + return zero(); + + int max = Math.max(decimal, other.decimal); + String s1 = stringMultiply('0', max - decimal+1) + digits; + String s2 = stringMultiply('0', max - other.decimal+1) + other.digits; + if (s1.length() < s2.length()) + s1 = s1 + stringMultiply('0', s2.length() - s1.length()); + else if (s2.length() < s1.length()) + s2 = s2 + stringMultiply('0', s1.length() - s2.length()); + + if (s2.compareTo(s1) > 0) { + String s3 = s1; + s1 = s2; + s2 = s3; + } + String[] s = new String[s2.length()]; + + int t = 0; + for (int i = s2.length()-1; i >= 0; i--) { + s[i] = stringMultiply('0', s2.length()-(i+1)); + int c = 0; + for (int j = s1.length() - 1; j >= 0; j--) { + t = c + (dig(s1.charAt(j)) * dig(s2.charAt(i))); + s[i] = insert(String.valueOf(cdig(t % 10)), s[i], 0); + c = t / 10; + } + while (c > 0) { + s[i] = insert(String.valueOf(cdig(t % 10)), s[i], 0); + c = t / 10; + } + } + + t = 0; + for (String sv : s) + t = Math.max(t, sv.length()); + for (int i = 0; i < s.length; i++) + s[i] = stringMultiply('0', t-s[i].length())+s[i]; + + String res = ""; + int c = 0; + for (int i = t - 1; i>= 0; i--) { + for (int j = 0; j < s.length; j++) + c = c + dig(s[j].charAt(i)); + res = insert(String.valueOf(cdig(c %10)), res, 0); + c = c / 10; + } + + if (c > 0) { + throw new Error("internal logic error"); + // while.. + // s[i-1] = s[i-1] + cdig(t mod 10); + // c = t div 10; + } + + int dec = res.length() - ((s1.length() - (max+1))*2); + + while (!Utilities.noString(res) && !res.equals("0") && res.startsWith("0")) { + res = res.substring(1); + dec--; + } + + int prec = 0; + if (isWholeNumber() && other.isWholeNumber()) + // at least the specified precision, and possibly more + prec = Math.max(Math.max(digits.length(), other.digits.length()), Math.min(precision, other.precision)); + else if (isWholeNumber()) + prec = other.precision; + else if (other.isWholeNumber()) + prec = precision; + else + prec = Math.min(precision, other.precision); + while (res.length() > prec && res.charAt(res.length()-1) == '0') + res = delete(res, res.length()-1, 1); + + Decimal result = new Decimal(); + try { + result.setValueDecimal(res); + } catch (Exception e) { + // won't happen + } + result.precision = prec; + result.decimal = dec; + result.negative = negative != other.negative; + result.scientific = scientific || other.scientific; + return result; + } + + public Decimal divide(Decimal other) throws UcumException { + if (other == null) + return null; + + if (isZero()) + return zero(); + + if (other.isZero()) + throw new UcumException("Attempt to divide "+toString()+" by zero"); + + String s = "0"+other.digits; + int m = Math.max(digits.length(), other.digits.length()) + 40; // max loops we'll do + String[] tens = new String[10]; + tens[0] = stringAddition(stringMultiply('0', s.length()), s); + for (int i = 1; i < 10; i++) + tens[i] = stringAddition(tens[i-1], s); + String v = digits; + String r = ""; + int l = 0; + int d = (digits.length() - decimal + 1) - (other.digits.length() - other.decimal + 1); + + while (v.length() < tens[0].length()) { + v = v + "0"; + d++; + } + + String w; + int vi; + if (v.substring(0, other.digits.length()).compareTo(other.digits) < 0) { + if (v.length() == tens[0].length()) { + v = v + '0'; + d++; + } + w = v.substring(0, other.digits.length()+1); + vi = w.length(); + } else { + w = "0"+v.substring(0, other.digits.length()); + vi = w.length()-1; + } + + boolean handled = false; + boolean proc; + + while (!(handled && ((l > m) || ((vi >= v.length()) && ((Utilities.noString(w) || allZeros(w, 0))))))) { + l++; + handled = true; + proc = false; + for (int i = 8; i >= 0; i--) { + if (tens[i].compareTo(w) <= 0) { + proc = true; + r = r + cdig(i+1); + w = trimLeadingZeros(stringSubtraction(w, tens[i])); + if (!(handled && ((l > m) || ((vi >= v.length()) && ((Utilities.noString(w) || allZeros(w, 0))))))) { + if (vi < v.length()) { + w = w + v.charAt(vi); + vi++; + handled = false; + } else { + w = w + '0'; + d++; + } + while (w.length() < tens[0].length()) + w = '0'+w; + } + break; + } + } + if (!proc) { + assert(w.charAt(0) == '0'); + w = delete(w, 0, 1); + r = r + "0"; + if (!(handled && ((l > m) || ((vi >= v.length()) && ((Utilities.noString(w) || allZeros(w, 0))))))) { + if (vi < v.length()) { + w = w + v.charAt(vi); + vi++; + handled = false; + } else { + w = w + '0'; + d++; + } + while (w.length() < tens[0].length()) + w = '0'+w; + } + } + } + + int prec; + + if (isWholeNumber() && other.isWholeNumber() && (l < m)) { + for (int i = 0; i < d; i++) { + if (r.charAt(r.length()-1) == '0') { + r = delete(r, r.length()-1, 1); + d--; + } + } + prec = 100; + } else { + if (isWholeNumber() && other.isWholeNumber()) + prec = Math.max(digits.length(), other.digits.length()); + else if (isWholeNumber()) + prec = Math.max(other.precision, r.length() - d); + else if (other.isWholeNumber()) + prec = Math.max(precision, r.length() - d); + else + prec = Math.max(Math.min(precision, other.precision), r.length() - d); + if (r.length() > prec) { + d = d - (r.length() - prec); + char dig = r.charAt(prec); + boolean up = dig >= '5'; + if (up) { + char[] rs = r.substring(0, prec).toCharArray(); + int i = rs.length-1; + boolean carry = true; + while (carry && i >= 0) { + char ls = rs[i]; + if (ls == '9') { + rs[i] = '0'; + } else { + ls = (char) (((int) ls) + 1); + rs[i] = ls; + carry = false; + } + i--; + } + if (carry) { + r = "1"+new String(rs); + d++; // cause we added one at the start + } + else + r = new String(rs); + } else + r = r.substring(0, prec); + } + } + + Decimal result = new Decimal(); + result.setValueDecimal(r); + result.decimal = r.length() - d; + result.negative = negative != other.negative; + result.precision = prec; + result.scientific = scientific || other.scientific; + return result; + } + + + private String trimLeadingZeros(String s) { + if (s == null) + return null; + + int i = 0; + while (i < s.length() && s.charAt(i) == '0') + i++; + if (i == s.length()) + return "0"; + else + return s.substring(i); + } + + public Decimal divInt(Decimal other) throws UcumException { + if (other == null) + return null; + Decimal t = divide(other); + return t.trunc(); + } + + public Decimal modulo(Decimal other) throws UcumException { + if (other == null) + return null; + Decimal t = divInt(other); + Decimal t2 = t.multiply(other); + return subtract(t2); + } + + public boolean equals(Decimal value, Decimal maxDifference) { + Decimal diff = this.subtract(value).absolute(); + return diff.comparesTo(maxDifference) <= 0; + } + + private Decimal absolute() { + Decimal d = copy(); + d.negative = false; + return d; + } + + @Override + public boolean equals(Object other) { + if (other instanceof Decimal) + return asDecimal().equals(((Decimal) other).asDecimal()); + else + return super.equals(other); + } + + @Override + public int hashCode() { + return asDecimal().hashCode(); + } +} diff --git a/src/main/java/org/fhir/ucum/DefinedUnit.java b/src/main/java/org/fhir/ucum/DefinedUnit.java index ef06cbc..4cfd80f 100644 --- a/src/main/java/org/fhir/ucum/DefinedUnit.java +++ b/src/main/java/org/fhir/ucum/DefinedUnit.java @@ -14,7 +14,9 @@ public class DefinedUnit extends Unit{ - /** + private static final long serialVersionUID = 6610597337302313079L; + + /** * whether this is a metric unit or not */ private boolean metric; diff --git a/src/main/java/org/fhir/ucum/Pair.java b/src/main/java/org/fhir/ucum/Pair.java index 71bd7fc..78b1cc8 100644 --- a/src/main/java/org/fhir/ucum/Pair.java +++ b/src/main/java/org/fhir/ucum/Pair.java @@ -1,60 +1,64 @@ -/******************************************************************************* - * Crown Copyright (c) 2006 - 2014, Copyright (c) 2006 - 2014 Kestral Computing P/L. - * 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: - * Kestral Computing P/L - initial implementation - *******************************************************************************/ - -package org.fhir.ucum; - -public class Pair { - - private Decimal value; - private String code; - - - /** - * @param value - * @param code - */ - public Pair(Decimal value, String code) { - super(); - this.value = value; - this.code = code; - } - /** - * @return the value - */ - public Decimal getValue() { - return value; - } - /** - * @return the code - */ - public String getCode() { - return code; - } - @Override - public boolean equals(Object other) { - if (other instanceof Pair) { - Pair p = (Pair) other; - return value.equals(p.value) && code.equals(p.code); - } else - return super.equals(other); - } - - @Override - public int hashCode() { - return toString().hashCode(); - } - @Override - public String toString() { - return value.toString()+" "+code; - } - - -} +/******************************************************************************* + * Crown Copyright (c) 2006 - 2014, Copyright (c) 2006 - 2014 Kestral Computing P/L. + * 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: + * Kestral Computing P/L - initial implementation + *******************************************************************************/ + +package org.fhir.ucum; + +import java.io.Serializable; + +public class Pair implements Serializable { + + private static final long serialVersionUID = -1201864084549128274L; + + private Decimal value; + private String code; + + + /** + * @param value + * @param code + */ + public Pair(Decimal value, String code) { + super(); + this.value = value; + this.code = code; + } + /** + * @return the value + */ + public Decimal getValue() { + return value; + } + /** + * @return the code + */ + public String getCode() { + return code; + } + @Override + public boolean equals(Object other) { + if (other instanceof Pair) { + Pair p = (Pair) other; + return value.equals(p.value) && code.equals(p.code); + } else + return super.equals(other); + } + + @Override + public int hashCode() { + return toString().hashCode(); + } + @Override + public String toString() { + return value.toString()+" "+code; + } + + +} diff --git a/src/main/java/org/fhir/ucum/Prefix.java b/src/main/java/org/fhir/ucum/Prefix.java index b8a5145..59cec8d 100644 --- a/src/main/java/org/fhir/ucum/Prefix.java +++ b/src/main/java/org/fhir/ucum/Prefix.java @@ -13,8 +13,10 @@ public class Prefix extends Concept { - - /** + + private static final long serialVersionUID = 7489713906606871520L; + + /** * value for the prefix. */ private Decimal value; // 1^-24 through to 1^24 diff --git a/src/main/java/org/fhir/ucum/UcumEssenceService.java b/src/main/java/org/fhir/ucum/UcumEssenceService.java index 543b838..5b06ba4 100644 --- a/src/main/java/org/fhir/ucum/UcumEssenceService.java +++ b/src/main/java/org/fhir/ucum/UcumEssenceService.java @@ -40,9 +40,10 @@ */ public class UcumEssenceService implements UcumService { + private static final long serialVersionUID = 1058845586935921655L; public static final String UCUM_OID = "2.16.840.1.113883.6.8"; - - private UcumModel model; + + private UcumModel model; private Registry handlers = new Registry(); /** diff --git a/src/main/java/org/fhir/ucum/UcumModel.java b/src/main/java/org/fhir/ucum/UcumModel.java index 65e8f70..f3699db 100644 --- a/src/main/java/org/fhir/ucum/UcumModel.java +++ b/src/main/java/org/fhir/ucum/UcumModel.java @@ -11,13 +11,16 @@ package org.fhir.ucum; +import java.io.Serializable; import java.util.ArrayList; import java.util.Date; import java.util.List; -public class UcumModel { +public class UcumModel implements Serializable { - /** + private static final long serialVersionUID = 2263441561255569053L; + + /** * version="1.7" */ private String version; diff --git a/src/main/java/org/fhir/ucum/UcumService.java b/src/main/java/org/fhir/ucum/UcumService.java index 5c0700a..088656d 100644 --- a/src/main/java/org/fhir/ucum/UcumService.java +++ b/src/main/java/org/fhir/ucum/UcumService.java @@ -12,6 +12,7 @@ * Health Intersections - ongoing maintenance *******************************************************************************/ +import java.io.Serializable; import java.util.Date; import java.util.List; import java.util.Set; @@ -25,7 +26,7 @@ * @author Grahame Grieve * */ -public interface UcumService { +public interface UcumService extends Serializable { /** * provided for various utility/QA uses. Should not be used diff --git a/src/main/java/org/fhir/ucum/Unit.java b/src/main/java/org/fhir/ucum/Unit.java index 3a53717..ad19120 100644 --- a/src/main/java/org/fhir/ucum/Unit.java +++ b/src/main/java/org/fhir/ucum/Unit.java @@ -14,7 +14,9 @@ public abstract class Unit extends Concept { - /** + private static final long serialVersionUID = -359123350391877225L; + + /** * kind of thing this base unit represents */ private String property; diff --git a/src/main/java/org/fhir/ucum/Value.java b/src/main/java/org/fhir/ucum/Value.java index 94536ee..c416d38 100644 --- a/src/main/java/org/fhir/ucum/Value.java +++ b/src/main/java/org/fhir/ucum/Value.java @@ -11,9 +11,13 @@ package org.fhir.ucum; -public class Value { +import java.io.Serializable; - private String unit; +public class Value implements Serializable { + + private static final long serialVersionUID = 6179476364128662688L; + + private String unit; private String unitUC; diff --git a/src/main/java/org/fhir/ucum/special/CelsiusHandler.java b/src/main/java/org/fhir/ucum/special/CelsiusHandler.java index 68ec226..87a782a 100644 --- a/src/main/java/org/fhir/ucum/special/CelsiusHandler.java +++ b/src/main/java/org/fhir/ucum/special/CelsiusHandler.java @@ -15,7 +15,9 @@ public class CelsiusHandler extends SpecialUnitHandler { - @Override + private static final long serialVersionUID = 8622694656482031531L; + + @Override public String getCode() { return "Cel"; } diff --git a/src/main/java/org/fhir/ucum/special/FahrenheitHandler.java b/src/main/java/org/fhir/ucum/special/FahrenheitHandler.java index f0ada08..ea1af12 100644 --- a/src/main/java/org/fhir/ucum/special/FahrenheitHandler.java +++ b/src/main/java/org/fhir/ucum/special/FahrenheitHandler.java @@ -15,7 +15,9 @@ public class FahrenheitHandler extends SpecialUnitHandler { - @Override + private static final long serialVersionUID = 5300754465863682114L; + + @Override public String getCode() { return "[degF]"; } diff --git a/src/main/java/org/fhir/ucum/special/HoldingHandler.java b/src/main/java/org/fhir/ucum/special/HoldingHandler.java index 7691fe0..e6ea617 100644 --- a/src/main/java/org/fhir/ucum/special/HoldingHandler.java +++ b/src/main/java/org/fhir/ucum/special/HoldingHandler.java @@ -22,7 +22,9 @@ */ public class HoldingHandler extends SpecialUnitHandler { - private String code; + private static final long serialVersionUID = -6165027832340262895L; + + private String code; private String units; private Decimal value = Decimal.one(); diff --git a/src/main/java/org/fhir/ucum/special/Registry.java b/src/main/java/org/fhir/ucum/special/Registry.java index 8c0f293..d8b92b5 100644 --- a/src/main/java/org/fhir/ucum/special/Registry.java +++ b/src/main/java/org/fhir/ucum/special/Registry.java @@ -11,14 +11,17 @@ package org.fhir.ucum.special; +import java.io.Serializable; import java.util.HashMap; import java.util.Map; import org.fhir.ucum.Decimal; -public class Registry { +public class Registry implements Serializable { - Map handlers = new HashMap(); + private static final long serialVersionUID = 3809426006717720452L; + + Map handlers = new HashMap(); public Registry() { super(); diff --git a/src/main/java/org/fhir/ucum/special/SpecialUnitHandler.java b/src/main/java/org/fhir/ucum/special/SpecialUnitHandler.java index 4f815d3..e019df0 100644 --- a/src/main/java/org/fhir/ucum/special/SpecialUnitHandler.java +++ b/src/main/java/org/fhir/ucum/special/SpecialUnitHandler.java @@ -11,11 +11,14 @@ package org.fhir.ucum.special; +import java.io.Serializable; import org.fhir.ucum.Decimal; -public abstract class SpecialUnitHandler { +public abstract class SpecialUnitHandler implements Serializable { - /** + private static final long serialVersionUID = 1000724308948489980L; + + /** * Used to connect this handler with the case sensitive unit * @return */