/**************************************************************
 *
 * 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_scripting.hxx"

#include <cppuhelper/weakref.hxx>
#include <cppuhelper/implementationentry.hxx>
#include <cppuhelper/factory.hxx>
#include <cppuhelper/exc_hlp.hxx>
#include <cppuhelper/implbase1.hxx>
#include <comphelper/mediadescriptor.hxx>

#include <com/sun/star/lang/XMultiComponentFactory.hpp>
#include <com/sun/star/frame/XModel.hpp>
#include <com/sun/star/reflection/XProxyFactory.hpp>

#include <com/sun/star/script/provider/XScriptProviderFactory.hpp>
#include <com/sun/star/script/browse/BrowseNodeFactoryViewTypes.hpp>
#include <com/sun/star/document/XScriptInvocationContext.hpp>

#include <tools/diagnose_ex.h>

#include "BrowseNodeFactoryImpl.hxx"
#include "ActiveMSPList.hxx"
#include <util/MiscUtils.hxx>
#include <util/util.hxx>

#include <vector>
#include <algorithm>
using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::script;
using namespace ::sf_misc;

namespace browsenodefactory
{
class BrowseNodeAggregator :
    public ::cppu::WeakImplHelper1< browse::XBrowseNode >
{
private:
    ::rtl::OUString m_Name;
    Sequence< Reference< browse::XBrowseNode > > m_Nodes;

public:

    BrowseNodeAggregator( const Reference< browse::XBrowseNode >& node )
    {
        m_Name = node->getName();
        m_Nodes.realloc( 1 );
        m_Nodes[ 0 ] = node;
    }

    ~BrowseNodeAggregator()
    {
    }

    void addBrowseNode( const Reference< browse::XBrowseNode>& node )
    {
        sal_Int32 index = m_Nodes.getLength();

        m_Nodes.realloc( index + 1 );
        m_Nodes[ index ] = node;
    }

    virtual ::rtl::OUString
    SAL_CALL getName()
            throw ( RuntimeException )
    {
        return m_Name;
    }

    virtual Sequence< Reference< browse::XBrowseNode > > SAL_CALL
    getChildNodes()
        throw ( RuntimeException )
    {
        std::vector<  Sequence< Reference < browse::XBrowseNode > > > seqs;
        seqs.reserve( m_Nodes.getLength() );

        sal_Int32 numChildren = 0;

        for ( sal_Int32 i = 0; i < m_Nodes.getLength(); i++ )
        {
            Sequence< Reference < browse::XBrowseNode > > childs;
            try
            {
                childs = m_Nodes[ i ]->getChildNodes();
                seqs.push_back( childs );
                numChildren += childs.getLength();
            }
            catch ( Exception& )
            {
                // some form of exception getting child nodes so they
                // won't be displayed
            }
        }

        std::vector<  Sequence< Reference < browse::XBrowseNode > > >::const_iterator it = seqs.begin();
        std::vector<  Sequence< Reference < browse::XBrowseNode > > >::const_iterator it_end = seqs.end();

        Sequence< Reference < browse::XBrowseNode > > result( numChildren );
        for ( sal_Int32 index = 0; it != it_end && index < numChildren ; ++it )
        {
            Sequence< Reference < browse::XBrowseNode > > childs = *it;
            for ( sal_Int32 j = 0; j < childs.getLength(); j++ )
            {
                result[ index++ ] = childs[ j ];
            }
        }
        return result;
    }

    virtual sal_Bool SAL_CALL
    hasChildNodes()
        throw ( RuntimeException )
    {
        if ( m_Nodes.getLength() != 0 )
        {
            for ( sal_Int32 i = 0 ; i < m_Nodes.getLength(); i++ )
            {
                try
                {
                    if ( m_Nodes[ i ]->hasChildNodes() )
                    {
                        return sal_True;
                    }
                }
                catch ( Exception& )
                {
                    // some form of exception getting child nodes so move
                    // on to the next one
                }
            }
        }

        return sal_False;
    }

    virtual sal_Int16 SAL_CALL getType()
        throw ( RuntimeException )
    {
        return browse::BrowseNodeTypes::CONTAINER;
    }
};


//typedef ::std::map< ::rtl::OUString, Reference< browse::XBrowseNode > >
typedef ::std::hash_map< ::rtl::OUString, Reference< browse::XBrowseNode >,
    ::rtl::OUStringHash, ::std::equal_to< ::rtl::OUString > >
        BrowseNodeAggregatorHash;
typedef ::std::vector< ::rtl::OUString > vString;


struct alphaSort
{
    bool operator()( const ::rtl::OUString& a, const ::rtl::OUString& b )
    {
        return a.compareTo( b ) < 0;
    }
};
class LocationBrowseNode :
    public ::cppu::WeakImplHelper1< browse::XBrowseNode >
{
private:
    BrowseNodeAggregatorHash* m_hBNA;
    vString m_vStr;
    ::rtl::OUString m_sNodeName;
    Reference< browse::XBrowseNode > m_origNode;

public:

    LocationBrowseNode( const Reference< browse::XBrowseNode >& node )
    {
        m_sNodeName = node->getName();
        m_hBNA = NULL;
        m_origNode.set( node );
    }

    ~LocationBrowseNode()
    {
        if (m_hBNA)
        {
            delete m_hBNA;
        }
    }

    // -------------------------------------------------------------------------
    // XBrowseNode
    // -------------------------------------------------------------------------

    virtual ::rtl::OUString SAL_CALL getName()
        throw ( RuntimeException )
    {
        return m_sNodeName;
    }

    virtual Sequence< Reference< browse::XBrowseNode > > SAL_CALL
    getChildNodes()
        throw ( RuntimeException )
    {
        if ( m_hBNA == NULL )
        {
            loadChildNodes();
        }

        Sequence<  Reference< browse::XBrowseNode > > children( m_hBNA->size() );
        sal_Int32 index = 0;

        vString::const_iterator it = m_vStr.begin();

        for ( ; it != m_vStr.end(); ++it, index++ )
        {
            children[ index ].set( m_hBNA->find( *it )->second );
        }

        return children;
    }

    virtual sal_Bool SAL_CALL hasChildNodes()
        throw ( RuntimeException )
    {
        return sal_True;
    }

    virtual sal_Int16 SAL_CALL getType()
        throw ( RuntimeException )
    {
        return browse::BrowseNodeTypes::CONTAINER;
    }

private:

    void loadChildNodes()
    {
        m_hBNA = new BrowseNodeAggregatorHash();

        Sequence< Reference< browse::XBrowseNode > > langNodes =
            m_origNode->getChildNodes();

        for ( sal_Int32 i = 0; i < langNodes.getLength(); i++ )
        {
            Reference< browse::XBrowseNode > xbn;
            if ( langNodes[ i ]->getName().equals(::rtl::OUString::createFromAscii("uno_packages")) )
            {
                xbn.set( new LocationBrowseNode( langNodes[ i ] ) );
            }
            else
            {
                xbn.set( langNodes[ i ] );
            }

            Sequence< Reference< browse::XBrowseNode > > grandchildren =
                xbn->getChildNodes();

            for ( sal_Int32 j = 0; j < grandchildren.getLength(); j++ )
            {
                Reference< browse::XBrowseNode > grandchild(grandchildren[j]);

                BrowseNodeAggregatorHash::iterator h_it =
                    m_hBNA->find( grandchild->getName() );

                if ( h_it != m_hBNA->end() )
                {
                    BrowseNodeAggregator* bna = static_cast< BrowseNodeAggregator* >( h_it->second.get() );
                    bna->addBrowseNode( grandchild );
                }
                else
                {
                    Reference< browse::XBrowseNode > bna(
                        new BrowseNodeAggregator( grandchild ) );
                    (*m_hBNA)[ grandchild->getName() ].set( bna );
                    m_vStr.push_back( grandchild->getName() );
                }
            }
        }
        // sort children alphabetically
        ::std::sort( m_vStr.begin(), m_vStr.end(), alphaSort() );
    }
};

namespace
{

Sequence< Reference< browse::XBrowseNode > > getAllBrowseNodes( const Reference< XComponentContext >& xCtx )
{
	Reference< lang::XMultiComponentFactory > mcf =
		xCtx->getServiceManager();

	Sequence< ::rtl::OUString > openDocs =
		MiscUtils::allOpenTDocUrls( xCtx );

	Reference< provider::XScriptProviderFactory > xFac;
	sal_Int32 initialSize = openDocs.getLength() + 2;
	sal_Int32 mspIndex = 0;

	Sequence < Reference < browse::XBrowseNode > > locnBNs( initialSize );
	try
	{
		xFac.set(
			xCtx->getValueByName(
				OUSTR("/singletons/com.sun.star.script.provider.theMasterScriptProviderFactory") ), UNO_QUERY_THROW );

		locnBNs[ mspIndex++ ] = Reference< browse::XBrowseNode >( xFac->createScriptProvider( makeAny( ::rtl::OUString::createFromAscii("user") ) ), UNO_QUERY_THROW );
		locnBNs[ mspIndex++ ] = Reference< browse::XBrowseNode >( xFac->createScriptProvider( makeAny( ::rtl::OUString::createFromAscii("share") ) ), UNO_QUERY_THROW );
	}
	// TODO proper exception handling, should throw
	catch( Exception& e )
	{
		(void)e;
		OSL_TRACE("Caught Exception %s",
			::rtl::OUStringToOString( e.Message , RTL_TEXTENCODING_ASCII_US ).pData->buffer );
		locnBNs.realloc( mspIndex );
		return locnBNs;
	}

	for ( sal_Int32 i = 0; i < openDocs.getLength(); i++ )
	{
		try
		{
			Reference< frame::XModel > model( MiscUtils::tDocUrlToModel( openDocs[ i ] ), UNO_QUERY_THROW );

			// #i44599 Check if it's a real document or something special like Hidden/Preview
			css::uno::Reference< css::frame::XController > xCurrentController = model->getCurrentController();
			if( xCurrentController.is() )
			{
				comphelper::MediaDescriptor aMD( model->getArgs() );
				sal_Bool bDefault = false;
				sal_Bool bHidden  = aMD.getUnpackedValueOrDefault( comphelper::MediaDescriptor::PROP_HIDDEN(),  bDefault );
				sal_Bool bPreview = aMD.getUnpackedValueOrDefault( comphelper::MediaDescriptor::PROP_PREVIEW(), bDefault );
				if( !bHidden && !bPreview )
                {
                    Reference< document::XEmbeddedScripts > xScripts( model, UNO_QUERY );
                    if ( xScripts.is() )
					    locnBNs[ mspIndex++ ] = Reference< browse::XBrowseNode >(
                            xFac->createScriptProvider( makeAny( model ) ), UNO_QUERY_THROW );
                }
			}
		}
		catch( const Exception& )
		{
            DBG_UNHANDLED_EXCEPTION();
		}

	}

	Sequence < Reference < browse::XBrowseNode > > locnBNs_Return( mspIndex );
	for ( sal_Int32 j = 0; j < mspIndex; j++ )
		locnBNs_Return[j] = locnBNs[j];

    return locnBNs_Return;
}

} // namespace

typedef ::std::vector< Reference< browse::XBrowseNode > > vXBrowseNodes;

struct alphaSortForBNodes
{
    bool operator()( const Reference< browse::XBrowseNode >& a, const Reference< browse::XBrowseNode >& b )
    {
        return a->getName().compareTo( b->getName() ) < 0;
    }
};

typedef ::cppu::WeakImplHelper1< browse::XBrowseNode > t_BrowseNodeBase;
class DefaultBrowseNode :
    public t_BrowseNodeBase
{

private:
    Reference< browse::XBrowseNode > m_xWrappedBrowseNode;
    Reference< lang::XTypeProvider > m_xWrappedTypeProv;
    Reference< XAggregation >        m_xAggProxy;
    Reference< XComponentContext >   m_xCtx;

    DefaultBrowseNode();
public:
    DefaultBrowseNode( const Reference< XComponentContext >& xCtx, const Reference< browse::XBrowseNode>& xNode ) : m_xWrappedBrowseNode( xNode ), m_xWrappedTypeProv( xNode, UNO_QUERY ), m_xCtx( xCtx, UNO_QUERY )
    {
        OSL_ENSURE( m_xWrappedBrowseNode.is(), "DefaultBrowseNode::DefaultBrowseNode(): No BrowseNode to wrap" );
        OSL_ENSURE( m_xWrappedTypeProv.is(), "DefaultBrowseNode::DefaultBrowseNode(): No BrowseNode to wrap" );
        OSL_ENSURE( m_xCtx.is(), "DefaultBrowseNode::DefaultBrowseNode(): No ComponentContext" );
    // Use proxy factory service to create aggregatable proxy.
        try
        {
            Reference< lang::XMultiComponentFactory > xMFac( m_xCtx->getServiceManager(), UNO_QUERY_THROW );
            Reference< reflection::XProxyFactory > xProxyFac(
                xMFac->createInstanceWithContext(
                        rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
                            "com.sun.star.reflection.ProxyFactory" ) ),
                        m_xCtx  ), UNO_QUERY_THROW );
            m_xAggProxy = xProxyFac->createProxy( m_xWrappedBrowseNode );
        }
        catch(  uno::Exception& )
        {
            OSL_ENSURE( false, "DefaultBrowseNode::DefaultBrowseNode: Caught exception!" );
        }
        OSL_ENSURE( m_xAggProxy.is(),
            "DefaultBrowseNode::DefaultBrowseNode: Wrapped BrowseNode cannot be aggregated!" );

        if ( m_xAggProxy.is() )
        {
            osl_incrementInterlockedCount( &m_refCount );

            /* i35609 - Fix crash on Solaris. The setDelegator call needs
               to be in its own block to ensure that all temporary Reference
               instances that are acquired during the call are released
               before m_refCount is decremented again */
            {
                m_xAggProxy->setDelegator(
                    static_cast< cppu::OWeakObject * >( this ) );
            }

            osl_decrementInterlockedCount( &m_refCount );
        }
    }

    ~DefaultBrowseNode()
    {
        if ( m_xAggProxy.is() )
        {
            m_xAggProxy->setDelegator( uno::Reference< uno::XInterface >() );
        }
    }

    virtual Sequence< Reference< browse::XBrowseNode > > SAL_CALL
                getChildNodes()
    throw ( RuntimeException )
    {
        if ( hasChildNodes() )
        {
            vXBrowseNodes m_vNodes;
            Sequence < Reference< browse::XBrowseNode > > nodes =
                m_xWrappedBrowseNode->getChildNodes();
            for ( sal_Int32 i=0; i<nodes.getLength(); i++ )
            {
				Reference< browse::XBrowseNode > xBrowseNode = nodes[ i ];
		        OSL_ENSURE( xBrowseNode.is(), "DefaultBrowseNode::getChildNodes(): Invalid BrowseNode" );
				if( xBrowseNode.is() )
	                m_vNodes.push_back( new DefaultBrowseNode( m_xCtx, xBrowseNode ) );
            }

            ::std::sort( m_vNodes.begin(), m_vNodes.end(), alphaSortForBNodes() );
            Sequence < Reference< browse::XBrowseNode > > children( m_vNodes.size() );
            vXBrowseNodes::const_iterator it = m_vNodes.begin();
            for ( sal_Int32 i=0; it != m_vNodes.end() && i<children.getLength(); i++, ++it )
            {
                children[ i ].set( *it );
            }
            return children;
        }
        else
        {
            // no nodes

            Sequence < Reference< browse::XBrowseNode > > none;
            return none;
        }
    }

    virtual sal_Int16 SAL_CALL getType()
        throw ( RuntimeException )
    {
        return m_xWrappedBrowseNode->getType();
    }

    virtual ::rtl::OUString
    SAL_CALL getName()
    throw ( RuntimeException )
    {
        return m_xWrappedBrowseNode->getName();
    }

    virtual sal_Bool SAL_CALL
    hasChildNodes()
        throw ( RuntimeException )
    {
        return m_xWrappedBrowseNode->hasChildNodes();
    }

    // XInterface
    virtual Any SAL_CALL queryInterface( const Type& aType )
        throw ( com::sun::star::uno::RuntimeException )
    {
        Any aRet = t_BrowseNodeBase::queryInterface( aType );
        if ( aRet.hasValue() )
        {
            return aRet;
        }
        if ( m_xAggProxy.is() )
        {
            return m_xAggProxy->queryAggregation( aType );
        }
        else
        {
            return Any();
        }
    }

    virtual void SAL_CALL acquire()
        throw ()

    {
        osl_incrementInterlockedCount( &m_refCount );
    }
    virtual void SAL_CALL release()
        throw ()
    {
        if ( osl_decrementInterlockedCount( &m_refCount ) == 0 )
        {
            delete this;
        }
    }
    // XTypeProvider (implemnented by base, but needs to be overridden for
    //                delegating to aggregate)
    virtual Sequence< Type > SAL_CALL getTypes()
        throw ( com::sun::star::uno::RuntimeException )
    {
        return m_xWrappedTypeProv->getTypes();
    }
    virtual Sequence< sal_Int8 > SAL_CALL getImplementationId()
        throw ( com::sun::star::uno::RuntimeException )
    {
        return m_xWrappedTypeProv->getImplementationId();

    }
};

