/**************************************************************
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
 *************************************************************/



// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_xmloff.hxx"
#include <tools/debug.hxx>
#include <xmloff/xmltoken.hxx>
#include "xmloff/xmlnmspe.hxx"
#include <xmloff/xmlmetai.hxx>
#include <xmloff/xmlstyle.hxx>
#include "SchXMLImport.hxx"
#include "SchXMLCalculationSettingsContext.hxx"

#include "contexts.hxx"
#include "SchXMLChartContext.hxx"

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

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

class SchXMLBodyContext_Impl : public SvXMLImportContext
{
private:
	SchXMLImportHelper& mrImportHelper;

public:

	SchXMLBodyContext_Impl( SchXMLImportHelper& rImpHelper,
				SvXMLImport& rImport, sal_uInt16 nPrfx,
				const ::rtl::OUString& rLName );
	virtual ~SchXMLBodyContext_Impl();

	virtual SvXMLImportContext *CreateChildContext( sal_uInt16 nPrefix,
			const ::rtl::OUString& rLocalName,
				const uno::Reference< xml::sax::XAttributeList > & xAttrList );
};

SchXMLBodyContext_Impl::SchXMLBodyContext_Impl(
		SchXMLImportHelper& rImpHelper, SvXMLImport& rImport,
		sal_uInt16 nPrfx, const ::rtl::OUString& rLName ) :
	SvXMLImportContext( rImport, nPrfx, rLName ),
	mrImportHelper( rImpHelper )
{
}

SchXMLBodyContext_Impl::~SchXMLBodyContext_Impl()
{
}

SvXMLImportContext *SchXMLBodyContext_Impl::CreateChildContext(
		sal_uInt16 nPrefix,
		const ::rtl::OUString& rLocalName,
		const uno::Reference< xml::sax::XAttributeList > & )
{
	return new SchXMLBodyContext( mrImportHelper, GetImport(), nPrefix,
								  rLocalName );
}

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

SchXMLDocContext::SchXMLDocContext( SchXMLImportHelper& rImpHelper,
									SvXMLImport& rImport,
									sal_uInt16 nPrefix,
									const rtl::OUString& rLName ) :
		SvXMLImportContext( rImport, nPrefix, rLName ),
		mrImportHelper( rImpHelper )
{
	DBG_ASSERT( XML_NAMESPACE_OFFICE == nPrefix &&
		( IsXMLToken( rLName, XML_DOCUMENT ) ||
		  IsXMLToken( rLName, XML_DOCUMENT_META) ||
		  IsXMLToken( rLName, XML_DOCUMENT_STYLES) ||
		  IsXMLToken( rLName, XML_DOCUMENT_CONTENT) ),
				"SchXMLDocContext instantiated with no <office:document> element" );
}

SchXMLDocContext::~SchXMLDocContext()
{}

TYPEINIT1( SchXMLDocContext, SvXMLImportContext );

SvXMLImportContext* SchXMLDocContext::CreateChildContext(
	sal_uInt16 nPrefix,
	const ::rtl::OUString& rLocalName,
	const uno::Reference< xml::sax::XAttributeList >& xAttrList )
{
	SvXMLImportContext* pContext = 0;
	const SvXMLTokenMap& rTokenMap = mrImportHelper.GetDocElemTokenMap();
	sal_uInt16 nFlags = GetImport().getImportFlags();

	switch( rTokenMap.Get( nPrefix, rLocalName ))
	{
		case XML_TOK_DOC_AUTOSTYLES:
			if( nFlags & IMPORT_AUTOSTYLES )
                // not nice, but this is safe, as the SchXMLDocContext class can only by
                // instantiated by the chart import class SchXMLImport (header is not exported)
                pContext =
                    static_cast< SchXMLImport& >( GetImport() ).CreateStylesContext( rLocalName, xAttrList );
			break;
		case XML_TOK_DOC_STYLES:
			// for draw styles containing gradients/hatches/markers and dashes
			if( nFlags & IMPORT_STYLES )
				pContext = new SvXMLStylesContext( GetImport(), nPrefix, rLocalName, xAttrList );
			break;
		case XML_TOK_DOC_META:
          // we come here in the flat ODF file format,
          // if XDocumentPropertiesSupplier is not supported at the model
//        DBG_WARNING("XML_TOK_DOC_META: should not have come here, maybe document is invalid?");
            pContext = SvXMLImportContext::CreateChildContext( nPrefix, rLocalName, xAttrList );
			break;
		case XML_TOK_DOC_BODY:
			if( nFlags & IMPORT_CONTENT )
				pContext = new SchXMLBodyContext_Impl( mrImportHelper, GetImport(), nPrefix, rLocalName );
			break;
	}

	// call parent when no own context was created
	if( ! pContext )
		pContext = SvXMLImportContext::CreateChildContext( nPrefix, rLocalName, xAttrList );

	return pContext;
}

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

