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
),
78 _writeHandler (NULL
),
84 _readHeaderVersion(0 ),
95 /*-------------------------------------------------------------------------*/
100 OSBRootElement::~OSBRootElement(void)
105 /*-------------------------------------------------------------------------*/
108 /*! Initializes this root element for a read operation from \a inStream.
109 This must be called before OSBRootElement::read(const std::string&).
111 \param[in] inStream Stream to read data from.
114 OSBRootElement::initialiseRead(std::istream
&inStream
)
116 _readHandler
= new BinaryReadHandler(inStream
);
120 _readPtrFields
.clear();
123 /*! Performs clean up tasks after a read operation. This must be called after
124 OSBRootElement::postRead(void).
127 OSBRootElement::terminateRead(void)
129 ElementListIt eI
= editElementList().begin();
130 ElementListIt eE
= editElementList().end ();
132 for(; eI
!= eE
; ++eI
)
134 OSBElementFactory::the()->release(*eI
);
139 _readPtrFields
.clear();
145 /*! Reads from the stream set by a preceding call to initialiseRead. Since the
146 root element is the first one created it reads the file header and
147 creates the elements to read the data following the header.
149 \param[in] typeName The argument is ignored.
152 OSBRootElement::read(const std::string
&/*typeName*/)
154 OSG_OSB_LOG(("OSBRootElement::read\n"));
156 BinaryReadHandler
*rh
= getReadHandler();
157 std::string headerMarker
;
159 rh
->getValue(headerMarker
);
161 if(headerMarker
== OSGOSB_HEADER_ID_1
)
163 OSG_OSB_LOG(("OSBRootElement::read: Header version: [%u]\n",
164 OSGOSBHeaderVersion100
));
165 setHeaderVersion(OSGOSBHeaderVersion100
);
167 else if(headerMarker
== OSGOSB_HEADER_ID_2
)
169 OSG_OSB_LOG(("OSBRootElement::read: Header version: [%u]\n",
170 OSGOSBHeaderVersion200
));
171 setHeaderVersion(OSGOSBHeaderVersion200
);
173 // else if(headerMarker == OSGOSB_HEADER_ID_201)
175 // OSG_OSB_LOG(("OSBRootElement::read: Header version: [%u]\n",
176 // OSGOSBHeaderVersion201));
177 // setHeaderVersion(OSGOSBHeaderVersion201);
181 FWARNING(("OSBRootElement::read: Unrecognized file header, could not "
186 std::string headerName
;
187 rh
->getValue(headerName
);
188 std::string headerOptions
;
189 rh
->getValue(headerOptions
);
191 rh
->getValue(fileSize
);
193 OSG_OSB_LOG(("OSBRootElement::read: headerName: [%s]\n",
194 headerName
.c_str()));
195 OSG_OSB_LOG(("OSBRootElement::read: headerOptions: [%s]\n",
196 headerOptions
.c_str()));
197 OSG_OSB_LOG(("OSBRootElement::read: fileSize: [%" PRISize
"]\n",
200 std::string fcTypeName
;
201 UInt32 fcIdFile
; // id used in the file
202 UInt32 fcIdSystem
; // id used in the system
203 OSBElementBase
*elem
;
207 if(!readFieldContainerHeader(fcTypeName
, fcIdFile
))
210 OSG_OSB_LOG(("OSBRootElement::read: fcTypeName [%s] fcIdFile: [%u]\n",
211 fcTypeName
.c_str(), fcIdFile
));
213 elem
= OSBElementFactory::the()->acquire(fcTypeName
, this);
214 elem
->setFCIdFile(fcIdFile
);
215 elem
->read (fcTypeName
);
217 if(elem
->getContainer() != NULL
)
219 fcIdSystem
= elem
->getContainer()->getId();
221 OSG_OSB_LOG(("OSBRootElement::read: fcIdFile: [%u] fcIdSystem: [%u]\n",
222 fcIdFile
, fcIdSystem
));
225 FieldContainerIdMap::value_type(fcIdFile
, fcIdSystem
));
227 if(getContainer() == NULL
)
229 setContainer(elem
->getContainer());
232 editElementList().push_back(elem
);
233 editIdElemMap ().insert (std::make_pair(fcIdFile
, elem
));
238 /*! Performs post processing for all elements created during the previous
240 Specifically all these elements have their postRead function called and
241 afterwards pointer field remapping is performed. This process fills all
242 fields that hold pointers to FieldContainers with the correct values.
245 OSBRootElement::postRead(void)
247 OSG_OSB_LOG(("OSBRootElement::postRead\n"));
249 ElementListConstIt elemIt
= getElementList().begin();
250 ElementListConstIt elemEnd
= getElementList().end ();
252 for(; elemIt
!= elemEnd
; ++elemIt
)
254 (*elemIt
)->postRead();
259 PtrFieldListConstIt ptrFieldIt
= getPtrFieldList().begin();
260 PtrFieldListConstIt ptrFieldEnd
= getPtrFieldList().end ();
262 for(; ptrFieldIt
!= ptrFieldEnd
; ++ptrFieldIt
)
264 mapPtrField(*ptrFieldIt
);
270 void OSBRootElement::postMap(void)
272 OSG_OSB_LOG(("OSBRootElement::postMap\n"));
274 ElementListConstIt elemIt
= getElementList().begin();
275 ElementListConstIt elemEnd
= getElementList().end ();
277 for(; elemIt
!= elemEnd
; ++elemIt
)
279 (*elemIt
)->postMap();
283 /*-------------------------------------------------------------------------*/
286 /*! Initializes this root element for a write operation to \a outStream.
287 This must be called before
288 OSBRootElement::preWrite(const FieldContainerPtr&).
290 \param[in] outStream Stream to write data to.
293 OSBRootElement::initialiseWrite(std::ostream
&outStream
)
295 _writeHandler
= new BinaryWriteHandler(outStream
);
297 _writeFCList
.clear();
298 _writeIdSet
.clear();
301 /*! Performs clean up tasks after a write operation. This must be called after
302 OSBRootElement::write(void).
305 OSBRootElement::terminateWrite(void)
307 ElementListIt eI
= editElementList().begin();
308 ElementListIt eE
= editElementList().end ();
310 for(; eI
!= eE
; ++eI
)
312 OSBElementFactory::the()->release(*eI
);
316 _writeFCList
.clear();
317 _writeIdSet
.clear();
319 _writeHandler
->flush();
321 delete _writeHandler
;
325 /*! Collects all containers that are reachable from \a fc and schedules them
326 for writing. For each container an approriate element is created and
327 its preWrite method is called, thus recursively discovering all reachable
330 \param[in] fc FieldContainer that is inspected for reachable containers.
333 OSBRootElement::preWrite(FieldContainer
* const fc
)
335 OSG_OSB_LOG(("OSBRootElement::preWrite\n"));
340 const std::string
&typeName
= fc
->getType().getName();
341 OSBElementBase
*elem
= OSBElementFactory::the()->acquire(
344 editElementList().push_back(elem
);
345 elem
->setContainer(fc
);
346 elem
->setFCIdFile (fc
->getId());
347 elem
->preWrite (fc
);
350 /*! Writes the containers collected with the previous call to preWrite to the
351 stream set by initialiseWrite.
352 First the file header is written, then for each element created during
353 preWrite the write function is called.
356 OSBRootElement::write(void)
358 OSG_OSB_LOG(("OSBRootElement::write\n"));
360 BinaryWriteHandler
*wh
= getWriteHandler();
362 wh
->putValue(OSGOSB_HEADER_ID_2
); // version
363 wh
->putValue(std::string("") ); // name
364 wh
->putValue(std::string("") ); // options
365 wh
->putValue(static_cast<UInt64
>(0)); // size
367 ElementListConstIt elemIt
= getElementList().begin();
368 ElementListConstIt elemEnd
= getElementList().end ();
370 for(; elemIt
!= elemEnd
; ++elemIt
)
372 writeFieldContainerHeader((*elemIt
)->getContainer());
377 /*-------------------------------------------------------------------------*/
380 /*! Fills the "pointer field" described by \a ptrField with the correct
383 \param[in] ptrField Field to fill.
386 OSBRootElement::mapPtrField(const PtrFieldInfo
&ptrField
)
388 OSG_OSB_LOG(("OSBRootElement::mapPtrField\n"));
390 PtrFieldInfo::PtrIdStoreConstIt idIt
= ptrField
.beginIdStore();
391 PtrFieldInfo::PtrIdStoreConstIt idEnd
= ptrField
.endIdStore ();
393 PtrFieldInfo::BindingStoreConstIt bindingIt
= ptrField
.beginBindingStore();
394 PtrFieldInfo::BindingStoreConstIt bindingEnd
= ptrField
.endBindingStore ();
396 const FieldContainerIdMap
&idMap
= getIdMap();
397 FieldContainerIdMapConstIt idMapIt
;
398 FieldContainerIdMapConstIt idMapEnd
= idMap
.end();
400 if(bindingIt
!= bindingEnd
)
402 if(ptrField
.getHandledField() == true)
404 FieldContainer
*fieldCon
= ptrField
.getContainer();
405 UInt32 fieldId
= ptrField
.getFieldId();
407 EditFieldHandlePtr fHandle
= fieldCon
->editField(fieldId
);
409 EditMapFieldHandlePtr sfMapField
=
410 boost::dynamic_pointer_cast
<EditMapFieldHandle
>(fHandle
);
412 if(sfMapField
== NULL
|| sfMapField
->isValid() == false)
415 sfMapField
->fillFrom(ptrField
.getBindingStore(),
416 ptrField
.getIdStore (),
421 Attachment
*att
= NULL
;
422 AttachmentContainer
*attCon
=
423 dynamic_cast<AttachmentContainer
*>(ptrField
.getContainer());
425 for(; (idIt
!= idEnd
) && (bindingIt
!= bindingEnd
); ++idIt
,
430 idMapIt
= idMap
.find(*idIt
);
432 if(idMapIt
!= idMapEnd
)
434 att
= dynamic_cast<Attachment
*>(
435 FieldContainerFactory::the()->getContainer(
440 FWARNING(("OSBRootElement::mapPtrField: could not find "
441 "FieldContainer with id [%u]\n", *idIt
));
452 OSG_OSB_LOG(("OSBRootElement::mapPtrField: adding "
453 "attchment [%u] [%u]\n",
454 att
->getType().getGroupId(), *bindingIt
));
457 attCon
->addAttachment(att
, *bindingIt
);
463 FieldContainer
*fc
= NULL
;
464 FieldContainer
*fieldCon
= ptrField
.getContainer();
465 UInt32 fieldId
= ptrField
.getFieldId();
467 EditFieldHandlePtr fHandle
= fieldCon
->editField(fieldId
);
469 FieldContainerPtrSFieldBase::EditHandlePtr pSFHandle
=
470 boost::dynamic_pointer_cast
<
471 FieldContainerPtrSFieldBase::EditHandle
>(fHandle
);
473 FieldContainerPtrMFieldBase::EditHandlePtr pMFHandle
=
474 boost::dynamic_pointer_cast
<
475 FieldContainerPtrMFieldBase::EditHandle
>(fHandle
);
477 for(; idIt
!= idEnd
; ++idIt
)
481 idMapIt
= idMap
.find(*idIt
);
483 if(idMapIt
!= idMapEnd
)
485 fc
= FieldContainerFactory::the()->getContainer(
490 FWARNING(("OSBRootElement::mapPtrField: could not find "
491 "FieldContainer with (file) id [%u]\n", *idIt
));
500 if(pSFHandle
!= NULL
&& pSFHandle
->isValid())
504 else if(pMFHandle
!= NULL
&& pMFHandle
->isValid())
510 FWARNING(("OSBRootElement::mapPtrField: FieldHandles invalid, "
511 "can not set pointer - target fc [%u][%s] "
512 "fieldId [%u][%s] file id [%u] system id [%u]\n",
513 (fc
!= NULL
? fc
->getId() : 0),
514 (fc
!= NULL
? fc
->getType().getCName() : ""),
517 fc
->getType().getFieldDesc(fieldId
)->getCName() : ""),
519 (idMapIt
!= idMapEnd
? idMapIt
->second
: 0) ));
525 /*! Prints the map showing the relation between FieldContainer ids in the file
526 and the system, which is used by mapPtrField to fill in the right pointers.
529 OSBRootElement::dumpIdMap(void) const
531 OSG_OSB_LOG(("OSBRootElement::dumpIdMap\n"));
533 FieldContainerIdMapConstIt mapIt
= getIdMap().begin();
534 FieldContainerIdMapConstIt mapEnd
= getIdMap().end ();
536 for(; mapIt
!= mapEnd
; ++mapIt
)
538 OSG_OSB_LOG((" file id %u -> %u system id\n", mapIt
->first
, mapIt
->second
));