<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: apifactory.cxx,v $
 *
 *  $Revision: 1.12 $
 *
 *  last change: $Author: ihi $ $Date: 2007-11-23 14:02:17 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 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
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_configmgr.hxx"

#include "apifactory.hxx"
#include "objectregistry.hxx"

#include "apitreeaccess.hxx"
#include "apitreeimplobj.hxx"

#include <com/sun/star/uno/Reference.hxx>
#include <com/sun/star/lang/XUnoTunnel.hpp>

#include "noderef.hxx"
#include "anynoderef.hxx"

#include "configexcept.hxx"
#include "configset.hxx"

namespace configmgr
{
//-----------------------------------------------------------------------------
    namespace css = ::com::sun::star;
    namespace uno   = css::uno;
    namespace lang  = css::lang;
//-----------------------------------------------------------------------------
    namespace configapi
    {
//-----------------------------------------------------------------------------
        typedef uno::XInterface UnoInterface;
        typedef uno::Reference< uno::XInterface > UnoInterfaceRef;
        typedef uno::Any UnoAny;

        using uno::Reference;
        using lang::XUnoTunnel;
        using configuration::Tree;
        using configuration::ElementTree;
        using configuration::TemplateHolder;
        using configuration::NodeRef;
        using configuration::NodeID;

//-----------------------------------------------------------------------------
ObjectRegistry::~ObjectRegistry()
{
    OSL_ENSURE(m_aMap.empty(),"WARNING: Configuration Object Map: Some Objects were not revoked correctly");
}

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

Factory::Factory(ObjectRegistryHolder pRegistry)
: m_pRegistry(pRegistry)
, m_aTunnelID()
{
    OSL_ENSURE(pRegistry.is(), "ERROR: Factory requires a Object Registry");
}
//-----------------------------------------------------------------------------

Factory::~Factory()
{
}
//-----------------------------------------------------------------------------
inline
NodeElement* Factory::implFind(configuration::NodeID const& aNode)
{
    return m_pRegistry->findElement(aNode);
}
//-----------------------------------------------------------------------------
inline
void Factory::doRegisterElement(configuration::NodeID const& aNode, NodeElement* pElement)
{
    m_pRegistry->registerElement(aNode,pElement);
}
//-----------------------------------------------------------------------------
inline
void Factory::doRevokeElement(configuration::NodeID const& aNode, NodeElement* pElement)
{
    m_pRegistry->revokeElement(aNode,pElement);
}
//-----------------------------------------------------------------------------

ApiTreeImpl& Factory::getImplementation(NodeElement& rElement)
{
    return rElement.getApiTree();
}
//-----------------------------------------------------------------------------

inline
TemplateHolder Factory::implGetSetElementTemplate(Tree const& aTree, NodeRef const& aNode)
{
    TemplateHolder aRet;
    if (configuration::isSetNode(aTree,aNode))
    {
        aRet = configuration::SetElementInfo::extractElementInfo(aTree,aNode);
    }
    else if (!configuration::isGroupNode(aTree,aNode))
    {
        OSL_ENSURE( !configuration::isStructuralNode(aTree,aNode), "ERROR: Configuration: unknown kind of object");
        throw configuration::Exception("INTERNAL ERROR: Cannot create template - Unexpected node type");
    }
    return aRet;
}
//-----------------------------------------------------------------------------
inline
UnoInterfaceRef Factory::implToUno(NodeElement* pElement)
{
    if ( pElement )
        return UnoInterfaceRef(pElement->getUnoInstance(), uno::UNO_REF_NO_ACQUIRE);
    else
        return UnoInterfaceRef();
}
//-----------------------------------------------------------------------------
inline
void Factory::implHaveNewElement(NodeID aNodeID, NodeElement* pElement)
{
    OSL_ENSURE(pElement ,"WARNING: New API object could not be created");

    if (pElement)
    {
        doRegisterElement(aNodeID,pElement);
        OSL_ENSURE(implFind(aNodeID) == pElement,"WARNING: New API object could not be registered with its factory");
    }
}
//-----------------------------------------------------------------------------

UnoInterfaceRef Factory::makeUnoElement(Tree const& aTree, NodeRef const& aNode)
{
    return implToUno(makeElement(aTree,aNode));
}
//-----------------------------------------------------------------------------
NodeElement* Factory::makeElement(Tree const& aTree, NodeRef const& aNode)
{
    OSL_PRECOND( !aTree.isEmpty() == aNode.isValid(), "ERROR: Configuration: Making element from tree requires valid node");
    if (aTree.isEmpty())
        return 0;

    OSL_PRECOND( aTree.isValidNode(aNode), "ERROR: Configuration: NodeRef does not match Tree");
    OSL_PRECOND( configuration::isStructuralNode(aTree,aNode), "ERROR: Configuration: Cannot make object for value node");

    NodeID aNodeID(aTree,aNode);
    NodeElement* pRet = findElement(aNodeID);
    if (pRet == 0)
    {
        TemplateHolder aTemplate = implGetSetElementTemplate(aTree,aNode);

        if (!aTree.isRootNode(aNode))
        {
            pRet = doCreateGroupMember(aTree,aNode,aTemplate.get());
        }
        else
        {
            ElementTree aElementTree = ElementTree::extract(aTree);
            if (aElementTree.isValid())
            {
                pRet = doCreateSetElement(aElementTree,aTemplate.get());
            }
            else
            {
                OSL_ENSURE(aTree.getContextTree().isEmpty(),"INTERNAL ERROR: Found tree (not a set element) with a parent tree.");
                pRet = doCreateAccessRoot(aTree,aTemplate.get(), vos::ORef< OOptions >());
            }
        }
        implHaveNewElement(aNodeID,pRet);
    }
    return pRet;
}
//-----------------------------------------------------------------------------

UnoInterfaceRef Factory::findUnoElement(NodeID const& aNodeID)
{
    return implToUno(findElement(aNodeID));
}
//-----------------------------------------------------------------------------
NodeElement* Factory::findElement(NodeID const& aNodeID)
{
    NodeElement* pReturn = implFind(aNodeID);
    if (pReturn) pReturn->getUnoInstance()->acquire();
    return pReturn;
}
//-----------------------------------------------------------------------------

void Factory::revokeElement(NodeID const& aNodeID)
{
    if (NodeElement* pElement = implFind(aNodeID))
        doRevokeElement(aNodeID, pElement);
}
//-----------------------------------------------------------------------------

void Factory::revokeElement(NodeID const& aNodeID, NodeElement& rElement)
{
    if (implFind(aNodeID) == &rElement)
        doRevokeElement(aNodeID, &rElement);
}

//-----------------------------------------------------------------------------
TreeElement* Factory::makeAccessRoot(Tree const& aTree, RequestOptions const& _aOptions)
{
    OSL_PRECOND( !aTree.isEmpty() , "ERROR: Configuration: Making element from tree requires valid tree");
    if (aTree.isEmpty()) return 0;

    OSL_ENSURE(aTree.getContextTree().isEmpty(),"INTERNAL ERROR: Tree with parent tree should not be used for an access root");
    OSL_ENSURE(!ElementTree::extract(aTree).isValid(),"INTERNAL ERROR: Element Tree should not be used for an access root");

    NodeRef aRoot = aTree.getRootNode();
    OSL_ENSURE(aRoot.isValid(),"INTERNAL ERROR: Tree has no root node");

    OSL_PRECOND( configuration::isStructuralNode(aTree,aRoot), "ERROR: Configuration: Cannot make object for value node");

    NodeID aNodeID(aTree,aRoot);
    // must be a tree element if it is a tree root
    TreeElement* pRet = static_cast<TreeElement*>(findElement(aNodeID));
    if (0 == pRet)
    {
        TemplateHolder aTemplate = implGetSetElementTemplate(aTree,aRoot);
        vos::ORef<OOptions> xOptions = new OOptions(_aOptions);
        pRet = doCreateAccessRoot(aTree,aTemplate.get(), xOptions);
        implHaveNewElement (aNodeID,pRet);
    }
    return pRet;
}
//-----------------------------------------------------------------------------

UnoInterfaceRef Factory::makeUnoGroupMember(Tree const& aTree, NodeRef const& aNode)
{
    return implToUno(makeGroupMember(aTree,aNode));
}
//-----------------------------------------------------------------------------
NodeElement* Factory::makeGroupMember(Tree const& aTree, NodeRef const& aNode)
{
    OSL_PRECOND( !aTree.isEmpty() , "ERROR: Configuration: Creating an object requires a valid tree");
    if (aTree.isEmpty()) return 0;

    OSL_PRECOND( aNode.isValid() , "ERROR: Configuration: Creating an object requires a valid node");
    OSL_PRECOND( aTree.isValidNode(aNode), "ERROR: Configuration: NodeRef does not match Tree");
    if (!aTree.isValidNode(aNode)) return 0;

    OSL_PRECOND( configuration::isStructuralNode(aTree,aNode), "ERROR: Configuration: Cannot make object for value node");
    OSL_ENSURE(!aTree.isRootNode(aNode),"INTERNAL ERROR: Root of Tree should not be used for a group member object");

    NodeID aNodeID(aTree,aNode);
    NodeElement* pRet = findElement(aNodeID);
    if (0 == pRet)
    {
        TemplateHolder aTemplate = implGetSetElementTemplate(aTree,aNode);

        pRet = doCreateGroupMember(aTree,aNode,aTemplate.get());

        OSL_ENSURE( pRet,"WARNING: New API object could not be created");

        implHaveNewElement(aNodeID,pRet);
    }
    return pRet;
}
//-----------------------------------------------------------------------------

UnoInterfaceRef Factory::makeUnoSetElement(ElementTree const& aElementTree)
{
    UnoInterfaceRef aRet = implToUno(makeSetElement(aElementTree));
    OSL_ENSURE( uno::Reference<XUnoTunnel>::query(aRet).is(),"ERROR: API set element has no UnoTunnel");
    OSL_ENSURE( uno::Reference<XUnoTunnel>::query(aRet).is() &&
                0 != uno::Reference<XUnoTunnel>::query(aRet)->getSomething(doGetElementTunnelID()),
                "ERROR: API set element does not support the right tunnel ID");

    return aRet;
}
//-----------------------------------------------------------------------------

SetElement* Factory::makeSetElement(ElementTree const& aElementTree)
{
    OSL_PRECOND( aElementTree.isValid() , "ERROR: Configuration: Making element from tree requires valid tree");
    if (!aElementTree.isValid()) return 0;

    Tree aTree = aElementTree.getTree();
    OSL_ENSURE(!aTree.isEmpty(),"INTERNAL ERROR: Element Tree has no Tree");

    NodeRef aRoot = aTree.getRootNode();
    OSL_ENSURE(aRoot.isValid(),"INTERNAL ERROR: Tree has no root node");

    OSL_ENSURE( configuration::isStructuralNode(aTree,aRoot), "ERROR: Configuration: Cannot make object for value node");

    NodeID aNodeID(aTree,aRoot);
    // must be a set element if it wraps a ElementTree
    SetElement* pRet = static_cast<SetElement*>( findElement(aNodeID) );
    if (0 == pRet)
    {
        TemplateHolder aTemplate = implGetSetElementTemplate(aTree,aRoot);

        pRet = doCreateSetElement(aElementTree,aTemplate.get());

        implHaveNewElement(aNodeID,pRet);
    }
    return pRet;
}
//-----------------------------------------------------------------------------

SetElement* Factory::findSetElement(configuration::ElementRef const& aElement)
{
    OSL_PRECOND( aElement.isValid() , "ERROR: Configuration: Making element from tree requires valid tree");
    if (!aElement.isValid()) return 0;

    configuration::TreeRef aTree = aElement.getTreeRef();
    OSL_ENSURE(!aTree.isEmpty(),"INTERNAL ERROR: Element Tree has no Tree");

    NodeRef aRoot = aTree.getRootNode();
    OSL_ENSURE(aRoot.isValid(),"INTERNAL ERROR: Tree has no root node");

    NodeID aNodeID(aTree,aRoot);
    // must be a set element if it wraps a ElementTree
    SetElement* pRet = static_cast<SetElement*>( findElement(aNodeID) );

    return pRet;
}
//-----------------------------------------------------------------------------

SetElement* Factory::extractSetElement(UnoAny const& aElement)
{
    using configuration::ElementTreeImpl;
    SetElement* pTunneledImpl = 0;

    Reference< XUnoTunnel > xElementTunnel;
    if ( aElement.hasValue() && (aElement >>= xElementTunnel) )
    {
        OSL_ASSERT( xElementTunnel.is() );

        sal_Int64 nSomething = xElementTunnel->getSomething(doGetElementTunnelID());
        if (0 != nSomething)
        {
            void* pVoid = reinterpret_cast<void*>(nSomething);
            pTunneledImpl = static_cast<SetElement*>(pVoid);
        }
    }
    return pTunneledImpl;
}
//-----------------------------------------------------------------------------

bool Factory::tunnelSetElement(sal_Int64& nSomething, SetElement& rElement, uno::Sequence< sal_Int8 > const& aTunnelID)
{
    if (aTunnelID == doGetElementTunnelID())
    {
        void* pVoid = &rElement;
        nSomething = reinterpret_cast<sal_Int64>(pVoid);

        return true;
    }
    else
        return false;
}

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

ApiTreeImpl const* Factory::findDescendantTreeImpl(configuration::NodeID const& aNode, ApiTreeImpl const* pImpl)
{
    ApiTreeImpl* pRet = 0;
    if (pImpl)
    {
        if ( NodeElement* pElement = pImpl->getFactory().implFind( aNode ) )
            pRet = &pElement->getApiTree();
    }
    return pRet;
}

//-----------------------------------------------------------------------------
    }
}
<commit_msg>INTEGRATION: CWS changefileheader (1.12.16); FILE MERGED 2008/03/31 12:22:35 rt 1.12.16.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: apifactory.cxx,v $
 * $Revision: 1.13 $
 *
 * 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.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_configmgr.hxx"

