Commit 5e2a9f57 authored by Yumin Yuan's avatar Yumin Yuan Committed by Kitware Robot
Browse files

Merge topic 'export-import-smtk-model'

53d5dabb Fix linux build error with ifstream constructor
60be0d69 Add all new non-sub models to created after ImportSMTKModel op
048a0acf Dont overwrite url for existing model while importing smtk model
99e021d6 Refactor some logic in json import and export of models and meshes.
8ec9713b Modified some tags in session exporting and importing
8ff0325e Made discrete write-op to be like write-ops in other sessions
80683af9 Adding methods and operators for saving session models and meshes
f164badc

 More methods for writing JSON meshes and collections
Acked-by: Kitware Robot's avatarKitware Robot <kwrobot@kitware.com>
Merge-request: !24
parents 8c6f59df 53d5dabb
......@@ -129,6 +129,7 @@ namespace smtk
class MeshPhrase;
class MeshListPhrase;
class Model;
typedef std::vector<Model> Models;
class Operator;
class PropertyValuePhrase;
class PropertyListPhrase;
......
......@@ -49,14 +49,15 @@ WriteOperator::WriteOperator()
bool WriteOperator::ableToOperate()
{
smtk::model::Model model;
smtk::model::Models models =
this->specification()->associatedModelEntities<smtk::model::Models>();
bool able2Op =
this->ensureSpecification() &&
// The SMTK model must be valid
(model = this->specification()->findModelEntity("model")
->value().as<smtk::model::Model>()).isValid() &&
(models.size() > 0 && models[0].isValid() &&
// The CMB model must exist
this->discreteSession()->findModelEntity(model.entity());
this->discreteSession()->findModelEntity(models[0].entity()));
if(!able2Op)
return false;
......@@ -74,8 +75,12 @@ OperatorResult WriteOperator::operateInternal()
Session* opsession = this->discreteSession();
// ableToOperate should have verified that the model exists
smtk::model::Model model = this->specification()->
findModelEntity("model")->value().as<smtk::model::Model>();
smtk::model::Models models =
this->specification()->associatedModelEntities<smtk::model::Models>();
if (models.size() == 0)
return this->createResult(OPERATION_FAILED);
smtk::model::Model model = models[0];
vtkDiscreteModelWrapper* modelWrapper =
opsession->findModelEntity(model.entity());
......
......@@ -4,10 +4,15 @@
<Definitions>
<!-- Operator -->
<AttDef Type="write" BaseType="operator">
<AssociationsDef Name="Model" NumberOfRequiredValues="1">
<MembershipMask>model</MembershipMask>
</AssociationsDef>
<ItemDefinitions>
<!--
<ModelEntity Name="model" NumberOfRequiredValues="1">
<MembershipMask>model</MembershipMask>
</ModelEntity>
-->
<File Name="filename" NumberOfRequiredValues="1"
ShouldExist="false"
FileFilters="Conceptual Model Builder (*.cmb)">
......
......@@ -652,12 +652,8 @@ bool Session::ensureChildParentMapEntry(vtkDataObject* child, vtkDataObject* par
// ++ 12 ++
SessionIOPtr Session::createIODelegate(const std::string& format)
{
if (format == "json")
{
return SessionIOJSON::create();
}
return SessionIOPtr();
// Currently the DefaultSession is handling this.
return this->Superclass::createIODelegate(format);
}
// -- 12 --
......
......@@ -20,24 +20,32 @@ namespace smtk {
*
* Subclasses should return 1 on success and 0 on failure.
*/
// ++ 2 ++
int SessionIOJSON::importJSON(ManagerPtr modelMgr, cJSON* sessionRec)
int SessionIOJSON::importJSON(ManagerPtr modelMgr,
const SessionPtr& session,
cJSON* sessionRec,
bool loadNativeModels)
{
(void)modelMgr;
(void)session;
(void)sessionRec;
(void)loadNativeModels;
return 1;
}
// -- 2 --
/**\brief Encode information into \a sessionRec for the given \a 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 --
......@@ -48,11 +56,15 @@ int SessionIOJSON::exportJSON(ManagerPtr modelMgr, cJSON* sessionRec)
* This variant should export only information for the given models.
*/
// ++ 3 ++
int SessionIOJSON::exportJSON(ManagerPtr modelMgr, const common::UUIDs& modelIds, cJSON* sessionRec)
int SessionIOJSON::exportJSON(ManagerPtr modelMgr, const SessionPtr& session,
const common::UUIDs &modelIds, cJSON* sessionRec,
bool writeNativeModels)
{
(void)modelMgr;
(void)session;
(void)modelIds;
(void)sessionRec;
(void)writeNativeModels;
return 1;
}
// -- 3 --
......
......@@ -30,9 +30,13 @@ public:
smtkCreateMacro(SessionIOJSON);
virtual ~SessionIOJSON() { }
virtual int importJSON(SessionRef modelMgr, cJSON* sessionRec);
virtual int exportJSON(SessionRef modelMgr, cJSON* sessionRec);
virtual int exportJSON(ManagerPtr modelMgr, const common::UUIDs& modelIds, cJSON* sessionRec);
virtual int importJSON(ManagerPtr modelMgr, const SessionPtr& session,
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,
bool writeNativeModels = false);
};
// -- 1 --
......
......@@ -486,7 +486,10 @@ int ExportJSON::forManagerIntegerProperties(const smtk::common::UUID& uid, cJSON
return ExportJSON::forIntegerData(dict, entIt->second);
}
int ExportJSON::forManagerSession(const smtk::common::UUID& uid, cJSON* node, ManagerPtr modelMgr)
int ExportJSON::forManagerSession(const smtk::common::UUID& uid,
cJSON* node,
ManagerPtr modelMgr,
bool writeNativeModels)
{
int status = 1;
SessionPtr session = SessionRef(modelMgr, uid).session();
......@@ -501,30 +504,32 @@ int ExportJSON::forManagerSession(const smtk::common::UUID& uid, cJSON* node, Ma
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;
}
int ExportJSON::forManagerSessionPartial(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, uid).session();
SessionPtr session = SessionRef(modelMgr, sessionid).session();
if (!session)
return status;
cJSON* sess = cJSON_CreateObject();
cJSON_AddItemToObject(node, uid.toString().c_str(), sess);
cJSON_AddItemToObject(node, sessionid.toString().c_str(), sess);
cJSON_AddStringToObject(sess, "type", "session");
cJSON_AddStringToObject(sess, "name", session->name().c_str());
SessionIOJSONPtr delegate =
smtk::dynamic_pointer_cast<SessionIOJSON>(
session->createIODelegate("json"));
if (delegate)
status &= delegate->exportJSON(modelMgr, modelIds, sess);
status &= delegate->exportJSON(modelMgr, session, modelIds, sess, writeNativeModels);
status &= ExportJSON::forOperatorDefinitions(session->operatorSystem(), sess);
return status;
}
......@@ -624,7 +629,7 @@ int ExportJSON::forOperatorResult(OperatorResult res, cJSON* entRec)
if(collectionIds.size() > 0)
{
cJSON* mesh_records = cJSON_CreateObject();
ExportJSON::forMeshes(mesh_records, collectionIds, meshMgr);
ExportJSON::forMeshCollections(mesh_records, collectionIds, meshMgr);
cJSON_AddItemToObject(entRec, "mesh_records", mesh_records);
}
}
......@@ -742,14 +747,14 @@ int ExportJSON::forManagerMeshes(
return status;
}
/**\brief Serialize all the smtk::mesh associated with given EntityRefs.
/**\brief Serialize input mesh Collections.
*
* This creates and populate an JSON Object "mesh_collections"
* and add it to the parent json node (\a pnode) with
* data required to recreate the smtk::mesh Collections
* associated with the given \a collectionIds.
* data required to recreate the mesh Collections
* associated with the given \a collectionIds of mesh manager (\a meshMgr)
*/
int ExportJSON::forMeshes(
int ExportJSON::forMeshCollections(
cJSON* pnode,
const smtk::common::UUIDs& collectionIds,
smtk::mesh::ManagerPtr meshMgr)
......@@ -764,8 +769,12 @@ int ExportJSON::forMeshes(
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)
......@@ -776,6 +785,32 @@ int ExportJSON::forMeshes(
return status;
}
/**\brief Serialize all the mesh collections associated with given \a modelid.
*
* This creates and populate an JSON Object "mesh_collections"
* and add it to the parent json node (\a pnode) with
* all mesh collections associated with the given \a modelid.
*/
int ExportJSON::forModelMeshes(
const smtk::common::UUID& modelid,
cJSON* pnode,
smtk::model::ManagerPtr modelMgr)
{
if (!pnode || pnode->type != cJSON_Object)
{
return 0;
}
smtk::mesh::ManagerPtr meshMgr = modelMgr->meshes();
smtk::model::Model model(modelMgr, modelid);
if(!model.isValid() || !meshMgr)
{
return 0;
}
smtk::common::UUIDs cids = meshMgr->associatedCollectionIds(model);
return ExportJSON::forMeshCollections(pnode, cids, meshMgr);
}
namespace {
......
......@@ -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*);
......@@ -103,12 +105,19 @@ public:
static int forSingleCollection(cJSON* mdesc,
smtk::mesh::CollectionPtr collection);
// Serialize all the smtk::mesh associated with given EntityRefs.
static int forMeshes(
// Serialize all the input mesh Collections in mesh manager \a meshMgr,
// given the mesh \a collectionIds.
static int forMeshCollections(
cJSON* pnode,
const smtk::common::UUIDs& collectionIds,
smtk::mesh::ManagerPtr meshMgr);
// Serialize all the smtk::mesh collections associated with given \a modelid.
static int forModelMeshes(
const smtk::common::UUID& modelid,
cJSON* pnode,
smtk::model::ManagerPtr modelMgr);
static int forLog(
cJSON* logrecordarray,
const smtk::io::Logger& log,
......
......@@ -54,8 +54,6 @@ int ExportJSON::forEntities(
}
if (sections & JSON_TESSELLATIONS)
status &= ExportJSON::forManagerTessellation(it->first, curChild, modelMgr);
if (sections & JSON_ANALYSISMESH)
status &= ExportJSON::forManagerAnalysis(it->first, curChild, modelMgr);
if (sections & JSON_PROPERTIES)
{
status &= ExportJSON::forManagerFloatProperties(it->first, curChild, modelMgr);
......@@ -63,7 +61,7 @@ int ExportJSON::forEntities(
status &= ExportJSON::forManagerIntegerProperties(it->first, curChild, modelMgr);
}
}
return 0;
return status;
}
/**\brief Populate the \a json node with the record(s) related to given \a entities.
......
......@@ -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,7 +827,7 @@ int ImportJSON::ofLocalSession(cJSON* node, ManagerPtr context)
sref.session()->createIODelegate("json"));
if (delegate)
{
status = delegate->importJSON(context, node);
status = delegate->importJSON(context, sref.session(), node, loadNativeModels);
}
return status;
}
......
......@@ -45,7 +45,8 @@ 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);
static int ofDanglingEntities(cJSON* node, smtk::model::ManagerPtr context);
......
......@@ -48,6 +48,8 @@ set(modelSrcs
operators/CloseModel.cxx
operators/SetProperty.cxx
operators/ExportModelJSON.cxx
operators/ExportSMTKModel.cxx
operators/ImportSMTKModel.cxx
)
set(modelHeaders
......@@ -112,6 +114,8 @@ smtk_session_json("${CMAKE_CURRENT_SOURCE_DIR}/DefaultSession.json" defSessionJS
smtk_operator_xml("${CMAKE_CURRENT_SOURCE_DIR}/operators/CloseModel.sbt" defOpXML)
smtk_operator_xml("${CMAKE_CURRENT_SOURCE_DIR}/operators/SetProperty.sbt" defOpXML)
smtk_operator_xml("${CMAKE_CURRENT_SOURCE_DIR}/operators/ExportModelJSON.sbt" defOpXML)
smtk_operator_xml("${CMAKE_CURRENT_SOURCE_DIR}/operators/ExportSMTKModel.sbt" defOpXML)
smtk_operator_xml("${CMAKE_CURRENT_SOURCE_DIR}/operators/ImportSMTKModel.sbt" defOpXML)
#install the headers
smtk_public_headers(${modelHeaders})
......
......@@ -4,7 +4,8 @@
{
"name": "native",
"filetypes": [
".json (Native SMTK model)"
".smtk (SMTK JSON model)",
".json (SMTK JSON model)"
]
}
]
......
......@@ -9,7 +9,7 @@
//=========================================================================
#include "smtk/model/Session.h"
#include "smtk/model/SessionIO.h"
#include "smtk/model/SessionIOJSON.h"
#include "smtk/model/Manager.h"
#include "smtk/model/RemoteOperator.h"
#include "smtk/model/ArrangementHelper.h"
......@@ -806,7 +806,11 @@ OperatorConstructor Session::findOperatorConstructorInternal(
*/
SessionIOPtr Session::createIODelegate(const std::string& format)
{
(void)format;
if (format == "json")
{
return SessionIOJSON::create();
}
return SessionIOPtr();
}
......
......@@ -9,10 +9,20 @@
//=========================================================================
#include "smtk/model/SessionIOJSON.h"
#include "smtk/attribute/FileItem.h"
#include "smtk/attribute/IntItem.h"
#include "smtk/common/UUID.h"
#include "smtk/io/ExportJSON.h"
#include "smtk/io/ExportJSON.txx"
#include "smtk/io/ImportJSON.h"
#include "smtk/model/Manager.h"
#include "smtk/model/Operator.h"
#include "boost/filesystem.hpp"
#include "cJSON.h"
using namespace boost::filesystem;
namespace smtk {
namespace model {
......@@ -20,21 +30,169 @@ namespace smtk {
*
* Subclasses should return 1 on success and 0 on failure.
*/
int SessionIOJSON::importJSON(ManagerPtr modelMgr, cJSON* sessionRec)
int SessionIOJSON::importJSON(ManagerPtr modelMgr,
const SessionPtr& session,
cJSON* sessionRec,
bool loadNativeModels)
{
(void)modelMgr;
(void)sessionRec;
return 1;
smtk::common::UUIDs models =
modelMgr->entitiesMatchingFlags(smtk::model::MODEL_ENTITY);
cJSON* modelsObj = cJSON_GetObjectItem(sessionRec, "models");
if (!modelsObj)
{
smtkInfoMacro(modelMgr->log(), "Expecting a \"models\" entry!");
return 0;
}
std::map<smtk::common::UUID, std::string> existingURLs;
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;
}
// import native model if the model does not exist;
// NOTE: what should we do if it already exists? erase then re-load
// the original model from file (stored in string property "url")?
// Else, just import meta info
if(models.find(modelid) == models.end())
{
// find the model entry, and get the native model file name if it exists,
// by looking at "output_native_url" property
for (cJSON* curChild = modelentry->child; curChild; curChild = curChild->next)
{
if (!curChild->string || !curChild->string[0])
{
continue;
}
// find the model id in dictionary
if (smtk::common::UUID(curChild->string) != modelid)
{
continue;
}
// failed to load properties is still OK
smtk::io::ImportJSON::ofManagerStringProperties(modelid, curChild, modelMgr);
break;
}
if(loadNativeModels)
{
std::string nativemodelfile;
std::string nativefilekey = modelMgr->hasStringProperty(modelid, "output_native_url") ?
"output_native_url" :
(modelMgr->hasStringProperty(modelid, "url") ? "url" : "");
if (!nativefilekey.empty())
{
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);
}
}
}
else if(modelMgr->hasStringProperty(modelid, "url"))
{
smtk::model::StringList const& nprop(modelMgr->stringProperty(modelid, "url"));
if (!nprop.empty())
{
existingURLs[modelid] = nprop[0];
}
}
}
int status = this->loadModelsRecord(modelMgr, sessionRec);
status &= this->loadMeshesRecord(modelMgr, sessionRec);
// recover "url" property for models already loaded
std::map<smtk::common::UUID, std::string>::const_iterator mit;
for(mit = existingURLs.begin(); mit != existingURLs.end(); ++mit)
{
modelMgr->setStringProperty(mit->first, "url", mit->second);
}
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);
}
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)
{