/*************************************************************************
 *
 *  $RCSfile: SchXMLPlotAreaContext.cxx,v $
 *
 *  $Revision: 1.33 $
 *
 *  last change: $Author: obo $ $Date: 2005-07-05 10:55:30 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#include "SchXMLChartContext.hxx"
#include "SchXMLPlotAreaContext.hxx"
#include "SchXMLImport.hxx"

#ifndef _TOOLS_DEBUG_HXX
#include <tools/debug.hxx>
#endif

#ifndef _XMLOFF_XMLNMSPE_HXX
#include "xmlnmspe.hxx"
#endif
#ifndef _XMLOFF_XMLTOKEN_HXX
#include "xmltoken.hxx"
#endif
#ifndef _XMLOFF_XMLTOKEN_HXX
#include "xmltoken.hxx"
#endif
#ifndef _XMLOFF_XMLEMENT_HXX
#include "xmlement.hxx"
#endif
#ifndef _XMLOFF_NMSPMAP_HXX
#include "nmspmap.hxx"
#endif
#ifndef _XMLOFF_XMLUCONV_HXX
#include "xmluconv.hxx"
#endif
#ifndef _XMLOFF_PRSTYLEI_HXX_
#include "prstylei.hxx"
#endif
#ifndef _XMLOFF_XMLSTYLE_HXX
#include "xmlstyle.hxx"
#endif
#ifndef _XEXPTRANSFORM_HXX
#include "xexptran.hxx"
#endif

#ifndef _COM_SUN_STAR_XML_SAX_XATTRIBUTELIST_HPP_
#include <com/sun/star/xml/sax/XAttributeList.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XSERVICEINFO_HPP_
#include <com/sun/star/lang/XServiceInfo.hpp>
#endif
#ifndef _COM_SUN_STAR_CHART_XTWOAXISXSUPPLIER_HPP_
#include <com/sun/star/chart/XTwoAxisXSupplier.hpp>
#endif
#ifndef _COM_SUN_STAR_CHART_XTWOAXISYSUPPLIER_HPP_
#include <com/sun/star/chart/XTwoAxisYSupplier.hpp>
#endif
#ifndef _COM_SUN_STAR_CHART_XAXISZSUPPLIER_HPP_
#include <com/sun/star/chart/XAxisZSupplier.hpp>
#endif
#ifndef _COM_SUN_STAR_UTIL_XSTRINGMAPPING_HPP_
#include <com/sun/star/util/XStringMapping.hpp>
#endif
#ifndef _COM_SUN_STAR_CHART_CHARTDATAROWSOURCE_HPP_
#include <com/sun/star/chart/ChartDataRowSource.hpp>
#endif
#ifndef _COM_SUN_STAR_CHART_CHARTAXISASSIGN_HPP_
#include <com/sun/star/chart/ChartAxisAssign.hpp>
#endif
#ifndef _COM_SUN_STAR_CHART_X3DDISPLAY_HPP_
#include <com/sun/star/chart/X3DDisplay.hpp>
#endif
#ifndef _COM_SUN_STAR_CHART_XSTATISTICDISPLAY_HPP_
#include <com/sun/star/chart/XStatisticDisplay.hpp>
#endif

#ifndef _COM_SUN_STAR_AWT_POINT_HPP_
#include <com/sun/star/awt/Point.hpp>
#endif
#ifndef _COM_SUN_STAR_AWT_SIZE_HPP_
#include <com/sun/star/awt/Size.hpp>
#endif

using namespace com::sun::star;
using namespace ::xmloff::token;

using ::rtl::OUString;

static __FAR_DATA SvXMLEnumMapEntry aXMLAxisClassMap[] =
{
    { XML_X,  SCH_XML_AXIS_X  },
    { XML_Y,  SCH_XML_AXIS_Y  },
    { XML_Z,  SCH_XML_AXIS_Z  },
    { XML_TOKEN_INVALID, 0 }
};

// ========================================

SchXML3DSceneAttributesHelper::SchXML3DSceneAttributesHelper(
    SvXMLImport& rImporter ) :
        SdXML3DSceneAttributesHelper( rImporter ),
        m_bIsDirty( false )
{
    mnDistance =    4110; // default in base class: 1000
    mnFocalLength = 800;  // default in base class: 1000
}

bool SchXML3DSceneAttributesHelper::IsDirty()
{
    return m_bIsDirty;
}

void SchXML3DSceneAttributesHelper::SetDirty()
{
    m_bIsDirty = true;
}

void SchXML3DSceneAttributesHelper::SetDistance( sal_Int32 nDistance )
{
    mnDistance = nDistance;
}

// ========================================

SchXMLPlotAreaContext::SchXMLPlotAreaContext( SchXMLImportHelper& rImpHelper,
                                              SvXMLImport& rImport, const rtl::OUString& rLocalName,
                                              uno::Sequence< chart::ChartSeriesAddress >& rSeriesAddresses,
                                              ::rtl::OUString& rCategoriesAddress,
                                              ::rtl::OUString& rChartAddress,
                                              ::rtl::OUString& rTableNumberList) :
        SvXMLImportContext( rImport, XML_NAMESPACE_CHART, rLocalName ),
        mrImportHelper( rImpHelper ),
        mrSeriesAddresses( rSeriesAddresses ),
        mrCategoriesAddress( rCategoriesAddress ),
        mrChartAddress( rChartAddress ),
        mrTableNumberList( rTableNumberList ),
        mnDomainOffset( 0 ),
        mnNumOfLines( 0 ),
        mbStockHasVolume( sal_False ),
        mnSeries( 0 ),
        mnMaxSeriesLength( 0 ),
        maSceneImportHelper( rImport ),
        mbSetDiagramSize( false ),
        mbSetDiagramPosition( false )
{
    // get Diagram
    uno::Reference< chart::XChartDocument > xDoc( rImpHelper.GetChartDocument(), uno::UNO_QUERY );
    if( xDoc.is())
    {
        mxDiagram = xDoc->getDiagram();
        // other default for distance for pie charts
        if( mxDiagram.is() &&
            mxDiagram->getDiagramType().equalsAscii("com.sun.star.chart.PieDiagram"))
            maSceneImportHelper.SetDistance( 5000 );
    }
    DBG_ASSERT( mxDiagram.is(), "Couldn't get XDiagram" );

    // turn off all axes initially
    uno::Any aFalseBool;
    aFalseBool <<= (sal_Bool)(sal_False);

    uno::Reference< lang::XServiceInfo > xInfo( mxDiagram, uno::UNO_QUERY );
    uno::Reference< beans::XPropertySet > xProp( mxDiagram, uno::UNO_QUERY );
    if( xInfo.is() &&
        xProp.is())
    {
        try
        {
            if( xInfo->supportsService( rtl::OUString::createFromAscii( "com.sun.star.chart.ChartAxisXSupplier" )))
            {
                xProp->setPropertyValue(
                    rtl::OUString::createFromAscii( "HasXAxis" ), aFalseBool );
                xProp->setPropertyValue(
                    rtl::OUString::createFromAscii( "HasXAxisGrid" ), aFalseBool );
                xProp->setPropertyValue(
                    rtl::OUString::createFromAscii( "HasXAxisDescription" ), aFalseBool );
            }
            if( xInfo->supportsService( rtl::OUString::createFromAscii( "com.sun.star.chart.ChartTwoAxisXSupplier" )))
            {
                xProp->setPropertyValue(
                    rtl::OUString::createFromAscii( "HasSecondaryXAxis" ), aFalseBool );
                xProp->setPropertyValue(
                    rtl::OUString::createFromAscii( "HasSecondaryXAxisDescription" ), aFalseBool );
            }

            if( xInfo->supportsService( rtl::OUString::createFromAscii( "com.sun.star.chart.ChartAxisYSupplier" )))
            {
                xProp->setPropertyValue(
                    rtl::OUString::createFromAscii( "HasYAxis" ), aFalseBool );
                xProp->setPropertyValue(
                    rtl::OUString::createFromAscii( "HasYAxisGrid" ), aFalseBool );
                xProp->setPropertyValue(
                    rtl::OUString::createFromAscii( "HasYAxisDescription" ), aFalseBool );
            }
            if( xInfo->supportsService( rtl::OUString::createFromAscii( "com.sun.star.chart.ChartTwoAxisYSupplier" )))
            {
                xProp->setPropertyValue(
                    rtl::OUString::createFromAscii( "HasSecondaryYAxis" ), aFalseBool );
                xProp->setPropertyValue(
                    rtl::OUString::createFromAscii( "HasSecondaryYAxisDescription" ), aFalseBool );
            }

            if( xInfo->supportsService( rtl::OUString::createFromAscii( "com.sun.star.chart.ChartAxisZSupplier" )))
            {
                xProp->setPropertyValue(
                    rtl::OUString::createFromAscii( "HasZAxis" ), aFalseBool );
                xProp->setPropertyValue(
                    rtl::OUString::createFromAscii( "HasZAxisDescription" ), aFalseBool );
            }
            uno::Any aAny;
            chart::ChartDataRowSource eSource = chart::ChartDataRowSource_COLUMNS;
            aAny <<= eSource;
            xProp->setPropertyValue( rtl::OUString::createFromAscii( "DataRowSource" ), aAny );
        }
        catch( beans::UnknownPropertyException )
        {
            DBG_ERROR( "Property required by service not supported" );
        }
    }
}

SchXMLPlotAreaContext::~SchXMLPlotAreaContext()
{}

SvXMLImportContext* SchXMLPlotAreaContext::CreateChildContext(
    USHORT nPrefix,
    const rtl::OUString& rLocalName,
    const uno::Reference< xml::sax::XAttributeList >& xAttrList )
{
    SvXMLImportContext* pContext = 0;
    const SvXMLTokenMap& rTokenMap = mrImportHelper.GetPlotAreaElemTokenMap();

    switch( rTokenMap.Get( nPrefix, rLocalName ))
    {
        case XML_TOK_PA_AXIS:
            pContext = new SchXMLAxisContext( mrImportHelper, GetImport(), rLocalName,
                                              mxDiagram, maAxes, mrCategoriesAddress );
            break;

        case XML_TOK_PA_SERIES:
            {
                mrSeriesAddresses.realloc( mnSeries + 1 );
                pContext = new SchXMLSeriesContext( mrImportHelper, GetImport(), rLocalName,
                                                    mxDiagram, maAxes, mrSeriesAddresses[ mnSeries ],
                                                    maSeriesStyleList,
                                                    mnSeries, mnMaxSeriesLength, mnDomainOffset,
                                                    mnNumOfLines, mbStockHasVolume );
                mnSeries++;
            }
            break;

        case XML_TOK_PA_WALL:
            pContext = new SchXMLWallFloorContext( mrImportHelper, GetImport(), nPrefix, rLocalName, mxDiagram,
                                                   SchXMLWallFloorContext::CONTEXT_TYPE_WALL );
            break;
        case XML_TOK_PA_FLOOR:
            pContext = new SchXMLWallFloorContext( mrImportHelper, GetImport(), nPrefix, rLocalName, mxDiagram,
                                                   SchXMLWallFloorContext::CONTEXT_TYPE_FLOOR );
            break;

        case XML_TOK_PA_LIGHT_SOURCE:
            pContext = maSceneImportHelper.create3DLightContext( nPrefix, rLocalName, xAttrList );
            maSceneImportHelper.SetDirty();
            break;

        // elements for stock charts
        case XML_TOK_PA_STOCK_GAIN:
            pContext = new SchXMLStockContext( mrImportHelper, GetImport(), nPrefix, rLocalName, mxDiagram,
                                               SchXMLStockContext::CONTEXT_TYPE_GAIN );
            break;
        case XML_TOK_PA_STOCK_LOSS:
            pContext = new SchXMLStockContext( mrImportHelper, GetImport(), nPrefix, rLocalName, mxDiagram,
                                               SchXMLStockContext::CONTEXT_TYPE_LOSS );
            break;
        case XML_TOK_PA_STOCK_RANGE:
            pContext = new SchXMLStockContext( mrImportHelper, GetImport(), nPrefix, rLocalName, mxDiagram,
                                               SchXMLStockContext::CONTEXT_TYPE_RANGE );
            break;

        default:
            pContext = new SvXMLImportContext( GetImport(), nPrefix, rLocalName );
    }

    return pContext;
}

void SchXMLPlotAreaContext::StartElement( const uno::Reference< xml::sax::XAttributeList >& xAttrList )
{
    uno::Any aTransMatrixAny;

    // initialize size and position
    uno::Reference< drawing::XShape > xDiaShape( mxDiagram, uno::UNO_QUERY );
    if( xDiaShape.is())
    {
        maSize = xDiaShape->getSize();
        maPosition = xDiaShape->getPosition();
    }

    // parse attributes
    sal_Int16 nAttrCount = xAttrList.is()? xAttrList->getLength(): 0;
    rtl::OUString aValue;
    const SvXMLTokenMap& rAttrTokenMap = mrImportHelper.GetPlotAreaAttrTokenMap();

    sal_Bool bColHasLabels = sal_False;
    sal_Bool bRowHasLabels = sal_False;

    for( sal_Int16 i = 0; i < nAttrCount; i++ )
    {
        rtl::OUString sAttrName = xAttrList->getNameByIndex( i );
        rtl::OUString aLocalName;
        rtl::OUString aValue = xAttrList->getValueByIndex( i );
        USHORT nPrefix = GetImport().GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName );

        switch( rAttrTokenMap.Get( nPrefix, aLocalName ))
        {
            case XML_TOK_PA_X:
                GetImport().GetMM100UnitConverter().convertMeasure( maPosition.X, aValue );
                mbSetDiagramPosition = true;
                break;
            case XML_TOK_PA_Y:
                GetImport().GetMM100UnitConverter().convertMeasure( maPosition.Y, aValue );
                mbSetDiagramPosition = true;
                break;
            case XML_TOK_PA_WIDTH:
                GetImport().GetMM100UnitConverter().convertMeasure( maSize.Width, aValue );
                mbSetDiagramSize = true;
                break;
            case XML_TOK_PA_HEIGHT:
                GetImport().GetMM100UnitConverter().convertMeasure( maSize.Height, aValue );
                mbSetDiagramSize = true;
                break;
            case XML_TOK_PA_STYLE_NAME:
                msAutoStyleName = aValue;
                break;
            case XML_TOK_PA_CHART_ADDRESS:
                mrChartAddress = aValue;
                break;
            case XML_TOK_PA_TABLE_NUMBER_LIST:
                mrTableNumberList = aValue;
                break;
            case XML_TOK_PA_DS_HAS_LABELS:
                {
                    if( aValue.equals( ::xmloff::token::GetXMLToken( ::xmloff::token::XML_BOTH )))
                        bColHasLabels = bRowHasLabels = sal_True;
                    else if( aValue.equals( ::xmloff::token::GetXMLToken( ::xmloff::token::XML_ROW )))
                        bRowHasLabels = sal_True;
                    else if( aValue.equals( ::xmloff::token::GetXMLToken( ::xmloff::token::XML_COLUMN )))
                        bColHasLabels = sal_True;
                }
                break;
            case XML_TOK_PA_TRANSFORM:
            case XML_TOK_PA_VRP:
            case XML_TOK_PA_VPN:
            case XML_TOK_PA_VUP:
            case XML_TOK_PA_PROJECTION:
            case XML_TOK_PA_DISTANCE:
            case XML_TOK_PA_FOCAL_LENGTH:
            case XML_TOK_PA_SHADOW_SLANT:
            case XML_TOK_PA_SHADE_MODE:
            case XML_TOK_PA_AMBIENT_COLOR:
            case XML_TOK_PA_LIGHTING_MODE:
                maSceneImportHelper.processSceneAttribute( nPrefix, aLocalName, aValue );
                maSceneImportHelper.SetDirty();
                break;
        }
    }

    uno::Reference< beans::XPropertySet > xDocProp( mrImportHelper.GetChartDocument(), uno::UNO_QUERY );
    if( xDocProp.is())
    {
        try
        {
            uno::Any aAny;
            aAny <<= (sal_Bool)(bColHasLabels);
            xDocProp->setPropertyValue(
                ::rtl::OUString::createFromAscii( "DataSourceLabelsInFirstColumn" ),
                aAny );

            aAny <<= (sal_Bool)(bRowHasLabels);
            xDocProp->setPropertyValue(
                ::rtl::OUString::createFromAscii( "DataSourceLabelsInFirstRow" ),
                aAny );
        }
        catch( beans::UnknownPropertyException )
        {
            DBG_ERRORFILE( "Properties missing" );
        }
    }

    // set properties
    uno::Reference< beans::XPropertySet > xProp( mxDiagram, uno::UNO_QUERY );
    if( msAutoStyleName.getLength())
    {
        if( xProp.is())
        {
            const SvXMLStylesContext* pStylesCtxt = mrImportHelper.GetAutoStylesContext();
            if( pStylesCtxt )
            {
                const SvXMLStyleContext* pStyle = pStylesCtxt->FindStyleChildContext(
                    mrImportHelper.GetChartFamilyID(), msAutoStyleName );

                if( pStyle && pStyle->ISA( XMLPropStyleContext ))
                    (( XMLPropStyleContext* )pStyle )->FillPropertySet( xProp );
            }

            // perform BuildChart to make scene etc. available
            uno::Reference< chart::XChartDocument > xDoc( mrImportHelper.GetChartDocument(), uno::UNO_QUERY );
            if( xDoc.is() &&
                xDoc->hasControllersLocked())
            {
                xDoc->unlockControllers();
                xDoc->lockControllers();
            }
        }
    }
}

void SchXMLPlotAreaContext::EndElement()
{
    sal_Int32 i;

    uno::Reference< beans::XPropertySet > xProp( mxDiagram, uno::UNO_QUERY );
    if( xProp.is())
    {
        sal_Bool bIsThreeDim = sal_False;
        uno::Any aAny = xProp->getPropertyValue( ::rtl::OUString::createFromAscii( "Dim3D" ));
        aAny >>= bIsThreeDim;

        // set 3d scene attributes
        if( bIsThreeDim && maSceneImportHelper.IsDirty() )
        {
            // set scene attributes at diagram
            maSceneImportHelper.setSceneAttributes( xProp );
        }

        // #i32368# number of lines is determined by class-attribute of series
        if( mnNumOfLines > 0 &&
            0 == mxDiagram->getDiagramType().reverseCompareToAsciiL(
                RTL_CONSTASCII_STRINGPARAM( "com.sun.star.chart.BarDiagram" )))
        {
            try
            {
                xProp->setPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "NumberOfLines" )),
                                         uno::makeAny( mnNumOfLines ));
            }
            catch( uno::Exception & aEx )
            {
                String aStr( aEx.Message );
                ByteString aBStr( aStr, RTL_TEXTENCODING_ASCII_US );
                DBG_ERROR1( "Exception caught for property NumberOfLines: %s", aBStr.GetBuffer());
            }
        }

        // #i32366# stock has volume
        if( 0 == mxDiagram->getDiagramType().reverseCompareToAsciiL(
                RTL_CONSTASCII_STRINGPARAM( "com.sun.star.chart.StockDiagram" )))
        {
            try
            {
                xProp->setPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Volume" )),
                                         uno::makeAny( mbStockHasVolume ));
            }
            catch( uno::Exception & aEx )
            {
                String aStr( aEx.Message );
                ByteString aBStr( aStr, RTL_TEXTENCODING_ASCII_US );
                DBG_ERROR1( "Exception caught for property NumberOfLines: %s", aBStr.GetBuffer());
            }
        }
    }

    // set changed size and position after properties (esp. 3d)
    uno::Reference< drawing::XShape > xDiaShape( mxDiagram, uno::UNO_QUERY );
    if( xDiaShape.is())
    {
        if( mbSetDiagramSize )
            xDiaShape->setSize( maSize );
        if( mbSetDiagramPosition )
            xDiaShape->setPosition( maPosition );
    }

    // resize data so that all series and data point properties can be set
    mrImportHelper.ResizeChartData( mnSeries + mnDomainOffset, mnMaxSeriesLength );

    // set autostyles for series and data points
    const SvXMLStylesContext* pStylesCtxt = mrImportHelper.GetAutoStylesContext();
    const SvXMLStyleContext* pStyle = NULL;
    ::rtl::OUString sCurrStyleName;

    if( pStylesCtxt )
    {
        ::std::list< ::chartxml::DataRowPointStyle >::iterator iStyle;
        // iterate over series attributes first ...
        for( iStyle = maSeriesStyleList.begin(); iStyle != maSeriesStyleList.end(); iStyle++ )
        {
            if( iStyle->meType != ::chartxml::DataRowPointStyle::DATA_POINT )
            {
                // data row style
                for( i = 0; i < iStyle->mnRepeat; i++ )
                {
                    try
                    {
                        xProp = mxDiagram->getDataRowProperties( iStyle->mnSeries + i );

                        if( iStyle->meType != ::chartxml::DataRowPointStyle::DATA_SERIES &&
                            xProp.is() )
                        {
                            // we have a statistical proertyset
                            uno::Any aAny;
                            switch( iStyle->meType )
                            {
                                case ::chartxml::DataRowPointStyle::MEAN_VALUE:
                                    aAny = xProp->getPropertyValue(
                                        OUString( RTL_CONSTASCII_USTRINGPARAM(
                                                      "DataMeanValueProperties" )));
                                    break;
                                case ::chartxml::DataRowPointStyle::REGRESSION:
                                    aAny = xProp->getPropertyValue(
                                        OUString( RTL_CONSTASCII_USTRINGPARAM(
                                                      "DataRegressionProperties" )));
                                    break;
                                case ::chartxml::DataRowPointStyle::ERROR_INDICATOR:
                                    aAny = xProp->getPropertyValue(
                                        OUString( RTL_CONSTASCII_USTRINGPARAM(
                                                      "DataErrorProperties" )));
                                    break;
                            }
                            aAny >>= xProp;
                        }

                        if( xProp.is())
                        {
                            if( (iStyle->msStyleName).getLength())
                            {
                                if( ! sCurrStyleName.equals( iStyle->msStyleName ))
                                {
                                    sCurrStyleName = iStyle->msStyleName;
                                    pStyle = pStylesCtxt->FindStyleChildContext(
                                        mrImportHelper.GetChartFamilyID(), sCurrStyleName );
                                }

                                if( pStyle && pStyle->ISA( XMLPropStyleContext ))
                                    (( XMLPropStyleContext* )pStyle )->FillPropertySet( xProp );
                            }

                            if( iStyle->meType == ::chartxml::DataRowPointStyle::DATA_SERIES &&
                                iStyle->mnAttachedAxis != 1 )
                            {
                                uno::Any aAny;
                                aAny <<= chart::ChartAxisAssign::SECONDARY_Y;

                                xProp->setPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Axis" )), aAny );
                            }
                        }
                    }
                    catch( uno::Exception aEx )
                    {
#ifdef DBG_UTIL
                        String aStr( aEx.Message );
                        ByteString aBStr( aStr, RTL_TEXTENCODING_ASCII_US );
                        DBG_ERROR1( "PlotAreaContext:EndElement(): Exception caught: %s", aBStr.GetBuffer());
#endif
                    }
                }
            }
        }

        // ... then iterate over data-point attributes, so the latter are not overwritten
        for( iStyle = maSeriesStyleList.begin(); iStyle != maSeriesStyleList.end(); iStyle++ )
        {
            if( iStyle->mnIndex != -1 )
            {
                // data point style
                for( i = 0; i < iStyle->mnRepeat; i++ )
                {
                    try
                    {
                        xProp = mxDiagram->getDataPointProperties( iStyle->mnIndex + i, iStyle->mnSeries );

                        if( xProp.is())
                        {
                            if( ! sCurrStyleName.equals( iStyle->msStyleName ))
                            {
                                sCurrStyleName = iStyle->msStyleName;
                                pStyle = pStylesCtxt->FindStyleChildContext(
                                    mrImportHelper.GetChartFamilyID(), sCurrStyleName );
                            }

                            if( pStyle && pStyle->ISA( XMLPropStyleContext ))
                                (( XMLPropStyleContext* )pStyle )->FillPropertySet( xProp );
                        }
                    }
                    catch( uno::Exception aEx )
                    {
#ifdef DBG_UTIL
                        String aStr( aEx.Message );
                        ByteString aBStr( aStr, RTL_TEXTENCODING_ASCII_US );
                        DBG_ERROR1( "PlotAreaContext:EndElement(): Exception caught: %s", aBStr.GetBuffer());
#endif
                    }
                }
            }
        }   // styles iterator
    }
}

// ========================================

SchXMLAxisContext::SchXMLAxisContext( SchXMLImportHelper& rImpHelper,
                                      SvXMLImport& rImport, const rtl::OUString& rLocalName,
                                      uno::Reference< chart::XDiagram > xDiagram,
                                      std::vector< SchXMLAxis >& aAxes,
                                      ::rtl::OUString & rCategoriesAddress ) :
        SvXMLImportContext( rImport, XML_NAMESPACE_CHART, rLocalName ),
        mrImportHelper( rImpHelper ),
        mxDiagram( xDiagram ),
        maAxes( aAxes ),
        mrCategoriesAddress( rCategoriesAddress )
{
}

SchXMLAxisContext::~SchXMLAxisContext()
{}

/* returns a shape for the current axis's title. The property
   "Has...AxisTitle" is set to "True" to get the shape
 */
