/*******************************************************************************
 * Copyright (c) 2004, 2005 Actuate Corporation.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *  Actuate Corporation  - initial API and implementation
 *******************************************************************************/

package org.eclipse.birt.data.engine.olap.data.util;

import java.io.IOException;

/**
 * A List class providing the service of reading/writing objects from one file
 * when cache is not enough . It makes the reading/writing objects transparent.
 */

public class StructureDiskArray extends BaseDiskArray
{

	private IStructureCreator creator;
	private ObjectWriter[] fieldWriters;
	private ObjectReader[] fieldReaders;

	/**
	 * @throws IOException 
	 * 
	 * 
	 */
	public StructureDiskArray( IStructureCreator creator ) throws IOException
	{
		super( );
		this.creator = creator;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.birt.data.engine.cache.BasicCachedList#writeObject(java.io.DataOutputStream,
	 *      java.lang.Object)
	 */
	protected void writeObject( Object object ) throws IOException
	{
		if ( object == null )
		{
			randomAccessFile.writeShort( NULL_VALUE );
			return;
		}
		IStructure cachedObject = (IStructure) object;
		Object[] objects = cachedObject.getFieldValues( );
		randomAccessFile.writeShort( (short) objects.length );
		if ( fieldWriters == null || fieldWriters.length < objects.length )
		{
			createReadersAndWriters( objects.length );
		}
		for ( int i = 0; i < objects.length; i++ )
		{
			if( i >= fieldWriters.length )
			{
				fieldWriters[fieldWriters.length-1].write( randomAccessFile, objects[i] );
			}
			else
			{
				fieldWriters[i].write( randomAccessFile, objects[i] );
			}
		}
	}

	/**
	 * 
	 * @param size
	 */
	private void createReadersAndWriters( int size )
	{
		fieldWriters = new ObjectWriter[size];
		fieldReaders = new ObjectReader[size];
		for ( int i = 0; i < size; i++ )
		{
			fieldWriters[i] = new ObjectWriter( );
			fieldReaders[i] = new ObjectReader( );
		}
	}
	
	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.birt.data.engine.cache.BasicCachedList#readObject(java.io.DataInputStream)
	 */
	protected Object readObject( ) throws IOException
	{
		short fieldCount = randomAccessFile.readShort( );
		if ( fieldCount == NULL_VALUE )
		{
			return null;
		}
		Object[] objects = new Object[fieldCount];
		for ( int i = 0; i < objects.length; i++ )
		{
			if ( i < fieldReaders.length && fieldReaders[i].getDataType( ) != fieldWriters[i].getDataType( ) )
				fieldReaders[i].setDataType( fieldWriters[i].getDataType( ) );
			if( i >= fieldReaders.length )
			{
				objects[i] = fieldReaders[fieldReaders.length-1].read( randomAccessFile );
			}
			else
			{
				objects[i] = fieldReaders[i].read( randomAccessFile );
			}
		}
		return creator.createInstance( objects );
	}
	
	public void clear( ) throws IOException
	{
		fieldWriters = null;
		fieldReaders = null;
		super.clear();
	}

}
@@ -611,16 +611,48 @@
 ception;
+%0Aimport java.lang.reflect.Array;
 %0A%0A/**%0A *
@@ -2081,24 +2081,83 @@
 t size )%0A%09%7B%0A
+%09%09if ( fieldWriters == null && fieldReaders == null )%0A%09%09%7B%0A%09
 %09%09fieldWrite
@@ -2185,16 +2185,17 @@
 %5Bsize%5D;%0A
+%09
 %09%09fieldR
@@ -2227,16 +2227,17 @@
 %5Bsize%5D;%0A
+%09
 %09%09for ( 
@@ -2261,26 +2261,28 @@
 ze; i++ )%0A%09%09
+%09
 %7B%0A
+%09
 %09%09%09fieldWrit
@@ -2310,24 +2310,25 @@
 iter( );%0A%09%09%09
+%09
 fieldReaders
@@ -2356,17 +2356,919 @@
 r( );%0A%09%09
-%7D
+%09%7D%0A%09%09%7D%0A%09%09else%0A%09%09%7B%0A            int i = fieldWriters.length;%0A            fieldReaders = copyOf( fieldReaders, size );%0A            fieldWriters = copyOf( fieldWriters, size );%0A            for ( ; i %3C fieldReaders.length; i++ )%0A            %7B%0A                    fieldWriters%5Bi%5D = new ObjectWriter( );%0A                    fieldReaders%5Bi%5D = new ObjectReader( );%0A            %7D%0A%09%09%7D%0A%09%7D%09%0A%0A%09public static %3CT, U%3E T%5B%5D copyOf( U%5B%5D original, int newLength )%0A%09%7B%0A%09    T%5B%5D copy = ( (Object) original.getClass( ) == (Object) Object%5B%5D.class )%0A%09                    ? (T%5B%5D) new Object%5BnewLength%5D%0A%09                    : (T%5B%5D) Array.newInstance( original.getClass( )%0A%09                                    .getComponentType( ), newLength );%0A%09    System.arraycopy( original,%0A%09                    0,%0A%09                    copy,%0A%09                    0,%0A%09                    Math.min( original.length, newLength ) );%0A%09    return copy;
 %0A%09%7D%0A%09%0A%09/

Fix StructureDiskArray read NPE issue. [43248]