#include "apifactory.hxx"
#include "objectregistry.hxx"

#include "apitreeaccess.hxx"
#include "apitreeimplobj.hxx"

#include <com/sun/star/uno/Reference.hxx>
#include <com/sun/star/lang/XUnoTunnel.hpp>

#include "noderef.hxx"
#include "anynoderef.hxx"

#include "configexcept.hxx"
#include "configset.hxx"

namespace configmgr
{
//-----------------------------------------------------------------------------
    namespace css = ::com::sun::star;
    namespace uno   = css::uno;
    namespace lang  = css::lang;
//-----------------------------------------------------------------------------
    namespace configapi
    {
//-----------------------------------------------------------------------------
        typedef uno::XInterface UnoInterface;
        typedef uno::Reference< uno::XInterface > UnoInterfaceRef;
        typedef uno::Any UnoAny;

        using uno::Reference;
        using lang::XUnoTunnel;
        using configuration::Tree;
        using configuration::ElementTree;
        using configuration::TemplateHolder;
        using configuration::NodeRef;
        using configuration::NodeID;

//-----------------------------------------------------------------------------
ObjectRegistry::~ObjectRegistry()
{
    OSL_ENSURE(m_aMap.empty(),"WARNING: Configuration Object Map: Some Objects were not revoked correctly");
}

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

Factory::Factory(ObjectRegistryHolder pRegistry)
: m_pRegistry(pRegistry)
, m_aTunnelID()
{
    OSL_ENSURE(pRegistry.is(), "ERROR: Factory requires a Object Registry");
}
//-----------------------------------------------------------------------------

Factory::~Factory()
{
}
//-----------------------------------------------------------------------------
inline
NodeElement* Factory::implFind(configuration::NodeID const& aNode)
{
    return m_pRegistry->findElement(aNode);
}
//-----------------------------------------------------------------------------
inline
void Factory::doRegisterElement(configuration::NodeID const& aNode, NodeElement* pElement)
{
    m_pRegistry->registerElement(aNode,pElement);
}
//-----------------------------------------------------------------------------
inline
void Factory::doRevokeElement(configuration::NodeID const& aNode, NodeElement* pElement)
{
    m_pRegistry->revokeElement(aNode,pElement);
}
//-----------------------------------------------------------------------------

ApiTreeImpl& Factory::getImplementation(NodeElement& rElement)
{
    return rElement.getApiTree();
}
//-----------------------------------------------------------------------------

inline
TemplateHolder Factory::implGetSetElementTemplate(Tree const& aTree, NodeRef const& aNode)
{
    TemplateHolder aRet;
    if (configuration::isSetNode(aTree,aNode))
    {
        aRet = configuration::SetElementInfo::extractElementInfo(aTree,aNode);
    }
    else if (!configuration::isGroupNode(aTree,aNode))
    {
        OSL_ENSURE( !configuration::isStructuralNode(aTree,aNode), "ERROR: Configuration: unknown kind of object");
        throw configuration::Exception("INTERNAL ERROR: Cannot create template - Unexpected node type");
    }
    return aRet;
}
//-----------------------------------------------------------------------------
inline
UnoInterfaceRef Factory::implToUno(NodeElement* pElement)
{
    if ( pElement )
        return UnoInterfaceRef(pElement->getUnoInstance(), uno::UNO_REF_NO_ACQUIRE);
    else
        return UnoInterfaceRef();
}
//-----------------------------------------------------------------------------
inline
void Factory::implHaveNewElement(NodeID aNodeID, NodeElement* pElement)
{
    OSL_ENSURE(pElement ,"WARNING: New API object could not be created");

    if (pElement)
    {
        doRegisterElement(aNodeID,pElement);
        OSL_ENSURE(implFind(aNodeID) == pElement,"WARNING: New API object could not be registered with its factory");
    }
}
//-----------------------------------------------------------------------------

UnoInterfaceRef Factory::makeUnoElement(Tree const& aTree, NodeRef const& aNode)
{
    return implToUno(makeElement(aTree,aNode));
}
//-----------------------------------------------------------------------------
NodeElement* Factory::makeElement(Tree const& aTree, NodeRef const& aNode)
{
    OSL_PRECOND( !aTree.isEmpty() == aNode.isValid(), "ERROR: Configuration: Making element from tree requires valid node");
    if (aTree.isEmpty())
        return 0;

    OSL_PRECOND( aTree.isValidNode(aNode), "ERROR: Configuration: NodeRef does not match Tree");
    OSL_PRECOND( configuration::isStructuralNode(aTree,aNode), "ERROR: Configuration: Cannot make object for value node");

    NodeID aNodeID(aTree,aNode);
    NodeElement* pRet = findElement(aNodeID);
    if (pRet == 0)
    {
        TemplateHolder aTemplate = implGetSetElementTemplate(aTree,aNode);

        if (!aTree.isRootNode(aNode))
        {
            pRet = doCreateGroupMember(aTree,aNode,aTemplate.get());
        }
        else
        {
            ElementTree aElementTree = ElementTree::extract(aTree);
            if (aElementTree.isValid())
            {
                pRet = doCreateSetElement(aElementTree,aTemplate.get());
            }
            else
            {
                OSL_ENSURE(aTree.getContextTree().isEmpty(),"INTERNAL ERROR: Found tree (not a set element) with a parent tree.");
                pRet = doCreateAccessRoot(aTree,aTemplate.get(), vos::ORef< OOptions >());
            }
        }
        implHaveNewElement(aNodeID,pRet);
    }
    return pRet;
}
//-----------------------------------------------------------------------------

UnoInterfaceRef Factory::findUnoElement(NodeID const& aNodeID)
{
    return implToUno(findElement(aNodeID));
}
//-----------------------------------------------------------------------------
NodeElement* Factory::findElement(NodeID const& aNodeID)
{
    NodeElement* pReturn = implFind(aNodeID);
    if (pReturn) pReturn->getUnoInstance()->acquire();
    return pReturn;
}
//-----------------------------------------------------------------------------

void Factory::revokeElement(NodeID const& aNodeID)
{
    if (NodeElement* pElement = implFind(aNodeID))
        doRevokeElement(aNodeID, pElement);
}
//-----------------------------------------------------------------------------

void Factory::revokeElement(NodeID const& aNodeID, NodeElement& rElement)
{
    if (implFind(aNodeID) == &rElement)
        doRevokeElement(aNodeID, &rElement);
}

//-----------------------------------------------------------------------------
TreeElement* Factory::makeAccessRoot(Tree const& aTree, RequestOptions const& _aOptions)
{
    OSL_PRECOND( !aTree.isEmpty() , "ERROR: Configuration: Making element from tree requires valid tree");
    if (aTree.isEmpty()) return 0;

    OSL_ENSURE(aTree.getContextTree().isEmpty(),"INTERNAL ERROR: Tree with parent tree should not be used for an access root");
    OSL_ENSURE(!ElementTree::extract(aTree).isValid(),"INTERNAL ERROR: Element Tree should not be used for an access root");

    NodeRef aRoot = aTree.getRootNode();
    OSL_ENSURE(aRoot.isValid(),"INTERNAL ERROR: Tree has no root node");

    OSL_PRECOND( configuration::isStructuralNode(aTree,aRoot), "ERROR: Configuration: Cannot make object for value node");

    NodeID aNodeID(aTree,aRoot);
    // must be a tree element if it is a tree root
    TreeElement* pRet = static_cast<TreeElement*>(findElement(aNodeID));
    if (0 == pRet)
    {
        TemplateHolder aTemplate = implGetSetElementTemplate(aTree,aRoot);
        vos::ORef<OOptions> xOptions = new OOptions(_aOptions);
        pRet = doCreateAccessRoot(aTree,aTemplate.get(), xOptions);
        implHaveNewElement (aNodeID,pRet);
    }
    return pRet;
}
//-----------------------------------------------------------------------------

UnoInterfaceRef Factory::makeUnoGroupMember(Tree const& aTree, NodeRef const& aNode)
{
    return implToUno(makeGroupMember(aTree,aNode));
}
//-----------------------------------------------------------------------------
NodeElement* Factory::makeGroupMember(Tree const& aTree, NodeRef const& aNode)
{
    OSL_PRECOND( !aTree.isEmpty() , "ERROR: Configuration: Creating an object requires a valid tree");
    if (aTree.isEmpty()) return 0;

    OSL_PRECOND( aNode.isValid() , "ERROR: Configuration: Creating an object requires a valid node");
    OSL_PRECOND( aTree.isValidNode(aNode), "ERROR: Configuration: NodeRef does not match Tree");
    if (!aTree.isValidNode(aNode)) return 0;

    OSL_PRECOND( configuration::isStructuralNode(aTree,aNode), "ERROR: Configuration: Cannot make object for value node");
    OSL_ENSURE(!aTree.isRootNode(aNode),"INTERNAL ERROR: Root of Tree should not be used for a group member object");

    NodeID aNodeID(aTree,aNode);
    NodeElement* pRet = findElement(aNodeID);
    if (0 == pRet)
    {
        TemplateHolder aTemplate = implGetSetElementTemplate(aTree,aNode);

        pRet = doCreateGroupMember(aTree,aNode,aTemplate.get());

        OSL_ENSURE( pRet,"WARNING: New API object could not be created");

        implHaveNewElement(aNodeID,pRet);
    }
    return pRet;
}
//-----------------------------------------------------------------------------

UnoInterfaceRef Factory::makeUnoSetElement(ElementTree const& aElementTree)
{
    UnoInterfaceRef aRet = implToUno(makeSetElement(aElementTree));
    OSL_ENSURE( uno::Reference<XUnoTunnel>::query(aRet).is(),"ERROR: API set element has no UnoTunnel");
    OSL_ENSURE( uno::Reference<XUnoTunnel>::query(aRet).is() &&
                0 != uno::Reference<XUnoTunnel>::query(aRet)->getSomething(doGetElementTunnelID()),
                "ERROR: API set element does not support the right tunnel ID");

    return aRet;
}
//-----------------------------------------------------------------------------

SetElement* Factory::makeSetElement(ElementTree const& aElementTree)
{
    OSL_PRECOND( aElementTree.isValid() , "ERROR: Configuration: Making element from tree requires valid tree");
    if (!aElementTree.isValid()) return 0;

    Tree aTree = aElementTree.getTree();
    OSL_ENSURE(!aTree.isEmpty(),"INTERNAL ERROR: Element Tree has no Tree");

    NodeRef aRoot = aTree.getRootNode();
    OSL_ENSURE(aRoot.isValid(),"INTERNAL ERROR: Tree has no root node");

    OSL_ENSURE( configuration::isStructuralNode(aTree,aRoot), "ERROR: Configuration: Cannot make object for value node");

    NodeID aNodeID(aTree,aRoot);
    // must be a set element if it wraps a ElementTree
    SetElement* pRet = static_cast<SetElement*>( findElement(aNodeID) );
    if (0 == pRet)
    {
        TemplateHolder aTemplate = implGetSetElementTemplate(aTree,aRoot);

        pRet = doCreateSetElement(aElementTree,aTemplate.get());

        implHaveNewElement(aNodeID,pRet);
    }
    return pRet;
}
//-----------------------------------------------------------------------------

SetElement* Factory::findSetElement(configuration::ElementRef const& aElement)
{
    OSL_PRECOND( aElement.isValid() , "ERROR: Configuration: Making element from tree requires valid tree");
    if (!aElement.isValid()) return 0;

    configuration::TreeRef aTree = aElement.getTreeRef();
    OSL_ENSURE(!aTree.isEmpty(),"INTERNAL ERROR: Element Tree has no Tree");

    NodeRef aRoot = aTree.getRootNode();
    OSL_ENSURE(aRoot.isValid(),"INTERNAL ERROR: Tree has no root node");

    NodeID aNodeID(aTree,aRoot);
    // must be a set element if it wraps a ElementTree
    SetElement* pRet = static_cast<SetElement*>( findElement(aNodeID) );

    return pRet;
}
//-----------------------------------------------------------------------------

SetElement* Factory::extractSetElement(UnoAny const& aElement)
{
    using configuration::ElementTreeImpl;
    SetElement* pTunneledImpl = 0;

    Reference< XUnoTunnel > xElementTunnel;
    if ( aElement.hasValue() && (aElement >>= xElementTunnel) )
    {
        OSL_ASSERT( xElementTunnel.is() );

        sal_Int64 nSomething = xElementTunnel->getSomething(doGetElementTunnelID());
        if (0 != nSomething)
        {
            void* pVoid = reinterpret_cast<void*>(nSomething);
            pTunneledImpl = static_cast<SetElement*>(pVoid);
        }
    }
    return pTunneledImpl;
}
//-----------------------------------------------------------------------------

bool Factory::tunnelSetElement(sal_Int64& nSomething, SetElement& rElement, uno::Sequence< sal_Int8 > const& aTunnelID)
{
    if (aTunnelID == doGetElementTunnelID())
    {
        void* pVoid = &rElement;
        nSomething = reinterpret_cast<sal_Int64>(pVoid);

        return true;
    }
    else
        return false;
}

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

ApiTreeImpl const* Factory::findDescendantTreeImpl(configuration::NodeID const& aNode, ApiTreeImpl const* pImpl)
{
    ApiTreeImpl* pRet = 0;
    if (pImpl)
    {
        if ( NodeElement* pElement = pImpl->getFactory().implFind( aNode ) )
            pRet = &pElement->getApiTree();
    }
    return pRet;
}

//-----------------------------------------------------------------------------
    }
}
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qcontactabstractrequest.h"
#include "qcontactabstractrequest_p.h"
#include "qcontactmanager.h"
#include "qcontactmanager_p.h"
#include "qcontactmanagerengine.h"
#include <QCoreApplication>
/*!
 * \class QContactAbstractRequest
 * \brief Allows a client to asynchronously request some functionality of a particular QContactManager.
 *
 * This class provides a mechanism for asynchronous requests to be made of a manager if it supports them.
 */

