Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Debian packages RPM packages NuGet packages

Repository URL to install this package:

Details    
Size: Mime:
#pragma once

#include <cpporm/util/macros.h>

CPPORM_BEGIN_NAMESPACE

// Forward declarations
namespace db
{
class Session;
class Cursor;
class Query;
class Statement;
}
class Attribute;
class Entity;
class Relationship;
class PropertyMap;
class AttributeMap;
class RelationshipMap;
class ConstraintMap;

/*!
 * \brief Abstract class to represent database tables
 *
 * An entity maps a C++ object to an entry in a database table. All entities should derive from this
 * class. It has a name, a set of properties and a set of constraints, all being static members of
 * the
 * derived class. It contains an internal state comprised of:
 *  1. a set of attributes, which correspond to the table columns
 *  2. a set of relationships, which correspond to the table foreign keys
 *
 * Transactions and save-points can be used with entities. The entity attributes can be accessed and
 * modified through polymorphism by means of a container which maps column names to attributes.
 * Relationships can be accessed in a similar manner. This effectively implements a (rather
 * primitive) kind of object introspection mechanism.
 *
 * An entity can have a primary key. If there is no primary key declared in the database table, then
 * all attributes combined are considered as the primary key. This is needed to guarantee uniqueness
 * within the session cache.
 *
 * An entity can also have a version field. A version field is a set of attributes which indicates
 * the version of an entity. This is required for the optimistic locking strategy used in
 * concurrency control.
 *
 * One can loop through the entity relationships recusrively using a depth-first search procedure.
 *
 * There is a database session with which an entity can be associated, and a unique identifier for
 * the entity in the session cache. The nature of this identifier is implementation detail, and
 * should not matter for most users. There are methods for obtaining and resetting the ID.
 *
 * One can check if any of the entity attributes was modified since the last commit or since it was
 * constructed. It is also possible to rollback or save the internal state when using transactions.
 *
 * Some of the methods help in the construction of prepared statements, while others have to do with
 * the database schema of the database table being represented. Still others have do to with the
 * entity relationships.
 *
 * Finally, some convenience methods are provided which help in copying attributes from other
 * entities.
 *
 * \see Attribute
 * \see db::Session
 */
class CPPORM_EXPORT Entity
{
public:
    /*!
     * \brief Destructor
     */
    virtual ~Entity();

    /*!
     * \brief Clone entity
     * \return The cloned entity
     */
    virtual Entity *Clone() const = 0;

    /*!
     * \brief Get entity name
     * \return The entity name
     */
    virtual const std::string &GetName() const = 0;

    /*!
     * \brief Get entity properties
     * \return The entity properties
     */
    virtual const PropertyMap &GetProperties() const = 0;

    /*!
     * \brief Get entityattributes
     * \return The entity attributes
     */
    virtual const AttributeMap &GetAttributes() const = 0;

    /*!
     * \brief Get entity relationships
     * \return The entity relationships
     */
    virtual const RelationshipMap &GetRelationships() const = 0;

    /*!
     * \brief Get entity constraints
     * \return The entity constraints
     */
    virtual const ConstraintMap &GetConstraints() const = 0;

    /*!
     * \brief Get entity primary key
     * \return The entity primary key
     */
    const AttributeMap &GetPrimaryKey() const;

    /*!
     * \brief Get entity version key
     * \return The entity version key
     */
    const AttributeMap &GetVersionKey() const;

    /*!
     * \brief Get entity attribute by name
     * \param[in] name The attribute name
     * \return The attribute
     */
    Attribute &operator[](const std::string &name);

    /*!
     * \brief Get entity attribute by name (const version)
     * \param[in] name The attribute name
     * \return The attribute
     */
    const Attribute &operator[](const std::string &name) const;

    /*!
     * \brief Get entity relationship by name
     * \param[in] name The relationship name
     * \return The relationship
     */
    Relationship &GetRelationship(const std::string &name);

    /*!
     * \brief Traverse result
     */
    enum class TraverseResult
    {
        ok, /*!< continue iterating */
        skip, /*!< skip this entity */
        halt /*!< halt the iteration and return */
    };

    /*!
     * \brief Traverse entity relationships
     * \param[in] function The function
     * \return The traverse result
     */
    TraverseResult TraverseRelationships(std::function<TraverseResult(Entity &)> function);

    /*!
     * \brief Associate entity with a database session
     * \param[in] session The database session
     */
    void SetSession(db::Session *session);

    /*!
     * \brief Get entity unique ID
     * \return The entity unique ID
     */
    const std::string &GetId();

    /*!
     * \brief Reset entity unique ID
     */
    void ResetId();

    /*!
     * \brief Check whether the entity was modified since last commit
     * \return True if the entity was modified; false otherwise
     */
    bool WasModified();