SchXMLFlatDocContext_Impl::SchXMLFlatDocContext_Impl(
		SchXMLImportHelper& i_rImpHelper,
        SchXMLImport& i_rImport,
        sal_uInt16 i_nPrefix, const ::rtl::OUString & i_rLName,
        const uno::Reference<document::XDocumentProperties>& i_xDocProps,
        const uno::Reference<xml::sax::XDocumentHandler>& i_xDocBuilder) :
    SvXMLImportContext(i_rImport, i_nPrefix, i_rLName),
    SchXMLDocContext(i_rImpHelper, i_rImport, i_nPrefix, i_rLName),
    SvXMLMetaDocumentContext(i_rImport, i_nPrefix, i_rLName,
        i_xDocProps, i_xDocBuilder)
{
}

SchXMLFlatDocContext_Impl::~SchXMLFlatDocContext_Impl() { }


SvXMLImportContext *SchXMLFlatDocContext_Impl::CreateChildContext(
    sal_uInt16 i_nPrefix, const ::rtl::OUString& i_rLocalName,
    const uno::Reference<xml::sax::XAttributeList>& i_xAttrList)
{
    // behave like meta base class iff we encounter office:meta
    const SvXMLTokenMap& rTokenMap =
        mrImportHelper.GetDocElemTokenMap();
	if ( XML_TOK_DOC_META == rTokenMap.Get( i_nPrefix, i_rLocalName ) ) {
        return SvXMLMetaDocumentContext::CreateChildContext(
                    i_nPrefix, i_rLocalName, i_xAttrList );
    } else {
        return SchXMLDocContext::CreateChildContext(
                    i_nPrefix, i_rLocalName, i_xAttrList );
    }
}

// ----------------------------------------

SchXMLBodyContext::SchXMLBodyContext( SchXMLImportHelper& rImpHelper,
									  SvXMLImport& rImport,
									  sal_uInt16 nPrefix,
									  const rtl::OUString& rLName ) :
		SvXMLImportContext( rImport, nPrefix, rLName ),
		mrImportHelper( rImpHelper )
{
	DBG_ASSERT( XML_NAMESPACE_OFFICE == nPrefix &&
				IsXMLToken( rLName, XML_CHART ),
				"SchXMLBodyContext instantiated with no <office:chart> element" );
}

SchXMLBodyContext::~SchXMLBodyContext()
{}

void SchXMLBodyContext::EndElement()
{
}

SvXMLImportContext* SchXMLBodyContext::CreateChildContext(
	sal_uInt16 nPrefix,
	const rtl::OUString& rLocalName,
	const uno::Reference< xml::sax::XAttributeList >& xAttrList )
{
	SvXMLImportContext* pContext = 0;

	// <chart:chart> element
	if( nPrefix == XML_NAMESPACE_CHART &&
        IsXMLToken( rLocalName, XML_CHART ) )
	{
		pContext = mrImportHelper.CreateChartContext( GetImport(),
													  nPrefix, rLocalName,
													  GetImport().GetModel(),
													  xAttrList );
	}
    else if(nPrefix == XML_NAMESPACE_TABLE &&
            IsXMLToken( rLocalName, XML_CALCULATION_SETTINGS ))
    {
        // i99104 handle null date correctly
        pContext = new SchXMLCalculationSettingsContext ( GetImport(), nPrefix, rLocalName, xAttrList);
    }
	else
	{
		pContext = SvXMLImportContext::CreateChildContext( nPrefix, rLocalName, xAttrList );
	}

	return pContext;
}
