#ifndef OWNER_H  //fix 
#define OWNER_H

#ifndef OWN_H
#include "Own.h"
#endif

#ifndef ARRAY_OF_OWN_H
#include "Array_of_own.h"
#endif

namespace MM
{

/*
template <class R>
class Taker
{
public:
    virtual void    adopt  (R *obj)=0;
};
//*/

template <class OBJ>
class Aware
{
public:
    virtual void    forget   (OBJ &obj)=0;
};

    
template <class OBJ>
class Owner
{
public:
    virtual void    erase (OBJ &obj)=0;
};


template <class OBJ>
class Connections
{
    Own < Owner <OBJ> >           owner_;
    Array_of_own < Aware <OBJ> >  aware_;

public:
    void    erase (OBJ &obj)                      
    {
        for (int i=0;  i<aware_.size();  ++i)
            aware_[i].forget (obj);                

        owner_().erase (obj);
    }

    void    set_ownership (Owner <OBJ> * owner)  {owner_.adopt (owner);}
    void    remember      (Aware <OBJ> * aware)  {aware_.push_back (aware);}
};  

template <class HOLDER, class OBJ>
class Owner_impl : public Owner <OBJ>
{
    HOLDER  &holder_;

public:
    explicit Owner_impl (HOLDER & holder) : holder_(holder) { }

    void            erase (OBJ &obj)     {holder_.erase (obj);}
};

template <class HOLDER, class OBJ>
class Aware_impl : public Aware <OBJ>
{
    HOLDER  &holder_;

public:
    explicit Aware_impl (HOLDER & holder) : holder_(holder) { }

    void            forget (OBJ &obj)     {holder_.forget (obj);}
};

template <class HOLDER, class OBJ> void
set_ownership (OBJ & obj, HOLDER & holder)
{
        obj.connections_.set_ownership (new Owner_impl <HOLDER, OBJ> (holder));
}

template <class HOLDER, class OBJ> void
remember (OBJ & obj, HOLDER & holder)    //fix to keep
{
    obj.connections_.remember (new Aware_impl <HOLDER, OBJ> (holder));
}

}//MM

#endif //OWNER_H