uno::Reference< drawing::XShape > SchXMLAxisContext::getTitleShape()
{
    uno::Reference< drawing::XShape > xResult;
    uno::Any aTrueBool;
    aTrueBool <<= (sal_Bool)(sal_True);
    uno::Reference< beans::XPropertySet > xDiaProp( mxDiagram, uno::UNO_QUERY );

    uno::Reference< chart::XChartDocument > xDoc( mrImportHelper.GetChartDocument(), uno::UNO_QUERY );
    sal_Bool bHasControllersLocked = sal_False;
    if( xDoc.is() &&
        (bHasControllersLocked = xDoc->hasControllersLocked()) == sal_True )
        xDoc->unlockControllers();

    switch( maCurrentAxis.eClass )
    {
        case SCH_XML_AXIS_X:
            if( maCurrentAxis.nIndexInCategory == 0 )
            {
                uno::Reference< chart::XAxisXSupplier > xSuppl( mxDiagram, uno::UNO_QUERY );
                if( xSuppl.is())
                {
                    if( xDiaProp.is())
                        xDiaProp->setPropertyValue( rtl::OUString::createFromAscii( "HasXAxisTitle" ), aTrueBool );
                    xResult = uno::Reference< drawing::XShape >( xSuppl->getXAxisTitle(), uno::UNO_QUERY );
                }
            }
            break;
        case SCH_XML_AXIS_Y:
            if( maCurrentAxis.nIndexInCategory == 0 )
            {
                uno::Reference< chart::XAxisYSupplier > xSuppl( mxDiagram, uno::UNO_QUERY );
                if( xSuppl.is())
                {
                    if( xDiaProp.is())
                        xDiaProp->setPropertyValue( rtl::OUString::createFromAscii( "HasYAxisTitle" ), aTrueBool );
                    xResult = uno::Reference< drawing::XShape >( xSuppl->getYAxisTitle(), uno::UNO_QUERY );
                }
            }
            break;
        case SCH_XML_AXIS_Z:
            uno::Reference< chart::XAxisZSupplier > xSuppl( mxDiagram, uno::UNO_QUERY );
            if( xSuppl.is())
            {
                if( xDiaProp.is())
                    xDiaProp->setPropertyValue( rtl::OUString::createFromAscii( "HasZAxisTitle" ), aTrueBool );
                xResult = uno::Reference< drawing::XShape >( xSuppl->getZAxisTitle(), uno::UNO_QUERY );
            }
            break;
    }

    if( bHasControllersLocked && xDoc.is())
        xDoc->lockControllers();

    return xResult;
}

