/* 
 * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; version 2 of the
 * License.
 * 
 * This program 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 General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301  USA
 */

#ifndef _GRTPP_REFERENCES_H_
#define _GRTPP_REFERENCES_H_
namespace grt {
  class GRT;
  
  namespace internal
  {
    class Serializer;
    class Unserializer;
  };
  
  struct refcounted_value_data
  {
      void* allocator;
      void* ptr_value;
  };

  //used only to view Value* in debugger
  struct value_ptr_data
  {
      void* allocator;
      internal::Value* ptr_value;
  };


  class MYSQLGRT_PUBLIC TypeHandler
  {
  public:
      union DataStorage
      {
        value_ptr_data vdata;
        refcounted_value_data refcounted_value;
        int int_value;
        double double_value;
        const char* string_ptr;
      };
      typedef DataStorage TypeHandle;
      virtual void release(TypeHandle&)const = 0;
      virtual void retain(TypeHandle&)const = 0;
      virtual bool equals(const TypeHandle&, const ValueRef&)const= 0;
      virtual bool less_than(const TypeHandle&, const ValueRef&)const = 0;
      virtual void reset_references(TypeHandle&)const = 0;
      virtual void clear(TypeHandle&)const = 0;
      virtual bool is_same(const TypeHandle&, const ValueRef& value) const = 0;
      virtual Type type(const TypeHandle&) const = 0;
      virtual std::string repr(const TypeHandle&) const = 0;
      virtual void mark_global(const TypeHandle&) const = 0;
      virtual void unmark_global(const TypeHandle&) const = 0;
      virtual internal::Value* valueptr(const TypeHandle&) const = 0;
      virtual int refcount(const TypeHandle&) const = 0;

  };

  MYSQLGRT_PUBLIC TypeHandler* get_object_type_handler();

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

  /** Base GRT value reference class.
   * The Ref classes act as a smart pointer for GRT values. Because GRT
   * values are allocated on the heap and are reference counted, the Ref
   * classes will wrap around these values and perform automatic reference
   * incrementing or decrementing when statically allocated. In most cases
   * you must not directly reference or allocate a GRT value.
   * 
   * They also have methods for accessing meta-information about the value
   * like the type and implement some basic operators like assignment, ==,
   * != and <
   * 
   * The comparison operators will work on the actual GRT value wrapped,
   * even when you compare through the ValueRef type. In this case, if the
   * types of the compared values do not match they will also compare the
   * type of each value.
   *
   * @ingroup GRT
   */ 
  class LuaContext;
  class PythonContext;

  class MYSQLGRT_PUBLIC ValueRef
  {
  public:
    ValueRef() : _type_handler(_defalut_handler) { };
    ValueRef(TypeHandler* type_handler) : _type_handler(type_handler) { };

    ValueRef(const ValueRef &value)
      : _type_handler(value._type_handler), _value(value._value)
    {
      _type_handler->retain(_value);
    }

    /*virtual*/ ~ValueRef()
    {
      _type_handler->release(_value);
    }

    inline void clear() 
    { 
        _type_handler->clear(_value);
        _type_handler = get_default_type_handler();
    }

    inline bool is_valid() const { return _defalut_handler != _type_handler; }
    inline bool is_same(const ValueRef &value) const { return _type_handler->is_same(_value, value); }

    inline Type type() const { return _type_handler->type(_value); }
    
    ValueRef &operator= (const ValueRef& other) { 
        release();
        _value = other._value;
        _type_handler = other._type_handler;
        retain();
        return *this;
    }
    
    inline bool operator == (const ValueRef &other) const
    {
      return _type_handler->equals(_value, other);
    }
     
    inline bool operator != (const ValueRef &other) const
    {
      return !(operator ==(other));
    }

    inline bool operator < (const ValueRef &other) const
    {
      return _type_handler->less_than(_value, other);
    }

    std::string repr() const { return _type_handler->repr(_value); }

    inline internal::Value *valueptr() const { return _type_handler->valueptr(_value); }

    int refcount() const { return _type_handler->refcount(_value); }
    void retain() { _type_handler->retain(_value); }
    void release() { _type_handler->release(_value); }
    void mark_global() const{_type_handler->mark_global(_value);};
    void unmark_global() const{_type_handler->unmark_global(_value);};
    const TypeHandler::TypeHandle& get_data()const {return _value;};
  protected:
    static TypeHandler* get_default_type_handler(){return _defalut_handler;};
    static TypeHandler* _defalut_handler;
    TypeHandler* _type_handler;
    TypeHandler::TypeHandle _value;
  private:
    //Used only in interaction with lua/python and always implicitly assumes to be ptr to list/dict/obj
    //After refactoring that this constructor should be removed
    friend class LuaContext;
    friend class PythonContext;

    explicit ValueRef(internal::Value *value)
      : _type_handler(get_object_type_handler())
    {
      _value.refcounted_value.ptr_value = value;
      _type_handler->retain(_value);
    }

  };


  //----------------------------------------------------------------------
  // Object Refs
  
  template<class C> class Ref;
   
  typedef Ref<internal::Object> ObjectRef;

    
  /** Holds a reference to a GRT object.
   * 
   * Use it as Ref<db_Table> or db_TableRef, which is an alias created along
   * auto-generated classes.
   * 
   * To allocate a new object from C++ code:
   * @code
   *   db_TableRef table(grt);
   * @endcode
   *
   * To access members and methods:
   * @code
   *   table->member();
   * @endcode
   * 
   * Reference counting is performed automatically.
   *
   * @ingroup GRT
   */ 
  template<class Class>
    class Ref : public ValueRef
  {
  public:
    typedef Class RefType;
    
