From 2ac8379cfceeff419726c159ea3d44ac08fe8d67 Mon Sep 17 00:00:00 2001 From: Julien Valentin Date: Tue, 14 Jun 2016 11:43:45 +0100 Subject: [PATCH] osgDB Wrapper Associates Revision Tagging --- include/osgDB/ObjectWrapper | 23 ++++++++- include/osgDB/Serializer | 6 +++ src/osgDB/ClassInterface.cpp | 24 ++++----- src/osgDB/InputStream.cpp | 34 ++++++++----- src/osgDB/ObjectWrapper.cpp | 98 ++++++++++++++++++++++++++++++++---- src/osgDB/OutputStream.cpp | 66 +++++++++++++----------- 6 files changed, 186 insertions(+), 65 deletions(-) diff --git a/include/osgDB/ObjectWrapper b/include/osgDB/ObjectWrapper index 80424880f..2bda5b54e 100644 --- a/include/osgDB/ObjectWrapper +++ b/include/osgDB/ObjectWrapper @@ -50,12 +50,21 @@ struct FinishedObjectReadCallback : public osg::Referenced virtual void objectRead(osgDB::InputStream& is, osg::Object& obj) = 0; }; +struct OSGDB_EXPORT ObjectWrapperAssociate +{ + ObjectWrapperAssociate(std::string name):_firstVersion(0),_lastVersion(INT_MAX),_name(name){} + int _firstVersion; + int _lastVersion; + std::string _name; +}; + class OSGDB_EXPORT ObjectWrapper : public osg::Referenced { public: typedef std::vector< BaseSerializer::Type > TypeList; typedef std::vector< osg::ref_ptr > SerializerList; typedef std::vector< osg::ref_ptr > FinishedObjectReadCallbackList; + typedef std::list RevisionAssociateList; typedef osg::Object* CreateInstanceFunc(); ObjectWrapper( CreateInstanceFunc* createInstanceFunc, const std::string& name, @@ -69,7 +78,8 @@ public: osg::Object* createInstance() const { return _createInstanceFunc(); } const std::string& getDomain() const { return _domain; } const std::string& getName() const { return _name; } - const StringList& getAssociates() const { return _associates; } + + const RevisionAssociateList& getAssociates() const { return _associates; } SerializerList& getSerializerList() { return _serializers; } const SerializerList& getSerializerList() const { return _serializers; } @@ -79,6 +89,10 @@ public: void addSerializer( BaseSerializer* s, BaseSerializer::Type t=BaseSerializer::RW_UNDEFINED ); void markSerializerAsRemoved( const std::string& name ); + + void markAssociateAsRemoved(const std::string& name); + void markAssociateAsAdded(const std::string& name); + BaseSerializer* getLastSerializer() { return _serializers.empty() ? 0 : _serializers.back().get(); } BaseSerializer* getSerializer( const std::string& name ); BaseSerializer* getSerializer( const std::string& name, BaseSerializer::Type& type); @@ -99,6 +113,8 @@ public: MethodObjectMap& getMethodObjectMap() { return _methodObjectMap; } const MethodObjectMap& getMethodObjectMap() const { return _methodObjectMap; } + void setupAssociatesRevisionsInheritanceIfRequired(); + protected: ObjectWrapper() : _version(0) {} virtual ~ObjectWrapper() {} @@ -106,13 +122,16 @@ protected: CreateInstanceFunc* _createInstanceFunc; std::string _domain; std::string _name; - StringList _associates; + RevisionAssociateList _associates; SerializerList _serializers; SerializerList _backupSerializers; TypeList _typeList; FinishedObjectReadCallbackList _finishedObjectReadCallbacks; MethodObjectMap _methodObjectMap; int _version; // Last updated version of the wrapper + //simulate associate revisions inheritance + bool _isAssociatesRevisionsInheritanceDone; + static void splitAssociates( const std::string& src, ObjectWrapper::RevisionAssociateList& list, char separator=' ' ); }; struct UpdateWrapperVersionProxy diff --git a/include/osgDB/Serializer b/include/osgDB/Serializer index 351c41022..d1b91ae56 100644 --- a/include/osgDB/Serializer +++ b/include/osgDB/Serializer @@ -1880,6 +1880,12 @@ protected: #define UPDATE_TO_VERSION_SCOPED(VER) \ osgDB::UpdateWrapperVersionProxy uwvp(wrapper, (VER)); +#define ADDED_ASSOCIATE(STR) \ + wrapper->markAssociateAsAdded( STR ); + +#define REMOVED_ASSOCIATE(STR) \ + wrapper->markAssociateAsRemoved( STR ); + #define REMOVE_SERIALIZER(PROP) \ wrapper->markSerializerAsRemoved( #PROP ); diff --git a/src/osgDB/ClassInterface.cpp b/src/osgDB/ClassInterface.cpp index f2e638082..15253262b 100644 --- a/src/osgDB/ClassInterface.cpp +++ b/src/osgDB/ClassInterface.cpp @@ -509,12 +509,12 @@ bool ClassInterface::getSupportedProperties(const osg::Object* object, PropertyM if (searchAssociates) { - const osgDB::StringList& associates = ow->getAssociates(); - for(osgDB::StringList::const_iterator aitr = associates.begin(); + const ObjectWrapper::RevisionAssociateList& associates = ow->getAssociates(); + for(ObjectWrapper::RevisionAssociateList::const_iterator aitr = associates.begin(); aitr != associates.end(); ++aitr) { - osgDB::ObjectWrapper* associate_wrapper = osgDB::Registry::instance()->getObjectWrapperManager()->findWrapper(*aitr); + osgDB::ObjectWrapper* associate_wrapper = osgDB::Registry::instance()->getObjectWrapperManager()->findWrapper(aitr->_name); if (associate_wrapper) { const osgDB::ObjectWrapper::SerializerList& associate_serializers = associate_wrapper->getSerializerList(); @@ -560,12 +560,12 @@ bool ClassInterface::isObjectOfType(const osg::Object* object, const std::string return false; } - const osgDB::StringList& associates = ow->getAssociates(); - for(osgDB::StringList::const_iterator aitr = associates.begin(); + const ObjectWrapper::RevisionAssociateList& associates = ow->getAssociates(); + for(ObjectWrapper::RevisionAssociateList::const_iterator aitr = associates.begin(); aitr != associates.end(); ++aitr) { - if ((*aitr)==compoundClassName) return true; + if ((aitr->_name)==compoundClassName) return true; } return false; } @@ -584,12 +584,12 @@ bool ClassInterface::run(void* objectPtr, const std::string& compoundClassName, if (mo->run(objectPtr, inputParameters, outputParameters)) return true; } - const osgDB::StringList& associates = ow->getAssociates(); - for(osgDB::StringList::const_iterator aitr = associates.begin(); + const ObjectWrapper::RevisionAssociateList& associates = ow->getAssociates(); + for(ObjectWrapper::RevisionAssociateList::const_iterator aitr = associates.begin(); aitr != associates.end(); ++aitr) { - osgDB::ObjectWrapper* aow = osgDB::Registry::instance()->getObjectWrapperManager()->findWrapper(*aitr); + osgDB::ObjectWrapper* aow = osgDB::Registry::instance()->getObjectWrapperManager()->findWrapper(aitr->_name); if (aow) { const ObjectWrapper::MethodObjectMap& methodObjectMap = aow->getMethodObjectMap(); @@ -620,12 +620,12 @@ bool ClassInterface::hasMethod(const std::string& compoundClassName, const std:: ObjectWrapper::MethodObjectMap::const_iterator oitr = ow_methodObjectMap.find(methodName); if (oitr!=ow_methodObjectMap.end()) return true; - const osgDB::StringList& associates = ow->getAssociates(); - for(osgDB::StringList::const_iterator aitr = associates.begin(); + const ObjectWrapper::RevisionAssociateList& associates = ow->getAssociates(); + for(ObjectWrapper::RevisionAssociateList::const_iterator aitr = associates.begin(); aitr != associates.end(); ++aitr) { - osgDB::ObjectWrapper* aow = osgDB::Registry::instance()->getObjectWrapperManager()->findWrapper(*aitr); + osgDB::ObjectWrapper* aow = osgDB::Registry::instance()->getObjectWrapperManager()->findWrapper(aitr->_name); if (aow) { const ObjectWrapper::MethodObjectMap& methodObjectMap = aow->getMethodObjectMap(); diff --git a/src/osgDB/InputStream.cpp b/src/osgDB/InputStream.cpp index bc292ce30..f4b695b3e 100644 --- a/src/osgDB/InputStream.cpp +++ b/src/osgDB/InputStream.cpp @@ -905,26 +905,36 @@ osg::ref_ptr InputStream::readObjectFields( const std::string& clas << className << std::endl; return NULL; } + int inputVersion = getFileVersion(wrapper->getDomain()); osg::ref_ptr obj = existingObj ? existingObj : wrapper->createInstance(); _identifierMap[id] = obj; if ( obj.valid() ) { - const StringList& associates = wrapper->getAssociates(); - for ( StringList::const_iterator itr=associates.begin(); itr!=associates.end(); ++itr ) + const ObjectWrapper::RevisionAssociateList& associates = wrapper->getAssociates(); + for ( ObjectWrapper::RevisionAssociateList::const_iterator itr=associates.begin(); itr!=associates.end(); ++itr ) { - ObjectWrapper* assocWrapper = Registry::instance()->getObjectWrapperManager()->findWrapper(*itr); - if ( !assocWrapper ) + if ( itr->_firstVersion <= inputVersion && + inputVersion <= itr->_lastVersion) { - OSG_WARN << "InputStream::readObject(): Unsupported associated class " - << *itr << std::endl; - continue; - } - _fields.push_back( assocWrapper->getName() ); - assocWrapper->read( *this, *obj ); - if ( getException() ) return NULL; + ObjectWrapper* assocWrapper = Registry::instance()->getObjectWrapperManager()->findWrapper(itr->_name); + if ( !assocWrapper ) + { + OSG_WARN << "InputStream::readObject(): Unsupported associated class " + << itr->_name << std::endl; + continue; + } + _fields.push_back( assocWrapper->getName() ); + assocWrapper->read( *this, *obj ); + if ( getException() ) return NULL; - _fields.pop_back(); + _fields.pop_back(); + } + else + { + /* OSG_INFO << "InputStream::readObject():"<_name<<"["<_firstVersion <<","<_lastVersion <<"]for version "<getObjectWrapperManager()->findWrapper(itr->_name); + if ( assocWrapper && assocWrapper != this ) + { + ///crawl association revisions in associates + for ( ObjectWrapper::RevisionAssociateList::const_iterator itr2=assocWrapper->getAssociates().begin(); itr2!=assocWrapper->getAssociates().end(); ++itr2 ) + { + for ( ObjectWrapper::RevisionAssociateList::iterator itr3=_associates.begin(); itr3!=_associates.end(); ++itr3 ) + { + ///they share associates + if(itr3->_name==itr2->_name) + { + itr3->_firstVersion=itr3->_firstVersion>itr2->_firstVersion? itr3->_firstVersion:itr2->_firstVersion; + itr3->_lastVersion=itr3->_lastVersion_lastVersion? itr3->_lastVersion:itr2->_lastVersion; + } + } + } + } + } + _isAssociatesRevisionsInheritanceDone=true; + } + +} +void ObjectWrapper::markAssociateAsAdded(const std::string& name) +{ + for ( ObjectWrapper::RevisionAssociateList:: iterator itr=_associates.begin(); itr!=_associates.end(); ++itr ) + { + if(itr->_name==name) + { + itr->_firstVersion=_version; + return; + } + } + OSG_NOTIFY(osg::WARN)<<"ObjectWrapper::associateAddedAtVersion: Associate class "<_name==name) + { + itr->_lastVersion = _version-1; + return; + } + } + OSG_NOTIFY(osg::WARN)<<"ObjectWrapper::associateRemovedAtVersion: Associate class "<_firstVersion = _version; @@ -127,9 +198,9 @@ BaseSerializer* ObjectWrapper::getSerializer( const std::string& name ) return itr->get(); } - for ( StringList::const_iterator itr=_associates.begin(); itr!=_associates.end(); ++itr ) + for ( RevisionAssociateList::const_iterator itr=_associates.begin(); itr!=_associates.end(); ++itr ) { - const std::string& assocName = *itr; + const std::string& assocName = itr->_name; ObjectWrapper* assocWrapper = Registry::instance()->getObjectWrapperManager()->findWrapper(assocName); if ( !assocWrapper ) { @@ -163,9 +234,9 @@ BaseSerializer* ObjectWrapper::getSerializer( const std::string& name, BaseSeria } } - for ( StringList::const_iterator itr=_associates.begin(); itr!=_associates.end(); ++itr ) + for ( RevisionAssociateList::const_iterator itr=_associates.begin(); itr!=_associates.end(); ++itr ) { - const std::string& assocName = *itr; + const std::string& assocName = itr->_name; ObjectWrapper* assocWrapper = Registry::instance()->getObjectWrapperManager()->findWrapper(assocName); if ( !assocWrapper ) { @@ -681,17 +752,22 @@ ObjectWrapper* ObjectWrapperManager::findWrapper( const std::string& name ) { std::string libName = std::string( name, 0, posDoubleColon ); + ObjectWrapper* found=0; std::string nodeKitLib = osgDB::Registry::instance()->createLibraryNameForNodeKit(libName); if ( osgDB::Registry::instance()->loadLibrary(nodeKitLib)==osgDB::Registry::LOADED ) - return findWrapper(name); + found= findWrapper(name); std::string pluginLib = osgDB::Registry::instance()->createLibraryNameForExtension(std::string("serializers_")+libName); if ( osgDB::Registry::instance()->loadLibrary(pluginLib)==osgDB::Registry::LOADED ) - return findWrapper(name); + found= findWrapper(name); pluginLib = osgDB::Registry::instance()->createLibraryNameForExtension(libName); if ( osgDB::Registry::instance()->loadLibrary(pluginLib)==osgDB::Registry::LOADED ) - return findWrapper(name); + found= findWrapper(name); + + if (found) found->setupAssociatesRevisionsInheritanceIfRequired(); + + return found; } return NULL; } diff --git a/src/osgDB/OutputStream.cpp b/src/osgDB/OutputStream.cpp index 98efa9f9e..4132ff93f 100644 --- a/src/osgDB/OutputStream.cpp +++ b/src/osgDB/OutputStream.cpp @@ -645,44 +645,54 @@ void OutputStream::writeObjectFields( const osg::Object* obj, const std::string& << name << std::endl; return; } + int outputVersion = getFileVersion(wrapper->getDomain()); - const StringList& associates = wrapper->getAssociates(); - for ( StringList::const_iterator itr=associates.begin(); itr!=associates.end(); ++itr ) + const ObjectWrapper::RevisionAssociateList& associates = wrapper->getAssociates(); + for ( ObjectWrapper::RevisionAssociateList::const_iterator itr=associates.begin(); itr!=associates.end(); ++itr ) { - const std::string& assocName = *itr; - ObjectWrapper* assocWrapper = Registry::instance()->getObjectWrapperManager()->findWrapper(assocName); - if ( !assocWrapper ) + if ( itr->_firstVersion <= outputVersion && + outputVersion <= itr->_lastVersion) { - OSG_WARN << "OutputStream::writeObject(): Unsupported associated class " - << assocName << std::endl; - continue; - } - else if ( _useSchemaData ) - { - if ( _inbuiltSchemaMap.find(assocName)==_inbuiltSchemaMap.end() ) + const std::string& assocName = itr->_name; + ObjectWrapper* assocWrapper = Registry::instance()->getObjectWrapperManager()->findWrapper(assocName); + if ( !assocWrapper ) { - StringList properties; - ObjectWrapper::TypeList types; - assocWrapper->writeSchema( properties, types ); - - unsigned int size = osg::minimum( properties.size(), types.size() ); - if ( size>0 ) + OSG_WARN << "OutputStream::writeObject(): Unsupported associated class " + << assocName << std::endl; + continue; + } + else if ( _useSchemaData ) + { + if ( _inbuiltSchemaMap.find(assocName)==_inbuiltSchemaMap.end() ) { - std::stringstream propertiesStream; - for ( unsigned int i=0; iwriteSchema( properties, types ); + + unsigned int size = osg::minimum( properties.size(), types.size() ); + if ( size>0 ) { - propertiesStream << properties[i] << ":" << types[i] << " "; + std::stringstream propertiesStream; + for ( unsigned int i=0; igetName() ); + + assocWrapper->write( *this, *obj ); + if ( getException() ) return; + + _fields.pop_back(); + } + else + { + /*OSG_INFO << "OutputStream::writeObject():"<_name<<"["<_firstVersion <<","<_lastVersion <<"]for output version "<getName() ); - - assocWrapper->write( *this, *obj ); - if ( getException() ) return; - - _fields.pop_back(); } }