void SchXMLAxisContext::CreateGrid( ::rtl::OUString sAutoStyleName,
                                    sal_Bool bIsMajor )
{
    uno::Reference< chart::XDiagram > xDia = mrImportHelper.GetChartDocument()->getDiagram();
    uno::Reference< beans::XPropertySet > xGridProp;
    ::rtl::OUString sPropertyName;
    DBG_ASSERT( xDia.is(), "diagram object is invalid!" );

    switch( maCurrentAxis.eClass )
    {
        case SCH_XML_AXIS_X:
            {
                uno::Reference< chart::XAxisXSupplier > xSuppl( xDia, uno::UNO_QUERY );
                if( xSuppl.is())
                {
                    if( bIsMajor )
                    {
                        xGridProp = xSuppl->getXMainGrid();
                        sPropertyName = ::rtl::OUString::createFromAscii( "HasXAxisGrid" );
                    }
                    else
                    {
                        xGridProp = xSuppl->getXHelpGrid();
                        sPropertyName = ::rtl::OUString::createFromAscii( "HasXAxisHelpGrid" );
                    }
                }
            }
            break;
        case SCH_XML_AXIS_Y:
            {
                uno::Reference< chart::XAxisYSupplier > xSuppl( xDia, uno::UNO_QUERY );
                if( xSuppl.is())
                {
                    if( bIsMajor )
                    {
                        xGridProp = xSuppl->getYMainGrid();
                        sPropertyName = ::rtl::OUString::createFromAscii( "HasYAxisGrid" );
                    }
                    else
                    {
                        xGridProp = xSuppl->getYHelpGrid();
                        sPropertyName = ::rtl::OUString::createFromAscii( "HasYAxisHelpGrid" );
                    }
                }
            }
            break;
        case SCH_XML_AXIS_Z:
            {
                uno::Reference< chart::XAxisZSupplier > xSuppl( xDia, uno::UNO_QUERY );
                if( xSuppl.is())
                {
                    if( bIsMajor )
                    {
                        xGridProp = xSuppl->getZMainGrid();
                        sPropertyName = ::rtl::OUString::createFromAscii( "HasZAxisGrid" );
                    }
                    else
                    {
                        xGridProp = xSuppl->getZHelpGrid();
                        sPropertyName = ::rtl::OUString::createFromAscii( "HasZAxisHelpGrid" );
                    }
                }
            }
            break;
    }

    // enable grid
    if( sPropertyName.getLength())
    {
        uno::Reference< beans::XPropertySet > xDiaProp( xDia, uno::UNO_QUERY );
        uno::Any aTrueBool;
        aTrueBool <<= (sal_Bool)(sal_True);
        if( xDiaProp.is())
        {
            try
            {
                xDiaProp->setPropertyValue( sPropertyName, aTrueBool );
            }
            catch( beans::UnknownPropertyException )
            {
                DBG_ERROR( "Cannot enable grid due to missing property" );
            }
        }
    }

    // set properties
    if( sAutoStyleName.getLength() &&
        xGridProp.is())
    {
        const SvXMLStylesContext* pStylesCtxt = mrImportHelper.GetAutoStylesContext();
        if( pStylesCtxt )
        {
            const SvXMLStyleContext* pStyle = pStylesCtxt->FindStyleChildContext(
                mrImportHelper.GetChartFamilyID(), sAutoStyleName );

            if( pStyle && pStyle->ISA( XMLPropStyleContext ))
                (( XMLPropStyleContext* )pStyle )->FillPropertySet( xGridProp );
        }
    }
}

