Commit 99e021d6 authored by Yumin Yuan's avatar Yumin Yuan
Browse files

Refactor some logic in json import and export of models and meshes.

When exporting and importing smtk models (.smtk) with meshes in json format, more logics are added so we
have control over whether native models will be saved or loaded when saving and loading smtk models. Also,
when saving smtk models with meshes, a mesh file (.h5m) will be written out for the meshes, and then
loaded back with the model when importing the saved smtk model.
parent 8ec9713b
......@@ -129,6 +129,7 @@ namespace smtk
class MeshPhrase;
class MeshListPhrase;
class Model;
typedef std::vector<Model> Models;
class Operator;
class PropertyValuePhrase;
class PropertyListPhrase;
......
......@@ -16,30 +16,19 @@
namespace smtk {
namespace model {
/**\brief Decode information from \a sessionRec for the given \a modelMgr.
*
* Subclasses should return 1 on success and 0 on failure.
*/
// ++ 2 ++
int SessionIOJSON::importJSON(ManagerPtr modelMgr, cJSON* sessionRec)
{
(void)modelMgr;
(void)sessionRec;
return 1;
}
// -- 2 --
/**\brief Decode information from \a sessionRec for the given \a modelMgr.
*
* Subclasses should return 1 on success and 0 on failure.
*/
int SessionIOJSON::importJSON(ManagerPtr modelMgr,
const SessionPtr& session,
cJSON* sessionRec)
cJSON* sessionRec,
bool loadNativeModels)
{
(void)modelMgr;
(void)session;
(void)sessionRec;
(void)loadNativeModels;
return 1;
}
......@@ -48,10 +37,15 @@ int SessionIOJSON::importJSON(ManagerPtr modelMgr,
* Subclasses should return 1 on success and 0 on failure.
*/
// ++ 1 ++
int SessionIOJSON::exportJSON(ManagerPtr modelMgr, cJSON* sessionRec)
int SessionIOJSON::exportJSON(ManagerPtr modelMgr,
const SessionPtr& session,
cJSON* sessionRec,
bool writeNativeModels)
{
(void)modelMgr;
(void)session;
(void)sessionRec;
(void)writeNativeModels;
return 1;
}
// -- 1 --
......@@ -63,12 +57,14 @@ int SessionIOJSON::exportJSON(ManagerPtr modelMgr, cJSON* sessionRec)
*/
// ++ 3 ++
int SessionIOJSON::exportJSON(ManagerPtr modelMgr, const SessionPtr& session,
const common::UUIDs &modelIds, cJSON* sessionRec)
const common::UUIDs &modelIds, cJSON* sessionRec,
bool writeNativeModels)
{
(void)modelMgr;
(void)session;
(void)modelIds;
(void)sessionRec;
(void)writeNativeModels;
return 1;
}
// -- 3 --
......
......@@ -30,12 +30,13 @@ public:
smtkCreateMacro(SessionIOJSON);
virtual ~SessionIOJSON() { }
virtual int importJSON(ManagerPtr modelMgr, cJSON* sessionRec);
virtual int importJSON(ManagerPtr modelMgr, const SessionPtr& session,
cJSON* sessionRec);
virtual int exportJSON(ManagerPtr modelMgr, cJSON* sessionRec);
cJSON* sessionRec, bool loadNativeModels = false);
virtual int exportJSON(ManagerPtr modelMgr, const SessionPtr& sessPtr,
cJSON* sessionRec, bool writeNativeModels = false);
virtual int exportJSON(ManagerPtr modelMgr, const SessionPtr& session,
const common::UUIDs &modelIds, cJSON* sessionRec);
const common::UUIDs &modelIds, cJSON* sessionRec,
bool writeNativeModels = false);
};
// -- 1 --
......
......@@ -488,7 +488,8 @@ int ExportJSON::forManagerIntegerProperties(const smtk::common::UUID& uid, cJSON
int ExportJSON::forManagerSession(const smtk::common::UUID& uid,
cJSON* node,
ManagerPtr modelMgr)
ManagerPtr modelMgr,
bool writeNativeModels)
{
int status = 1;
SessionPtr session = SessionRef(modelMgr, uid).session();
......@@ -503,7 +504,7 @@ int ExportJSON::forManagerSession(const smtk::common::UUID& uid,
smtk::dynamic_pointer_cast<SessionIOJSON>(
session->createIODelegate("json"));
if (delegate)
status &= delegate->exportJSON(modelMgr, sess);
status &= delegate->exportJSON(modelMgr, session, sess, writeNativeModels);
status &= ExportJSON::forOperatorDefinitions(session->operatorSystem(), sess);
return status;
}
......@@ -511,7 +512,8 @@ int ExportJSON::forManagerSession(const smtk::common::UUID& uid,
int ExportJSON::forManagerSessionPartial(const smtk::common::UUID& sessionid,
const smtk::common::UUIDs& modelIds,
cJSON* node,
ManagerPtr modelMgr)
ManagerPtr modelMgr,
bool writeNativeModels)
{
int status = 1;
SessionPtr session = SessionRef(modelMgr, sessionid).session();
......@@ -527,7 +529,7 @@ int ExportJSON::forManagerSessionPartial(const smtk::common::UUID& sessionid,
smtk::dynamic_pointer_cast<SessionIOJSON>(
session->createIODelegate("json"));
if (delegate)
status &= delegate->exportJSON(modelMgr, session, modelIds, sess);
status &= delegate->exportJSON(modelMgr, session, modelIds, sess, writeNativeModels);
status &= ExportJSON::forOperatorDefinitions(session->operatorSystem(), sess);
return status;
}
......@@ -767,8 +769,12 @@ int ExportJSON::forMeshCollections(
return 0;
}
int status = 1;
cJSON* mesh = cJSON_CreateObject();
cJSON_AddItemToObject(pnode, "mesh_collections", mesh);
cJSON* mesh = cJSON_GetObjectItem(pnode, "mesh_collections");
if(!mesh)
{
mesh = cJSON_CreateObject();
cJSON_AddItemToObject(pnode, "mesh_collections", mesh);
}
smtk::common::UUIDs::const_iterator cit;
for(cit = collectionIds.begin(); cit != collectionIds.end(); ++cit)
......
......@@ -83,8 +83,10 @@ public:
static int forManagerStringProperties(const smtk::common::UUID& uid, cJSON*, smtk::model::ManagerPtr modelMgr);
static int forManagerIntegerProperties(const smtk::common::UUID& uid, cJSON*, smtk::model::ManagerPtr modelMgr);
static int forManagerMeshes(smtk::mesh::ManagerPtr meshes, cJSON*, smtk::model::ManagerPtr modelMgr);
static int forManagerSession(const smtk::common::UUID& uid, cJSON*, smtk::model::ManagerPtr modelMgr);
static int forManagerSessionPartial(const smtk::common::UUID& sessionId, const common::UUIDs &modelIds, cJSON*, smtk::model::ManagerPtr modelMgrId);
static int forManagerSession(const smtk::common::UUID& sessionId, cJSON*, smtk::model::ManagerPtr modelMgr,
bool writeNativeModels = false);
static int forManagerSessionPartial(const smtk::common::UUID& sessionId, const common::UUIDs &modelIds, cJSON*,
smtk::model::ManagerPtr modelMgrId, bool writeNativeModels = false);
//static int forModelOperators(const smtk::common::UUID& uid, cJSON*, smtk::model::ManagerPtr modelMgr);
static int forOperatorDefinitions(smtk::attribute::System* opSys, cJSON*);
static int forOperator(smtk::model::OperatorSpecification op, cJSON*);
......
......@@ -747,7 +747,7 @@ int ImportJSON::ofRemoteSession(cJSON* node, DefaultSessionPtr destSession, Mana
destSession->createIODelegate("json"));
if (delegate)
{
delegate->importJSON(context, node);
delegate->importJSON(context, destSession, node);
}
return status;
}
......@@ -785,7 +785,7 @@ int ImportJSON::ofRemoteSession(cJSON* node, DefaultSessionPtr destSession, Mana
* special care must be taken to avoid that behavior when importing
* a session.
*/
int ImportJSON::ofLocalSession(cJSON* node, ManagerPtr context)
int ImportJSON::ofLocalSession(cJSON* node, ManagerPtr context, bool loadNativeModels)
{
int status = 0;
cJSON* opsObj;
......@@ -827,8 +827,7 @@ int ImportJSON::ofLocalSession(cJSON* node, ManagerPtr context)
sref.session()->createIODelegate("json"));
if (delegate)
{
status = 1;
//status = delegate->importJSON(context, sref.session(), node);
status = delegate->importJSON(context, sref.session(), node, loadNativeModels);
}
return status;
}
......
......@@ -45,7 +45,7 @@ public:
static int ofManagerIntegerProperties(const smtk::common::UUID& uid, cJSON*, smtk::model::ManagerPtr manager);
static int forManagerMeshes(smtk::mesh::ManagerPtr meshes, cJSON*, smtk::model::ManagerPtr modelMgr);
static int ofRemoteSession(cJSON*, smtk::model::DefaultSessionPtr destSession, smtk::model::ManagerPtr context);
static int ofLocalSession(cJSON*, smtk::model::ManagerPtr context);
static int ofLocalSession(cJSON*, smtk::model::ManagerPtr context, bool loadNativeModels = false);
static int ofOperator(cJSON* node, smtk::model::OperatorPtr& op, smtk::model::ManagerPtr context);
static int ofOperatorResult(cJSON* node, smtk::model::OperatorResult& resOut, smtk::model::RemoteOperatorPtr op);
......
......@@ -26,27 +26,15 @@ using namespace boost::filesystem;
namespace smtk {
namespace model {
/**\brief Decode information from \a sessionRec for the given \a modelMgr.
*
* Subclasses should return 1 on success and 0 on failure.
*/
// ++ 2 ++
int SessionIOJSON::importJSON(ManagerPtr modelMgr, cJSON* sessionRec)
{
(void)modelMgr;
(void)sessionRec;
return 1;
}
/**\brief Decode information from \a sessionRec for the given \a modelMgr.
*
* Subclasses should return 1 on success and 0 on failure.
*/
int SessionIOJSON::importJSON(ManagerPtr modelMgr,
const SessionPtr& session,
cJSON* sessionRec)
cJSON* sessionRec,
bool loadNativeModels)
{
int status = 0;
smtk::common::UUIDs models =
modelMgr->entitiesMatchingFlags(smtk::model::MODEL_ENTITY);
......@@ -54,11 +42,11 @@ int SessionIOJSON::importJSON(ManagerPtr modelMgr,
if (!modelsObj)
{
smtkInfoMacro(modelMgr->log(), "Expecting a \"models\" entry!");
return status;
return 0;
}
cJSON* modelentry;
// import all model entites, should only have meta info
// import all native models model entites, should only have meta info
for (modelentry = modelsObj->child; modelentry; modelentry = modelentry->next)
{
if (!modelentry->string || !modelentry->string[0])
......@@ -94,43 +82,102 @@ int SessionIOJSON::importJSON(ManagerPtr modelMgr,
break;
}
std::string nativemodelfile;
std::string nativefilekey = modelMgr->hasStringProperty(modelid, "output_native_url") ?
"output_native_url" :
(modelMgr->hasStringProperty(modelid, "url") ? "url" : "");
if (!nativefilekey.empty())
if(loadNativeModels)
{
smtk::model::StringList const& nprop(modelMgr->stringProperty(modelid, nativefilekey));
if (!nprop.empty())
std::string nativemodelfile;
std::string nativefilekey = modelMgr->hasStringProperty(modelid, "output_native_url") ?
"output_native_url" :
(modelMgr->hasStringProperty(modelid, "url") ? "url" : "");
if (!nativefilekey.empty())
{
nativemodelfile = nprop[0];
smtk::model::StringList const& nprop(modelMgr->stringProperty(modelid, nativefilekey));
if (!nprop.empty())
{
nativemodelfile = nprop[0];
}
}
}
if(!nativemodelfile.empty())
{
// failed to load native model is still ok
this->loadNativeModel(modelMgr, session, nativemodelfile);
if(!nativemodelfile.empty())
{
// failed to load native model is still ok
this->loadNativeModel(modelMgr, session, nativemodelfile);
}
}
}
}
int status = this->loadModelsRecord(modelMgr, sessionRec);
status &= this->loadMeshesRecord(modelMgr, sessionRec);
return status;
}
/**\brief Parse models info from \a sessionRec for the given \a modelMgr.
*
* Subclasses should return 1 on success and 0 on failure.
*/
int SessionIOJSON::loadModelsRecord(ManagerPtr modelMgr,
cJSON* sessionRec)
{
cJSON* modelsObj = cJSON_GetObjectItem(sessionRec, "models");
if (!modelsObj)
{
// It's okay if we don't have "models" entry. Could be a record that
// did not come from SessionIOJSON;
smtkInfoMacro(modelMgr->log(), "Expecting a \"models\" entry!");
return 1;
}
int status = 1;
cJSON* modelentry;
// import all native models model entites, should only have meta info
for (modelentry = modelsObj->child; modelentry; modelentry = modelentry->next)
{
if (!modelentry->string || !modelentry->string[0])
continue;
smtk::common::UUID modelid = smtk::common::UUID(modelentry->string);
if (modelid.isNull())
{
smtkInfoMacro(modelMgr->log(), "Invalid model uuid, skipping!");
continue;
}
// model meta info
status &= smtk::io::ImportJSON::ofManager(modelentry, modelMgr);
// mesh collections related to this model
status &= smtk::io::ImportJSON::ofMeshesOfModel(modelentry, modelMgr, true);
}
return status;
}
/**\brief Parse meshes info from \a sessionRec for the given \a modelMgr.
*
* Subclasses should return 1 on success and 0 on failure.
*/
int SessionIOJSON::loadMeshesRecord(ManagerPtr modelMgr,
cJSON* sessionRec)
{
cJSON* meshesObj = cJSON_GetObjectItem(sessionRec, "mesh_collections");
if (!meshesObj)
{
// It's okay if we don't have "mesh_collections" entry. Could be a record that
// did not come from SessionIOJSON;
smtkInfoMacro(modelMgr->log(), "Expecting a \"mesh_collections\" entry!");
return 1;
}
return smtk::io::ImportJSON::ofMeshesOfModel(sessionRec, modelMgr, true);
}
/**\brief Encode information into \a sessionRec for the given \a modelMgr.
*
* Subclasses should return 1 on success and 0 on failure.
*/
int SessionIOJSON::exportJSON(ManagerPtr modelMgr, cJSON* sessionRec)
int SessionIOJSON::exportJSON(ManagerPtr modelMgr,
const SessionPtr& session,
cJSON* sessionRec,
bool writeNativeModels)
{
(void)modelMgr;
(void)session;
(void)sessionRec;
(void)writeNativeModels;
return 1;
}
......@@ -141,41 +188,97 @@ int SessionIOJSON::exportJSON(ManagerPtr modelMgr, cJSON* sessionRec)
int SessionIOJSON::exportJSON(ManagerPtr modelMgr,
const SessionPtr& session,
const smtk::common::UUIDs& modelIds,
cJSON* sessionRec)
cJSON* sessionRec,
bool writeNativeModels)
{
cJSON* jmodels = cJSON_CreateObject();
cJSON_AddItemToObject(sessionRec, "models", jmodels);
// we will write each model seperately
smtk::common::UUIDs::const_iterator modit;
for(modit = modelIds.begin(); modit != modelIds.end(); ++modit)
if(writeNativeModels)
{
smtk::model::Model model(modelMgr, *modit);
std::string outNativeFile;
if(this->writeNativeModel(
modelMgr, session, model, outNativeFile))
// we will write each model seperately
smtk::common::UUIDs::const_iterator modit;
for(modit = modelIds.begin(); modit != modelIds.end(); ++modit)
{
modelMgr->setStringProperty(*modit, "output_native_url", outNativeFile);
smtk::model::Model model(modelMgr, *modit);
std::string outNativeFile = this->getOutputFileNameForNativeModel(modelMgr, session, model);
if(this->writeNativeModel(modelMgr, session, model, outNativeFile))
{
modelMgr->setStringProperty(*modit, "output_native_url", outNativeFile);
}
}
}
this->addModelsRecord(modelMgr, modelIds, sessionRec);
this->addMeshesRecord(modelMgr, modelIds, sessionRec);
return 1;
}
/**\brief Add records for \a modelIds to its parent \a sessionRec.
*
* This will add a "models" record to \a sessionRec, and all models
* will be added as children of "models"
*/
void SessionIOJSON::addModelsRecord(const ManagerPtr& modelMgr,
const smtk::common::UUIDs& modelIds,
cJSON* sessionRec)
{
smtk::model::Models models;
smtk::model::EntityRef::EntityRefsFromUUIDs(models, modelMgr, modelIds);
this->addModelsRecord(modelMgr, models, sessionRec);
}
void SessionIOJSON::addModelsRecord(const ManagerPtr& modelMgr,
const smtk::model::Models& inModels,
cJSON* sessionRec)
{
cJSON* jmodels = cJSON_CreateObject();
cJSON_AddItemToObject(sessionRec, "models", jmodels);
// add record for each model
smtk::model::Models::const_iterator modit;
for(modit = inModels.begin(); modit != inModels.end(); ++modit)
{
//smtk::model::Model model(modelMgr, *modit);
cJSON* jmodel = cJSON_CreateObject();
cJSON_AddStringToObject(jmodel, "type", "model");
cJSON_AddStringToObject(jmodel, "name", model.name().c_str());
// Write out all entities of the model, only the meta data
smtk::model::Models currentmodels;
currentmodels.push_back(model);
currentmodels.push_back(*modit);
smtk::io::ExportJSON::forEntities(jmodel, currentmodels,
smtk::model::ITERATE_MODELS,
smtk::io::JSON_CLIENT_DATA);
static_cast<smtk::io::JSONFlags>(
smtk::io::JSON_ENTITIES | smtk::io::JSON_PROPERTIES));
cJSON_AddItemToObject(jmodels, modit->entity().toString().c_str(), jmodel);
}
}
/**\brief Add records for meshes of \a modelIds to its parent \a sessionRec.
*
* This will add a "mesh_collections" record to \a sessionRec, and all meshes
* will be added as children of "mesh_collections"
*/
void SessionIOJSON::addMeshesRecord(const ManagerPtr& modelMgr,
const smtk::common::UUIDs& modelIds,
cJSON* sessionRec)
{
smtk::model::Models models;
smtk::model::EntityRef::EntityRefsFromUUIDs(models, modelMgr, modelIds);
this->addMeshesRecord(modelMgr, models, sessionRec);
}
void SessionIOJSON::addMeshesRecord(const ManagerPtr& modelMgr,
const smtk::model::Models& inModels,
cJSON* sessionRec)
{
// add record for each model
smtk::model::Models::const_iterator modit;
for(modit = inModels.begin(); modit != inModels.end(); ++modit)
{
// Write out related mesh collections.
// When writing a single collection, all its MeshSets will also be written out.
smtk::io::ExportJSON::forModelMeshes(*modit, jmodel, modelMgr);
cJSON_AddItemToObject(jmodels, modit->toString().c_str(), jmodel);
smtk::io::ExportJSON::forModelMeshes(modit->entity(), sessionRec, modelMgr);
}
return 1;
}
/**\brief Create and write to a file (\a outNativeFile) for the given \a model.
......@@ -185,7 +288,7 @@ int SessionIOJSON::exportJSON(ManagerPtr modelMgr,
int SessionIOJSON::writeNativeModel(smtk::model::ManagerPtr modelMgr,
const smtk::model::SessionPtr& sess,
const smtk::model::Model& model,
std::string& outNativeFile)
const std::string& outNativeFile)
{
// if this is not a valid session, return;
if(!sess)
......@@ -194,6 +297,35 @@ int SessionIOJSON::writeNativeModel(smtk::model::ManagerPtr modelMgr,
return 0;
}
smtk::model::OperatorPtr writeOp = sess->op("write");
if (!writeOp)
{
smtkInfoMacro(modelMgr->log(), "Failed to create a write operator to write the model for native kernel!");
return 0;
}
writeOp->specification()->findFile("filename")->setValue(outNativeFile);
writeOp->specification()->associateEntity(model);
smtk::model::OperatorResult opresult = writeOp->operate();
if (opresult->findInt("outcome")->value() !=
smtk::model::OPERATION_SUCCEEDED)
{
smtkInfoMacro(modelMgr->log(), "Failed to write the model for native kernel!");
return 0;
}
return 1;
}
/**\brief Get or construct a filename for saving the native model.
*
* Return a full file path.
*/
std::string SessionIOJSON::getOutputFileNameForNativeModel(
smtk::model::ManagerPtr modelMgr,
const smtk::model::SessionPtr& sess,
const smtk::model::Model& model) const
{
std::string smtkfilepath, smtkfilename, origfilename, origfileext;
if (modelMgr->hasStringProperty(model.entity(), "smtk_url"))
{
......@@ -222,26 +354,8 @@ int SessionIOJSON::writeNativeModel(smtk::model::ManagerPtr modelMgr,
std::ostringstream outfilename;
outfilename << smtkfilename << "_native" << origfileext;
outNativeFile = (path(smtkfilepath) / path(outfilename.str())).string();
return (path(smtkfilepath) / path(outfilename.str())).string();
smtk::model::OperatorPtr writeOp = sess->op("write");
if (!writeOp)
{
smtkInfoMacro(modelMgr->log(), "Failed to create a write operator to write the model for native kernel!");
return 0;
}
writeOp->specification()->findFile("filename")->setValue(outNativeFile);
writeOp->specification()->associateEntity(model);
smtk::model::OperatorResult opresult = writeOp->operate();
if (opresult->findInt("outcome")->value() !=
smtk::model::OPERATION_SUCCEEDED)
{
smtkInfoMacro(modelMgr->log(), "Failed to write the model for native kernel!");
return 0;
}
return 1;
}
/**\brief Load the native model given the filename (\a inNativeFile).
......
......@@ -30,21 +30,44 @@ public:
virtual ~SessionIOJSON() { }
virtual int importJSON(ManagerPtr modelMgr, cJSON* sessionRec);
virtual int importJSON(ManagerPtr modelMgr, const SessionPtr& session,
cJSON* sessionRec);
virtual int exportJSON(ManagerPtr modelMgr, cJSON* sessionRec);
cJSON* sessionRec, bool loadNativeModels = false);
virtual int exportJSON(ManagerPtr modelMgr, const SessionPtr& sessPtr,
cJSON* sessionRec, bool writeNativeModels = false);
virtual int exportJSON(ManagerPtr modelMgr, const SessionPtr& session,
const common::UUIDs &modelIds, cJSON* sessionRec);
const common::UUIDs &modelIds, cJSON* sessionRec,
bool writeNativeModels = false);
protected:
virtual int writeNativeModel(smtk::model::ManagerPtr modelMgr,
const smtk::model::SessionPtr& sess,
const smtk::model::Model& model,
std::string& outNativeFile);
const std::string& outNativeFile);
virtual int loadNativeModel(smtk::model::ManagerPtr modelMgr,
const smtk::model::SessionPtr& sess,
const std::string& inNativeFile);
virtual std::string getOutputFileNameForNativeModel(
smtk::model::ManagerPtr modelMgr,
const smtk::model::SessionPtr& sess,
const smtk::model::Model& model) const;
virtual void addModelsRecord(const smtk::model::ManagerPtr& modelMgr,
const smtk::common::UUIDs& modelIds,
cJSON* sessionRec);
virtual void addModelsRecord(const smtk::model::ManagerPtr& modelMgr,
const smtk::model::Models& models,
cJSON* sessionRec);
virtual void addMeshesRecord(const ManagerPtr& modelMgr,
const smtk::common::UUIDs& modelIds,
cJSON* sessionRec);
virtual void addMeshesRecord(const ManagerPtr& modelMgr,
const smtk::model::Models& inModels,
cJSON* sessionRec);
virtual int loadModelsRecord(smtk::model::ManagerPtr modelMgr,
cJSON* sessionRec);
virtual int loadMeshesRecord(smtk::model::ManagerPtr modelMgr,
cJSON* sessionRec);
};
} // namespace model
......
......@@ -9,27 +9,25 @@
//=========================================================================
#include "smtk/model/operators/ExportSMTKModel.h"