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 java.io.IOException; 022import java.io.InputStream; 023 024/** 025 * Uses a 2 EBCDIC byte length field. 026 * 027 * right-justified with leading 0 028 * and packed data as BCD. 2 BCD digits 029 * per byte and adding the value hex(0xF) 030 * for padding if length is odd. 031 * 032 * @author julien.moebs@paybox.net 033 * @author doronf@xor-t.com 034 * @version $Id$ 035 * @see ISOFieldPackager 036 * @see ISOComponent 037 */ 038public class IFEB_LLNUM extends ISOFieldPackager { 039 /** Default constructor. */ 040 public IFEB_LLNUM () { 041 super(); 042 } 043 /** 044 * Constructs a packager with the given length and description. 045 * @param len - field len 046 * @param description symbolic descrption 047 */ 048 public IFEB_LLNUM (int len, String description) { 049 super(len, description); 050 } 051 /** 052 * @param c - a component 053 * @return packed component 054 * @exception ISOException on ISO processing error 055 */ 056 public byte[] pack(ISOComponent c) throws ISOException { 057 boolean odd = false; 058 int len; 059 String s = (String) c.getValue(); 060 061 if ((len=s.length()) > getLength() || len>99) // paranoia settings 062 throw new ISOException( 063 "invalid len "+len +" packing IFEB_LLNUM field "+ c.getKey()); 064 065 // if odd length 066 if ( len%2 ==1 ) { 067 odd = true; 068 len = len/2 +1; 069 } else { 070 odd = false; 071 len = len/2; 072 } 073 074 String fieldLength = ISOUtil.zeropad(Integer.toString(len), 2); 075 076 byte [] EBCDIClength = ISOUtil.asciiToEbcdic(fieldLength); 077 078 // bcd stuff 079 byte[] bcd = ISOUtil.str2bcd(s, false); 080 081 if(odd) 082 bcd[len-1] = (byte) (bcd[len-1] | 0xf); 083 084 byte[] b = new byte[bcd.length + 2]; 085 086 b[0] = EBCDIClength[0]; 087 b[1] = EBCDIClength[1]; 088 System.arraycopy(bcd, 0, b, 2, bcd.length); 089 090 return b; 091 } 092 /** 093 * @param c - the Component to unpack 094 * @param b - binary image 095 * @param offset - starting offset within the binary image 096 * @return consumed bytes 097 * @exception ISOException on ISO processing error 098 */ 099 public int unpack(ISOComponent c, byte[] b, int offset) 100 throws ISOException { 101 boolean pad = false; 102 int len = (b[offset] & 0x0f) * 10 + (b[offset+1] & 0x0f); 103 int tempLen = len*2; 104 105 // odd handling 106 byte lastByte = b[offset+2+len-1]; 107 108 if((lastByte & 0x0f) == 0x0f) 109 tempLen--; 110 111 c.setValue(ISOUtil.bcd2str(b, offset+2, tempLen, pad)); 112 113 return len+2; 114 } 115 116 /* 117 * code contributed by doronf@xor-t.com 118 */ 119 public void unpack (ISOComponent c, InputStream in) 120 throws IOException, ISOException 121 { 122 byte[] b = readBytes (in, 2); 123 int len = 124 100 * (((b[0] >> 4 & 0x0F) > 0x09 ? 0 : 125 b[0] >> 4 & 0x0F) * 10 + (b[0] & 0x0F)) 126 + ((b[1] >> 4 & 0x0F) > 0x09 ? 0 : 127 b[1] >> 4 & 0x0F) * 10 + (b[1] & 0x0F); 128 c.setValue (ISOUtil.bcd2str (readBytes (in, len), 0, 2*len, pad)); 129 } 130 131 public int getMaxPackedLength() { 132 return getLength()+2; 133 } 134}