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.tlv.packager; 020 021import org.jpos.iso.ISOComponent; 022import org.jpos.iso.ISOException; 023import org.jpos.iso.ISOField; 024import org.jpos.iso.ISOFieldPackager; 025import org.jpos.iso.TaggedFieldPackager; 026 027import java.io.IOException; 028import java.io.InputStream; 029import java.nio.ByteBuffer; 030 031/** 032 * Field Separator Terminated packager 033 * @author Vishnu Pillai 034 */ 035public class IF_FSTCHAR extends ISOFieldPackager implements TaggedFieldPackager { 036 037 private char terminator = '\\'; 038 039 public IF_FSTCHAR() { 040 super(); 041 } 042 043 @Override 044 public void setToken(String token) { 045 if (token == null || token.length() != 1) { 046 throw new IllegalArgumentException("IF_FSTCHAR needs a token of 1 character."); 047 } 048 terminator = token.charAt(0); 049 } 050 051 @Override 052 public String getToken() { 053 return String.valueOf(terminator); 054 } 055 056 /** 057 * @param len - field len 058 * @param description symbolic descrption 059 */ 060 public IF_FSTCHAR(int len, String description) { 061 super(len, description); 062 } 063 064 /** 065 * @param c - a component 066 * @return packed component 067 * @throws org.jpos.iso.ISOException 068 */ 069 public byte[] pack(ISOComponent c) throws ISOException { 070 int len; 071 String s = (String) c.getValue(); 072 073 if ((len = s.length()) > getLength()) { 074 throw new ISOException( 075 "Invalid length " + len + " packing IF_FSTCHAR field " 076 + c.getKey() + " max length=" + getLength() 077 ); 078 } 079 080 s = s + terminator; 081 return s.getBytes(); 082 } 083 084 /** 085 * @param c - the Component to unpack 086 * @param b - binary image 087 * @param offset - starting offset within the binary image 088 * @return consumed bytes 089 * @throws org.jpos.iso.ISOException 090 */ 091 public int unpack(ISOComponent c, byte[] b, int offset) 092 throws ISOException { 093 if (!(c instanceof ISOField)) 094 throw new ISOException 095 (c.getClass().getName() + " is not an ISOField"); 096 int length = -1; 097 for (int i = 0; i < getMaxPackedLength(); i++) { 098 byte dataByte = b[offset + i]; 099 if ((char) dataByte == terminator) { 100 length = i; 101 break; 102 } 103 } 104 if (length >= 0) { 105 String value = new String(b, offset, length); 106 c.setValue(value); 107 return length + 1; 108 } else { 109 throw new ISOException("Terminating Backslash does not exist"); 110 } 111 } 112 113 public void unpack(ISOComponent c, InputStream in) 114 throws IOException, ISOException { 115 116 if (!(c instanceof ISOField)) 117 throw new ISOException 118 (c.getClass().getName() + " is not an ISOField"); 119 120 boolean endFound = false; 121 if (in.markSupported()) { 122 in.mark(getMaxPackedLength()); 123 } 124 ByteBuffer buf = ByteBuffer.allocate(getMaxPackedLength()); 125 126 for (int i = 0; i < getMaxPackedLength() && in.available() > 0; i++) { 127 byte dataByte = (byte) in.read(); 128 if ((char) dataByte == terminator) { 129 endFound = true; 130 break; 131 } else { 132 buf.put(dataByte); 133 } 134 } 135 if (endFound) { 136 byte[] data = byteBufferToBytes(buf); 137 String value = new String(data); 138 c.setValue(value); 139 } else { 140 if (in.markSupported()) { 141 in.reset(); 142 } 143 throw new ISOException("Terminating Backslash does not exist"); 144 } 145 } 146 147 private byte[] byteBufferToBytes(ByteBuffer buffer) { 148 int dataLength = buffer.position(); 149 byte[] bytes = new byte[dataLength]; 150 buffer.position(0); 151 buffer.get(bytes); 152 buffer.position(dataLength); 153 return bytes; 154 } 155 156 public int getMaxPackedLength() { 157 return getLength() + 1; 158 } 159} 160