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 * Wraps a regular binary field packager so its payload can be exposed as an 026 * {@link ISODatasetField}. 027 */ 028public class DatasetFieldPackager extends ISOFieldPackager { 029 /** Inner packager that handles the dataset payload (TLV/DBM). */ 030 protected ISODatasetPackager datasetPackager; 031 /** Outer field packager handling length and transport encoding. */ 032 protected ISOFieldPackager fieldPackager; 033 034 /** 035 * Creates a dataset-aware field packager. 036 * 037 * @param fieldPackager outer field packager used for length and transport encoding 038 * @param datasetPackager inner dataset payload packager 039 */ 040 public DatasetFieldPackager(ISOFieldPackager fieldPackager, ISODatasetPackager datasetPackager) { 041 super(fieldPackager.getLength(), fieldPackager.getDescription()); 042 this.datasetPackager = datasetPackager; 043 this.fieldPackager = fieldPackager; 044 } 045 046 /** 047 * Packs a dataset field by first encoding the inner dataset payload and 048 * then delegating the outer field framing to the wrapped field packager. 049 * 050 * @param c field component to pack 051 * @return packed field bytes 052 * @throws ISOException on packing errors 053 */ 054 @Override 055 public byte[] pack(ISOComponent c) throws ISOException { 056 if (c instanceof ISODatasetField) { 057 ISODatasetField datasetField = (ISODatasetField) c; 058 int fieldNumber = datasetField.getFieldNumber() >= 0 ? datasetField.getFieldNumber() : 0; 059 ISOBinaryField field = new ISOBinaryField(fieldNumber, datasetPackager.pack(datasetField)); 060 if (datasetPackager.getFieldNumber() > -1) { 061 field.setFieldNumber(datasetPackager.getFieldNumber()); 062 } 063 return fieldPackager.pack(field); 064 } 065 return fieldPackager.pack(c); 066 } 067 068 /** 069 * Unpacks a dataset field from a byte array. 070 * 071 * @param c destination component 072 * @param b source buffer 073 * @param offset starting offset 074 * @return number of bytes consumed from the outer field 075 * @throws ISOException on unpacking errors 076 */ 077 @Override 078 public int unpack(ISOComponent c, byte[] b, int offset) throws ISOException { 079 ISOBinaryField field = new ISOBinaryField(0); 080 if (datasetPackager.getFieldNumber() > -1) { 081 field.setFieldNumber(datasetPackager.getFieldNumber()); 082 } 083 int consumed = fieldPackager.unpack(field, b, offset); 084 if (field.getValue() != null && c instanceof ISODatasetField) { 085 datasetPackager.unpack(c, (byte[]) field.getValue()); 086 } 087 return consumed; 088 } 089 090 /** 091 * Unpacks a dataset field from a stream. 092 * 093 * @param c destination component 094 * @param in source stream 095 * @throws IOException on stream errors 096 * @throws ISOException on unpacking errors 097 */ 098 @Override 099 public void unpack(ISOComponent c, InputStream in) throws IOException, ISOException { 100 ISOBinaryField field = new ISOBinaryField(0); 101 if (datasetPackager.getFieldNumber() > -1) { 102 field.setFieldNumber(datasetPackager.getFieldNumber()); 103 } 104 fieldPackager.unpack(field, in); 105 if (field.getValue() != null && c instanceof ISODatasetField) { 106 datasetPackager.unpack(c, (byte[]) field.getValue()); 107 } 108 } 109 110 /** 111 * Creates an {@link ISODatasetField} for the supplied field number. 112 * 113 * @param fieldNumber outer field number 114 * @return dataset field component 115 */ 116 @Override 117 public ISOComponent createComponent(int fieldNumber) { 118 return new ISODatasetField(fieldNumber); 119 } 120 121 /** 122 * Returns the maximum packed length of the outer field. 123 * 124 * @return maximum packed length 125 */ 126 @Override 127 public int getMaxPackedLength() { 128 return fieldPackager.getLength(); 129 } 130 131 /** 132 * Returns the inner dataset payload packager. 133 * 134 * @return dataset packager 135 */ 136 public ISODatasetPackager getISODatasetPackager() { 137 return datasetPackager; 138 } 139 140 /** 141 * Returns the wrapped outer field packager. 142 * 143 * @return outer field packager 144 */ 145 public ISOFieldPackager getISOFieldPackager() { 146 return fieldPackager; 147 } 148}