/******************************************************************************
* Product: Adempiere ERP & CRM Smart Business Solution *
* Copyright (C) 1999-2007 ComPiere, Inc. All Rights Reserved. *
* This program is free software, you can redistribute it and/or modify it *
* under the terms version 2 of the GNU General Public License as published *
* by the Free Software Foundation. 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 General Public License for more details. *
* You should have received a copy of the GNU General Public License along *
* with this program, if not, write to the Free Software Foundation, Inc., *
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
* For the text or an alternative of this public license, you may reach us *
* ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA *
* or via info@compiere.org or http://www.compiere.org/license.html *
*****************************************************************************/
package ar.com.ergio.print.fiscal;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import ar.com.ergio.print.fiscal.util.ByteFormatter;
/**
* An abstract base class for FiscalPacket implementations.
* @contributor Emiliano Pereyra - http://www.ergio.com.ar
*/
public abstract class AbstractFiscalPacket implements FiscalPacket
{
private static final long serialVersionUID = 558117040031879527L;
private static final boolean DISCARD_LEAP_SECOND = true;
private static final byte[] EMPTY_FIELD = new byte[0];
private List fields = new ArrayList();
private FiscalPrinterDevice fiscalPrinter;
public AbstractFiscalPacket() {
super();
}
/**
* @param fiscalPrinter
*/
public AbstractFiscalPacket(FiscalPrinterDevice fiscalPrinter) {
super();
this.fiscalPrinter = fiscalPrinter;
}
public boolean equals(Object o)
{
if (this == o) return true;
if (!(o instanceof FiscalPacket)) return false;
FiscalPacket p = (FiscalPacket) o;
int s = getSize();
if (s != p.getSize()) return false;
for (int i = 0; i < s; i++) if (!Arrays.equals(get(i), p.get(i))) return false;
return true;
}
public Object clone()
{
AbstractFiscalPacket p;
try { p = (AbstractFiscalPacket) super.clone(); }
catch (CloneNotSupportedException e) { throw new Error(e.toString()); }
List f = new ArrayList(fields.size());
Iterator i = fields.iterator();
while (i.hasNext())
{
byte[] x = (byte[]) i.next();
int l = x.length;
byte[] y = new byte[l];
System.arraycopy(x, 0, y, 0, l);
f.add(y);
}
p.fields = f;
p.setFiscalPrinter(getFiscalPrinter());
return p;
}
public String toString() { return toHexString(); }
public String toHexString()
{
StringBuffer b = new StringBuffer();
b.append('{');
for (int i = 0, s = getSize(); i < s; i++)
{
b.append(' ');
ByteFormatter.toHexString(b, get(i));
}
b.append(' ').append('}');
return b.toString();
}
public String toASCIIString()
{
StringBuffer b = new StringBuffer();
b.append('{');
for (int i = 0, s = getSize(); i < s; i++)
{
b.append(' ');
ByteFormatter.toASCIIString(b, get(i));
}
b.append(' ').append('}');
return b.toString();
}
// Size
public void clear() { fields.clear(); }
public void setSize(int size)
{
int s = fields.size();
if (s < size)
{
do { fields.add(EMPTY_FIELD); s++; }
while (s < size);
}
else if (s > size)
{
if (size > 0)
{
do { s--; fields.remove(s); }
while (s > size);
}
else
{
if (size == 0) fields.clear();
else throw new IndexOutOfBoundsException();
}
}
}
public int getSize() { return fields.size(); }
// Fields
public void clear(int field) { set(field, EMPTY_FIELD); }
public void set(int field, byte[] value)
{
if (value == null) throw new NullPointerException();
int s = fields.size();
if (field < s) fields.set(field, value);
else
{
while (field > s) { fields.add(EMPTY_FIELD); s++; }
fields.add(value);
}
}
public byte[] get(int field) { return (byte[]) fields.get(field); }
public int getLength(int field) { return get(field).length; }
// Field Copies
public void setCopy(int field, byte[] value) { setCopy(field, value, 0, value.length); }
public void setCopy(int field, byte[] value, int offset, int length)
{
byte[] x = new byte[length];
System.arraycopy(value, offset, x, 0, length);
set(field, x);
}
public byte[] getCopy(int field)
{
byte[] x = get(field);
int l = x.length;
byte[] y = new byte[l];
System.arraycopy(x, 0, y, 0, l);
return y;
}
public int getCopy(int field, byte[] value) { return getCopy(field, value, 0, value.length); }
public int getCopy(int field, byte[] value, int offset, int length)
{
byte[] x = get(field);
int xl = x.length;
System.arraycopy(x, 0, value, offset, length >= xl ? xl : length);
return xl;
}
// Special Numeric Fields
public void setByte(int field, int value)
{
if (value < 0 || value > 0xFF) throw new IllegalArgumentException();
set(field, new byte[] { (byte) value });
}
public int getByte(int field)
{
byte[] v = get(field);
if (v.length != 1) throw new NumberFormatException();
return v[0] & 0xFF;
}
public void setHex16(int field, int value) // NOTE: Does not use setString().
{
if (value < 0 || value > 0xFFFF) throw new IllegalArgumentException();
byte[] v = new byte[4];
int p = 0;
for (int k = 12; k >= 0; k -= 4) v[p++] = (byte) Character.toUpperCase(Character.forDigit((value >> k) & 0xF, 0x10));
set(field, v);
}
public int getHex16(int field) // NOTE: Does not use getString().
{
byte[] v = get(field);
if (v.length != 4) throw new NumberFormatException();
int value = 0;
int p = 0;
for (int k = 12; k >= 0; k -= 4)
{
int d = Character.digit((char) (v[p++] & 0xFF), 0x10);
if (d < 0) throw new NumberFormatException();
value |= (d << k);
}
return value;
}
// Numeric Fields
public void setInt(int field, int value) { setString(field, String.valueOf(value)); }
public int getInt(int field) { return Integer.parseInt(getString(field)); }
public void setLong(int field, long value) { setString(field, String.valueOf(value)); }
public long getLong(int field) { return Long.parseLong(getString(field)); }
public void setFloat(int field, float value) { setString(field, new BigDecimal(String.valueOf(value)).toString()); }
public float getFloat(int field) { return Float.parseFloat(getString(field)); }
public void setDouble(int field, double value) { setString(field, new BigDecimal(String.valueOf(value)).toString()); }
public double getDouble(int field) { return Double.parseDouble(getString(field)); }
public void setBigInteger(int field, BigInteger value) { setString(field, value.toString()); }
public BigInteger getBigInteger(int field) { return new BigInteger(getString(field)); }
public void setBigDecimal(int field, BigDecimal value) { setString(field, value.toString()); }
public BigDecimal getBigDecimal(int field) { return new BigDecimal(getString(field)); }
// Date And Time Fields
public void setDateAndTime(int dateField, int timeField, int year, int month, int day, int hour, int minute, int second)
{
byte[] d = get(dateField);
byte[] t = get(timeField);
boolean success = false;
try
{
setDate(dateField, year, month, day);
setTime(timeField, hour, minute, second);
success = true;
}
finally
{
if (!success)
{
set(dateField, d);
set(timeField, t);
}
}
}
public void setDate(int field, Date date)
{
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
setDate(field, calendar);
}
public Date getDate(int field)
{
Calendar calendar = Calendar.getInstance();
getDate(field, calendar);
return calendar.getTime();
}
public void setDateAndTime(int dateField, int timeField, Date date)
{
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
setDateAndTime(dateField, timeField, calendar);
}
public Date getDateAndTime(int dateField, int timeField)
{
Calendar calendar = Calendar.getInstance();
getDateAndTime(dateField, timeField, calendar);
return calendar.getTime();
}
public void setDate(int field, Calendar calendar)
{
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH) + 1;
int day = calendar.get(Calendar.DAY_OF_MONTH);
setDate(field, year, month, day);
}
public Calendar getDate(int field, Calendar calendar)
{
calendar.clear();
calendar.set(Calendar.YEAR, getDateYear(field));
calendar.set(Calendar.MONTH, getDateMonth(field) - 1);
calendar.set(Calendar.DAY_OF_MONTH, getDateDay(field));
return calendar;
}
public void setDateAndTime(int dateField, int timeField, Calendar calendar)
{
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH) + 1;
int day = calendar.get(Calendar.DAY_OF_MONTH);
int hour = calendar.get(Calendar.HOUR_OF_DAY);
int minute = calendar.get(Calendar.MINUTE);
int second = calendar.get(Calendar.SECOND);
if (DISCARD_LEAP_SECOND && (second == 60 || second == 61)) second = 59;
setDateAndTime(dateField, timeField, year, month, day, hour, minute, second);
}
public Calendar getDateAndTime(int dateField, int timeField, Calendar calendar)
{
calendar.clear();
calendar.set(Calendar.YEAR, getDateYear(dateField));
calendar.set(Calendar.MONTH, getDateMonth(dateField) - 1);
calendar.set(Calendar.DAY_OF_MONTH, getDateDay(dateField));
calendar.set(Calendar.HOUR_OF_DAY, getTimeHour(timeField));
calendar.set(Calendar.MINUTE, getTimeMinute(timeField));
calendar.set(Calendar.SECOND, getTimeSecond(timeField));
return calendar;
}
public void setBoolean(int field, boolean value, String trueValue, String falseValue) {
if(value)
setString(field, trueValue);
else
setString(field, falseValue);
}
public void setOptionalField(int field, Object value) {
if(value == null)
set(field,EMPTY_FIELD);
else if(value instanceof Integer)
setInt(field, (Integer)value);
else if(value instanceof String)
setString(field, (String)value);
else if(value instanceof Float)
setFloat(field, (Float)value);
else if(value instanceof Long)
setLong(field, (Long)value);
else if(value instanceof Double)
setDouble(field, (Double)value);
else if(value instanceof BigInteger)
setBigInteger(field,(BigInteger)value);
else if(value instanceof BigDecimal)
setBigDecimal(field,(BigDecimal)value);
else if(value instanceof Date)
setDate(field, (Date)value);
else
throw new IllegalArgumentException();
}
public void setOptionalBoolean(int field, Boolean value, String trueValue, String falseValue) {
if(value == null)
set(field, EMPTY_FIELD);
else
setBoolean(field, value, trueValue, falseValue);
}
public FiscalPrinterDevice getFiscalPrinter() {
return fiscalPrinter;
}
public void setFiscalPrinter(FiscalPrinterDevice fiscalPrinter) {
this.fiscalPrinter = fiscalPrinter;
}
public void setQuantity(int field, BigDecimal quantity, boolean optional) {
String qtyStr = quantity.toString();
if(getFiscalPrinter() != null)
qtyStr = getFiscalPrinter().formatQuantity(quantity);
if(optional)
setOptionalField(field,qtyStr);
else
setString(field, qtyStr);
}
public void setAmount(int field, BigDecimal amount, boolean optional) {
String amtStr = amount.toString();
if(getFiscalPrinter() != null)
amtStr = getFiscalPrinter().formatAmount(amount);
if(optional)
setOptionalField(field,amtStr);
else
setString(field, amtStr);
}
public void setPerceptionAmount(int field, BigDecimal amount, boolean optional) {
String amtStr = amount.toString();
if(getFiscalPrinter() != null)
amtStr = getFiscalPrinter().formatPerceptionAmount(amount);
if(optional)
setOptionalField(field,amtStr);
else
setString(field, amtStr);
}
public void setText(int field, String text, int maxLength, boolean optional) {
if(getFiscalPrinter() != null)
text = getFiscalPrinter().formatText(text, maxLength);
if(optional)
setOptionalField(field,text);
else
setString(field, text);
}
public void setText(int field, String text, boolean optional) {
int length = (text == null? 0: text.length());
setText(field, text, length, optional);
}
public void setNumber(int field, BigDecimal number, int integerPart, int decimalPart, boolean optional) {
String numStr = number.toString();
if(getFiscalPrinter() != null)
numStr = getFiscalPrinter().formatNumber(number, integerPart, decimalPart);
if(optional)
setOptionalField(field, numStr);
else
setString(field, numStr);
}
public void setNumber(int field, BigDecimal number, boolean optional) {
if(optional)
setOptionalField(field, number);
else
setBigDecimal(field, number);
}
public void setNumber(int field, Integer number, boolean optional) {
if(optional)
setOptionalField(field, number);
else
setInt(field, number);
}
public void setBoolean(int field, Boolean value, String trueValue, String falseValue, boolean optional) {
if(optional)
setOptionalBoolean(field, value, trueValue, falseValue);
else
setBoolean(field, value, trueValue, falseValue);
}
public void decode(String packetStr) {
decode(packetStr.getBytes());
}
}