void SchXMLAxisContext::StartElement( const uno::Reference< xml::sax::XAttributeList >& xAttrList )
{
    // parse attributes
    sal_Int16 nAttrCount = xAttrList.is()? xAttrList->getLength(): 0;
    rtl::OUString aValue;
    SchXMLImport& rImport = ( SchXMLImport& )GetImport();
    const SvXMLTokenMap& rAttrTokenMap = mrImportHelper.GetAxisAttrTokenMap();

    for( sal_Int16 i = 0; i < nAttrCount; i++ )
    {
        rtl::OUString sAttrName = xAttrList->getNameByIndex( i );
        rtl::OUString aLocalName;
        rtl::OUString aValue = xAttrList->getValueByIndex( i );
        USHORT nPrefix = GetImport().GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName );

        switch( rAttrTokenMap.Get( nPrefix, aLocalName ))
        {
            case XML_TOK_AXIS_DIMENSION:
                {
                    USHORT nEnumVal;
                    if( rImport.GetMM100UnitConverter().convertEnum( nEnumVal, aValue, aXMLAxisClassMap ))
                        maCurrentAxis.eClass = ( SchXMLAxisClass )nEnumVal;
                }
                break;
            case XML_TOK_AXIS_NAME:
                maCurrentAxis.aName = aValue;
                break;
            case XML_TOK_AXIS_STYLE_NAME:
                msAutoStyleName = aValue;
                break;
        }
    }

    // check for number of axes with same category
    maCurrentAxis.nIndexInCategory = 0;
    sal_Int32 nNumOfAxes = maAxes.size();
    for( sal_Int32 nCurrent = 0; nCurrent < nNumOfAxes; nCurrent++ )
    {
        if( maAxes[ nCurrent ].eClass == maCurrentAxis.eClass )
            maCurrentAxis.nIndexInCategory++;
    }
}

