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

Last change on this file since 640 was 640, checked in by rlacroix, 7 years ago

Start using the filter infrastructure to read and write fields.

Note that currently only the simple cases are working. References and all types of operations are disabled.

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