#include "AdvMultiDataOperationBase.hh"


/** 
 *  Operation Base
 *
 *  @author TANIMORI Souichirou, AdvanceSoft Corp.
 *  @version 0.0
 */

//const std::string AdvMultiDataOperationBase::DOMAIN=std::string("domain");

const std::string AdvMultiDataOperationBase::className=std::string("AdvMultiDataOperationBase");

/** 
 *  constructor
 */
AdvMultiDataOperationBase::AdvMultiDataOperationBase() {
    std::string memberName=std::string("AdvMultiDataOperationBase()");

    this->source=NULL;
    DebugMessage(className, memberName, "initialize source to Null\n");
    this->method=NULL;
    DebugMessage(className, memberName, "initialize method to Null\n");
    this->result=new ElementContainerArray();
    DebugMessage(className, memberName, "create ElementContainerArray for the result\n");
}


/**
 *  constructor
 *
 * \param[in] src an element conatier as the source data
 */
AdvMultiDataOperationBase::AdvMultiDataOperationBase(ElementContainerArray *src) {
    std::string memberName=std::string("AdvMultiDataOperationBase(ElementContainerArray *)");

    this->setSource(src);
    this->method=NULL;
    DebugMessage(className, memberName, "initialize method to Null\n");
    this->result=new ElementContainerArray();
    DebugMessage(className, memberName, "create ElementContainerArray for the result\n");
}

/**
 *  constructor
 *
 *  \param[in] src     an element container as the source data
 *  \param[in] method  the method for an operation
 */
AdvMultiDataOperationBase::AdvMultiDataOperationBase(ElementContainerArray *src, AdvMultiDataMethod *method) {
    std::string memberName=std::string("AdvMultiDataOperationBase(ElementContainerArray *, AdvMultiDataMethod *)");

    this->setSource(src);
    this->setMethod(method);
    this->setDefaultParam();
    this->result=new ElementContainerArray();
    DebugMessage(className, memberName, "create ElementContainerArray for the result\n");
}

/**
 *  constructor
 *
 *  \param[in] src        an element container as the source data
 *  \param[in] methodtype the method type for an operation
 */
AdvMultiDataOperationBase::AdvMultiDataOperationBase(ElementContainerArray *src, const AdvMethodType &methodType) {
    std::string memberName=std::string("AdvMultiDataOperationBase(ElementContainerArray *, const AdvMethodtype *)");

    this->setSource(src);
    this->setMethod(methodType);
    this->setDefaultParam();
    this->result=new ElementContainerArray();
    DebugMessage(className, memberName, "create ElementContainerArray for the result\n");
}

/**
 *  constructor
 *
 *  \param[in] src        an element container as the source data
 *  \param[in] methodtype the method type for an operation
 */
AdvMultiDataOperationBase::AdvMultiDataOperationBase(ElementContainerArray *src, const std::string &methodName) {
    std::string memberName=std::string("AdvMultiDataOperationBase(ElementContainerArray *, const AdvMethodtype *)");

    this->setSource(src);
    this->setMethod(methodName);
    this->setDefaultParam();
    this->result=new ElementContainerArray();
    DebugMessage(className, memberName, "create ElementContainerArray for the result\n");
}

/**
 *  constructor
 *
 *  \param[in] src     an element container as the source data
 *  \param[in] method  the method for an operation
 *  \param[in] xLower  the lower bound of the domain for the operation
 *  \param[in] xUpper  the upper bound of the domain for the operation
 */
AdvMultiDataOperationBase::AdvMultiDataOperationBase(ElementContainerArray *src, AdvMultiDataMethod *method, const Double xLower, const Double xUpper) {
    std::string memberName=std::string("AdvMultiDataOperationBase(ElementContainerArray *, AdvMultiDataMethod *, const Double, const Double)");

    this->setSource(src);
    this->setMethod(method);
    this->setDefaultParam();
    this->setDomain(xLower, xUpper);
    this->result=new ElementContainerArray();
    DebugMessage(className, memberName, "create ElementContainerArray for the result\n");
}