void SchXMLAxisContext::EndElement()
{
    // add new Axis to list
    maAxes.push_back( maCurrentAxis );

    // set axis at chart
    uno::Reference< beans::XPropertySet > xDiaProp( mxDiagram, uno::UNO_QUERY );
    uno::Reference< beans::XPropertySet > xProp;
    uno::Any aTrueBool;
    aTrueBool <<= (sal_Bool)(sal_True);
    sal_Bool bHasTitle = ( maCurrentAxis.aTitle.getLength() > 0 );
    uno::Reference< frame::XModel > xDoc( mrImportHelper.GetChartDocument(), uno::UNO_QUERY );

    switch( maCurrentAxis.eClass )
    {
        case SCH_XML_AXIS_X:
            if( maCurrentAxis.nIndexInCategory == 0 )
            {
                try
                {
                    xDiaProp->setPropertyValue(
                        rtl::OUString::createFromAscii( "HasXAxis" ), aTrueBool );
                }
                catch( beans::UnknownPropertyException )
                {
                    DBG_ERROR( "Couldn't turn on x axis" );
                }
                uno::Reference< chart::XAxisXSupplier > xSuppl( mxDiagram, uno::UNO_QUERY );
                if( xSuppl.is())
                {
                    xProp = xSuppl->getXAxis();
                    if( bHasTitle )
                    {
                        uno::Reference< beans::XPropertySet > xTitleProp( xSuppl->getXAxisTitle(), uno::UNO_QUERY );
                        if( xTitleProp.is())
                        {
                            try
                            {
                                uno::Any aAny;
                                aAny <<= maCurrentAxis.aTitle;
                                xTitleProp->setPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "String" )), aAny );
                            }
                            catch( beans::UnknownPropertyException )
                            {
                                DBG_ERROR( "Property String for Title not available" );
                            }
                            uno::Reference< drawing::XShape > xShape( xTitleProp, uno::UNO_QUERY );
                            if( xShape.is())
                            {
                                // perform build chart with new title string
                                // so that setting the position works correctly
                                if( xDoc.is())
                                {
                                    xDoc->unlockControllers();
                                    xDoc->lockControllers();
                                }
                                if( maCurrentAxis.bTitleHasMoved )
                                    xShape->setPosition( maCurrentAxis.aPosition );
                            }
                        }
                    }
                }
            }
            else
            {
                try
                {
                    xDiaProp->setPropertyValue(
                        rtl::OUString::createFromAscii( "HasSecondaryXAxis" ), aTrueBool );
                }
                catch( beans::UnknownPropertyException )
                {
                    DBG_ERROR( "Couldn't turn on second x axis" );
                }
                uno::Reference< chart::XTwoAxisXSupplier > xSuppl( mxDiagram, uno::UNO_QUERY );
                if( xSuppl.is())
                    xProp = xSuppl->getSecondaryXAxis();
            }
            break;

        case SCH_XML_AXIS_Y:
            if( maCurrentAxis.nIndexInCategory == 0 )
            {
                try
                {
                    xDiaProp->setPropertyValue(
                        rtl::OUString::createFromAscii( "HasYAxis" ), aTrueBool );
                }
                catch( beans::UnknownPropertyException )
                {
                    DBG_ERROR( "Couldn't turn on y axis" );
                }
                uno::Reference< chart::XAxisYSupplier > xSuppl( mxDiagram, uno::UNO_QUERY );
                if( xSuppl.is())
                {
                    xProp = xSuppl->getYAxis();
                    if( bHasTitle )
                    {
                        uno::Reference< beans::XPropertySet > xTitleProp( xSuppl->getYAxisTitle(), uno::UNO_QUERY );
                        if( xTitleProp.is())
                        {
                            try
                            {
                                uno::Any aAny;
                                aAny <<= maCurrentAxis.aTitle;
                                xTitleProp->setPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "String" )), aAny );
                            }
                            catch( beans::UnknownPropertyException )
                            {
                                DBG_ERROR( "Property String for Title not available" );
                            }
                            uno::Reference< drawing::XShape > xShape( xTitleProp, uno::UNO_QUERY );
                            if( xShape.is())
                            {
                                // perform build chart with new title string
                                // so that setting the position works correctly
                                if( xDoc.is())
                                {
                                    xDoc->unlockControllers();
                                    xDoc->lockControllers();
                                }
                                if( maCurrentAxis.bTitleHasMoved )
                                    xShape->setPosition( maCurrentAxis.aPosition );
                            }
                        }
                    }
                }
            }
            else
            {
                try
                {
                    xDiaProp->setPropertyValue(
                        rtl::OUString::createFromAscii( "HasSecondaryYAxis" ), aTrueBool );
                }
                catch( beans::UnknownPropertyException )
                {
                    DBG_ERROR( "Couldn't turn on second y axis" );
                }
                uno::Reference< chart::XTwoAxisYSupplier > xSuppl( mxDiagram, uno::UNO_QUERY );
                if( xSuppl.is())
                    xProp = xSuppl->getSecondaryYAxis();
            }
            break;

        case SCH_XML_AXIS_Z:
            {
                try
                {
                    xDiaProp->setPropertyValue(
                        rtl::OUString::createFromAscii( "HasZAxis" ), aTrueBool );
                }
                catch( beans::UnknownPropertyException )
                {
                    DBG_ERROR( "Couldn't turn on z axis" );
                }
                uno::Reference< chart::XAxisZSupplier > xSuppl( mxDiagram, uno::UNO_QUERY );
                if( xSuppl.is())
                {
                    xProp = xSuppl->getZAxis();
                    if( bHasTitle )
                    {
                        uno::Reference< beans::XPropertySet > xTitleProp( xSuppl->getZAxisTitle(), uno::UNO_QUERY );
                        if( xTitleProp.is())
                        {
                            try
                            {
                                uno::Any aAny;
                                aAny <<= maCurrentAxis.aTitle;
                                xTitleProp->setPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "String" )), aAny );
                            }
                            catch( beans::UnknownPropertyException )
                            {
                                DBG_ERROR( "Property String for Title not available" );
                            }
                            uno::Reference< drawing::XShape > xShape( xTitleProp, uno::UNO_QUERY );
                            if( xShape.is())
                            {
                                // perform build chart with new title string
                                // so that setting the position works correctly
                                if( xDoc.is())
                                {
                                    xDoc->unlockControllers();
                                    xDoc->lockControllers();
                                }
                                if( maCurrentAxis.bTitleHasMoved )
                                    xShape->setPosition( maCurrentAxis.aPosition );
                            }
                        }
                    }
                }
            }
            break;
    }

    // set properties
    if( msAutoStyleName.getLength() &&
        xProp.is())
    {
        // #88077# AutoOrigin 'on' is default
        xProp->setPropertyValue( rtl::OUString::createFromAscii( "AutoOrigin" ), aTrueBool );

        const SvXMLStylesContext* pStylesCtxt = mrImportHelper.GetAutoStylesContext();
        if( pStylesCtxt )
        {
            const SvXMLStyleContext* pStyle = pStylesCtxt->FindStyleChildContext(
                mrImportHelper.GetChartFamilyID(), msAutoStyleName );

            if( pStyle && pStyle->ISA( XMLPropStyleContext ))
                (( XMLPropStyleContext* )pStyle )->FillPropertySet( xProp );
        }
    }
}

