1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.joda.money;
17
18 import java.io.Externalizable;
19 import java.io.IOException;
20 import java.io.InvalidClassException;
21 import java.io.InvalidObjectException;
22 import java.io.ObjectInput;
23 import java.io.ObjectOutput;
24 import java.io.StreamCorruptedException;
25 import java.math.BigDecimal;
26 import java.math.BigInteger;
27
28
29
30
31
32
33 final class Ser implements Externalizable {
34
35
36 static final byte BIG_MONEY = 'B';
37
38 static final byte MONEY = 'M';
39
40 static final byte CURRENCY_UNIT = 'C';
41
42
43 private byte type;
44
45 private Object object;
46
47
48
49
50 public Ser() {
51 }
52
53
54
55
56
57
58
59 Ser(byte type, Object object) {
60 this.type = type;
61 this.object = object;
62 }
63
64
65
66
67
68
69
70
71
72 public void writeExternal(ObjectOutput out) throws IOException {
73 out.writeByte(type);
74 switch (type) {
75 case BIG_MONEY: {
76 BigMoney obj = (BigMoney) object;
77 writeBigMoney(out, obj);
78 return;
79 }
80 case MONEY: {
81 Money obj = (Money) object;
82 writeBigMoney(out, obj.toBigMoney());
83 return;
84 }
85 case CURRENCY_UNIT: {
86 CurrencyUnit obj = (CurrencyUnit) object;
87 writeCurrency(out, obj);
88 return;
89 }
90 }
91 throw new InvalidClassException("Joda-Money bug: Serialization broken");
92 }
93
94 private void writeBigMoney(ObjectOutput out, BigMoney obj) throws IOException {
95 writeCurrency(out, obj.getCurrencyUnit());
96 byte[] bytes = obj.getAmount().unscaledValue().toByteArray();
97 out.writeInt(bytes.length);
98 out.write(bytes);
99 out.writeInt(obj.getScale());
100 }
101
102 private void writeCurrency(ObjectOutput out, CurrencyUnit obj) throws IOException {
103 out.writeUTF(obj.getCode());
104 out.writeShort(obj.getNumericCode());
105 out.writeShort(obj.getDefaultFractionDigits());
106 }
107
108
109
110
111
112
113
114 public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
115 type = in.readByte();
116 switch (type) {
117 case BIG_MONEY: {
118 object = readBigMoney(in);
119 return;
120 }
121 case MONEY: {
122 object = new Money(readBigMoney(in));
123 return;
124 }
125 case CURRENCY_UNIT: {
126 object = readCurrency(in);
127 return;
128 }
129 }
130 throw new StreamCorruptedException("Serialization input has invalid type");
131 }
132
133 private BigMoney readBigMoney(ObjectInput in) throws IOException {
134 CurrencyUnit currency = readCurrency(in);
135 byte[] bytes = new byte[in.readInt()];
136 in.readFully(bytes);
137 BigDecimal bd = new BigDecimal(new BigInteger(bytes), in.readInt());
138 BigMoney bigMoney = new BigMoney(currency, bd);
139 return bigMoney;
140 }
141
142 private CurrencyUnit readCurrency(ObjectInput in) throws IOException {
143 String code = in.readUTF();
144 CurrencyUnit singletonCurrency = CurrencyUnit.of(code);
145 if (singletonCurrency.getNumericCode() != in.readShort()) {
146 throw new InvalidObjectException("Deserialization found a mismatch in the numeric code for currency " + code);
147 }
148 if (singletonCurrency.getDefaultFractionDigits() != in.readShort()) {
149 throw new InvalidObjectException("Deserialization found a mismatch in the decimal places for currency " + code);
150 }
151 return singletonCurrency;
152 }
153
154
155
156
157
158
159 private Object readResolve() {
160 return object;
161 }
162
163 }