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
00103 }
00104 else
00105 {
00106
00107 return true;
00108 }
00109 }
00110 }
00111
00112
00113
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
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
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
00236
00237
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
00249 Result << Context << OutField;
00250 setStatusInfo(Context, "Created field ["+ResultFieldname+"]");
00251 }
00252 else
00253 setStatusInfo(Context, "Used old field ["+ResultFieldname+"]");
00254
00255 }
00256 else
00257 setStatusError(Context, "Invalid input type of input field");
00258
00259
00260 return true;
00261 }
00262 };
00263
00264
00265 }
00266
00267 #endif
00268