SvXMLImportContext* SchXMLAxisContext::CreateChildContext(
    USHORT nPrefix,
    const rtl::OUString& rLocalName,
    const uno::Reference< xml::sax::XAttributeList >& xAttrList )
{
    SvXMLImportContext* pContext = 0;
    const SvXMLTokenMap& rTokenMap = mrImportHelper.GetAxisElemTokenMap();

    switch( rTokenMap.Get( nPrefix, rLocalName ))
    {
        case XML_TOK_AXIS_TITLE:
        {
            uno::Reference< drawing::XShape > xTitleShape = getTitleShape();
            pContext = new SchXMLTitleContext( mrImportHelper, GetImport(), rLocalName,
                                               maCurrentAxis.aTitle,
                                               xTitleShape,
                                               maCurrentAxis.aPosition,
                                               maCurrentAxis.bTitleHasMoved );
        }
        break;

        case XML_TOK_AXIS_CATEGORIES:
            pContext = new SchXMLCategoriesDomainContext( mrImportHelper, GetImport(),
                                                          nPrefix, rLocalName,
                                                          mrCategoriesAddress );
            break;

        case XML_TOK_AXIS_GRID:
        {
            sal_Int16 nAttrCount = xAttrList.is()? xAttrList->getLength(): 0;
            sal_Bool bIsMajor = sal_True;       // default value for class is "major"
            rtl::OUString sAutoStyleName;

            for( sal_Int16 i = 0; i < nAttrCount; i++ )
            {
                rtl::OUString sAttrName = xAttrList->getNameByIndex( i );
                rtl::OUString aLocalName;
                USHORT nPrefix = GetImport().GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName );

                if( nPrefix == XML_NAMESPACE_CHART )
                {
                    if( IsXMLToken( aLocalName, XML_CLASS ) )
                    {
                        if( IsXMLToken( xAttrList->getValueByIndex( i ), XML_MINOR ) )
                            bIsMajor = sal_False;
                    }
                    else if( IsXMLToken( aLocalName, XML_STYLE_NAME ) )
                        sAutoStyleName = xAttrList->getValueByIndex( i );
                }
            }

            CreateGrid( sAutoStyleName, bIsMajor );

            // don't create a context => use default context. grid elements are empty
            pContext = new SvXMLImportContext( GetImport(), nPrefix, rLocalName );
        }
        break;

        default:
            pContext = new SvXMLImportContext( GetImport(), nPrefix, rLocalName );
            break;
    }

    return pContext;
}

// ========================================

SchXMLSeriesContext::SchXMLSeriesContext(
    SchXMLImportHelper& rImpHelper,
    SvXMLImport& rImport, const rtl::OUString& rLocalName,
    uno::Reference< chart::XDiagram >& xDiagram,
    std::vector< SchXMLAxis >& rAxes,
    com::sun::star::chart::ChartSeriesAddress& rSeriesAddress,
    ::std::list< ::chartxml::DataRowPointStyle >& rStyleList,
    sal_Int32 nSeriesIndex,
    sal_Int32& rMaxSeriesLength,
    sal_Int32& rDomainOffset,
    sal_Int32& rNumOfLines,
    sal_Bool&  rStockHasVolume ) :
        SvXMLImportContext( rImport, XML_NAMESPACE_CHART, rLocalName ),
        mxDiagram( xDiagram ),
        mrAxes( rAxes ),
        mrImportHelper( rImpHelper ),
        mrSeriesAddress( rSeriesAddress ),
        mrStyleList( rStyleList ),
        mnSeriesIndex( nSeriesIndex ),
        mnDataPointIndex( 0 ),
        mrDomainOffset( rDomainOffset ),
        mrNumOfLines( rNumOfLines ),
        mrStockHasVolume( rStockHasVolume ),
        mrMaxSeriesLength( rMaxSeriesLength ),
        mpAttachedAxis( NULL )
{
}

SchXMLSeriesContext::~SchXMLSeriesContext()
{
}