AdvMultiDataOperationBase::AdvMultiDataOperationBase(ElementContainerArray *src, const AdvMethodType &methodType, const Double xLower, const Double xUpper) {
    std::string memberName=std::string("AdvMultiDataOperationBase(ElementContainerArray *, const AdvMethodtype&, const Double, const Double)");

    this->setSource(src);
    this->setMethod(methodType);
    this->setDefaultParam();
    this->setDomain(xLower, xUpper);
    this->result=new ElementContainerArray();
    DebugMessage(className, memberName, "create ElementContainerArray for the result\n");
}

AdvMultiDataOperationBase::AdvMultiDataOperationBase(ElementContainerArray *src, const std::string &methodName, const Double xLower, const Double xUpper) {
    std::string memberName=std::string("AdvMultiDataOperationBase(ElementContainerArray *, const AdvMethodtype&, const Double, const Double)");

    this->setSource(src);
    this->setMethod(methodName);
    this->setDefaultParam();
    this->setDomain(xLower, xUpper);
    this->result=new ElementContainerArray();
    DebugMessage(className, memberName, "create ElementContainerArray for the result\n");
}

/**
 *  constructor
 *
 *  \param[in] src     an element container as the source data
 *  \param[in] method  the method for an operation
 *  \param[in] lower  the index for the lower bound of the domain for the operation
 *  \param[in] upper  the index for the upper bound of the domain for the operation
 */
AdvMultiDataOperationBase::AdvMultiDataOperationBase(ElementContainerArray *src, AdvMultiDataMethod *method, const UInt4 lower, const UInt4 upper) {
    std::string memberName=std::string("AdvMultiDataOperationBase(ElementContainerArray *, AdvMethod *, const UInt4, const UInt4)");

    this->setSource(src);
    this->setMethod(method);
    this->setDefaultParam();
    this->setDomain(lower, upper);
    this->result=new ElementContainerArray();
    DebugMessage(className, memberName, "create ElementContainerArray for the result\n");
}

AdvMultiDataOperationBase::AdvMultiDataOperationBase(ElementContainerArray *src, const AdvMethodType &methodType, const UInt4 lower, const UInt4 upper) {

    std::string memberName=std::string("AdvMultiDataOperationBase(ElementContainerArray *, const AdvMethodType &, const UInt4, const UInt4)");

    this->setSource(src);
    this->setMethod(methodType);
    this->setDefaultParam();
    this->setDomain(lower, upper);
    this->result=new ElementContainerArray();
    DebugMessage(className, memberName, "create ElementContainerArray for the result\n");
}

AdvMultiDataOperationBase::AdvMultiDataOperationBase(ElementContainerArray *src, const std::string &methodName, const UInt4 lower, const UInt4 upper) {
    std::string memberName=std::string("AdvMultiDataOperationBase(ElementContainerArray *, const estd::string &, const UInt4, const UInt4)");

    this->setSource(src);
    this->setMethod(methodName);
    this->setDefaultParam();
    this->setDomain(lower, upper);
    this->result=new ElementContainerArray();
    DebugMessage(className, memberName, "create ElementContainerArray for the result\n");
}

/** 
 *  constructor with determing a AdvDomain for the operation
 *
 *  \deprecated
 *  \param[in] src     an element container as the source data
 *  \param[in] xLower  the lower bound of the domain for the operation
 *  \param[in] xUpper  the upper bound of the domain for the operation
 */
AdvMultiDataOperationBase::AdvMultiDataOperationBase(ElementContainerArray *src, const Double xLower, const Double xUpper) {
    this->setSource(src);
    for (UInt4 i=0; i<this->source->PutSize(); ++i) {
        this->domains.at(i).setType(AdvDomain::CC);
        this->domains.at(i).setRange(xLower, xUpper);
    }
    this->result=new ElementContainerArray(src->PutHeader());
}

/**
 *  destructor
 */
AdvMultiDataOperationBase::~AdvMultiDataOperationBase() {
    std::string memberName=std::string("~AdvMultiDataOperationBase()");
    DebugMessage(className, memberName, "enter\n");
    this->result=static_cast<ElementContainerArray*>(NULL);
    this->method=static_cast<AdvMultiDataMethod*>(NULL);
    this->source=static_cast<ElementContainerArray*>(NULL);
    DebugMessage(className, memberName, "exit\n");
};