    /*!
     * \brief Mark entity for removal
     * \return True if the entity was previously marked for removal; false otherwise
     */
    bool MarkForRemoval();

    /*!
     * \brief Rollback entity internal state
     */
    void Rollback();

    /*!
     * \brief Commit entity internal state
     */
    void Commit();

    /*!
     * \brief Push entity internal state
     */
    void PushState();

    /*!
     * \brief Extract entity attributes
     * \param[in] cursor The database cursor
     */
    void Extract(db::Cursor &cursor);

    /*!
     * \brief Extract entity primary key
     * \param[in] cursor The database cursor
     */
    void ExtractPrimaryKey(db::Cursor &cursor);

    /*!
     * \brief Save entity primary key
     */
    void SavePrimaryKey();

    /*!
     * \brief Compose part of query needed to fetch the entity from the database
     * \param[in] query The database query
     */
    void Fetch(db::Query &query);

    /*!
     * \brief Compose part of query needed to fetch the last inserted ID from the database
     * \param[in] query The database query
     * \return True if there is a last insert id to be fetched; false otherwise
     */
    bool FetchLastId(db::Query &query);

    /*!
     * \brief Compose part of query needed to fetch the entity primary key from the database
     * \param[in] query The database query
     */
    void FetchPrimaryKey(db::Query &query);

    /*!
     * \brief Compose part of query needed to insert the entity into the database
     * \param[in] query The database query
     */
    void Insert(db::Query &query);

    /*!
     * \brief Compose part of query needed to insert the entity into a temporary database table
     * \param[in] query The database query
     */
    void InsertIntoTemp(db::Query &query);

    /*!
     * \brief Compose part of query needed to join the temporary database table
     * \param[in] query The database query
     */
    void JoinTemp(db::Query &query);

    /*!
     * \brief Compose part of query needed to update the entity in the database
     * \param[in] query The database query
     */
    void Update(db::Query &query);

    /*!
     * \brief Compose part of query needed to delete the entity from the database
     * \param[in] query The database query
     */
    void Delete(db::Query &query);

    /*!
     * \brief Compose part of query needed to lookup the entity in the database
     * \param[in] query The database query
     */
    void Where(db::Query &query);

    /*!
     * \brief Bind the entity attributes to a prepared statement
     * \param[in] statement The database statement
     */
    void Bind(db::Statement &statement);

    /*!
     * \brief Bind the primary key attributes of this entity to a prepared statement
     * \param[in] statement The database statement
     */
    void BindPrimaryKey(db::Statement &statement);

    /*!
     * \brief Validate the database schema of this entity
     */
    void ValidateSchema() const;

    /*!
     * \brief Compose part of query needed to create the database schema of this entity
     * \param[in] query The database query
     */
    void CreateSchema(db::Query &query) const;

    /*!
     * \brief Compose part of query needed to create the temporary database schema
     * \param[in] query The database query
     * \note Only the primary key attributes make up the temporary table
     */
    void CreateTempSchema(db::Query &query) const;

    /*!
     * \brief Compose part of query needed to erase the table associated with this entity
     * \param[in] query The database query
     */
    void EraseTable(db::Query &query) const;

    /*!
     * \brief Compose part of query needed to erase the temporary table associated with this entity
     * \param[in] query The database query
     */
    void EraseTempTable(db::Query &query) const;

    /*!
     * \brief Compose part of query needed to drop the database schema associated with this entity
     * \param[in] query The database query
     */
    void DropSchema(db::Query &query) const;

    /*!
     * \brief Compose part of query needed to drop the temporary database schema associated with
     * this entity
     * \param[in] query The database query
     */
    void DropTempSchema(db::Query &query) const;

    /*!
     * \brief Reload the entity relationships
     */
    void ReloadRelationships();

    /*!
     * \brief Dissolve the entity relationships
     */
    void DissolveRelationships();

    /*!
     * \brief Copy all attributes except primary key and version key from another entity
     * \param[in] entity The other entity
     */
    void CopyFrom(Entity &entity);

    /*!
     * \brief Copy all attributes (including primary key and version key) from another entity
     * \param[in] entity The other entity
     */
    void CopyAllFrom(Entity &entity);

protected:
    /*!
     * \brief Befriend class Relationship
     */
    friend class Relationship;

    /*!
     * \brief The database session
     */
    db::Session *mSession;

private:
    /*!
     * \brief The entity unique ID
     */
    std::string mUniqueId;

    /*!
     * \brief A flag to indicate whether the entity is marked for update
     */
    bool mIsMarkedForUpdate = false;

    /*!
     * \brief A flag to indicate whether the entity is marked for removal
     */
    bool mIsMarkedForRemoval = false;
};

/*!
 * \example cpporm/entity.cpp
 *
 * This is an example of how to use the Entity class.
 */

CPPORM_END_NAMESPACE