// uniCenta oPOS - Touch Friendly Point Of Sale // Copyright (c) 2009-2013 uniCenta & previous Openbravo POS works // http://www.unicenta.net/unicentaopos // // This file is part of uniCenta oPOS // // uniCenta oPOS is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // uniCenta oPOS 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 uniCenta oPOS. If not, see <http://www.gnu.org/licenses/>. package com.openbravo.pos.printer; import com.openbravo.data.loader.LocalRes; import com.openbravo.pos.forms.DataLogicSystem; import com.openbravo.pos.ticket.TicketInfo; import java.applet.Applet; import java.applet.AudioClip; import java.awt.image.BufferedImage; import java.io.IOException; import java.io.Reader; import java.io.StringReader; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import org.xml.sax.Attributes; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; public class TicketParser extends DefaultHandler { private static SAXParser m_sp = null; private DeviceTicket m_printer; private DataLogicSystem m_system; private StringBuilder text; private String bctype; private String bcposition; private int m_iTextAlign; private int m_iTextLength; private int m_iTextStyle; private StringBuilder m_sVisorLine; private int m_iVisorAnimation; private String m_sVisorLine1; private String m_sVisorLine2; private double m_dValue1; private double m_dValue2; private int attribute3; private int m_iOutputType; private static final int OUTPUT_NONE = 0; private static final int OUTPUT_DISPLAY = 1; private static final int OUTPUT_TICKET = 2; private static final int OUTPUT_FISCAL = 3; private DevicePrinter m_oOutputPrinter; private DateFormat df= new SimpleDateFormat("MM/dd/yyyy HH:mm:ss"); private Date today; private String cUser; private String ticketId; /** Creates a new instance of TicketParser */ public TicketParser(DeviceTicket printer, DataLogicSystem system) { m_printer = printer; m_system = system; today = Calendar.getInstance().getTime(); } public void printTicket(String sIn, TicketInfo ticket) throws TicketPrinterException { cUser=ticket.getUser().getName(); ticketId=Integer.toString(ticket.getTicketId()); if (ticket.getTicketId()==0){ticketId="No Sale";} printTicket(new StringReader(sIn)); } public void printTicket(String sIn) throws TicketPrinterException { printTicket(new StringReader(sIn)); } public void printTicket(Reader in) throws TicketPrinterException { try { if (m_sp == null) { SAXParserFactory spf = SAXParserFactory.newInstance(); m_sp = spf.newSAXParser(); } m_sp.parse(new InputSource(in), this); } catch (ParserConfigurationException ePC) { throw new TicketPrinterException(LocalRes.getIntString("exception.parserconfig") , ePC); } catch (SAXException eSAX) { throw new TicketPrinterException(LocalRes.getIntString("exception.xmlfile") , eSAX); } catch (IOException eIO) { throw new TicketPrinterException(LocalRes.getIntString("exception.iofile") , eIO); } } @Override public void startDocument() throws SAXException { // inicalizo las variables pertinentes text = null; bctype = null; bcposition = null; m_sVisorLine = null; m_iVisorAnimation = DeviceDisplayBase.ANIMATION_NULL; m_sVisorLine1 = null; m_sVisorLine2 = null; m_iOutputType = OUTPUT_NONE; m_oOutputPrinter = null; } @Override public void endDocument() throws SAXException { } @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException{ String openDate = df.format(today); switch (m_iOutputType) { case OUTPUT_NONE: if ("opendrawer".equals(qName)) { m_printer.getDevicePrinter(readString(attributes.getValue("printer"), "1")).openDrawer(); // Cashdrawer has been activated record the data in the table // try { // m_system.execDrawerOpened( // new Object[] {openDate,cUser,ticketId}); // } catch (BasicException ex) {} } else if ("play".equals(qName)) { text = new StringBuilder(); } else if ("ticket".equals(qName)) { m_iOutputType = OUTPUT_TICKET; m_oOutputPrinter = m_printer.getDevicePrinter(readString(attributes.getValue("printer"), "1")); m_oOutputPrinter.beginReceipt(); } else if ("display".equals(qName)) { m_iOutputType = OUTPUT_DISPLAY; String animation = attributes.getValue("animation"); if ("scroll".equals(animation)) { m_iVisorAnimation = DeviceDisplayBase.ANIMATION_SCROLL; } else if ("flyer".equals(animation)) { m_iVisorAnimation = DeviceDisplayBase.ANIMATION_FLYER; } else if ("blink".equals(animation)) { m_iVisorAnimation = DeviceDisplayBase.ANIMATION_BLINK; } else if ("curtain".equals(animation)) { m_iVisorAnimation = DeviceDisplayBase.ANIMATION_CURTAIN; } else { // "none" m_iVisorAnimation = DeviceDisplayBase.ANIMATION_NULL; } m_sVisorLine1 = null; m_sVisorLine2 = null; m_oOutputPrinter = null; } else if ("fiscalreceipt".equals(qName)) { m_iOutputType = OUTPUT_FISCAL; m_printer.getFiscalPrinter().beginReceipt(); } else if ("fiscalzreport".equals(qName)) { m_printer.getFiscalPrinter().printZReport(); } else if ("fiscalxreport".equals(qName)) { m_printer.getFiscalPrinter().printXReport(); } break; case OUTPUT_TICKET: if ("logo".equals(qName)){ text = new StringBuilder(); } else if ("image".equals(qName)){ text = new StringBuilder(); } else if ("barcode".equals(qName)) { text = new StringBuilder(); bctype = attributes.getValue("type"); bcposition = attributes.getValue("position"); } else if ("line".equals(qName)) { m_oOutputPrinter.beginLine(parseInt(attributes.getValue("size"), DevicePrinter.SIZE_0)); } else if ("text".equals(qName)) { text = new StringBuilder(); m_iTextStyle = ("true".equals(attributes.getValue("bold")) ? DevicePrinter.STYLE_BOLD : DevicePrinter.STYLE_PLAIN) | ("true".equals(attributes.getValue("underline")) ? DevicePrinter.STYLE_UNDERLINE : DevicePrinter.STYLE_PLAIN); String sAlign = attributes.getValue("align"); if ("right".equals(sAlign)) { m_iTextAlign = DevicePrinter.ALIGN_RIGHT; } else if ("center".equals(sAlign)) { m_iTextAlign = DevicePrinter.ALIGN_CENTER; } else { m_iTextAlign = DevicePrinter.ALIGN_LEFT; } m_iTextLength = parseInt(attributes.getValue("length"), 0); } break; case OUTPUT_DISPLAY: if ("line".equals(qName)) { // line 1 or 2 of the display m_sVisorLine = new StringBuilder(); } else if ("line1".equals(qName)) { // linea 1 del visor m_sVisorLine = new StringBuilder(); } else if ("line2".equals(qName)) { // linea 2 del visor m_sVisorLine = new StringBuilder(); } else if ("text".equals(qName)) { text = new StringBuilder(); String sAlign = attributes.getValue("align"); if ("right".equals(sAlign)) { m_iTextAlign = DevicePrinter.ALIGN_RIGHT; } else if ("center".equals(sAlign)) { m_iTextAlign = DevicePrinter.ALIGN_CENTER; } else { m_iTextAlign = DevicePrinter.ALIGN_LEFT; } m_iTextLength = parseInt(attributes.getValue("length")); } break; case OUTPUT_FISCAL: if ("line".equals(qName)) { text = new StringBuilder(); m_dValue1 = parseDouble(attributes.getValue("price")); m_dValue2 = parseDouble(attributes.getValue("units"), 1.0); attribute3 = parseInt(attributes.getValue("tax")); } else if ("message".equals(qName)) { text = new StringBuilder(); } else if ("total".equals(qName)) { text = new StringBuilder(); m_dValue1 = parseDouble(attributes.getValue("paid")); } break; } } public void endElement(String uri, String localName, String qName) throws SAXException { switch (m_iOutputType) { case OUTPUT_NONE: if ("play".equals(qName)) { try { AudioClip oAudio = Applet.newAudioClip(getClass().getClassLoader().getResource(text.toString())); oAudio.play(); } catch (Exception fnfe) { //throw new ResourceNotFoundException( fnfe.getMessage() ); } text = null; } break; // Added 23.05.13 used by star TSP700 to print stored logo image JDL case OUTPUT_TICKET: if ("logo".equals(qName)){ m_oOutputPrinter.printLogo(); // } }else if ("image".equals(qName)){ try { // BufferedImage image = ImageIO.read(getClass().getClassLoader().getResourceAsStream(m_sText.toString())); BufferedImage image = m_system.getResourceAsImage(text.toString()); if (image != null) { m_oOutputPrinter.printImage(image); } } catch (Exception fnfe) { //throw new ResourceNotFoundException( fnfe.getMessage() ); } text = null; } else if ("barcode".equals(qName)) { m_oOutputPrinter.printBarCode( bctype, bcposition, text.toString()); text = null; } else if ("text".equals(qName)) { if (m_iTextLength > 0) { switch(m_iTextAlign) { case DevicePrinter.ALIGN_RIGHT: m_oOutputPrinter.printText(m_iTextStyle, DeviceTicket.alignRight(text.toString(), m_iTextLength)); break; case DevicePrinter.ALIGN_CENTER: m_oOutputPrinter.printText(m_iTextStyle, DeviceTicket.alignCenter(text.toString(), m_iTextLength)); break; default: // DevicePrinter.ALIGN_LEFT m_oOutputPrinter.printText(m_iTextStyle, DeviceTicket.alignLeft(text.toString(), m_iTextLength)); break; } } else { m_oOutputPrinter.printText(m_iTextStyle, text.toString()); } text = null; } else if ("line".equals(qName)) { m_oOutputPrinter.endLine(); } else if ("ticket".equals(qName)) { m_oOutputPrinter.endReceipt(); m_iOutputType = OUTPUT_NONE; m_oOutputPrinter = null; } break; case OUTPUT_DISPLAY: if ("line".equals(qName)) { // line 1 or 2 of the display if (m_sVisorLine1 == null) { m_sVisorLine1 = m_sVisorLine.toString(); } else { m_sVisorLine2 = m_sVisorLine.toString(); } m_sVisorLine = null; } else if ("line1".equals(qName)) { // linea 1 del visor m_sVisorLine1 = m_sVisorLine.toString(); m_sVisorLine = null; } else if ("line2".equals(qName)) { // linea 2 del visor m_sVisorLine2 = m_sVisorLine.toString(); m_sVisorLine = null; } else if ("text".equals(qName)) { if (m_iTextLength > 0) { switch(m_iTextAlign) { case DevicePrinter.ALIGN_RIGHT: m_sVisorLine.append(DeviceTicket.alignRight(text.toString(), m_iTextLength)); break; case DevicePrinter.ALIGN_CENTER: m_sVisorLine.append(DeviceTicket.alignCenter(text.toString(), m_iTextLength)); break; default: // DevicePrinter.ALIGN_LEFT m_sVisorLine.append(DeviceTicket.alignLeft(text.toString(), m_iTextLength)); break; } } else { m_sVisorLine.append(text); } text = null; } else if ("display".equals(qName)) { m_printer.getDeviceDisplay().writeVisor(m_iVisorAnimation, m_sVisorLine1, m_sVisorLine2); m_iVisorAnimation = DeviceDisplayBase.ANIMATION_NULL; m_sVisorLine1 = null; m_sVisorLine2 = null; m_iOutputType = OUTPUT_NONE; m_oOutputPrinter = null; } break; case OUTPUT_FISCAL: if ("fiscalreceipt".equals(qName)) { m_printer.getFiscalPrinter().endReceipt(); m_iOutputType = OUTPUT_NONE; } else if ("line".equals(qName)) { m_printer.getFiscalPrinter().printLine(text.toString(), m_dValue1, m_dValue2, attribute3); text = null; } else if ("message".equals(qName)) { m_printer.getFiscalPrinter().printMessage(text.toString()); text = null; } else if ("total".equals(qName)) { m_printer.getFiscalPrinter().printTotal(text.toString(), m_dValue1); text = null; } break; } } @Override public void characters(char[] ch, int start, int length) throws SAXException { if (text != null) { text.append(ch, start, length); } } private int parseInt(String sValue, int iDefault) { try { return Integer.parseInt(sValue); } catch (NumberFormatException eNF) { return iDefault; } } private int parseInt(String sValue) { return parseInt(sValue, 0); } private double parseDouble(String sValue, double ddefault) { try { return Double.parseDouble(sValue); } catch (NumberFormatException eNF) { return ddefault; } } private double parseDouble(String sValue) { return parseDouble(sValue, 0.0); } private String readString(String sValue, String sDefault) { if (sValue == null || sValue.equals("")) { return sDefault; } else { return sValue; } } }