/**
 *  set an element container as source data for the operation
 *
 *  \param[in] src  an element container as the source data
 */
void AdvMultiDataOperationBase::setSource(ElementContainerArray *src) {
    std::string memberName=std::string("setSource(ElementContainerArray)");

    assert(src != static_cast<ElementContainerArray*>(NULL));
    assert(src->PutSize() >= 2);
    this->source=src;
    DebugMessage(className, memberName, "\n");
    this->domains=*(new std::vector<AdvDomain>(src->PutSize()));
    for (UInt4 i=0; i<src->PutSize(); ++i) {
        this->domains.at(i)=*(new AdvDomain());
        ElementContainer ec=this->source->Put(i);
        this->domains.at(i).setSource(ec);
    }
    DebugMessage(className, memberName, "initialize domain (set source)\n");
}

/**
 *  set an algorithm for the operation
 *
 *  \param[in] methodc an instanse of the class implementsd algorithm for the operation
 */
void AdvMultiDataOperationBase::setMethod(AdvMultiDataMethod *method) {
    std::string memberName=std::string("setMethod(AdvMultiDataMethod *)");

    assert(method != static_cast<AdvMultiDataMethod*>(NULL));
    this->method = method;
    DebugMessage(className, memberName, "\n");
}

/**
 *  set an algorithm for the operation
 *
 *  \param[in] type method type
 */
void AdvMultiDataOperationBase::setMethod(const AdvMethodType &type) {
    std::string memberName=std::string("setMethod(const AdvMethodType &)");
    DebugMessage(className, memberName, "enter\n");
    DebugMessage(className, memberName, __FILE__, __LINE__, "id=%d name=%s symbol=%s\n", type.value, type.name.c_str(), type.symbol.c_str());
    DebugMessage(className, memberName, __FILE__, __LINE__, "id=%d name=%s symbol=%s\n", UNKNOWN_METHOD_TYPE.value, UNKNOWN_METHOD_TYPE.name.c_str(), UNKNOWN_METHOD_TYPE.symbol.c_str());

    assert( type.value != UNKNOWN_METHOD_TYPE.value);
    AdvMultiDataMethodFactory *factory = AdvMultiDataMethodFactory::getInstance();
    this->method = factory->createMethod(type);
    DebugMessage(className, memberName, "exit\n");
}


/**
 *  set an algorithm for the operation
 *
 * \param[in] methodName method name
 */
void AdvMultiDataOperationBase::setMethod(const std::string &methodName) {
    std::string memberName=std::string("setMethod(const std::string &)");

    DebugMessage(className, memberName, "enter\n");
//    assert( methodName == BSPLINE.name   || methodName == MOVING_AVERAGE.name   || methodName == LEVMAR.name ||
//            methodName == BSPLINE.symbol || methodName == MOVING_AVERAGE.symbol || methodName == LEVMAR.symbol); 

    AdvMultiDataMethodFactory *factory = AdvMultiDataMethodFactory::getInstance();
    this->method = factory->createMethod(methodName);
    DebugMessage(className, memberName, "exit\n");
}


/** 
 *  set member variables by given values
 *
 *  \deprecated
 *  \param[in] src     an element container as the source data
 *  \param[in] xLower  the lower bound of the domain for the operation
 *  \param[in] xUpper  the upper bound of the domain for the operation
 */
void AdvMultiDataOperationBase::setDomain(ElementContainerArray *src, const Double xLower, const Double xUpper) {

    assert(src->PutSize() >= 2 );
    assert(this->result->PutHeaderPointer() != static_cast<HeaderBase*>(NULL));

    this->setSource(src);
    for (UInt4 i=0; i<this->source->PutSize(); ++i) {
        this->domains.at(i).setRange(xLower, xUpper);
    }
}


/** 
 *  set the domain domain by giving the both bounds
 *
 *  \param[in] xLower  the lower bound of the domain for the operation
 *  \param[in] xUpper  the upper bound of the domain for the operation
 */