    Ref()
    {
    }

    Ref(internal::Value *value)
        : ValueRef(get_object_type_handler())
    {
        _value.vdata.ptr_value = value;
        _value.vdata.ptr_value->retain();
    }

    Ref(Class *obj)
      : ValueRef(get_object_type_handler())
    {
        _value.refcounted_value.ptr_value = obj;
        retain();
    }

    /** Constructor for creating and initializing a new object. 
     */
    explicit Ref(GRT *grt)
      : ValueRef(get_object_type_handler())
    {
      _value.refcounted_value.ptr_value =  new Class(grt);
      retain();
      content().init();
    }

    Ref(const Ref<Class> &ref)
      : ValueRef(ref)
    {
#ifdef ENABLE_DEBUG
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 2) // this causes errors in mac, with gcc 4.2
      // just to give an error if Class is not an object
      Class::static_class_name();
#endif
#endif
    }

    template<class Subclass>
      Ref(const Ref<Subclass> &ref)
          : ValueRef(ref)
    {
#if defined(ENABLE_DEBUG) || defined(_DEBUG)
      // poor mans compile-time type "check". compiler will throw an error if Subclass is not derived from Class
#ifdef __GNUC__
      Class *dummy_variable_just_for_type_check __attribute__((unused))= static_cast<Subclass*>(ref.valueptr());
#else
      Class *dummy_variable_just_for_type_check= static_cast<Subclass*>(ref.valueptr());
#endif
#endif
    }

    static inline bool can_wrap(const ValueRef &value) 
    { 
      return (value.type() == ObjectType) && (!value.is_valid() || dynamic_cast<Class*>(value.valueptr()));
    }

    static inline Ref<Class> cast_from(const ValueRef &ov)
    {
      if (ov.is_valid())
      {
        Class *obj= dynamic_cast<Class*>(ov.valueptr());
        if (!obj)
        {
          internal::Object* object= dynamic_cast<internal::Object*>(ov.valueptr());
          if (object)
            throw grt::type_error(Class::static_class_name(), object->class_name());
          else
            throw grt::type_error(Class::static_class_name(), ov.type());
        }
        return Ref<Class>(obj);
      }
      return Ref<Class>();
    }

    const std::string &id() const { return content().id(); }
    const std::string &class_name() const { return content().class_name(); }
    MetaClass *get_metaclass() const { return content().get_metaclass(); }

    bool is_instance(MetaClass *mc) const { return content().is_instance(mc); }
    bool is_instance(const std::string &klass) const { return content().is_instance(klass); }
    template <class C>
      bool is_instance() const { return C::static_class_name().empty() ? true : content().is_instance(C::static_class_name()); }
    
//    Ref<Class> &operator= (const Ref<Class>& other) { Ref<Class> tmp(other); swap(tmp._value); return *this; }

//    bool operator == (const ValueRef& other) const { return _value.refcounted_value.ptr_value == other.valueptr() || (content().equals(other.valueptr())); }
//    bool operator != (const ValueRef& other) const { return !(operator == (other)); }
    
    Class *operator->() const { return static_cast<Class*>(_value.refcounted_value.ptr_value); }

    ValueRef get_member(const std::string &m) const { return content().get_member(m); }
    ValueRef get_member(const struct ClassMember *m) const;
    void set_member(const std::string &m, const ValueRef &new_value) { content().set_member(m, new_value); }

    std::string get_string_member(const std::string &member) const { return content().get_string_member(member); }
    internal::Double::storage_type get_double_member(const std::string &member) const { return content().get_double_member(member); }
    internal::Integer::storage_type get_integer_member(const std::string &member) const { return content().get_integer_member(member); }
    bool has_member(const std::string &member) const { return content().has_member(member); }

    bool has_method(const std::string &method) const { return content().has_method(method); }
//    Class *operator*() const { return static_cast<Class*>(_value); }
    
    GRT *get_grt() const { return content().get_grt(); }
    
  public:
      Class &content() const { return *static_cast<Class*>(_value.refcounted_value.ptr_value); }
  };

#if 0
  //----------------------------------------------------------------------
  // Weak Object Refs
  
  template<class C> class WeakRef;
  
  typedef WeakRef<internal::Object> WeakObjectRef;  
  
  /** Holds a weak reference to a GRT object.
   * 
   * Use it as WeakRef<db_Table>
   * 
   * Weak references will not increment the reference count of the referenced object,
   * but will be able to tell whether it has been deleted. Use it to avoid circular
   * loops and other situations where you don't want a real reference to an object.
   *
   * @ingroup GRT
   */ 
  template<class Class>
  class WeakRef
    {
    public:
      typedef Class RefType;
      
      /// unitialized weak reference is invalid
      WeakRef() : _content(0), _valid_flag(false) // unassigned means reference is undefined
      {
      }

      // copy constructor
      WeakRef(const WeakRef<Class> &copy)
      : _content(copy._content), _valid_flag(copy._valid_flag)
      {
      }

      // Create a weak-ref from a normal ref
      WeakRef(const Ref<Class> &object_ref)
      : _content(object_ref.is_valid() ? &object_ref.content() : 0), 
        _valid_flag(object_ref.is_valid() ? object_ref->weakref_valid_flag() : internal::ObjectValidFlag(false))
      {
      }

      // gets a real usable reference to the object
      Ref<Class> lock() const
      { 
        if (!_valid_flag.valid())
          throw std::logic_error("attempt to access invalid weak-reference");
        return Ref<Class>(_content);
      }
      
      void reset()
      {
        _content= 0; // pointer was nullified, it's a valid reference to null (ie not undefined)
        _valid_flag= internal::ObjectValidFlag(true);
      }

      //! Returns true if the reference is still valid, false if the referenced object is gone
      bool expired() const
      {
        return _valid_flag.valid();
      }
      
      WeakRef<Class> &operator= (const WeakRef<Class>& other) 
      { 
        WeakRef<Class> tmp(other);
        swap(tmp);
        return *this; 
      }

      WeakRef<Class> &operator= (const Ref<Class>& other) 
      { 
        WeakRef<Class> tmp(other);
        swap(tmp);
        return *this; 
      }
    
      void swap(Ref<Class> &other)
      {
        std::swap(_content, other._content);
        _valid_flag.swap(other._valid_flag);
      }
      
      bool operator == (const WeakRef<Class>& other) const 
      { 
        return lock() == other.lock();
      }

      bool operator != (const WeakRef<Class>& other) const 
      {
        return lock() != other.lock();
      }

    private:
      /* Create a weak reference to a raw object pointer... is not safe, so we just disallow it */
      explicit WeakRef(Class *instance) 
      : _content(instance),  // if object is null, the reference is valid, just null
      _valid_flag(instance ? instance->weakref_valid_flag() : internal::ObjectValidFlag(true))
      {
      }
      
    private:
      Class *_content;
      internal::ObjectValidFlag _valid_flag;
    };
