source: XIOS/trunk/src/node/field.cpp @ 641

Last change on this file since 641 was 641, checked in by rlacroix, 6 years ago

Use the filter infrastructure to handle field references.

Add a pass-through filter to do so.

  • Property copyright set to
    Software name : XIOS (Xml I/O Server)
    http://forge.ipsl.jussieu.fr/ioserver
    Creation date : January 2009
    Licence : CeCCIL version2
    see license file in root directory : Licence_CeCILL_V2-en.txt
    or http://www.cecill.info/licences/Licence_CeCILL_V2-en.html
    Holder : CEA/LSCE (Laboratoire des Sciences du CLimat et de l'Environnement)
    CNRS/IPSL (Institut Pierre Simon Laplace)
    Project Manager : Yann Meurdesoif
    yann.meurdesoif@cea.fr
  • Property svn:executable set to *
File size: 47.4 KB
Line 
1#include "field.hpp"
2
3#include "attribute_template.hpp"
4#include "object_template.hpp"
5#include "group_template.hpp"
6
7#include "node_type.hpp"
8#include "calendar_util.hpp"
9#include "message.hpp"
10#include "xios_spl.hpp"
11#include "type.hpp"
12#include "timer.hpp"
13#include "context_client.hpp"
14#include "context_server.hpp"
15#include <set>
16#include "garbage_collector.hpp"
17#include "source_filter.hpp"
18#include "store_filter.hpp"
19#include "file_writer_filter.hpp"
20#include "pass_through_filter.hpp"
21
22namespace xios{
23
24   /// ////////////////////// Définitions ////////////////////// ///
25
26   CField::CField(void)
27      : CObjectTemplate<CField>(), CFieldAttributes()
28      , refObject(), baseRefObject()
29      , grid(), file()
30      , freq_operation(), freq_write()
31      , nstep(0), nstepMax(0), isEOF(false)
32      , last_Write(), last_operation()
33      , foperation(), hasInstantData(false), hasExpression(false)
34      , active(false) , hasOutputFile(false),hasFieldOut(false), slotUpdateDate(NULL)
35      , processed(false), domAxisIds_("", ""), areAllReferenceSolved(false), areAllExpressionBuilt(false)
36      , isReadDataRequestPending(false)
37      , filterSources_()
38   { setVirtualVariableGroup(); }
39
40   CField::CField(const StdString& id)
41      : CObjectTemplate<CField>(id), CFieldAttributes()
42      , refObject(), baseRefObject()
43      , grid(), file()
44      , freq_operation(), freq_write()
45      , nstep(0), nstepMax(0), isEOF(false)
46      , last_Write(), last_operation()
47      , foperation(), hasInstantData(false), hasExpression(false)
48      , active(false), hasOutputFile(false), hasFieldOut(false), slotUpdateDate(NULL)
49      , processed(false), domAxisIds_("", ""), areAllReferenceSolved(false), areAllExpressionBuilt(false)
50      , isReadDataRequestPending(false)
51      , filterSources_()
52   { setVirtualVariableGroup(); }
53
54   CField::~CField(void)
55   {
56//      this->grid.reset();
57//      this->file.reset();
58      this->foperation.reset();
59      if (hasExpression) delete expression;
60      if (slotUpdateDate != NULL) delete slotUpdateDate;
61
62   }
63
64
65  //----------------------------------------------------------------
66
67   void CField::setVirtualVariableGroup(CVariableGroup* newVVariableGroup)
68   {
69      this->vVariableGroup = newVVariableGroup;
70   }
71
72   void CField::setVirtualVariableGroup(void)
73   {
74      this->setVirtualVariableGroup(CVariableGroup::create());
75   }
76
77   CVariableGroup* CField::getVirtualVariableGroup(void) const
78   {
79      return this->vVariableGroup;
80   }
81
82
83   std::vector<CVariable*> CField::getAllVariables(void) const
84   {
85      return this->vVariableGroup->getAllChildren();
86   }
87
88   void CField::solveDescInheritance(bool apply, const CAttributeMap* const parent)
89   {
90      SuperClassAttribute::setAttributes(parent, apply);
91      this->getVirtualVariableGroup()->solveDescInheritance(apply, NULL);
92   }
93   //----------------------------------------------------------------
94   //----------------------------------------------------------------
95
96   bool CField::updateDataServer
97      (const CDate& currDate,
98       const std::deque< CArray<double, 1>* > storedClient)
99   {
100      const CDate opeDate      = *last_operation + freq_operation;
101      const CDate writeDate    = *last_Write     + freq_write;
102
103      if (opeDate <= currDate)
104      {
105         if (this->data.numElements() != this->grid->storeIndex[0]->numElements())
106         {
107            this->data.resize(this->grid->storeIndex[0]->numElements());
108         }
109         CArray<double,1> input(data.numElements());
110         this->grid->inputFieldServer(storedClient, input);
111         (*this->foperation)(input);
112         *last_operation = currDate;
113      }
114      if (writeDate < (currDate + freq_operation))
115      {
116         this->foperation->final();
117         this->incrementNStep();
118         *last_Write = writeDate;
119         return true;
120      }
121      return false;
122   }
123
124  bool CField::dispatchEvent(CEventServer& event)
125  {
126    if (SuperClass::dispatchEvent(event)) return true;
127    else
128    {
129      switch(event.type)
130      {
131        case EVENT_ID_UPDATE_DATA :
132          recvUpdateData(event);
133          return true;
134          break;
135
136        case EVENT_ID_READ_DATA :
137          recvReadDataRequest(event);
138          return true;
139          break;
140
141        case EVENT_ID_READ_DATA_READY :
142          recvReadDataReady(event);
143          return true;
144          break;
145
146        case EVENT_ID_ADD_VARIABLE :
147          recvAddVariable(event);
148          return true;
149          break;
150
151        case EVENT_ID_ADD_VARIABLE_GROUP :
152          recvAddVariableGroup(event);
153          return true;
154          break;
155
156        default :
157          ERROR("bool CField::dispatchEvent(CEventServer& event)", << "Unknown Event");
158          return false;
159      }
160    }
161  }
162
163  void CField::sendUpdateData(void)
164  {
165    CContext* context = CContext::getCurrent();
166    CContextClient* client = context->client;
167
168    CEventClient event(getType(),EVENT_ID_UPDATE_DATA);
169
170    map<int,CArray<int, 1>* >::iterator it;
171    list<shared_ptr<CMessage> > list_msg;
172    list< CArray<double,1>* > list_data;
173
174    if (!grid->doGridHaveDataDistributed())
175    {
176       if (0 == client->clientRank)
177       {
178          for(it=grid->storeIndex_toSrv.begin();it!=grid->storeIndex_toSrv.end();it++)
179          {
180            int rank=(*it).first ;
181            CArray<int,1>& index = *(it->second) ;
182            CArray<double,1> data_tmp(index.numElements()) ;
183            for(int n=0;n<data_tmp.numElements();n++) data_tmp(n)=data(index(n)) ;
184
185            list_msg.push_back(shared_ptr<CMessage>(new CMessage)) ;
186            list_data.push_back(new CArray<double,1>(data_tmp)) ;
187            *list_msg.back()<<getId()<<*list_data.back() ;
188            event.push(rank,1,*list_msg.back()) ;
189          }
190          client->sendEvent(event) ;
191       } else client->sendEvent(event);
192    }
193    else
194    {
195      for(it=grid->storeIndex_toSrv.begin();it!=grid->storeIndex_toSrv.end();it++)
196      {
197        int rank=(*it).first ;
198        CArray<int,1>& index = *(it->second) ;
199        CArray<double,1> data_tmp(index.numElements()) ;
200        for(int n=0;n<data_tmp.numElements();n++) data_tmp(n)=data(index(n)) ;
201        list_msg.push_back(shared_ptr<CMessage>(new CMessage)) ;
202        list_data.push_back(new CArray<double,1>(data_tmp)) ;
203        *list_msg.back()<<getId()<<*list_data.back() ;
204        event.push(rank,grid->nbSenders[rank],*list_msg.back()) ;
205      }
206      client->sendEvent(event) ;
207    }
208
209    for (list< CArray<double,1>* >::iterator it = list_data.begin(); it != list_data.end(); it++) delete *it;
210  }
211
212  void CField::sendUpdateData(const CArray<double,1>& data)
213  {
214    CTimer::get("XIOS Send Data").resume();
215
216    CContext* context = CContext::getCurrent();
217    CContextClient* client = context->client;
218
219    CEventClient event(getType(), EVENT_ID_UPDATE_DATA);
220
221    map<int, CArray<int,1>* >::iterator it;
222    list<CMessage> list_msg;
223    list<CArray<double,1> > list_data;
224
225    if (!grid->doGridHaveDataDistributed())
226    {
227       if (0 == client->clientRank)
228       {
229          for (it = grid->storeIndex_toSrv.begin(); it != grid->storeIndex_toSrv.end(); it++)
230          {
231            int rank = (*it).first;
232            CArray<int,1>& index = *(it->second);
233
234            list_msg.push_back(CMessage());
235            list_data.push_back(CArray<double,1>(index.numElements()));
236
237            CArray<double,1>& data_tmp = list_data.back();
238            for (int n = 0; n < data_tmp.numElements(); n++) data_tmp(n) = data(index(n));
239
240            list_msg.back() << getId() << data_tmp;
241            event.push(rank, 1, list_msg.back());
242          }
243          client->sendEvent(event);
244       } else client->sendEvent(event);
245    }
246    else
247    {
248      for (it = grid->storeIndex_toSrv.begin(); it != grid->storeIndex_toSrv.end(); it++)
249      {
250        int rank = (*it).first;
251        CArray<int,1>& index = *(it->second);
252
253        list_msg.push_back(CMessage());
254        list_data.push_back(CArray<double,1>(index.numElements()));
255
256        CArray<double,1>& data_tmp = list_data.back();
257        for (int n = 0; n < data_tmp.numElements(); n++) data_tmp(n) = data(index(n));
258
259        list_msg.back() << getId() << data_tmp;
260        event.push(rank, grid->nbSenders[rank], list_msg.back());
261      }
262      client->sendEvent(event);
263    }
264   
265    CTimer::get("XIOS Send Data").suspend();
266  }
267
268  void CField::recvUpdateData(CEventServer& event)
269  {
270    vector<int> ranks;
271    vector<CBufferIn*> buffers;
272
273    list<CEventServer::SSubEvent>::iterator it;
274    string fieldId;
275
276    for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it)
277    {
278      int rank = it->rank;
279      CBufferIn* buffer = it->buffer;
280      *buffer >> fieldId;
281      ranks.push_back(rank);
282      buffers.push_back(buffer);
283    }
284    get(fieldId)->recvUpdateData(ranks,buffers);
285  }
286
287  void  CField::recvUpdateData(vector<int>& ranks, vector<CBufferIn*>& buffers)
288  {
289    if (data_srv.empty())
290    {
291      for (map<int, CArray<size_t, 1>* >::iterator it = grid->outIndexFromClient.begin(); it != grid->outIndexFromClient.end(); ++it)
292      {
293        int rank = it->first;
294        CArray<double,1> data_tmp(it->second->numElements());
295        data_srv.insert( pair<int, CArray<double,1>* >(rank, new CArray<double,1>(data_tmp)));
296        foperation_srv.insert(pair<int,boost::shared_ptr<func::CFunctor> >(rank,boost::shared_ptr<func::CFunctor>(new func::CInstant(*data_srv[rank]))));
297      }
298    }
299
300    CContext* context = CContext::getCurrent();
301    const CDate& currDate = context->getCalendar()->getCurrentDate();
302    const CDate opeDate      = *last_operation_srv + freq_operation_srv;
303    const CDate writeDate    = *last_Write_srv     + freq_write_srv;
304
305    if (opeDate <= currDate)
306    {
307      for (int n = 0; n < ranks.size(); n++)
308      {
309        CArray<double,1> data_tmp;
310        *buffers[n] >> data_tmp;
311        (*foperation_srv[ranks[n]])(data_tmp);
312      }
313      *last_operation_srv = currDate;
314    }
315
316    if (writeDate < (currDate + freq_operation_srv))
317    {
318      for (int n = 0; n < ranks.size(); n++)
319      {
320        this->foperation_srv[ranks[n]]->final();
321      }
322
323      *last_Write_srv = writeDate;
324      writeField();
325      *lastlast_Write_srv = *last_Write_srv;
326    }
327  }
328
329  void CField::writeField(void)
330  {
331    if (!getRelFile()->allDomainEmpty)
332    {
333      if (grid->doGridHaveDataToWrite() || getRelFile()->type == CFile::type_attr::one_file)
334      {
335        getRelFile()->checkFile();
336        this->incrementNStep();
337        getRelFile()->getDataOutput()->writeFieldData(CField::get(this));
338      }
339    }
340  }
341
342  void CField::sendReadDataRequest(void)
343  {
344    CContext* context = CContext::getCurrent();
345    CContextClient* client = context->client;
346
347    CEventClient event(getType(), EVENT_ID_READ_DATA);
348    if (client->isServerLeader())
349    {
350      CMessage msg;
351      msg << getId();
352      const std::list<int>& ranks = client->getRanksServerLeader();
353      for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
354        event.push(*itRank, 1, msg);
355      client->sendEvent(event);
356    }
357    else client->sendEvent(event);
358
359    lastDataRequestedFromServer = context->getCalendar()->getCurrentDate();
360    isReadDataRequestPending = true;
361  }
362
363  /*!
364  Send request new data read from file if need be, that is the current data is out-of-date.
365  \return true if and only if some data was requested
366  */
367  bool CField::sendReadDataRequestIfNeeded(void)
368  {
369    const CDate& currentDate = CContext::getCurrent()->getCalendar()->getCurrentDate();
370
371    bool requestData = (currentDate >= lastDataRequestedFromServer + file->output_freq.getValue());
372
373    if (requestData)
374      sendReadDataRequest();
375
376    return requestData;
377  }
378
379  void CField::recvReadDataRequest(CEventServer& event)
380  {
381    CBufferIn* buffer = event.subEvents.begin()->buffer;
382    StdString fieldId;
383    *buffer >> fieldId;
384    get(fieldId)->recvReadDataRequest();
385  }
386
387  void CField::recvReadDataRequest(void)
388  {
389    CContext* context = CContext::getCurrent();
390    CContextClient* client = context->client;
391
392    CEventClient event(getType(), EVENT_ID_READ_DATA_READY);
393    std::list<CMessage> msgs;
394
395    bool hasData = readField();
396
397    map<int, CArray<double,1>* >::iterator it;
398    for (it = data_srv.begin(); it != data_srv.end(); it++)
399    {
400      msgs.push_back(CMessage());
401      CMessage& msg = msgs.back();
402      msg << getId();
403      if (hasData)
404        msg << getNStep() - 1 << *it->second;
405      else
406        msg << size_t(-1);
407      event.push(it->first, grid->nbSenders[it->first], msg);
408    }
409    client->sendEvent(event);
410  }
411
412  bool CField::readField(void)
413  {
414    if (!getRelFile()->allDomainEmpty)
415    {
416      if (grid->doGridHaveDataToWrite() || getRelFile()->type == CFile::type_attr::one_file)
417      {
418        if (data_srv.empty())
419        {
420          for (map<int, CArray<size_t, 1>* >::iterator it = grid->outIndexFromClient.begin(); it != grid->outIndexFromClient.end(); ++it)
421            data_srv.insert(pair<int, CArray<double,1>*>(it->first, new CArray<double,1>(it->second->numElements())));
422        }
423
424        getRelFile()->checkFile();
425        this->incrementNStep();
426
427        if (!nstepMax)
428        {
429          nstepMax = getRelFile()->getDataInput()->getFieldNbRecords(CField::get(this));
430        }
431
432        if (getNStep() > nstepMax)
433          return false;
434
435        getRelFile()->getDataInput()->readFieldData(CField::get(this));
436      }
437    }
438
439    return true;
440  }
441
442  void CField::recvReadDataReady(CEventServer& event)
443  {
444    string fieldId;
445    vector<int> ranks;
446    vector<CBufferIn*> buffers;
447
448    list<CEventServer::SSubEvent>::iterator it;
449    for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it)
450    {
451      ranks.push_back(it->rank);
452      CBufferIn* buffer = it->buffer;
453      *buffer >> fieldId;
454      buffers.push_back(buffer);
455    }
456    get(fieldId)->recvReadDataReady(ranks, buffers);
457  }
458
459  void CField::recvReadDataReady(vector<int> ranks, vector<CBufferIn*> buffers)
460  {
461    CContext* context = CContext::getCurrent();
462    StdSize record;
463    std::map<int, CArray<double,1> > data;
464
465    for (int i = 0; i < ranks.size(); i++)
466    {
467      int rank = ranks[i];
468      *buffers[i] >> record;
469      isEOF = (record == size_t(-1));
470
471      if (!isEOF)
472        *buffers[i] >> data[rank];
473      else
474        break;
475    }
476
477    if (isEOF)
478      serverSourceFilter->signalEndOfStream(lastDataRequestedFromServer);
479    else
480      serverSourceFilter->streamDataFromServer(lastDataRequestedFromServer, data);
481
482    /*for (int i = 0; i < ranks.size(); i++)
483    {
484      int rank = ranks[i];
485      *buffers[i] >> record;
486      isEOF = (record == size_t(-1));
487
488      if (!isEOF)
489      {
490        CArray<int,1>& index = *grid->storeIndex_toSrv[rank];
491        CArray<double,1> data_tmp(index.numElements());
492        *buffers[i] >> data_tmp;
493        for (int n = 0; n < data_tmp.numElements(); n++)
494          instantData(index(n)) = data_tmp(n);
495      }
496      else
497        break;
498    }
499
500    if (!isEOF)
501    {
502      for (list< pair<CField*, int> >::iterator it = fieldDependency.begin(); it != fieldDependency.end(); ++it)
503        it->first->setSlot(it->second);
504
505      if (!hasExpression) // Should be always true ?
506      {
507        const std::vector<CField*>& refField = getAllReference();
508        std::vector<CField*>::const_iterator it = refField.begin(), end = refField.end();
509
510        for (; it != end; it++) (*it)->setDataFromExpression(instantData);
511        if (hasFieldOut) updateDataFromExpression(instantData);
512      }
513    }*/
514
515    isReadDataRequestPending = false;
516  }
517
518   //----------------------------------------------------------------
519
520   void CField::setRelFile(CFile* _file)
521   {
522      this->file = _file;
523      hasOutputFile = true;
524   }
525
526   //----------------------------------------------------------------
527
528   StdString CField::GetName(void)    { return StdString("field"); }
529   StdString CField::GetDefName(void) { return CField::GetName(); }
530   ENodeType CField::GetType(void)    { return eField; }
531
532   //----------------------------------------------------------------
533
534   CGrid* CField::getRelGrid(void) const
535   {
536      return this->grid;
537   }
538
539   //----------------------------------------------------------------
540
541   CFile* CField::getRelFile(void) const
542   {
543      return this->file;
544   }
545
546   StdSize CField::getNStep(void) const
547   {
548      return this->nstep;
549   }
550
551   void CField::incrementNStep(void)
552   {
553      this->nstep++;
554   }
555
556   void CField::resetNStep(void)
557   {
558      this->nstep = 0;
559   }
560
561   void CField::resetNStepMax(void)
562   {
563      this->nstepMax = 0;
564   }
565
566   //----------------------------------------------------------------
567
568   const CDuration& CField::getFreqOperation(void) const
569   {
570      return this->freq_operation;
571   }
572
573   //----------------------------------------------------------------
574
575   const CDuration& CField::getFreqWrite(void) const
576   {
577      return this->freq_write;
578   }
579
580   //----------------------------------------------------------------
581
582   boost::shared_ptr<func::CFunctor> CField::getFieldOperation(void) const
583   {
584      return this->foperation;
585   }
586
587   bool CField::isActive(void) const
588   {
589      return !this->refObject.empty();
590   }
591
592   //----------------------------------------------------------------
593
594   CArray<double, 1> CField::getData(void) const
595   {
596      return(this->data);
597   }
598
599   //----------------------------------------------------------------
600
601   boost::shared_ptr<CDate> CField::getLastWriteDate(void) const
602   {
603      return(this->last_Write);
604   }
605
606   //----------------------------------------------------------------
607
608   boost::shared_ptr<CDate> CField::getLastOperationDate(void) const
609   {
610      return(this->last_operation);
611   }
612
613   //----------------------------------------------------------------
614
615   boost::shared_ptr<COutputPin> CField::getInstantDataFilter()
616   {
617     return instantDataFilter;
618   }
619
620   //----------------------------------------------------------------
621
622   void CField::solveAllReferenceEnabledField(bool doSending2Sever)
623   {
624     CContext* context = CContext::getCurrent();
625     if (!areAllReferenceSolved)
626     {
627        areAllReferenceSolved = true;
628        if (context->hasClient)
629        {
630          solveRefInheritance(true);
631          solveBaseReference();
632        }
633
634        solveOperation();
635        solveGridReference();
636     }
637     solveGridDomainAxisRef(doSending2Sever);
638     if (context->hasClient)
639     {
640       solveTransformedGrid();
641     }
642     solveCheckMaskIndex(doSending2Sever);
643   }
644
645   std::map<int, StdSize> CField::getGridDataSize()
646   {
647     return grid->getConnectedServerDataSize();
648   }
649
650   void CField::buildAllExpressionEnabledField()
651   {
652     if (!areAllReferenceSolved) solveAllReferenceEnabledField(true);
653     if (!areAllExpressionBuilt)
654     {
655       areAllExpressionBuilt = true;
656       if (hasDirectFieldReference() && (grid_ref.isEmpty())) baseRefObject->buildAllExpressionEnabledField();
657       buildExpression();
658       active = true;
659     }
660   }
661
662   //----------------------------------------------------------------
663
664   void  CField::solveOperation(void)
665   {
666      using namespace func;
667
668      CContext* context = CContext::getCurrent();
669
670      if (!context->hasServer || !hasOutputFile) return;
671
672      StdString id;
673      if (hasId()) id = getId();
674      else if (!name.isEmpty()) id = name;
675      else if (hasDirectFieldReference()) id = baseRefObject->getId();
676
677      if (freq_op.isEmpty()) freq_op.setValue(TimeStep);
678
679      if (operation.isEmpty())
680      {
681         ERROR("CField::solveOperation(void)",
682               << "[ id = " << id << "]"
683               << "Impossible to define an operation for this field !");
684      }
685
686      if (freq_offset.isEmpty())
687        freq_offset.setValue(NoneDu);
688
689//      if (CXIOSManager::GetStatus() == CXIOSManager::LOC_SERVER)
690      if (context->hasServer)
691      {
692         if (hasOutputFile)
693         {
694           this->freq_operation_srv = this->file->output_freq.getValue();
695           this->freq_write_srv = this->file->output_freq.getValue();
696         }
697         this->lastlast_Write_srv = boost::shared_ptr<CDate>
698                        (new CDate(context->getCalendar()->getInitDate()));
699         this->last_Write_srv     = boost::shared_ptr<CDate>
700                        (new CDate(context->getCalendar()->getInitDate()));
701         this->last_operation_srv = boost::shared_ptr<CDate>
702                        (new CDate(context->getCalendar()->getInitDate()));
703//         this->foperation_srv     =
704//             boost::shared_ptr<func::CFunctor>(new CInstant(this->data_srv));
705
706         if (hasOutputFile)
707         {
708           const CDuration toffset = this->freq_operation_srv - freq_offset.getValue() - context->getCalendar()->getTimeStep();
709           *this->last_operation_srv   = *this->last_operation_srv - toffset;
710         }
711      }
712
713//      if (context->hasClient)
714//      {
715         this->freq_operation = freq_op.getValue();
716         if (hasOutputFile) this->freq_write = this->file->output_freq.getValue();
717         if (hasFieldOut)
718         {
719           this->freq_write = this->fieldOut->freq_op.getValue();
720         }
721         this->last_Write     = boost::shared_ptr<CDate>
722                        (new CDate(context->getCalendar()->getInitDate()));
723         this->last_operation = boost::shared_ptr<CDate>
724                        (new CDate(context->getCalendar()->getInitDate()));
725
726         const CDuration toffset = this->freq_operation - freq_offset.getValue() - context->getCalendar()->getTimeStep();
727         *this->last_operation   = *this->last_operation - toffset;
728
729         lastDataRequestedFromServer.setRelCalendar(*context->getCalendar());
730
731        if (operation.get() == "once") isOnceOperation = true;
732        else isOnceOperation = false;
733        isFirstOperation = true;
734
735#define DECLARE_FUNCTOR(MType, mtype) \
736   if (operation.getValue().compare(#mtype) == 0) \
737   { \
738      if (!detect_missing_value.isEmpty() && !default_value.isEmpty() && detect_missing_value == true) \
739      { \
740        boost::shared_ptr<func::CFunctor> foperation_(new C##MType(this->data,default_value)); \
741        this->foperation = foperation_; \
742      } \
743      else \
744      { \
745        boost::shared_ptr<func::CFunctor> foperation_(new C##MType(this->data)); \
746        this->foperation = foperation_; \
747      } \
748      return; \
749   }
750
751#include "functor_type.conf"
752
753         ERROR("CField::solveOperation(void)",
754               << "[ operation = " << operation.getValue() << "]"
755               << "The operation is not defined !");
756//      }
757   }
758
759   //----------------------------------------------------------------
760
761   /*!
762    * Constructs the graph filter for the field, enabling or not the data output.
763    * This method should not be called more than once with enableOutput equal to true.
764    *
765    * \param gc the garbage collector to use when building the filter graph
766    * \param enableOutput must be true when the field data is to be
767    *                     read by the client or/and written to a file
768    */
769   void CField::buildFilterGraph(CGarbageCollector& gc, bool enableOutput)
770   {
771     if (!areAllReferenceSolved) solveAllReferenceEnabledField(false);
772
773     // Start by building a filter which can provide the field's instant data
774     if (!instantDataFilter)
775     {
776       // Check if we have a reference on another field
777       if (!field_ref.isEmpty())
778       {
779         boost::shared_ptr<CPassThroughFilter> passThroughFilter(new CPassThroughFilter(gc));
780         instantDataFilter = passThroughFilter;
781         CField* fieldRef = CField::get(field_ref);
782         fieldRef->buildFilterGraph(gc, false);
783         fieldRef->getInstantDataFilter()->connectOutput(passThroughFilter, 0);
784       }
785       // Check if the data is to be read from a file
786       else if (file && !file->mode.isEmpty() && file->mode == CFile::mode_attr::read)
787         instantDataFilter = serverSourceFilter = boost::shared_ptr<CSourceFilter>(new CSourceFilter(grid));
788       else // The data might be passed from the model
789         instantDataFilter = clientSourceFilter = boost::shared_ptr<CSourceFilter>(new CSourceFilter(grid));
790     }
791
792     // If the field data is to be read by the client or/and written to a file
793     if (enableOutput && !storeFilter && !fileWriterFilter)
794     {
795       if (!read_access.isEmpty() && read_access.getValue())
796       {
797         storeFilter = boost::shared_ptr<CStoreFilter>(new CStoreFilter(gc, CContext::getCurrent(), grid));
798         instantDataFilter->connectOutput(storeFilter, 0);
799       }
800
801       if (file && (file->mode.isEmpty() || file->mode == CFile::mode_attr::write))
802       {
803         fileWriterFilter = boost::shared_ptr<CFileWriterFilter>(new CFileWriterFilter(gc, this));
804         instantDataFilter->connectOutput(fileWriterFilter, 0);
805       }
806     }
807   }
808
809   //----------------------------------------------------------------
810/*
811   void CField::fromBinary(StdIStream& is)
812   {
813      SuperClass::fromBinary(is);
814#define CLEAR_ATT(name_)\
815      SuperClassAttribute::operator[](#name_)->reset()
816
817         CLEAR_ATT(domain_ref);
818         CLEAR_ATT(axis_ref);
819#undef CLEAR_ATT
820
821   }
822*/
823   //----------------------------------------------------------------
824
825   void CField::solveGridReference(void)
826   {
827      CDomain* domain;
828      CAxis* axis;
829      std::vector<CDomain*> vecDom;
830      std::vector<CAxis*> vecAxis;
831      std::vector<std::string> domList, axisList;
832
833      if (!domain_ref.isEmpty())
834      {
835         if (CDomain::has(domain_ref.getValue()))
836         {
837           domain = CDomain::get(domain_ref.getValue());
838           vecDom.push_back(domain);
839         }
840         else
841            ERROR("CField::solveGridReference(void)",
842                  << "Reference to the domain \'"
843                  << domain_ref.getValue() << "\' is wrong");
844      }
845
846      if (!axis_ref.isEmpty())
847      {
848         if (CAxis::has(axis_ref.getValue()))
849         {
850           axis = CAxis::get(axis_ref.getValue());
851           vecAxis.push_back(axis);
852         }
853         else
854            ERROR("CField::solveGridReference(void)",
855                  << "Reference to the axis \'"
856                  << axis_ref.getValue() <<"\' is wrong");
857      }
858
859      if (!grid_ref.isEmpty())
860      {
861         if (CGrid::has(grid_ref.getValue()))
862         {
863           this->grid = CGrid::get(grid_ref.getValue());
864           domList = grid->getDomainList();
865           axisList = grid->getAxisList();
866           if (domList.empty() && axisList.empty())
867           {
868             this->grid = CGrid::createGrid(vecDom, vecAxis);
869           }
870         }
871         else
872            ERROR("CField::solveGridReference(void)",
873                  << "Reference to the grid \'"
874                  << grid_ref.getValue() << "\' is wrong");
875      }
876      else
877      {
878         this->grid = CGrid::createGrid(vecDom, vecAxis);
879      }
880
881      if (grid_ref.isEmpty() && domain_ref.isEmpty() && axis_ref.isEmpty())
882      {
883            ERROR("CField::solveGridReference(void)",
884                  << "At least one dimension must be defined for this field.");
885      }
886   }
887
888   void CField::solveGridDomainAxisRef(bool checkAtt)
889   {
890     grid->solveDomainAxisRef(checkAtt);
891   }
892
893   void CField::solveCheckMaskIndex(bool doSendingIndex)
894   {
895     grid->checkMaskIndex(doSendingIndex);
896   }
897
898   CGrid* CField::getGridRefOfBaseReference()
899   {
900     solveRefInheritance(true);
901     solveBaseReference();
902     baseRefObject->solveGridReference();
903
904     return baseRefObject->grid;
905   }
906
907   void CField::solveTransformedGrid()
908   {
909     if (!grid_ref.isEmpty() && (!field_ref.isEmpty()))
910     {
911       CField* fieldRef  = this;
912       CGrid* gridRefOfFieldRef = 0;
913       while (fieldRef->hasDirectFieldReference())
914       {
915         if ((!(fieldRef->grid_ref.isEmpty())) &&
916             (fieldRef->grid_ref.getValue() != grid_ref.getValue()))
917         {
918           gridRefOfFieldRef = fieldRef->getGridRefOfBaseReference();
919           fieldRef->addReference(this);
920           fieldRef->solveGridDomainAxisRef(false);
921           break;
922         }
923         CField* tmp = fieldRef->getDirectFieldReference();
924         fieldRef = tmp;
925       }
926
927       if ((0 == gridRefOfFieldRef) &&
928           (!(fieldRef->grid_ref.isEmpty())) &&
929           (fieldRef->grid_ref.getValue() != grid_ref.getValue()))
930       {
931         gridRefOfFieldRef = fieldRef->getGridRefOfBaseReference();
932         fieldRef->addReference(this);
933         fieldRef->solveGridDomainAxisRef(false);
934       }
935
936       CGrid* relGridRef = CGrid::get(grid_ref.getValue());
937       if ((0 != gridRefOfFieldRef) && (relGridRef != gridRefOfFieldRef) && (!(relGridRef->isTransformed())))
938       {
939         relGridRef->transformGrid(gridRefOfFieldRef);
940         filterSources_.push_back(fieldRef);
941       }
942     }
943   }
944
945   const std::vector<CField*>& CField::getFilterSources()
946   {
947     return filterSources_;
948   }
949
950   void CField::applyFilter(const CArray<double, 1>& dataToSend, CArray<double,1>& dataToReceive)
951   {
952     std::vector<CField*>::iterator  itFilterSrc, iteFilterSrc;
953     if (!filterSources_.empty())
954     {
955        itFilterSrc = filterSources_.begin(); iteFilterSrc = filterSources_.end();
956        dataToReceive = 0.0; // Reset all data destination
957        for (; itFilterSrc != iteFilterSrc; ++itFilterSrc)
958        {
959          if (0 != grid->getTransformations())
960          {
961             const std::map<int, CArray<int,1>* >& localIndexToSend = grid->getTransformations()->getLocalIndexToSendFromGridSource();
962             const std::map<int,std::vector<std::vector<std::pair<int,double> > > >& localIndexToReceive = grid->getTransformations()->getLocalIndexToReceiveOnGridDest();
963
964             sendAndReceiveTransformedData(localIndexToSend, dataToSend,
965                                           localIndexToReceive, dataToReceive);
966          }
967
968        }
969     }
970   }
971
972   void CField::sendAndReceiveTransformedData(const std::map<int, CArray<int,1>* >& localIndexToSend,
973                                              const CArray<double, 1>& dataSrc,
974                                              const std::map<int,std::vector<std::vector<std::pair<int,double> > > >& localIndexToReceive,
975                                              CArray<double,1>& dataDest)
976   {
977     CContext* context = CContext::getCurrent();
978     CContextClient* client=context->client;
979
980     // Sending data from field sources to do transformations
981     std::map<int, CArray<int,1>* >::const_iterator itbSend = localIndexToSend.begin(), itSend,
982                                                    iteSend = localIndexToSend.end();
983     int sendBuffSize = 0;
984     for (itSend = itbSend; itSend != iteSend; ++itSend) sendBuffSize = (sendBuffSize < (itSend->second)->numElements())
985                                                                        ? (itSend->second)->numElements(): sendBuffSize;
986     double* sendBuff;
987     if (0 != sendBuffSize) sendBuff = new double [sendBuffSize];
988     for (itSend = itbSend; itSend != iteSend; ++itSend)
989     {
990       int destRank = itSend->first;
991       CArray<int,1>* localIndex_p = itSend->second;
992       int countSize = localIndex_p->numElements();
993       for (int idx = 0; idx < countSize; ++idx)
994       {
995         sendBuff[idx] = dataSrc((*localIndex_p)(idx));
996       }
997       MPI_Send(sendBuff, countSize, MPI_DOUBLE, destRank, 12, client->intraComm);
998     }
999
1000     // Receiving data on destination fields
1001     std::map<int,std::vector<std::vector<std::pair<int,double> > > >::const_iterator itbRecv = localIndexToReceive.begin(), itRecv,
1002                                                                  iteRecv = localIndexToReceive.end();
1003     int recvBuffSize = 0;
1004     for (itRecv = itbRecv; itRecv != iteRecv; ++itRecv) recvBuffSize = (recvBuffSize < (itRecv->second).size())
1005                                                                        ? (itRecv->second).size() : recvBuffSize;
1006     double* recvBuff;
1007     if (0 != recvBuffSize) recvBuff = new double [recvBuffSize];
1008     for (itRecv = itbRecv; itRecv != iteRecv; ++itRecv)
1009     {
1010       MPI_Status status;
1011       int srcRank = itRecv->first;
1012       int countSize = (itRecv->second).size();
1013       MPI_Recv(recvBuff, recvBuffSize, MPI_DOUBLE, srcRank, 12, client->intraComm, &status);
1014       for (int idx = 0; idx < countSize; ++idx)
1015       {
1016         const std::vector<std::pair<int,double> >& localIndex_p = (itRecv->second)[idx];
1017         int numIndex = localIndex_p.size();
1018         for (int i = 0; i < numIndex; ++i)
1019         {
1020//           if ((localIndex_p)[i].first >= dataDest.numElements() )
1021           dataDest((localIndex_p)[i].first) += recvBuff[idx] * ((localIndex_p)[i].second);
1022         }
1023       }
1024     }
1025
1026     if (0 != sendBuffSize) delete [] sendBuff;
1027     if (0 != recvBuffSize) delete [] recvBuff;
1028   }
1029
1030   ///-------------------------------------------------------------------
1031
1032   template <>
1033   void CGroupTemplate<CField, CFieldGroup, CFieldAttributes>::solveRefInheritance(void)
1034   {
1035      if (this->group_ref.isEmpty()) return;
1036      StdString gref = this->group_ref.getValue();
1037
1038      if (!CFieldGroup::has(gref))
1039         ERROR("CGroupTemplate<CField, CFieldGroup, CFieldAttributes>::solveRefInheritance(void)",
1040               << "[ gref = " << gref << "]"
1041               << " invalid group name !");
1042
1043      CFieldGroup* group = CFieldGroup::get(gref);
1044      CFieldGroup* owner = CFieldGroup::get(boost::polymorphic_downcast<CFieldGroup*>(this));
1045
1046      std::vector<CField*> allChildren  = group->getAllChildren();
1047      std::vector<CField*>::iterator it = allChildren.begin(), end = allChildren.end();
1048
1049      for (; it != end; it++)
1050      {
1051         CField* child = *it;
1052         if (child->hasId()) owner->createChild()->field_ref.setValue(child->getId());
1053
1054      }
1055   }
1056
1057   void CField::scaleFactorAddOffset(double scaleFactor, double addOffset)
1058   {
1059     map<int, CArray<double,1>* >::iterator it;
1060     for (it = data_srv.begin(); it != data_srv.end(); it++) *it->second = (*it->second - addOffset) / scaleFactor;
1061   }
1062
1063   void CField::invertScaleFactorAddOffset(double scaleFactor, double addOffset)
1064   {
1065     map<int, CArray<double,1>* >::iterator it;
1066     for (it = data_srv.begin(); it != data_srv.end(); it++) *it->second = *it->second * scaleFactor + addOffset;
1067   }
1068
1069   void CField::outputField(CArray<double,3>& fieldOut)
1070   {
1071      map<int, CArray<double,1>* >::iterator it;
1072      for (it = data_srv.begin(); it != data_srv.end(); it++)
1073      {
1074        grid->outputField(it->first,*it->second, fieldOut.dataFirst());
1075      }
1076   }
1077
1078   void CField::outputField(CArray<double,2>& fieldOut)
1079   {
1080      map<int, CArray<double,1>* >::iterator it;
1081      for(it=data_srv.begin();it!=data_srv.end();it++)
1082      {
1083         grid->outputField(it->first,*it->second, fieldOut.dataFirst()) ;
1084      }
1085   }
1086
1087   void CField::outputField(CArray<double,1>& fieldOut)
1088   {
1089      map<int, CArray<double,1>* >::iterator it;
1090
1091      for (it = data_srv.begin(); it != data_srv.end(); it++)
1092      {
1093         grid->outputField(it->first,*it->second, fieldOut.dataFirst()) ;
1094      }
1095   }
1096
1097   void CField::inputField(CArray<double,3>& fieldOut)
1098   {
1099      map<int, CArray<double,1>*>::iterator it;
1100      for (it = data_srv.begin(); it != data_srv.end(); it++)
1101      {
1102        grid->inputField(it->first, fieldOut.dataFirst(), *it->second);
1103      }
1104   }
1105
1106   void CField::inputField(CArray<double,2>& fieldOut)
1107   {
1108      map<int, CArray<double,1>*>::iterator it;
1109      for(it = data_srv.begin(); it != data_srv.end(); it++)
1110      {
1111         grid->inputField(it->first, fieldOut.dataFirst(), *it->second);
1112      }
1113   }
1114
1115   void CField::inputField(CArray<double,1>& fieldOut)
1116   {
1117      map<int, CArray<double,1>*>::iterator it;
1118      for (it = data_srv.begin(); it != data_srv.end(); it++)
1119      {
1120         grid->inputField(it->first, fieldOut.dataFirst(), *it->second);
1121      }
1122   }
1123
1124   ///-------------------------------------------------------------------
1125
1126   void CField::parse(xml::CXMLNode& node)
1127   {
1128      SuperClass::parse(node);
1129      if (!node.getContent(this->content))
1130      {
1131        if (node.goToChildElement())
1132        {
1133          do
1134          {
1135            if (node.getElementName() == "variable" || node.getElementName() == "variable_group") this->getVirtualVariableGroup()->parseChild(node);
1136          } while (node.goToNextElement());
1137          node.goToParentElement();
1138        }
1139      }
1140    }
1141
1142  CArray<double,1>* CField::getInstantData(void)
1143  {
1144    if (!hasInstantData)
1145    {
1146      instantData.resize(grid->storeIndex_client.numElements());
1147      hasInstantData = true;
1148    }
1149    return &instantData;
1150  }
1151
1152  void CField::addDependency(CField* field, int slotId)
1153  {
1154    fieldDependency.push_back(pair<CField*,int>(field,slotId));
1155  }
1156
1157  void CField::buildExpression(void)
1158  {
1159    if (content.size() > 0)
1160    {
1161      CSimpleNodeExpr* simpleExpr = parseExpr(content+'\0');
1162      expression = CFieldNode::newNode(simpleExpr);
1163      delete simpleExpr;
1164      set<string> instantFieldIds;
1165      map<string,CField*> associatedInstantFieldIds;
1166      expression->getInstantFieldIds(instantFieldIds);
1167      for (set<string>::iterator it = instantFieldIds.begin(); it != instantFieldIds.end(); ++it)
1168      {
1169        if (*it != "this")
1170        {
1171          if (CField::has(*it))
1172          {
1173            CField* field = CField::get(*it);
1174//            field->processEnabledField();
1175            field->buildAllExpressionEnabledField();
1176            associatedInstantFieldIds[*it] = field;
1177          }
1178          else  ERROR("void CField::buildExpression(void)", << " Field " << *it << " does not exist");
1179        }
1180      }
1181
1182      set<string> averageFieldIds;
1183      map<string,CField*> associatedAverageFieldIds;
1184
1185      expression->getAverageFieldIds(averageFieldIds);
1186      for (set<string>::iterator it = averageFieldIds.begin(); it != averageFieldIds.end(); ++it)
1187      {
1188        if (CField::has(*it))
1189        {
1190           CFieldGroup* root = CFieldGroup::get("field_definition");
1191           CField* averageField = root->createChild();
1192           CField* instantField = root->createChild();
1193           averageField->field_ref = *it;
1194           averageField->hasFieldOut = true;
1195           averageField->fieldOut = instantField;
1196           instantField->freq_op = freq_op;
1197//           averageField-> processEnabledField();
1198           averageField->buildAllExpressionEnabledField();
1199           instantField->SuperClassAttribute::setAttributes(averageField, true);
1200           instantField->field_ref.reset();
1201           instantField->operation.reset();
1202
1203//           instantField-> processEnabledField();
1204           instantField->buildAllExpressionEnabledField();
1205           associatedAverageFieldIds[*it] = instantField;
1206        }
1207        else ERROR("void CField::buildExpression(void)", << " Field " << *it << " does not exist");
1208      }
1209
1210      expression->reduce(this,associatedInstantFieldIds,associatedAverageFieldIds);
1211
1212      slots.resize(instantFieldIds.size() + averageFieldIds.size());
1213      resetSlots();
1214      int slotId = 0;
1215      set<CField*> fields;
1216      expression->getFields(fields);
1217      for (set<CField*>::iterator it = fields.begin(); it != fields.end(); ++it, ++slotId) (*it)->addDependency(this,slotId);
1218      hasExpression = true;
1219    }
1220  }
1221
1222  void CField::resetSlots(void)
1223  {
1224    for (vector<bool>::iterator it = slots.begin(); it != slots.end(); ++it) *it = false;
1225  }
1226
1227  bool CField::slotsFull(void)
1228  {
1229    bool ret = true;
1230    for (vector<bool>::iterator it = slots.begin(); it != slots.end(); ++it) ret &= *it;
1231    return ret;
1232  }
1233
1234  void CField::setSlot(int slotId)
1235  {
1236    CContext* context = CContext::getCurrent();
1237    const CDate& currDate = context->getCalendar()->getCurrentDate();
1238    if (slotUpdateDate == NULL || currDate != *slotUpdateDate)
1239    {
1240      resetSlots();
1241      if (slotUpdateDate == NULL) slotUpdateDate = new CDate(currDate);
1242      else *slotUpdateDate = currDate;
1243    }
1244    slots[slotId] = true;
1245    if (slotsFull())
1246    {
1247      CArray<double,1> expr(expression->compute());
1248
1249      if (hasInstantData)
1250      {
1251        instantData = expr;
1252        for (list< pair<CField *,int> >::iterator it = fieldDependency.begin(); it != fieldDependency.end(); ++it)
1253          if (it->first != this) it->first->setSlot(it->second);
1254      }
1255
1256      if (hasOutputFile) updateDataFromExpression(expr);
1257
1258      const std::vector<CField*>& refField = getAllReference();
1259      for (std::vector<CField*>::const_iterator it = refField.begin(); it != refField.end(); it++)
1260      {
1261        if (!(*it)->hasExpression)
1262          (*it)->setDataFromExpression(expr);
1263      }
1264    }
1265  }
1266
1267   /*!
1268     This function retrieves Id of corresponding domain_ref and axis_ref (if any)
1269   of a field. In some cases, only domain exists but axis doesn't
1270   \return pair of Domain and Axis id
1271   */
1272   const std::pair<StdString,StdString>& CField::getRefDomainAxisIds()
1273   {
1274     CGrid* cgPtr = getRelGrid();
1275     if (NULL != cgPtr)
1276     {
1277       std::vector<StdString>::iterator it;
1278       if (!domain_ref.isEmpty())
1279       {
1280         std::vector<StdString> domainList = cgPtr->getDomainList();
1281         it = std::find(domainList.begin(), domainList.end(), domain_ref.getValue());
1282         if (domainList.end() != it) domAxisIds_.first = *it;
1283       }
1284
1285       if (!axis_ref.isEmpty())
1286       {
1287         std::vector<StdString> axisList = cgPtr->getAxisList();
1288         it = std::find(axisList.begin(), axisList.end(), axis_ref.getValue());
1289         if (axisList.end() != it) domAxisIds_.second = *it;
1290       }
1291     }
1292     return (domAxisIds_);
1293   }
1294
1295   CVariable* CField::addVariable(const string& id)
1296   {
1297     return vVariableGroup->createChild(id);
1298   }
1299
1300   CVariableGroup* CField::addVariableGroup(const string& id)
1301   {
1302     return vVariableGroup->createChildGroup(id);
1303   }
1304
1305   void CField::sendAddAllVariables()
1306   {
1307     if (!getAllVariables().empty())
1308     {
1309       // Firstly, it's necessary to add virtual variable group
1310       sendAddVariableGroup(getVirtualVariableGroup()->getId());
1311
1312       // Okie, now we can add to this variable group
1313       std::vector<CVariable*> allVar = getAllVariables();
1314       std::vector<CVariable*>::const_iterator it = allVar.begin();
1315       std::vector<CVariable*>::const_iterator itE = allVar.end();
1316
1317       for (; it != itE; ++it)
1318       {
1319         this->sendAddVariable((*it)->getId());
1320         (*it)->sendAllAttributesToServer();
1321         (*it)->sendValue();
1322       }
1323     }
1324   }
1325
1326   void CField::sendAddVariable(const string& id)
1327   {
1328    CContext* context = CContext::getCurrent();
1329
1330    if (!context->hasServer)
1331    {
1332       CContextClient* client = context->client;
1333
1334       CEventClient event(this->getType(),EVENT_ID_ADD_VARIABLE);
1335       if (client->isServerLeader())
1336       {
1337         CMessage msg;
1338         msg << this->getId();
1339         msg << id;
1340         const std::list<int>& ranks = client->getRanksServerLeader();
1341         for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1342           event.push(*itRank,1,msg);
1343         client->sendEvent(event);
1344       }
1345       else client->sendEvent(event);
1346    }
1347   }
1348
1349   void CField::sendAddVariableGroup(const string& id)
1350   {
1351    CContext* context = CContext::getCurrent();
1352    if (!context->hasServer)
1353    {
1354       CContextClient* client = context->client;
1355
1356       CEventClient event(this->getType(),EVENT_ID_ADD_VARIABLE_GROUP);
1357       if (client->isServerLeader())
1358       {
1359         CMessage msg;
1360         msg << this->getId();
1361         msg << id;
1362         const std::list<int>& ranks = client->getRanksServerLeader();
1363         for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1364           event.push(*itRank,1,msg);
1365         client->sendEvent(event);
1366       }
1367       else client->sendEvent(event);
1368    }
1369   }
1370
1371   void CField::recvAddVariable(CEventServer& event)
1372   {
1373
1374      CBufferIn* buffer = event.subEvents.begin()->buffer;
1375      string id;
1376      *buffer >> id;
1377      get(id)->recvAddVariable(*buffer);
1378   }
1379
1380   void CField::recvAddVariable(CBufferIn& buffer)
1381   {
1382      string id;
1383      buffer >> id;
1384      addVariable(id);
1385   }
1386
1387   void CField::recvAddVariableGroup(CEventServer& event)
1388   {
1389
1390      CBufferIn* buffer = event.subEvents.begin()->buffer;
1391      string id;
1392      *buffer >> id;
1393      get(id)->recvAddVariableGroup(*buffer);
1394   }
1395
1396   void CField::recvAddVariableGroup(CBufferIn& buffer)
1397   {
1398      string id;
1399      buffer >> id;
1400      addVariableGroup(id);
1401   }
1402
1403   DEFINE_REF_FUNC(Field,field)
1404
1405//  void CField::addReference(CField* field)
1406//  {
1407//    refObject.push_back(field);
1408//  }
1409//
1410//   //----------------------------------------------------------------
1411//
1412//   bool CField::hasDirectFieldReference(void) const
1413//   {
1414//     return !this->field_ref.isEmpty();
1415//   }
1416//
1417//   //----------------------------------------------------------------
1418//
1419//   const StdString& CField::getBaseFieldId(void) const
1420//   {
1421//      return this->getBaseFieldReference()->getId();
1422//   }
1423//
1424//   //----------------------------------------------------------------
1425//
1426//   /*!
1427//   \brief Get pointer to direct field to which the current field refers.
1428//   */
1429//   CField* CField::getDirectFieldReference(void) const
1430//   {
1431//      if (this->field_ref.isEmpty())
1432//         return this->getBaseFieldReference();
1433//
1434//      if (!CField::has(this->field_ref.getValue()))
1435//         ERROR("CField::getDirectFieldReference(void)",
1436//               << "[ ref_name = " << this->field_ref.getValue() << "]"
1437//               << " invalid field name !");
1438//
1439//      return CField::get(this->field_ref.getValue());
1440//   }
1441//
1442//   //----------------------------------------------------------------
1443//
1444//   CField* CField::getBaseFieldReference(void) const
1445//   {
1446//      return baseRefObject;
1447//   }
1448//
1449//   //----------------------------------------------------------------
1450//
1451//   const std::vector<CField*>& CField::getAllReference(void) const
1452//   {
1453//      return refObject;
1454//   }
1455//
1456//   /*!
1457//   \brief Searching for all reference of a field
1458//   If a field refers to (an)other field(s), we will search for all its referenced parents.
1459//   Moreover, if any father, direct or indirect (e.g: two levels up), has non-empty attributes,
1460//   all its attributes will be added to the current field
1461//   \param [in] apply Flag to specify whether current field uses attributes of its father
1462//               in case the attribute is empty (true) or its attributes are replaced by ones of its father (false)
1463//   */
1464//   void CField::solveRefInheritance(bool apply)
1465//   {
1466//      std::set<CField *> sset;
1467//      CField* refer_sptr;
1468//      CField* refer_ptr = this;
1469//
1470//      while (refer_ptr->hasDirectFieldReference())
1471//      {
1472//         refer_sptr = refer_ptr->getDirectFieldReference();
1473//         refer_ptr  = refer_sptr;
1474//
1475//         if(sset.end() != sset.find(refer_ptr))
1476//         {
1477//            DEBUG (<< "Circular dependency stopped for field object on "
1478//                   << "\"" + refer_ptr->getId() + "\" !");
1479//            break;
1480//         }
1481//
1482//         SuperClassAttribute::setAttributes(refer_ptr, apply);
1483//         sset.insert(refer_ptr);
1484//      }
1485//   }
1486//
1487//   /*!
1488//   \brief Only on SERVER side. Remove all field_ref from current field
1489//   On creating a new field on server side, redundant "field_ref" is still kept in the attribute list
1490//   of the current field. This function removes this from current field
1491//   */
1492//   void CField::removeRefInheritance()
1493//   {
1494//     if (this->field_ref.isEmpty()) return;
1495//     this->clearAttribute("field_ref");
1496//   }
1497//
1498//   void CField::solveBaseReference(void)
1499//   {
1500//      std::set<CField *> sset;
1501//      CField* refer_sptr;
1502//      CField* refer_ptr = this;
1503//
1504//      if (this->hasDirectFieldReference())  baseRefObject = getDirectFieldReference();
1505//      else  baseRefObject = CField::get(this);
1506//
1507//      while (refer_ptr->hasDirectFieldReference())
1508//      {
1509//         refer_sptr = refer_ptr->getDirectFieldReference();
1510//         refer_ptr  = refer_sptr;
1511//
1512//         if(sset.end() != sset.find(refer_ptr))
1513//         {
1514//            DEBUG (<< "Circular dependency stopped for field object on "
1515//                   << "\"" + refer_ptr->getId() + "\" !");
1516//            break;
1517//         }
1518//
1519//         sset.insert(refer_ptr);
1520//      }
1521//
1522//      if (hasDirectFieldReference()) baseRefObject->addReference(this);
1523//   }
1524} // namespace xios
Note: See TracBrowser for help on using the repository browser.