void AdvMultiDataOperationBase::setDomain(const Double xLower, const Double xUpper) {
    std::string memberName=std::string("setDomain(const Double, const Double)");

    DebugMessage(className, memberName, "enter\n");
    for (UInt4 i=0; i<this->source->PutSize(); ++i) {
        this->domains.at(i).setRange(xLower, xUpper);
    }
    DebugMessage(className, memberName, "exit\n");
}

void AdvMultiDataOperationBase::setDomain(const UInt4 i, const Double xLower, const Double xUpper) {
    std::string memberName=std::string("setDomain(const Double, const Double)");

    DebugMessage(className, memberName, "enter\n");
    this->domains.at(i).setRange(xLower, xUpper);
    DebugMessage(className, memberName, "exit\n");
}



/**
 *  set the domain by the indices for the both bounds
 *
 *  \param[in] lower  the index for the lower bound of the domain for the operation
 *  \param[in] upper  the index for the upper bound of the domain for the operation
 */
void AdvMultiDataOperationBase::setDomain(const UInt4 lower, const UInt4 upper) {
    std::string memberName=std::string("setDomain(const UInt4, const UInt4)");

    DebugMessage(className, memberName, "enter\n");
    for (UInt4 i=0; i<this->source->PutSize(); ++i) {
        this->domains.at(i).setRange(lower, upper);
    }
    DebugMessage(className, memberName, "exit\n");
}


void AdvMultiDataOperationBase::setDomain(const UInt4 i, UInt4 lower, UInt4 upper) {
    std::string memberName=std::string("setDomain(const UInt4 ,sconst UInt4, const UInt4)");
    DebugMessage(className, memberName, "enter\n");
    this->domains.at(i).setRange(lower, upper);
    DebugMessage(className, memberName, "exit\n");
}

void AdvMultiDataOperationBase::setDomainByBinBoundID(const UInt4 lower, const UInt4 upper) {
    std::string memberName=std::string("setDomainByBinBoundID(const UInt4, const UInt4)");

    DebugMessage(className, memberName, "enter\n");
    for (UInt4 i=0; i<this->source->PutSize(); ++i) {
        this->domains.at(i).setBinBoundRange(lower, upper);
    }
    DebugMessage(className, memberName, "exit\n");
}

void AdvMultiDataOperationBase::setDomainByBinBoundID(const UInt4 i, const UInt4 lower, const UInt4 upper) {
    std::string memberName=std::string("setDomainByBinBoundID(const UInt4, const UInt4)");

    DebugMessage(className, memberName, "enter\n");
    this->domains.at(i).setBinBoundRange(lower, upper);
    DebugMessage(className, memberName, "exit\n");
}

void AdvMultiDataOperationBase::setDomainByBinID(const UInt4 lower, const UInt4 upper) {
    std::string memberName=std::string("setDomainByBinID(const UInt4, const UInt4)");

    DebugMessage(className, memberName, "enter\n");
    for (UInt4 i=0; i<this->source->PutSize(); ++i) {
        this->domains.at(i).setBinRange(lower, upper);
    }
    DebugMessage(className, memberName, "exit\n");
}

void AdvMultiDataOperationBase::setDomainByBinID(const UInt4 i, const UInt4 lower, const UInt4 upper) {
    std::string memberName=std::string("setDomainByBinID(const UInt4, const UInt4)");

    DebugMessage(className, memberName, "enter\n");
    this->domains.at(i).setBinRange(lower, upper);
    DebugMessage(className, memberName, "exit\n");
}

/**
 *  set the types of the domain by bin bounds
 */
void AdvMultiDataOperationBase::setDomain(const AdvDomain::BoundsType type) {
    for (UInt4 i=0; i<this->source->PutSize(); ++i) {
        this->domains.at(i).setType(type);
    }
}


/**
 *  \return the domain for the operation
 */
std::vector<AdvDomain> AdvMultiDataOperationBase::getDomain() {
    return this->domains;
}

/** get the domain of the i-th. source data.
 */
AdvDomain AdvMultiDataOperationBase::getDomain(UInt4 i) {
    if (i < this->domains.size()) {
        return this->domains.at(i);
    } else {
        return *(new AdvDomain());
    }
}