#endif // disabled


  MYSQLGRT_PUBLIC TypeHandler* get_int_type_handler();

  /** Reference object class for integer GRT values.
   * 
   * aka IntegerRef
   * 
   * To create an integer value:
   * @code
   *   InegerRef(1234);
   * @endcode
   * 
   * An implicit constructor for long is available, so you can assign
   * to a IntegerRef as:
   * @code 
   *   IntegerRef i= 1234;
   * @endcode
   *
   * @ingroup GRT
   */ 

  //----------------------------------------------------------------------
  // IntegerRef
  class IntegerRef : public ValueRef
  {
  public:
      //should be gone
      typedef internal::Integer RefType;
      typedef long storage_type;
      IntegerRef(const IntegerRef &value)
          : ValueRef(value)
      {

      }

      IntegerRef(long value)
          : ValueRef(get_int_type_handler())
      {
          _value.int_value = value;      
      }

      static inline IntegerRef cast_from(const ValueRef &svalue)
      {
          if (svalue.is_valid() && svalue.type() != IntegerType)
              throw type_error(IntegerType, svalue.type());
          return svalue;
      }

static inline storage_type extract_from(const ValueRef &svalue)
    {
      if (!svalue.is_valid() || svalue.type() != IntegerType)
        throw type_error(IntegerType, svalue.type());
      return svalue.get_data().int_value;
    }
    inline operator storage_type () const { return _value.int_value; }
    inline storage_type operator *() const { return _value.int_value; }

    static inline bool can_wrap(const ValueRef &value) 
    { 
      return (value.type() == IntegerType);
    }

    static Type static_type() { return IntegerType; }

    inline bool operator==(long v) const
    {
        return _value.int_value == v;
    }

    inline bool operator==(int v) const
    {
        return _value.int_value == v;
    }

    inline bool operator!=(long v) const
    {
        return _value.int_value != v;
    }

    inline bool operator!=(int v) const
    {
        return _value.int_value != v;
    }

  protected:
      IntegerRef()//Explicit value must be provided to construct integer
          : ValueRef(get_int_type_handler())
      {
          _value.int_value = 0;
      }

      IntegerRef(const ValueRef &value)
          : ValueRef(value)
      {

      }

  };

  //----------------------------------------------------------------------
  //DoubleRef
  MYSQLGRT_PUBLIC TypeHandler* get_double_type_handler();

  /** Reference object class for double GRT values.
   * 
   * aka DoubleRef
   * 
   * To create a double value:
   * @code
   *   DoubleRef(12.34);
   * @endcode
   * 
   * An implicit constructor for long is available, so you can assign
   * to a DoubleRef as:
   * @code 
   *   DoubleRef i= 12.34;
   * @endcode
   *
   * @ingroup GRT
   */ 
  
 class DoubleRef : public ValueRef
  {
  public:
      //should be gone
      typedef internal::Double RefType;
      typedef double storage_type;
      DoubleRef(const DoubleRef& value)
          : ValueRef(value)
      {

      }

      DoubleRef(double value)
          : ValueRef(get_double_type_handler())
      {
          _value.double_value = value;      
      }

      static inline DoubleRef cast_from(const ValueRef &svalue)
      {
          if (svalue.is_valid() && svalue.type() != DoubleType)
              throw type_error(DoubleType, svalue.type());
          return svalue;
      }

static inline storage_type extract_from(const ValueRef &svalue)
    {
      if (!svalue.is_valid() || svalue.type() != DoubleType)
        throw type_error(DoubleType, svalue.type());
      return svalue.get_data().double_value;
    }
    inline operator storage_type () const { return _value.double_value; }
    inline storage_type operator *() const { return _value.double_value; }

    static inline bool can_wrap(const ValueRef &value) 
    { 
      return (value.type() == DoubleType);
    }

    static Type static_type() { return DoubleType; }

    inline bool operator==(const DoubleRef &o) const
    {
        return _value.double_value == o._value.double_value;
    }
     
    inline bool operator==(storage_type v) const
    {
      return _value.double_value == v;
    }

    inline bool operator!=(storage_type v) const
    {
      return _value.double_value != v;
    }

    inline bool operator!=(const DoubleRef &o) const
    {
      return !(operator == (o));
    }

  protected:
      DoubleRef()
          : ValueRef(get_double_type_handler())
      {
          _value.double_value = 0;
      }

      DoubleRef(const ValueRef &value)
          : ValueRef(value)
      {

      }

  };
 
 struct StringListConstIterator;

  //----------------------------------------------------------------------
  // StringRef
 TypeHandler* get_string_type_handler(TypeHandler::TypeHandle& handle, const char* srcstring, const size_t len);

 inline TypeHandler* get_string_type_handler(TypeHandler::TypeHandle& handle, const char* srcstring)
 {
     return get_string_type_handler(handle, srcstring, strlen(srcstring));
 };

 class MYSQLGRT_PUBLIC StringRef : public ValueRef
  {
  public:
    typedef internal::String RefType;
    typedef const char* storage_type;

    static inline StringRef cast_from(const ValueRef &svalue)
    {
      if (svalue.type() != StringType)
        throw type_error(StringType, svalue.type());
      return StringRef(svalue);
    }
    
    static inline std::string extract_from(const ValueRef &svalue)
    {
      if (svalue.type() != StringType)
        throw type_error(StringType, svalue.type());
      return svalue.get_data().string_ptr;
    }

    static inline bool can_wrap(const ValueRef &value) 
    { 
      return (value.type() == internal::String::static_type());
    }
     
    static StringRef format(const char *format, ...);

    StringRef() {}

    StringRef(const StringRef &value)
      : ValueRef(value)
    {}

    StringRef(const std::string &value)
       : ValueRef()
    {
        _type_handler = get_string_type_handler(_value, value.c_str(), value.length());
        retain();
    }

    StringRef(const char *value)
       : ValueRef()
    {
        _type_handler = get_string_type_handler(_value, value);
        retain();
    }

    //inline operator storage_type () const { return content(); }
    inline operator std::string () const { return std::string(content()); }
    inline std::string operator *() const { return content(); }
     
    const char *c_str() const { return content(); }
    bool empty() const { return *content() == '\0'; }

//    Ref<internal::String> &operator= (const Ref<internal::String>& other) { swap(other._value); return *this; }

    inline bool operator==(const StringRef &v) const
    {
        return ValueRef::operator==(v);
    }
    
    /*
    inline bool operator==(const storage_type &v) const
    {
      return _value.refcounted_value.ptr_value && (*content() == v);
    }*/

    inline bool operator==(const char *v) const
    {
      return _value.string_ptr && (strcmp(content(), v)==0);
    }

    inline bool operator!=(const StringRef &v) const
    {
      return !operator ==(v);
    }

    inline bool operator!=(const storage_type &v) const
    {
      return !operator ==(v);
    }
/*
    inline bool operator!=(const char *v) const
    {
      return !operator ==(v);
    }
*/
  protected:
      friend struct StringListConstIterator;//should be fixed

    explicit StringRef(const ValueRef &ivalue)
        : ValueRef(ivalue)
    {

    }

    storage_type content() const { return _value.string_ptr; }
  };

 /** Reference object class for string GRT values.
   * 
   * aka StringRef
   * 
   * To create a string value:
   * @code
   *   StringRef("foo");
   * @endcode
   * 
   * An implicit constructor for string is available, so you can assign
   * to a StringRef as:
   * @code 
   *   StringRef s= "foo";
   * @endcode
   *
   * @ingroup GRT
   */
   
  //----------------------------------------------------------------------
  // Lists

  template<class C>
  struct TypedListConstIterator
  {
    typedef std::random_access_iterator_tag iterator_category;
    typedef C value_type;
    typedef int difference_type;
    typedef C* pointer;
    typedef C& reference;
    typedef internal::List::raw_const_iterator IterType;

    IterType iter;
    
    TypedListConstIterator() : iter(0) {}

    TypedListConstIterator(const TypedListConstIterator &content) : iter(content.iter) {}
    
    TypedListConstIterator(const IterType &content)
      : iter(content)
    {}

    inline bool operator < (const TypedListConstIterator &o) const
    {
      return iter < o.iter;
    }

    inline Ref<C> operator *() const
    {
      return iter->is_valid()?Ref<C>((C*)iter->valueptr()):Ref<C>();
    }

    inline bool operator == (const TypedListConstIterator &o) const
    {
      return iter == o.iter;
    }

    inline bool operator != (const TypedListConstIterator &o) const
    {
      return iter != o.iter;
    }

    inline TypedListConstIterator& operator ++()
    {
      ++iter;
      return *this;
    }

    inline TypedListConstIterator operator ++(int)
    {
      TypedListConstIterator temp(*this);
      ++iter;
      return temp;
    }
  };

  template<class C>
  struct TypedListConstReverseIterator
  {
    typedef std::random_access_iterator_tag iterator_category;
    typedef C value_type;
    typedef int difference_type;
    typedef C* pointer;
    typedef C& reference;
    typedef internal::List::raw_const_reverse_iterator IterType;
    
    IterType iter;
    
    TypedListConstReverseIterator() {}
    
    TypedListConstReverseIterator(const TypedListConstReverseIterator &content) : iter(content.iter) {}
    
    TypedListConstReverseIterator(const IterType &content)
    : iter(content)
    {}
    
    inline bool operator < (const TypedListConstReverseIterator &o) const
    {
      return iter < o.iter;
    }
    
    inline Ref<C> operator *() const
    {
      return Ref<C>((C*)iter->valueptr());
    }
    
    inline bool operator == (const TypedListConstReverseIterator &o) const
    {
      return iter == o.iter;
    }
    
    inline bool operator != (const TypedListConstReverseIterator &o) const
    {
      return iter != o.iter;
    }
    
    inline TypedListConstReverseIterator& operator ++()
    {
      ++iter;
      return *this;
    }
    
    inline TypedListConstReverseIterator operator ++(int)
    {
      TypedListConstReverseIterator temp(*this);
      ++iter;
      return temp;
    }
  };
  
  

  /** Base GRT list reference class.
   *
   * @ingroup GRT
   */
  class MYSQLGRT_PUBLIC BaseListRef : public ValueRef
  {
  public:
    typedef internal::List RefType;
    typedef internal::List::raw_const_iterator raw_const_iterator;
    typedef internal::List::raw_const_reverse_iterator raw_const_reverse_iterator;
    
    enum {
      npos= internal::List::npos
    };
    
    BaseListRef() {}

    BaseListRef(const BaseListRef &list)
      : ValueRef(list)
    {
    }
    
    BaseListRef(internal::List *list)
      : ValueRef(list?get_object_type_handler():get_default_type_handler())
    {
        _value.refcounted_value.ptr_value = list;
        retain();
    }

    BaseListRef(GRT *grt, bool allow_null= true)
      : ValueRef(get_object_type_handler())
    {
        _value.refcounted_value.ptr_value = new internal::List(grt, allow_null);
        retain();
    }

    BaseListRef(GRT *grt, Type type, const std::string &class_name= "", internal::Object *owner= 0, bool allow_null= true)
       : ValueRef(get_object_type_handler())
    {
        _value.refcounted_value.ptr_value = owner ? new internal::OwnedList(grt, type, class_name, owner, allow_null) : new internal::List(grt, type, class_name, allow_null);
        retain();
    }

    inline Type content_type() const { return content().content_type(); };
    inline std::string content_class_name() const { return content().content_class_name(); }

    static bool can_wrap(const ValueRef &value)
    {
      return value.type() == ListType;
    }
     
    static BaseListRef cast_from(const ValueRef &value)
    {
      return BaseListRef(value);
    }

    inline void remove(size_t index)
    {
      content().remove(index);
    }

    inline void remove_all()
    {
      while (content().count() > 0)
        content().remove(0);
    }
    
    inline size_t count() const 
    {
      return is_valid() ? content().count() : 0;
    }

    inline const ValueRef &operator[](size_t index) const
    {
      return content().get(index);
    }

    inline const ValueRef &get(size_t index) const
    {
      return content().get(index);
    }

    inline raw_const_iterator begin() const
    {
      return content().raw_begin();
    }

    inline raw_const_iterator end() const
    {
      return content().raw_end();
    }
/*
    inline raw_const_reverse_iterator rbegin() const
    {
      return content().raw_rbegin();
    }
    
    inline raw_const_reverse_iterator rend() const
    {
      return content().raw_rend();
    }
  */
    template<typename TPred>
    bool foreach(TPred pred) const
    {
      for (internal::List::raw_const_iterator end= content().raw_end(), iter= content().raw_begin();
        iter != end; ++iter)
      {
        if (!pred(*iter))
          return false;
      }
      return true;
    }

    inline size_t get_index(const ValueRef &value) const
    {
      return content().get_index(value);
    }

    inline void reorder(size_t oindex, size_t nindex)
    {
      content().reorder(oindex, nindex);
    }

    // methods beginning with g perform type checking at runtime
    inline void gset(size_t index, const ValueRef &value)
    {
      content().set_checked(index, value);
    }

    inline void ginsert(const ValueRef &value, size_t index= npos)
    {
      content().insert_checked(value, index);
    }

    inline void gremove_value(const ValueRef &value)
    {
      content().remove(value);
    }

    
    inline void gset_unchecked(size_t index, const ValueRef &value)
    {
      content().set_unchecked(index, value);
    }

    inline void ginsert_unchecked(const ValueRef &value, size_t index= npos)
    {
      content().insert_unchecked(value, index);
    }

    GRT *get_grt() const { return content().get_grt(); }

  public:
    inline internal::List &content() const { return *static_cast<internal::List*>(_value.refcounted_value.ptr_value); }

    // For consistency with other Ref<> templates use -> operator as shortcut for content().
    inline internal::List *operator->() const { return static_cast<internal::List*>(_value.refcounted_value.ptr_value); }
  protected:
    explicit BaseListRef(const ValueRef &lvalue)
        : ValueRef(lvalue)
    {
    }
  };


  //----------------------------------------------------------------------
  // ListRef<Object>
  
  
  /** GRT object list reference class.
   *
   * @ingroup GRT
   */
  template<class O>
    class ListRef : public BaseListRef
  {
  public:
    typedef TypedListConstIterator<O> const_iterator;
    typedef TypedListConstReverseIterator<O> const_reverse_iterator;
    typedef Ref<O> value_type;

    
    ListRef() {}

    ListRef(GRT *grt, bool allow_null= true)
      : BaseListRef(grt, ObjectType, O::static_class_name(), 0, allow_null)
    {
    }

    ListRef(GRT *grt, internal::Object *owner, bool allow_null= true)
      : BaseListRef(grt, ObjectType, O::static_class_name(), owner, allow_null)
    {
    }
     
    template<class Subclass>
      ListRef(const ListRef<Subclass> &other)
       : BaseListRef(other)
    {
       Subclass *x= 0;
#ifdef __GNUC__
       O *tmp __attribute__((unused))= x;// hack so that we get a compile error if Subclass is not a subclass of O
#else
       O *tmp= x;// hack so that we get a compile error if Subclass is not a subclass of O
#endif
    }

    static ListRef<O> cast_from(const ValueRef &value)
    {
      // check if a list
      if (!value.is_valid() || can_wrap(value))
        return ListRef<O>(value);

      TypeSpec expected;
      expected.base.type= ListType;
      expected.content.type= ObjectType;
      expected.content.object_class= O::static_class_name();
            
      if (value.type() == ListType)
      {
        TypeSpec actual;
        actual.base.type= ListType;
        actual.content= BaseListRef::cast_from(value)->content_type_spec();
        throw type_error(expected, actual); 
      }
      else
        throw type_error(ListType, value.type());
    }

    static bool can_wrap(const ValueRef &value);

    inline void insert(const Ref<O> &value, size_t index= npos)
    {
      content().insert_unchecked(value, index);
    }

    inline void remove_value(const Ref<O> &value)
    {
      content().remove(value);
    }
    
    // Return const Ref<> so that list[i]= newvalue; won't be attempted (that wouldnt work as expected)
    inline const Ref<O> operator[](size_t index) const
    {
      return get(index);
    }

    inline Ref<O> get(size_t index) const
    {
      return Ref<O>::cast_from(content().get(index));
    }

    inline void set(size_t index, const Ref<O> &value)
    {
      content().set_unchecked(index, value);
    }

    inline const_iterator begin() const
    {
      return const_iterator(content().raw_begin());
    }

    inline const_iterator end() const
    {
      return const_iterator(content().raw_end());
    }

    inline const_reverse_iterator rbegin() const
    {
      return const_reverse_iterator(content().raw_rbegin());
    }
    
    inline const_reverse_iterator rend() const
    {
      return const_reverse_iterator(content().raw_rend());
    }
    
    template<typename TPred>
    bool foreach(TPred pred) const
    {
      for (internal::List::raw_const_iterator end= content().raw_end(), iter= content().raw_begin();
        iter != end; ++iter)
      {
        Ref<O> tmp((O*)iter->valueptr());
        if (!pred(tmp))
          return false;
      }
      return true;
    }

  protected:
    explicit ListRef(const ValueRef &lvalue)
      : BaseListRef(lvalue)
    {
      if (lvalue.is_valid() && content().content_type() != O::static_type())
        throw type_error(O::static_type(), content().content_type(), ListType);
    }
  };

  typedef ListRef<internal::Object> ObjectListRef;

  //----------------------------------------------------------------------
  // ListRef<Integer>

  typedef ListRef<internal::Integer> IntegerListRef;

  /** GRT integer list reference class.
   *
   * aka IntegerListRef
   * 
   * @ingroup GRT
   */
  template<>
    class MYSQLGRT_PUBLIC ListRef<internal::Integer> : public BaseListRef
  {
  public:
    ListRef()
    {
    }

    ListRef(GRT *grt, internal::Object *owner= 0, bool allow_null= true)
      : BaseListRef(grt, IntegerType, "", owner, allow_null)
    {
    }

    static inline bool can_wrap(const ValueRef &value)
    {
      if (value.type() != ListType) 
        return false; 
      if (static_cast<internal::List*>(value.valueptr())->content_type() != IntegerType)
        return false; 
      return true; 
    }

    static ListRef<internal::Integer> cast_from(const ValueRef &value)
    {
      return ListRef<internal::Integer>(value);
    }

    inline void insert(const IntegerRef &value, size_t index= npos)
    {
      content().insert_unchecked(value, index);
    }

    inline IntegerRef operator[](size_t index) const
    {
      return get(index);
    }

    inline IntegerRef get(size_t index) const
    {
      return IntegerRef::cast_from(content().get(index));
    }

    inline void set(size_t index, const IntegerRef &value)
    {
      content().set_unchecked(index, value);
    }

    template<typename TPred>
    bool foreach(TPred pred) const
    {
      for (internal::List::raw_const_iterator end= content().raw_end(), iter= content().raw_begin();
        iter != end; ++iter)
      {
        if (!pred(*(internal::Integer*)iter->valueptr()))
          return false;
      }
      return true;
    }

    inline void remove_value(const IntegerRef &value)
    {
      content().remove(value);
    }

  protected:
    explicit ListRef<internal::Integer>(const ValueRef &lvalue)
      : BaseListRef(lvalue)
    {
      if (lvalue.is_valid() && content().content_type() != IntegerType)
        throw type_error(IntegerType, content().content_type(), ListType);
    }
  };


  //----------------------------------------------------------------------
  // ListRef<Double>

  typedef ListRef<internal::Double> DoubleListRef;

  /** GRT double number list reference class.
   *
   * aka DoubleListRef
   * 
   * @ingroup GRT
   */
  template<> 
  class MYSQLGRT_PUBLIC ListRef<internal::Double> : public BaseListRef
  {
  public:
    ListRef()
    {
    }

    ListRef(GRT *grt, internal::Object *owner= 0, bool allow_null= true)
      : BaseListRef(grt, DoubleType, "", owner, allow_null)
    {
    }
    
    static inline bool can_wrap(const ValueRef &value) 
    { 
      if (value.type() != ListType) 
        return false;
      if (static_cast<internal::List*>(value.valueptr())->content_type() != DoubleType)
        return false; 
      return true; 
    }

    static ListRef<internal::Double> cast_from(const ValueRef &value)
    {
      return ListRef<internal::Double>(value);
    }

    inline void insert(const DoubleRef &value, size_t index= npos)
    { 
      content().insert_unchecked(value, index);
    }

    inline DoubleRef operator[](size_t index) const
    {
      return get(index);
    }

    inline DoubleRef get(size_t index) const
    {
      return DoubleRef::cast_from(content().get(index));
    }

    inline void set(size_t index, const DoubleRef &value)
    {
      content().set_unchecked(index, value);
    }

    template<typename TPred>
    bool foreach(TPred pred) const
    {
      for (internal::List::raw_const_iterator end= content().raw_end(), iter= content().raw_begin();
        iter != end; ++iter)
      {
        if (!pred(*(internal::Double*)iter->valueptr()))
          return false;
      }
      return true;
    }

    inline void remove_value(const DoubleRef &value)
    {
      content().remove(value);
    }

  protected:
    explicit ListRef(const ValueRef &lvalue)
      : BaseListRef(lvalue)
    {
      if (lvalue.is_valid() && content().content_type() != DoubleType)
        throw type_error(DoubleType, content().content_type(), ListType);
    }
  };


  //----------------------------------------------------------------------
  // ListRef<internal::String>


  struct StringListConstIterator
  {
    typedef std::random_access_iterator_tag iterator_category;
    typedef std::string value_type;
    typedef int difference_type;
    typedef std::string* pointer;
    typedef std::string& reference;
    typedef internal::List::raw_const_iterator IterType;

    IterType iter;
    
    StringListConstIterator() {}

    StringListConstIterator(const StringListConstIterator &content) : iter(content.iter) {}
    
    StringListConstIterator(const IterType &content)
      : iter(content)
    {}

    inline bool operator < (const StringListConstIterator &o) const
    {
      return iter < o.iter;
    }

    inline StringRef operator *() const
    {
      return static_cast<StringRef>(*iter);
    }

    inline bool operator == (const StringListConstIterator &o) const
    {
      return iter == o.iter;
    }

    inline bool operator != (const StringListConstIterator &o) const
    {
      return iter != o.iter;
    }

    inline StringListConstIterator& operator ++()
    {
      ++iter;
      return *this;
    }

    inline StringListConstIterator operator ++(int)
    {
      StringListConstIterator temp(*this);
      ++iter;
      return temp;
    }
  };

  //typedef ListRef<internal::String> StringListRef;

  /** GRT string list reference class.
   *
   * aka StringListRef
   * 
   * @ingroup GRT
   */
    class MYSQLGRT_PUBLIC StringListRef : public BaseListRef
  {
  public:
    typedef StringListConstIterator const_iterator;
    typedef TypedListConstReverseIterator<internal::String> const_reverse_iterator;
    
    StringListRef()
    {
    }

    StringListRef(GRT *grt, internal::Object *owner= 0, bool allow_null= true)
      : BaseListRef(grt, StringType, "", owner, allow_null)
    {
    }

    static inline bool can_wrap(const ValueRef &value) 
    { 
      if (value.type() != ListType) 
        return false; 
      if (static_cast<internal::List*>(value.valueptr())->content_type() != StringType)
        return false; 
      return true;
    }

    static StringListRef cast_from(const ValueRef &value) THROW(type_error)
    {
      return StringListRef(value);
    }

    inline void insert(const StringRef &value, size_t index= npos)
    { 
      content().insert_unchecked(value, index);
    }

    /*
    inline Reference operator[](size_t index) THROW (bad_item)
    {
//      return 
    }*/

    inline StringRef operator[](size_t index) const
    {
      return get(index);
    }

    inline StringRef get(size_t index) const THROW (bad_item)
    {
      return StringRef::cast_from(content().get(index));
    }

    inline void set(size_t index, const StringRef &value) THROW (bad_item, std::invalid_argument)
    {
      content().set_unchecked(index, value);
    }

    inline const_iterator begin() const
    {
      return const_iterator(content().raw_begin());
    }

    inline const_iterator end() const
    {
      return const_iterator(content().raw_end());
    }

    inline const_reverse_iterator rbegin() const
    {
      return const_reverse_iterator(content().raw_rbegin());
    }
    
    inline const_reverse_iterator rend() const
    {
      return const_reverse_iterator(content().raw_rend());
    }
    
    template<typename TPred>
    bool foreach(TPred pred) const
    {
      for (internal::List::raw_const_iterator end= content().raw_end(), iter= content().raw_begin();
        iter != end; ++iter)
      {
        if (!pred(*(internal::String*)iter->valueptr()))
          return false;
      }
      return true;
    }

    inline void remove_value(const StringRef &value)
    {
      content().remove(value);
    }

    inline size_t get_index(const std::string &str)
    {
      return BaseListRef::get_index(StringRef(str));
    }

  protected:
    explicit StringListRef(const ValueRef &lvalue)
      : BaseListRef(lvalue)
    {
      if (lvalue.is_valid() && content().content_type() != StringType)
        throw type_error(StringType, content().content_type(), ListType);
    }
  };


  //----------------------------------------------------------------------
  // DictRef.

  /** GRT dictionary reference class.
   * 
   * @ingroup GRT
   */
  class MYSQLGRT_PUBLIC DictRef : public ValueRef
  {
  public:
    typedef internal::Dict RefType;

    typedef internal::Dict::const_iterator const_iterator;

  public:
    DictRef() {}

    DictRef(GRT *grt, bool allow_null= true)
      : ValueRef(get_object_type_handler())
    {
        _value.refcounted_value.ptr_value = new internal::Dict(grt, allow_null);
        retain();
    }

    DictRef(GRT *grt, Type type, const std::string &cclass="", bool allow_null= true)
      : ValueRef(get_object_type_handler())
    {
        _value.refcounted_value.ptr_value = new internal::Dict(grt, type, cclass, allow_null);
        retain();
    }

    DictRef(internal::Dict *dict)
        : ValueRef(dict?get_object_type_handler():get_default_type_handler())
    {
        _value.refcounted_value.ptr_value = dict;
        retain();
    }

    DictRef(GRT *grt, internal::Object *owner, bool allow_null= true)
      : ValueRef(get_object_type_handler())
    {
        _value.refcounted_value.ptr_value = new internal::OwnedDict(grt, AnyType, "", owner, allow_null);
        retain();
    }

    DictRef(GRT *grt, Type type, const std::string &cclass, internal::Object *owner, bool allow_null= true)
      : ValueRef(get_object_type_handler())
    {
        _value.refcounted_value.ptr_value = new internal::OwnedDict(grt, type, cclass, owner, allow_null);
        retain();
    }

    static bool can_wrap(const ValueRef& ivalue)
    {
        return ivalue.type() == DictType;
    }

    static DictRef cast_from(const ValueRef& ivalue)
    {
      if (ivalue.is_valid() && ivalue.type() != DictType)
        throw type_error(DictType, ivalue.type());
      return DictRef(ivalue);
    }

    inline Type content_type() const { return content().content_type(); };
    inline std::string content_class_name() const { return content().content_class_name(); }

    const_iterator begin() const { return content().begin(); }
    const_iterator end() const { return content().end(); }
    
    template<typename TPred>
    bool foreach(TPred pred) const
    {
      for (const_iterator end= content().end(), iter= content().begin();
        iter != end; ++iter)
      {
        if (!pred(iter->first, iter->second))
          return false;
      }
      return true;
    }

    inline bool has_key(const std::string &k) const
    {
      return content().has_key(k);
    }

    inline ValueRef operator[](const std::string &k) const
    {
      return get(k);
    }

//    inline DictRef& operator = (const DictRef &o) { DictRef tmp(o); swap(o._value); return *this; }

/*
    inline Reference operator[](const std::string &k)
    {
      if (!has_key(k))
        throw bad_item(k);
      return Reference(this, k);
    }
  */ 
    inline size_t count() const { return content().count(); }
    
    inline void remove(const std::string &k)
    {
      content().remove(k);
    }

    void reset_entries()
    {
      content().reset_entries();
    }

    inline ValueRef get(const std::string &k) const
    {
      return ValueRef(content().get(k));
    }

    inline ValueRef get(const std::string &k, const ValueRef &defvalue) const
    {
      // No need to check here if the key exists.
      // If it does not then an invalid ValueRef will be returned.
      ValueRef tmp= content().get(k);
      if (!tmp.is_valid())
        return defvalue;
      return tmp;
    }

    std::string get_string(const std::string &k, const std::string &defvalue="") const
    {
      ValueRef value= get(k);
      if (value.is_valid())
        return StringRef::extract_from(value);
      return defvalue;
    }

    internal::Integer::storage_type get_int(const std::string &k, internal::Integer::storage_type defvalue=0) const
    {
      ValueRef value= get(k);
      if (value.is_valid())
        return IntegerRef::extract_from(value);
      return defvalue;
    }

    internal::Double::storage_type get_double(const std::string &k, internal::Double::storage_type defvalue=0.0) const
    {
      ValueRef value= get(k);
      if (value.is_valid())
        return DoubleRef::extract_from(value);
      return defvalue;
    }

    inline void set(const std::string &k, const ValueRef &value)
    {
      content().set(k, value);
    }

    inline void gset(const std::string &k, const std::string &value)
    {
      content().set(k, StringRef(value));
    }

    inline void gset(const std::string &k, long value)
    {
      content().set(k, IntegerRef(value));
    }
    
    inline void gset(const std::string &k, int value)
    {
      content().set(k, IntegerRef(value));
    }

    inline void gset(const std::string &k, internal::Double::storage_type value)
    {
      content().set(k, DoubleRef(value));
    }

    inline GRT *get_grt() const
    {
      return content().get_grt();
    }
    
    inline internal::Dict &content() const { return *static_cast<internal::Dict*>(_value.refcounted_value.ptr_value); }

  protected:
    explicit DictRef(const ValueRef &dvalue)
      : ValueRef(dvalue)
    {
      if (dvalue.is_valid() && dvalue.type() != DictType)
        throw type_error(DictType, dvalue.type());
    }
  };

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

  typedef ListRef<internal::Dict> DictListRef;

  /** GRT Dict list reference class.
   *
   * aka DictListRef
   * 
   * @ingroup GRT
   */
  template<>
    class MYSQLGRT_PUBLIC ListRef<internal::Dict> : public BaseListRef
  {
  public:
    ListRef()
    {
    }

    ListRef(GRT *grt, internal::Object *owner= 0, bool allow_null= true)
      : BaseListRef(grt, DictType, "", owner, allow_null)
    {
    }

    static inline bool can_wrap(const ValueRef &value)
    {
      if (value.type() != ListType) 
        return false; 
      if (static_cast<internal::List*>(value.valueptr())->content_type() != DictType)
        return false; 
      return true; 
    }

    static ListRef<internal::Dict> cast_from(const ValueRef &value)
    {
      return ListRef<internal::Dict>(value);
    }

    inline void insert(const DictRef &value, size_t index= npos)
    {
      content().insert_unchecked(value, index);
    }

    inline DictRef operator[](size_t index) const
    {
      return get(index);
    }

    inline DictRef get(size_t index) const
    {
      return DictRef::cast_from(content().get(index));
    }

    inline void set(size_t index, const DictRef &value)
    {
      content().set_unchecked(index, value);
    }

    template<typename TPred>
    bool foreach(TPred pred) const
    {
      for (internal::List::raw_const_iterator end= content().raw_end(), iter= content().raw_begin();
        iter != end; ++iter)
      {
        if (!pred(*(internal::Dict*)iter->valueptr()))
          return false;
      }
      return true;
    }

    inline void remove_value(const DictRef &value)
    {
      content().remove(value);
    }

  protected:
    explicit ListRef<internal::Dict>(const ValueRef &lvalue)
      : BaseListRef(lvalue)
    {
      if (lvalue.is_valid() && content().content_type() != DictType)
        throw type_error(DictType, content().content_type(), ListType);
    }
  };

}
#endif