/*
 * jPOS Project [http://jpos.org]
 * Copyright (C) 2000-2015 Alejandro P. Revilla
 *
 * 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 <http://www.gnu.org/licenses/>.
 */

package org.jpos.fsdpackager;

import java.util.Map;

import org.jpos.fsdpackager.compliance.APCICompliance;
import org.jpos.fsdpackager.compliance.NoCompliance;
import org.jpos.iso.AsciiInterpreter;
import org.jpos.iso.ISOException;
import org.jpos.iso.Interpreter;

public class VariableFieldPackager extends AFSDFieldPackager {

	String value;
	Byte delimiter;
	Interpreter interpreter = AsciiInterpreter.INSTANCE;
	private int maxSize = Integer.MAX_VALUE;
	int size;
	boolean mandatory = false;
	private APCICompliance compliance = new NoCompliance();

	@Override
	public int unpack(byte[] inStream, int offset, Map<String, String> fields) throws ISOException {

		boolean delimiterFound = false;
		int i = offset;
		int lengthTotraverse;
		if (maxSize <= inStream.length - offset) // length-offset = remaining
													// bytes
			lengthTotraverse = maxSize + offset + 1;// to incluse th delimiter
		else
			lengthTotraverse = inStream.length;
		while (i < lengthTotraverse) { // there is no point traversing to the
										// end, if we can we should traverse to
										// the maxsize
			if (inStream[i] == delimiter.byteValue()) {
				delimiterFound = true;
				break;
			}

			i++;
		}
		if (delimiterFound || i == inStream.length) {

			byte[] dest = new byte[i - offset];
			if ((i - offset) == 0) {
				// Means there is no data and its terminated by delimiter
				value = "";
			} else if ((i - offset) <= maxSize) {
				System.arraycopy(inStream, offset, dest, 0, i - offset);
				value = interpreter.uninterpret(dest, 0, i - offset);

			} else
				throw new ISOException(
						String.format("Field size [%d] is greater than max size [%d] of field ", i - offset, maxSize));

		} else {
			throw new ISOException(String.format("Field [%s]: Delimiter %x not present after max size %d", getName(),
					delimiter.byteValue(), maxSize));
		}
		setValue(value);
		return i - offset + 1;
	}

	@Override
	public byte[] pack(Map<String, String> fields) throws ISOException {

		if (value == null || value.equals("")) {
			// if field is not set, make sure to send the delimiter to indicate
			// its presence.
			return new byte[] { delimiter.byteValue() };
		}
		if (value.length() <= maxSize) {
			byte[] b = new byte[interpreter.getPackedLength(value.length() + 1)];
			interpreter.interpret(value, b, 0);
			b[b.length - 1] = delimiter.byteValue();

			return b;
		}
		throw new ISOException(String.format("Size [%d] is greater than maxSize[%d] ", value.length(), maxSize));
	}

	public VariableFieldPackager(String name, int maxSize, Byte delimiter, Interpreter interpretter) {

		this.maxSize = maxSize;
		this.interpreter = interpretter;
		this.delimiter = delimiter;
		this.setName(name);
	}

	public VariableFieldPackager(String name, int maxSize, Byte delimiter, Interpreter interpretter,
			APCICompliance compliance) {
		this(name, maxSize, delimiter, interpretter);
		this.compliance = compliance;
	}

	public VariableFieldPackager(String name, Byte delimiter, Interpreter interpretter) {

		this.interpreter = interpretter;
		this.delimiter = delimiter;
		this.setName(name);
	}

	public VariableFieldPackager(String name, Byte delimiter, Interpreter interpretter, APCICompliance compliance) {

		this.interpreter = interpretter;
		this.delimiter = delimiter;
		this.setName(name);
		this.compliance = compliance;
	}

	public VariableFieldPackager(String name, int maxSize, Byte delimiter, Interpreter interpretter,
			boolean mandatory) {

		this(name, maxSize, delimiter, interpretter);
		this.mandatory = mandatory;
	}

	@Override
	public String getValue() {
		// TODO Auto-generated method stub
		return value;
	}

	@Override
	public void setValue(String value) {
		this.value = value;
		// TODO Auto-generated method stub

	}

	@Override
	public String dump(String prefix, Map<String, String> setfields) {
		if (getValue()!=null)
		return String.format("%s<field id=\"%s\" value=\"%s\"/>%n", prefix, getName(),
				compliance.makeCompliant(getValue()));
		return "";
	}

	@Override
	public byte[] hexDump(String prefix, Map<String, String> setfields) {

		int numberOfPackedBytes = interpreter.getPackedLength(getValue().length());
		String compliant = compliance.makeCompliant(getValue());
		byte[] temp = new byte[numberOfPackedBytes];
		try {
			interpreter.interpret(compliant, temp, 0);
		} catch (ISOException e) {
			// TODO Auto-generated catch block
			return null;
		}
		return temp;

	}

	@Override
	public String getParserTree(String prefix) {

		return String.format("%sField [%s] : VAR[0..%d] delimiter[0x%X] or EOM%n  %s", prefix, getName(),maxSize, delimiter.byteValue(), getValue()==null?"":": "+getValue());

	}

}

@@ -1644,17 +1644,17 @@
 to inclu
-s
+d
 e th del
@@ -5023,18 +5023,43 @@
 kedBytes
-%5D;
++1%5D;// +1 for the delimiter
 %0A%09%09try %7B
@@ -5111,72 +5111,81 @@
 ;%0A%09%09
-%7D catch (ISOException e) %7B%0A%09%09%09// TODO Auto-generated catch block
+%09temp%5Btemp.length-1%5D= delimiter.byteValue();%0A%09%09%7D catch (ISOException e) %7B
 %0A%09%09%09

Update VariableFieldPackager.java