void SchXMLSeriesContext::StartElement( const uno::Reference< xml::sax::XAttributeList >& xAttrList )
{
    // parse attributes
    sal_Int16 nAttrCount = xAttrList.is()? xAttrList->getLength(): 0;
    ::rtl::OUString aValue;
    const SvXMLTokenMap& rAttrTokenMap = mrImportHelper.GetSeriesAttrTokenMap();
    mnAttachedAxis = 1;

    for( sal_Int16 i = 0; i < nAttrCount; i++ )
    {
        rtl::OUString sAttrName = xAttrList->getNameByIndex( i );
        rtl::OUString aLocalName;
        rtl::OUString aValue = xAttrList->getValueByIndex( i );
        USHORT nPrefix = GetImport().GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName );

        switch( rAttrTokenMap.Get( nPrefix, aLocalName ))
        {
            case XML_TOK_SERIES_CELL_RANGE:
                mrSeriesAddress.DataRangeAddress = aValue;
                break;
            case XML_TOK_SERIES_LABEL_ADDRESS:
                mrSeriesAddress.LabelAddress = aValue;
                break;
            case XML_TOK_SERIES_ATTACHED_AXIS:
                {
                    sal_Int32 nNumOfAxes = mrAxes.size();
                    for( sal_Int32 nCurrent = 0; nCurrent < nNumOfAxes; nCurrent++ )
                    {
                        if( aValue.equals( mrAxes[ nCurrent ].aName ) &&
                            mrAxes[ nCurrent ].eClass == SCH_XML_AXIS_Y )
                        {
                            mpAttachedAxis = &( mrAxes[ nCurrent ] );
                        }
                    }
                }
                break;
            case XML_TOK_SERIES_STYLE_NAME:
                msAutoStyleName = aValue;
                break;
            case XML_TOK_SERIES_CHART_CLASS:
                {
                    rtl::OUString sClassName;
                    sal_uInt16 nClassPrefix =
                        GetImport().GetNamespaceMap().GetKeyByAttrName(
                            aValue, &sClassName );
                    if( XML_NAMESPACE_CHART == nClassPrefix )
                    {
                        // used for bar-line combi chart
                        if( IsXMLToken( sClassName, XML_LINE ))
                            ++mrNumOfLines;
                        if( IsXMLToken( sClassName, XML_BAR ))
                            mrStockHasVolume = sal_True;
                    }
                }
                break;
        }
    }

    if( mpAttachedAxis )
    {
        if( mpAttachedAxis->nIndexInCategory > 0 )
        {
            // secondary axis => property has to be set (primary is default)
            mnAttachedAxis = 2;
        }
    }
}

void SchXMLSeriesContext::EndElement()
{
    if( mrMaxSeriesLength < mnDataPointIndex )
        mrMaxSeriesLength = mnDataPointIndex;

    if( msAutoStyleName.getLength() ||
        mnAttachedAxis != 1 )
    {
        ::chartxml::DataRowPointStyle aStyle(
            ::chartxml::DataRowPointStyle::DATA_SERIES,
            mnSeriesIndex + mrDomainOffset, -1, 1,
            msAutoStyleName, mnAttachedAxis );
        mrStyleList.push_back( aStyle );
    }
}

SvXMLImportContext* SchXMLSeriesContext::CreateChildContext(
    USHORT nPrefix,
    const rtl::OUString& rLocalName,
    const uno::Reference< xml::sax::XAttributeList >& xAttrList )
{
    SvXMLImportContext* pContext = 0;
    const SvXMLTokenMap& rTokenMap = mrImportHelper.GetSeriesElemTokenMap();

    switch( rTokenMap.Get( nPrefix, rLocalName ))
    {
        case XML_TOK_SERIES_DOMAIN:
            {
                sal_Int32 nIndex = mrSeriesAddress.DomainRangeAddresses.getLength();
                mrSeriesAddress.DomainRangeAddresses.realloc( nIndex + 1 );
                mrDomainOffset++;
                pContext = new SchXMLCategoriesDomainContext(
                    mrImportHelper, GetImport(),
                    nPrefix, rLocalName,
                    mrSeriesAddress.DomainRangeAddresses[ nIndex ] );
            }
            break;

        case XML_TOK_SERIES_MEAN_VALUE_LINE:
            pContext = new SchXMLStatisticsObjectContext(
                mrImportHelper, GetImport(),
                nPrefix, rLocalName,
                mrStyleList, mnSeriesIndex + mrDomainOffset,
                SchXMLStatisticsObjectContext::CONTEXT_TYPE_MEAN_VALUE_LINE );
            break;
        case XML_TOK_SERIES_REGRESSION_CURVE:
            pContext = new SchXMLStatisticsObjectContext(
                mrImportHelper, GetImport(),
                nPrefix, rLocalName,
                mrStyleList, mnSeriesIndex + mrDomainOffset,
                SchXMLStatisticsObjectContext::CONTEXT_TYPE_REGRESSION_CURVE );
            break;
        case XML_TOK_SERIES_ERROR_INDICATOR:
            pContext = new SchXMLStatisticsObjectContext(
                mrImportHelper, GetImport(),
                nPrefix, rLocalName,
                mrStyleList, mnSeriesIndex + mrDomainOffset,
                SchXMLStatisticsObjectContext::CONTEXT_TYPE_ERROR_INDICATOR );
            break;

        case XML_TOK_SERIES_DATA_POINT:
            pContext = new SchXMLDataPointContext( mrImportHelper, GetImport(), rLocalName, mxDiagram,
                                                   mrStyleList, mnSeriesIndex + mrDomainOffset, mnDataPointIndex );
            break;

        default:
            pContext = new SvXMLImportContext( GetImport(), nPrefix, rLocalName );
    }

    return pContext;
}

// ========================================

SchXMLDataPointContext::SchXMLDataPointContext(  SchXMLImportHelper& rImpHelper,
                                                 SvXMLImport& rImport, const rtl::OUString& rLocalName,
                                                 uno::Reference< chart::XDiagram >& xDiagram,
                                                 ::std::list< ::chartxml::DataRowPointStyle >& rStyleList,
                                                 sal_Int32 nSeries, sal_Int32& rIndex ) :
        SvXMLImportContext( rImport, XML_NAMESPACE_CHART, rLocalName ),
        mrImportHelper( rImpHelper ),
        mxDiagram( xDiagram ),
        mrStyleList( rStyleList ),
        mnSeries( nSeries ),
        mrIndex( rIndex )
{
}

SchXMLDataPointContext::~SchXMLDataPointContext()
{
}

void SchXMLDataPointContext::StartElement( const uno::Reference< xml::sax::XAttributeList >& xAttrList )
{
    sal_Int16 nAttrCount = xAttrList.is()? xAttrList->getLength(): 0;
    ::rtl::OUString aValue;
    ::rtl::OUString sAutoStyleName;
    sal_Int32 nRepeat = 1;

    for( sal_Int16 i = 0; i < nAttrCount; i++ )
    {
        rtl::OUString sAttrName = xAttrList->getNameByIndex( i );
        rtl::OUString aLocalName;
        USHORT nPrefix = GetImport().GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName );

        if( nPrefix == XML_NAMESPACE_CHART )
        {
            if( IsXMLToken( aLocalName, XML_STYLE_NAME ) )
                sAutoStyleName = xAttrList->getValueByIndex( i );
            else if( IsXMLToken( aLocalName, XML_REPEATED ) )
                nRepeat = xAttrList->getValueByIndex( i ).toInt32();
        }
    }

    if( sAutoStyleName.getLength())
    {
        ::chartxml::DataRowPointStyle aStyle(
            ::chartxml::DataRowPointStyle::DATA_POINT,
            mnSeries, mrIndex, nRepeat, sAutoStyleName );
        mrStyleList.push_back( aStyle );
    }
    mrIndex += nRepeat;
}

// ========================================

SchXMLCategoriesDomainContext::SchXMLCategoriesDomainContext(
    SchXMLImportHelper& rImpHelper,
    SvXMLImport& rImport,
    sal_uInt16 nPrefix,
    const rtl::OUString& rLocalName,
    rtl::OUString& rAddress ) :
        SvXMLImportContext( rImport, nPrefix, rLocalName ),
        mrImportHelper( rImpHelper ),
        mrAddress( rAddress )
{
}

SchXMLCategoriesDomainContext::~SchXMLCategoriesDomainContext()
{
}

