/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 * 
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

/*TODO
    - late init
    - order by number!
    - insert default detector and loader as last ones in hashes ... don't hold it as an extra member!
      => CheckedIterator will be obsolete!
 */

#ifndef __FRAMEWORK_CLASSES_FILTERCACHE_HXX_
#define __FRAMEWORK_CLASSES_FILTERCACHE_HXX_

//_________________________________________________________________________________________________________________
//	my own includes
//_________________________________________________________________________________________________________________

#include <classes/filtercachedata.hxx>
#include <threadhelp/threadhelpbase.hxx>

#include <threadhelp/transactionbase.hxx>
#include <general.h>
#include <queries.h>

//_________________________________________________________________________________________________________________
//	interface includes
//_________________________________________________________________________________________________________________
#include <com/sun/star/uno/Reference.hxx>
#include <com/sun/star/uno/Sequence.hxx>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/registry/XRegistryKey.hpp>
#include <com/sun/star/beans/PropertyValue.hpp>
#include <com/sun/star/container/ElementExistException.hpp>
#include <com/sun/star/container/NoSuchElementException.hpp>

//_________________________________________________________________________________________________________________
//	other includes
//_________________________________________________________________________________________________________________
#include <rtl/ustring.hxx>

#ifdef ENABLE_GENERATEFILTERCACHE
    #ifndef _RTL_USTRBUF_HXX_
    #include <rtl/ustrbuf.hxx>
    #endif
#endif

//_________________________________________________________________________________________________________________
//	namespace
//_________________________________________________________________________________________________________________