class DefaultRootBrowseNode :
    public ::cppu::WeakImplHelper1< browse::XBrowseNode >
{

private:
    vXBrowseNodes m_vNodes;
    ::rtl::OUString m_Name;

    DefaultRootBrowseNode();
public:
    DefaultRootBrowseNode( const Reference< XComponentContext >& xCtx )
    {
        Sequence < Reference< browse::XBrowseNode > > nodes =
            getAllBrowseNodes( xCtx );

        for ( sal_Int32 i=0; i<nodes.getLength(); i++ )
        {
            m_vNodes.push_back( new DefaultBrowseNode( xCtx, nodes[ i ] ) );
        }
        m_Name = ::rtl::OUString::createFromAscii( "Root" );
    }

    ~DefaultRootBrowseNode()
    {
    }

    virtual Sequence< Reference< browse::XBrowseNode > > SAL_CALL
                getChildNodes()
    throw ( RuntimeException )
    {
        // no need to sort user, share, doc1...docN
        //::std::sort( m_vNodes.begin(), m_vNodes.end(), alphaSortForBNodes() );
        Sequence < Reference< browse::XBrowseNode > > children( m_vNodes.size() );
        vXBrowseNodes::const_iterator it = m_vNodes.begin();
        for ( sal_Int32 i=0; it != m_vNodes.end() && i<children.getLength(); i++, ++it )
        {
            children[ i ].set( *it );
        }
        return children;
    }

    virtual sal_Int16 SAL_CALL getType()
        throw ( RuntimeException )
    {
        return browse::BrowseNodeTypes::ROOT;
    }

    virtual ::rtl::OUString
    SAL_CALL getName()
    throw ( RuntimeException )
    {
        return m_Name;
    }

    virtual sal_Bool SAL_CALL
    hasChildNodes()
        throw ( RuntimeException )
    {
        sal_Bool result = sal_True;
        if ( !m_vNodes.size() )
        {
            result = sal_False;
        }
        return result;
    }
};