/**
 *  \return the lower bound of the domain
 */
std::vector<Double> AdvMultiDataOperationBase::getLowerBound() {
    std::vector<Double> *retval=new std::vector<Double>();
    for (std::vector<AdvDomain>::const_iterator d=this->domains.begin(); d != this->domains.end(); ++d) {
        retval->push_back((*d).getLowerBound());
    }
    return *retval;
}

Double AdvMultiDataOperationBase::getLowerBound(UInt4 i) {
    return this->domains.at(i).getLowerBound();
}

/**
 *  \return the upper bound of the domain
 */
std::vector<Double> AdvMultiDataOperationBase::getUpperBound() {
    std::vector<Double> *retval=new std::vector<Double>();
    for (std::vector<AdvDomain>::const_iterator d=this->domains.begin(); d != this->domains.end(); ++d) {
        retval->push_back((*d).getUpperBound());
    }
    return *retval;
}

Double AdvMultiDataOperationBase::getUpperBound(UInt4 i) {
    return this->domains.at(i).getUpperBound();
}

/**
 *  \return the index of the lower bound of the domain
 */
std::vector<UInt4> AdvMultiDataOperationBase::getLowerBoundID() {
    std::vector<UInt4> *retval=new std::vector<UInt4>();
    for (std::vector<AdvDomain>::const_iterator d=this->domains.begin(); d != this->domains.end(); ++d) {
        retval->push_back((*d).getUpperBoundID());
    }
    return *retval;
}

UInt4 AdvMultiDataOperationBase::getLowerBoundID(UInt4 i) {
    return this->domains.at(i).getLowerBoundID();
}

/**
 *  \return the index of the upper bound of the domain
 */
std::vector<UInt4> AdvMultiDataOperationBase::getUpperBoundID() {
    std::vector<UInt4> *retval=new std::vector<UInt4>();
    for (std::vector<AdvDomain>::const_iterator d=this->domains.begin(); d != this->domains.end(); ++d) {
        retval->push_back((*d).getUpperBoundID());
    }
    return *retval;
}

UInt4 AdvMultiDataOperationBase::getUpperBoundID(UInt4 i) {
    return this->domains.at(i).getUpperBoundID();
}


/**
 *  set the parameters for the operation
 *
 *  \param[in] param  a set of parameters for the operaion
 */
void AdvMultiDataOperationBase::setParam(AdvParamSet param) {
    this->param=param;
}

/**
 *  set the parameters for the operation to default values
 */
void AdvMultiDataOperationBase::setDefaultParam() {
    std::string memberName=std::string("setDefaultParam()");
    DebugMessage(className, memberName, "enter\n");

    this->param=this->method->setDefaultParam(*(this->source));
    DebugMessage(className, memberName, "set a set of parames to default values\n");
    //this->domain.setRange(static_cast<UInt4>(0), this->source->PutSize( this->source->PutYKey() )-1U );
    for (UInt4 i=0; i < this->source->PutSize(); ++i) {
        ElementContainer ec=this->source->Put(i);
        this->domains.at(i) = *(new AdvDomain());
        this->domains.at(i).setSource(ec);
        this->domains.at(i).setBinBoundRange(static_cast<UInt4>(0), ec.PutSize( ec.PutXKey() )-1U );
    }

    DebugMessage(className, memberName, "set range of the domain\n");
    DebugMessage(className, memberName, "exit\n");
}

/**
 *  \return a set of parameters as result of the operation
 */
AdvParamSet AdvMultiDataOperationBase::getParam() {
    return this->param;
}

/**
 *  \return a set of fitted parameters
 */
AdvParamSet AdvMultiDataOperationBase::getFittedParam() {
    return this->method->getFittedParam();
}

#include <typeinfo>
/**
 *  set a boolean parameter with key to the given value
 *
 *  \param[in] key   the key for the boolean parameter
 *  \param[in] value the value of the boolean parameter
 */
