1 /*
2  *  simple_actions.h
3  *
4  *
5  *  Created by Andreas Vox on 02.06.06.
6  *  Copyright 2006 under GPL2. All rights reserved.
7  *
8  */
9 
10 
11 
12 #ifndef SIMPLE_ACTIONS_H
13 #define SIMPLE_ACTIONS_H
14 
15 #include "actions.h"
16 /*****
17 
18     Defines the following actions:
19 
20     Factory<D>( fun )                               - -> D
21     Factory<D>()                                    - -> D
22     Prototype<D>( data )                            - -> D
23     Top<O>( 3 )                                     O x x x -> O x x x O
24     Getter<O,D>( fun )                              O -> O D
25     Setter<O,D>( fun )                              O D -> O D
26     SetterWithConversion<O,D,S>( fun )              O S -> O S
27     SetAttribute<O,D>( fun, name, default)          O -> O
28     SetAttribute<O,D>( fun, name)                   O -> O
29     SetAttributeWithConversion<O,D>( f, n, c, def)  O -> O
30     SetAttributeWithConversion<O,D>( f, n, convert) O -> O
31     SetAttributes<O>( fun )                         O -> O
32     SetText<O,D>( fun )                             O -> O
33     AddText<O,D>( fun )                             O -> O
34     Transform<D,E> ( fun )                          D -> E
35     *TransformLater<D,E> ( fun )                     D -> E
36     IdRef<O>()                                      O -> O
37     Lookup<D>( name )                               - -> D
38     PatchIdRefAttribute<O,D>( fun, name)            O -> O
39     Result<O>()                                     O -> O
40 
41 *****/
42 
43 
44 namespace desaxe {
45 
46 	using namespace desaxe;
47 
48 /**
49  *   Pushes a new object of type Obj_Type onto the stack.
50  *   Obj_Type needs a default constructor
51  */
52 template<class Obj_Type>
53 class Factory_body : public Generator_body<Obj_Type>
54 {
55 public:
56 	typedef Obj_Type* (*FunType)();
57 
Factory_body()58 	Factory_body()
59 	: create_(nullptr)
60 	{}
61 
Factory_body(FunType create)62 	Factory_body(FunType create)
63 	: create_(create)
64 	{}
65 
begin(const Xml_string &,Xml_attr)66 	void begin(const Xml_string&, Xml_attr)
67 	{
68 		this->dig->push(create_? create_() : new Obj_Type());
69 	}
70 private:
71     Obj_Type* (*create_)();
72 };
73 
74 template <class Type>
75 struct  Factory : public MakeGenerator<Factory_body<Type>, Type, typename Factory_body<Type>::FunType>
76 {
FactoryFactory77 	Factory(typename Factory_body<Type>::FunType create)
78 	: MakeGenerator<Factory_body<Type>, Type, typename Factory_body<Type>::FunType>(create) {}
79 
FactoryFactory80 	Factory()
81 	: MakeGenerator<Factory_body<Type>, Type, typename Factory_body<Type>::FunType>() {}
82 };
83 
84 
85 /**
86  *   Pushes a new object of type Obj_Type onto the stack.
87  */
88 template<class Obj_Type>
89 class FactoryWithArgs_body : public Generator_body<Obj_Type>
90 {
91 public:
92 	typedef Obj_Type* (*FunType)(const Xml_string&, Xml_attr);
93 
FactoryWithArgs_body(FunType create)94 	FactoryWithArgs_body(FunType create)
95 		: create_(create)
96 	{}
97 
begin(const Xml_string & name,Xml_attr attr)98 	void begin(const Xml_string& name, Xml_attr attr)
99 	{
100 		this->dig->push(create_(name, attr));
101 	}
102 private:
103 		Obj_Type* (*create_)(const Xml_string&, Xml_attr);
104 };
105 
106 template <class Type>
107 struct  FactoryWithArgs : public MakeGenerator<FactoryWithArgs_body<Type>, Type, typename FactoryWithArgs_body<Type>::FunType>
108 {
FactoryWithArgsFactoryWithArgs109 	FactoryWithArgs(typename FactoryWithArgs_body<Type>::FunType create)
110 	: MakeGenerator<FactoryWithArgs_body<Type>, Type, typename FactoryWithArgs_body<Type>::FunType>::MakeGenerator(create) {}
111 };
112 
113 
114 /**
115  *   Pushes a new object of type Obj_Type onto the stack which is initialized with the tag name.
116  *   If no create method is given, Obj_Type needs a constructor which taks a Xml_string argument
117  */
118 template<class Obj_Type>
119 class FactoryWithName_body : public Generator_body<Obj_Type>
120 {
121 public:
122 	typedef Obj_Type* (*FunType)(const Xml_string&);
123 
FactoryWithName_body()124 	FactoryWithName_body()
125 	: create_(NULL)
126 	{}
127 
FactoryWithName_body(FunType create)128 	FactoryWithName_body(FunType create)
129 	: create_(create)
130 	{}
131 
begin(const Xml_string & tag,Xml_attr)132 	void begin(const Xml_string& tag, Xml_attr)
133 	{
134 		this->dig->push(create_? create_(tag) : new Obj_Type(tag));
135 	}
136 private:
137 	FunType create_;
138 };
139 
140 template <class Type>
141 struct  FactoryWithName : public MakeGenerator<FactoryWithName_body<Type>, Type, typename FactoryWithName_body<Type>::FunType>
142 {
FactoryWithNameFactoryWithName143 	FactoryWithName()
144 	: MakeGenerator<FactoryWithName_body<Type>, Type, typename FactoryWithName_body<Type>::FunType>::MakeGenerator() {}
145 
FactoryWithNameFactoryWithName146 	FactoryWithName(typename FactoryWithName_body<Type>::FunType create)
147 	: MakeGenerator<FactoryWithName_body<Type>, Type, typename FactoryWithName_body<Type>::FunType>::MakeGenerator(create) {}
148 };
149 
150 
151 /**
152  *   Pushes a clone of proto onto the stack. Obj_Type needs a copy constructor
153  */
154 template<class Obj_Type>
155 class Prototype_body : public Generator_body<Obj_Type>
156 {
157 public:
Prototype_body(const Obj_Type & proto)158 	Prototype_body(const Obj_Type& proto)
159 	: proto_(new Obj_Type(proto))
160 	{}
161 
~Prototype_body()162 	~Prototype_body()
163 	{
164 		delete proto_;
165 	}
166 
begin(const Xml_string &,Xml_attr)167 	void begin(const Xml_string&, Xml_attr)
168 	{
169 		this->dig->push(new Obj_Type(proto_));
170 	}
171 private:
172 	const Obj_Type* proto_;
173 };
174 
175 
176 template <class Type>
177 struct  Prototype : public MakeGenerator<Prototype_body<Type>, Type, const Type&>
178 {
PrototypePrototype179 	Prototype(const Type& def)
180 	: MakeGenerator<Prototype_body<Type>, Type, const Type&>::MakeGenerator(def) {}
181 };
182 
183 
184 
185 /**
186  *   Pushes a new pointer to the n-th object on the stack.
187  */
188 template<class Obj_Type>
189 class Top_body : public Generator_body<Obj_Type>
190 {
191 public:
Top_body(unsigned int n)192 	Top_body(unsigned int n)
193 	: distance(n)
194 	{}
195 
begin(const Xml_string &,Xml_attr)196 	void begin(const Xml_string&, Xml_attr)
197 	{
198 		this->dig->push(this->dig->template top<Obj_Type>(distance));
199 	}
200 private:
201 	unsigned int distance;
202 };
203 
204 
205 template <class Type>
206 struct  Top : public MakeGenerator<Top_body<Type>, Type, unsigned int>
207 {
TopTop208 	Top(unsigned int distance)
209 	: MakeGenerator<Top_body<Type>, Type, unsigned int>::MakeGenerator(distance) {}
TopTop210 	Top()
211 	: MakeGenerator<Top_body<Type>, Type, unsigned int>::MakeGenerator(0) {}
212 };
213 
214 
215 
216 /**
217  *  Reads an object of type Data_Type from the object on top of the stack,
218  *  then pushes this Data_Type object onto the stack.
219  */
220 template<class Obj_Type, class Data_Type>
221 class Getter_body : public Generator_body<Data_Type>
222 {
223 public:
224 	typedef const Data_Type& (Obj_Type::*FunType)();
225 
Getter_body(FunType get)226 	Getter_body(FunType get)
227 	: get_(get)
228 	{}
229 
begin(const Xml_string &,Xml_attr)230 	void begin(const Xml_string&, Xml_attr)
231 	{
232 		Obj_Type* obj = this->dig->template top<Obj_Type>(1);
233 		Data_Type* data = (obj->*get_)();
234 		this->dig->push(data);
235 	}
236 private:
237 	FunType get_;
238 };
239 
240 
241 template <class Type, class Data>
242 struct  Getter : public MakeGenerator<Getter_body<Type, Data>, Data, typename Getter_body<Type, Data>::FunType>
243 {
GetterGetter244 	Getter(typename Getter_body<Type, Data>::FunType get)
245 	: MakeGenerator<Getter_body<Type, Data>, Data, typename Getter_body<Type, Data>::FunType>::MakeGenerator(get) {}
246 };
247 
248 
249 /**
250  *    Writes the topmost object to the topmost object but one on the stack, where the set method takes a pointer
251  */
252 template<class Obj_Type, class Data_Type, class Store_Type>
253 class SetterP_body : public Action_body
254 {
255 public:
256 	typedef void (Obj_Type::*FunType)(Data_Type*);
257 
SetterP_body(FunType set)258 	SetterP_body(FunType set)
259 	: set_(set)
260 	{}
261 
end(const Xml_string &)262 	void end(const Xml_string&)
263 	{
264 		Store_Type* data = this->dig->template top<Store_Type>();
265 		Obj_Type* obj = this->dig->template top<Obj_Type>(1);
266 #ifdef DESAXE_DEBUG
267 		std::cerr << "setter(ptr): " << obj << " .= " << data << "\n";
268 #endif
269 		(obj->*set_)( data );
270 	}
271 private:
272 	FunType set_;
273 };
274 
275 
276 template <class Type, class Data, class Store = Data>
277 struct  SetterP : public MakeAction<SetterP_body<Type, Data, Store>, typename SetterP_body<Type, Data, Store>::FunType>
278 {
SetterPSetterP279 	SetterP(typename SetterP_body<Type, Data, Store>::FunType set)
280 	: MakeAction<SetterP_body<Type, Data, Store>, typename SetterP_body<Type, Data, Store>::FunType>(set) {}
281 };
282 
283 
284 /**
285  *  Writes the topmost object to the topmost object but one on the stack.
286  */
287 template<class Obj_Type, class Data_Type>
288 class Setter_body : public Action_body
289 {
290 public:
291 	typedef void (Obj_Type::*FunType)(Data_Type);
292 
Setter_body(FunType set)293 	Setter_body(FunType set)
294 	: set_(set)
295 	{}
296 
end(const Xml_string &)297 	void end(const Xml_string&)
298 	{
299 		Data_Type* data = this->dig->template top<Data_Type>();
300 		Obj_Type* obj = this->dig->template top<Obj_Type>(1);
301 #ifdef DESAXE_DEBUG
302 		std::cerr << "setter: " << obj << " .= *(" << data << ")\n";
303 #endif
304 		(obj->*set_)( *data );
305 	}
306 private:
307 	FunType set_;
308 };
309 
310 
311 template <class Type, class Data>
312 struct  Setter : public MakeAction<Setter_body<Type, Data>, typename Setter_body<Type, Data>::FunType>
313 {
SetterSetter314 	Setter(typename Setter_body<Type, Data>::FunType set)
315 	: MakeAction<Setter_body<Type, Data>, typename Setter_body<Type, Data>::FunType>(set) {}
316 };
317 
318 
319 /**
320  *  Writes the topmost object to the topmost object but one on the stack.
321  */
322 template<class Obj_Type, class Data_Type, class Store_Type>
323 class SetterWithConversion_body : public Action_body
324 {
325 public:
326 	typedef void (Obj_Type::*FunType)(Data_Type);
327 	typedef Data_Type (*ConvType)(Store_Type);
328 
SetterWithConversion_body(FunType set,ConvType conv)329 	SetterWithConversion_body(FunType set, ConvType conv)
330 		: set_(set), conv_(conv)
331 	{}
332 
end(const Xml_string &)333 	void end(const Xml_string&)
334 	{
335 		Store_Type* data = this->dig->template top<Store_Type>();
336 		Obj_Type* obj = this->dig->template top<Obj_Type>(1);
337 #ifdef DESAXE_DEBUG
338 		std::cerr << "setter: " << obj << " .= " << conv_ << "(*" << data << ")\n";
339 #endif
340 		if (conv_)
341 			(obj->*set_)( conv_(*data) );
342 		else
343 			(obj->*set_)( static_cast<Data_Type>(*data) );
344 	}
345 private:
346 		FunType set_;
347 	ConvType conv_;
348 };
349 
350 
351 template <class Type, class Data, class Store>
352 struct  SetterWithConversion : public MakeAction<SetterWithConversion_body<Type, Data, Store>, typename SetterWithConversion_body<Type, Data, Store>::FunType, typename SetterWithConversion_body<Type, Data, Store>::ConvType>
353 {
354 	typedef SetterWithConversion_body<Type, Data, Store> BodyType;
SetterWithConversionSetterWithConversion355 	SetterWithConversion(typename SetterWithConversion_body<Type, Data, Store>::FunType set)
356 	: MakeAction<SetterWithConversion_body<Type, Data, Store>, typename SetterWithConversion_body<Type, Data, Store>::FunType, typename SetterWithConversion_body<Type, Data, Store>::ConvType>(set, NULL) {}
SetterWithConversionSetterWithConversion357 	SetterWithConversion(typename BodyType::FunType set, typename SetterWithConversion_body<Type, Data, Store>::ConvType conv)
358 	: MakeAction<SetterWithConversion_body<Type, Data, Store>, typename SetterWithConversion_body<Type, Data, Store>::FunType, typename SetterWithConversion_body<Type, Data, Store>::ConvType>(set, conv) {}
359 };
360 
361 
362 /**
363  *   Stores all attributes to the topmost object on the stack.
364  */
365 template<class Obj_Type>
366 class SetAttributes_body : public Action_body
367 {
368 public:
369 	typedef void (Obj_Type::*FunType)(const Xml_string&, const Xml_string&) ;
370 
SetAttributes_body(FunType set)371 	SetAttributes_body(FunType set) : set_(set)
372 	{}
373 
begin(const Xml_string &,Xml_attr attr)374 	void begin(const Xml_string&, Xml_attr attr)
375 	{
376 		Obj_Type* obj = this->dig->template top<Obj_Type>();
377 		Xml_attr::iterator it;
378 		for(it=attr.begin(); it != attr.end(); ++it)
379 			(obj->*set_)( Xml_key(it), Xml_data(it) );
380 	}
381 private:
382 	FunType set_;
383 };
384 
385 
386 template <class Type>
387 struct  SetAttributes : public MakeAction<SetAttributes_body<Type>, typename SetAttributes_body<Type>::FunType>
388 {
SetAttributesSetAttributes389 	SetAttributes(typename SetAttributes_body<Type>::FunType set)
390 	: MakeAction<SetAttributes_body<Type>, typename SetAttributes_body<Type>::FunType>(set) {}
391 };
392 
393 
394 
395 /**
396  *   Stores named attribute to the topmost object on the stack if attribute present,
397  *   or stores defauot if present.
398  */
399 template<class Obj_Type, class Data_Type>
400 class SetAttribute_body : public Action_body
401 {
402 public:
403 	typedef void (Obj_Type::*FunType)(Data_Type) ;
404 
SetAttribute_body(FunType set,const Xml_string & name)405 	SetAttribute_body(FunType set, const Xml_string& name)
406 		: set_(set), name_(name), default_(), hasDefault_(false)
407 	{}
408 
SetAttribute_body(FunType set,const Xml_string & name,Data_Type deflt)409 	SetAttribute_body(FunType set, const Xml_string& name, Data_Type deflt)
410 		: set_(set), name_(name), default_(deflt), hasDefault_(true)
411 	{}
412 
begin(const Xml_string &,Xml_attr attr)413 	void begin(const Xml_string&, Xml_attr attr)
414 	{
415 		Obj_Type* obj = this->dig->template top<Obj_Type>();
416 		Xml_attr::iterator it = attr.find(name_);
417 		if (it != attr.end() )
418 			(obj->*set_)( Data_Type(Xml_data(it)) );
419 		else if (hasDefault_)
420 			(obj->*set_)( default_ );
421 	}
422 private:
423 	FunType set_;
424 	Xml_string name_;
425 	Data_Type default_;
426 	bool hasDefault_;
427 };
428 
429 
430 template <class Type, class Data>
431 struct  SetAttribute : public MakeAction<SetAttribute_body<Type,Data>, typename SetAttribute_body<Type,Data>::FunType, const Xml_string&, Data>
432 {
SetAttributeSetAttribute433 	SetAttribute(typename SetAttribute_body<Type,Data>::FunType set, const Xml_string& name)
434 	: MakeAction<SetAttribute_body<Type,Data>, typename SetAttribute_body<Type,Data>::FunType, const Xml_string&, Data>(set,name) {}
435 
SetAttributeSetAttribute436 	SetAttribute(typename SetAttribute_body<Type,Data>::FunType set, const Xml_string& name, Data deflt)
437 	: MakeAction<SetAttribute_body<Type,Data>, typename SetAttribute_body<Type,Data>::FunType, const Xml_string&, Data>(set,name,deflt) {}
438 };
439 
440 
441 
442 /**
443  *   Stores named attribute to the topmost object on the stack if attribute present,
444  *   or stores default if present.
445  */
446 template<class Obj_Type, class Data_Type>
447 class SetAttributeWithConversion_body : public Action_body
448 {
449 public:
450 	typedef void (Obj_Type::*FunType)(Data_Type) ;
451 	typedef Data_Type (*ConvType)(const Xml_string&);
452 
SetAttributeWithConversion_body(FunType set,const Xml_string & name,ConvType conv)453 	SetAttributeWithConversion_body(FunType set, const Xml_string& name, ConvType conv)
454 		: set_(set), name_(name), conv_(conv), default_(), hasDefault_(false)
455 	{}
456 
SetAttributeWithConversion_body(FunType set,const Xml_string & name,ConvType conv,Data_Type deflt)457 	SetAttributeWithConversion_body(FunType set, const Xml_string& name, ConvType conv, Data_Type deflt)
458 		: set_(set), name_(name), conv_(conv), default_(deflt), hasDefault_(true)
459 	{}
460 
begin(const Xml_string &,Xml_attr attr)461 	void begin(const Xml_string&, Xml_attr attr)
462 	{
463 		Obj_Type* obj = this->dig->template top<Obj_Type>();
464 		Xml_attr::iterator it = attr.find(name_);
465 		if (it != attr.end() && conv_)
466 			(obj->*set_)( conv_(Xml_data(it)) );
467 		else if (hasDefault_)
468 			(obj->*set_)( default_ );
469 	}
470 private:
471 	FunType set_;
472 	Xml_string name_;
473 	ConvType conv_;
474 	Data_Type default_;
475 	bool hasDefault_;
476 };
477 
478 
479 template <class Type, class Data>
480 struct  SetAttributeWithConversion : public MakeAction<SetAttributeWithConversion_body<Type,Data>, typename SetAttributeWithConversion_body<Type,Data>::FunType, const Xml_string&, typename SetAttributeWithConversion_body<Type,Data>::ConvType, Data>
481 {
482 	typedef SetAttributeWithConversion_body<Type,Data> BodyType;
483 
SetAttributeWithConversionSetAttributeWithConversion484 	SetAttributeWithConversion(typename BodyType::FunType set, const Xml_string& name, typename BodyType::ConvType conv)
485 	: MakeAction<BodyType, typename BodyType::FunType, const Xml_string&, typename BodyType::ConvType, Data>(set,name,conv) {}
486 
SetAttributeWithConversionSetAttributeWithConversion487 	SetAttributeWithConversion(typename BodyType::FunType set, const Xml_string& name, typename BodyType::ConvType conv, Data deflt)
488 	: MakeAction<BodyType, typename BodyType::FunType, const Xml_string&, typename BodyType::ConvType, Data>(set,name,conv,deflt) {}
489 };
490 
491 
492 
493 /**
494  *   Stores text (PCDATA) in the topmost object on the stack.
495  *   This might be called more than once.
496  */
497 template<class Obj_Type>
498 class AddText_body : public Action_body
499 {
500 public:
501 	typedef void (Obj_Type::*FunType)(const Xml_string&);
502 
AddText_body(FunType add)503 	AddText_body(FunType add) : addT(add)
504 	{}
505 
chars(const Xml_string & txt)506 	void chars(const Xml_string& txt)
507 	{
508 		Obj_Type* obj = this->dig->template top<Obj_Type>();
509 		(obj->*addT)( txt );
510 	}
511 private:
512 	FunType addT;
513 };
514 
515 
516 
517 template <class Type>
518 struct  AddText : public MakeAction<AddText_body<Type>, typename AddText_body<Type>::FunType>
519 {
AddTextAddText520 	AddText(typename AddText_body<Type>::FunType set)
521 	: MakeAction<AddText_body<Type>, typename AddText_body<Type>::FunType>(set) {}
522 };
523 
524 
525 
526 
527 /**
528  *   Collects text (PCDATA) chunks and later stores it in the topmost object
529  *   on the stack.
530  *   This is only called once at the close tag of the current pattern.
531  *   WARNING: not safe for nesting
532  */
533 template<class Obj_Type>
534 class SetText_body : public Action_body
535 {
536 public:
537 	typedef void (Obj_Type::*FunType)(const Xml_string&);
538 
SetText_body(FunType set)539 	SetText_body(FunType set) : setT(set)
540 	{}
541 
begin(const Xml_string &,Xml_attr)542 	void begin(const Xml_string&, Xml_attr)
543 	{
544 		txt.clear();
545 	}
546 
chars(const Xml_string & chunk)547 	void chars(const Xml_string& chunk)
548 	{
549 		txt += chunk;
550 	}
551 
end(const Xml_string & tag)552 	void end(const Xml_string& tag)
553 	{
554 		Obj_Type* obj = this->dig->template top<Obj_Type>();
555 		(obj->*setT)( txt );
556 	}
557 
558 private:
559 	FunType setT;
560 	Xml_string txt;
561 };
562 
563 
564 
565 template <class Type>
566 struct  SetText : public MakeAction<SetText_body<Type>, typename SetText_body<Type>::FunType>
567 {
568 	typedef SetText_body<Type> BodyType;
SetTextSetText569 	SetText(typename BodyType::FunType set)
570 	: MakeAction<BodyType, typename BodyType::FunType>(set) {}
571 };
572 
573 
574 
575 
576 template<class Obj_Type>
577 class Store_body : public Action_body
578 {
579 public:
Store_body(const Xml_string & name)580 	Store_body(const Xml_string& name) : m_name(name) {}
581 
begin(const Xml_string & tag,Xml_attr attr)582 	void begin(const Xml_string& tag, Xml_attr attr)
583 	{
584 		Obj_Type* obj = this->dig->template top<Obj_Type>();
585 //		qDebug() << QString("Store: %1 <- %2").arg(tag).arg(typeid(obj).name());
586 		this->dig->template store<Obj_Type>(m_name, obj);
587 	}
588 
589 private:
590 	Xml_string m_name;
591 };
592 
593 
594 template <class Type>
595 struct  Store : public MakeAction<Store_body<Type>, const Xml_string& >
596 {
StoreStore597 	Store(const Xml_string& name) : MakeAction<Store_body<Type>, const Xml_string& >(name) {}
598 };
599 
600 
601 
602 /**
603  *  This applies "id" and "idref" attributes to the object on top of the stack.
604  *  In case of an "id" attribute, if there is no entry with this ID in
605  *  the digester's storage, the topmost object is stored there. Otherwise the
606  *  topmost object is replaced with the stored object.
607  *  In case of an "idref" attribute, if there is no entry with this ID in
608  *  the digester's storage, the topmost object is also stored there. Then the
609  *  trigger "WithinIdRef" is set during begin() and the processing continues
610  *  normally. When end() is called, the topmost object is replaced by the
611  *  stored one (this will be a no-op if there wasnt an entry in storage before)
612  */
613 template<class Obj_Type>
614 class IdRef_body : public Action_body
615 {
616 public:
IdRef_body()617 	IdRef_body() : stack() {}
618 
begin(const Xml_string &,Xml_attr attr)619 	void begin(const Xml_string&, Xml_attr attr)
620 	{
621 		Obj_Type* obj = this->dig->template top<Obj_Type>();
622 		Mode mode;
623 		Xml_attr::iterator it = attr.find("id");
624 		if (it != attr.end())
625 		{
626 			mode.ID = attr["id"];
627 			mode.isIdRef = false;
628 		}
629 		else {
630 			Xml_attr::iterator it = attr.find("idref");
631 			if (it != attr.end())
632 			{
633 				mode.ID = attr["idref"];
634 				mode.isIdRef = true;
635 			}
636 			else {
637 				mode.ID.clear();
638 				mode.isIdRef = false;
639 			}
640 		}
641 		if (!mode.ID.isEmpty())
642 		{
643 			Obj_Type* storedObj = this->dig->template lookup<Obj_Type>(mode.ID);
644 			if ( !storedObj )
645 			{
646 				this->dig->store(mode.ID, obj);
647 			}
648 			else if ( !mode.isIdRef )
649 			{
650 				delete (this->dig->template top<Obj_Type>());
651 				this->dig->pop();
652 				this->dig->push(this->dig->template lookup<Obj_Type>(mode.ID));
653 			}
654 			else
655 			{
656 				// NYI: set trigger
657 			}
658 		}
659 		stack.push_back(mode);
660 
661 	}
end(const Xml_string &)662 	void end(const Xml_string&)
663 	{
664 		Mode mode = stack.back();
665 		stack.pop_back();
666 		if (mode.isIdRef)
667 		{
668 			delete (this->dig->template top<Obj_Type>());
669 			this->dig->pop();
670 			this->dig->push(this->dig->template lookup<Obj_Type>(mode.ID));
671 			// NYI reset trigger
672 		}
673 	}
674 private:
675 	struct Mode { Xml_string ID; bool isIdRef; };
676 	std::vector<Mode> stack;
677 };
678 
679 
680 template <class Type>
681 struct  IdRef : public MakeAction<IdRef_body<Type> >
682 {};
683 
684 
685 /**
686  *  Reads an object of type Data_Type from the digesters
687  *  storage and pushes it onto the stack.
688  *  WARNING: this might be a NULL pointer
689  */
690 template<class Data_Type>
691 class Lookup_body : public Generator_body<Data_Type>
692 {
693 public:
Lookup_body(const Xml_string & ID)694 	Lookup_body(const Xml_string& ID)
695 		: ID_(ID)
696 	{}
697 
begin(const Xml_string &,Xml_attr)698 	void begin(const Xml_string&, Xml_attr)
699 	{
700 		Data_Type* data = this->dig->template lookup<Data_Type>(ID_);
701 		this->dig->push(data);
702 	}
703 private:
704 	Xml_string ID_;
705 };
706 
707 
708 template <class Data>
709 struct  Lookup : public MakeGenerator<Lookup_body<Data>, const Xml_string&>
710 {
LookupLookup711 	Lookup(Xml_string ID)
712 	: MakeGenerator<Lookup_body<Data>, const Xml_string&>::MakeGenerator(ID) {}
713 };
714 
715 
716 
717 /**
718  *  Transforms the topmost object to the topmost object but one on the stack. // FIXME: this should just be a getter...
719  */
720 template<class Obj_Type, class Arg_Type>
721 class Transform_body : public Action_body
722 {
723 public:
724 	typedef Obj_Type (*FunType)(const Arg_Type&);
725 
Transform_body(FunType fun)726 	Transform_body(FunType fun)
727 		: fun_(fun), stack()
728 	{}
729 
begin(const Xml_string &,Xml_attr)730 	void begin(const Xml_string&, Xml_attr)
731 	{
732 		Cell cell;
733 		cell.arg = this->dig->template top<Arg_Type>();
734 		cell.obj = fun_(*cell.arg);
735 #ifdef DESAXE_DEBUG
736 		std::cerr << "transform: " << cell.arg << " -> " << cell.obj << ")\n";
737 #endif
738 		stack.push_back(cell);
739 		this->dig->pop();
740 		this->dig->push(&cell.obj);
741 	}
742 
end(const Xml_string &)743 	void end(const Xml_string&)
744 	{
745 		Cell cell = stack.back();
746 		stack.pop_back();
747 		this->dig->pop();
748 		this->dig->push(cell.arg);
749 	}
750 private:
751 		FunType fun_;
752 	struct Cell { Arg_Type* arg; Obj_Type obj; };
753 	std::vector<Cell> stack;
754 };
755 
756 
757 template <class Type, class Arg>
758 struct  Transform : public MakeAction<Transform_body<Type, Arg>, typename Transform_body<Type, Arg>::FunType>
759 {
760 	typedef Transform_body<Type, Arg> BodyType;
TransformTransform761 	Transform(typename BodyType::FunType f) : MakeAction<BodyType, typename BodyType::FunType>(f) {}
762 };
763 
764 
765 
766 
767 template<class Obj_Type, class Data_Type>
768 class PatchIdRefAttribute_body : public Action_body
769 {
770 public:
771 	typedef void (Obj_Type::*FunType)(Data_Type*) ;
772 
PatchIdRefAttribute_body(FunType set,const Xml_string & name)773 	PatchIdRefAttribute_body(FunType set, const Xml_string& name)
774 		: set_(set), name_(name)
775 	{}
776 
begin(const Xml_string &,Xml_attr attr)777 	void begin(const Xml_string&, Xml_attr attr)
778 	{
779 		Xml_attr::iterator it = attr.find(name_);
780 		if (it != attr.end())
781 		{
782 			Obj_Type* obj = this->dig->template top<Obj_Type>();
783 			this->dig->template patchInvoke<Obj_Type,Data_Type>(Xml_data(it), obj, set_);
784 		}
785 	}
786 private:
787 	FunType set_;
788 	Xml_string name_;
789 };
790 
791 
792 template <class Type, class Data>
793 struct  PatchIdRefAttribute : public MakeAction<PatchIdRefAttribute_body<Type,Data>, typename PatchIdRefAttribute_body<Type,Data>::FunType, const Xml_string&>
794 {
795 	typedef PatchIdRefAttribute_body<Type,Data> BodyType;
PatchIdRefAttributePatchIdRefAttribute796 	PatchIdRefAttribute(typename BodyType::FunType set, const Xml_string& name)
797 	: MakeAction<BodyType, typename BodyType::FunType, const Xml_string&>(set,name) {}
798 };
799 
800 
801 
802 
803 /**
804  *   defines the topmost object as the result
805  */
806 template<class Data_Type>
807 class Result_body : public Action_body
808 {
809 public:
Result_body()810 	Result_body()
811 	{}
812 
end(const Xml_string &)813 	void end(const Xml_string&)
814 	{
815 		this->dig->setResult(dig->template top<Data_Type>());
816 	}
817 };
818 
819 
820 
821 template <class Data>
822 struct  Result : public MakeAction<Result_body<Data> > {};
823 
824 
825 } // namespace
826 
827 #endif
828