class SelectorBrowseNode :
    public ::cppu::WeakImplHelper1< browse::XBrowseNode >
{
private:
    Reference< XComponentContext > m_xComponentContext;

public:
    SelectorBrowseNode( const Reference< XComponentContext >& xContext )
      : m_xComponentContext( xContext )
    {
    }

    ~SelectorBrowseNode()
    {
    }

    virtual ::rtl::OUString SAL_CALL getName()
        throw ( RuntimeException )
    {
	    return ::rtl::OUString::createFromAscii( "Root" );
    }

    virtual Sequence< Reference< browse::XBrowseNode > > SAL_CALL
    getChildNodes()
        throw ( RuntimeException )
    {

        Sequence < Reference < browse::XBrowseNode > > locnBNs = getAllBrowseNodes( m_xComponentContext );

        Sequence<  Reference< browse::XBrowseNode > > children(
            locnBNs.getLength() );

        for ( sal_Int32 j = 0; j < locnBNs.getLength(); j++ )
        {
            children[j] = new LocationBrowseNode( locnBNs[j] );
        }

        return children;
    }

    virtual sal_Bool SAL_CALL hasChildNodes()
        throw ( RuntimeException )
    {
        return sal_True; // will always be user and share
    }

    virtual sal_Int16 SAL_CALL getType()
        throw ( RuntimeException )
    {
        return browse::BrowseNodeTypes::CONTAINER;
    }
};

