]> git.mxchange.org Git - simgear.git/blob - simgear/hla/HLAObjectClass.cxx
hla: Use a different extrapolation method for HLALocation.
[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 "HLADataTypeVisitor.hxx"
32 #include "HLAFederate.hxx"
33 #include "HLAObjectInstance.hxx"
34
35 namespace simgear {
36
37 HLAObjectClass::InstanceCallback::~InstanceCallback()
38 {
39 }
40
41 void
42 HLAObjectClass::InstanceCallback::discoverInstance(const HLAObjectClass&, HLAObjectInstance& objectInstance, const RTIData& tag)
43 {
44 }
45
46 void
47 HLAObjectClass::InstanceCallback::removeInstance(const HLAObjectClass&, HLAObjectInstance& objectInstance, const RTIData& tag)
48 {
49 }
50
51 void
52 HLAObjectClass::InstanceCallback::registerInstance(const HLAObjectClass&, HLAObjectInstance& objectInstance)
53 {
54 }
55
56 void
57 HLAObjectClass::InstanceCallback::deleteInstance(const HLAObjectClass&, HLAObjectInstance& objectInstance)
58 {
59 }
60
61 HLAObjectClass::RegistrationCallback::~RegistrationCallback()
62 {
63 }
64
65 HLAObjectClass::HLAObjectClass(const std::string& name, HLAFederate* federate) :
66     _federate(federate),
67     _name(name)
68 {
69     if (!federate) {
70         SG_LOG(SG_NETWORK, SG_ALERT, "HLAObjectClass::HLAObjectClass(): "
71                "No parent federate given for object class \"" << getName() << "\"!");
72         return;
73     }
74     federate->_insertObjectClass(this);
75 }
76
77 HLAObjectClass::~HLAObjectClass()
78 {
79     // HLAObjectClass objects only get deleted when the parent federate
80     // dies. So we do not need to deregister there.
81
82     _clearRTIObjectClass();
83 }
84
85 const std::string&
86 HLAObjectClass::getName() const
87 {
88     return _name;
89 }
90
91 const SGWeakPtr<HLAFederate>&
92 HLAObjectClass::getFederate() const
93 {
94     return _federate;
95 }
96
97 unsigned
98 HLAObjectClass::getNumAttributes() const
99 {
100     return _attributeVector.size();
101 }
102
103 unsigned
104 HLAObjectClass::addAttribute(const std::string& name)
105 {
106     unsigned index = _attributeVector.size();
107     _nameIndexMap[name] = index;
108     _attributeVector.push_back(Attribute(name));
109     _resolveAttributeIndex(name, index);
110     return index;
111 }
112
113 unsigned
114 HLAObjectClass::getAttributeIndex(const std::string& name) const
115 {
116     NameIndexMap::const_iterator i = _nameIndexMap.find(name);
117     if (i == _nameIndexMap.end())
118         return ~0u;
119     return i->second;
120 }
121
122 std::string
123 HLAObjectClass::getAttributeName(unsigned index) const
124 {
125     if (_attributeVector.size() <= index)
126         return std::string();
127     return _attributeVector[index]._name;
128 }
129
130 const HLADataType*
131 HLAObjectClass::getAttributeDataType(unsigned index) const
132 {
133     if (_attributeVector.size() <= index)
134         return 0;
135     return _attributeVector[index]._dataType.get();
136 }
137
138 void
139 HLAObjectClass::setAttributeDataType(unsigned index, const HLADataType* dataType)
140 {
141     if (_attributeVector.size() <= index)
142         return;
143     _attributeVector[index]._dataType = dataType;
144 }
145
146 HLAUpdateType
147 HLAObjectClass::getAttributeUpdateType(unsigned index) const
148 {
149     if (_attributeVector.size() <= index)
150         return HLAUndefinedUpdate;
151     return _attributeVector[index]._updateType;
152 }
153
154 void
155 HLAObjectClass::setAttributeUpdateType(unsigned index, HLAUpdateType updateType)
156 {
157     if (_attributeVector.size() <= index)
158         return;
159     _attributeVector[index]._updateType = updateType;
160 }
161
162 HLASubscriptionType
163 HLAObjectClass::getAttributeSubscriptionType(unsigned index) const
164 {
165     if (_attributeVector.size() <= index)
166         return HLAUnsubscribed;
167     return _attributeVector[index]._subscriptionType;
168 }
169
170 void
171 HLAObjectClass::setAttributeSubscriptionType(unsigned index, HLASubscriptionType subscriptionType)
172 {
173     if (_attributeVector.size() <= index)
174         return;
175     _attributeVector[index]._subscriptionType = subscriptionType;
176 }
177
178 HLAPublicationType
179 HLAObjectClass::getAttributePublicationType(unsigned index) const
180 {
181     if (_attributeVector.size() <= index)
182         return HLAUnpublished;
183     return _attributeVector[index]._publicationType;
184 }
185
186 void
187 HLAObjectClass::setAttributePublicationType(unsigned index, HLAPublicationType publicationType)
188 {
189     if (_attributeVector.size() <= index)
190         return;
191     _attributeVector[index]._publicationType = publicationType;
192 }
193
194 bool
195 HLAObjectClass::getDataElementIndex(HLADataElementIndex& dataElementIndex, const std::string& path) const
196 {
197     if (path.empty()) {
198         SG_LOG(SG_NETWORK, SG_ALERT, "HLAObjectClass: failed to parse empty element path!");
199         return false;
200     }
201     std::string::size_type len = std::min(path.find_first_of("[."), path.size());
202     unsigned index = 0;
203     while (index < getNumAttributes()) {
204         if (path.compare(0, len, getAttributeName(index)) == 0)
205             break;
206         ++index;
207     }
208     if (getNumAttributes() <= index) {
209         SG_LOG(SG_NETWORK, SG_ALERT, "HLAObjectClass: faild to parse data element index \"" << path << "\":\n"
210                << "Attribute \"" << path.substr(0, len) << "\" not found in object class \""
211                << getName() << "\"!");
212         return false;
213     }
214     if (!getAttributeDataType(index)) {
215         SG_LOG(SG_NETWORK, SG_ALERT, "HLAObjectClass: faild to parse data element index \"" << path << "\":\n"
216                << "Undefined attribute data type in variant record data type \""
217                << getAttributeName(index) << "\"!");
218         return false;
219     }
220     dataElementIndex.push_back(index);
221     return getAttributeDataType(index)->getDataElementIndex(dataElementIndex, path, len);
222 }
223
224 HLADataElementIndex
225 HLAObjectClass::getDataElementIndex(const std::string& path) const
226 {
227     HLADataElementIndex dataElementIndex;
228     getDataElementIndex(dataElementIndex, path);
229     return dataElementIndex;
230 }
231
232 bool
233 HLAObjectClass::subscribe()
234 {
235     if (!_rtiObjectClass.valid()) {
236         SG_LOG(SG_NETWORK, SG_WARN, "HLAObjectClass::subscribe(): "
237                "No RTIObject class for object class \"" << getName() << "\"!");
238         return false;
239     }
240
241     HLAIndexList indexList;
242     for (unsigned i = 1; i < getNumAttributes(); ++i) {
243         if (_attributeVector[i]._subscriptionType != HLASubscribedActive)
244             continue;
245         indexList.push_back(i);
246     }
247     if (!indexList.empty()) {
248         if (!_rtiObjectClass->subscribe(indexList, true))
249             return false;
250     }
251
252     indexList.clear();
253     for (unsigned i = 1; i < getNumAttributes(); ++i) {
254         if (_attributeVector[i]._subscriptionType != HLASubscribedPassive)
255             continue;
256         indexList.push_back(i);
257     }
258     if (!indexList.empty()) {
259         if (!_rtiObjectClass->subscribe(indexList, false))
260             return false;
261     }
262     return true;
263 }
264
265 bool
266 HLAObjectClass::unsubscribe()
267 {
268     if (!_rtiObjectClass.valid()) {
269         SG_LOG(SG_NETWORK, SG_WARN, "HLAObjectClass::unsubscribe(): "
270                "No RTIObject class for object class \"" << getName() << "\"!");
271         return false;
272     }
273     return _rtiObjectClass->unsubscribe();
274 }
275
276 bool
277 HLAObjectClass::publish()
278 {
279     if (!_rtiObjectClass.valid()) {
280         SG_LOG(SG_NETWORK, SG_WARN, "HLAObjectClass::publish(): "
281                "No RTIObject class for object class \"" << getName() << "\"!");
282         return false;
283     }
284
285     HLAIndexList indexList;
286     for (unsigned i = 1; i < getNumAttributes(); ++i) {
287         if (_attributeVector[i]._publicationType == HLAUnpublished)
288             continue;
289         indexList.push_back(i);
290     }
291     if (indexList.empty())
292         return true;
293     if (!_rtiObjectClass->publish(indexList))
294         return false;
295     return true;
296 }
297
298 bool
299 HLAObjectClass::unpublish()
300 {
301     if (!_rtiObjectClass.valid()) {
302         SG_LOG(SG_NETWORK, SG_WARN, "HLAObjectClass::unpublish(): "
303                "No RTIObject class for object class \"" << getName() << "\"!");
304         return false;
305     }
306     return _rtiObjectClass->unpublish();
307 }
308
309 void
310 HLAObjectClass::discoverInstance(HLAObjectInstance& objectInstance, const RTIData& tag)
311 {
312     if (_instanceCallback.valid())
313         _instanceCallback->discoverInstance(*this, objectInstance, tag);
314 }
315
316 void
317 HLAObjectClass::removeInstance(HLAObjectInstance& objectInstance, const RTIData& tag)
318 {
319     if (_instanceCallback.valid())
320         _instanceCallback->removeInstance(*this, objectInstance, tag);
321 }
322
323 void
324 HLAObjectClass::registerInstance(HLAObjectInstance& objectInstance)
325 {
326     if (_instanceCallback.valid())
327         _instanceCallback->registerInstance(*this, objectInstance);
328 }
329
330 void
331 HLAObjectClass::deleteInstance(HLAObjectInstance& objectInstance)
332 {
333     if (_instanceCallback.valid())
334         _instanceCallback->deleteInstance(*this, objectInstance);
335 }
336
337 void
338 HLAObjectClass::startRegistration() const
339 {
340 }
341
342 void
343 HLAObjectClass::stopRegistration() const
344 {
345 }
346
347 HLAObjectInstance*
348 HLAObjectClass::createObjectInstance(const std::string& name)
349 {
350     SGSharedPtr<HLAFederate> federate = _federate.lock();
351     if (!federate.valid())
352         return 0;
353     return federate->createObjectInstance(this, name);
354 }
355
356 void
357 HLAObjectClass::createAttributeDataElements(HLAObjectInstance& objectInstance)
358 {
359     unsigned numAttributes = getNumAttributes();
360     for (unsigned i = 0; i < numAttributes; ++i)
361         objectInstance.createAndSetAttributeDataElement(i);
362 }
363
364 HLADataElement*
365 HLAObjectClass::createAttributeDataElement(HLAObjectInstance& objectInstance, unsigned index)
366 {
367     // FIXME here we want to have a vector of factories and if this fails do the following
368     const HLADataType* dataType = getAttributeDataType(index);
369     if (!dataType)
370         return 0;
371     HLADataElementFactoryVisitor dataElementFactoryVisitor;
372     dataType->accept(dataElementFactoryVisitor);
373     return dataElementFactoryVisitor.getDataElement();
374 }
375
376 void
377 HLAObjectClass::_setRTIObjectClass(RTIObjectClass* objectClass)
378 {
379     if (_rtiObjectClass) {
380         SG_LOG(SG_NETWORK, SG_ALERT, "HLAObjectClass: Setting RTIObjectClass twice for object class \"" << getName() << "\"!");
381         return;
382     }
383     _rtiObjectClass = objectClass;
384     if (_rtiObjectClass->_objectClass != this) {
385         SG_LOG(SG_NETWORK, SG_ALERT, "HLAObjectClass: backward reference does not match!");
386         return;
387     }
388     for (unsigned i = 0; i < _attributeVector.size(); ++i)
389         _resolveAttributeIndex(_attributeVector[i]._name, i);
390 }
391
392 void
393 HLAObjectClass::_resolveAttributeIndex(const std::string& name, unsigned index)
394 {
395     if (!_rtiObjectClass)
396         return;
397     if (!_rtiObjectClass->resolveAttributeIndex(name, index))
398         SG_LOG(SG_NETWORK, SG_ALERT, "HLAObjectClass: Could not resolve attribute \""
399                << name << "\" for object class \"" << getName() << "\"!");
400 }
401
402 void
403 HLAObjectClass::_clearRTIObjectClass()
404 {
405     if (!_rtiObjectClass.valid())
406         return;
407     _rtiObjectClass->_objectClass = 0;
408     _rtiObjectClass = 0;
409 }
410
411 void
412 HLAObjectClass::_discoverInstance(RTIObjectInstance* rtiObjectInstance, const RTIData& tag)
413 {
414     SGSharedPtr<HLAFederate> federate = _federate.lock();
415     if (!federate.valid()) {
416         SG_LOG(SG_NETWORK, SG_ALERT, "RTI: could not find parent federate while discovering object instance");
417         return;
418     }
419
420     SGSharedPtr<HLAObjectInstance> objectInstance = createObjectInstance(rtiObjectInstance->getName());
421     if (!objectInstance.valid()) {
422         SG_LOG(SG_NETWORK, SG_INFO, "RTI: could not create new object instance for discovered \""
423                << rtiObjectInstance->getName() << "\" object");
424         return;
425     }
426     SG_LOG(SG_NETWORK, SG_INFO, "RTI: create new object instance for discovered \""
427            << rtiObjectInstance->getName() << "\" object");
428     objectInstance->_setRTIObjectInstance(rtiObjectInstance);
429     if (!federate->_insertObjectInstance(objectInstance)) {
430         SG_LOG(SG_NETWORK, SG_ALERT, "RTI: could not insert new object instance for discovered \""
431                << rtiObjectInstance->getName() << "\" object");
432         return;
433     }
434     objectInstance->discoverInstance(tag);
435     objectInstance->createAttributeDataElements();
436 }
437
438 void
439 HLAObjectClass::_removeInstance(HLAObjectInstance& objectInstance, const RTIData& tag)
440 {
441     SGSharedPtr<HLAFederate> federate = _federate.lock();
442     if (!federate.valid()) {
443         SG_LOG(SG_NETWORK, SG_ALERT, "RTI: could not find parent federate while removing object instance");
444         return;
445     }
446     SG_LOG(SG_NETWORK, SG_INFO, "RTI: remove object instance \"" << objectInstance.getName() << "\"");
447     objectInstance.removeInstance(tag);
448     federate->_eraseObjectInstance(objectInstance.getName());
449 }
450
451 void
452 HLAObjectClass::_registerInstance(HLAObjectInstance* objectInstance)
453 {
454     SGSharedPtr<HLAFederate> federate = _federate.lock();
455     if (!federate.valid()) {
456         SG_LOG(SG_NETWORK, SG_ALERT, "RTI: could not find parent federate while registering object instance");
457         return;
458     }
459     if (!objectInstance)
460         return;
461     // We can only register object instances with a valid name at the rti.
462     // So, we cannot do that at HLAObjectInstance creation time.
463     if (!federate->_insertObjectInstance(objectInstance)) {
464         SG_LOG(SG_NETWORK, SG_ALERT, "RTI: could not insert new object instance \""
465                << objectInstance->getName() << "\" object");
466         return;
467     }
468     registerInstance(*objectInstance);
469     objectInstance->createAttributeDataElements();
470 }
471
472 void
473 HLAObjectClass::_deleteInstance(HLAObjectInstance& objectInstance)
474 {
475     SGSharedPtr<HLAFederate> federate = _federate.lock();
476     if (!federate.valid()) {
477         SG_LOG(SG_NETWORK, SG_ALERT, "RTI: could not find parent federate while deleting object instance");
478         return;
479     }
480     deleteInstance(objectInstance);
481     federate->_eraseObjectInstance(objectInstance.getName());
482 }
483
484 void
485 HLAObjectClass::_startRegistration()
486 {
487     if (_registrationCallback.valid())
488         _registrationCallback->startRegistration(*this);
489     else
490         startRegistration();
491 }
492
493 void
494 HLAObjectClass::_stopRegistration()
495 {
496     if (_registrationCallback.valid())
497         _registrationCallback->stopRegistration(*this);
498     else
499         stopRegistration();
500 }
501
502 } // namespace simgear