/data/maps/the_great/

option value='87596fb8c1facd225a8aed407186ad25fcc4d7bd'>this commit Natural language generation library
summary refs log blame commit diff stats
path: root/lib/field.h
blob: 30c62be9c78f6a9e2ff89326e4ed96404d1a449a (plain) (tree)

















































































































































































































































































































                                                                                                                                        
#ifndef FIELD_H_43258321
#define FIELD_H_43258321

#include "enums.h"
#include <stdexcept>
#include <tuple>

namespace verbly {
  
  class filter;
  
  class field {
  public:
    enum class type {
      undefined,
      string,
      integer,
      boolean,
      join,
      join_through,
      hierarchal_join
    };
    
    // Default constructor
    
    field()
    {
    }
    
    // Static factories
    
    static field stringField(
      object obj,
      const char* name,
      bool nullable = false)
    {
      return field(obj, type::string, name, nullable);
    }
    
    static field stringField(
      const char* table,
      const char* name,
      bool nullable = false)
    {
      return field(object::undefined, type::string, name, nullable, table);
    }
    
    static field integerField(
      object obj,
      const char* name,
      bool nullable = false)
    {
      return field(obj, type::integer, name, nullable);
    }
    
    static field integerField(
      const char* table,
      const char* name,
      bool nullable = false)
    {
      return field(object::undefined, type::integer, name, nullable, table);
    }
    
    static field booleanField(
      object obj,
      const char* name,
      bool nullable = false)
    {
      return field(obj, type::boolean, name, nullable);
    }
    
    static field booleanField(
      const char* table,
      const char* name,
      bool nullable = false)
    {
      return field(object::undefined, type::boolean, name, nullable, table);
    }
    
    static field joinField(
      object obj,
      const char* name,
      object joinWith,
      bool nullable = false)
    {
      return field(obj, type::join, name, nullable, 0, joinWith);
    }
    
    static field joinField(
      object obj,
      const char* name,
      const char* table,
      bool nullable = false)
    {
      return field(obj, type::join, name, nullable, table);
    }
    
    static field joinThrough(
      object obj,
      const char* name,
      object joinWith,
      const char* joinTable,
      const char* foreignColumn)
    {
      return field(obj, type::join_through, name, true, joinTable, joinWith, foreignColumn, name, foreignColumn);
    }
    
    static field joinThrough(
      object obj,
      const char* name,
      object joinWith,
      const char* joinTable,
      const char* foreignColumn,
      const char* joinColumn,
      const char* foreignJoinColumn)
    {
      return field(obj, type::join_through, name, true, joinTable, joinWith, foreignColumn, joinColumn, foreignJoinColumn);
    }
    
    static field selfJoin(
      object obj,
      const char* name,
      const char* joinTable,
      const char* joinColumn,
      const char* foreignJoinColumn)
    {
      return field(obj, type::join_through, name, true, joinTable, obj, name, joinColumn, foreignJoinColumn);
    }
    
    static field hierarchalSelfJoin(
      object obj,
      const char* name,
      const char* joinTable,
      const char* joinColumn,
      const char* foreignJoinColumn)
    {
      return field(obj, type::hierarchal_join, name, true, joinTable, obj, name, joinColumn, foreignJoinColumn);
    }
    
    // Accessors
    
    object getObject() const
    {
      return object_;
    }
    
    type getType() const
    {
      return type_;
    }
    
    bool isJoin() const
    {
      return ((type_ == type::join) || (type_ == type::join_through) || (type_ == type::hierarchal_join));
    }
    
    const char* getColumn() const
    {
      return column_;
    }
    
    bool isNullable() const
    {
      return nullable_;
    }
    
    bool hasTable() const
    {
      return (table_ != 0);
    }
    
    const char* getTable() const
    {
      return table_;
    }
    
    // Joins
    