namespace framework{

//_________________________________________________________________________________________________________________
//	exported const
//_________________________________________________________________________________________________________________

//_________________________________________________________________________________________________________________
//	exported definitions
//_________________________________________________________________________________________________________________

/*-************************************************************************************************************//**
    @short          cache for all filter and type information
    @descr			Frameloader- and filterfactory need some informations about our current registered filters and types.
                    For better performance its neccessary to cache all needed values.

    @implements		-
    @base           ThreadHelpBase
                    TransactionBase

    @devstatus		ready to use
    @threadsafe     yes
*//*-*************************************************************************************************************/

class FilterCache   :   private ThreadHelpBase
                    ,   private TransactionBase
{
    public:

    //-------------------------------------------------------------------------------------------------------------
    //	public methods
    //-------------------------------------------------------------------------------------------------------------

    public:

        //---------------------------------------------------------------------------------------------------------
        //	constructor / destructor
        //---------------------------------------------------------------------------------------------------------

        FilterCache( sal_Int32 nVersion = DEFAULT_FILTERCACHE_VERSION,
                     sal_Int16 nMode    = DEFAULT_FILTERCACHE_MODE   );

        /*-****************************************************************************************************//**
            @short		standard destructor to delete instance
            @descr		This will clear the cache if last owner release it.

            @seealso	-

            @param		-
            @return		-

            @onerror	-
        *//*-*****************************************************************************************************/

        virtual ~FilterCache();

        void flush( DataContainer::ECFGType eType );

        /*-****************************************************************************************************//**
            @short		get the current state of the cache
            @descr		Call this methods to get information about the state of the current cache.

            @seealso	-

            @param		-
            @return		-
            @return		-

            @onerror	-
        *//*-*****************************************************************************************************/

        sal_Bool isValidOrRepairable() const;
        sal_Bool hasTypes           () const;
        sal_Bool hasFilters         () const;
        sal_Bool hasDetectors       () const;
        sal_Bool hasLoaders         () const;
        sal_Bool hasContentHandlers () const;

        /*-****************************************************************************************************//**
            @short		search routines to find items which match given parameter
            @descr		Mostly we search for a type first and get all informations about filter, detector and loader
                        services from the other configuration tables which are registered for this type.
                        These operations support a FindFirst/Next mechanism.
                        If you call search...( ... nStartEntry=0 ... ) we search for
                        the first entry. If these return a value different from <empty> you can work with these value.
                        If found value isn't the right one - you can call search method again.
                        DONT'T CHANGE THE VALUE OF "rStartEntry" between two search calls!
                        You can use returned value as parameter for getBy...Name() functions of this implementation too!

            @attention	returned type name is an internal name
                        returned filter name is an internal name
                        returned loader name is an implementation name of a service
                        returned detector name is an implementation name of a service

            @seealso	-

            @param      "sResult", name of found type, filter, ...
            @return		true, if search was successful,
                        false, otherwise.

            @onerror	We return false.
        *//*-*****************************************************************************************************/

        sal_Bool searchType                     (   const   ::rtl::OUString&            sURL                ,
                                                    const   ::rtl::OUString&            sMediaType          ,
                                                    const   ::rtl::OUString&            sClipboardFormat    ,
                                                            CheckedTypeIterator&        aStartEntry         ,
                                                            ::rtl::OUString&            sResult             ) const;

        sal_Bool searchFilterForType            (   const   ::rtl::OUString&            sInternalTypeName   ,
                                                            CheckedStringListIterator&  aStartEntry         ,
                                                            ::rtl::OUString&            sResult             ) const;

        sal_Bool searchDetectorForType          (   const   ::rtl::OUString&            sInternalTypeName   ,
                                                            CheckedStringListIterator&  aStartEntry         ,
                                                            ::rtl::OUString&            sResult             ) const;

        sal_Bool searchLoaderForType            (   const   ::rtl::OUString&            sInternalTypeName   ,
                                                            CheckedStringListIterator&  aStartEntry         ,
                                                            ::rtl::OUString&            sResult             ) const;

        sal_Bool searchContentHandlerForType    (   const   ::rtl::OUString&            sInternalTypeName   ,
                                                            CheckedStringListIterator&  aStartEntry         ,
                                                            ::rtl::OUString&            sResult             ) const;

        /*-****************************************************************************************************//**
            @short		get all properties of a cache entry by given name
            @descr		If you need additional informations about our internal cache values
                        you can use these methods to get a list of all cached config values
                        and subkeys of specified entry.

            @seealso	-

            @param      "sName", name of suspected entry in cache
            @return		A structure with valid information if item exists! An empty Any otherwise.

            @onerror	We return an empty Any.
        *//*-*****************************************************************************************************/

        css::uno::Sequence< ::rtl::OUString >               getAllTypeNames                 () const;
        css::uno::Sequence< ::rtl::OUString >               getAllFilterNames               () const;
        css::uno::Sequence< ::rtl::OUString >               getAllDetectorNames             () const;   // without default detector!
        css::uno::Sequence< ::rtl::OUString >               getAllLoaderNames               () const;   // without default loader!
        css::uno::Sequence< ::rtl::OUString >               getAllContentHandlerNames       () const;
        css::uno::Sequence< ::rtl::OUString >               getAllDetectorNamesWithDefault  () const;   // default detector is last one!
        css::uno::Sequence< ::rtl::OUString >               getAllLoaderNamesWithDefault    () const;   // default loader is last one!
        ::rtl::OUString                                     getDefaultLoader                () const;

        css::uno::Sequence< css::beans::PropertyValue >     getTypeProperties               (   const   ::rtl::OUString&    sName   ) const;
        css::uno::Sequence< css::beans::PropertyValue >     getFilterProperties             (   const   ::rtl::OUString&    sName   ) const;
        css::uno::Sequence< css::beans::PropertyValue >     getDetectorProperties           (   const   ::rtl::OUString&    sName   ) const;
        css::uno::Sequence< css::beans::PropertyValue >     getLoaderProperties             (   const   ::rtl::OUString&    sName   ) const;
        css::uno::Sequence< css::beans::PropertyValue >     getContentHandlerProperties     (   const   ::rtl::OUString&    sName   ) const;

        FileType                                            getType                         (   const   ::rtl::OUString&    sName   ) const;
        Filter                                              getFilter                       (   const   ::rtl::OUString&    sName   ) const;
        Detector                                            getDetector                     (   const   ::rtl::OUString&    sName   ) const;
        Loader                                              getLoader                       (   const   ::rtl::OUString&    sName   ) const;
        ContentHandler                                      getContentHandler               (   const   ::rtl::OUString&    sName   ) const;

        sal_Bool                                            existsType                      (   const   ::rtl::OUString&    sName   ) const;
        sal_Bool                                            existsFilter                    (   const   ::rtl::OUString&    sName   ) const;
        sal_Bool                                            existsDetector                  (   const   ::rtl::OUString&    sName   ) const;
        sal_Bool                                            existsLoader                    (   const   ::rtl::OUString&    sName   ) const;
        sal_Bool                                            existsContentHandler            (   const   ::rtl::OUString&    sName   ) const;

        /*-****************************************************************************************************//**
            @short		support special query modes
            @descr		Our owner services need sometimes a special mode to query for subsets of our configuration!
                        They give us a special query string - we return right values.

            @seealso	file queries.h
            @seealso	class FilterFactory
            @seealso	class FrameLoaderFactory
            @seealso	class TypeDetection

            @param      "sName", name of query
            @return		A structure with valid information!

            @onerror	We return an empty result set.
        *//*-*****************************************************************************************************/

        css::uno::Any queryFilters( const ::rtl::OUString& sQuery ) const;

        /*-****************************************************************************************************//**
            @short		support registration of elements in current configuration
            @descr		Use this methods to add or remove items in our configuration files.
                        We use the globale configuration to do that ... in fat office "share/config/registry/..."!

                        *** structure of type properties **********************************************************

                            PropertyValue.Name					PropertyValue.Value					Description
                            ---------------------------------------------------------------------------------------
                            ...

                        *** structure of filter properties ********************************************************

                            PropertyValue.Name					PropertyValue.Value					Description
                            ---------------------------------------------------------------------------------------
                            "Name"								[string]							internal name
                            "Type"								[string]							registered for these type
                            "UIName"							[string]							localized name for UI (valid for current locale at runtime!)
                            "UINames"							[stringlist]						assignment of all supported localized names to right locales
                            "DocumentService"					[string]							uno servicename of document services
                            "FilterService"						[string]							uno servicename of filter implementation
                            "Flags"								[long]								describe filter
                            "UserData"							[stringlist]						additional user data (format not fixed!)
                            "FileFormatVersion"					[long]								version numbher of supported files
                            "TemplateName"						[string]							name of template

                        *** structure of detector properties ******************************************************

                            PropertyValue.Name					PropertyValue.Value					Description
                            ---------------------------------------------------------------------------------------
                            ...

                        *** structure of loader properties ********************************************************

                            PropertyValue.Name					PropertyValue.Value					Description
                            ---------------------------------------------------------------------------------------
                            ...

            @seealso	-

            @param      "sName"			, name of type, filter ...
            @param      "lProperties"	, values of new type, filter
            @return		state of operation as bool

            @onerror	We return false then.
        *//*-*****************************************************************************************************/

        sal_Bool addFilter    ( const ::rtl::OUString&                                 sName       ,
                                const css::uno::Sequence< css::beans::PropertyValue >& lProperties ,
                                      sal_Bool                                         bException  ) throw(css::container::ElementExistException  ,
                                                                                                           css::registry::InvalidRegistryException);
        sal_Bool replaceFilter( const ::rtl::OUString&                                 sName       ,
                                const css::uno::Sequence< css::beans::PropertyValue >& lProperties ,
                                      sal_Bool                                         bException  ) throw(css::container::NoSuchElementException  ,
                                                                                                           css::registry::InvalidRegistryException);
        sal_Bool removeFilter ( const ::rtl::OUString&                                 sName       ,
                                      sal_Bool                                         bException  ) throw(css::container::NoSuchElementException  ,
                                                                                                           css::registry::InvalidRegistryException);

        sal_Bool addType      ( const ::rtl::OUString&                                 sName       ,
                                const css::uno::Sequence< css::beans::PropertyValue >& lProperties ,
                                      sal_Bool                                         bException  ) throw(css::container::ElementExistException  ,
                                                                                                           css::registry::InvalidRegistryException);
        sal_Bool replaceType  ( const ::rtl::OUString&                                 sName       ,
                                const css::uno::Sequence< css::beans::PropertyValue >& lProperties ,
                                      sal_Bool                                         bException  ) throw(css::container::NoSuchElementException  ,
                                                                                                           css::registry::InvalidRegistryException);
        sal_Bool removeType   ( const ::rtl::OUString&                                 sName       ,
                                      sal_Bool                                         bException  ) throw(css::container::NoSuchElementException  ,
                                                                                                           css::registry::InvalidRegistryException);

        sal_Bool addDetector    ( const ::rtl::OUString&                                 sName       ,
                                  const css::uno::Sequence< css::beans::PropertyValue >& lProperties ,
                                        sal_Bool                                         bException  ) throw(css::container::ElementExistException  ,
                                                                                                             css::registry::InvalidRegistryException);
        sal_Bool replaceDetector( const ::rtl::OUString&                                 sName       ,
                                  const css::uno::Sequence< css::beans::PropertyValue >& lProperties ,
                                        sal_Bool                                         bException  ) throw(css::container::NoSuchElementException  ,
                                                                                                             css::registry::InvalidRegistryException);
        sal_Bool removeDetector ( const ::rtl::OUString&                                 sName       ,
                                        sal_Bool                                         bException  ) throw(css::container::NoSuchElementException  ,
                                                                                                             css::registry::InvalidRegistryException);

        sal_Bool validateAndRepair();
        sal_Bool validateAndRepairTypes();
        sal_Bool validateAndRepairFilter();
        sal_Bool validateAndRepairDetectors();
        sal_Bool validateAndRepairLoader();
        sal_Bool validateAndRepairHandler();

    //-------------------------------------------------------------------------------------------------------------
    //	protected methods
    //-------------------------------------------------------------------------------------------------------------

    protected:

    //-------------------------------------------------------------------------------------------------------------
    //	private methods
    //-------------------------------------------------------------------------------------------------------------

    private:

    //-------------------------------------------------------------------------------------------------------------
    //	debug methods
    //-------------------------------------------------------------------------------------------------------------

        /*-****************************************************************************************************//**
            @short		debug-method to check incoming parameter of some other mehods of this class
            @descr		The following methods are used to check parameters for other methods
                        of this class. The return value is used directly for an ASSERT(...).

            @seealso	ASSERT in implementation!

            @param		references to checking variables
            @return		sal_False ,on invalid parameter
            @return		sal_True  ,otherwise

            @onerror	-
        *//*-*****************************************************************************************************/

    #ifdef ENABLE_ASSERTIONS

    private:

        static sal_Bool implcp_searchType							(	const	::rtl::OUString&									sURL				,
                                                                        const	::rtl::OUString*									pMediaType			,
                                                                        const	::rtl::OUString*									pClipboardFormat	,
                                                                        const	CheckedTypeIterator&								aStartEntry			,
                                                                        const	::rtl::OUString&									sResult				);
        static sal_Bool implcp_searchFilterForType					(	const	::rtl::OUString&									sInternalTypeName	,
                                                                        const	CheckedStringListIterator&							aStartEntry			,
                                                                        const	::rtl::OUString&									sResult				);
        static sal_Bool implcp_searchDetectorForType				(	const	::rtl::OUString&									sInternalTypeName	,
                                                                        const	CheckedStringListIterator&							aStartEntry			,
                                                                        const	::rtl::OUString&									sResult				);
        static sal_Bool implcp_searchLoaderForType					(	const	::rtl::OUString&									sInternalTypeName	,
                                                                        const	CheckedStringListIterator&							aStartEntry			,
                                                                        const	::rtl::OUString&									sResult				);
        static sal_Bool implcp_searchContentHandlerForType          (   const   ::rtl::OUString&                                    sInternalTypeName   ,
                                                                        const	CheckedStringListIterator&							aStartEntry			,
                                                                        const	::rtl::OUString&									sResult				);
        static sal_Bool implcp_getTypeProperties					(	const	::rtl::OUString&									sName				);
        static sal_Bool implcp_getFilterProperties					(	const	::rtl::OUString&									sName				);
        static sal_Bool implcp_getDetectorProperties				(	const	::rtl::OUString&									sName				);
        static sal_Bool implcp_getLoaderProperties					(	const	::rtl::OUString&									sName				);
        static sal_Bool implcp_getContentHandlerProperties          (   const   ::rtl::OUString&                                    sName               );
        static sal_Bool implcp_getType								(	const	::rtl::OUString&									sName				);
        static sal_Bool implcp_getFilter							(	const	::rtl::OUString&									sName				);
        static sal_Bool implcp_getDetector							(	const	::rtl::OUString&									sName				);
        static sal_Bool implcp_getLoader							(	const	::rtl::OUString&									sName				);
        static sal_Bool implcp_getContentHandler                    (   const   ::rtl::OUString&                                    sName               );
        static sal_Bool implcp_existsType							(	const	::rtl::OUString&									sName				);
        static sal_Bool implcp_existsFilter							(	const	::rtl::OUString&									sName				);
        static sal_Bool implcp_existsDetector						(	const	::rtl::OUString&									sName				);
        static sal_Bool implcp_existsLoader							(	const	::rtl::OUString&									sName				);
        static sal_Bool implcp_existsContentHandler                 (   const   ::rtl::OUString&                                    sName               );
        static sal_Bool implcp_addFilter							(	const	::rtl::OUString&									sName				,
                                                                        const	css::uno::Sequence< css::beans::PropertyValue >&	lProperties			);
        static sal_Bool implcp_replaceFilter						(	const	::rtl::OUString&									sName				,
                                                                        const	css::uno::Sequence< css::beans::PropertyValue >&	lProperties			);
        static sal_Bool implcp_removeFilter							(	const	::rtl::OUString&									sName				);
        static sal_Bool implcp_queryFilters							(	const	::rtl::OUString&									sQuery				);

    #endif	//	#ifdef ENABLE_ASSERTIONS

    #ifdef ENABLE_COMPONENT_SELF_CHECK

    private:

        void impldbg_dumpCache();

    #endif // ENABLE_COMPONENT_SELF_CHECK

    //-------------------------------------------------------------------------------------------------------------
    //	private variables
    //-------------------------------------------------------------------------------------------------------------
    private:

        static sal_Int32        m_nRefCount         ;
        static DataContainer*   m_pData             ;
        static sal_Int32        m_nVersion          ;
        static sal_Int16        m_nMode             ;

};		//	class FilterCache

}		//	namespace framework

#endif	//	#ifndef __FRAMEWORK_CLASSES_FILTERCACHE_HXX_

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
