Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/core2/src/orxonox/core/XMLPort.h @ 898

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

removed some test output in Namespace.cc and corrected one line of debug output in XMLPort

File size: 14.8 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 "util/SubString.h"
35#include "Functor.h"
36#include "Debug.h"
37#include "CoreIncludes.h"
38#include "BaseObject.h"
39
40#include "CorePrereqs.h"
41
42
43#define XMLPortParam(classname, paramname, loadfunction, savefunction, xmlelement, loading) \
44    XMLPortParamGeneric(classname, paramname, xmlcontainer##loadfunction##savefunction, createFunctor(&classname::loadfunction), createFunctor(&classname::savefunction), xmlelement, loading)
45#define XMLPortParam_Template(classname, paramname, loadtemplate, loadfunction, savetemplate, savefunction, xmlelement, loading) \
46    XMLPortParamGeneric(classname, paramname, xmlcontainer##loadfunction##savefunction, createFunctor loadtemplate (&classname::loadfunction), createFunctor savetemplate (&classname::savefunction), xmlelement, loading)
47
48
49#define XMLPortParamLoadOnly(classname, paramname, loadfunction, xmlelement, loading) \
50    XMLPortParamGeneric(classname, paramname, xmlcontainer##loadfunction##0, createFunctor(&classname::loadfunction), 0, xmlelement, loading)
51#define XMLPortParamLoadOnly_Template(classname, paramname, loadtemplate, loadfunction, xmlelement, loading) \
52    XMLPortParamGeneric(classname, paramname, xmlcontainer##loadfunction##0, createFunctor loadtemplate (&classname::loadfunction), 0, xmlelement, loading)
53
54
55#define XMLPortParamGeneric(classname, paramname, containername, loadfunctor, savefunctor, xmlelement, loading) \
56    orxonox::XMLPortClassParamContainer<classname>* containername = (orxonox::XMLPortClassParamContainer<classname>*)(this->getIdentifier()->getXMLPortParamContainer(paramname)); \
57    if (!containername) \
58    { \
59        containername = new orxonox::XMLPortClassParamContainer<classname>(this->getIdentifier()->getName(), std::string(paramname), loadfunctor, savefunctor); \
60        this->getIdentifier()->addXMLPortParamContainer(paramname, containername); \
61    } \
62    containername->port(this, xmlelement, loading)
63
64
65#define XMLPortObject(classname, objectclass, sectionname, loadfunction, savefunction, xmlelement, loading, bApplyLoaderMask, bLoadBefore) \
66    orxonox::XMLPortClassObjectContainer<classname, objectclass>* xmlcontainer##loadfunction##savefunction = (orxonox::XMLPortClassObjectContainer<classname, objectclass>*)(this->getIdentifier()->getXMLPortObjectContainer(sectionname)); \
67    if (!xmlcontainer##loadfunction##savefunction) \
68    { \
69        xmlcontainer##loadfunction##savefunction = new orxonox::XMLPortClassObjectContainer<classname, objectclass>(this->getIdentifier()->getName(), std::string(sectionname), &classname::loadfunction, &classname::savefunction, bApplyLoaderMask, bLoadBefore); \
70        this->getIdentifier()->addXMLPortObjectContainer(sectionname, xmlcontainer##loadfunction##savefunction); \
71    } \
72    xmlcontainer##loadfunction##savefunction->port(this, xmlelement, loading)
73
74
75namespace orxonox
76{
77    // ###############################
78    // ###  XMLPortParamContainer  ###
79    // ###############################
80    class _CoreExport XMLPortParamContainer
81    {
82        public:
83            XMLPortParamContainer();
84
85            inline const std::string& getName() const
86                { return this->paramname_; }
87
88            XMLPortParamContainer& description(const std::string description);
89            const std::string& getDescription();
90
91            XMLPortParamContainer& defaultValues(const MultiTypeMath& param1 = MT_null, const MultiTypeMath& param2 = MT_null, const MultiTypeMath& param3 = MT_null, const MultiTypeMath& param4 = MT_null, const MultiTypeMath& param5 = MT_null)
92            {
93                this->defaultValues_[0] = param1;
94                this->defaultValues_[1] = param2;
95                this->defaultValues_[2] = param3;
96                this->defaultValues_[3] = param4;
97                this->defaultValues_[4] = param5;
98
99                return (*this);
100            }
101
102        protected:
103            std::string classname_;
104            std::string paramname_;
105            MultiTypeMath defaultValues_[5];
106
107        private:
108            LanguageEntryLabel description_;
109            bool bAddedDescription_;
110            bool bAddedDefaultValues_;
111    };
112
113    template <class T>
114    class XMLPortClassParamContainer : public XMLPortParamContainer
115    {
116        public:
117            XMLPortClassParamContainer(const std::string classname, const std::string paramname, FunctorMember<T>* loadfunction, FunctorMember<T>* savefunction)
118            {
119                this->classname_ = classname;
120                this->paramname_ = paramname;
121                this->loadfunction_ = loadfunction;
122                this->savefunction_ = savefunction;
123            }
124
125            XMLPortParamContainer& port(T* object, Element& xmlelement, bool loading)
126            {
127                if (loading)
128                {
129                    try
130                    {
131                        std::string attribute = xmlelement.GetAttribute(this->paramname_);
132                        if (attribute.size() > 0)
133                        {
134                            SubString tokens(attribute, ",", SubString::WhiteSpaces, false, '\\', '"', '(', ')', '\0');
135                            if ((unsigned int)tokens.size() >= (unsigned int)this->loadfunction_->getParamCount())
136                            {
137                                COUT(5) << object->getLoaderIndentation() << "Loading parameter " << this->paramname_ << " in " << this->classname_ << " (objectname " << object->getName() << ") with ";
138                                if (this->loadfunction_->getParamCount() == 1)
139                                {
140                                    COUT(5) << "1 parameter (using whole string):" << std::endl;
141                                    COUT(5) << object->getLoaderIndentation() << "  " << attribute << std::endl;
142                                    (*this->loadfunction_)(object, MultiTypeMath(attribute));
143                                }
144                                else
145                                {
146                                    COUT(5) << tokens.size() << " parameter (using MultiTypeMath)." << std::endl;
147                                    MultiTypeMath param1 = MT_null, param2 = MT_null, param3 = MT_null, param4 = MT_null, param5 = MT_null;
148                                    if (tokens.size() >= 1) param1 = tokens[0];
149                                    if (tokens.size() >= 2) param2 = tokens[1];
150                                    if (tokens.size() >= 3) param3 = tokens[2];
151                                    if (tokens.size() >= 4) param4 = tokens[3];
152                                    if (tokens.size() >= 5) param5 = tokens[4];
153                                    COUT(5) << object->getLoaderIndentation() << "  " << attribute << std::endl;
154                                    COUT(5) << object->getLoaderIndentation() << "  " << param1 << ", " << param2 << ", " << param3 << ", " << param4 << ", " << param5 << std::endl;
155
156                                    (*this->loadfunction_)(object, param1, param2, param3, param4, param5);
157                                }
158                            }
159                            else
160                            {
161                                COUT(2) << object->getLoaderIndentation() << "Warning: Parameter \"" << this->paramname_ << "\" in \"" << this->classname_ << "\" (objectname: " << object->getName() << ") is incomplete and couln't be loaded." << std::endl;
162                            }
163                        }
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->classname_ << "' (objectname: " << object->getName() << ") in " << object->getLevelfile() << ":" << std::endl;
169                        COUT(1) << ex.what() << std::endl;
170                    }
171                }
172                else
173                {
174                    if (this->savefunction_)
175                    {
176//                        xmlelement.SetAttribute(this->paramname_, "...");
177                    }
178                }
179
180                return (*this);
181            }
182
183        private:
184            FunctorMember<T>* loadfunction_;
185            FunctorMember<T>* savefunction_;
186    };
187
188
189    // ################################
190    // ###  XMLPortObjectContainer  ###
191    // ################################
192    class _CoreExport XMLPortObjectContainer
193    {
194        public:
195            XMLPortObjectContainer();
196
197            inline const std::string& getName() const
198                { return this->sectionname_; }
199
200            XMLPortObjectContainer& description(const std::string description);
201            const std::string& getDescription();
202            bool identifierIsIncludedInLoaderMask(const Identifier* identifier);
203
204        protected:
205            std::string classname_;
206            std::string sectionname_;
207            bool bApplyLoaderMask_;
208            bool bLoadBefore_;
209
210        private:
211            LanguageEntryLabel description_;
212            bool bAddedDescription_;
213    };
214
215    template <class T, class O>
216    class XMLPortClassObjectContainer : public XMLPortObjectContainer
217    {
218        public:
219            XMLPortClassObjectContainer(const std::string classname, const std::string sectionname, void (T::*loadfunction)(O*), const O* (T::*savefunction)(unsigned int) const, bool bApplyLoaderMask, bool bLoadBefore)
220            {
221                this->classname_ = classname;
222                this->sectionname_ = sectionname;
223                this->loadfunction_ = loadfunction;
224                this->savefunction_ = savefunction;
225                this->bApplyLoaderMask_ = bApplyLoaderMask;
226                this->bLoadBefore_ = bLoadBefore;
227            }
228
229            XMLPortObjectContainer& port(T* object, Element& xmlelement, bool loading)
230            {
231                if (loading)
232                {
233                    try
234                    {
235                        Element* xmlsubelement;
236                        if (this->sectionname_ != "")
237                            xmlsubelement = xmlelement.FirstChildElement(this->sectionname_, false);
238                        else
239                            xmlsubelement = &xmlelement;
240
241                        if (xmlsubelement)
242                        {
243                            for (ticpp::Iterator<ticpp::Element> child = xmlsubelement->FirstChildElement(false); child != child.end(); child++)
244                            {
245                                Identifier* identifier = ID(child->Value());
246                                if (identifier)
247                                {
248                                    if (identifier->isA(Class(O)))
249                                    {
250                                        if (this->identifierIsIncludedInLoaderMask(identifier))
251                                        {
252                                            COUT(4) << object->getLoaderIndentation() << "fabricating " << child->Value() << "..." << std::endl;
253                                            O* newObject = (O*)identifier->fabricate();
254                                            newObject->setLoaderIndentation(object->getLoaderIndentation() + "  ");
255                                            newObject->setLevel(object->getLevel());
256                                            newObject->setNamespace(object->getNamespace());
257                                            if (this->bLoadBefore_)
258                                                newObject->XMLPort(*child, true);
259                                            COUT(4) << object->getLoaderIndentation() << "assigning " << child->Value() << " (objectname " << newObject->getName() << ") to " << this->classname_ << " (objectname " << object->getName() << ")" << std::endl;
260                                            (*object.*this->loadfunction_)(newObject);
261                                            if (!this->bLoadBefore_)
262                                                newObject->XMLPort(*child, true);
263                                            COUT(5) << object->getLoaderIndentation() << "...fabricated " << child->Value() << " (objectname " << newObject->getName() << ")." << std::endl;
264                                        }
265                                    }
266                                    else
267                                    {
268                                        COUT(2) << object->getLoaderIndentation() << "Warning: '" << child->Value() << "' is not a '" << Class(O)->getName() << "'." << std::endl;
269                                    }
270                                }
271                                else
272                                {
273                                    COUT(2) << object->getLoaderIndentation() << "Warning: '" << child->Value() << "' is not a valid classname." << std::endl;
274                                }
275                            }
276                        }
277                    }
278                    catch(ticpp::Exception& ex)
279                    {
280                        COUT(1) << std::endl;
281                        COUT(1) << "An error occurred in XMLPort.h while loading a '" << Class(O)->getName() << "' in '" << this->sectionname_ << "' of '" << this->classname_ << "' (objectname: " << object->getName() << ") in " << object->getLevelfile() << ":" << std::endl;
282                        COUT(1) << ex.what() << std::endl;
283                    }
284                }
285                else
286                {
287                }
288
289                return (*this);
290            }
291
292        private:
293            void     (T::*loadfunction_)(O*);
294            const O* (T::*savefunction_)(unsigned int) const;
295    };
296}
297
298#endif /* _XMLPort_H__ */
Note: See TracBrowser for help on using the repository browser.