1 /*---------------------------------------------------------------------------*\
5 * Copyright (C) 2007 by the OpenSG Forum *
9 * contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de *
11 \*---------------------------------------------------------------------------*/
12 /*---------------------------------------------------------------------------*\
15 * This library is free software; you can redistribute it and/or modify it *
16 * under the terms of the GNU Library General Public License as published *
17 * by the Free Software Foundation, version 2. *
19 * This library is distributed in the hope that it will be useful, but *
20 * WITHOUT ANY WARRANTY; without even the implied warranty of *
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
22 * Library General Public License for more details. *
24 * You should have received a copy of the GNU Library General Public *
25 * License along with this library; if not, write to the Free Software *
26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
28 \*---------------------------------------------------------------------------*/
29 /*---------------------------------------------------------------------------*\
37 \*---------------------------------------------------------------------------*/
39 #include "OSGOSBRootElement.h"
41 #include "OSGOSBElementFactory.h"
42 #include "OSGContainerPtrFuncs.h"
44 #include "OSGAttachmentContainer.h"
45 #include "OSGAttachment.h"
46 #include "OSGFieldContainerSFields.h"
50 /*-------------------------------------------------------------------------*/
52 /*-------------------------------------------------------------------------*/
54 /*! \class OSG::OSBRootElement
55 The root element is different from the other elements for it is not
56 responsible for loading a certain type of FieldContainer but instead holds
57 the shared state of the OSB IO subsystem. All elements (including the
58 root element itself) have a pointer to it and can access the shared state
62 /*-------------------------------------------------------------------------*/
65 OSBElementRegistrationHelper
<OSBRootElement
>
66 OSBRootElement::_regHelper
=
67 OSBElementRegistrationHelper
<OSBRootElement
>("RootElement");
69 /*-------------------------------------------------------------------------*/
74 OSBRootElement::OSBRootElement(OSBRootElement
* /* root */)
75 : Inherited(this, Inherited::OSGOSBHeaderVersion200
)
80 /*-------------------------------------------------------------------------*/
85 OSBRootElement::~OSBRootElement(void)
90 /*-------------------------------------------------------------------------*/
93 /*! Initializes this root element for a read operation from \a inStream.
94 This must be called before OSBRootElement::read(const std::string&).
96 \param[in] inStream Stream to read data from.
99 OSBRootElement::initialiseRead(std::istream
&inStream
)
101 _readHandler
= new BinaryReadHandler(inStream
);
105 _readPtrFields
.clear();
108 /*! Performs clean up tasks after a read operation. This must be called after
109 OSBRootElement::postRead(void).
112 OSBRootElement::terminateRead(void)
114 ElementListIt eI
= editElementList().begin();
115 ElementListIt eE
= editElementList().end ();
117 for(; eI
!= eE
; ++eI
)
119 OSBElementFactory::the()->release(*eI
);
124 _readPtrFields
.clear();
130 /*! Reads from the stream set by a preceding call to initialiseRead. Since the
131 root element is the first one created it reads the file header and
132 creates the elements to read the data following the header.
134 \param[in] typeName The argument is ignored.
137 OSBRootElement::read(const std::string
&/*typeName*/)
139 OSG_OSB_LOG(("OSBRootElement::read\n"));
141 BinaryReadHandler
*rh
= getReadHandler();
142 std::string headerMarker
;
144 rh
->getValue(headerMarker
);
146 if(headerMarker
== OSGOSB_HEADER_ID_1
)
148 OSG_OSB_LOG(("OSBRootElement::read: Header version: [%u]\n",
149 OSGOSBHeaderVersion100
));
150 setHeaderVersion(OSGOSBHeaderVersion100
);
152 else if(headerMarker
== OSGOSB_HEADER_ID_2
)
154 OSG_OSB_LOG(("OSBRootElement::read: Header version: [%u]\n",
155 OSGOSBHeaderVersion200
));
156 setHeaderVersion(OSGOSBHeaderVersion200
);
158 // else if(headerMarker == OSGOSB_HEADER_ID_201)
160 // OSG_OSB_LOG(("OSBRootElement::read: Header version: [%u]\n",
161 // OSGOSBHeaderVersion201));
162 // setHeaderVersion(OSGOSBHeaderVersion201);
166 FWARNING(("OSBRootElement::read: Unrecognized file header, could not "
171 std::string headerName
;
172 rh
->getValue(headerName
);
173 std::string headerOptions
;
174 rh
->getValue(headerOptions
);
176 rh
->getValue(fileSize
);
178 OSG_OSB_LOG(("OSBRootElement::read: headerName: [%s]\n",
179 headerName
.c_str()));
180 OSG_OSB_LOG(("OSBRootElement::read: headerOptions: [%s]\n",
181 headerOptions
.c_str()));
182 OSG_OSB_LOG(("OSBRootElement::read: fileSize: [%" PRISize
"]\n",
185 std::string fcTypeName
;
186 UInt32 fcIdFile
; // id used in the file
187 UInt32 fcIdSystem
; // id used in the system
188 OSBElementBase
*elem
;
192 if(!readFieldContainerHeader(fcTypeName
, fcIdFile
))
195 OSG_OSB_LOG(("OSBRootElement::read: fcTypeName [%s] fcIdFile: [%u]\n",
196 fcTypeName
.c_str(), fcIdFile
));
198 elem
= OSBElementFactory::the()->acquire(fcTypeName
, this);
199 elem
->setFCIdFile(fcIdFile
);
200 elem
->read (fcTypeName
);
202 if(elem
->getContainer() != NULL
)
204 fcIdSystem
= elem
->getContainer()->getId();
206 OSG_OSB_LOG(("OSBRootElement::read: fcIdFile: [%u] fcIdSystem: [%u]\n",
207 fcIdFile
, fcIdSystem
));
210 FieldContainerIdMap::value_type(fcIdFile
, fcIdSystem
));
212 if(getContainer() == NULL
)
214 setContainer(elem
->getContainer());
217 editElementList().push_back(elem
);
218 editIdElemMap ().insert (std::make_pair(fcIdFile
, elem
));
223 /*! Performs post processing for all elements created during the previous
225 Specifically all these elements have their postRead function called and
226 afterwards pointer field remapping is performed. This process fills all
227 fields that hold pointers to FieldContainers with the correct values.
230 OSBRootElement::postRead(void)
232 OSG_OSB_LOG(("OSBRootElement::postRead\n"));
234 ElementListConstIt elemIt
= getElementList().begin();
235 ElementListConstIt elemEnd
= getElementList().end ();
237 for(; elemIt
!= elemEnd
; ++elemIt
)
239 (*elemIt
)->postRead();
244 PtrFieldListConstIt ptrFieldIt
= getPtrFieldList().begin();
245 PtrFieldListConstIt ptrFieldEnd
= getPtrFieldList().end ();
247 for(; ptrFieldIt
!= ptrFieldEnd
; ++ptrFieldIt
)
249 mapPtrField(*ptrFieldIt
);
255 void OSBRootElement::postMap(void)
257 OSG_OSB_LOG(("OSBRootElement::postMap\n"));
259 ElementListConstIt elemIt
= getElementList().begin();
260 ElementListConstIt elemEnd
= getElementList().end ();
262 for(; elemIt
!= elemEnd
; ++elemIt
)
264 (*elemIt
)->postMap();
268 /*-------------------------------------------------------------------------*/
271 /*! Initializes this root element for a write operation to \a outStream.
272 This must be called before
273 OSBRootElement::preWrite(const FieldContainerPtr&).
275 \param[in] outStream Stream to write data to.
278 OSBRootElement::initialiseWrite(std::ostream
&outStream
)
280 _writeHandler
= new BinaryWriteHandler(outStream
);
282 _writeFCList
.clear();
283 _writeIdSet
.clear();
286 /*! Performs clean up tasks after a write operation. This must be called after
287 OSBRootElement::write(void).
290 OSBRootElement::terminateWrite(void)
292 ElementListIt eI
= editElementList().begin();
293 ElementListIt eE
= editElementList().end ();
295 for(; eI
!= eE
; ++eI
)
297 OSBElementFactory::the()->release(*eI
);
301 _writeFCList
.clear();
302 _writeIdSet
.clear();
304 _writeHandler
->flush();
306 delete _writeHandler
;
310 /*! Collects all containers that are reachable from \a fc and schedules them
311 for writing. For each container an approriate element is created and
312 its preWrite method is called, thus recursively discovering all reachable
315 \param[in] fc FieldContainer that is inspected for reachable containers.
318 OSBRootElement::preWrite(FieldContainer
* const fc
)
320 OSG_OSB_LOG(("OSBRootElement::preWrite\n"));
325 const std::string
&typeName
= fc
->getType().getName();
326 OSBElementBase
*elem
= OSBElementFactory::the()->acquire(
329 editElementList().push_back(elem
);
330 elem
->setContainer(fc
);
331 elem
->setFCIdFile (fc
->getId());
332 elem
->preWrite (fc
);
335 /*! Writes the containers collected with the previous call to preWrite to the
336 stream set by initialiseWrite.
337 First the file header is written, then for each element created during
338 preWrite the write function is called.
341 OSBRootElement::write(void)
343 OSG_OSB_LOG(("OSBRootElement::write\n"));
345 BinaryWriteHandler
*wh
= getWriteHandler();
347 wh
->putValue(OSGOSB_HEADER_ID_2
); // version
348 wh
->putValue(std::string("") ); // name
349 wh
->putValue(std::string("") ); // options
350 wh
->putValue(static_cast<UInt64
>(0)); // size
352 ElementListConstIt elemIt
= getElementList().begin();
353 ElementListConstIt elemEnd
= getElementList().end ();
355 for(; elemIt
!= elemEnd
; ++elemIt
)
357 writeFieldContainerHeader((*elemIt
)->getContainer());
362 /*-------------------------------------------------------------------------*/
365 /*! Fills the "pointer field" described by \a ptrField with the correct
368 \param[in] ptrField Field to fill.
371 OSBRootElement::mapPtrField(const PtrFieldInfo
&ptrField
)
373 OSG_OSB_LOG(("OSBRootElement::mapPtrField\n"));
375 PtrFieldInfo::PtrIdStoreConstIt idIt
= ptrField
.beginIdStore();
376 PtrFieldInfo::PtrIdStoreConstIt idEnd
= ptrField
.endIdStore ();
378 PtrFieldInfo::BindingStoreConstIt bindingIt
= ptrField
.beginBindingStore();
379 PtrFieldInfo::BindingStoreConstIt bindingEnd
= ptrField
.endBindingStore ();
381 const FieldContainerIdMap
&idMap
= getIdMap();
382 FieldContainerIdMapConstIt idMapIt
;
383 FieldContainerIdMapConstIt idMapEnd
= idMap
.end();
385 if(bindingIt
!= bindingEnd
)
387 if(ptrField
.getHandledField() == true)
389 FieldContainer
*fieldCon
= ptrField
.getContainer();
390 UInt32 fieldId
= ptrField
.getFieldId();
392 EditFieldHandlePtr fHandle
= fieldCon
->editField(fieldId
);
394 EditMapFieldHandlePtr sfMapField
=
395 boost::dynamic_pointer_cast
<EditMapFieldHandle
>(fHandle
);
397 if(sfMapField
== NULL
|| sfMapField
->isValid() == false)
400 sfMapField
->fillFrom(ptrField
.getBindingStore(),
401 ptrField
.getIdStore (),
406 Attachment
*att
= NULL
;
407 AttachmentContainer
*attCon
=
408 dynamic_cast<AttachmentContainer
*>(ptrField
.getContainer());
410 for(; (idIt
!= idEnd
) && (bindingIt
!= bindingEnd
); ++idIt
,
415 idMapIt
= idMap
.find(*idIt
);
417 if(idMapIt
!= idMapEnd
)
419 att
= dynamic_cast<Attachment
*>(
420 FieldContainerFactory::the()->getContainer(
425 FWARNING(("OSBRootElement::mapPtrField: could not find "
426 "FieldContainer with id [%u]\n", *idIt
));
437 OSG_OSB_LOG(("OSBRootElement::mapPtrField: adding "
438 "attchment [%u] [%u]\n",
439 att
->getType().getGroupId(), *bindingIt
));
442 attCon
->addAttachment(att
, *bindingIt
);
448 FieldContainer
*fc
= NULL
;
449 FieldContainer
*fieldCon
= ptrField
.getContainer();
450 UInt32 fieldId
= ptrField
.getFieldId();
452 EditFieldHandlePtr fHandle
= fieldCon
->editField(fieldId
);
454 FieldContainerPtrSFieldBase::EditHandlePtr pSFHandle
=
455 boost::dynamic_pointer_cast
<
456 FieldContainerPtrSFieldBase::EditHandle
>(fHandle
);
458 FieldContainerPtrMFieldBase::EditHandlePtr pMFHandle
=
459 boost::dynamic_pointer_cast
<
460 FieldContainerPtrMFieldBase::EditHandle
>(fHandle
);
462 for(; idIt
!= idEnd
; ++idIt
)
466 idMapIt
= idMap
.find(*idIt
);
468 if(idMapIt
!= idMapEnd
)
470 fc
= FieldContainerFactory::the()->getContainer(
475 FWARNING(("OSBRootElement::mapPtrField: could not find "
476 "FieldContainer with (file) id [%u]\n", *idIt
));
485 if(pSFHandle
!= NULL
&& pSFHandle
->isValid())
489 else if(pMFHandle
!= NULL
&& pMFHandle
->isValid())
495 FWARNING(("OSBRootElement::mapPtrField: FieldHandles invalid, "
496 "can not set pointer - target fc [%u][%s] "
497 "fieldId [%u][%s] file id [%u] system id [%u]\n",
498 (fc
!= NULL
? fc
->getId() : 0),
499 (fc
!= NULL
? fc
->getType().getCName() : ""),
502 fc
->getType().getFieldDesc(fieldId
)->getCName() : ""),
504 (idMapIt
!= idMapEnd
? idMapIt
->second
: 0) ));
510 /*! Prints the map showing the relation between FieldContainer ids in the file
511 and the system, which is used by mapPtrField to fill in the right pointers.
514 OSBRootElement::dumpIdMap(void) const
516 OSG_OSB_LOG(("OSBRootElement::dumpIdMap\n"));
518 FieldContainerIdMapConstIt mapIt
= getIdMap().begin();
519 FieldContainerIdMapConstIt mapEnd
= getIdMap().end ();
521 for(; mapIt
!= mapEnd
; ++mapIt
)
523 OSG_OSB_LOG((" file id %u -> %u system id\n", mapIt
->first
, mapIt
->second
));