    object getJoinObject() const
    {
      // We ignore hierarchal joins because they are always self joins.
      return ((type_ == type::join) || (type_ == type::join_through))
        ? joinObject_
        : throw std::domain_error("Non-join fields don't have join objects");
    }
        
    // Many-to-many joins
    
    const char* getForeignColumn() const
    {
      // We ignore hierarchal joins because they are always self joins.
      return (type_ == type::join_through)
        ? foreignColumn_
        : throw std::domain_error("Only many-to-many join fields have a foreign column");
    }
    
    const char* getJoinColumn() const
    {
      return ((type_ == type::join_through) || (type_ == type::hierarchal_join))
        ? joinColumn_
        : throw std::domain_error("Only many-to-many join fields have a join column");
    }
    
    const char* getForeignJoinColumn() const
    {
      return ((type_ == type::join_through) || (type_ == type::hierarchal_join))
        ? foreignJoinColumn_
        : throw std::domain_error("Only many-to-many join fields have a foreign join column");
    }
    
    // Ordering
    
    bool operator<(const field& other) const
    {
      // For the most part, (object, column) uniquely identifies fields.
      // However, there do exist a number of relationships from an object to
      // itself, such as notion hypernymy/hyponymy. Hypernymy and hyponymy have
      // the same object (notion), the same column (notion_id), and the same
      // table (hypernymy); however, they have different join columns.
      return std::tie(object_, column_, table_, joinColumn_) < std::tie(other.object_, other.column_, other.table_, other.joinColumn_);
    }
    
    // Equality
    
    bool operator==(const field& other) const
    {
      // For the most part, (object, column) uniquely identifies fields.
      // However, there do exist a number of relationships from an object to
      // itself, such as notion hypernymy/hyponymy. Hypernymy and hyponymy have
      // the same object (notion), the same column (notion_id), and the same
      // table (hypernymy); however, they have different join columns.
      return std::tie(object_, column_, table_, joinColumn_) == std::tie(other.object_, other.column_, other.table_, other.joinColumn_);
    }
    
    // Filter construction
    
    filter operator==(int value) const; // Integer equality
    filter operator!=(int value) const; // Integer inequality
    filter operator<(int value) const; // Integer is less than
    filter operator<=(int value) const; // Integer is at most
    filter operator>(int value) const; // Integer is greater than
    filter operator>=(int value) const; // Integer is at least
    
    filter operator==(part_of_speech value) const; // Part of speech equality
    filter operator==(positioning value) const; // Adjective positioning equality
    filter operator==(inflection value) const; // Inflection category equality
    
    filter operator==(bool value) const; // Boolean equality
    
    filter operator==(std::string value) const; // String equality
    filter operator!=(std::string value) const; // String inequality
    filter operator%=(std::string value) const; // String matching
    
    operator filter() const; // Non-nullity
    filter operator!() const; // Nullity
    
    filter operator%=(filter joinCondition) const; // Join
    
  private:
    
    // Constructor
    
    field(
      object obj,
      type datatype,
      const char* column,
      bool nullable = false,
      const char* table = 0,
      object joinObject = object::undefined,
      const char* foreignColumn = 0,
      const char* joinColumn = 0,
      const char* foreignJoinColumn = 0) :
        object_(obj),
        type_(datatype),
        column_(column),
        nullable_(nullable),
        table_(table),
        joinObject_(joinObject),
        foreignColumn_(foreignColumn),
        joinColumn_(joinColumn),
        foreignJoinColumn_(foreignJoinColumn)
    {
    }
    
    // General
    object object_ = object::undefined;
    type type_ = type::undefined;
    const char* column_ = 0;
    const char* table_ = 0;
    
    // Non-joins and belongs-to joins
    bool nullable_ = false;
    
    // Joins
    object joinObject_ = object::undefined;
    
    // Many-to-many joins
    const char* foreignColumn_ = 0;
    const char* joinColumn_ = 0;
    const char* foreignJoinColumn_ = 0;
    
  };
  
};

#endif /* end of include guard: FIELD_H_43258321 */