osgDB Wrapper Associates Revision Tagging

This commit is contained in:
Julien Valentin 2016-06-14 11:43:45 +01:00 committed by Robert Osfield
parent dcac0c1611
commit 2ac8379cfc
6 changed files with 186 additions and 65 deletions

View File

@ -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<BaseSerializer> > SerializerList;
typedef std::vector< osg::ref_ptr<FinishedObjectReadCallback> > FinishedObjectReadCallbackList;
typedef std::list<ObjectWrapperAssociate> 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

View File

@ -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 );

View File

@ -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();

View File

@ -905,26 +905,36 @@ osg::ref_ptr<osg::Object> InputStream::readObjectFields( const std::string& clas
<< className << std::endl;
return NULL;
}
int inputVersion = getFileVersion(wrapper->getDomain());
osg::ref_ptr<osg::Object> 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():"<<className<<" Ignoring associated class due to version mismatch"
<< itr->_name<<"["<<itr->_firstVersion <<","<<itr->_lastVersion <<"]for version "<<inputVersion<< std::endl;*/
}
}
}
return obj;

View File

@ -80,6 +80,24 @@ void osgDB::split( const std::string& src, StringList& list, char separator )
}
}
void ObjectWrapper::splitAssociates( const std::string& src, ObjectWrapper::RevisionAssociateList& list, char separator )
{
std::string::size_type start = src.find_first_not_of(separator);
while ( start!=std::string::npos )
{
std::string::size_type end = src.find_first_of(separator, start);
if ( end!=std::string::npos )
{
list.push_back( ObjectWrapperAssociate(std::string(src, start, end-start)) );
start = src.find_first_not_of(separator, end);
}
else
{
list.push_back( ObjectWrapperAssociate(std::string(src, start, src.size()-start)) );
start = end;
}
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// ObjectWrapper
@ -87,19 +105,72 @@ void osgDB::split( const std::string& src, StringList& list, char separator )
ObjectWrapper::ObjectWrapper( CreateInstanceFunc* createInstanceFunc, const std::string& name,
const std::string& associates )
: osg::Referenced(),
_createInstanceFunc(createInstanceFunc), _name(name), _version(0)
_createInstanceFunc(createInstanceFunc), _name(name), _version(0),_isAssociatesRevisionsInheritanceDone(false)
{
split( associates, _associates );
splitAssociates( associates, _associates );
}
ObjectWrapper::ObjectWrapper( CreateInstanceFunc* createInstanceFunc, const std::string& domain, const std::string& name,
const std::string& associates )
: osg::Referenced(),
_createInstanceFunc(createInstanceFunc), _domain(domain), _name(name), _version(0)
_createInstanceFunc(createInstanceFunc), _domain(domain), _name(name), _version(0),_isAssociatesRevisionsInheritanceDone(false)
{
split( associates, _associates );
splitAssociates( associates, _associates );
}
void ObjectWrapper::setupAssociatesRevisionsInheritanceIfRequired()
{
if(!_isAssociatesRevisionsInheritanceDone)
{
///for each associate wrapper
for ( ObjectWrapper::RevisionAssociateList::const_iterator itr=_associates.begin(); itr!=_associates.end(); ++itr )
{
ObjectWrapper* assocWrapper = Registry::instance()->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<itr2->_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<<" not defined for wrapper "<<_name<<std::endl;
}
void ObjectWrapper::markAssociateAsRemoved(const std::string& name)
{
for ( ObjectWrapper::RevisionAssociateList:: iterator itr=_associates.begin(); itr!=_associates.end(); ++itr )
{
if(itr->_name==name)
{
itr->_lastVersion = _version-1;
return;
}
}
OSG_NOTIFY(osg::WARN)<<"ObjectWrapper::associateRemovedAtVersion: Associate class "<<name<<" not defined for wrapper "<<_name<<std::endl;
}
void ObjectWrapper::addSerializer( BaseSerializer* s, BaseSerializer::Type t )
{
s->_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;
}

View File

@ -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; i<size; ++i )
StringList properties;
ObjectWrapper::TypeList types;
assocWrapper->writeSchema( 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; i<size; ++i )
{
propertiesStream << properties[i] << ":" << types[i] << " ";
}
_inbuiltSchemaMap[assocName] = propertiesStream.str();
}
_inbuiltSchemaMap[assocName] = propertiesStream.str();
}
}
_fields.push_back( assocWrapper->getName() );
assocWrapper->write( *this, *obj );
if ( getException() ) return;
_fields.pop_back();
}
else
{
/*OSG_INFO << "OutputStream::writeObject():"<<name<<" Ignoring associated class due to version mismatch "
<< itr->_name<<"["<<itr->_firstVersion <<","<<itr->_lastVersion <<"]for output version "<<outputVersion<< std::endl;*/
}
_fields.push_back( assocWrapper->getName() );
assocWrapper->write( *this, *obj );
if ( getException() ) return;
_fields.pop_back();
}
}