/*!
 * \enum QContactAbstractRequest::RequestType
 * Enumerates the various possible types of asynchronous requests
 * \value InvalidRequest An invalid request
 * \value ContactFetchRequest A request to fetch a list of contacts
 * \value ContactLocalIdFetchRequest A request to fetch a list of local contact ids
 * \value ContactRemoveRequest A request to remove a list of contacts
 * \value ContactSaveRequest A request to save a list of contacts
 * \value DetailDefinitionFetchRequest A request to fetch a collection of detail definitions
 * \value DetailDefinitionRemoveRequest A request to remove a list of detail definitions
 * \value DetailDefinitionSaveRequest A request to save a list of detail definitions
 * \value RelationshipFetchRequest A request to fetch relationships between contacts
 * \value RelationshipRemoveRequest A request to remove any relationships which match the request criteria
 * \value RelationshipSaveRequest A request to save a list of relationships
 */

/*!
 * \enum QContactAbstractRequest::Status
 * Enumerates the various states that a request may be in at any given time
 * \value Inactive Operation not yet started
 * \value Active Operation started, not yet finished
 * \value Cancelling Operation started then cancelled, not yet finished
 * \value Cancelled Operation is finished due to cancellation
 * \value Finished Operation successfully completed
 */

/*!
 * \fn QContactAbstractRequest::QContactAbstractRequest()
 * Constructs a new, invalid asynchronous request
 */

/*! Constructs a new request from the given request data \a otherd */
QContactAbstractRequest::QContactAbstractRequest(QContactAbstractRequestPrivate* otherd)
    : d_ptr(otherd)
{
}

/*! Cleans up the memory used by this request */
QContactAbstractRequest::~QContactAbstractRequest()
{
    if (d_ptr) {
        QContactManagerEngine *engine = QContactManagerData::engine(d_ptr->m_manager);
        if (engine) {
            engine->requestDestroyed(this);
        }

        delete d_ptr;
    }
}

/*!
 * Returns true if the request is pending, processing or cancelling; otherwise, returns false.
 *
 * \sa status()
 */
bool QContactAbstractRequest::isActive() const
{
    return (d_ptr->m_status == QContactAbstractRequest::Active
            || d_ptr->m_status == QContactAbstractRequest::Cancelling);
}

/*!
 * Returns true if the request is finished or cancelled; otherwise, returns false.
 *
 * \sa status()
 */
bool QContactAbstractRequest::isFinished() const
{
    return (d_ptr->m_status == QContactAbstractRequest::Finished
            || d_ptr->m_status == QContactAbstractRequest::Cancelled);
}

/*! Returns the overall error of the most recent asynchronous operation */
QContactManager::Error QContactAbstractRequest::error() const
{
    return d_ptr->m_error;
}

/*! Returns the list of errors which occurred during the most recent asynchronous operation.  Each individual error in the list corresponds to a result in the result list. */
QList<QContactManager::Error> QContactAbstractRequest::errors() const
{
    return d_ptr->m_errors;
}

/*!
 * Returns the type of this asynchronous request
 */
QContactAbstractRequest::RequestType QContactAbstractRequest::type() const
{
    return d_ptr->type();
}

/*!
 * Returns the current status of the request.
 *
 * \sa isFinished(), isActive()
 */
QContactAbstractRequest::Status QContactAbstractRequest::status() const
{
    return d_ptr->m_status;
}

/*! Returns a pointer to the manager of which this request instance requests operations */
QContactManager* QContactAbstractRequest::manager() const
{
    return d_ptr->m_manager;
}

/*! Sets the manager of which this request instance requests operations to \a manager */
void QContactAbstractRequest::setManager(QContactManager* manager)
{
    d_ptr->m_manager = manager;
}

/*! Attempts to start the request.  Returns false if the request is not in the \c QContactAbstractRequest::Inactive, \c QContactAbstractRequest::Finished or \c QContactAbstractRequest::Cancelled states,
    or if the request was unable to be performed by the manager engine; otherwise returns true. */
bool QContactAbstractRequest::start()
{
    QContactManagerEngine *engine = QContactManagerData::engine(d_ptr->m_manager);
    if (engine) {
        return engine->startRequest(this);
    }

    return false; // unable to start operation; another operation already in progress or no engine.
}

/*! Attempts to cancel the request.  Returns false if the request is not in the \c QContactAbstractRequest::Active state,
    or if the request is unable to be cancelled by the manager engine; otherwise returns true. */
bool QContactAbstractRequest::cancel()
{
    QContactManagerEngine *engine = QContactManagerData::engine(d_ptr->m_manager);
    if (engine) {
        return engine->cancelRequest(this);
    }

    return false; // unable to cancel operation; not in progress or no engine.
}

/*! Blocks until the request has been completed by the manager engine, or until \a msecs milliseconds has elapsed.
    If \a msecs is zero, this function will block indefinitely.
    Returns true if the request was cancelled or completed successfully within the given period, otherwise false. */
bool QContactAbstractRequest::waitForFinished(int msecs)
{
    bool ret = false;
    QContactManagerEngine *engine = QContactManagerData::engine(d_ptr->m_manager);
    if (engine) {
        ret = engine->waitForRequestFinished(this, msecs);
        QCoreApplication::processEvents();
    }
    return ret;
}

/*! Blocks until the manager engine signals that more partial results are available for the request, or until \a msecs milliseconds has elapsed.
    If \a msecs is zero, this function will block indefinitely.
    Returns true if the request was cancelled or more partial results were made available within the given period, otherwise false. */
bool QContactAbstractRequest::waitForProgress(int msecs)
{
    bool ret = false;
    QContactManagerEngine *engine = QContactManagerData::engine(d_ptr->m_manager);
    if (engine) {
        ret = engine->waitForRequestProgress(this, msecs);
        QCoreApplication::processEvents();
    }
    return ret;
}
<commit_msg>Revert "QContactAbstractRequest() should not check the request status when doing the start() cancel() wait() operations, they are not protected by mutex"<commit_after>/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qcontactabstractrequest.h"
#include "qcontactabstractrequest_p.h"
#include "qcontactmanager.h"
#include "qcontactmanager_p.h"
#include "qcontactmanagerengine.h"
#include <QCoreApplication>
/*!
 * \class QContactAbstractRequest
 * \brief Allows a client to asynchronously request some functionality of a particular QContactManager.
 *
 * This class provides a mechanism for asynchronous requests to be made of a manager if it supports them.
 */

/*!
 * \enum QContactAbstractRequest::RequestType
 * Enumerates the various possible types of asynchronous requests
 * \value InvalidRequest An invalid request
 * \value ContactFetchRequest A request to fetch a list of contacts
 * \value ContactLocalIdFetchRequest A request to fetch a list of local contact ids
 * \value ContactRemoveRequest A request to remove a list of contacts
 * \value ContactSaveRequest A request to save a list of contacts
 * \value DetailDefinitionFetchRequest A request to fetch a collection of detail definitions
 * \value DetailDefinitionRemoveRequest A request to remove a list of detail definitions
 * \value DetailDefinitionSaveRequest A request to save a list of detail definitions
 * \value RelationshipFetchRequest A request to fetch relationships between contacts
 * \value RelationshipRemoveRequest A request to remove any relationships which match the request criteria
 * \value RelationshipSaveRequest A request to save a list of relationships
 */