BrowseNodeFactoryImpl::BrowseNodeFactoryImpl(
    Reference< XComponentContext > const & xComponentContext )
    : m_xComponentContext( xComponentContext )
{
}

BrowseNodeFactoryImpl::~BrowseNodeFactoryImpl()
{
}


//############################################################################
// Implementation of XBrowseNodeFactory
//############################################################################

/*
 * The selector hierarchy is the standard hierarchy for organizers with the
 * language nodes removed.
 */
Reference< browse::XBrowseNode > SAL_CALL
BrowseNodeFactoryImpl::createView( sal_Int16 viewType )
    throw (RuntimeException)
{
    switch( viewType )
    {
        case browse::BrowseNodeFactoryViewTypes::MACROSELECTOR:
            return getSelectorHierarchy();
        case browse::BrowseNodeFactoryViewTypes::MACROORGANIZER:
            return getOrganizerHierarchy();
        default:
            throw RuntimeException( OUSTR("Unknown view type" ), Reference< XInterface >() );
    }
}

Reference< browse::XBrowseNode >
BrowseNodeFactoryImpl::getSelectorHierarchy()
    throw (RuntimeException)
{
    /*if ( !m_xSelectorBrowseNode.is() )
    {
        m_xSelectorBrowseNode = new SelectorBrowseNode( m_xComponentContext );
    }*/
    return new SelectorBrowseNode( m_xComponentContext );
}

