FieldFunctor.hpp

00001 #ifndef __FISH_BONE_FIELDFUNCTOR_HPP
00002 #define __FISH_BONE_FIELDFUNCTOR_HPP
00003 
00004 #include <bone/FieldOperatorObject.hpp>
00005 
00006 namespace Wizt
00007 {
00008 using namespace Fiber;
00009 using namespace Eagle;
00010 
00046 template <class Operation>
00047 class   FieldFunctor : public FieldOperatorObject
00048 {
00049 protected:
00050 
00052         bool doCreateArrayIfRequired;
00053 
00054 public:
00055         typedef typename Operation::input_type  input_type;
00056         typedef typename Operation::output_type output_type; 
00057 
00059         VOutput<Fiber::Field>   Result;
00060 
00064         FieldFunctor(const string&name, int p, const RefPtr<VCreationPreferences>&VP)
00065         : VObject(name, p, VP)
00066         , Fish<VObject>(this)
00067         , Fish<Field>("inputfield")
00068         , FieldOperatorObject(name, "inputfield", p, VP)
00069         , doCreateArrayIfRequired(true)
00070         , Result( self(), "result" )
00071         {
00072                 acceptType<input_type>();
00073         }
00074 
00079         struct Op : Field::Iterator, Operation
00080         {
00081                 RefPtr<Field>   ResultField;
00082                 bool            Modified;
00083                 bool            doCreateArrayIfRequired;
00084                 const FieldFunctor&theFieldFunctor;
00085                 VRequest          &theContext;
00086 
00087                 Op(const FieldFunctor&F, VRequest&Context)
00088                 : Modified(false)
00089                 , theFieldFunctor(F)
00090                 , theContext(Context)
00091                 {}
00092 
00094                 override bool apply(const RefPtr<FragmentID>&frag, const RefPtr<CreativeArrayBase>&CAB)
00095                 {
00096                         if (ResultField)
00097                         {
00098                                 if (RefPtr<CreativeArrayBase> ResultCreator = ResultField->getCreator( frag ) )
00099                                 {
00100                                         if (CAB->isNewerThan(*ResultCreator) )
00101                                         {
00102 //                                      puts("INPUT is NEWER");
00103                                         }
00104                                         else
00105                                         {
00106 //                                      puts("INPUT is OLDER"); 
00107                                         return true;
00108                                         }
00109                                 } 
00110                         } 
00111 
00112                         // 
00113                         // TODO: Move this into an OnDemandCreator 
00114                         //
00115 
00116                 const RefPtr<MemBase>&Data = CAB->create();
00117                         if (!Data)
00118                         {
00119                                 puts("FieldFunctor: DATA CREATION FAILED!"); fflush(stdout); 
00120                                 return false;
00121                         }
00122 
00123                 TypedIterator<input_type> T = Data; 
00124                         if (!T)
00125                         {
00126                                 T = Data->makeMemArray( NullPtr() ); 
00127                                 if (!T)
00128                                 {
00129 
00130                                 FieldSelector   FieldSelection; 
00131                                         theFieldFunctor.MyField << theContext >> FieldSelection; 
00132                                         puts("FieldFunctor: OUCCCH - Some data here, but no fitting data!"); fflush(stdout); 
00133                                         VActionNotifier::Warning("FieldFunctor \"" + theFieldFunctor.Name() + "\" :\n\n"
00134                                                                  "Need data of type '" + Typename(typeid(input_type)) +
00135                                                                  "', but input data are of type '" +
00136                                                                  Typename(Data->getType() ) +
00137                                                                  //"' (elements of type '" + Typename(Data->getFiberType().getType() ) + "'"
00138                                                                  ").\n\n"
00139                                                                  "Maybe a wrong input field was connected here. "
00140                                                                  "The currently connected input field is \""
00141                                                                  + FieldSelection() + "\" - check whether this is correct."
00142                                                                 );
00143                                         return false;
00144                                 }
00145                         } 
00146 
00147                 const Iterator<input_type>&Src = *T; 
00148 
00149                 RefPtr<TypedArray<output_type> >
00150                         Result = TypedArray<output_type>::create( T() ); 
00151 
00152                 const Iterator<output_type>&Dst = *Result ->creativeIterator() ; 
00153 
00154                 index_t end = Src.count(); 
00155                         for(index_t i = 0; i<end; i++)
00156                         {
00157                                 Dst[i] = compute( Src[i] );
00158                         } 
00159 
00160                         Result ->CacheInfoString = "Computed field."; 
00161                         if (!ResultField)
00162                                 ResultField = new Field();
00163                         ResultField->setDiscardableData( Result , Cache::MemCache(), frag); 
00164                         ResultField->touch();
00165                         Modified = true;
00166                         return true;
00167                 }
00168         };
00169 
00170 
00171 static string createChildname(const string&parent_name)
00172         {
00173                 return Operation::createChildname( parent_name );
00174         }
00175 
00182         virtual bool modifyOperator(VRequest&Context, Operation&Op) const
00183         {
00184                 return true;
00185         }
00186 
00199         virtual bool postOperation(VRequest&Context, Op&Result) const
00200         {
00201                 return true;
00202         }
00203 
00204         override bool FieldOperation(VRequest&Context, Fiber::Field&Source,
00205                                      Fiber::Representation&Target, Fiber::Representation&FieldIDSource)
00206         {
00207 //      puts("FieldFunctor::FieldOperation(VRequest&Context, Fiber::Field&Source)");
00208 
00209         Op      MyOp(*this, Context);
00210                 MyOp.doCreateArrayIfRequired = doCreateArrayIfRequired;
00211                 if (!modifyOperator(Context, MyOp) )
00212                 {
00213                         return false;
00214                 }
00215 
00216                 Source.iterate( MyOp ); 
00217 
00218                 if (!postOperation(Context, MyOp) )
00219                 {
00220                         return false;
00221                 }
00222 
00223                 if (MyOp.ResultField)
00224                 {
00225                 string  ResultFieldname = createChildname( Fieldname(Context) ); 
00226 
00227                 RefPtr<FieldID> ResultID = Target.createSharedFieldID( FieldIDSource, ResultFieldname );
00228                         assert( ResultID );
00229 
00230                         Target[ ResultID ] = MyOp.ResultField; 
00231                         assert( Target.getField( ResultID ) );
00232 
00233                 FieldSelector InputField;
00234                         MyField << Context >> InputField; 
00235 //                      printf("FIELDFUNCTOR got data at T=%lg\n", F.getTime() );
00236 
00237 //                      if (MyOp.Modified) puts("ResultField.modified"); else  puts("NOT ResultField.modified"); 
00238 
00239                 FieldSelector OutField( InputField );
00240                         OutField.selectField( ResultFieldname );
00241                         OutField.accept<output_type>();
00242 
00243                 FieldSelector PreviousOutField;
00244                         Result << Context >> PreviousOutField;
00245 
00246                         if (MyOp.Modified || OutField != PreviousOutField)
00247                         {
00248 //                              puts("SET NEW Field");
00249                                 Result << Context << OutField;
00250                                 setStatusInfo(Context, "Created field ["+ResultFieldname+"]");
00251                         }
00252                         else
00253                                 setStatusInfo(Context, "Used old field ["+ResultFieldname+"]"); 
00254 //                              puts("OLD Field is fine");
00255                 } 
00256                 else
00257                         setStatusError(Context, "Invalid input type of input field");
00258 
00259 //              return setStatusInfo(Context, "Created field ["+ResultFieldname+"]");
00260                 return true;
00261         }
00262 };
00263 
00264 
00265 } // namespace
00266 
00267 #endif
00268