oMax = new Double( 99.99 );
oMax = new Double( 100 );
	private final Object getMinMax( Axis ax, int iType ) throws ChartException,			IllegalArgumentException	{		final Series[] sea = ax.getRuntimeSeries( );		final int iSeriesCount = sea.length;		Series se;		DataSet ds;		Object oV1, oV2, oMin = null, oMax = null;		PluginSettings ps = PluginSettings.instance( );		IDataSetProcessor iDSP = null;		// ANY STACKED SERIES ASSOCIATED WITH AXIS 'ax'		boolean bAnyStacked = false;		for ( int i = 0; i < iSeriesCount; i++ )		{			if ( sea[i].isStacked( ) )			{				if ( sea[i].canBeStacked( ) )				{					bAnyStacked = true;					continue;				}				else				{					throw new IllegalArgumentException( MessageFormat.format( Messages.getResourceBundle( rtc.getULocale( ) )							.getString( "exception.unstackable.is.stacked" ), //$NON-NLS-1$							new Object[]{								sea[i]							} ) );				}			}			iDSP = ps.getDataSetProcessor( sea[i].getClass( ) );			ds = sea[i].getDataSet( );			oV1 = iDSP.getMinimum( ds );			oV2 = iDSP.getMaximum( ds );			if ( ( iType & NUMERICAL ) == NUMERICAL )			{				if ( oV1 != null ) // SETUP THE MINIMUM VALUE FOR ALL DATASETS				{					if ( oMin == null )					{						oMin = oV1;					}					else					{						final double dV1 = asDouble( oV1 ).doubleValue( );						if ( Math.min( asDouble( oMin ).doubleValue( ), dV1 ) == dV1 )						{							oMin = oV1;						}					}				}				if ( oV2 != null ) // SETUP THE MAXIMUM VALUE FOR ALL DATASETS				{					if ( oMax == null )					{						oMax = oV2;					}					else					{						final double dV2 = asDouble( oV2 ).doubleValue( );						if ( Math.max( asDouble( oMax ).doubleValue( ), dV2 ) == dV2 )						{							oMax = oV2;						}					}				}			}			else if ( ( iType & DATE_TIME ) == DATE_TIME )			{				if ( oV1 != null ) // SETUP THE MINIMUM VALUE FOR ALL DATASETS				{					if ( oMin == null )					{						oMin = oV1;					}					else					{						final CDateTime cdtV1 = asDateTime( oV1 );						final CDateTime cdtMin = asDateTime( oMin );						if ( cdtV1.before( cdtMin ) )						{							oMin = cdtV1;						}					}				}				if ( oV2 != null ) // SETUP THE MAXIMUM VALUE FOR ALL DATASETS				{					if ( oMax == null )					{						oMax = oV2;					}					else					{						final CDateTime cdtV2 = asDateTime( oV2 );						final CDateTime cdtMax = asDateTime( oMax );						if ( cdtV2.after( cdtMax ) )						{							oMax = cdtV2;						}					}				}			}		}		// ONLY NUMERIC VALUES ARE SUPPORTED IN STACKED ELEMENT COMPUTATIONS		if ( bAnyStacked || ax.isPercent( ) )		{			if ( ax.getType( ).getValue( ) == AxisType.DATE_TIME )			{				throw new IllegalArgumentException( MessageFormat.format( Messages.getResourceBundle( rtc.getULocale( ) )						.getString( "exception.stacked.datetime.axis.series" ), //$NON-NLS-1$						new Object[]{							ax						} ) );			}			Object oValue;			int iSeriesPerGroup;			double dGroupMin, dGroupMax, dValue, dAbsTotal, dPercentMax = 0, dPercentMin = 0;			double dAxisMin = Double.MAX_VALUE, dAxisMax = -Double.MAX_VALUE;			ArrayList alSeriesGroupsPerAxis = ssl.getStackGroups( ax );			ArrayList alSeriesPerGroup;			StackGroup sg;			DataSetIterator[] dsi = new DataSetIterator[ssl.getSeriesCount( ax )];			if ( alSeriesGroupsPerAxis == null )			{				throw new ChartException( ChartEnginePlugin.ID,						ChartException.DATA_SET,						"exception.internal.stack.series.setup", //$NON-NLS-1$						new Object[]{							ax						},						Messages.getResourceBundle( rtc.getULocale( ) ) );			}			logger.log( ILogger.INFORMATION,					Messages.getString( "info.processing.stacked.info", //$NON-NLS-1$							new Object[]{								ax							},							rtc.getULocale( ) ) );			int iSeriesIndex, iDataSetCount = ssl.getUnitCount( );			for ( int k = 0; k < iDataSetCount; k++ ) // PER UNIT			{				dAbsTotal = 0;				iSeriesIndex = 0;				for ( int i = 0; i < alSeriesGroupsPerAxis.size( ); i++ )				{					sg = (StackGroup) alSeriesGroupsPerAxis.get( i );					alSeriesPerGroup = sg.getSeries( );					iSeriesPerGroup = alSeriesPerGroup.size( );					if ( iSeriesPerGroup > 0 )					{						se = (Series) alSeriesPerGroup.get( 0 );						ds = se.getDataSet( );						if ( dsi[iSeriesIndex] == null )						{							dsi[iSeriesIndex] = new DataSetIterator( ds );							if ( ( dsi[iSeriesIndex].getDataType( ) & IConstants.NUMERICAL ) != IConstants.NUMERICAL )							{								throw new ChartException( ChartEnginePlugin.ID,										ChartException.DATA_SET,										"exception.percent.stacked.non.numerical", //$NON-NLS-1$ 										Messages.getResourceBundle( rtc.getULocale( ) ) );							}						}						// ALL SERIES MUST HAVE THE SAME DATASET ELEMENT COUNT						iDataSetCount = dsi[iSeriesIndex].size( );						dGroupMin = 0;						dGroupMax = 0;						if ( ax.isPercent( ) )						{							dAbsTotal = 0;						}						for ( int j = 0; j < iSeriesPerGroup; j++ )						{							se = (Series) alSeriesPerGroup.get( j );							if ( j > 0 ) // ALREADY DONE FOR '0'							{								if ( dsi[iSeriesIndex] == null )								{									ds = se.getDataSet( ); // DATA SET									dsi[iSeriesIndex] = new DataSetIterator( ds );									if ( ( dsi[iSeriesIndex].getDataType( ) & IConstants.NUMERICAL ) != IConstants.NUMERICAL )									{										throw new ChartException( ChartEnginePlugin.ID,												ChartException.DATA_SET,												"exception.percent.stacked.non.numerical", //$NON-NLS-1$ 												Messages.getResourceBundle( rtc.getULocale( ) ) );									}								}							}							// EACH ROW OF DATA							oValue = dsi[iSeriesIndex].next( );							if ( oValue != null ) // NULL CHECK							{								// EXTRACT WRAPPED VALUE								dValue = ( (Double) oValue ).doubleValue( );								dAbsTotal += Math.abs( dValue );								if ( dValue > 0 )								{									dGroupMax += dValue; // UPDATE MAX								}								else if ( dValue < 0 )								{									dGroupMin += dValue; // UPDATE MIN								}							}							iSeriesIndex++;						}						final AxisSubUnit au = ssl.getSubUnit( sg, k );						au.setPositiveTotal( dGroupMax );						au.setNegativeTotal( dGroupMin );						// FOR EACH UNIT, UPDATE THE MIN/MAX BASED ON ALL						// STACKED SERIES						dAxisMax = Math.max( dGroupMax, dAxisMax );						dAxisMin = Math.min( dGroupMin, dAxisMin );						if ( ax.isPercent( ) )						{							if ( dAbsTotal != 0d )							{								dPercentMax = Math.max( ( dGroupMax / dAbsTotal ) * 100d,										dPercentMax );								dPercentMin = Math.min( ( dGroupMin / dAbsTotal ) * 100d,										dPercentMin );							}						}					}				}			}			if ( ax.isPercent( ) ) // HANDLE PERCENT			{				if ( dPercentMax >= 100 )					dPercentMax = 99.9;				if ( dPercentMin <= -100 )					dPercentMin = -99.9;				if ( dPercentMax == 0 && dPercentMin == 0 )				{					dPercentMax = 99;				}				dAxisMin = dPercentMin;				dAxisMax = dPercentMax;			}			if ( ( iType & LOGARITHMIC ) == LOGARITHMIC )			{				dAxisMin = 1;			}			oMin = new Double( dAxisMin );			oMax = new Double( dAxisMax );		}		// IF NO DATASET WAS FOUND BECAUSE NO SERIES WERE ATTACHED TO AXES,		// SIMULATE MIN/MAX VALUES		if ( oMin == null && oMax == null )		{			if ( iType == DATE_TIME )			{				oMin = new CDateTime( 1, 1, 2005 );				oMax = new CDateTime( 1, 1, 2006 );			}			else if ( ( iType & NUMERICAL ) == NUMERICAL )			{				if ( ( iType & PERCENT ) == PERCENT )				{					oMin = new Double( 0 );					oMax = new Double( 99.99 );				}				else if ( ( iType & LOGARITHMIC ) == LOGARITHMIC )				{					oMin = new Double( 1 );					oMax = new Double( 999 );				}				else				{					oMin = new Double( -0.9 );					oMax = new Double( 0.9 );				}			}		}		if ( iType == DATE_TIME )		{			try			{				return new Calendar[]{						asDateTime( oMin ), asDateTime( oMax )				};			}			catch ( ClassCastException ex )			{				throw new ChartException( ChartEnginePlugin.ID,						ChartException.DATA_SET,						"exception.numerical.data.datetime.axis", //$NON-NLS-1$ 						Messages.getResourceBundle( rtc.getULocale( ) ) );			}		}		else if ( ( iType & NUMERICAL ) == NUMERICAL )		{			try			{				return new double[]{						asDouble( oMin ).doubleValue( ),						asDouble( oMax ).doubleValue( )				};			}			catch ( ClassCastException ex )			{				throw new ChartException( ChartEnginePlugin.ID,						ChartException.DATA_SET,						"exception.datetime.data.numerical.axis", //$NON-NLS-1$ 						Messages.getResourceBundle( rtc.getULocale( ) ) );			}		}		return null;	}