]> git.mxchange.org Git - simgear.git/blob - simgear/hla/HLAObjectClass.cxx
Merge branch 'timoore/optimizations' into next
[simgear.git] / simgear / hla / HLAObjectClass.cxx
1 // Copyright (C) 2009 - 2012  Mathias Froehlich - Mathias.Froehlich@web.de
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Library General Public
5 // License as published by the Free Software Foundation; either
6 // version 2 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Library General Public License for more details.
12 //
13 // You should have received a copy of the GNU General Public License
14 // along with this program; if not, write to the Free Software
15 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
16 //
17
18 #ifdef HAVE_CONFIG_H
19 #  include <simgear_config.h>
20 #endif
21
22 #include <simgear/compiler.h>
23
24 #include "HLAObjectClass.hxx"
25
26 #include "simgear/debug/logstream.hxx"
27 #include "RTIFederate.hxx"
28 #include "RTIObjectClass.hxx"
29 #include "RTIObjectInstance.hxx"
30 #include "HLADataType.hxx"
31 #include "HLAFederate.hxx"
32 #include "HLAObjectInstance.hxx"
33
34 namespace simgear {
35
36 HLAObjectClass::InstanceCallback::~InstanceCallback()
37 {
38 }
39
40 void
41 HLAObjectClass::InstanceCallback::discoverInstance(const HLAObjectClass&, HLAObjectInstance& objectInstance, const RTIData& tag)
42 {
43 }
44
45 void
46 HLAObjectClass::InstanceCallback::removeInstance(const HLAObjectClass&, HLAObjectInstance& objectInstance, const RTIData& tag)
47 {
48 }
49
50 void
51 HLAObjectClass::InstanceCallback::registerInstance(const HLAObjectClass&, HLAObjectInstance& objectInstance)
52 {
53 }
54
55 void
56 HLAObjectClass::InstanceCallback::deleteInstance(const HLAObjectClass&, HLAObjectInstance& objectInstance)
57 {
58 }
59
60 HLAObjectClass::RegistrationCallback::~RegistrationCallback()
61 {
62 }
63
64 HLAObjectClass::HLAObjectClass(const std::string& name, HLAFederate* federate) :
65     _federate(federate),
66     _name(name)
67 {
68     if (!federate) {
69         SG_LOG(SG_NETWORK, SG_ALERT, "HLAObjectClass::HLAObjectClass(): "
70                "No parent federate given for object class \"" << getName() << "\"!");
71         return;
72     }
73     federate->_insertObjectClass(this);
74 }
75
76 HLAObjectClass::~HLAObjectClass()
77 {
78     // HLAObjectClass objects only get deleted when the parent federate
79     // dies. So we do not need to deregister there.
80
81     _clearRTIObjectClass();
82 }
83
84 const std::string&
85 HLAObjectClass::getName() const
86 {
87     return _name;
88 }
89
90 const SGWeakPtr<HLAFederate>&
91 HLAObjectClass::getFederate() const
92 {
93     return _federate;
94 }
95
96 unsigned
97 HLAObjectClass::getNumAttributes() const
98 {
99     return _attributeVector.size();
100 }
101
102 unsigned
103 HLAObjectClass::addAttribute(const std::string& name)
104 {
105     unsigned index = _attributeVector.size();
106     _nameIndexMap[name] = index;
107     _attributeVector.push_back(Attribute(name));
108     _resolveAttributeIndex(name, index);
109     return index;
110 }
111
112 unsigned
113 HLAObjectClass::getAttributeIndex(const std::string& name) const
114 {
115     NameIndexMap::const_iterator i = _nameIndexMap.find(name);
116     if (i == _nameIndexMap.end())
117         return ~0u;
118     return i->second;
119 }
120
121 std::string
122 HLAObjectClass::getAttributeName(unsigned index) const
123 {
124     if (_attributeVector.size() <= index)
125         return std::string();
126     return _attributeVector[index]._name;
127 }
128
129 const HLADataType*
130 HLAObjectClass::getAttributeDataType(unsigned index) const
131 {
132     if (_attributeVector.size() <= index)
133         return 0;
134     return _attributeVector[index]._dataType.get();
135 }
136
137 void
138 HLAObjectClass::setAttributeDataType(unsigned index, const HLADataType* dataType)
139 {
140     if (_attributeVector.size() <= index)
141         return;
142     _attributeVector[index]._dataType = dataType;
143 }
144
145 HLAUpdateType
146 HLAObjectClass::getAttributeUpdateType(unsigned index) const
147 {
148     if (_attributeVector.size() <= index)
149         return HLAUndefinedUpdate;
150     return _attributeVector[index]._updateType;
151 }
152
153 void
154 HLAObjectClass::setAttributeUpdateType(unsigned index, HLAUpdateType updateType)
155 {
156     if (_attributeVector.size() <= index)
157         return;
158     _attributeVector[index]._updateType = updateType;
159 }
160
161 HLASubscriptionType
162 HLAObjectClass::getAttributeSubscriptionType(unsigned index) const
163 {
164     if (_attributeVector.size() <= index)
165         return HLAUnsubscribed;
166     return _attributeVector[index]._subscriptionType;
167 }
168
169 void
170 HLAObjectClass::setAttributeSubscriptionType(unsigned index, HLASubscriptionType subscriptionType)
171 {
172     if (_attributeVector.size() <= index)
173         return;
174     _attributeVector[index]._subscriptionType = subscriptionType;
175 }
176
177 HLAPublicationType
178 HLAObjectClass::getAttributePublicationType(unsigned index) const
179 {
180     if (_attributeVector.size() <= index)
181         return HLAUnpublished;
182     return _attributeVector[index]._publicationType;
183 }
184
185 void
186 HLAObjectClass::setAttributePublicationType(unsigned index, HLAPublicationType publicationType)
187 {
188     if (_attributeVector.size() <= index)
189         return;
190     _attributeVector[index]._publicationType = publicationType;
191 }
192
193 HLADataElement::IndexPathPair
194 HLAObjectClass::getIndexPathPair(const HLADataElement::StringPathPair& stringPathPair) const
195 {
196     unsigned index = getAttributeIndex(stringPathPair.first);
197     if (getNumAttributes() <= index) {
198         SG_LOG(SG_NETWORK, SG_ALERT, "HLAObjectClass::getIndexPathPair(\""
199                << HLADataElement::toString(stringPathPair)
200                << "\"): Could not resolve attribute \"" << stringPathPair.first
201                << "\" for object class \"" << getName() << "\"!");
202     }
203     return HLADataElement::IndexPathPair(index, stringPathPair.second);
204 }
205
206 HLADataElement::IndexPathPair
207 HLAObjectClass::getIndexPathPair(const std::string& path) const
208 {
209     return getIndexPathPair(HLADataElement::toStringPathPair(path));
210 }
211
212 bool
213 HLAObjectClass::subscribe()
214 {
215     if (!_rtiObjectClass.valid()) {
216         SG_LOG(SG_NETWORK, SG_WARN, "HLAObjectClass::subscribe(): "
217                "No RTIObject class for object class \"" << getName() << "\"!");
218         return false;
219     }
220
221     HLAIndexList indexList;
222     for (unsigned i = 1; i < getNumAttributes(); ++i) {
223         if (_attributeVector[i]._subscriptionType != HLASubscribedActive)
224             continue;
225         indexList.push_back(i);
226     }
227     if (!indexList.empty()) {
228         if (!_rtiObjectClass->subscribe(indexList, true))
229             return false;
230     }
231
232     indexList.clear();
233     for (unsigned i = 1; i < getNumAttributes(); ++i) {
234         if (_attributeVector[i]._subscriptionType != HLASubscribedPassive)
235             continue;
236         indexList.push_back(i);
237     }
238     if (!indexList.empty()) {
239         if (!_rtiObjectClass->subscribe(indexList, false))
240             return false;
241     }
242     return true;
243 }
244
245 bool
246 HLAObjectClass::unsubscribe()
247 {
248     if (!_rtiObjectClass.valid()) {
249         SG_LOG(SG_NETWORK, SG_WARN, "HLAObjectClass::unsubscribe(): "
250                "No RTIObject class for object class \"" << getName() << "\"!");
251         return false;
252     }
253     return _rtiObjectClass->unsubscribe();
254 }
255
256 bool
257 HLAObjectClass::publish()
258 {
259     if (!_rtiObjectClass.valid()) {
260         SG_LOG(SG_NETWORK, SG_WARN, "HLAObjectClass::publish(): "
261                "No RTIObject class for object class \"" << getName() << "\"!");
262         return false;
263     }
264
265     HLAIndexList indexList;
266     for (unsigned i = 1; i < getNumAttributes(); ++i) {
267         if (_attributeVector[i]._publicationType == HLAUnpublished)
268             continue;
269         indexList.push_back(i);
270     }
271     if (indexList.empty())
272         return true;
273     if (!_rtiObjectClass->publish(indexList))
274         return false;
275     return true;
276 }
277
278 bool
279 HLAObjectClass::unpublish()
280 {
281     if (!_rtiObjectClass.valid()) {
282         SG_LOG(SG_NETWORK, SG_WARN, "HLAObjectClass::unpublish(): "
283                "No RTIObject class for object class \"" << getName() << "\"!");
284         return false;
285     }
286     return _rtiObjectClass->unpublish();
287 }
288
289 void
290 HLAObjectClass::startRegistration() const
291 {
292 }
293
294 void
295 HLAObjectClass::stopRegistration() const
296 {
297 }
298
299 HLAObjectInstance*
300 HLAObjectClass::createObjectInstance(const std::string& name)
301 {
302     SGSharedPtr<HLAFederate> federate = _federate.lock();
303     if (!federate.valid())
304         return 0;
305     return federate->createObjectInstance(this, name);
306 }
307
308 void
309 HLAObjectClass::_setRTIObjectClass(RTIObjectClass* objectClass)
310 {
311     if (_rtiObjectClass) {
312         SG_LOG(SG_NETWORK, SG_ALERT, "HLAObjectClass: Setting RTIObjectClass twice for object class \"" << getName() << "\"!");
313         return;
314     }
315     _rtiObjectClass = objectClass;
316     if (_rtiObjectClass->_objectClass != this) {
317         SG_LOG(SG_NETWORK, SG_ALERT, "HLAObjectClass: backward reference does not match!");
318         return;
319     }
320     for (unsigned i = 0; i < _attributeVector.size(); ++i)
321         _resolveAttributeIndex(_attributeVector[i]._name, i);
322 }
323
324 void
325 HLAObjectClass::_resolveAttributeIndex(const std::string& name, unsigned index)
326 {
327     if (!_rtiObjectClass)
328         return;
329     if (!_rtiObjectClass->resolveAttributeIndex(name, index))
330         SG_LOG(SG_NETWORK, SG_ALERT, "HLAObjectClass: Could not resolve attribute \""
331                << name << "\" for object class \"" << getName() << "\"!");
332 }
333
334 void
335 HLAObjectClass::_clearRTIObjectClass()
336 {
337     if (!_rtiObjectClass.valid())
338         return;
339     _rtiObjectClass->_objectClass = 0;
340     _rtiObjectClass = 0;
341 }
342
343 void
344 HLAObjectClass::_discoverInstance(RTIObjectInstance* rtiObjectInstance, const RTIData& tag)
345 {
346     SGSharedPtr<HLAFederate> federate = _federate.lock();
347     if (!federate.valid()) {
348         SG_LOG(SG_NETWORK, SG_ALERT, "RTI: could not find parent federate while discovering object instance");
349         return;
350     }
351
352     SGSharedPtr<HLAObjectInstance> objectInstance = createObjectInstance(rtiObjectInstance->getName());
353     if (!objectInstance.valid()) {
354         SG_LOG(SG_NETWORK, SG_INFO, "RTI: could not create new object instance for discovered \""
355                << rtiObjectInstance->getName() << "\" object");
356         return;
357     }
358     SG_LOG(SG_NETWORK, SG_INFO, "RTI: create new object instance for discovered \""
359            << rtiObjectInstance->getName() << "\" object");
360     objectInstance->_setRTIObjectInstance(rtiObjectInstance);
361     if (!federate->_insertObjectInstance(objectInstance)) {
362         SG_LOG(SG_NETWORK, SG_ALERT, "RTI: could not insert new object instance for discovered \""
363                << rtiObjectInstance->getName() << "\" object");
364         return;
365     }
366     if (_instanceCallback.valid())
367         _instanceCallback->discoverInstance(*this, *objectInstance, tag);
368 }
369
370 void
371 HLAObjectClass::_removeInstance(HLAObjectInstance& objectInstance, const RTIData& tag)
372 {
373     SGSharedPtr<HLAFederate> federate = _federate.lock();
374     if (!federate.valid()) {
375         SG_LOG(SG_NETWORK, SG_ALERT, "RTI: could not find parent federate while removing object instance");
376         return;
377     }
378     SG_LOG(SG_NETWORK, SG_INFO, "RTI: remove object instance \"" << objectInstance.getName() << "\"");
379     if (_instanceCallback.valid())
380         _instanceCallback->removeInstance(*this, objectInstance, tag);
381     federate->_eraseObjectInstance(objectInstance.getName());
382 }
383
384 void
385 HLAObjectClass::_registerInstance(HLAObjectInstance* objectInstance)
386 {
387     SGSharedPtr<HLAFederate> federate = _federate.lock();
388     if (!federate.valid()) {
389         SG_LOG(SG_NETWORK, SG_ALERT, "RTI: could not find parent federate while registering object instance");
390         return;
391     }
392     if (!objectInstance)
393         return;
394     // We can only register object instances with a valid name at the rti.
395     // So, we cannot do that at HLAObjectInstance creation time.
396     if (!federate->_insertObjectInstance(objectInstance)) {
397         SG_LOG(SG_NETWORK, SG_ALERT, "RTI: could not insert new object instance \""
398                << objectInstance->getName() << "\" object");
399         return;
400     }
401     if (_instanceCallback.valid())
402         _instanceCallback->registerInstance(*this, *objectInstance);
403 }
404
405 void
406 HLAObjectClass::_deleteInstance(HLAObjectInstance& objectInstance)
407 {
408     SGSharedPtr<HLAFederate> federate = _federate.lock();
409     if (!federate.valid()) {
410         SG_LOG(SG_NETWORK, SG_ALERT, "RTI: could not find parent federate while deleting object instance");
411         return;
412     }
413     if (_instanceCallback.valid())
414         _instanceCallback->deleteInstance(*this, objectInstance);
415     federate->_eraseObjectInstance(objectInstance.getName());
416 }
417
418 void
419 HLAObjectClass::_startRegistration()
420 {
421     if (_registrationCallback.valid())
422         _registrationCallback->startRegistration(*this);
423     else
424         startRegistration();
425 }
426
427 void
428 HLAObjectClass::_stopRegistration()
429 {
430     if (_registrationCallback.valid())
431         _registrationCallback->stopRegistration(*this);
432     else
433         stopRegistration();
434 }
435
436 } // namespace simgear