Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/objecthierarchy/src/core/XMLPort.h @ 2079

Last change on this file since 2079 was 2065, checked in by landauf, 16 years ago

added two more graphical classes, ParticleEmitter and ParticleSpawner

  • Property svn:eol-style set to native
File size: 30.7 KB
Line 
1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *                    > www.orxonox.net <
4 *
5 *
6 *   License notice:
7 *
8 *   This program is free software; you can redistribute it and/or
9 *   modify it under the terms of the GNU General Public License
10 *   as published by the Free Software Foundation; either version 2
11 *   of the License, or (at your option) any later version.
12 *
13 *   This program is distributed in the hope that it will be useful,
14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *   GNU General Public License for more details.
17 *
18 *   You should have received a copy of the GNU General Public License
19 *   along with this program; if not, write to the Free Software
20 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 *
22 *   Author:
23 *      Fabian 'x3n' Landau
24 *   Co-authors:
25 *      ...
26 *
27 */
28
29/**
30    @file XMLPort.h
31    @brief Declaration of the XMLPort helper classes and macros.
32
33    XMLPort is a virtual function of every BaseObject. Every object can change this function.
34    The XMLPort function gets called with an XMLElement, containing all attributes and
35    subclasses the object gets from the levelfile.
36
37    This file declares classes and macros to simplify XML-parsing.
38*/
39
40#ifndef _XMLPort_H__
41#define _XMLPort_H__
42
43#include "CorePrereqs.h"
44
45#include "util/Debug.h"
46#include "util/MultiType.h"
47#include "tinyxml/ticpp.h"
48#include "XMLIncludes.h"
49#include "Executor.h"
50#include "CoreIncludes.h"
51#include "BaseObject.h"
52
53// ------------
54// XMLPortParam
55
56/**
57    @brief Declares an XML attribute with a name, which will be set through load- and savefunctions.
58    @param classname The name of the class owning this param
59    @param paramname The name of the attribute
60    @param loadfunction A function to set the param in the object with a given value (~a set-function)
61    @param savefunction A function to get the value of the param from the object (~a get-function)
62    @param xmlelement The XMLElement, you get this from the XMLPort function
63    @param mode The mode (load or save), you get this from the XMLPort function
64
65    In the XML file, a param or attribute will be set like this:
66    <classname paramname="value" />
67
68    The macro will then call loadfunction(value) to set the given value (or call savefunction() to
69    write an existing value to an XML file).
70*/
71#define XMLPortParam(classname, paramname, loadfunction, savefunction, xmlelement, mode) \
72    XMLPortParamGeneric(xmlcontainer##loadfunction##savefunction, classname, classname, this, paramname, orxonox::createExecutor(orxonox::createFunctor(&classname::loadfunction), std::string( #classname ) + "::" + #loadfunction), orxonox::createExecutor(orxonox::createFunctor(&classname::savefunction), std::string( #classname ) + "::" + #savefunction), xmlelement, mode)
73/**
74    @brief This is the same as XMLPortParam, but you can set the template arguments needed to store the loadfunction.
75
76    Sometimes the name of the loadfunction is ambiguous (example: setPosition(Vector3) or
77    setPosition(float, float, float)). In this case, you can choose the right function by
78    telling the types of the functionparams. In our example, this would be either
79    > XMLPortParamTemplate(classname, paramname, loadfunction, savefunction, xmlelement, mode, Vector3);
80    or
81    > XMLPortParamTemplate(classname, paramname, loadfunction, savefunction, xmlelement, mode, float, float, float);
82    You don't have to use this, if there exist only one function with the given name.
83*/
84#define XMLPortParamTemplate(classname, paramname, loadfunction, savefunction, xmlelement, mode, ...) \
85    XMLPortParamGeneric(xmlcontainer##loadfunction##savefunction, classname, classname, this, paramname, orxonox::createExecutor(orxonox::createFunctor<classname, __VA_ARGS__ >(&classname::loadfunction), std::string( #classname ) + "::" + #loadfunction), orxonox::createExecutor(orxonox::createFunctor(&classname::savefunction), std::string( #classname ) + "::" + #savefunction), xmlelement, mode)
86
87// --------------------
88// XMLPortParamLoadOnly
89
90/**
91    @brief Declares an XML attribute with a name, which can be set through a loadfunction.
92
93    This is the same as XMLPortParam, but you don't need a savefunction (get-function). Therefore,
94    this param won't be saved in an XML file, but you can add the attribute manually an it will be
95    loaded.
96
97    This might be helpful in cases, when you have several options to set a value, for example the
98    rotation. You can set the rotation with a quaternion, but you could also use three angles.
99    When saving the object, only one of both options has to be saved; this is, where this macro helps.
100*/
101#define XMLPortParamLoadOnly(classname, paramname, loadfunction, xmlelement, mode) \
102    XMLPortParamGeneric(xmlcontainer##loadfunction##0, classname, classname, this, paramname, orxonox::createExecutor(orxonox::createFunctor(&classname::loadfunction), std::string( #classname ) + "::" + #loadfunction), 0, xmlelement, mode)
103/**
104    @brief This is the same as XMLPortParamTemplate, but for load-only attributes (see XMLPortParamLoadOnly).
105*/
106#define XMLPortParamLoadOnlyTemplate(classname, paramname, loadfunction, xmlelement, mode, ...) \
107    XMLPortParamGeneric(xmlcontainer##loadfunction##0, classname, classname, this, paramname, orxonox::createExecutor(orxonox::createFunctor<classname, __VA_ARGS__ >(&classname::loadfunction), std::string( #classname ) + "::" + #loadfunction), 0, xmlelement, mode)
108
109// ------------------
110// XMLPortParamExtern
111
112/**
113    @brief This is the same as XMLPortParam, but for attributes in an extern class.
114    @param classname The name of the class owning the object owning the attribute
115    @param externclass The name of the extern class (the objects class)
116    @param object The name of the object of the extern class (a member of the main class)
117    @param paramname The name of the attribute
118    @param loadfunction The function to set the attribute inside of the member object.
119    @param loadfunction The function to get the attribute from the member object
120
121    Sometimes you'll have a member object in your class, which has it's own load- and savefunctions.
122    With this macro, you can simply use them instead of writing your own functions.
123
124    @example
125    Your class is called SpaceShip and this class has an object (myPilot_) of class Pilot. Pilot has a name
126    and two functions, setName(name) and getName(). Now you want an attribute "pilotname" in your
127    SpaceShip class. Instead of writing wrapper functions, you can simply use the XMLPortParamExtern
128    macro:
129    > XMLPortParamExtern(SpaceShip, Pilot, myPilot_, "pilotname", setName, getName, xmlelement, mode);
130*/
131#define XMLPortParamExtern(classname, externclass, object, paramname, loadfunction, savefunction, xmlelement, mode) \
132    XMLPortParamGeneric(xmlcontainer##loadfunction##savefunction, classname, externclass, object, paramname, orxonox::createExecutor(orxonox::createFunctor(&externclass::loadfunction), std::string( #externclass ) + "::" + #loadfunction), orxonox::createExecutor(orxonox::createFunctor(&externclass::savefunction), std::string( #externclass ) + "::" + #savefunction), xmlelement, mode);
133/**
134    @brief This is the same as XMLPortParamTemplate, but for extern attributes (see XMLPortParamExtern).
135*/
136#define XMLPortParamExternTemplate(classname, externclass, object, paramname, loadfunction, savefunction, xmlelement, mode, ...) \
137    XMLPortParamGeneric(xmlcontainer##loadfunction##savefunction, classname, externclass, object, paramname, orxonox::createExecutor(orxonox::createFunctor<externclass, __VA_ARGS__ >(&externclass::loadfunction), std::string( #externclass ) + "::" + #loadfunction), orxonox::createExecutor(orxonox::createFunctor(&externclass::savefunction), std::string( #externclass ) + "::" + #savefunction), xmlelement, mode);
138
139// -------------------
140// XMLPortParamGeneric
141
142/**
143    @brief This is the generic XMLPort param macro, which is used by all six specialized macros above.
144*/
145#define XMLPortParamGeneric(containername, classname, objectclass, object, paramname, loadexecutor, saveexecutor, xmlelement, mode) \
146    orxonox::XMLPortClassParamContainer<objectclass>* containername = (orxonox::XMLPortClassParamContainer<objectclass>*)(ClassIdentifier<classname>::getIdentifier()->getXMLPortParamContainer(paramname)); \
147    if (!containername) \
148    { \
149        containername = new orxonox::XMLPortClassParamContainer<objectclass>(std::string(paramname), ClassIdentifier<classname>::getIdentifier(), loadexecutor, saveexecutor); \
150        ClassIdentifier<classname>::getIdentifier()->addXMLPortParamContainer(paramname, containername); \
151    } \
152    containername->port((BaseObject*)this, object, xmlelement, mode)
153
154// --------------------
155// XMLPortObjectExtended
156
157/**
158    @brief Declares a possible sub-object that can be added in the XML file.
159    @param classname The name of the class that uses this macro
160    @param objectclass The baseclass of objects that can be added
161    @param sectionname The name of the subsection in the XML file that encloses the sub-objects ("" means no subsection)
162    @param loadfunction The function to add a new object to the class
163    @param loadfunction The function to get all added objects from the class
164    @param xmlelement The XMLElement (recieved through the XMLPort function)
165    @param mode The mode (load/save) (received through the XMLPort function)
166    @param bApplyLoaderMask If this is true, an added sub-object only gets loaded if it's class is included in the Loaders ClassTreeMask (this is usually false)
167    @param bLoadBefore If this is true, the sub-cobject gets loaded (through XMLPort) BEFORE it gets added to the main class (this is usually true)
168
169    bApplyLoaderMask is usually false for the following reason:
170    If the loaders mask says, for example, "load only SpaceShips" and you added weapons to the
171    SpaceShips, then the Weapons will still be loaded (which is most probably what you want).
172    Of course, if there are "standalone" weapons in the level, they wont be loaded.
173
174    If bLoadBefore, an added object already has all attributes set (like it's name). This is most
175    likely the best option, so this is usually true.
176
177    @note
178    The load- and savefunctions have to follow an exactly defined protocol.
179    Loadfunction:
180      The loadfunction gets a pointer to the object.
181      > void loadfunction(objectclass* pointer);
182
183    Savefunction:
184      The savefunction gets an index, starting with 0. For every returnvalue != 0, the savefunction
185      gets called again, but with index + 1. It's the functions responsibility to do something smart
186      with the index and to return 0 if all objects were returned.
187      > objectclass* savefunction(unsigned int index) const;
188
189      Possible implementation:
190        objectclass* savefunction(unsigned int index) const
191        {
192          if (index < number_of_added_objects_)
193            return my_added_objects[index];
194          else
195            return 0;
196        }
197
198    @example
199    Possible usage of the macro:
200    > XMLPortObject(SpaceShip, Weapon, "weapons", addWeapon, getWeapon, xmlelement, mode, false, true);
201
202    Now you can add weapons through the XML file:
203    <SpaceShip someattribute="..." ...>
204      <weapons>
205        <Weapon someattribute="..." ... />
206        <Weapon someattribute="..." ... />
207        <Weapon someattribute="..." ... />
208      </weapons>
209    </SpaceShip>
210
211    Note that "weapons" is the subsection. This allows you to add more types of sub-objects. In our example,
212    you could add pilots, blinking lights or other stuff. If you don't want a subsection, just use "" (an
213    empty string). The you can add sub-objects directly into the mainclass.
214*/
215#define XMLPortObjectExtended(classname, objectclass, sectionname, loadfunction, savefunction, xmlelement, mode, bApplyLoaderMask, bLoadBefore) \
216    XMLPortObjectGeneric(xmlcontainer##loadfunction##savefunction, classname, objectclass, sectionname, orxonox::createExecutor(orxonox::createFunctor(&classname::loadfunction), std::string( #classname ) + "::" + #loadfunction), orxonox::createExecutor(orxonox::createFunctor(&classname::savefunction), std::string( #classname ) + "::" + #savefunction), xmlelement, mode, bApplyLoaderMask, bLoadBefore)
217/**
218    @brief This is the same as XMLPortObjectExtended, but you can specify the loadfunction by adding the param types. See XMLPortParamTemplate for more details about the types.
219*/
220#define XMLPortObjectExtendedTemplate(classname, objectclass, sectionname, loadfunction, savefunction, xmlelement, mode, bApplyLoaderMask, bLoadBefore, ...) \
221    XMLPortObjectGeneric(xmlcontainer##loadfunction##savefunction, classname, objectclass, sectionname, orxonox::createExecutor(orxonox::createFunctor<classname, __VA_ARGS__ >(&classname::loadfunction), std::string( #classname ) + "::" + #loadfunction), orxonox::createExecutor(orxonox::createFunctor(&classname::savefunction), std::string( #classname ) + "::" + #savefunction), xmlelement, mode, bApplyLoaderMask, bLoadBefore)
222
223// -------------
224// XMLPortObject
225
226/**
227    @brief This is the same as XMLPortObjectExtended, but bApplyLoaderMask is false and bLoadBefore is true by default.
228*/
229#define XMLPortObject(classname, objectclass, sectionname, loadfunction, savefunction, xmlelement, mode) \
230    XMLPortObjectGeneric(xmlcontainer##loadfunction##savefunction, classname, objectclass, sectionname, orxonox::createExecutor(orxonox::createFunctor(&classname::loadfunction), std::string( #classname ) + "::" + #loadfunction), orxonox::createExecutor(orxonox::createFunctor(&classname::savefunction), std::string( #classname ) + "::" + #savefunction), xmlelement, mode, false, true)
231/**
232    @brief This is the same as XMLPortObject, but you can specify the loadfunction by adding the param types. See XMLPortParamTemplate for more details about the types.
233*/
234#define XMLPortObjectTemplate(classname, objectclass, sectionname, loadfunction, savefunction, xmlelement, mode, ...) \
235    XMLPortObjectGeneric(xmlcontainer##loadfunction##savefunction, classname, objectclass, sectionname, orxonox::createExecutor(orxonox::createFunctor<classname, __VA_ARGS__ >(&classname::loadfunction), std::string( #classname ) + "::" + #loadfunction), orxonox::createExecutor(orxonox::createFunctor(&classname::savefunction), std::string( #classname ) + "::" + #savefunction), xmlelement, mode, false, true)
236
237// --------------------
238// XMLPortObjectGeneric
239
240/**
241    @brief Generic XMLPortObject macro, that gets called by all other XMLPortObject macros above.
242*/
243#define XMLPortObjectGeneric(containername, classname, objectclass, sectionname, loadexecutor, saveexecutor, xmlelement, mode, bApplyLoaderMask, bLoadBefore) \
244    orxonox::XMLPortClassObjectContainer<classname, objectclass>* containername = (orxonox::XMLPortClassObjectContainer<classname, objectclass>*)(ClassIdentifier<classname>::getIdentifier()->getXMLPortObjectContainer(sectionname)); \
245    if (!containername) \
246    { \
247        containername = new orxonox::XMLPortClassObjectContainer<classname, objectclass>(std::string(sectionname), ClassIdentifier<classname>::getIdentifier(), loadexecutor, saveexecutor, bApplyLoaderMask, bLoadBefore); \
248        ClassIdentifier<classname>::getIdentifier()->addXMLPortObjectContainer(sectionname, containername); \
249    } \
250    containername->port(this, xmlelement, mode)
251
252
253namespace orxonox
254{
255    // ###############################
256    // ###  XMLPortParamContainer  ###
257    // ###############################
258    class _CoreExport XMLPortParamContainer
259    {
260    public:
261        enum ParseResult
262        {
263            PR_not_started,
264            PR_finished,
265            PR_waiting_for_default_values
266        };
267
268        public:
269            XMLPortParamContainer()
270                { this->parseResult_ = PR_not_started; }
271            virtual ~XMLPortParamContainer() {}
272
273            inline const std::string& getName() const
274                { return this->paramname_; }
275
276            virtual XMLPortParamContainer& description(const std::string description) = 0;
277            virtual const std::string& getDescription() = 0;
278
279            virtual XMLPortParamContainer& defaultValue(unsigned int index, const MultiType& param) = 0;
280            virtual XMLPortParamContainer& defaultValues(const MultiType& param1) = 0;
281            virtual XMLPortParamContainer& defaultValues(const MultiType& param1, const MultiType& param2) = 0;
282            virtual XMLPortParamContainer& defaultValues(const MultiType& param1, const MultiType& param2, const MultiType& param3) = 0;
283            virtual XMLPortParamContainer& defaultValues(const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4) = 0;
284            virtual XMLPortParamContainer& defaultValues(const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5) = 0;
285
286        protected:
287            std::string paramname_;
288            ParseResult parseResult_;
289            Identifier* identifier_;
290            BaseObject* owner_;
291    };
292
293    template <class T>
294    class XMLPortClassParamContainer : public XMLPortParamContainer
295    {
296        struct ParseParams
297        {
298            T* object;
299            Element* xmlelement;
300            XMLPort::Mode mode;
301        };
302
303        public:
304            XMLPortClassParamContainer(const std::string paramname, Identifier* identifier, ExecutorMember<T>* loadexecutor, ExecutorMember<T>* saveexecutor)
305            {
306                this->paramname_ = paramname;
307                this->identifier_ = identifier;
308                this->loadexecutor_ = loadexecutor;
309                this->saveexecutor_ = saveexecutor;
310            }
311
312            XMLPortParamContainer& port(BaseObject* owner, T* object, Element& xmlelement, XMLPort::Mode mode)
313            {
314                this->owner_ = owner;
315                this->parseParams_.object = object;
316                this->parseParams_.xmlelement = &xmlelement;
317                this->parseParams_.mode = mode;
318
319                if (mode == XMLPort::LoadObject)
320                {
321                    try
322                    {
323                        std::string attribute = xmlelement.GetAttribute(this->paramname_);
324                        if ((attribute.size() > 0) || (this->loadexecutor_->allDefaultValuesSet()))
325                        {
326                            COUT(5) << this->owner_->getLoaderIndentation() << "Loading parameter " << this->paramname_ << " in " << this->identifier_->getName() << " (objectname " << this->owner_->getName() << ")." << std::endl << this->owner_->getLoaderIndentation();
327                            if (this->loadexecutor_->parse(object, attribute, ","))
328                                this->parseResult_ = PR_finished;
329                            else
330                                this->parseResult_ = PR_waiting_for_default_values;
331                        }
332                        else
333                            this->parseResult_ = PR_waiting_for_default_values;
334                    }
335                    catch (ticpp::Exception& ex)
336                    {
337                        COUT(1) << std::endl;
338                        COUT(1) << "An error occurred in XMLPort.h while loading attribute '" << this->paramname_ << "' of '" << this->identifier_->getName() << "' (objectname: " << this->owner_->getName() << ") in " << this->owner_->getFilename() << ":" << std::endl;
339                        COUT(1) << ex.what() << std::endl;
340                    }
341                }
342                else
343                {
344                    if (this->saveexecutor_)
345                    {
346//                        xmlelement.SetAttribute(this->paramname_, "...");
347                    }
348                }
349
350                return (*this);
351            }
352
353            XMLPortParamContainer& port(BaseObject* owner, const ParseParams& parseParams)
354            {
355                return this->port(owner, parseParams.object, *parseParams.xmlelement, parseParams.mode);
356            }
357
358            XMLPortParamContainer& portIfWaitingForDefaultValues(const ParseResult& result, const ParseParams& params)
359            {
360                if (result == PR_waiting_for_default_values)
361                    return this->port(this->owner_, params);
362                else
363                    return (*this);
364            }
365
366            virtual XMLPortParamContainer& description(const std::string description)
367                { this->loadexecutor_->setDescription(description); return (*this); }
368            virtual const std::string& getDescription()
369                { return this->loadexecutor_->getDescription(); }
370
371            virtual XMLPortParamContainer& defaultValue(unsigned int index, const MultiType& param)
372            {
373                if (!this->loadexecutor_->defaultValueSet(index))
374                    this->loadexecutor_->setDefaultValue(index, param);
375                return this->portIfWaitingForDefaultValues(this->parseResult_, this->parseParams_);
376            }
377            virtual XMLPortParamContainer& defaultValues(const MultiType& param1)
378            {
379                if (!this->loadexecutor_->defaultValueSet(0))
380                    this->loadexecutor_->setDefaultValues(param1);
381                return this->portIfWaitingForDefaultValues(this->parseResult_, this->parseParams_);
382            }
383            virtual XMLPortParamContainer& defaultValues(const MultiType& param1, const MultiType& param2)
384            {
385                if ((!this->loadexecutor_->defaultValueSet(0)) || (!this->loadexecutor_->defaultValueSet(1)))
386                    this->loadexecutor_->setDefaultValues(param1, param2);
387                return this->portIfWaitingForDefaultValues(this->parseResult_, this->parseParams_);
388            }
389            virtual XMLPortParamContainer& defaultValues(const MultiType& param1, const MultiType& param2, const MultiType& param3)
390            {
391                if ((!this->loadexecutor_->defaultValueSet(0)) || (!this->loadexecutor_->defaultValueSet(1)) || (!this->loadexecutor_->defaultValueSet(2)))
392                    this->loadexecutor_->setDefaultValues(param1, param2, param3);
393                return this->portIfWaitingForDefaultValues(this->parseResult_, this->parseParams_);
394            }
395            virtual XMLPortParamContainer& defaultValues(const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4)
396            {
397                if ((!this->loadexecutor_->defaultValueSet(0)) || (!this->loadexecutor_->defaultValueSet(1)) || (!this->loadexecutor_->defaultValueSet(2)) || (!this->loadexecutor_->defaultValueSet(3)))
398                    this->loadexecutor_->setDefaultValues(param1, param2, param3, param4);
399                return this->portIfWaitingForDefaultValues(this->parseResult_, this->parseParams_);
400            }
401            virtual XMLPortParamContainer& defaultValues(const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5)
402            {
403                if ((!this->loadexecutor_->defaultValueSet(0)) || (!this->loadexecutor_->defaultValueSet(1)) || (!this->loadexecutor_->defaultValueSet(2)) || (!this->loadexecutor_->defaultValueSet(3)) || (!this->loadexecutor_->defaultValueSet(4)))
404                    this->loadexecutor_->setDefaultValues(param1, param2, param3, param4, param5);
405                return this->portIfWaitingForDefaultValues(this->parseResult_, this->parseParams_);
406            }
407
408        private:
409            ExecutorMember<T>* loadexecutor_;
410            ExecutorMember<T>* saveexecutor_;
411            ParseParams parseParams_;
412    };
413
414
415    // ################################
416    // ###  XMLPortObjectContainer  ###
417    // ################################
418    class _CoreExport XMLPortObjectContainer
419    {
420        public:
421            XMLPortObjectContainer()
422                { this->bApplyLoaderMask_ = false; }
423            virtual ~XMLPortObjectContainer() {}
424
425            inline const std::string& getName() const
426                { return this->sectionname_; }
427
428            virtual XMLPortObjectContainer& description(const std::string description) = 0;
429            virtual const std::string& getDescription() = 0;
430
431            bool identifierIsIncludedInLoaderMask(const Identifier* identifier);
432
433        protected:
434            std::string sectionname_;
435            bool bApplyLoaderMask_;
436            bool bLoadBefore_;
437            Identifier* identifier_;
438    };
439
440    template <class T, class O>
441    class XMLPortClassObjectContainer : public XMLPortObjectContainer
442    {
443        public:
444            XMLPortClassObjectContainer(const std::string sectionname, Identifier* identifier, ExecutorMember<T>* loadexecutor, ExecutorMember<T>* saveexecutor, bool bApplyLoaderMask, bool bLoadBefore)
445            {
446                this->sectionname_ = sectionname;
447                this->identifier_ = identifier;
448                this->loadexecutor_ = loadexecutor;
449                this->saveexecutor_ = saveexecutor;
450                this->bApplyLoaderMask_ = bApplyLoaderMask;
451                this->bLoadBefore_ = bLoadBefore;
452            }
453
454            XMLPortObjectContainer& port(T* object, Element& xmlelement, XMLPort::Mode mode)
455            {
456                if (mode == XMLPort::LoadObject)
457                {
458                    try
459                    {
460                        Element* xmlsubelement;
461                        if ((this->sectionname_ != "") && (this->sectionname_.size() > 0))
462                            xmlsubelement = xmlelement.FirstChildElement(this->sectionname_, false);
463                        else
464                            xmlsubelement = &xmlelement;
465
466                        if (xmlsubelement)
467                        {
468                            for (ticpp::Iterator<ticpp::Element> child = xmlsubelement->FirstChildElement(false); child != child.end(); child++)
469                            {
470                                Identifier* identifier = ClassByString(child->Value());
471                                if (identifier)
472                                {
473                                    if (identifier->isA(Class(O)))
474                                    {
475                                        if (identifier->isLoadable())
476                                        {
477                                            if (this->identifierIsIncludedInLoaderMask(identifier))
478                                            {
479                                                COUT(4) << ((BaseObject*)object)->getLoaderIndentation() << "fabricating " << child->Value() << "..." << std::endl;
480
481                                                BaseObject* newObject = identifier->fabricate((BaseObject*)object);
482                                                assert(newObject);
483                                                newObject->setLoaderIndentation(((BaseObject*)object)->getLoaderIndentation() + "  ");
484
485                                                O* castedObject = dynamic_cast<O*>(newObject);
486                                                assert(castedObject);
487
488                                                if (this->bLoadBefore_)
489                                                {
490                                                    newObject->XMLPort(*child, XMLPort::LoadObject);
491                                                    COUT(4) << ((BaseObject*)object)->getLoaderIndentation() << "assigning " << child->Value() << " (objectname " << newObject->getName() << ") to " << this->identifier_->getName() << " (objectname " << ((BaseObject*)object)->getName() << ")" << std::endl;
492                                                }
493                                                else
494                                                {
495                                                    COUT(4) << ((BaseObject*)object)->getLoaderIndentation() << "assigning " << child->Value() << " (object not yet loaded) to " << this->identifier_->getName() << " (objectname " << ((BaseObject*)object)->getName() << ")" << std::endl;
496                                                }
497
498                                                COUT(5) << ((BaseObject*)object)->getLoaderIndentation();
499                                                (*this->loadexecutor_)(object, castedObject);
500
501                                                if (!this->bLoadBefore_)
502                                                    newObject->XMLPort(*child, XMLPort::LoadObject);
503
504                                                COUT(5) << ((BaseObject*)object)->getLoaderIndentation() << "...fabricated " << child->Value() << " (objectname " << newObject->getName() << ")." << std::endl;
505                                            }
506                                        }
507                                        else
508                                        {
509                                            COUT(2) << ((BaseObject*)object)->getLoaderIndentation() << "Warning: '" << child->Value() << "' is not loadable." << std::endl;
510                                        }
511                                    }
512                                    else
513                                    {
514                                        COUT(2) << ((BaseObject*)object)->getLoaderIndentation() << "Warning: '" << child->Value() << "' is not a '" << Class(O)->getName() << "'." << std::endl;
515                                    }
516                                }
517                                else
518                                {
519                                    if (this->sectionname_ != "")
520                                    {
521                                        COUT(2) << object->getLoaderIndentation() << "Warning: '" << child->Value() << "' is not a valid classname." << std::endl;
522                                    }
523                                    else
524                                    {
525                                        // It's probably just another subsection
526                                    }
527                                }
528                            }
529                        }
530                    }
531                    catch (ticpp::Exception& ex)
532                    {
533                        COUT(1) << std::endl;
534                        COUT(1) << "An error occurred in XMLPort.h while loading a '" << Class(O)->getName() << "' in '" << this->sectionname_ << "' of '" << this->identifier_->getName() << "' (objectname: " << ((BaseObject*)object)->getName() << ") in " << object->getFilename() << ":" << std::endl;
535                        COUT(1) << ex.what() << std::endl;
536                    }
537                }
538                else
539                {
540                }
541
542                return (*this);
543            }
544
545            virtual XMLPortObjectContainer& description(const std::string description)
546                { this->loadexecutor_->setDescription(description); return (*this); }
547            virtual const std::string& getDescription()
548                { return this->loadexecutor_->getDescription(); }
549
550        private:
551            ExecutorMember<T>* loadexecutor_;
552            ExecutorMember<T>* saveexecutor_;
553    };
554}
555
556#endif /* _XMLPort_H__ */
Note: See TracBrowser for help on using the repository browser.