Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/core/XMLPort.h @ 1055

Last change on this file since 1055 was 1052, checked in by landauf, 16 years ago

merged core2 back to trunk
there might be some errors, wasn't able to test it yet due to some strange g++ and linker behaviour.

File size: 19.4 KB
Line 
1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *
4 *
5 *   License notice:
6 *
7 *   This program is free software; you can redistribute it and/or
8 *   modify it under the terms of the GNU General Public License
9 *   as published by the Free Software Foundation; either version 2
10 *   of the License, or (at your option) any later version.
11 *
12 *   This program is distributed in the hope that it will be useful,
13 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
14 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 *   GNU General Public License for more details.
16 *
17 *   You should have received a copy of the GNU General Public License
18 *   along with this program; if not, write to the Free Software
19 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
20 *
21 *   Author:
22 *      Fabian 'x3n' Landau
23 *   Co-authors:
24 *      ...
25 *
26 */
27
28#ifndef _XMLPort_H__
29#define _XMLPort_H__
30
31#include "util/XMLIncludes.h"
32#include "util/MultiTypeMath.h"
33#include "util/tinyxml/ticpp.h"
34#include "Executor.h"
35#include "Debug.h"
36#include "CoreIncludes.h"
37#include "BaseObject.h"
38
39#include "CorePrereqs.h"
40
41
42#define XMLPortParam(classname, paramname, loadfunction, savefunction, xmlelement, mode) \
43    XMLPortParamGeneric(xmlcontainer##loadfunction##savefunction, classname, paramname, orxonox::createExecutor(orxonox::createFunctor(&classname::loadfunction), #loadfunction), orxonox::createExecutor(orxonox::createFunctor(&classname::savefunction), #savefunction), xmlelement, mode)
44#define XMLPortParam_Template(classname, paramname, loadtemplate, loadfunction, savetemplate, savefunction, xmlelement, mode) \
45    XMLPortParamGeneric(xmlcontainer##loadfunction##savefunction, classname, paramname, orxonox::createExecutor(orxonox::createFunctor loadtemplate (&classname::loadfunction), #loadfunction), orxonox::createExecutor(orxonox::createFunctor savetemplate (&classname::savefunction), #savefunction), xmlelement, mode)
46
47#define XMLPortParamLoadOnly(classname, paramname, loadfunction, xmlelement, mode) \
48    XMLPortParamGeneric(xmlcontainer##loadfunction##0, classname, paramname, orxonox::createExecutor(orxonox::createFunctor(&classname::loadfunction), #loadfunction), 0, xmlelement, mode)
49#define XMLPortParamLoadOnly_Template(classname, paramname, loadtemplate, loadfunction, xmlelement, mode) \
50    XMLPortParamGeneric(xmlcontainer##loadfunction##0, classname, paramname, orxonox::createExecutor(orxonox::createFunctor loadtemplate (&classname::loadfunction), #loadfunction), 0, xmlelement, mode)
51
52#define XMLPortParamGeneric(containername, classname, paramname, loadexecutor, saveexecutor, xmlelement, mode) \
53    orxonox::XMLPortClassParamContainer<classname>* containername = (orxonox::XMLPortClassParamContainer<classname>*)(this->getIdentifier()->getXMLPortParamContainer(paramname)); \
54    if (!containername) \
55    { \
56        containername = new orxonox::XMLPortClassParamContainer<classname>(std::string(paramname), loadexecutor, saveexecutor); \
57        this->getIdentifier()->addXMLPortParamContainer(paramname, containername); \
58    } \
59    containername->port(this, xmlelement, mode)
60
61
62#define XMLPortObject(classname, objectclass, sectionname, loadfunction, savefunction, xmlelement, mode, bApplyLoaderMask, bLoadBefore) \
63    XMLPortObjectGeneric(xmlcontainer##loadfunction##savefunction, classname, objectclass, sectionname, orxonox::createExecutor(orxonox::createFunctor(&classname::loadfunction), #loadfunction), orxonox::createExecutor(orxonox::createFunctor(&classname::savefunction), #savefunction), xmlelement, mode, bApplyLoaderMask, bLoadBefore)
64#define XMLPortObject_Template(classname, objectclass, sectionname, loadtemplate, loadfunction, savetemplate, savefunction, xmlelement, mode, bApplyLoaderMask, bLoadBefore) \
65    XMLPortObjectGeneric(xmlcontainer##loadfunction##savefunction, classname, objectclass, sectionname, orxonox::createExecutor(orxonox::createFunctor loadtemplate (&classname::loadfunction), #loadfunction), orxonox::createExecutor(orxonox::createFunctor savetemplate (&classname::savefunction), #savefunction), xmlelement, mode, bApplyLoaderMask, bLoadBefore)
66
67#define XMLPortObjectGeneric(containername, classname, objectclass, sectionname, loadexecutor, saveexecutor, xmlelement, mode, bApplyLoaderMask, bLoadBefore) \
68    orxonox::XMLPortClassObjectContainer<classname, objectclass>* containername = (orxonox::XMLPortClassObjectContainer<classname, objectclass>*)(this->getIdentifier()->getXMLPortObjectContainer(sectionname)); \
69    if (!containername) \
70    { \
71        containername = new orxonox::XMLPortClassObjectContainer<classname, objectclass>(std::string(sectionname), loadexecutor, saveexecutor, bApplyLoaderMask, bLoadBefore); \
72        this->getIdentifier()->addXMLPortObjectContainer(sectionname, containername); \
73    } \
74    containername->port(this, xmlelement, mode)
75
76
77namespace orxonox
78{
79
80#ifndef _XMLPort_Mode__
81#define _XMLPort_Mode__
82    namespace XMLPort
83    {
84        enum Mode
85        {
86            LoadObject,
87            SaveObject
88        };
89    }
90#endif
91
92    // ###############################
93    // ###  XMLPortParamContainer  ###
94    // ###############################
95    class _CoreExport XMLPortParamContainer
96    {
97        enum ParseResult
98        {
99            PR_not_started,
100            PR_finished,
101            PR_waiting_for_default_values
102        };
103
104        public:
105            XMLPortParamContainer()
106                { this->parseResult_ = PR_not_started; }
107            virtual ~XMLPortParamContainer() {}
108
109            inline const std::string& getName() const
110                { return this->paramname_; }
111
112            virtual XMLPortParamContainer& description(const std::string description) = 0;
113            virtual const std::string& getDescription() = 0;
114
115            virtual XMLPortParamContainer& defaultValue(unsigned int index, const MultiTypeMath& param) = 0;
116            virtual XMLPortParamContainer& defaultValues(const MultiTypeMath& param1) = 0;
117            virtual XMLPortParamContainer& defaultValues(const MultiTypeMath& param1, const MultiTypeMath& param2) = 0;
118            virtual XMLPortParamContainer& defaultValues(const MultiTypeMath& param1, const MultiTypeMath& param2, const MultiTypeMath& param3) = 0;
119            virtual XMLPortParamContainer& defaultValues(const MultiTypeMath& param1, const MultiTypeMath& param2, const MultiTypeMath& param3, const MultiTypeMath& param4) = 0;
120            virtual XMLPortParamContainer& defaultValues(const MultiTypeMath& param1, const MultiTypeMath& param2, const MultiTypeMath& param3, const MultiTypeMath& param4, const MultiTypeMath& param5) = 0;
121
122        protected:
123            std::string paramname_;
124            ParseResult parseResult_;
125
126    };
127
128    template <class T>
129    class XMLPortClassParamContainer : public XMLPortParamContainer
130    {
131        struct ParseParams
132        {
133            T* object;
134            Element* xmlelement;
135            XMLPort::Mode mode;
136        };
137
138        public:
139            XMLPortClassParamContainer(const std::string paramname, ExecutorMember<T>* loadexecutor, ExecutorMember<T>* saveexecutor)
140            {
141                this->paramname_ = paramname;
142                this->loadexecutor_ = loadexecutor;
143                this->saveexecutor_ = saveexecutor;
144            }
145
146            XMLPortParamContainer& port(T* object, Element& xmlelement, XMLPort::Mode mode)
147            {
148                this->parseParams_.object = object;
149                this->parseParams_.xmlelement = &xmlelement;
150                this->parseParams_.mode = mode;
151
152                if (mode == XMLPort::LoadObject)
153                {
154                    try
155                    {
156                        std::string attribute = xmlelement.GetAttribute(this->paramname_);
157                        if ((attribute.size() > 0) || (this->loadexecutor_->allDefaultValuesSet()))
158                        {
159                            COUT(5) << object->getLoaderIndentation() << "Loading parameter " << this->paramname_ << " in " << object->getIdentifier()->getName() << " (objectname " << object->getName() << ")." << std::endl << object->getLoaderIndentation();
160                            if (this->loadexecutor_->parse(object, attribute, ","))
161                                this->parseResult_ = PR_finished;
162                            else
163                                this->parseResult_ = PR_waiting_for_default_values;
164                        }
165                    }
166                    catch(ticpp::Exception& ex)
167                    {
168                        COUT(1) << std::endl;
169                        COUT(1) << "An error occurred in XMLPort.h while loading attribute '" << this->paramname_ << "' of '" << object->getIdentifier()->getName() << "' (objectname: " << object->getName() << ") in " << object->getLevelfile() << ":" << std::endl;
170                        COUT(1) << ex.what() << std::endl;
171                    }
172                }
173                else
174                {
175                    if (this->saveexecutor_)
176                    {
177//                        xmlelement.SetAttribute(this->paramname_, "...");
178                    }
179                }
180
181                return (*this);
182            }
183
184            XMLPortParamContainer& port(const ParseParams& parseParams)
185            {
186                return this->port(parseParams.object, *parseParams.xmlelement, parseParams.mode);
187            }
188
189            XMLPortParamContainer& portIfWaitingForDefaultValues(const ParseResult& result, const ParseParams& params)
190            {
191                if (result == PR_waiting_for_default_values)
192                    return this->port(params);
193                else
194                    return (*this);
195            }
196
197            virtual XMLPortParamContainer& description(const std::string description)
198                { this->loadexecutor_->setDescription(description); return (*this); }
199            virtual const std::string& getDescription()
200                { return this->loadexecutor_->getDescription(); }
201
202            virtual XMLPortParamContainer& defaultValue(unsigned int index, const MultiTypeMath& param)
203            {
204                if (!this->loadexecutor_->defaultValueSet(index))
205                    this->loadexecutor_->setDefaultValue(index, param);
206                return this->portIfWaitingForDefaultValues(this->parseResult_, this->parseParams_);
207            }
208            virtual XMLPortParamContainer& defaultValues(const MultiTypeMath& param1)
209            {
210                if (!this->loadexecutor_->defaultValueSet(0))
211                    this->loadexecutor_->setDefaultValues(param1);
212                return this->portIfWaitingForDefaultValues(this->parseResult_, this->parseParams_);
213            }
214            virtual XMLPortParamContainer& defaultValues(const MultiTypeMath& param1, const MultiTypeMath& param2)
215            {
216                if ((!this->loadexecutor_->defaultValueSet(0)) || (!this->loadexecutor_->defaultValueSet(1)))
217                    this->loadexecutor_->setDefaultValues(param1, param2);
218                return this->portIfWaitingForDefaultValues(this->parseResult_, this->parseParams_);
219            }
220            virtual XMLPortParamContainer& defaultValues(const MultiTypeMath& param1, const MultiTypeMath& param2, const MultiTypeMath& param3)
221            {
222                if ((!this->loadexecutor_->defaultValueSet(0)) || (!this->loadexecutor_->defaultValueSet(1)) || (!this->loadexecutor_->defaultValueSet(2)))
223                    this->loadexecutor_->setDefaultValues(param1, param2, param3);
224                return this->portIfWaitingForDefaultValues(this->parseResult_, this->parseParams_);
225            }
226            virtual XMLPortParamContainer& defaultValues(const MultiTypeMath& param1, const MultiTypeMath& param2, const MultiTypeMath& param3, const MultiTypeMath& param4)
227            {
228                if ((!this->loadexecutor_->defaultValueSet(0)) || (!this->loadexecutor_->defaultValueSet(1)) || (!this->loadexecutor_->defaultValueSet(2)) || (!this->loadexecutor_->defaultValueSet(3)))
229                    this->loadexecutor_->setDefaultValues(param1, param2, param3, param4);
230                return this->portIfWaitingForDefaultValues(this->parseResult_, this->parseParams_);
231            }
232            virtual XMLPortParamContainer& defaultValues(const MultiTypeMath& param1, const MultiTypeMath& param2, const MultiTypeMath& param3, const MultiTypeMath& param4, const MultiTypeMath& param5)
233            {
234                if ((!this->loadexecutor_->defaultValueSet(0)) || (!this->loadexecutor_->defaultValueSet(1)) || (!this->loadexecutor_->defaultValueSet(2)) || (!this->loadexecutor_->defaultValueSet(3)) || (!this->loadexecutor_->defaultValueSet(4)))
235                    this->loadexecutor_->setDefaultValues(param1, param2, param3, param4, param5);
236                return this->portIfWaitingForDefaultValues(this->parseResult_, this->parseParams_);
237            }
238
239        private:
240            ExecutorMember<T>* loadexecutor_;
241            ExecutorMember<T>* saveexecutor_;
242            ParseParams parseParams_;
243    };
244
245
246    // ################################
247    // ###  XMLPortObjectContainer  ###
248    // ################################
249    class _CoreExport XMLPortObjectContainer
250    {
251        public:
252            XMLPortObjectContainer()
253                { this->bApplyLoaderMask_ = false; }
254            virtual ~XMLPortObjectContainer() {}
255
256            inline const std::string& getName() const
257                { return this->sectionname_; }
258
259            virtual XMLPortObjectContainer& description(const std::string description) = 0;
260            virtual const std::string& getDescription() = 0;
261
262            bool identifierIsIncludedInLoaderMask(const Identifier* identifier);
263
264        protected:
265            std::string sectionname_;
266            bool bApplyLoaderMask_;
267            bool bLoadBefore_;
268    };
269
270    template <class T, class O>
271    class XMLPortClassObjectContainer : public XMLPortObjectContainer
272    {
273        public:
274            XMLPortClassObjectContainer(const std::string sectionname, ExecutorMember<T>* loadexecutor, ExecutorMember<T>* saveexecutor, bool bApplyLoaderMask, bool bLoadBefore)
275            {
276                this->sectionname_ = sectionname;
277                this->loadexecutor_ = loadexecutor;
278                this->saveexecutor_ = saveexecutor;
279                this->bApplyLoaderMask_ = bApplyLoaderMask;
280                this->bLoadBefore_ = bLoadBefore;
281            }
282
283            XMLPortObjectContainer& port(T* object, Element& xmlelement, XMLPort::Mode mode)
284            {
285                if (mode == XMLPort::LoadObject)
286                {
287                    try
288                    {
289                        Element* xmlsubelement;
290                        if ((this->sectionname_ != "") && (this->sectionname_.size() > 0))
291                            xmlsubelement = xmlelement.FirstChildElement(this->sectionname_, false);
292                        else
293                            xmlsubelement = &xmlelement;
294
295                        if (xmlsubelement)
296                        {
297                            for (ticpp::Iterator<ticpp::Element> child = xmlsubelement->FirstChildElement(false); child != child.end(); child++)
298                            {
299                                Identifier* identifier = ID(child->Value());
300                                if (identifier)
301                                {
302                                    if (identifier->isA(Class(O)))
303                                    {
304                                        if (this->identifierIsIncludedInLoaderMask(identifier))
305                                        {
306                                            COUT(4) << object->getLoaderIndentation() << "fabricating " << child->Value() << "..." << std::endl;
307
308                                            O* newObject = (O*)identifier->fabricate();
309                                            newObject->setLoaderIndentation(object->getLoaderIndentation() + "  ");
310                                            newObject->setLevel(object->getLevel());
311                                            newObject->setNamespace(object->getNamespace());
312
313                                            if (this->bLoadBefore_)
314                                            {
315                                                newObject->XMLPort(*child, XMLPort::LoadObject);
316                                                COUT(4) << object->getLoaderIndentation() << "assigning " << child->Value() << " (objectname " << newObject->getName() << ") to " << object->getIdentifier()->getName() << " (objectname " << object->getName() << ")" << std::endl;
317                                            }
318                                            else
319                                            {
320                                                COUT(4) << object->getLoaderIndentation() << "assigning " << child->Value() << " (object not yet loaded) to " << object->getIdentifier()->getName() << " (objectname " << object->getName() << ")" << std::endl;
321                                            }
322
323                                            COUT(5) << object->getLoaderIndentation();
324                                            (*this->loadexecutor_)(object, newObject);
325
326                                            if (!this->bLoadBefore_)
327                                                newObject->XMLPort(*child, XMLPort::LoadObject);
328
329                                            COUT(5) << object->getLoaderIndentation() << "...fabricated " << child->Value() << " (objectname " << newObject->getName() << ")." << std::endl;
330                                        }
331                                    }
332                                    else
333                                    {
334                                        COUT(2) << object->getLoaderIndentation() << "Warning: '" << child->Value() << "' is not a '" << Class(O)->getName() << "'." << std::endl;
335                                    }
336                                }
337                                else
338                                {
339                                    COUT(2) << object->getLoaderIndentation() << "Warning: '" << child->Value() << "' is not a valid classname." << std::endl;
340                                }
341                            }
342                        }
343                    }
344                    catch(ticpp::Exception& ex)
345                    {
346                        COUT(1) << std::endl;
347                        COUT(1) << "An error occurred in XMLPort.h while loading a '" << Class(O)->getName() << "' in '" << this->sectionname_ << "' of '" << object->getIdentifier()->getName() << "' (objectname: " << object->getName() << ") in " << object->getLevelfile() << ":" << std::endl;
348                        COUT(1) << ex.what() << std::endl;
349                    }
350                }
351                else
352                {
353                }
354
355                return (*this);
356            }
357
358            virtual XMLPortObjectContainer& description(const std::string description)
359                { this->loadexecutor_->setDescription(description); return (*this); }
360            virtual const std::string& getDescription()
361                { return this->loadexecutor_->getDescription(); }
362
363        private:
364            ExecutorMember<T>* loadexecutor_;
365            ExecutorMember<T>* saveexecutor_;
366    };
367}
368
369#endif /* _XMLPort_H__ */
Note: See TracBrowser for help on using the repository browser.