/*!
 * \enum QContactAbstractRequest::Status
 * Enumerates the various states that a request may be in at any given time
 * \value Inactive Operation not yet started
 * \value Active Operation started, not yet finished
 * \value Cancelling Operation started then cancelled, not yet finished
 * \value Cancelled Operation is finished due to cancellation
 * \value Finished Operation successfully completed
 */

/*!
 * \fn QContactAbstractRequest::QContactAbstractRequest()
 * Constructs a new, invalid asynchronous request
 */

/*! Constructs a new request from the given request data \a otherd */
QContactAbstractRequest::QContactAbstractRequest(QContactAbstractRequestPrivate* otherd)
    : d_ptr(otherd)
{
}

/*! Cleans up the memory used by this request */
QContactAbstractRequest::~QContactAbstractRequest()
{
    if (d_ptr) {
        QContactManagerEngine *engine = QContactManagerData::engine(d_ptr->m_manager);
        if (engine) {
            engine->requestDestroyed(this);
        }

        delete d_ptr;
    }
}

/*!
 * Returns true if the request is pending, processing or cancelling; otherwise, returns false.
 *
 * \sa status()
 */
bool QContactAbstractRequest::isActive() const
{
    return (d_ptr->m_status == QContactAbstractRequest::Active
            || d_ptr->m_status == QContactAbstractRequest::Cancelling);
}

/*!
 * Returns true if the request is finished or cancelled; otherwise, returns false.
 *
 * \sa status()
 */
bool QContactAbstractRequest::isFinished() const
{
    return (d_ptr->m_status == QContactAbstractRequest::Finished
            || d_ptr->m_status == QContactAbstractRequest::Cancelled);
}

/*! Returns the overall error of the most recent asynchronous operation */
QContactManager::Error QContactAbstractRequest::error() const
{
    return d_ptr->m_error;
}

/*! Returns the list of errors which occurred during the most recent asynchronous operation.  Each individual error in the list corresponds to a result in the result list. */
QList<QContactManager::Error> QContactAbstractRequest::errors() const
{
    return d_ptr->m_errors;
}

/*!
 * Returns the type of this asynchronous request
 */
QContactAbstractRequest::RequestType QContactAbstractRequest::type() const
{
    return d_ptr->type();
}

/*!
 * Returns the current status of the request.
 *
 * \sa isFinished(), isActive()
 */
QContactAbstractRequest::Status QContactAbstractRequest::status() const
{
    return d_ptr->m_status;
}

/*! Returns a pointer to the manager of which this request instance requests operations */
QContactManager* QContactAbstractRequest::manager() const
{
    return d_ptr->m_manager;
}

/*! Sets the manager of which this request instance requests operations to \a manager */
void QContactAbstractRequest::setManager(QContactManager* manager)
{
    d_ptr->m_manager = manager;
}

/*! Attempts to start the request.  Returns false if the request is not in the \c QContactAbstractRequest::Inactive, \c QContactAbstractRequest::Finished or \c QContactAbstractRequest::Cancelled states,
    or if the request was unable to be performed by the manager engine; otherwise returns true. */
bool QContactAbstractRequest::start()
{
    QContactManagerEngine *engine = QContactManagerData::engine(d_ptr->m_manager);
    if (engine && !isActive()) {
        return engine->startRequest(this);
    }

    return false; // unable to start operation; another operation already in progress or no engine.
}

/*! Attempts to cancel the request.  Returns false if the request is not in the \c QContactAbstractRequest::Active state,
    or if the request is unable to be cancelled by the manager engine; otherwise returns true. */
bool QContactAbstractRequest::cancel()
{
    QContactManagerEngine *engine = QContactManagerData::engine(d_ptr->m_manager);
    if (engine && status() == QContactAbstractRequest::Active) {
        return engine->cancelRequest(this);
    }

    return false; // unable to cancel operation; not in progress or no engine.
}

/*! Blocks until the request has been completed by the manager engine, or until \a msecs milliseconds has elapsed.
    If \a msecs is zero, this function will block indefinitely.
    Returns true if the request was cancelled or completed successfully within the given period, otherwise false. */
bool QContactAbstractRequest::waitForFinished(int msecs)
{
    bool ret = false;
    QContactManagerEngine *engine = QContactManagerData::engine(d_ptr->m_manager);
    if (engine && isActive()) {
        ret = engine->waitForRequestFinished(this, msecs);
        QCoreApplication::processEvents();
    }
    return ret;
}

/*! Blocks until the manager engine signals that more partial results are available for the request, or until \a msecs milliseconds has elapsed.
    If \a msecs is zero, this function will block indefinitely.
    Returns true if the request was cancelled or more partial results were made available within the given period, otherwise false. */
bool QContactAbstractRequest::waitForProgress(int msecs)
{
    bool ret = false;
    QContactManagerEngine *engine = QContactManagerData::engine(d_ptr->m_manager);
    if (engine && isActive()) {
        ret = engine->waitForRequestProgress(this, msecs);
        QCoreApplication::processEvents();
    }
    return ret;
}
<|endoftext|>


<commit_before>/*
 * gui_render_backend.cpp
 *
 * Copyright (C) 2021 by Universitaet Stuttgart (VIS).
 * Alle Rechte vorbehalten.
 */

#include "gui_render_backend.h"
#include "mmcore/utility/log/Log.h"

#ifdef WITH_GL
#include "glad/glx.h"
#include "imgui_impl_opengl3.h"
#endif

using namespace megamol::gui;

gui_render_backend::gui_render_backend()
        : initialized_backend(GUIRenderBackend::NONE)
        , sw_window({1280, 720, 0, 0})
        , sw_monitor({1920, 1080}) {}

gui_render_backend::~gui_render_backend() {
#ifdef WITH_GL
    this->ogl_fbo.reset();
#endif // WITH_GL
    this->cpu_fbo.reset();
}

bool megamol::gui::gui_render_backend::CheckPrerequisites(GUIRenderBackend backend) {

    switch (backend) {
    case (GUIRenderBackend::OPEN_GL): {
#ifdef WITH_GL
        bool prerequisities_given = true;

#ifdef _WIN32 // Windows
        HDC ogl_current_display = ::wglGetCurrentDC();
        HGLRC ogl_current_context = ::wglGetCurrentContext();
        if (ogl_current_display == nullptr) {
            megamol::core::utility::log::Log::DefaultLog.WriteError(
                "[GUI] There is no OpenGL rendering context available.");
            prerequisities_given = false;
        }
        if (ogl_current_context == nullptr) {
            megamol::core::utility::log::Log::DefaultLog.WriteError(
                "[GUI] There is no current OpenGL rendering context available from the calling thread.");
            prerequisities_given = false;
        }
#else
        // LINUX
        /// XXX The following throws segfault if OpenGL is not loaded yet:
        // Display* gl_current_display = ::glXGetCurrentDisplay();
        // GLXContext ogl_current_context = ::glXGetCurrentContext();
        /// XXX Is there a better way to check existing OpenGL context?
        if (glXGetCurrentDisplay == nullptr) {
            megamol::core::utility::log::Log::DefaultLog.WriteError(
                "[GUI] There is no OpenGL rendering context available.");
            prerequisities_given = false;
        }
        if (glXGetCurrentContext == nullptr) {
            megamol::core::utility::log::Log::DefaultLog.WriteError(
                "[GUI] There is no current OpenGL rendering context available from the calling thread.");
            prerequisities_given = false;
        }
#endif // _WIN32

        if (!prerequisities_given) {
            megamol::core::utility::log::Log::DefaultLog.WriteError(
                "[GUI] Missing prerequisities to initialize render backend OpenGL. [%s, %s, line %d]", __FILE__,
                __FUNCTION__, __LINE__);
            return false;
        }
#else
        megamol::core::utility::log::Log::DefaultLog.WriteError("[GUI] Render backend OpenGL is not available.");
        return false;
#endif // WITH_GL
    } break;
    case (GUIRenderBackend::CPU): {
        /// nothing to check for CPU rendering ...
    } break;
    default: {
        megamol::core::utility::log::Log::DefaultLog.WriteError(
            "[GUI] Unknown render backend... [%s, %s, line %d]\n", __FILE__, __FUNCTION__, __LINE__);
        return false;
    } break;
    }

    return true;
}

bool gui_render_backend::Init(GUIRenderBackend backend) {

    if (this->IsBackendInitialized()) {
        megamol::core::utility::log::Log::DefaultLog.WriteError(
            "[GUI] Render backend is already initialized. [%s, %s, line %d]\n", __FILE__, __FUNCTION__, __LINE__);
        return false;
    }

    switch (backend) {
    case (GUIRenderBackend::OPEN_GL): {
#ifdef WITH_GL
        if (ImGui_ImplOpenGL3_Init(nullptr)) { // "#version 130"
            megamol::core::utility::log::Log::DefaultLog.WriteInfo("[GUI] Created ImGui render backend for Open GL.");
        } else {
            megamol::core::utility::log::Log::DefaultLog.WriteError(
                "[GUI] Unable to initialize OpenGL render backend for ImGui. [%s, %s, line %d]\n", __FILE__,
                __FUNCTION__, __LINE__);
            return false;
        }
#endif
    } break;
    case (GUIRenderBackend::CPU): {
        if (ImGui_ImplGeneric_Init(&this->sw_window)) { /// XXX How is sw_window used?
            imgui_sw::bind_imgui_painting();
            megamol::core::utility::log::Log::DefaultLog.WriteInfo("[GUI] Created ImGui render Backend for CPU.");
        } else {
            megamol::core::utility::log::Log::DefaultLog.WriteError(
                "[GUI] Unable to initialize CPU render backend for ImGui. [%s, %s, line %d]\n", __FILE__, __FUNCTION__,
                __LINE__);
            return false;
        }
    } break;
    default: {
        megamol::core::utility::log::Log::DefaultLog.WriteError(
            "[GUI] Unknown render backend... [%s, %s, line %d]\n", __FILE__, __FUNCTION__, __LINE__);
        return false;
    } break;
    }

    this->initialized_backend = backend;
    return true;
}

void gui_render_backend::NewFrame(glm::vec2 framebuffer_size, glm::vec2 window_size) {

    switch (this->initialized_backend) {
    case (GUIRenderBackend::OPEN_GL): {
#ifdef WITH_GL
        ImGui_ImplOpenGL3_NewFrame();
#endif
    } break;
    case (GUIRenderBackend::CPU): {
        this->sw_window.width = static_cast<int>(window_size.x);
        this->sw_window.height = static_cast<int>(window_size.y);
        this->sw_window.x = 0;
        this->sw_window.y = 0;
        this->sw_monitor.res_x = static_cast<int>(framebuffer_size.x);
        this->sw_monitor.res_y = static_cast<int>(framebuffer_size.y);
        ImGui_ImplGeneric_NewFrame(&this->sw_window, &this->sw_monitor);
    } break;
    default: {
        megamol::core::utility::log::Log::DefaultLog.WriteError(
            "[GUI] Unknown render backend... [%s, %s, line %d]\n", __FILE__, __FUNCTION__, __LINE__);
    } break;
    }
}