Reference< browse::XBrowseNode >
BrowseNodeFactoryImpl::getOrganizerHierarchy()
    throw (RuntimeException)
{
    Reference< browse::XBrowseNode > xRet = new  DefaultRootBrowseNode( m_xComponentContext );
    return xRet;
}
//############################################################################
// Helper methods
//############################################################################

//############################################################################
// Namespace global methods for setting up BrowseNodeFactory service
//############################################################################

Sequence< ::rtl::OUString > SAL_CALL
bnf_getSupportedServiceNames( )
    SAL_THROW( () )
{
    ::rtl::OUString str_name = ::rtl::OUString::createFromAscii(
        "com.sun.star.script.browse.BrowseNodeFactory");

    return Sequence< ::rtl::OUString >( &str_name, 1 );
}

::rtl::OUString SAL_CALL
bnf_getImplementationName( )
    SAL_THROW( () )
{
    return ::rtl::OUString::createFromAscii(
        "com.sun.star.script.browse.BrowseNodeFactory" );
}

Reference< XInterface > SAL_CALL
bnf_create( Reference< XComponentContext > const & xComponentContext )
    SAL_THROW( (Exception) )
{
    return static_cast< ::cppu::OWeakObject * >(
        new BrowseNodeFactoryImpl( xComponentContext ) );
}

//############################################################################
// Implementation of XServiceInfo
//############################################################################

::rtl::OUString SAL_CALL
BrowseNodeFactoryImpl::getImplementationName()
    throw (RuntimeException)
{
    return bnf_getImplementationName();
}

Sequence< ::rtl::OUString > SAL_CALL
BrowseNodeFactoryImpl::getSupportedServiceNames()
    throw (RuntimeException)
{
    return bnf_getSupportedServiceNames();
}

sal_Bool BrowseNodeFactoryImpl::supportsService(
    ::rtl::OUString const & serviceName )
    throw (RuntimeException)
{
//     check();

    Sequence< ::rtl::OUString > supported_services(
        getSupportedServiceNames() );

    ::rtl::OUString const * ar = supported_services.getConstArray();

    for ( sal_Int32 pos = supported_services.getLength(); pos--; )
    {
        if (ar[ pos ].equals( serviceName ))
            return sal_True;
    }
    return sal_False;
}

} // namespace browsenodefactory
