/** You may copy this example and use it for any purpose, commercial or otherwise. */ import com.ricebridge.xmlman.XmlSpec; import com.ricebridge.xmlman.RecordSpec; import com.ricebridge.xmlman.RecordListenerSupport; import com.ricebridge.xmlman.BeanRecordListener; import com.ricebridge.xmlman.BadRecord; import com.ricebridge.data.BeanSpec; import java.util.*; import java.io.*; /** This is a custom RecordListener than can handle streaming data. * It builds on the MultipleBeansRecordListener class, but instead of * storing the data, it creates the HTML directly. Thus, you can use this * class to handle arbitrarily large input files. * * To compile this class, you will need to include xmlman.jar * (in the lib folder of the XML Manager distribution) in your CLASSPATH. */ public class StreamingMultipleBeansRecordListener extends MultipleBeansRecordListener { // protected instance /** This is the PrintWriter for outputing the HTML. */ protected PrintWriter iPrintWriter = null; /** Flag to help create the right HTML table code. */ protected boolean iLastWasEmployee = false; /** Flag to indicate we are on the first record. */ protected boolean iFirst = true; /** Initialise the RecordListener with a PrintWriter. */ public StreamingMultipleBeansRecordListener( PrintWriter pPrintWriter ) { iPrintWriter = pPrintWriter; } /** This method now has no function, as we do not store the Beans. */ public List getBeans( String pCodeName) { return Collections.EMPTY_LIST; } // protected methods /** Start the load process. */ protected void startProcessImpl() { System.out.println( "Using StreamingMultipleBeansRecordListener" ); } /** Handle a data record. * Check the first value and use that as the bean code. Once the bean * is created, it is passed directly to the saveBean method for saving and is not * stored in memory. * @param pRecord data record fields * @param pRecordNumber number of records of this type seen so far */ protected BadRecord handleRecordImpl( String[] pRecord, long pRecordNumber ) throws Exception { String codename = pRecord[0]; if( iBeanSpecMap.containsKey( codename ) ) { BeanSpec bs = (BeanSpec) iBeanSpecMap.get( codename ); String[] fieldnames = (String[]) iBeanFieldsMap.get( codename ); Object bean = bs.getBeanClass().newInstance(); for( int fI = 1; fI < fieldnames.length; fI++ ) { bs.setStringValue( bean, fieldnames[fI], pRecord[fI], iUseDefault ); } saveBean( bean ); if( 0 == pRecordNumber % 100 ) { long memused = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(); System.out.println( codename+" records:"+pRecordNumber+" mem:"+memused ); } return null; } else { return new BadRecord( pRecordNumber, pRecord, "unknown code: "+codename ); } } /** End the load process. */ protected void endProcessImpl() { if( !iFirst ) { if( iLastWasEmployee ) { MakeTable.outputEndEmployeeTable( iPrintWriter ); } else { MakeTable.outputEndProjectTable( iPrintWriter ); } } } /** Save a Java Bean. * Based on the bean type, the correct HTML is output. Note that * cross-referencing is not possible when using the data as a stream. * @param pBean Employee or Project object. */ protected void saveBean( Object pBean ) { if( pBean instanceof Project ) { if( iLastWasEmployee || iFirst ) { if( !iFirst ) { MakeTable.outputEndEmployeeTable( iPrintWriter ); } else { iFirst = false; } MakeTable.outputStartProjectTable( iPrintWriter ); } MakeTable.outputProject( (Project) pBean, null, iPrintWriter ); iLastWasEmployee = false; } else if( pBean instanceof Employee ) { if( !iLastWasEmployee || iFirst ) { if( !iFirst ) { MakeTable.outputEndProjectTable( iPrintWriter ); } else { iFirst = false; } MakeTable.outputStartEmployeeTable( iPrintWriter ); } MakeTable.outputEmployee( (Employee) pBean, null, iPrintWriter ); iLastWasEmployee = true; } } }