001/* 002 * jPOS Project [http://jpos.org] 003 * Copyright (C) 2000-2026 jPOS Software SRL 004 * 005 * This program is free software: you can redistribute it and/or modify 006 * it under the terms of the GNU Affero General Public License as 007 * published by the Free Software Foundation, either version 3 of the 008 * License, or (at your option) any later version. 009 * 010 * This program is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 013 * GNU Affero General Public License for more details. 014 * 015 * You should have received a copy of the GNU Affero General Public License 016 * along with this program. If not, see <http://www.gnu.org/licenses/>. 017 */ 018 019package org.jpos.iso; 020 021import org.jpos.iso.packager.XMLPackager; 022 023import java.io.*; 024import java.math.BigDecimal; 025import java.util.Objects; 026 027public class ISOAmount 028 extends ISOComponent 029 implements Cloneable, Externalizable 030{ 031 static final long serialVersionUID = -6130248734056876225L; 032 private int fieldNumber; 033 private int currencyCode; 034 private String value; 035 private BigDecimal amount; 036 037 public ISOAmount () { 038 super(); 039 setFieldNumber (-1); 040 } 041 public ISOAmount (int fieldNumber) { 042 super (); 043 setFieldNumber (fieldNumber); 044 } 045 public ISOAmount (int fieldNumber, int currencyCode, BigDecimal amount) throws ISOException { 046 super (); 047 setFieldNumber(fieldNumber); 048 this.currencyCode = currencyCode; 049 try { 050 this.amount = amount.setScale(ISOCurrency.getCurrency(currencyCode).getDecimals()); 051 } catch (ArithmeticException e) { 052 throw new ISOException ( 053 "rounding problem, amount=" + amount + " scale=" + ISOCurrency.getCurrency(currencyCode).getDecimals() 054 ); 055 } 056 } 057 public Object getKey() { 058 return fieldNumber; 059 } 060 public Object getValue() throws ISOException { 061 if (value == null) { 062 StringBuilder sb = new StringBuilder(); 063 sb.append (ISOUtil.zeropad (Integer.toString(currencyCode), 3)); 064 sb.append (Integer.toString (amount.scale())); 065 sb.append ( 066 ISOUtil.zeropad ( 067 amount.movePointRight(amount.scale()).toString(),12 068 ) 069 ); 070 value = sb.toString(); 071 } 072 return value; 073 074 } 075 public void setValue (Object obj) throws ISOException { 076 if (obj instanceof String) { 077 String s = (String) obj; 078 if (s.length() < 12) { 079 throw new ISOException ( 080 "ISOAmount invalid length " + s.length() 081 ); 082 } 083 try { 084 currencyCode = Integer.parseInt (s.substring(0,3)); 085 int dec = Integer.parseInt (s.substring(3,4)); 086 amount = new BigDecimal (s.substring(4)).movePointLeft (dec); 087 value = s; 088 } catch (NumberFormatException e) { 089 throw new ISOException (e.getMessage()); 090 } 091 } 092 } 093 public void setFieldNumber (int fieldNumber) { 094 this.fieldNumber = fieldNumber; 095 } 096 097 @Override 098 public int getFieldNumber () { 099 return fieldNumber; 100 } 101 public BigDecimal getAmount () { 102 return amount; 103 } 104 public int getScale() { 105 return amount.scale() % 10; 106 } 107 public String getScaleAsString() { 108 return Integer.toString(getScale()); 109 } 110 public int getCurrencyCode() { 111 return currencyCode; 112 } 113 public String getCurrencyCodeAsString() throws ISOException { 114 return ISOUtil.zeropad(Integer.toString(currencyCode),3); 115 } 116 public String getAmountAsLegacyString() throws ISOException { 117 return ISOUtil.zeropad (amount.unscaledValue().toString(), 12); 118 } 119 public String getAmountAsString() throws ISOException { 120 StringBuilder sb = new StringBuilder(16); 121 sb.append (ISOUtil.zeropad (Integer.toString (currencyCode),3)); 122 sb.append (Integer.toString(amount.scale() % 10)); 123 sb.append (ISOUtil.zeropad (amount.unscaledValue().toString(), 12)); 124 return sb.toString(); 125 } 126 public byte[] pack() throws ISOException { 127 throw new ISOException ("Not available"); 128 } 129 public int unpack(byte[] b) throws ISOException { 130 throw new ISOException ("Not available"); 131 } 132 public void unpack(InputStream in) throws ISOException { 133 throw new ISOException ("Not available"); 134 } 135 public void dump (PrintStream p, String indent) { 136 p.println (indent +"<"+XMLPackager.ISOFIELD_TAG + " " 137 +XMLPackager.ID_ATTR +"=\"" +fieldNumber +"\" " 138 +"currency=\"" +ISOUtil.zeropad (currencyCode, 3)+"\" " 139 +XMLPackager.TYPE_ATTR +"=\"amount\" " 140 +XMLPackager.VALUE_ATTR+"=\"" + amount.toString() +"\"/>" 141 ); 142 } 143 public void writeExternal (ObjectOutput out) throws IOException { 144 out.writeShort (fieldNumber); 145 try { 146 out.writeUTF ((String) getValue()); 147 } catch (ISOException e) { 148 throw new IOException (e); 149 } 150 } 151 public void readExternal (ObjectInput in) 152 throws IOException, ClassNotFoundException 153 { 154 fieldNumber = in.readShort (); 155 try { 156 setValue(in.readUTF()); 157 } catch (ISOException e) { 158 throw new IOException (e.getMessage()); 159 } 160 } 161 162 @Override 163 public boolean equals(Object o) { 164 if (this == o) return true; 165 if (o == null || getClass() != o.getClass()) return false; 166 ISOAmount isoAmount = (ISOAmount) o; 167 return fieldNumber == isoAmount.fieldNumber && 168 currencyCode == isoAmount.currencyCode && 169 Objects.equals(amount, isoAmount.amount); 170 } 171 172 @Override 173 public int hashCode() { 174 return Objects.hash(fieldNumber, currencyCode, amount); 175 } 176 177 @Override 178 public String toString() { 179 return "ISOAmount{" + 180 "fieldNumber=" + fieldNumber + 181 ", currencyCode=" + currencyCode + 182 ", amount=" + amount + 183 '}'; 184 } 185} 186