Added new IsoTypes: BINARY, LLBIN and LLLBIN. Similar to ALPHA, LLVAR and LLLVAR but they handle binary values that get translated to byte arrays, directly if using binary coding, or hex-encoded if using ASCII.
git-svn-id: https://j8583.svn.sourceforge.net/svnroot/j8583/j8583@63 db60a039-f72e-0410-b1d2-baa000846441
This commit is contained in:
@@ -50,7 +50,13 @@ public enum IsoType {
|
||||
/** Time of day in format HHmmss */
|
||||
TIME(false, 6),
|
||||
/** An amount, expressed in cents with a fixed length of 12. */
|
||||
AMOUNT(false, 12);
|
||||
AMOUNT(false, 12),
|
||||
/** Similar to ALPHA but holds byte arrays instead of strings. */
|
||||
BINARY(true, 0),
|
||||
/** Similar to LLVAR but holds byte arrays instead of strings. */
|
||||
LLBIN(false, 0),
|
||||
/** Similar to LLLVAR but holds byte arrays instead of strings. */
|
||||
LLLBIN(false, 0);
|
||||
|
||||
private boolean needsLen;
|
||||
private int length;
|
||||
@@ -85,7 +91,7 @@ public enum IsoType {
|
||||
throw new IllegalArgumentException("Cannot format date as " + this);
|
||||
}
|
||||
|
||||
/** Formats the string to the given length (length is only useful if type is ALPHA). */
|
||||
/** Formats the string to the given length (length is only useful if type is ALPHA, NUMERIC or BINARY). */
|
||||
public String format(String value, int length) {
|
||||
if (this == ALPHA) {
|
||||
if (value == null) {
|
||||
@@ -116,6 +122,23 @@ public enum IsoType {
|
||||
return new String(c);
|
||||
} else if (this == AMOUNT) {
|
||||
return IsoType.NUMERIC.format(new BigDecimal(value).movePointRight(2).intValue(), 12);
|
||||
} else if (this == BINARY) {
|
||||
|
||||
if (value == null) {
|
||||
value = "";
|
||||
}
|
||||
if (value.length() > length) {
|
||||
return value.substring(0, length);
|
||||
}
|
||||
char[] c = new char[length];
|
||||
System.arraycopy(value.toCharArray(), 0, c, 0, value.length());
|
||||
for (int i = value.length(); i < c.length; i++) {
|
||||
c[i] = '0';
|
||||
}
|
||||
return new String(c);
|
||||
|
||||
} else if (this == LLBIN || this == LLLBIN) {
|
||||
return value;
|
||||
}
|
||||
throw new IllegalArgumentException("Cannot format String as " + this);
|
||||
}
|
||||
@@ -145,6 +168,8 @@ public enum IsoType {
|
||||
//No hay decimales asi que dejamos los dos ultimos digitos como 0
|
||||
System.arraycopy(v.toCharArray(), 0, digits, 10 - v.length(), v.length());
|
||||
return new String(digits);
|
||||
} else if (this == BINARY || this == LLBIN || this == LLLBIN) {
|
||||
//TODO
|
||||
}
|
||||
throw new IllegalArgumentException("Cannot format number as " + this);
|
||||
}
|
||||
@@ -158,6 +183,8 @@ public enum IsoType {
|
||||
return format(value.longValue(), length);
|
||||
} else if (this == ALPHA || this == LLVAR || this == LLLVAR) {
|
||||
return format(value.toString(), length);
|
||||
} else if (this == BINARY || this == LLBIN || this == LLLBIN) {
|
||||
//TODO
|
||||
}
|
||||
throw new IllegalArgumentException("Cannot format BigDecimal as " + this);
|
||||
}
|
||||
|
||||
@@ -23,6 +23,8 @@ import java.io.OutputStream;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
import com.solab.iso8583.util.HexCodec;
|
||||
|
||||
/** Represents a value that is stored in a field inside an ISO8583 message.
|
||||
* It can format the value when the message is generated.
|
||||
* Some values have a fixed length, other values require a length to be specified
|
||||
@@ -72,6 +74,22 @@ public class IsoValue<T> implements Cloneable {
|
||||
} else if (t == IsoType.LLLVAR && length > 999) {
|
||||
throw new IllegalArgumentException("LLLVAR can only hold values up to 999 chars");
|
||||
}
|
||||
} else if (type == IsoType.LLBIN || type == IsoType.LLLBIN) {
|
||||
if (custom == null) {
|
||||
length = ((byte[])value).length;
|
||||
} else {
|
||||
//TODO special encoder, NO strings
|
||||
String enc = custom.encodeField(value);
|
||||
if (enc == null) {
|
||||
enc = value == null ? "" : value.toString();
|
||||
}
|
||||
length = enc.length();
|
||||
}
|
||||
if (t == IsoType.LLBIN && length > 99) {
|
||||
throw new IllegalArgumentException("LLBIN can only hold values up to 99 chars");
|
||||
} else if (t == IsoType.LLLBIN && length > 999) {
|
||||
throw new IllegalArgumentException("LLLBIN can only hold values up to 999 chars");
|
||||
}
|
||||
} else {
|
||||
length = type.getLength();
|
||||
}
|
||||
@@ -104,6 +122,16 @@ public class IsoValue<T> implements Cloneable {
|
||||
} else if (t == IsoType.LLLVAR && length > 999) {
|
||||
throw new IllegalArgumentException("LLLVAR can only hold values up to 999 chars");
|
||||
}
|
||||
} else if (t == IsoType.LLBIN || t == IsoType.LLLBIN) {
|
||||
if (len == 0) {
|
||||
//TODO customfield binary!
|
||||
length = custom == null ? ((byte[])val).length : custom.encodeField(value).length();
|
||||
}
|
||||
if (t == IsoType.LLBIN && length > 99) {
|
||||
throw new IllegalArgumentException("LLBIN can only hold values up to 99 chars");
|
||||
} else if (t == IsoType.LLLBIN && length > 999) {
|
||||
throw new IllegalArgumentException("LLLBIN can only hold values up to 999 chars");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -148,6 +176,10 @@ public class IsoValue<T> implements Cloneable {
|
||||
return encoder == null ? value.toString() : encoder.encodeField(value);
|
||||
} else if (value instanceof Date) {
|
||||
return type.format((Date)value);
|
||||
} else if (type == IsoType.BINARY) {
|
||||
return type.format(encoder == null ? HexCodec.hexEncode((byte[])value) : encoder.encodeField(value), length * 2);
|
||||
} else if (type == IsoType.LLBIN || type == IsoType.LLLBIN) {
|
||||
return encoder == null ? HexCodec.hexEncode((byte[])value) : encoder.encodeField(value);
|
||||
}
|
||||
return encoder == null ? value.toString() : encoder.encodeField(value);
|
||||
}
|
||||
@@ -204,6 +236,25 @@ public class IsoValue<T> implements Cloneable {
|
||||
}
|
||||
outs.write((length % 10) + 48);
|
||||
}
|
||||
} else if (type == IsoType.LLBIN || type == IsoType.LLLBIN) {
|
||||
if (binary) {
|
||||
if (type == IsoType.LLLBIN ) {
|
||||
outs.write(length / 100); //00 to 09 automatically in BCD
|
||||
}
|
||||
//BCD encode the rest of the length
|
||||
outs.write((((length % 100) / 10) << 4) | (length % 10));
|
||||
} else {
|
||||
//write the length in ASCII
|
||||
if (type == IsoType.LLLBIN) {
|
||||
outs.write((length / 50) + 48);
|
||||
}
|
||||
if (length >= 10) {
|
||||
outs.write((((length*2) % 100) / 10) + 48);
|
||||
} else {
|
||||
outs.write(48);
|
||||
}
|
||||
outs.write(((length*2) % 10) + 48);
|
||||
}
|
||||
} else if (binary) {
|
||||
//numeric types in binary are coded like this
|
||||
byte[] buf = null;
|
||||
@@ -221,8 +272,12 @@ public class IsoValue<T> implements Cloneable {
|
||||
return;
|
||||
}
|
||||
}
|
||||
//Just write the value as text
|
||||
outs.write(toString().getBytes());
|
||||
if (binary && (type == IsoType.BINARY || type == IsoType.LLBIN || type == IsoType.LLLBIN)) {
|
||||
outs.write((byte[])value);
|
||||
} else {
|
||||
//Just write the value as text
|
||||
outs.write(toString().getBytes());
|
||||
}
|
||||
}
|
||||
|
||||
/** Encode the value as BCD and put it in the buffer. The buffer must be big enough
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
package com.solab.iso8583.util;
|
||||
|
||||
/** Utility class to perform HEX encoding/decoding of values. */
|
||||
public class HexCodec {
|
||||
|
||||
static final char[] HEX = new char[]{ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
|
||||
|
||||
public static String hexEncode(byte[] buffer) {
|
||||
if (buffer.length == 0) {
|
||||
return "";
|
||||
}
|
||||
int holder = 0;
|
||||
char[] chars = new char[buffer.length * 2];
|
||||
for (int i = 0; i < buffer.length; i++) {
|
||||
holder = (buffer[i] & 0xf0) >> 4;
|
||||
chars[i * 2] = HEX[holder];
|
||||
holder = buffer[i] & 0x0f;
|
||||
chars[(i * 2) + 1] = HEX[holder];
|
||||
}
|
||||
return new String(chars);
|
||||
}
|
||||
|
||||
public static byte[] hexDecode(String hex) {
|
||||
//A null string returns an empty array
|
||||
if (hex == null || hex.length() == 0) {
|
||||
return new byte[0];
|
||||
} else if (hex.length() < 3) {
|
||||
return new byte[]{ (byte)(Integer.parseInt(hex, 16) & 0xff) };
|
||||
}
|
||||
//Adjust accordingly for odd-length strings
|
||||
int count = hex.length();
|
||||
int nibble = 0;
|
||||
if (count % 2 != 0) {
|
||||
count++;
|
||||
nibble = 1;
|
||||
}
|
||||
byte[] buf = new byte[count / 2];
|
||||
char c = 0;
|
||||
int holder = 0;
|
||||
int pos = 0;
|
||||
for (int i = 0; i < buf.length; i++) {
|
||||
for (int z = 0; z < 2; z++) {
|
||||
c = hex.charAt(pos++);
|
||||
if (c >= 'A' && c <= 'F') {
|
||||
c -= 55;
|
||||
} else if (c >= '0' && c <= '9') {
|
||||
c -= 48;
|
||||
} else if (c >= 'a' && c <= 'f') {
|
||||
c -= 87;
|
||||
}
|
||||
if (nibble == 0) {
|
||||
holder = c << 4;
|
||||
} else {
|
||||
holder |= c;
|
||||
buf[i] = (byte)holder;
|
||||
}
|
||||
nibble = 1 - nibble;
|
||||
}
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user