/** 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.*; /** This is a custom RecordListener than can handle multiple * BeanRecordListeners. The first data field is taken as a code value * that indicated the actual BeanRecordListener to use. The data record * is then passed to that BeanRecordListener. * * 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 MultipleBeansRecordListener extends RecordListenerSupport { // protected instance /** Map of Lists of Java Beans, by code. */ protected HashMap iBeanListMap = new HashMap(); /** Map of Java Bean fields, by code. */ protected HashMap iBeanFieldsMap = new HashMap(); /** Map of BeanSpecs, by code. */ protected HashMap iBeanSpecMap = new HashMap(); /** If true, use the default value of the field if there is an error. */ protected boolean iUseDefault = false; // public methods /** Add a BeanSpec so that the Java Beans it describes can be handled by this class. * @param pCodeName code name which appears as first value in original data record * @param pBeanSpec BeanSpec object describing Java Bean * @param pRecordSpec RecordSpec that will load the data for this bean type */ public void addBeanSpec( String pCodeName, BeanSpec pBeanSpec, RecordSpec pRecordSpec ) { iBeanSpecMap.put( pCodeName, pBeanSpec ); iBeanFieldsMap.put( pCodeName, pRecordSpec.getFieldNames() ); iBeanListMap.put( pCodeName, new ArrayList() ); } /** Get the beans that have been loaded, by code. * @param pCodeName code name which appears as first value in original data record */ public List getBeans( String pCodeName) { return (List) iBeanListMap.get( pCodeName ); } // protected methods /** Get the XmlSpec settings that are relevant to this RecordListener. */ protected void setXmlSpecImpl( XmlSpec pXmlSpec ) { iUseDefault = pXmlSpec.getBooleanProperty( BeanRecordListener.PROP_Bean_useDefault ); } /** Start the load process. */ protected void startProcessImpl() { System.out.println( "Using MultipleBeansRecordListener" ); } /** Handle a data record. * Check the first value and use that as the bean code. * @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 ); } ArrayList beanlist = (ArrayList) iBeanListMap.get( codename ); beanlist.add( bean ); if( 0 == pRecordNumber % 100 ) { long memused = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(); System.out.println( codename+" records:"+pRecordNumber+" mem:"+memused ); } return null; } else { // Instead of throwing an Exception, we return a BadRecord to indicate that // the code is unknown. This allows processing to continue. return new BadRecord( pRecordNumber, pRecord, "unknown code: "+codename ); } } /** Since the first element of the data record String[] array contains the code, * we need to create a new array that just holds the data, so that the * BeanSpec can deal with a zero based array. */ /* protected String[] adjust( String[] pFieldNames ) { String[] fieldnames = new String[ pFieldNames.length-1 ]; System.arraycopy( pFieldNames, 1, fieldnames, 0, fieldnames.length ); return fieldnames; } */ }