bool gui_render_backend::EnableRendering(unsigned int width, unsigned int height) {

    switch (this->initialized_backend) {
    case (GUIRenderBackend::OPEN_GL): {
#ifdef WITH_GL
        auto width_i = static_cast<int>(width);
        auto height_i = static_cast<int>(height);
        bool create_fbo = false;
        if (this->ogl_fbo == nullptr) {
            create_fbo = true;
        } else if (((this->ogl_fbo->getWidth() != width_i) || (this->ogl_fbo->getHeight() != height_i)) &&
                   (width_i != 0) && (height_i != 0)) {
            create_fbo = true;
        }
        if (create_fbo) {
            try {
                glBindFramebuffer(GL_FRAMEBUFFER, 0);
                this->ogl_fbo.reset();
                this->ogl_fbo = std::make_shared<glowl::FramebufferObject>(width_i, height_i);
                this->ogl_fbo->createColorAttachment(GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE);
                // TODO: check completness and throw if not?
            } catch (glowl::FramebufferObjectException const& exc) {
                megamol::core::utility::log::Log::DefaultLog.WriteError(
                    "[GUI] Unable to create framebuffer object: %s [%s, %s, line %d]\n", exc.what(), __FILE__,
                    __FUNCTION__, __LINE__);
            }
        }
        if (this->ogl_fbo == nullptr) {
            megamol::core::utility::log::Log::DefaultLog.WriteError(
                "[GUI] Unable to create valid FBO. [%s, %s, line %d]\n", __FILE__, __FUNCTION__, __LINE__);
            return false;
        }

        this->ogl_fbo->bind();
        // glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
        // glClearDepth(1.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glViewport(0, 0, width, height);
        glEnable(GL_DEPTH_TEST);
        return true;
#endif
    } break;
    case (GUIRenderBackend::CPU): {
        bool create_fbo = false;
        if (this->cpu_fbo == nullptr) {
            create_fbo = true;
        } else if (((this->cpu_fbo->getWidth() != width) || (this->cpu_fbo->getHeight() != height)) && (width != 0) &&
                   (height != 0)) {
            create_fbo = true;
        }
        if (create_fbo) {
            this->cpu_fbo.reset();
            this->cpu_fbo = std::make_shared<megamol::core::view::CPUFramebuffer>();
            if (this->cpu_fbo == nullptr) {
                megamol::core::utility::log::Log::DefaultLog.WriteError(
                    "[GUI] Unable to create valid FBO. [%s, %s, line %d]\n", __FILE__, __FUNCTION__, __LINE__);
                return false;
            }
            this->cpu_fbo->colorBuffer = std::vector<uint32_t>(width * height, 0);
            this->cpu_fbo->width = width;
            this->cpu_fbo->height = height;
        }
        return true;
    } break;
    default: {
        megamol::core::utility::log::Log::DefaultLog.WriteError(
            "[GUI] Unknown render backend... [%s, %s, line %d]\n", __FILE__, __FUNCTION__, __LINE__);
    } break;
    }
    return false;
}

bool gui_render_backend::Render(ImDrawData* draw_data) {

    switch (this->initialized_backend) {
    case (GUIRenderBackend::OPEN_GL): {
#ifdef WITH_GL
        ImGui_ImplOpenGL3_RenderDrawData(draw_data);
        glBindFramebuffer(GL_FRAMEBUFFER, 0);
#endif
    } break;
    case (GUIRenderBackend::CPU): {
        std::fill_n(this->cpu_fbo->colorBuffer.data(), this->cpu_fbo->colorBuffer.size(), 0x19191919u);
        imgui_sw::paint_imgui(this->cpu_fbo->colorBuffer.data(), static_cast<int>(this->cpu_fbo->getWidth()),
            static_cast<int>(this->cpu_fbo->getHeight()));
    } break;
    default: {
        megamol::core::utility::log::Log::DefaultLog.WriteError(
            "[GUI] Unknown render backend... [%s, %s, line %d]\n", __FILE__, __FUNCTION__, __LINE__);
    } break;
    }
}

bool megamol::gui::gui_render_backend::ShutdownBackend() {

    switch (this->initialized_backend) {
    case (GUIRenderBackend::OPEN_GL): {
#ifdef WITH_GL
        ImGui_ImplOpenGL3_Shutdown();
#endif
    } break;
    case (GUIRenderBackend::CPU): {
        ImGui_ImplGeneric_Shutdown();
    } break;
    default:
        megamol::core::utility::log::Log::DefaultLog.WriteError(
            "[GUI] Unknown render backend... [%s, %s, line %d]\n", __FILE__, __FUNCTION__, __LINE__);
        break;
    }
    this->initialized_backend = GUIRenderBackend::NONE;
    return true;
}

bool gui_render_backend::CreateFont() {

    switch (this->initialized_backend) {
    case (GUIRenderBackend::NONE): {
        megamol::core::utility::log::Log::DefaultLog.WriteError(
            "[GUI] Fonts can only be loaded after render backend was initialized. [%s, %s, line %d]\n", __FILE__,
            __FUNCTION__, __LINE__);
    } break;
    case (GUIRenderBackend::OPEN_GL): {
#ifdef WITH_GL
        return ImGui_ImplOpenGL3_CreateFontsTexture();
#endif
    } break;
    case (GUIRenderBackend::CPU): {
        megamol::core::utility::log::Log::DefaultLog.WriteError(
            "[GUI] CPU rendering does not support painting with any other texture than the default font texture. [%s, "
            "%s, line %d]\n",
            __FILE__, __FUNCTION__, __LINE__);
    } break;
    default: {
        megamol::core::utility::log::Log::DefaultLog.WriteError(
            "[GUI] Unknown render backend... [%s, %s, line %d]\n", __FILE__, __FUNCTION__, __LINE__);
    } break;
    }
    return false;
}
<commit_msg>windows compile fix<commit_after>/*
 * gui_render_backend.cpp
 *
 * Copyright (C) 2021 by Universitaet Stuttgart (VIS).
 * Alle Rechte vorbehalten.
 */

#include "gui_render_backend.h"
#include "mmcore/utility/log/Log.h"

#ifdef WITH_GL

#ifdef _WIN32 // Windows
#include "glad/wgl.h"
#else // LINUX
#include "glad/glx.h"
#endif // _WIN32

#include "imgui_impl_opengl3.h"
#endif

using namespace megamol::gui;

gui_render_backend::gui_render_backend()
        : initialized_backend(GUIRenderBackend::NONE)
        , sw_window({1280, 720, 0, 0})
        , sw_monitor({1920, 1080}) {}

gui_render_backend::~gui_render_backend() {
#ifdef WITH_GL
    this->ogl_fbo.reset();
#endif // WITH_GL
    this->cpu_fbo.reset();
}

bool megamol::gui::gui_render_backend::CheckPrerequisites(GUIRenderBackend backend) {

    switch (backend) {
    case (GUIRenderBackend::OPEN_GL): {
#ifdef WITH_GL
        bool prerequisities_given = true;

#ifdef _WIN32 // Windows
        HDC ogl_current_display = ::wglGetCurrentDC();
        HGLRC ogl_current_context = ::wglGetCurrentContext();
        if (ogl_current_display == nullptr) {
            megamol::core::utility::log::Log::DefaultLog.WriteError(
                "[GUI] There is no OpenGL rendering context available.");
            prerequisities_given = false;
        }
        if (ogl_current_context == nullptr) {
            megamol::core::utility::log::Log::DefaultLog.WriteError(
                "[GUI] There is no current OpenGL rendering context available from the calling thread.");
            prerequisities_given = false;
        }
#else
        // LINUX
        /// XXX The following throws segfault if OpenGL is not loaded yet:
        // Display* gl_current_display = ::glXGetCurrentDisplay();
        // GLXContext ogl_current_context = ::glXGetCurrentContext();
        /// XXX Is there a better way to check existing OpenGL context?
        if (glXGetCurrentDisplay == nullptr) {
            megamol::core::utility::log::Log::DefaultLog.WriteError(
                "[GUI] There is no OpenGL rendering context available.");
            prerequisities_given = false;
        }
        if (glXGetCurrentContext == nullptr) {
            megamol::core::utility::log::Log::DefaultLog.WriteError(
                "[GUI] There is no current OpenGL rendering context available from the calling thread.");
            prerequisities_given = false;
        }
#endif // _WIN32

        if (!prerequisities_given) {
            megamol::core::utility::log::Log::DefaultLog.WriteError(
                "[GUI] Missing prerequisities to initialize render backend OpenGL. [%s, %s, line %d]", __FILE__,
                __FUNCTION__, __LINE__);
            return false;
        }
#else
        megamol::core::utility::log::Log::DefaultLog.WriteError("[GUI] Render backend OpenGL is not available.");
        return false;
#endif // WITH_GL
    } break;
    case (GUIRenderBackend::CPU): {
        /// nothing to check for CPU rendering ...
    } break;
    default: {
        megamol::core::utility::log::Log::DefaultLog.WriteError(
            "[GUI] Unknown render backend... [%s, %s, line %d]\n", __FILE__, __FUNCTION__, __LINE__);
        return false;
    } break;
    }

    return true;
}

bool gui_render_backend::Init(GUIRenderBackend backend) {

    if (this->IsBackendInitialized()) {
        megamol::core::utility::log::Log::DefaultLog.WriteError(
            "[GUI] Render backend is already initialized. [%s, %s, line %d]\n", __FILE__, __FUNCTION__, __LINE__);
        return false;
    }

    switch (backend) {
    case (GUIRenderBackend::OPEN_GL): {
#ifdef WITH_GL
        if (ImGui_ImplOpenGL3_Init(nullptr)) { // "#version 130"
            megamol::core::utility::log::Log::DefaultLog.WriteInfo("[GUI] Created ImGui render backend for Open GL.");
        } else {
            megamol::core::utility::log::Log::DefaultLog.WriteError(
                "[GUI] Unable to initialize OpenGL render backend for ImGui. [%s, %s, line %d]\n", __FILE__,
                __FUNCTION__, __LINE__);
            return false;
        }
#endif
    } break;
    case (GUIRenderBackend::CPU): {
        if (ImGui_ImplGeneric_Init(&this->sw_window)) { /// XXX How is sw_window used?
            imgui_sw::bind_imgui_painting();
            megamol::core::utility::log::Log::DefaultLog.WriteInfo("[GUI] Created ImGui render Backend for CPU.");
        } else {
            megamol::core::utility::log::Log::DefaultLog.WriteError(
                "[GUI] Unable to initialize CPU render backend for ImGui. [%s, %s, line %d]\n", __FILE__, __FUNCTION__,
                __LINE__);
            return false;
        }
    } break;
    default: {
        megamol::core::utility::log::Log::DefaultLog.WriteError(
            "[GUI] Unknown render backend... [%s, %s, line %d]\n", __FILE__, __FUNCTION__, __LINE__);
        return false;
    } break;
    }

    this->initialized_backend = backend;
    return true;
}

void gui_render_backend::NewFrame(glm::vec2 framebuffer_size, glm::vec2 window_size) {

    switch (this->initialized_backend) {
    case (GUIRenderBackend::OPEN_GL): {
#ifdef WITH_GL
        ImGui_ImplOpenGL3_NewFrame();
#endif
    } break;
    case (GUIRenderBackend::CPU): {
        this->sw_window.width = static_cast<int>(window_size.x);
        this->sw_window.height = static_cast<int>(window_size.y);
        this->sw_window.x = 0;
        this->sw_window.y = 0;
        this->sw_monitor.res_x = static_cast<int>(framebuffer_size.x);
        this->sw_monitor.res_y = static_cast<int>(framebuffer_size.y);
        ImGui_ImplGeneric_NewFrame(&this->sw_window, &this->sw_monitor);
    } break;
    default: {
        megamol::core::utility::log::Log::DefaultLog.WriteError(
            "[GUI] Unknown render backend... [%s, %s, line %d]\n", __FILE__, __FUNCTION__, __LINE__);
    } break;
    }
}

bool gui_render_backend::EnableRendering(unsigned int width, unsigned int height) {

    switch (this->initialized_backend) {
    case (GUIRenderBackend::OPEN_GL): {
#ifdef WITH_GL
        auto width_i = static_cast<int>(width);
        auto height_i = static_cast<int>(height);
        bool create_fbo = false;
        if (this->ogl_fbo == nullptr) {
            create_fbo = true;
        } else if (((this->ogl_fbo->getWidth() != width_i) || (this->ogl_fbo->getHeight() != height_i)) &&
                   (width_i != 0) && (height_i != 0)) {
            create_fbo = true;
        }
        if (create_fbo) {
            try {
                glBindFramebuffer(GL_FRAMEBUFFER, 0);
                this->ogl_fbo.reset();
                this->ogl_fbo = std::make_shared<glowl::FramebufferObject>(width_i, height_i);
                this->ogl_fbo->createColorAttachment(GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE);
                // TODO: check completness and throw if not?
            } catch (glowl::FramebufferObjectException const& exc) {
                megamol::core::utility::log::Log::DefaultLog.WriteError(
                    "[GUI] Unable to create framebuffer object: %s [%s, %s, line %d]\n", exc.what(), __FILE__,
                    __FUNCTION__, __LINE__);
            }
        }
        if (this->ogl_fbo == nullptr) {
            megamol::core::utility::log::Log::DefaultLog.WriteError(
                "[GUI] Unable to create valid FBO. [%s, %s, line %d]\n", __FILE__, __FUNCTION__, __LINE__);
            return false;
        }

        this->ogl_fbo->bind();
        // glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
        // glClearDepth(1.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glViewport(0, 0, width, height);
        glEnable(GL_DEPTH_TEST);
        return true;
#endif
    } break;
    case (GUIRenderBackend::CPU): {
        bool create_fbo = false;
        if (this->cpu_fbo == nullptr) {
            create_fbo = true;
        } else if (((this->cpu_fbo->getWidth() != width) || (this->cpu_fbo->getHeight() != height)) && (width != 0) &&
                   (height != 0)) {
            create_fbo = true;
        }
        if (create_fbo) {
            this->cpu_fbo.reset();
            this->cpu_fbo = std::make_shared<megamol::core::view::CPUFramebuffer>();
            if (this->cpu_fbo == nullptr) {
                megamol::core::utility::log::Log::DefaultLog.WriteError(
                    "[GUI] Unable to create valid FBO. [%s, %s, line %d]\n", __FILE__, __FUNCTION__, __LINE__);
                return false;
            }
            this->cpu_fbo->colorBuffer = std::vector<uint32_t>(width * height, 0);
            this->cpu_fbo->width = width;
            this->cpu_fbo->height = height;
        }
        return true;
    } break;
    default: {
        megamol::core::utility::log::Log::DefaultLog.WriteError(
            "[GUI] Unknown render backend... [%s, %s, line %d]\n", __FILE__, __FUNCTION__, __LINE__);
    } break;
    }
    return false;
}

bool gui_render_backend::Render(ImDrawData* draw_data) {

    switch (this->initialized_backend) {
    case (GUIRenderBackend::OPEN_GL): {
#ifdef WITH_GL
        ImGui_ImplOpenGL3_RenderDrawData(draw_data);
        glBindFramebuffer(GL_FRAMEBUFFER, 0);
#endif
    } break;
    case (GUIRenderBackend::CPU): {
        std::fill_n(this->cpu_fbo->colorBuffer.data(), this->cpu_fbo->colorBuffer.size(), 0x19191919u);
        imgui_sw::paint_imgui(this->cpu_fbo->colorBuffer.data(), static_cast<int>(this->cpu_fbo->getWidth()),
            static_cast<int>(this->cpu_fbo->getHeight()));
    } break;
    default: {
        megamol::core::utility::log::Log::DefaultLog.WriteError(
            "[GUI] Unknown render backend... [%s, %s, line %d]\n", __FILE__, __FUNCTION__, __LINE__);
    } break;
    }
}

bool megamol::gui::gui_render_backend::ShutdownBackend() {

    switch (this->initialized_backend) {
    case (GUIRenderBackend::OPEN_GL): {
#ifdef WITH_GL
        ImGui_ImplOpenGL3_Shutdown();
#endif
    } break;
    case (GUIRenderBackend::CPU): {
        ImGui_ImplGeneric_Shutdown();
    } break;
    default:
        megamol::core::utility::log::Log::DefaultLog.WriteError(
            "[GUI] Unknown render backend... [%s, %s, line %d]\n", __FILE__, __FUNCTION__, __LINE__);
        break;
    }
    this->initialized_backend = GUIRenderBackend::NONE;
    return true;
}

bool gui_render_backend::CreateFont() {

    switch (this->initialized_backend) {
    case (GUIRenderBackend::NONE): {
        megamol::core::utility::log::Log::DefaultLog.WriteError(
            "[GUI] Fonts can only be loaded after render backend was initialized. [%s, %s, line %d]\n", __FILE__,
            __FUNCTION__, __LINE__);
    } break;
    case (GUIRenderBackend::OPEN_GL): {
#ifdef WITH_GL
        return ImGui_ImplOpenGL3_CreateFontsTexture();
#endif
    } break;
    case (GUIRenderBackend::CPU): {
        megamol::core::utility::log::Log::DefaultLog.WriteError(
            "[GUI] CPU rendering does not support painting with any other texture than the default font texture. [%s, "
            "%s, line %d]\n",
            __FILE__, __FUNCTION__, __LINE__);
    } break;
    default: {
        megamol::core::utility::log::Log::DefaultLog.WriteError(
            "[GUI] Unknown render backend... [%s, %s, line %d]\n", __FILE__, __FUNCTION__, __LINE__);
    } break;
    }
    return false;
}
<|endoftext|>


<commit_before>// This file is part of the dune-gdt project:
//   http://users.dune-project.org/projects/dune-gdt
// Copyright holders: Felix Albrecht
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_GDT_OPERATOR_DARCY_HH
#define DUNE_GDT_OPERATOR_DARCY_HH

#include <limits>

#include <dune/stuff/functions/interfaces.hh>
#include <dune/stuff/la/container.hh>
#include <dune/stuff/la/solver.hh>

#include <dune/geometry/quadraturerules.hh>

#include <dune/gdt/space/continuouslagrange/fem.hh>
#include <dune/gdt/playground/space/raviartthomas/pdelab.hh>
#include <dune/gdt/discretefunction/default.hh>

#include "interfaces.hh"

namespace Dune {
namespace GDT {
namespace Operator {

// forward, to be used in the traits
template <class GridViewImp, class FunctionImp>
class DarcyReconstruction;

template <class GridViewImp, class FunctionImp>
class DarcyReconstructionTraits
{
  static_assert(std::is_base_of<Stuff::IsLocalizableFunction, FunctionImp>::value,
                "FunctionImp has to be derived from Stuff::IsLocalizableFunction!");
  static_assert(std::is_same<typename GridViewImp::ctype, typename FunctionImp::DomainFieldType>::value,
                "Types do not match!");
  static_assert(GridViewImp::dimension == FunctionImp::dimDomain, "Dimensions do not match!");

public:
  typedef DarcyReconstruction<GridViewImp, FunctionImp> derived_type;
  typedef GridViewImp GridViewType;
  typedef typename FunctionImp::RangeFieldType FieldType;
}; // class DarcyReconstructionTraits

/**
  * \note Only works for scalar valued function atm.
  **/
template <class GridViewImp, class FunctionImp>
class DarcyReconstruction : public OperatorInterface<DarcyReconstructionTraits<GridViewImp, FunctionImp>>
{
public:
  typedef DarcyReconstructionTraits<GridViewImp, FunctionImp> Traits;
  typedef typename Traits::GridViewType GridViewType;
  typedef typename Traits::FieldType FieldType;

  typedef typename GridViewType::template Codim<0>::Entity EntityType;
  typedef typename GridViewType::ctype DomainFieldType;
  static const unsigned int dimDomain = GridViewType::dimension;

  DarcyReconstruction(const GridViewType& grid_view, const FunctionImp& function)
    : grid_view_(grid_view)
    , function_(function)
  {
  }

  template <class E, class D, int d, class R, int r, int rC, class T, class V>
  void apply(const Stuff::LocalizableFunctionInterface<E, D, d, R, r, rC>& /*source*/,
             DiscreteFunction<SpaceInterface<T>, V>& /*range*/) const
  {
    static_assert((Dune::AlwaysFalse<E>::value), "Not implemented for this combination of source and range!");
  }

  /**
   * \brief Does an L2 projection of '- function * \gradient source' onto range.
   */
  template <class GP, int p, class V>
  void apply(const Stuff::LocalizableFunctionInterface<EntityType, DomainFieldType, dimDomain, FieldType, 1, 1>& source,
             DiscreteFunction<ContinuousLagrangeSpace::FemWrapper<GP, p, FieldType, dimDomain, 1>, V>& range) const
  {
    apply_l2_projection_to_(source, range);
  }

  template <class GP, int p, class V>
  void apply(const Stuff::LocalizableFunctionInterface<EntityType, DomainFieldType, dimDomain, FieldType, 1, 1>& source,
             DiscreteFunction<RaviartThomasSpace::PdelabBased<GP, p, FieldType, dimDomain, 1>, V>& range) const
  {
    apply_l2_projection_to_(source, range);
  }

private:
  template <class SourceType, class RangeType>
  void apply_l2_projection_to_(const SourceType& source, RangeType& range) const
  {
#if HAVE_EIGEN
    typedef Stuff::LA::EigenRowMajorSparseMatrix<FieldType> MatrixType;
    typedef Stuff::LA::EigenDenseVector<FieldType> VectorType;
#elif HAVE_DUNE_ISTL
    typedef Stuff::LA::IstlRowMajorSparseMatrix<FieldType> MatrixType;
    typedef Stuff::LA::IstlDenseVector<FieldType> VectorType;
#else
    typedef Stuff::LA::CommonDenseMatrix<FieldType> MatrixType;
    typedef Stuff::LA::CommonDenseVector<FieldType> VectorType;
#endif
    MatrixType lhs(
        range.space().mapper().size(), range.space().mapper().size(), range.space().compute_volume_pattern());
    VectorType rhs(range.space().mapper().size());

    // walk the grid
    const auto entity_it_end = grid_view_.template end<0>();
    for (auto entity_it = grid_view_.template begin<0>(); entity_it != entity_it_end; ++entity_it) {
      const auto& entity        = *entity_it;
      const auto local_function = function_.local_function(entity);
      const auto local_source   = source.local_function(entity);
      const auto basis          = range.space().base_function_set(entity);
      // do a volume quadrature
      const size_t integrand_order =
          std::max(local_function->order() + size_t(local_source->order() - 1), basis.order()) + basis.order();
      assert(integrand_order < std::numeric_limits<int>::max());
      const auto& quadrature       = QuadratureRules<DomainFieldType, dimDomain>::rule(entity.type(), int(integrand_order));
      const auto quadrature_it_end = quadrature.end();
      for (auto quadrature_it = quadrature.begin(); quadrature_it != quadrature_it_end; ++quadrature_it) {
        const auto xx                             = quadrature_it->position();
        const FieldType quadrature_weight         = quadrature_it->weight();
        const DomainFieldType integration_element = entity.geometry().integrationElement(xx);
        const auto function_value                 = local_function->evaluate(xx);
        const auto source_gradient                = local_source->jacobian(xx);
        const auto basis_value = basis.evaluate(xx);
        for (size_t ii = 0; ii < basis.size(); ++ii) {
          const size_t global_ii = range.space().mapper().mapToGlobal(entity, ii);
          rhs.add_to_entry(global_ii,
                           integration_element * quadrature_weight * -1.0 * function_value
                               * (source_gradient[0] * basis_value[ii]));
          for (size_t jj = 0; jj < basis.size(); ++jj) {
            const size_t global_jj = range.space().mapper().mapToGlobal(entity, jj);
            lhs.add_to_entry(
                global_ii, global_jj, integration_element * quadrature_weight * (basis_value[ii] * basis_value[jj]));
          }
        }
      } // do a volume quadrature
    } // walk the grid

    // solve
    Stuff::LA::Solver<MatrixType>(lhs).apply(rhs, range.vector());
  } // ... apply_l2_projection(...)

  const GridViewType& grid_view_;
  const FunctionImp& function_;
}; // class DarcyReconstruction

} // namespace Operator
} // namespace GDT
} // namespace Dune

#endif // DUNE_GDT_OPERATOR_DARCY_HH
<commit_msg>[operator.darcy] compute locally for raviarthomas range<commit_after>// This file is part of the dune-gdt project:
//   http://users.dune-project.org/projects/dune-gdt
// Copyright holders: Felix Albrecht
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_GDT_OPERATOR_DARCY_HH
#define DUNE_GDT_OPERATOR_DARCY_HH

#include <limits>

#include <dune/stuff/functions/interfaces.hh>
#include <dune/stuff/la/container.hh>
#include <dune/stuff/la/solver.hh>
#include <dune/stuff/common/exceptions.hh>

#include <dune/geometry/quadraturerules.hh>

#include <dune/gdt/space/continuouslagrange/fem.hh>
#include <dune/gdt/playground/space/raviartthomas/pdelab.hh>
#include <dune/gdt/discretefunction/default.hh>

#include "interfaces.hh"

namespace Dune {
namespace GDT {
namespace Operator {

// forward, to be used in the traits
template <class GridViewImp, class FunctionImp>
class DarcyReconstruction;

template <class GridViewImp, class FunctionImp>
class DarcyReconstructionTraits
{
  static_assert(std::is_base_of<Stuff::IsLocalizableFunction, FunctionImp>::value,
                "FunctionImp has to be derived from Stuff::IsLocalizableFunction!");
  static_assert(std::is_same<typename GridViewImp::ctype, typename FunctionImp::DomainFieldType>::value,
                "Types do not match!");
  static_assert(GridViewImp::dimension == FunctionImp::dimDomain, "Dimensions do not match!");

public:
  typedef DarcyReconstruction<GridViewImp, FunctionImp> derived_type;
  typedef GridViewImp GridViewType;
  typedef typename FunctionImp::RangeFieldType FieldType;
}; // class DarcyReconstructionTraits

/**
  * \note Only works for scalar valued function atm.
  **/
template <class GridViewImp, class FunctionImp>
class DarcyReconstruction : public OperatorInterface<DarcyReconstructionTraits<GridViewImp, FunctionImp>>
{
public:
  typedef DarcyReconstructionTraits<GridViewImp, FunctionImp> Traits;
  typedef typename Traits::GridViewType GridViewType;
  typedef typename Traits::FieldType FieldType;

  typedef typename GridViewType::template Codim<0>::Entity EntityType;
  typedef typename GridViewType::ctype DomainFieldType;
  static const unsigned int dimDomain = GridViewType::dimension;

  DarcyReconstruction(const GridViewType& grid_view, const FunctionImp& function)
    : grid_view_(grid_view)
    , function_(function)
  {
  }

  template <class E, class D, int d, class R, int r, int rC, class T, class V>
  void apply(const Stuff::LocalizableFunctionInterface<E, D, d, R, r, rC>& /*source*/,
             DiscreteFunction<SpaceInterface<T>, V>& /*range*/) const
  {
    static_assert((Dune::AlwaysFalse<E>::value), "Not implemented for this combination of source and range!");
  }

  /**
   * \brief Does an L2 projection of '- function * \gradient source' onto range.
   */
  template <class GP, int p, class V>
  void apply(const Stuff::LocalizableFunctionInterface<EntityType, DomainFieldType, dimDomain, FieldType, 1, 1>& source,
             DiscreteFunction<ContinuousLagrangeSpace::FemWrapper<GP, p, FieldType, dimDomain, 1>, V>& range) const
  {
#if HAVE_EIGEN
    typedef Stuff::LA::EigenRowMajorSparseMatrix<FieldType> MatrixType;
    typedef Stuff::LA::EigenDenseVector<FieldType> VectorType;
#elif HAVE_DUNE_ISTL
    typedef Stuff::LA::IstlRowMajorSparseMatrix<FieldType> MatrixType;
    typedef Stuff::LA::IstlDenseVector<FieldType> VectorType;
#else
    typedef Stuff::LA::CommonDenseMatrix<FieldType> MatrixType;
    typedef Stuff::LA::CommonDenseVector<FieldType> VectorType;
#endif
    MatrixType lhs(
        range.space().mapper().size(), range.space().mapper().size(), range.space().compute_volume_pattern());
    VectorType rhs(range.space().mapper().size());

    // walk the grid
    const auto entity_it_end = grid_view_.template end<0>();
    for (auto entity_it = grid_view_.template begin<0>(); entity_it != entity_it_end; ++entity_it) {
      const auto& entity        = *entity_it;
      const auto local_function = function_.local_function(entity);
      const auto local_source   = source.local_function(entity);
      const auto basis          = range.space().base_function_set(entity);
      // do a volume quadrature
      const size_t integrand_order =
          std::max(local_function->order() + size_t(local_source->order() - 1), basis.order()) + basis.order();
      assert(integrand_order < std::numeric_limits<int>::max());
      const auto& quadrature       = QuadratureRules<DomainFieldType, dimDomain>::rule(entity.type(), int(integrand_order));
      const auto quadrature_it_end = quadrature.end();
      for (auto quadrature_it = quadrature.begin(); quadrature_it != quadrature_it_end; ++quadrature_it) {
        const auto xx                             = quadrature_it->position();
        const FieldType quadrature_weight         = quadrature_it->weight();
        const DomainFieldType integration_element = entity.geometry().integrationElement(xx);
        const auto function_value                 = local_function->evaluate(xx);
        const auto source_gradient                = local_source->jacobian(xx);
        const auto basis_value = basis.evaluate(xx);
        for (size_t ii = 0; ii < basis.size(); ++ii) {
          const size_t global_ii = range.space().mapper().mapToGlobal(entity, ii);
          rhs.add_to_entry(global_ii,
                           integration_element * quadrature_weight * -1.0 * function_value
                               * (source_gradient[0] * basis_value[ii]));
          for (size_t jj = 0; jj < basis.size(); ++jj) {
            const size_t global_jj = range.space().mapper().mapToGlobal(entity, jj);
            lhs.add_to_entry(
                global_ii, global_jj, integration_element * quadrature_weight * (basis_value[ii] * basis_value[jj]));
          }
        }
      } // do a volume quadrature
    } // walk the grid

    // solve
    Stuff::LA::Solver<MatrixType>(lhs).apply(rhs, range.vector());
  } // ... apply(...)

  template <class GP, class V>
  void apply(const Stuff::LocalizableFunctionInterface<EntityType, DomainFieldType, dimDomain, FieldType, 1>& source,
             DiscreteFunction<RaviartThomasSpace::PdelabBased<GP, 0, FieldType, dimDomain>, V>& range) const
  {
    const auto& rtn0_space   = range.space();
    auto& range_vector       = range.vector();
    const FieldType infinity = std::numeric_limits<FieldType>::infinity();
    for (size_t ii = 0; ii < range_vector.size(); ++ii)
      range_vector[ii] = infinity;
    // walk the grid
    const auto entity_it_end = grid_view_.template end<0>();
    for (auto entity_it = grid_view_.template begin<0>(); entity_it != entity_it_end; ++entity_it) {
      const auto& entity            = *entity_it;
      const auto local_DoF_indices  = rtn0_space.local_DoF_indices(entity);
      const auto global_DoF_indices = rtn0_space.mapper().globalIndices(entity);
      assert(global_DoF_indices.size() == local_DoF_indices.size());
      const auto local_function = function_.local_function(entity);
      const auto local_source   = source.local_function(entity);
      const auto local_basis    = rtn0_space.base_function_set(entity);
      // walk the intersections
      const auto intersection_it_end = grid_view_.iend(entity);
      for (auto intersection_it = grid_view_.ibegin(entity); intersection_it != intersection_it_end;
           ++intersection_it) {
        const auto& intersection = *intersection_it;
        if (intersection.neighbor() && !intersection.boundary()) {
          const auto neighbor_ptr = intersection.outside();
          const auto& neighbor = *neighbor_ptr;
          if (grid_view_.indexSet().index(entity) < grid_view_.indexSet().index(neighbor)) {
            const auto local_function_neighbor    = function_.local_function(neighbor);
            const auto local_source_neighbor      = source.local_function(neighbor);
            const size_t local_intersection_index = intersection.indexInInside();
            const size_t local_DoF_index          = local_DoF_indices[local_intersection_index];
            // do a face quadrature
            FieldType lhs                = 0;
            FieldType rhs                = 0;
            const size_t integrand_order = local_function->order();
            assert(integrand_order < std::numeric_limits<int>::max());
            const auto& quadrature =
                QuadratureRules<DomainFieldType, dimDomain - 1>::rule(intersection.type(), int(integrand_order));
            const auto quadrature_it_end = quadrature.end();
            for (auto quadrature_it = quadrature.begin(); quadrature_it != quadrature_it_end; ++quadrature_it) {
              const auto xx_intersection         = quadrature_it->position();
              const auto normal                  = intersection.unitOuterNormal(xx_intersection);
              const FieldType integration_factor = intersection.geometry().integrationElement(xx_intersection);
              const FieldType weigth             = quadrature_it->weight();
              const auto xx_entity               = intersection.geometryInInside().global(xx_intersection);
              const auto xx_neighbor             = intersection.geometryInOutside().global(xx_intersection);
              // evalaute
              auto function_value = local_function->evaluate(xx_entity);
              function_value *= 0.5;
              auto function_value_neighbor = local_function_neighbor->evaluate(xx_neighbor);
              function_value_neighbor *= 0.5;
              function_value += function_value_neighbor;
              auto source_gradient = local_source->jacobian(xx_entity);
              source_gradient *= 0.5;
              auto source_gradient_neighbor = local_source_neighbor->jacobian(xx_neighbor);
              source_gradient_neighbor *= 0.5;
              source_gradient += source_gradient_neighbor;
              const auto basis_values = local_basis.evaluate(xx_entity);
              const auto basis_value  = basis_values[local_DoF_index];
              // compute integrals
              lhs += integration_factor * weigth * (basis_value * normal);
              rhs += integration_factor * weigth * -1.0 * function_value * (source_gradient[0] * normal);
            } // do a face quadrature
            // set DoF
            const size_t global_DoF_index = global_DoF_indices[local_DoF_index];
            assert(!(range_vector[global_DoF_index] < infinity));
            range_vector[global_DoF_index] = rhs / lhs;
          }
        } else if (intersection.boundary() && !intersection.neighbor()) {
          const size_t local_intersection_index = intersection.indexInInside();
          const size_t local_DoF_index          = local_DoF_indices[local_intersection_index];
          // do a face quadrature
          FieldType lhs                = 0;
          FieldType rhs                = 0;
          const size_t integrand_order = local_function->order();
          assert(integrand_order < std::numeric_limits<int>::max());
          const auto& quadrature =
              QuadratureRules<DomainFieldType, dimDomain - 1>::rule(intersection.type(), int(integrand_order));
          const auto quadrature_it_end = quadrature.end();
          for (auto quadrature_it = quadrature.begin(); quadrature_it != quadrature_it_end; ++quadrature_it) {
            const auto xx_intersection         = quadrature_it->position();
            const auto normal                  = intersection.unitOuterNormal(xx_intersection);
            const FieldType integration_factor = intersection.geometry().integrationElement(xx_intersection);
            const FieldType weigth             = quadrature_it->weight();
            const auto xx_entity               = intersection.geometryInInside().global(xx_intersection);
            // evalaute
            const auto function_value  = local_function->evaluate(xx_entity);
            const auto source_gradient = local_source->jacobian(xx_entity);
            const auto basis_values    = local_basis.evaluate(xx_entity);
            const auto basis_value     = basis_values[local_DoF_index];
            // compute integrals
            lhs += integration_factor * weigth * (basis_value * normal);
            rhs += integration_factor * weigth * -1.0 * function_value * (source_gradient[0] * normal);
          } // do a face quadrature
          // set DoF
          const size_t global_DoF_index = global_DoF_indices[local_DoF_index];
          assert(!(range_vector[global_DoF_index] < infinity));
          range_vector[global_DoF_index] = rhs / lhs;
        } else
          DUNE_THROW_COLORFULLY(Stuff::Exceptions::internal_error, "Unknown intersection type!");
      } // walk the intersections
    } // walk the grid
  } // ... apply(...)

private:
  const GridViewType& grid_view_;
  const FunctionImp& function_;
}; // class DarcyReconstruction

} // namespace Operator
} // namespace GDT
} // namespace Dune

#endif // DUNE_GDT_OPERATOR_DARCY_HH
<|endoftext|>


<commit_before>//
// Created by Jan de Visser on 2021-10-04.
//

#include <ctime>
#include <mutex>
#include <core/Logging.h>

namespace Obelix {

std::mutex g_logging_mutex;

std::string_view LogLevel_name(LogLevel level)
{
    switch (level) {
#undef __ENUMERATE_LOG_LEVEL
#define __ENUMERATE_LOG_LEVEL(level, cardinal) \
    case LogLevel::level:                      \
        return #level;
        ENUMERATE_LOG_LEVELS(__ENUMERATE_LOG_LEVEL)
#undef __ENUMERATE_LOG_LEVEL
    default:
        assert(false);
    }
}

std::optional<LogLevel> LogLevel_by_name(std::string_view const& name)
{
#undef __ENUMERATE_LOG_LEVEL
#define __ENUMERATE_LOG_LEVEL(level, cardinal) \
    if (name == #level) {                      \
        return LogLevel::level;                \
    }
    ENUMERATE_LOG_LEVELS(__ENUMERATE_LOG_LEVEL)
#undef __ENUMERATE_LOG_LEVEL
    return {};
}

LoggingCategory::LoggingCategory(std::string name) noexcept
    : m_name(move(name))
    , m_enabled(false)
    , m_logger(&Logger::get_logger())
{
    m_level = m_logger->level();
    m_logger->add_category(this);
}

bool LoggingCategory::enabled() const {
    return m_enabled || m_logger->m_all_enabled;
}

std::clock_t LoggingCategory::start()
{
    if constexpr (DEBUG) {
        return std::clock();
    } else {
        return 0;
    }
}

void Logger::set_nolock(std::basic_string_view<char> cat, bool enabled)
{
    if (cat != "all") {
        std::string cat_str(cat);
        if (m_categories.contains(cat_str)) {
            m_categories[cat_str] -> set(enabled);
        } else {
            m_unregistered[cat_str] = enabled;
        }
    } else {
        reset(enabled);
    }
}

LoggingCategory* Logger::add_category(LoggingCategory* category)
{
    const std::lock_guard<std::mutex> lock(g_logging_mutex);
    return add_category_nolock(category);
}

LoggingCategory* Logger::add_category_nolock(LoggingCategory* category)
{
    m_categories.insert_or_assign(category->name(), category);
    if (m_unregistered.contains(category->name())) {
        category->set(m_unregistered[category->name()]);
        m_unregistered.erase(category->name());
    }
    return m_categories[category->name()];
}

void Logger::reset(bool value)
{
    std::for_each(m_categories.begin(), m_categories.end(),
        [value](auto& p) {
            p.second->set(value);
        });
    std::for_each(m_unregistered.begin(), m_unregistered.end(),
        [value](auto &p) {
            p.second = value;
        });
    m_all_enabled = value;
}

void Logger::enable(std::string const& cat)
{
    const std::lock_guard<std::mutex> lock(g_logging_mutex);
    set_nolock(cat, true);
}

void Logger::disable(std::string const& cat)
{
    const std::lock_guard<std::mutex> lock(g_logging_mutex);
    set_nolock(cat, false);
}

bool Logger::status(std::string const& cat)
{
    if (m_categories.contains(cat)) {
        return m_categories[cat] -> enabled();
    } else if (m_unregistered.contains(cat)) {
        return m_unregistered[cat];
    } else {
        return m_all_enabled;
    }
}

LogLevel Logger::level() const
{
    return m_level;
}

LogLevel Logger::set_level(std::string const& level)
{
    const std::lock_guard<std::mutex> lock(g_logging_mutex);
    auto level_maybe = LogLevel_by_name(level);
    if (level_maybe.has_value())
        set_level(level_maybe.value());
    return m_level;
}

LogLevel Logger::set_level(LogLevel level)
{
    m_level = level;
    return m_level;
}

void Logger::set_file(std::string const& filename)
{
    const std::lock_guard<std::mutex> lock(g_logging_mutex);
    if (m_destination && (m_destination != stderr)) {
        fclose(m_destination);
    }
    m_destination = nullptr;
    m_logfile = filename;
}

Logger::Logger()
{
    if (auto obl_logfile = getenv("OBL_LOGFILE"); obl_logfile) {
        m_logfile = obl_logfile;
    }

    if (auto lvl = getenv("OBL_LOGLEVEL"); lvl && *lvl) {
        set_level(lvl);
    }

    auto cats = getenv("OBL_DEBUG");
    if (!cats) {
        cats = getenv("DEBUG");
    }
    if (cats && *cats) {
        std::string_view cats_sv(cats);
        size_t prev = 0;
        for (auto ix = cats_sv.find_first_of(";,:", 0); ix != std::string_view::npos; prev = ix, ix = cats_sv.find_first_of(";,:", ix)) {
            set_nolock(cats_sv.substr(prev, ix), true);
        }
        set_nolock(cats_sv.substr(prev), true);
    }
}

Logger& Logger::get_logger()
{
    static Logger *logger = nullptr;
    const std::lock_guard<std::mutex> lock(g_logging_mutex);
    if (!logger)
        logger = new Logger();
    return *logger;
}

}
<commit_msg>Clang-Tidy: switching the order of initialization<commit_after>//
// Created by Jan de Visser on 2021-10-04.
//

#include <ctime>
#include <mutex>
#include <core/Logging.h>

namespace Obelix {

std::mutex g_logging_mutex;

std::string_view LogLevel_name(LogLevel level)
{
    switch (level) {
#undef __ENUMERATE_LOG_LEVEL
#define __ENUMERATE_LOG_LEVEL(level, cardinal) \
    case LogLevel::level:                      \
        return #level;
        ENUMERATE_LOG_LEVELS(__ENUMERATE_LOG_LEVEL)
#undef __ENUMERATE_LOG_LEVEL
    default:
        assert(false);
    }
}

std::optional<LogLevel> LogLevel_by_name(std::string_view const& name)
{
#undef __ENUMERATE_LOG_LEVEL
#define __ENUMERATE_LOG_LEVEL(level, cardinal) \
    if (name == #level) {                      \
        return LogLevel::level;                \
    }
    ENUMERATE_LOG_LEVELS(__ENUMERATE_LOG_LEVEL)
#undef __ENUMERATE_LOG_LEVEL
    return {};
}

LoggingCategory::LoggingCategory(std::string name) noexcept
    : m_enabled(false)
    , m_name(move(name))
    , m_logger(&Logger::get_logger())
{
    m_level = m_logger->level();
    m_logger->add_category(this);
}

bool LoggingCategory::enabled() const {
    return m_enabled || m_logger->m_all_enabled;
}

std::clock_t LoggingCategory::start()
{
    if constexpr (DEBUG) {
        return std::clock();
    } else {
        return 0;
    }
}

void Logger::set_nolock(std::basic_string_view<char> cat, bool enabled)
{
    if (cat != "all") {
        std::string cat_str(cat);
        if (m_categories.contains(cat_str)) {
            m_categories[cat_str] -> set(enabled);
        } else {
            m_unregistered[cat_str] = enabled;
        }
    } else {
        reset(enabled);
    }
}

LoggingCategory* Logger::add_category(LoggingCategory* category)
{
    const std::lock_guard<std::mutex> lock(g_logging_mutex);
    return add_category_nolock(category);
}

LoggingCategory* Logger::add_category_nolock(LoggingCategory* category)
{
    m_categories.insert_or_assign(category->name(), category);
    if (m_unregistered.contains(category->name())) {
        category->set(m_unregistered[category->name()]);
        m_unregistered.erase(category->name());
    }
    return m_categories[category->name()];
}

void Logger::reset(bool value)
{
    std::for_each(m_categories.begin(), m_categories.end(),
        [value](auto& p) {
            p.second->set(value);
        });
    std::for_each(m_unregistered.begin(), m_unregistered.end(),
        [value](auto &p) {
            p.second = value;
        });
    m_all_enabled = value;
}

void Logger::enable(std::string const& cat)
{
    const std::lock_guard<std::mutex> lock(g_logging_mutex);
    set_nolock(cat, true);
}

void Logger::disable(std::string const& cat)
{
    const std::lock_guard<std::mutex> lock(g_logging_mutex);
    set_nolock(cat, false);
}

bool Logger::status(std::string const& cat)
{
    if (m_categories.contains(cat)) {
        return m_categories[cat] -> enabled();
    } else if (m_unregistered.contains(cat)) {
        return m_unregistered[cat];
    } else {
        return m_all_enabled;
    }
}

LogLevel Logger::level() const
{
    return m_level;
}

LogLevel Logger::set_level(std::string const& level)
{
    const std::lock_guard<std::mutex> lock(g_logging_mutex);
    auto level_maybe = LogLevel_by_name(level);
    if (level_maybe.has_value())
        set_level(level_maybe.value());
    return m_level;
}

LogLevel Logger::set_level(LogLevel level)
{
    m_level = level;
    return m_level;
}

void Logger::set_file(std::string const& filename)
{
    const std::lock_guard<std::mutex> lock(g_logging_mutex);
    if (m_destination && (m_destination != stderr)) {
        fclose(m_destination);
    }
    m_destination = nullptr;
    m_logfile = filename;
}

Logger::Logger()
{
    if (auto obl_logfile = getenv("OBL_LOGFILE"); obl_logfile) {
        m_logfile = obl_logfile;
    }

    if (auto lvl = getenv("OBL_LOGLEVEL"); lvl && *lvl) {
        set_level(lvl);
    }

    auto cats = getenv("OBL_DEBUG");
    if (!cats) {
        cats = getenv("DEBUG");
    }
    if (cats && *cats) {
        std::string_view cats_sv(cats);
        size_t prev = 0;
        for (auto ix = cats_sv.find_first_of(";,:", 0); ix != std::string_view::npos; prev = ix, ix = cats_sv.find_first_of(";,:", ix)) {
            set_nolock(cats_sv.substr(prev, ix), true);
        }
        set_nolock(cats_sv.substr(prev), true);
    }
}

Logger& Logger::get_logger()
{
    static Logger *logger = nullptr;
    const std::lock_guard<std::mutex> lock(g_logging_mutex);
    if (!logger)
        logger = new Logger();
    return *logger;
}

}
<|endoftext|>