void AdvMultiDataOperationBase::setParam(std::string key, const Bool value) {
    std::string memberName=std::string("setParam(std::string, Bool");
    DebugMessage(className, memberName, "key \"%s\", value's type; %s\n", key.c_str(), typeid(value).name());

    if (! this->param.contain(key) ) {
        this->param.add(key, value);
    } else {
        this->param.replace(key, value);
    }
}

/**
 *  set a Int4 type parameter with key to the given value
 *
 *  \param[in] key   the key for the Int4 type parameter
 *  \param[in] value the value of the Int4 type parameter
 */
void AdvMultiDataOperationBase::setParam(std::string key, const Int4 value) {
    std::string memberName=std::string("setParam(std::string, Int4)");
    DebugMessage(className, memberName, "key \"%s\", value's type; %s\n", key.c_str(), typeid(value).name());

    if (! this->param.contain(key)) {
         this->param.add(key, value); 
    } else {
         this->param.replace(key, value); 
    }
}

/**
 *  set a UInt4 type parameter with key to the given value
 *
 *  \param[in] key   the key for the UInt4 type parameter
 *  \param[in] value the value of the UInt4 type parameter
 */
void AdvMultiDataOperationBase::setParam(std::string key, const UInt4 value) {
    std::string memberName=std::string("setParam(std::string, UInt4)");
    DebugMessage(className, memberName, "key \"%s\", value's type; %s\n", key.c_str(), typeid(value).name());

    if ( ! this->param.contain(key) ) {
        this->param.add(key, value);

    } else {
        this->param.replace(key, value); 
    }
}

/**
 *  set a Double type parameter with key to the given value
 *
 *  \param[in] key   the key for the Double type parameter
 *  \param[in] value the value of the Double type parameter
 */
void AdvMultiDataOperationBase::setParam(std::string key, const Double value) {
    std::string memberName=std::string("setParam(std::string, Double)");
    DebugMessage(className, memberName, "value's type; %s\n", typeid(value).name());

    if ( ! this->param.contain(key) ) {
        this->param.add(key, value);
    } else {
        this->param.replace(key, value);
    }
}


/**
 *  set a Double type std::vector with key
 *
 *  \param[in] key   the key for the Double type std::vector
 *  \param[in] value the Double type std::vector
 */
void AdvMultiDataOperationBase::setParam(std::string key, std::vector<Double> value) {

    if ( ! this->param.contain(key) ) {
        this->param.add(key, value);
    } else {
        this->param.replace(key, value); 
    }
}

/**
 *  set the i-th component of the Double type std::vector with key
 *
 *  \param[in] key   the key for the Double type std::vector
 *  \param[in] i     the incex for the compoment of the vector
 *  \param[in] value the value of the compoment
 */
void AdvMultiDataOperationBase::setParam(std::string key, const UInt4 i, const Double value) {

    std::string memberName=std::string("setParam(std::string, UInt4, Double)");

    if ( ! this->param.contain(key) ) {
        errorMessage(className, memberName, "no data with key %s", key.c_str());
    } else {
        this->param.replace(key, i, value);
    }
}

/**
 *  set a Double type matrix with key
 *
 *  \param[in] key   the key for the Double type matrix
 *  \param[in] value the Double type matrix
 */
void AdvMultiDataOperationBase::setParam(std::string key, std::vector< std::vector<Double> > value) {

    if ( ! this->param.contain(key) ) {
        this->param.add(key, value);
    } else {
        this->param.replace(key, value); 
    }
}

/**
 *  set the (i, j) component of the Double type matrix with key
 *
 *  \param[in] key   the key for the Double type matrix
 *  \param[in] i     the row    incex for the compoment of the matrix
 *  \param[in] j     the column incex for the compoment of the matrix
 *  \param[in] value the value of the compoment
 */
void AdvMultiDataOperationBase::setParam(std::string key, const UInt4 i, const UInt4 j, const Double value) {

    std::string memberName=std::string("setParam(std::string&, UInt4, UInt4, Double)");

    if ( ! this->param.contain(key) ) {
        errorMessage(className, memberName, "no data with key %s", key.c_str());
    } else {
        this->param.replace(key, i, j, value);
    }
}