void SchXMLCategoriesDomainContext::StartElement( const uno::Reference< xml::sax::XAttributeList >& xAttrList )
{
    sal_Int16 nAttrCount = xAttrList.is()? xAttrList->getLength(): 0;

    for( sal_Int16 i = 0; i < nAttrCount; i++ )
    {
        rtl::OUString sAttrName = xAttrList->getNameByIndex( i );
        rtl::OUString aLocalName;
        USHORT nPrefix = GetImport().GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName );

        if( nPrefix == XML_NAMESPACE_TABLE &&
            IsXMLToken( aLocalName, XML_CELL_RANGE_ADDRESS ) )
        {
            mrAddress = xAttrList->getValueByIndex( i );
        }
    }
}

// ========================================

SchXMLWallFloorContext::SchXMLWallFloorContext(
    SchXMLImportHelper& rImpHelper,
    SvXMLImport& rImport,
    sal_uInt16 nPrefix,
    const rtl::OUString& rLocalName,
    uno::Reference< chart::XDiagram >& xDiagram,
    ContextType eContextType ) :
        SvXMLImportContext( rImport, nPrefix, rLocalName ),
        mrImportHelper( rImpHelper ),
        mxWallFloorSupplier( xDiagram, uno::UNO_QUERY ),
        meContextType( eContextType )
{
}

SchXMLWallFloorContext::~SchXMLWallFloorContext()
{
}

void SchXMLWallFloorContext::StartElement( const uno::Reference< xml::sax::XAttributeList >& xAttrList )
{
    if( mxWallFloorSupplier.is())
    {
        sal_Int16 nAttrCount = xAttrList.is()? xAttrList->getLength(): 0;
        rtl::OUString sAutoStyleName;

        for( sal_Int16 i = 0; i < nAttrCount; i++ )
        {
            rtl::OUString sAttrName = xAttrList->getNameByIndex( i );
            rtl::OUString aLocalName;
            USHORT nPrefix = GetImport().GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName );

            if( nPrefix == XML_NAMESPACE_CHART &&
                IsXMLToken( aLocalName, XML_STYLE_NAME ) )
            {
                sAutoStyleName = xAttrList->getValueByIndex( i );
            }
        }

        if( sAutoStyleName.getLength())
        {
            // set properties
            uno::Reference< beans::XPropertySet > xProp( ( meContextType == CONTEXT_TYPE_WALL )
                                                         ? mxWallFloorSupplier->getWall()
                                                         : mxWallFloorSupplier->getFloor(),
                                                         uno::UNO_QUERY );
            if( xProp.is())
            {
                const SvXMLStylesContext* pStylesCtxt = mrImportHelper.GetAutoStylesContext();
                if( pStylesCtxt )
                {
                    const SvXMLStyleContext* pStyle = pStylesCtxt->FindStyleChildContext(
                        mrImportHelper.GetChartFamilyID(), sAutoStyleName );

                    if( pStyle && pStyle->ISA( XMLPropStyleContext ))
                        (( XMLPropStyleContext* )pStyle )->FillPropertySet( xProp );
                }
            }
        }
    }
}

// ========================================

SchXMLStockContext::SchXMLStockContext(
    SchXMLImportHelper& rImpHelper,
    SvXMLImport& rImport,
    sal_uInt16 nPrefix,
    const rtl::OUString& rLocalName,
    uno::Reference< chart::XDiagram >& xDiagram,
    ContextType eContextType ) :
        SvXMLImportContext( rImport, nPrefix, rLocalName ),
        mrImportHelper( rImpHelper ),
        mxStockPropProvider( xDiagram, uno::UNO_QUERY ),
        meContextType( eContextType )
{
}

SchXMLStockContext::~SchXMLStockContext()
{
}

void SchXMLStockContext::StartElement( const uno::Reference< xml::sax::XAttributeList >& xAttrList )
{
    if( mxStockPropProvider.is())
    {
        sal_Int16 nAttrCount = xAttrList.is()? xAttrList->getLength(): 0;
        rtl::OUString sAutoStyleName;

        for( sal_Int16 i = 0; i < nAttrCount; i++ )
        {
            rtl::OUString sAttrName = xAttrList->getNameByIndex( i );
            rtl::OUString aLocalName;
            USHORT nPrefix = GetImport().GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName );

            if( nPrefix == XML_NAMESPACE_CHART &&
                IsXMLToken( aLocalName, XML_STYLE_NAME ) )
            {
                sAutoStyleName = xAttrList->getValueByIndex( i );
            }
        }

        if( sAutoStyleName.getLength())
        {
            // set properties
            uno::Reference< beans::XPropertySet > xProp;
            switch( meContextType )
            {
                case CONTEXT_TYPE_GAIN:
                    xProp = mxStockPropProvider->getUpBar();
                    break;
                case CONTEXT_TYPE_LOSS:
                    xProp = mxStockPropProvider->getDownBar();
                    break;
                case CONTEXT_TYPE_RANGE:
                    xProp = mxStockPropProvider->getMinMaxLine();
                    break;
            }
            if( xProp.is())
            {
                const SvXMLStylesContext* pStylesCtxt = mrImportHelper.GetAutoStylesContext();
                if( pStylesCtxt )
                {
                    const SvXMLStyleContext* pStyle = pStylesCtxt->FindStyleChildContext(
                        mrImportHelper.GetChartFamilyID(), sAutoStyleName );

                    if( pStyle && pStyle->ISA( XMLPropStyleContext ))
                        (( XMLPropStyleContext* )pStyle )->FillPropertySet( xProp );
                }
            }
        }
    }
}

// ========================================

SchXMLStatisticsObjectContext::SchXMLStatisticsObjectContext(

    SchXMLImportHelper& rImpHelper,
    SvXMLImport& rImport,
    sal_uInt16 nPrefix,
    const rtl::OUString& rLocalName,
    ::std::list< ::chartxml::DataRowPointStyle >& rStyleList,
    sal_Int32 nSeries, ContextType eContextType ) :

        SvXMLImportContext( rImport, nPrefix, rLocalName ),
        mrImportHelper( rImpHelper ),
        mnSeriesIndex( nSeries ),
        mrStyleList( rStyleList ),
        meContextType( eContextType )
{}

SchXMLStatisticsObjectContext::~SchXMLStatisticsObjectContext()
{
}

void SchXMLStatisticsObjectContext::StartElement( const uno::Reference< xml::sax::XAttributeList >& xAttrList )
{
    sal_Int16 nAttrCount = xAttrList.is()? xAttrList->getLength(): 0;
    ::rtl::OUString aValue;
    ::rtl::OUString sAutoStyleName;
    sal_Int32 nRepeat = 1;

    for( sal_Int16 i = 0; i < nAttrCount; i++ )
    {
        rtl::OUString sAttrName = xAttrList->getNameByIndex( i );
        rtl::OUString aLocalName;
        USHORT nPrefix = GetImport().GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName );

        if( nPrefix == XML_NAMESPACE_CHART )
        {
            if( IsXMLToken( aLocalName, XML_STYLE_NAME ) )
                sAutoStyleName = xAttrList->getValueByIndex( i );
        }
    }

    if( sAutoStyleName.getLength())
    {
        ::chartxml::DataRowPointStyle::StyleType eType = ::chartxml::DataRowPointStyle::MEAN_VALUE;
        switch( meContextType )
        {
            case CONTEXT_TYPE_MEAN_VALUE_LINE:
                eType = ::chartxml::DataRowPointStyle::MEAN_VALUE;
                break;
            case CONTEXT_TYPE_REGRESSION_CURVE:
                eType = ::chartxml::DataRowPointStyle::REGRESSION;
                break;
            case CONTEXT_TYPE_ERROR_INDICATOR:
                eType = ::chartxml::DataRowPointStyle::ERROR_INDICATOR;
                break;
        }
        ::chartxml::DataRowPointStyle aStyle(
            eType, mnSeriesIndex, -1, 1, sAutoStyleName );
        mrStyleList.push_back( aStyle );
    }
}
