return new Calendar[] { asDateTime(oMin), asDateTime(oMax) };
    private final Object getMinMax(Axis ax, int iType) throws PluginException, DataSetException,        UnexpectedInputException    {        final Series[] sea = ax.getRuntimeSeries();        final int iSeriesCount = sea.length;        Series se;        DataSet ds;        Object oV1, oV2, oMin = null, oMax = null;        EList elDataElements;        DataElement de;        PluginSettings ps = PluginSettings.instance();        IDataSetProcessor iDSP = null;        Class cDSP = null;        boolean bAnyStacked = false; // ANY STACKED SERIES ASSOCIATED WITH AXIS        // 'ax'        for (int i = 0; i < iSeriesCount; i++)        {            if (sea[i].isStacked())            {                if (sea[i].canBeStacked())                {                    bAnyStacked = true;                    continue;                }                else                {                    throw new UnexpectedInputException("A series " + sea[i]                        + " that may not be stacked is set to stacked");                }            }            iDSP = ps.getDataSetProcessor(sea[i].getClass());            ds = sea[i].getDataSet();            oV1 = iDSP.getMinimum(ds, iType);            oV2 = iDSP.getMaximum(ds, iType);            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 UnexpectedInputException("Cannot define stacked series on a date-time axis " + ax);            }            Object oValue;            ArrayList alI;            int iSeriesPerGroup;            NumberDataElement nde;            double dGroupMin, dGroupMax, dValue, dAbsTotal, dPercentMax = 0, dPercentMin = 0;            double dAxisMin = Double.MAX_VALUE, dAxisMax = Double.MIN_VALUE;            ArrayList alSeriesGroupsPerAxis = ssl.getStackGroups(ax);            ArrayList alSeriesPerGroup;            StackGroup sg;            DataSetIterator[] dsi = new DataSetIterator[ssl.getSeriesCount(ax)];            if (alSeriesGroupsPerAxis == null)            {                throw new DataSetException("Stacked series incorrectly setup for axis " + ax);            }            DefaultLoggerImpl.instance().log(ILogger.INFORMATION, "Processing stacked info for axis " + ax);            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 DataSetException(                                    "Unable to compute a percent/stacked axis containing non-numerical data");                            }                        }                        iDataSetCount = dsi[iSeriesIndex].size(); // ALL SERIES                        // MUST HAVE                        // THE SAME                        // DATASET                        // ELEMENT                        // COUNT                        dGroupMin = 0;                        dGroupMax = 0;                        if (ax.isPercent())                        {                            dAbsTotal = 0;                        }                        for (int j = 0; j < iSeriesPerGroup; j++) // FOR ALL                        // SERIES                        {                            se = (Series) alSeriesPerGroup.get(j); // EACH                            // SERIES                            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 DataSetException(                                            "Unable to compute a percent/stacked axis containing non-numerical data");                                    }                                }                            }                            oValue = dsi[iSeriesIndex].next(); // EACH ROW OF                            // DATA                            if (oValue != null) // NULL CHECK                            {                                dValue = ((Double) oValue).doubleValue(); // EXTRACT                                // WRAPPED                                // VALUE                                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())                        {                            dPercentMax = Math.max((dGroupMax / dAbsTotal) * 100d, dPercentMax);                            dPercentMin = Math.min((dGroupMin / dAbsTotal) * 100d, dPercentMin);                        }                    }                }                //DefaultLoggerImpl.instance().log(ILogger.INFORMATION, "Min                // for unit " + k + " is " + dAxisMin);                //DefaultLoggerImpl.instance().log(ILogger.INFORMATION, "Max                // for unit " + k + " is " + dAxisMax);            }            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        if (oMin == null && oMax == null)        {            if (iType == DATE_TIME)            {                oMin = new CDateTime(1, 1, 2005);                oMax = new CDateTime(1, 1, 2006);                return new Calendar[]                {                    asDateTime(oMin), asDateTime(oMax)                };            }            else if ((iType & NUMERICAL) == NUMERICAL)            {                if ((iType & PERCENT) == PERCENT)                {                    oMin = new Double(0);                    oMax = new Double(99.99);                }                else                {                    oMin = new Double(-1);                    oMax = new Double(1);                }                return new double[]                {                    asDouble(oMin).doubleValue(), asDouble(oMax).doubleValue()                };            }        }        if (iType == DATE_TIME)        {            return new Calendar[]            {                asDateTime(oMin), asDateTime(oMax)            };        }        else if ((iType & NUMERICAL) == NUMERICAL)        {            return new double[]            {                asDouble(oMin).doubleValue(), asDouble(oMax).doubleValue()            };        }        return null;    }