Commit 1f4c1215 authored by Robert Maynard's avatar Robert Maynard
Browse files

smtk::mesh::Manager now can generate unique names for collections.

parent 17a1e4e2
......@@ -979,7 +979,7 @@ private:
};
}
/**\brief Serialize a single mesh colelction
/**\brief Serialize a single mesh collection
*
*/
int ExportJSON::forSingleCollection(cJSON* mdesc,
......@@ -991,6 +991,11 @@ int ExportJSON::forSingleCollection(cJSON* mdesc,
cJSON_AddItemToObject(mdesc, collectionUUID.c_str(), jsonCollection);
cJSON_AddItemToObject(jsonCollection,"formatVersion", cJSON_CreateNumber(1));
//ask the manager to generate a unique name for the collection, if it
//doesn't already have a unique name
collection->assignUniqueNameIfNotAlready();
cJSON_AddStringToObject(jsonCollection,"name", collection->name().c_str());
//assoicated model uuid of the collection
if(!collection->associatedModel().isNull())
......
......@@ -152,6 +152,17 @@ void Collection::name(const std::string& n)
this->m_name = n;
}
//----------------------------------------------------------------------------
bool Collection::assignUniqueName()
{
smtk::mesh::ManagerPtr currentManager = this->m_internals->manager();
if(currentManager)
{ //if we are associated with a valid manager
return currentManager->assignUniqueName( this->shared_from_this() );
}
return false;
}
//----------------------------------------------------------------------------
const std::string& Collection::readLocation() const
{
......
......@@ -73,6 +73,14 @@ public:
const std::string& name() const;
void name(const std::string& n);
//assign the collection a unique name, given the current manager.
//Note:
//If the current name is already unique, no change will happen but we will
//return true.
//If the collection has no manager, the current name is not changed, and
//false is returned
bool assignUniqueNameIfNotAlready();
//get the file that this collection was created from
//will return an empty string if this collection wasn't read from file
const std::string& readLocation() const;
......
......@@ -13,6 +13,8 @@
#include "smtk/common/UUID.h"
#include <boost/lexical_cast.hpp>
#include <map>
namespace smtk {
......@@ -99,10 +101,34 @@ private:
ContainerType Collections;
};
//----------------------------------------------------------------------------
class Manager::InternalNameGeneratorImpl
{
public:
InternalNameGeneratorImpl():
m_value(1),
m_basename("Mesh_")
{
}
std::string next()
{
std::string result(this->m_basename);
result += boost::lexical_cast< std::string >(this->m_value++);
return result;
}
private:
int m_value;
std::string m_basename;
};
//----------------------------------------------------------------------------
Manager::Manager():
m_collector( new InternalStorageImpl() ),
m_nameGenerator( new InternalNameGeneratorImpl() ),
m_uuidGenerator()
{
......@@ -295,5 +321,47 @@ Manager::associatedCollectionIds( const smtk::model::EntityRef& eref) const
return result;
}
//----------------------------------------------------------------------------
bool
Manager::assignUniqueName( smtk::mesh::CollectionPtr collection )
{
//if we don't own this collection, we can't generate a unique name for it
if(!this->hasCollection(collection) )
{
return false;
}
bool needsName = false;
if(collection->name().empty())
{
//fast code path, the collection name is empty, so we don't need to check
//if the existing name is unique
needsName = true;
}
else
{
std::string currentName = collection->name();
//slow path, we have to determine if the current name is unique or not
for(const_iterator i = this->m_collector->begin();
i != this->m_collector->end() && needsName == false;
++i)
{
if(i->second != collection)
{
needsName = ( i->second->name() == currentName );
}
}
}
if(needsName)
{
//time to generate a new name
collection->name( this->m_nameGenerator->next() );
}
return true;
}
}
}
......@@ -87,6 +87,21 @@ public:
smtk::common::UUIDs associatedCollectionIds(
const smtk::model::EntityRef& c ) const;
//----------------------------------------------------------------------------
// Collection name commands
// Will generate a name that is not used by any other collection owned by this
// manager, and assign it to the collection that is past in.
//
// Notes:
// If the collection already has a name, that name will be kept as long as it
// is unique.
//
// Will return false and not assign a name if the collection is not owned
// by the manager being called.
bool assignUniqueName( smtk::mesh::CollectionPtr collection );
private:
//needs to be created using shared_ptr
Manager();
......@@ -96,6 +111,8 @@ private:
smtk::common::UUID nextEntityId();
std::string nextUniqueName();
//returns true if the collection was added or already is part of this manager
//if the collection is currently part of a different manager we will reparent
//it to this collection
......@@ -104,6 +121,9 @@ private:
class InternalStorageImpl;
smtk::shared_ptr< InternalStorageImpl > m_collector;
class InternalNameGeneratorImpl;
smtk::shared_ptr< InternalNameGeneratorImpl > m_nameGenerator;
smtk::common::UUIDGenerator m_uuidGenerator;
};
......
......@@ -145,6 +145,71 @@ void verify_add_remove_collection()
}
//----------------------------------------------------------------------------
void verify_name_generation()
{
//verify that we can generate 1024 collections with unique names
{
smtk::mesh::ManagerPtr mgr = smtk::mesh::Manager::create();
const int size=1024;
for( int i=0 ; i < size; ++i)
{
//make a collection and add it to manager
smtk::mesh::CollectionPtr c = mgr->makeCollection();
test(mgr->assignUniqueName( c ), "failed to generate a unique name");
}
//We need to verify that every collection has a unique name
std::set< std::string > names;
for(smtk::mesh::Manager::const_iterator i=mgr->collectionBegin();
i != mgr->collectionEnd();
++i)
{
names.insert( i->second->name() );
}
test( names.size() == size, "Found multiple collections with the same name");
}
//verify that assignUniqueName doesn't override an existing name
{
smtk::mesh::ManagerPtr mgr = smtk::mesh::Manager::create();
smtk::mesh::CollectionPtr c = mgr->makeCollection();
c->name( std::string("a") );
mgr->assignUniqueName(c);
test( c->name() == std::string("a"), "assignUniqueName overwrote existing unique name" );
}
//verify that assignUniqueName override an existing name that isn't unique
{
smtk::mesh::ManagerPtr mgr = smtk::mesh::Manager::create();
smtk::mesh::CollectionPtr c1 = mgr->makeCollection();
smtk::mesh::CollectionPtr c2 = mgr->makeCollection();
c1->name( std::string("a") );
c2->name( std::string("a") );
mgr->assignUniqueName(c1); //will change, as name is not unique
mgr->assignUniqueName(c2); //will not change as name is now unique
test( c1->name() != std::string("a"),
"assignUniqueName didn't overwrite existing non-unique name" );
test( c2->name() == std::string("a"),
"assignUniqueName overwrote existing unique name" );
}
//verify that the only the owning manager can assign unique names
{
smtk::mesh::ManagerPtr mgr = smtk::mesh::Manager::create();
smtk::mesh::ManagerPtr mgr2 = smtk::mesh::Manager::create();
smtk::mesh::CollectionPtr c = mgr->makeCollection();
test( mgr2->assignUniqueName( c ) == false,
"only the owning manager can generate unique names for a collection");
c->reparent(mgr2);
test( mgr2->assignUniqueName( c ) == true);
}
}
//----------------------------------------------------------------------------
void verify_has_association()
{
......@@ -336,6 +401,8 @@ int UnitTestManager(int, char** const)
verify_add_remove_collection();
verify_name_generation();
verify_has_association();
verify_has_multiple_association();
verify_add_remove_association();
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment