Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 1787 was 1787, checked in by rgrieder, 16 years ago

Replaced macro "Class" with "GetClassIdentifier" to avoid future collision because the macro is very short.
"ID" was already replaced with the introduction of CEGUI which used ID somewhere as non-macro. The compiler error was completely misleading though…

  • Property svn:eol-style set to native
File size: 21.1 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#ifndef _XMLPort_H__
30#define _XMLPort_H__
31
32#include "CorePrereqs.h"
33
34#include "util/Debug.h"
35#include "util/XMLIncludes.h"
36#include "util/MultiType.h"
37#include "tinyxml/ticpp.h"
38#include "Executor.h"
39#include "CoreIncludes.h"
40#include "BaseObject.h"
41
42
43#define XMLPortParam(classname, paramname, loadfunction, savefunction, xmlelement, mode) \
44    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)
45#define XMLPortParamTemplate(classname, paramname, loadfunction, savefunction, xmlelement, mode, ...) \
46    XMLPortParamGeneric(xmlcontainer##loadfunction##savefunction, classname, classname, this, paramname, orxonox::createExecutor(orxonox::createFunctor< __VA_ARGS__ >(&classname::loadfunction), std::string( #classname ) + "::" + #loadfunction), orxonox::createExecutor(orxonox::createFunctor(&classname::savefunction), std::string( #classname ) + "::" + #savefunction), xmlelement, mode)
47
48#define XMLPortParamLoadOnly(classname, paramname, loadfunction, xmlelement, mode) \
49    XMLPortParamGeneric(xmlcontainer##loadfunction##0, classname, classname, this, paramname, orxonox::createExecutor(orxonox::createFunctor(&classname::loadfunction), std::string( #classname ) + "::" + #loadfunction), 0, xmlelement, mode)
50#define XMLPortParamLoadOnlyTemplate(classname, paramname, loadfunction, xmlelement, mode, ...) \
51    XMLPortParamGeneric(xmlcontainer##loadfunction##0, classname, classname, this, paramname, orxonox::createExecutor(orxonox::createFunctor< __VA_ARGS__ >(&classname::loadfunction), std::string( #classname ) + "::" + #loadfunction), 0, xmlelement, mode)
52
53#define XMLPortParamExtern(classname, externclass, object, paramname, loadfunction, savefunction, xmlelement, mode) \
54    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);
55#define XMLPortParamExternTemplate(classname, externclass, object, paramname, loadfunction, savefunction, xmlelement, mode, ...) \
56    XMLPortParamGeneric(xmlcontainer##loadfunction##savefunction, classname, externclass, object, paramname, orxonox::createExecutor(orxonox::createFunctor< __VA_ARGS__ >(&externclass::loadfunction), std::string( #externclass ) + "::" + #loadfunction), orxonox::createExecutor(orxonox::createFunctor(&externclass::savefunction), std::string( #externclass ) + "::" + #savefunction), xmlelement, mode);
57
58#define XMLPortParamGeneric(containername, classname, objectclass, object, paramname, loadexecutor, saveexecutor, xmlelement, mode) \
59    orxonox::XMLPortClassParamContainer<objectclass>* containername = (orxonox::XMLPortClassParamContainer<objectclass>*)(ClassIdentifier<classname>::getIdentifier()->getXMLPortParamContainer(paramname)); \
60    if (!containername) \
61    { \
62        containername = new orxonox::XMLPortClassParamContainer<objectclass>(std::string(paramname), ClassIdentifier<classname>::getIdentifier(), loadexecutor, saveexecutor); \
63        ClassIdentifier<classname>::getIdentifier()->addXMLPortParamContainer(paramname, containername); \
64    } \
65    containername->port((BaseObject*)this, object, xmlelement, mode)
66
67
68#define XMLPortObject(classname, objectclass, sectionname, loadfunction, savefunction, xmlelement, mode, bApplyLoaderMask, bLoadBefore) \
69    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)
70#define XMLPortObjectTemplate(classname, objectclass, sectionname, loadfunction, savefunction, xmlelement, mode, bApplyLoaderMask, bLoadBefore, ...) \
71    XMLPortObjectGeneric(xmlcontainer##loadfunction##savefunction, classname, objectclass, sectionname, orxonox::createExecutor(orxonox::createFunctor< __VA_ARGS__ >(&classname::loadfunction), std::string( #classname ) + "::" + #loadfunction), orxonox::createExecutor(orxonox::createFunctor(&classname::savefunction), std::string( #classname ) + "::" + #savefunction), xmlelement, mode, bApplyLoaderMask, bLoadBefore)
72
73#define XMLPortObjectGeneric(containername, classname, objectclass, sectionname, loadexecutor, saveexecutor, xmlelement, mode, bApplyLoaderMask, bLoadBefore) \
74    orxonox::XMLPortClassObjectContainer<classname, objectclass>* containername = (orxonox::XMLPortClassObjectContainer<classname, objectclass>*)(ClassIdentifier<classname>::getIdentifier()->getXMLPortObjectContainer(sectionname)); \
75    if (!containername) \
76    { \
77        containername = new orxonox::XMLPortClassObjectContainer<classname, objectclass>(std::string(sectionname), ClassIdentifier<classname>::getIdentifier(), loadexecutor, saveexecutor, bApplyLoaderMask, bLoadBefore); \
78        ClassIdentifier<classname>::getIdentifier()->addXMLPortObjectContainer(sectionname, containername); \
79    } \
80    containername->port(this, xmlelement, mode)
81
82
83namespace orxonox
84{
85    // ###############################
86    // ###  XMLPortParamContainer  ###
87    // ###############################
88    class _CoreExport XMLPortParamContainer
89    {
90    public:
91        enum ParseResult
92        {
93            PR_not_started,
94            PR_finished,
95            PR_waiting_for_default_values
96        };
97
98        public:
99            XMLPortParamContainer()
100                { this->parseResult_ = PR_not_started; }
101            virtual ~XMLPortParamContainer() {}
102
103            inline const std::string& getName() const
104                { return this->paramname_; }
105
106            virtual XMLPortParamContainer& description(const std::string description) = 0;
107            virtual const std::string& getDescription() = 0;
108
109            virtual XMLPortParamContainer& defaultValue(unsigned int index, const MultiType& param) = 0;
110            virtual XMLPortParamContainer& defaultValues(const MultiType& param1) = 0;
111            virtual XMLPortParamContainer& defaultValues(const MultiType& param1, const MultiType& param2) = 0;
112            virtual XMLPortParamContainer& defaultValues(const MultiType& param1, const MultiType& param2, const MultiType& param3) = 0;
113            virtual XMLPortParamContainer& defaultValues(const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4) = 0;
114            virtual XMLPortParamContainer& defaultValues(const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5) = 0;
115
116        protected:
117            std::string paramname_;
118            ParseResult parseResult_;
119            Identifier* identifier_;
120            BaseObject* owner_;
121    };
122
123    template <class T>
124    class XMLPortClassParamContainer : public XMLPortParamContainer
125    {
126        struct ParseParams
127        {
128            T* object;
129            Element* xmlelement;
130            XMLPort::Mode mode;
131        };
132
133        public:
134            XMLPortClassParamContainer(const std::string paramname, Identifier* identifier, ExecutorMember<T>* loadexecutor, ExecutorMember<T>* saveexecutor)
135            {
136                this->paramname_ = paramname;
137                this->identifier_ = identifier;
138                this->loadexecutor_ = loadexecutor;
139                this->saveexecutor_ = saveexecutor;
140            }
141
142            XMLPortParamContainer& port(BaseObject* owner, T* object, Element& xmlelement, XMLPort::Mode mode)
143            {
144                this->owner_ = owner;
145                this->parseParams_.object = object;
146                this->parseParams_.xmlelement = &xmlelement;
147                this->parseParams_.mode = mode;
148
149                if (mode == XMLPort::LoadObject)
150                {
151                    try
152                    {
153                        std::string attribute = xmlelement.GetAttribute(this->paramname_);
154                        if ((attribute.size() > 0) || (this->loadexecutor_->allDefaultValuesSet()))
155                        {
156                            COUT(5) << this->owner_->getLoaderIndentation() << "Loading parameter " << this->paramname_ << " in " << this->identifier_->getName() << " (objectname " << this->owner_->getName() << ")." << std::endl << this->owner_->getLoaderIndentation();
157                            if (this->loadexecutor_->parse(object, attribute, ","))
158                                this->parseResult_ = PR_finished;
159                            else
160                                this->parseResult_ = PR_waiting_for_default_values;
161                        }
162                        else
163                            this->parseResult_ = PR_waiting_for_default_values;
164                    }
165                    catch (ticpp::Exception& ex)
166                    {
167                        COUT(1) << std::endl;
168                        COUT(1) << "An error occurred in XMLPort.h while loading attribute '" << this->paramname_ << "' of '" << this->identifier_->getName() << "' (objectname: " << this->owner_->getName() << ") in " << this->owner_->getLevelfile() << ":" << std::endl;
169                        COUT(1) << ex.what() << std::endl;
170                    }
171                }
172                else
173                {
174                    if (this->saveexecutor_)
175                    {
176//                        xmlelement.SetAttribute(this->paramname_, "...");
177                    }
178                }
179
180                return (*this);
181            }
182
183            XMLPortParamContainer& port(BaseObject* owner, const ParseParams& parseParams)
184            {
185                return this->port(owner, parseParams.object, *parseParams.xmlelement, parseParams.mode);
186            }
187
188            XMLPortParamContainer& portIfWaitingForDefaultValues(const ParseResult& result, const ParseParams& params)
189            {
190                if (result == PR_waiting_for_default_values)
191                    return this->port(this->owner_, params);
192                else
193                    return (*this);
194            }
195
196            virtual XMLPortParamContainer& description(const std::string description)
197                { this->loadexecutor_->setDescription(description); return (*this); }
198            virtual const std::string& getDescription()
199                { return this->loadexecutor_->getDescription(); }
200
201            virtual XMLPortParamContainer& defaultValue(unsigned int index, const MultiType& param)
202            {
203                if (!this->loadexecutor_->defaultValueSet(index))
204                    this->loadexecutor_->setDefaultValue(index, param);
205                return this->portIfWaitingForDefaultValues(this->parseResult_, this->parseParams_);
206            }
207            virtual XMLPortParamContainer& defaultValues(const MultiType& param1)
208            {
209                if (!this->loadexecutor_->defaultValueSet(0))
210                    this->loadexecutor_->setDefaultValues(param1);
211                return this->portIfWaitingForDefaultValues(this->parseResult_, this->parseParams_);
212            }
213            virtual XMLPortParamContainer& defaultValues(const MultiType& param1, const MultiType& param2)
214            {
215                if ((!this->loadexecutor_->defaultValueSet(0)) || (!this->loadexecutor_->defaultValueSet(1)))
216                    this->loadexecutor_->setDefaultValues(param1, param2);
217                return this->portIfWaitingForDefaultValues(this->parseResult_, this->parseParams_);
218            }
219            virtual XMLPortParamContainer& defaultValues(const MultiType& param1, const MultiType& param2, const MultiType& param3)
220            {
221                if ((!this->loadexecutor_->defaultValueSet(0)) || (!this->loadexecutor_->defaultValueSet(1)) || (!this->loadexecutor_->defaultValueSet(2)))
222                    this->loadexecutor_->setDefaultValues(param1, param2, param3);
223                return this->portIfWaitingForDefaultValues(this->parseResult_, this->parseParams_);
224            }
225            virtual XMLPortParamContainer& defaultValues(const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4)
226            {
227                if ((!this->loadexecutor_->defaultValueSet(0)) || (!this->loadexecutor_->defaultValueSet(1)) || (!this->loadexecutor_->defaultValueSet(2)) || (!this->loadexecutor_->defaultValueSet(3)))
228                    this->loadexecutor_->setDefaultValues(param1, param2, param3, param4);
229                return this->portIfWaitingForDefaultValues(this->parseResult_, this->parseParams_);
230            }
231            virtual XMLPortParamContainer& defaultValues(const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5)
232            {
233                if ((!this->loadexecutor_->defaultValueSet(0)) || (!this->loadexecutor_->defaultValueSet(1)) || (!this->loadexecutor_->defaultValueSet(2)) || (!this->loadexecutor_->defaultValueSet(3)) || (!this->loadexecutor_->defaultValueSet(4)))
234                    this->loadexecutor_->setDefaultValues(param1, param2, param3, param4, param5);
235                return this->portIfWaitingForDefaultValues(this->parseResult_, this->parseParams_);
236            }
237
238        private:
239            ExecutorMember<T>* loadexecutor_;
240            ExecutorMember<T>* saveexecutor_;
241            ParseParams parseParams_;
242    };
243
244
245    // ################################
246    // ###  XMLPortObjectContainer  ###
247    // ################################
248    class _CoreExport XMLPortObjectContainer
249    {
250        public:
251            XMLPortObjectContainer()
252                { this->bApplyLoaderMask_ = false; }
253            virtual ~XMLPortObjectContainer() {}
254
255            inline const std::string& getName() const
256                { return this->sectionname_; }
257
258            virtual XMLPortObjectContainer& description(const std::string description) = 0;
259            virtual const std::string& getDescription() = 0;
260
261            bool identifierIsIncludedInLoaderMask(const Identifier* identifier);
262
263        protected:
264            std::string sectionname_;
265            bool bApplyLoaderMask_;
266            bool bLoadBefore_;
267            Identifier* identifier_;
268    };
269
270    template <class T, class O>
271    class XMLPortClassObjectContainer : public XMLPortObjectContainer
272    {
273        public:
274            XMLPortClassObjectContainer(const std::string sectionname, Identifier* identifier, ExecutorMember<T>* loadexecutor, ExecutorMember<T>* saveexecutor, bool bApplyLoaderMask, bool bLoadBefore)
275            {
276                this->sectionname_ = sectionname;
277                this->identifier_ = identifier;
278                this->loadexecutor_ = loadexecutor;
279                this->saveexecutor_ = saveexecutor;
280                this->bApplyLoaderMask_ = bApplyLoaderMask;
281                this->bLoadBefore_ = bLoadBefore;
282            }
283
284            XMLPortObjectContainer& port(T* object, Element& xmlelement, XMLPort::Mode mode)
285            {
286                if (mode == XMLPort::LoadObject)
287                {
288                    try
289                    {
290                        Element* xmlsubelement;
291                        if ((this->sectionname_ != "") && (this->sectionname_.size() > 0))
292                            xmlsubelement = xmlelement.FirstChildElement(this->sectionname_, false);
293                        else
294                            xmlsubelement = &xmlelement;
295
296                        if (xmlsubelement)
297                        {
298                            for (ticpp::Iterator<ticpp::Element> child = xmlsubelement->FirstChildElement(false); child != child.end(); child++)
299                            {
300                                Identifier* identifier = GetIdentifier(child->Value());
301                                if (identifier)
302                                {
303                                    if (identifier->isA(GetClassIdentifier(O)))
304                                    {
305                                        if (this->identifierIsIncludedInLoaderMask(identifier))
306                                        {
307                                            COUT(4) << ((BaseObject*)object)->getLoaderIndentation() << "fabricating " << child->Value() << "..." << std::endl;
308
309                                            BaseObject* newObject = identifier->fabricate();
310                                            newObject->setLoaderIndentation(((BaseObject*)object)->getLoaderIndentation() + "  ");
311                                            newObject->setLevel(((BaseObject*)object)->getLevel());
312                                            newObject->setNamespace(((BaseObject*)object)->getNamespace());
313
314                                            if (this->bLoadBefore_)
315                                            {
316                                                newObject->XMLPort(*child, XMLPort::LoadObject);
317                                                COUT(4) << ((BaseObject*)object)->getLoaderIndentation() << "assigning " << child->Value() << " (objectname " << newObject->getName() << ") to " << this->identifier_->getName() << " (objectname " << ((BaseObject*)object)->getName() << ")" << std::endl;
318                                            }
319                                            else
320                                            {
321                                                COUT(4) << ((BaseObject*)object)->getLoaderIndentation() << "assigning " << child->Value() << " (object not yet loaded) to " << this->identifier_->getName() << " (objectname " << ((BaseObject*)object)->getName() << ")" << std::endl;
322                                            }
323
324                                            COUT(5) << ((BaseObject*)object)->getLoaderIndentation();
325                                            (*this->loadexecutor_)(object, newObject);
326
327                                            if (!this->bLoadBefore_)
328                                                newObject->XMLPort(*child, XMLPort::LoadObject);
329
330                                            COUT(5) << ((BaseObject*)object)->getLoaderIndentation() << "...fabricated " << child->Value() << " (objectname " << newObject->getName() << ")." << std::endl;
331                                        }
332                                    }
333                                    else
334                                    {
335                                        COUT(2) << ((BaseObject*)object)->getLoaderIndentation() << "Warning: '" << child->Value() << "' is not a '" << GetClassIdentifier(O)->getName() << "'." << std::endl;
336                                    }
337                                }
338                                else
339                                {
340                                    COUT(2) << object->getLoaderIndentation() << "Warning: '" << child->Value() << "' is not a valid classname." << std::endl;
341                                }
342                            }
343                        }
344                    }
345                    catch (ticpp::Exception& ex)
346                    {
347                        COUT(1) << std::endl;
348                        COUT(1) << "An error occurred in XMLPort.h while loading a '" << GetClassIdentifier(O)->getName() << "' in '" << this->sectionname_ << "' of '" << this->identifier_->getName() << "' (objectname: " << ((BaseObject*)object)->getName() << ") in " << object->getLevelfile() << ":" << std::endl;
349                        COUT(1) << ex.what() << std::endl;
350                    }
351                }
352                else
353                {
354                }
355
356                return (*this);
357            }
358
359            virtual XMLPortObjectContainer& description(const std::string description)
360                { this->loadexecutor_->setDescription(description); return (*this); }
361            virtual const std::string& getDescription()
362                { return this->loadexecutor_->getDescription(); }
363
364        private:
365            ExecutorMember<T>* loadexecutor_;
366            ExecutorMember<T>* saveexecutor_;
367    };
368}
369
370#endif /* _XMLPort_H__ */
Note: See TracBrowser for help on using the repository browser.