/**
 *  set a list of peaks with key
 *
 *  \param[in] key   the key for a list of peaks
 *  \param[in] value a list of peaks
 */
void AdvMultiDataOperationBase::setParam(std::string key, AdvPeakData value) {

    if ( ! this->param.contain(key) ) {
        this->param.add(key, value);
    } else {
        this->param.replace(key, value);
    }
}

/**
 *  set a list of functions as a function
 *
 *  \param[in] key   the key for a function list
 *  \param[in] value a list of functions
 */
void AdvMultiDataOperationBase::setParam(std::string key, std::vector<AdvFuncBase*> value) {
    if ( ! this->param.contain(key) ) {
        this->param.add(key, value);
    } else {
        this->param.replace(key, value);
    }
}

/**
 *  set expr as a list of functions
 *
 *  \param[in] key  the key for a expression
 *  \paran[in] expr an expression for a list of functions
 */
void AdvMultiDataOperationBase::setParam(std::string key, std::string expr) {
    std::string memberName = std::string("setParam(std::string, std::string)");

    AdvFuncParser *parser = new AdvFuncParser(expr);
    std::vector<AdvFuncBase*> value=parser->parse();
    if (value.empty()) {
        errorMessage(className, memberName, "fail to craete function list: %s\n", expr.c_str());
    } else {
        if ( ! this->param.contain(key) ){
            this->param.add(key, value);
        } else {
            this->param.replace(key, value);
        }
    }
}


void AdvMultiDataOperationBase::setParam(std::string key, std::vector< std::vector<AdvFuncBase*> > value) {
    if ( ! this->param.contain(key) ) {
        this->param.add(key, value);
    } else {
        this->param.replace(key, value);
    }
}

void AdvMultiDataOperationBase::setParam(std::string key, std::vector<std::string> expr) {
    std::string memberName = std::string("setParam(std::string, std::vector<std::string>)");

    std::vector< std::vector<AdvFuncBase*> > funcMatrix = *(new std::vector< std::vector<AdvFuncBase*> >());
    for (std::vector<std::string>:: const_iterator elem=expr.begin(); elem != expr.end(); ++elem) {
        AdvFuncParser *parser = new AdvFuncParser(*elem);
        std::vector<AdvFuncBase*> funcList=parser->parse();
        if (funcList.empty()) {
            errorMessage(className, memberName, "fail to craete function list: %s\n", (*elem).c_str());
            return;
        }
        funcMatrix.push_back(funcList);
    }

    if ( ! this->param.contain(key) ) {
        this->param.add(key, funcMatrix);
    } else {
        this->param.add(key, funcMatrix);
    }
}

/**
 *  set python object as Double type std::vector
 *
 *  \param[in] key   the key for a vector
 *  \param[in] value a pyhon object as a Double type vecotr
 */
void AdvMultiDataOperationBase::setParam(std::string key, PyObject *value) {
    if ( ! this->param.contain(key) ) {
       this->param.add(key, value);
    } else {
       this->param.replace(key, value);
    }
}

/**
 *  check consistency of paremters for the operation
 *
 *  \retval true if paramters are consistent
 */
Bool AdvMultiDataOperationBase::checkParam() {
    std::string memberName=std::string("checkParam");

    DebugMessage(className, memberName, "enter\n");
    return this->method->checkParam(*(this->source), this->domains, this->param);
}

/**
 *  \return an element container as the result of operarion
 */
ElementContainerArray AdvMultiDataOperationBase::getResult() {
    std::string memberName = std::string("getResult()");

    DebugMessage(className, memberName, "enter\n");
    ElementContainerArray *result=new ElementContainerArray();
    this->method->toElementContainerArray(*(this->source), *result);
    DebugMessage(className, memberName, "exit\n");
    return *result;
}

ElementContainer AdvMultiDataOperationBase::getResult(UInt4 i) {
    std::string memberName = std::string("getResult(UInt4 i)");

    DebugMessage(className, memberName, "enter\n");
    ElementContainer *retval=new ElementContainer();
    this->method->toElementContainer(*(this->source), i, *retval);
    DebugMessage(className, memberName, "exit\n");
    return *retval;
}
