//Editor-Info: -*- C++ -*-
//
//Subject: TOVE project / OVOPS++
//
//File: factory.cpp
//
//Version: $Revision: 1.36 $
//
//State: $State: Exp $
//
//Date: $Date: 1998/12/04 15:59:28 $
//
//Organisation:
//      Helsinki University of Technology
//      Laboratory of Telecommunications Software and Multimedia
// 
//Authors:
//      Pasi Nummisalo
//      Timo Pärnänen
//	Vesa-Matti Puro
//
//Description:
//      See corresponding header file.   
//
//Copyright:    
//      Copyright 1999 Helsinki University of Technology
//      ALL RIGHTS RESERVED BETWEEN JANUARY 1996 AND JUNE 1999.
//      
//Licence:
//     
//
//History:
//
//

#include "factory.h"

pfFactory :: pfFactory(void)
    : pfProtocol(),
      _aSidePrototype(),
      _bSidePrototype(),
      _bSideSet(0)
{
    return;
}

pfFactory :: pfFactory(const pfFactory &other_)
    : pfProtocol(other_),
      _aSidePrototype(other_._aSidePrototype),
      _bSidePrototype(other_._bSidePrototype),
      _bSideSet(other_._bSideSet)
{
    return;
}

pfFactory :: ~pfFactory()
{
    return;
}

pfConduit pfFactory :: createFactory(pfConduit &prototype_)
{
    pfFactory *factory = new pfFactory;
    factory->_aSidePrototype = prototype_;
    pfConduit newFactory(factory);
    return newFactory;
}

pfConduit pfFactory :: createFactory(pfConduit &aSidePrototype_,
                                     pfConduit &bSidePrototype_)
{
    pfFactory *factory = new pfFactory;
    factory->_aSidePrototype = aSidePrototype_;
    factory->_bSidePrototype = bSidePrototype_;
    factory->_bSideSet = 1;
    pfConduit newFactory(factory);
    return newFactory;
}

//
//Function: cloneImplementation
//
//Description:
//    Implement clone methods which use copyconstructor to return
//    a pointer of type pfProtocol to new object
//

pfProtocol *pfFactory :: cloneImplementation(void) const
{
    pfProtocol *factory = new pfFactory(*this);
    return factory;
}

//
//Functions: accept methods
//
//Description:
//    Factory always handles messages as synchronous
//
//

void pfFactory :: accept(pfTransporter *transporter_)
{
    if (transporter_->isSender(_sideA))
    {
        transporter_->setSenderIsA();
    }
    else
    {
        transporter_->setSenderIsB();
    }
    acceptSynchronous(transporter_);
    return;
} 

void pfFactory :: acceptSynchronous(pfTransporter *transporter_)
{
    transporter_->atFactory(this);
    return;
}

//
//Function: makeConduit
//
//Description:
//    Return cloned prototype.
//

void pfFactory :: makeConduit(pfConduit &aSide_, pfConduit &bSide_) const
{
    aSide_ = _aSidePrototype.clone();
    if (_bSideSet == 0)
    {
        bSide_ = aSide_;
    }
    else
    {
        bSide_ = _bSidePrototype.clone();
        aSide_.connectToB(bSide_);
        bSide_.connectToA(aSide_);
    }
    aSide_.setId(getId());
    bSide_.setId(getId());
    return;
}

//
//Functions: sendInstaller methods
//
//Description:
//    Send installer to the proper side of factory.
//

pfKey pfFactory 
    :: sendInstallerToA(pfConduit &conduit_,
                        bool useKey_,
                        pfKey key_)
{
    pfKey returnKey = 0;
    pfInstallTransporter installerA = 
        pfInstallTransporter::createInstallTransporter(conduit_);
    
    if (useKey_ != 0)
    {
        // Use key
        installerA.setKey(key_);
        installerA.useThisKey();
    }
    // Send installer
    toA(&installerA);
    returnKey = installerA.getKey();
    // Connect
    conduit_.connectToA(_sideA);

    return returnKey;
}

pfKey pfFactory
    :: sendInstallerToB(pfConduit &conduit_,
                        bool useKey_,
                        pfKey key_)
{
    pfKey returnKey = 0;
    pfInstallTransporter installerB =
        pfInstallTransporter::createInstallTransporter(conduit_);

    if (useKey_ != 0)
    {
        // Use key
        installerB.setKey(key_);
        installerB.useThisKey();
    }
    // Send installer
    toB(&installerB);
    returnKey = installerB.getKey();
    // Connect
    conduit_.connectToB(_sideB);

    return returnKey;
}

