org.jpos.iso.ISOFormattableBinaryFieldPackager Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jpos Show documentation
Show all versions of jpos Show documentation
jPOS is an ISO-8583 based financial transaction
library/framework that can be customized and
extended in order to implement financial interchanges.
/*
* jPOS Project [http://jpos.org]
* Copyright (C) 2000-2019 jPOS Software SRL
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see .
*/
package org.jpos.iso;
import java.io.IOException;
import java.io.InputStream;
/**
* Generic class for handling binary fields in Tag-Len-Value format
*
* Format is assemblied by header formatter
* Where
* TT is the n>0 digit field number (Tag)
* LL is the n>=0 digit field length (if n=0 it's means fixed length field with prefixer)
* .. is the field content
*
* @author Mikolaj Sosna
* @version $Revision: 2854 $ $Date: 2010-01-02 11:34:31 +0100 (sob) $
*/
public class ISOFormattableBinaryFieldPackager extends ISOFieldPackager
{
private Prefixer tagPrefixer;
private BinaryInterpreter interpreter;
private Padder padder;
private Prefixer prefixer;
private IsoFieldHeaderFormatter headerFormatter;
/**
* Constructs a default ISOTagBinaryFieldPackager. There is ASCII tag L prefixer, no padding,
* no length prefix and a literal binary interpretation. The set methods must be called to
* make this ISOBaseFieldPackager useful.
*/
public ISOFormattableBinaryFieldPackager() {
super();
this.tagPrefixer = AsciiPrefixer.L;
this.interpreter = LiteralBinaryInterpreter.INSTANCE;
this.padder = NullPadder.INSTANCE;
this.prefixer = NullPrefixer.INSTANCE;
this.headerFormatter = IsoFieldHeaderFormatter.TAG_FIRST;
}
/**
* Constructs an ISOTagBinaryFieldPackager with a specific Padder, Interpreter and Prefixer.
* The length and description should be set with setLength() and setDescription methods.
* @param tagPrefixer The type of tag prefixer used to encode tag.
* @param padder The type of padding used.
* @param interpreter The interpreter used to encode the field.
* @param prefixer The type of length prefixer used to encode this field.
*/
public ISOFormattableBinaryFieldPackager(Prefixer tagPrefixer, Padder padder,
BinaryInterpreter interpreter, Prefixer prefixer) {
super();
this.tagPrefixer = tagPrefixer;
this.padder = padder;
this.interpreter = interpreter;
this.prefixer = prefixer;
this.headerFormatter = IsoFieldHeaderFormatter.TAG_FIRST;
}
/**
* Constructs an ISOTagBinaryFieldPackager with a specific Padder, Interpreter and Prefixer.
* The length and description should be set with setLength() and setDescription methods.
* @param tagPrefixer The type of tag prefixer used to encode tag.
* @param padder The type of padding used.
* @param interpreter The interpreter used to encode the field.
* @param lengthPrefixer The type of length prefixer used to encode this field.
* @param headerFormatter The format of TAG TT and Length LL part
*/
public ISOFormattableBinaryFieldPackager(Prefixer tagPrefixer, Padder padder,
BinaryInterpreter interpreter, Prefixer lengthPrefixer,
IsoFieldHeaderFormatter headerFormatter) {
super();
this.tagPrefixer = tagPrefixer;
this.padder = padder;
this.interpreter = interpreter;
this.prefixer = lengthPrefixer;
this.headerFormatter = headerFormatter;
}
/**
* Creates an ISOTagBinaryFieldPackager.
* @param maxLength The maximum length of the field in characters or bytes depending on the datatype.
* @param description The description of the field. For human readable output.
* @param tagPrefixer The type of tag prefixer used to encode tag.
* @param interpreter The interpreter used to encode the field.
* @param padder The type of padding used.
* @param lengthPrefixer The type of length prefixer used to encode this field.
* @param headerFormatter The format of TAG TT and Length LL part
*/
public ISOFormattableBinaryFieldPackager(int maxLength, String description, Prefixer tagPrefixer,
Padder padder, BinaryInterpreter interpreter, Prefixer lengthPrefixer,
IsoFieldHeaderFormatter headerFormatter) {
super(maxLength, description);
this.tagPrefixer = tagPrefixer;
this.padder = padder;
this.interpreter = interpreter;
this.prefixer = lengthPrefixer;
this.headerFormatter = headerFormatter;
}
/**
* Sets the Padder.
* @param padder The padder to use during packing and unpacking.
*/
public void setPadder(Padder padder) {
this.padder = padder;
}
/**
* Sets the Interpreter.
* @param interpreter The interpreter to use in packing and unpacking.
*/
public void setInterpreter(BinaryInterpreter interpreter) {
this.interpreter = interpreter;
}
/**
* Sets the length prefixer.
* @param prefixer The length prefixer to use during packing and unpacking.
*/
public void setPrefixer(Prefixer prefixer) {
this.prefixer = prefixer;
}
/**
* Gets the formatter, which assembles tag TT and length LL parts in required format
* @return the formatter of the header part (length and tag parts)
*/
public IsoFieldHeaderFormatter getHeaderFormatter() {
return headerFormatter;
}
/**
* Sets the formatter, which assembles tag TT and length LL parts in required format
* @param headerFormatter the formatter of the header part (length and tag parts)
*/
public void setHeaderFormatter(IsoFieldHeaderFormatter headerFormatter) {
this.headerFormatter = headerFormatter;
}
/**
* Returns the prefixer's packed length and the interpreter's packed length.
* @see ISOFieldPackager#getMaxPackedLength()
*/
@Override
public int getMaxPackedLength() {
return tagPrefixer.getPackedLength() + prefixer.getPackedLength() + interpreter.getPackedLength(getLength());
}
/**
* Create a nice readable message for errors
*/
private String makeExceptionMessage(ISOComponent c, String operation) {
Object fieldKey = "unknown";
if (c != null)
try{
fieldKey = c.getKey();
} catch (Exception ignore){}
return this.getClass().getName() + ": Problem " + operation + " field " + fieldKey;
}
/**
* Convert the component into a byte[].
*/
@Override
public byte[] pack(ISOComponent c) throws ISOException {
try{
byte[] valueBytes = (byte[])c.getValue();
if (valueBytes.length < 0 || valueBytes.length > getLength())
throw new ISOException("Field length " + valueBytes.length + " too long. Max: " + getLength());
int tag = (Integer)c.getKey();
byte[] paddedValueBytes = valueBytes;
if (!(padder instanceof NullPadder)) //for save few cycles
paddedValueBytes = ISOUtil.hex2byte(padder.pad(ISOUtil.hexString(valueBytes), getLength()));
byte[] rawData = new byte[tagPrefixer.getPackedLength() + prefixer.getPackedLength() + interpreter.getPackedLength(paddedValueBytes.length)];
byte[] rawTagData = new byte[tagPrefixer.getPackedLength()];
tagPrefixer.encodeLength(tag, rawTagData);
byte[] rawLen = new byte[prefixer.getPackedLength()];
prefixer.encodeLength(!headerFormatter.isTagFirst() ? paddedValueBytes.length + tagPrefixer.getPackedLength() : paddedValueBytes.length, rawLen);
headerFormatter.format(tagPrefixer, prefixer, rawTagData, rawLen, rawData);
interpreter.interpret(paddedValueBytes, rawData, headerFormatter.getTotalLength(tagPrefixer, prefixer));
return rawData;
} catch(Exception e) {
throw new ISOException(makeExceptionMessage(c, "packing"), e);
}
}
/**
* Unpacks the byte array into the component.
* @param c The component to unpack into.
* @param b The byte array to unpack.
* @param offset The index in the byte array to start unpacking from.
* @return The number of bytes consumed unpacking the component.
*/
@Override
public int unpack(ISOComponent c, byte[] b, int offset) throws ISOException {
try{
int tagLen = tagPrefixer.getPackedLength();
c.setFieldNumber(tagPrefixer.decodeLength(b, offset + headerFormatter.getTagIndex(prefixer)));
int len = prefixer.decodeLength(b, offset + headerFormatter.getLengthIndex(tagPrefixer));
if (!headerFormatter.isTagFirst()) {
len -= tagPrefixer.getPackedLength();
}
if (len == -1) {
// The prefixer doesn't know how long the field is, so use
// maxLength instead
len = getLength();
} else if (getLength() > 0 && len > getLength()) {
throw new ISOException("Field length " + len + " too long. Max: " + getLength());
}
int lenLen = prefixer.getPackedLength();
byte[] unpacked = interpreter.uninterpret(b, offset + tagPrefixer.getPackedLength() + prefixer.getPackedLength(), len);
byte[] paddedValueBytes = unpacked;
if (!(padder instanceof NullPadder)) //for save few cycles
paddedValueBytes = ISOUtil.hex2byte(padder.unpad(ISOUtil.hexString(unpacked)));
c.setValue(paddedValueBytes);
return tagLen + lenLen + interpreter.getPackedLength(len);
} catch(Exception e){
throw new ISOException(makeExceptionMessage(c, "unpacking"), e);
}
}
/**
* Unpack the input stream into the component.
* @param c The Component to unpack into.
* @param in Input stream where the packed bytes come from.
* @exception IOException Thrown if there's a problem reading the input stream.
*/
@Override
public void unpack (ISOComponent c, InputStream in)
throws IOException, ISOException {
try {
int tagLen = tagPrefixer.getPackedLength();
int lenLen = prefixer.getPackedLength() == 0 ? getLength() : prefixer.getPackedLength();
int len = -1;
if (headerFormatter.getTagIndex(prefixer) == 0) {
c.setFieldNumber(tagPrefixer.decodeLength(readBytes(in, tagLen), 0));
len = prefixer.decodeLength(readBytes(in, lenLen), 0);
} else {
len = prefixer.decodeLength(readBytes(in, lenLen), 0);
c.setFieldNumber(tagPrefixer.decodeLength(readBytes(in, tagLen), 0));
}
if (getLength() > 0 && len > 0 && len > getLength()) {
throw new ISOException("Field length " + len + " too long. Max: " + getLength());
}
int packedLen = interpreter.getPackedLength(len);
byte[] unpacked = interpreter.uninterpret(readBytes (in, packedLen), 0, len);
c.setValue(unpacked);
} catch(ISOException e){
throw new ISOException(makeExceptionMessage(c, "unpacking"), e);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy