https://gitlab.opengeosys.org/ogs/ogs.git
Raw File
Tip revision: 2469b93cc241705d1622081dcf4ab20ba3cb687e authored by Christoph Lehmann on 03 November 2023, 08:51:42 UTC
Merge branch 'remove-coupled-solutions' into 'master'
Tip revision: 2469b93
TemplateVec.h
/**
 * \file
 * \date 2010-02-26
 * \author Thomas Fischer
 * \brief Definition of the GeoLib::TemplateVec class.
 *
 * \copyright
 * Copyright (c) 2012-2023, OpenGeoSys Community (http://www.opengeosys.org)
 *            Distributed under a Modified BSD License.
 *              See accompanying file LICENSE.txt or
 *              http://www.opengeosys.org/project/license
 *
 */

#pragma once

#include <algorithm>
#include <cstdlib>
#include <map>
#include <memory>
#include <string>
#include <utility>
#include <vector>

#include "BaseLib/Logging.h"

#include "BaseLib/Error.h"

namespace GeoLib
{
/**
 * \ingroup GeoLib
 *
 * \brief The class TemplateVec takes a unique name and manages
 * a std::vector of pointers to data elements of type T.
 *
 * Instances are classes PolylineVec and SurfaceVec.
 * */
template <class T>
class TemplateVec
{
public:
    using NameIdPair = std::pair<std::string, std::size_t>;
    using NameIdMap = std::map<std::string, std::size_t>;

    /**
     * Constructor of class TemlateVec.
     * \param name unique name of the project the elements belonging to.
     * In order to access the data elements a unique name is required.
     * \param data_vec Vector of data elements.
     * \attention{TemplateVec will take the ownership of the vector
     * and also its elements,
     * i.e. delete its elements and delete the vector itself!}
     * \param elem_name_map Names of data elements can be given by a
     * std::map<std::string, std::size_t>. Here the std::string is the name
     * of the element and the value for std::size_t stands for an index in
     * the data_vec.
     */
    TemplateVec(std::string const& name, std::vector<T*>&& data_vec,
                NameIdMap&& elem_name_map)
        : _name(name),
          _data_vec(std::move(data_vec)),
          _name_id_map(std::move(elem_name_map))
    {
    }

    /**
     * destructor, deletes all data elements
     */
    virtual ~TemplateVec()
    {
        for (std::size_t k(0); k < size(); k++)
        {
            delete _data_vec[k];
        }
    }

    /** sets the name of the vector of geometric objects
     * the data elements belonging to
     * \param n the name as standard string */
    void setName(const std::string& n) { _name = n; }
    /**
     * the name, the data element belonging to
     * \return the name of the object
     */
    std::string getName() const { return _name; }

    /// Returns the begin of the name id mapping structure
    NameIdMap::const_iterator getNameIDMapBegin() const
    {
        return _name_id_map.cbegin();
    }

    /// Returns the end of the name id mapping structure
    NameIdMap::const_iterator getNameIDMapEnd() const
    {
        return _name_id_map.cend();
    }

    /**
     * \return the number of data elements
     */
    std::size_t size() const { return _data_vec.size(); }

    /**
     * get a pointer to a standard vector containing the data elements
     * \return the data elements
     */
    std::vector<T*> const& getVector() const { return _data_vec; }

    /**
     * search the vector of names for the ID of the geometric element with the
     * given name
     * \param name the name of the geometric element
     * \param id the id of the geometric element
     */
    bool getElementIDByName(const std::string& name, std::size_t& id) const
    {
        auto it(_name_id_map.find(name));

        if (it != _name_id_map.end())
        {
            id = it->second;
            return true;
        }
        return false;
    }

    /// Returns an element with the given name.
    const T* getElementByName(const std::string& name) const
    {
        std::size_t id;
        bool ret(getElementIDByName(name, id));
        if (ret)
        {
            return _data_vec[id];
        }

        return nullptr;
    }

    /**
     * The method returns true if there is a name associated
     * with the given id, else method returns false.
     * \param id the id
     * \param element_name if a name associated with the id
     * is found name is assigned to element_name
     * \return if there is name associated with the given id:
     * true, else false
     */
    bool getNameOfElementByID(std::size_t id, std::string& element_name) const
    {
        // search in map for id
        auto it = findFirstElementByID(id);
        if (it == _name_id_map.end())
        {
            return false;
        }
        element_name = it->first;
        return true;
    }

    /// Return the name of an element based on its ID.
    void setNameOfElementByID(std::size_t id, std::string const& element_name)
    {
        _name_id_map[element_name] = id;
    }

    /**
     * The method returns true if the given element of type T
     * can be found and the element has a name, else method returns false.
     * \param data the data element, one wants to know the name
     * \param name the name of the data element (if the data element is
     * found and the data element has a name)
     * \return if element is found and has a name: true, else false
     */
    bool getNameOfElement(const T* data, std::string& name) const
    {
        for (std::size_t k(0); k < _data_vec.size(); k++)
        {
            if (_data_vec[k] == data)
            {
                return getNameOfElementByID(k, name);
            }
        }

        return false;
    }

    /// Adds a new element to the vector.
    virtual void push_back(T* data_element,
                           std::string const* const name = nullptr)
    {
        _data_vec.push_back(data_element);
        if (!name || name->empty())
        {
            return;
        }

        auto it(_name_id_map.find(*name));
        if (it == _name_id_map.end())
        {
            _name_id_map[*name] = _data_vec.size() - 1;
        }
        else
        {
            WARN(
                "Name '{:s}' exists already. The object will be inserted "
                "without a name",
                *name);
        }
    }

    /// Sets the given name for the element of the given ID.
    virtual void setNameForElement(std::size_t id, std::string const& name)
    {
        // Erase id if found in map.
        auto it = findFirstElementByID(id);
        if (it != _name_id_map.end())
        {
            _name_id_map.erase(it);
        }

        if (!name.empty())
        {
            // insert new or revised name
            _name_id_map[name] = id;
        }
    }

private:
    NameIdMap::const_iterator findFirstElementByID(std::size_t const& id) const
    {
        return std::find_if(_name_id_map.begin(), _name_id_map.end(),
                            [id](NameIdPair const& elem)
                            { return elem.second == id; });
    }

protected:
    TemplateVec(TemplateVec const&) = delete;
    TemplateVec(TemplateVec&&) = delete;
    TemplateVec& operator=(TemplateVec const& rhs) = delete;
    TemplateVec& operator=(TemplateVec&& rhs) = delete;

    /** the name of the object */
    std::string _name;

    /**
     * vector of data elements
     */
    std::vector<T*> _data_vec;
    /**
     * store names associated with the element ids
     */
    NameIdMap _name_id_map;
};
}  // end namespace GeoLib
back to top