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:
chochos
2010-12-06 18:42:02 +00:00
parent 64989e5168
commit 3c8cacbb8d
4 changed files with 189 additions and 4 deletions
+29 -2
View File
@@ -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);
}
+57 -2
View File
@@ -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;
}
}