Commit 7455cf63 authored by Yumin Yuan's avatar Yumin Yuan Committed by Kitware Robot

Merge topic 'relative-path-and-url'

043b8db5 Use canonical path when possible
9af4df5d Made exodus sessionIO saved url records consistent
6b6a2ec8 Make displayed url shown as absolute path after loading smtk model
55ac73f2 Made loading and writing mesh collections also handle relative path.
6f62805d Added FileLocation class for handling relative path
Acked-by: Kitware Robot's avatarKitware Robot <kwrobot@kitware.com>
Acked-by: Robert Maynard's avatarRobert Maynard <robert.maynard@kitware.com>
Merge-request: !46
parents 7729d1c0 043b8db5
......@@ -61,7 +61,7 @@ int SessionIOJSON::loadExodusFileWithUUIDs(
path tryme = this->referencePath() / absURL;
if (exists(tryme))
{
absURL = tryme;
absURL = canonical(tryme, this->referencePath());
}
}
......@@ -193,6 +193,8 @@ int SessionIOJSON::exportJSON(model::ManagerPtr modelMgr, const model::SessionPt
url = tryme.string();
}
}
// set the url property to be consistent with "modelFiles" record when written out
mit->setStringProperty("url", url.string());
modelFiles.insert(url.string());
}
}
......
# set up sources to build
set(commonSrcs
Environment.cxx
FileLocation.cxx
Paths.cxx
Resource.cxx
ResourceSet.cxx
......@@ -12,6 +13,7 @@ set(commonSrcs
set(commonHeaders
Environment.h
FileLocation.h
Paths.h
Resource.h
ResourceSet.h
......
//=========================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
//
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//=========================================================================
// .NAME smtkFileLocation.cxx - A convenient class for smtk file locations
// .SECTION Description
// .SECTION See Also
#include "smtk/common/FileLocation.h"
#include "boost/filesystem.hpp"
#include "boost/system/error_code.hpp"
using namespace boost::filesystem;
namespace smtk {
namespace common {
//----------------------------------------------------------------------------
FileLocation::FileLocation(
const std::string& filePath,
const std::string& refPath) :
m_filePath(filePath),
m_referencePath(refPath)
{
}
FileLocation::FileLocation(const FileLocation& other)
{
this->m_filePath = other.m_filePath;
this->m_referencePath = other.m_referencePath;
}
//----------------------------------------------------------------------------
bool FileLocation::operator == (const FileLocation &from) const
{
// just doing a simple string comparison, should we also verify the file
return ( m_filePath == from.m_filePath ) &&
( m_referencePath == from.m_referencePath );
}
//----------------------------------------------------------------------------
std::string FileLocation::absolutePath() const
{
path absPath(this->m_filePath);
if (!this->m_referencePath.empty() && !absPath.is_absolute())
{
absPath = this->m_referencePath / absPath;
if(exists(absPath))
{
// remove potential ".." from the path
absPath = canonical(absPath, this->m_referencePath);
}
}
return absPath.is_absolute() ? absPath.string() : std::string();
}
//----------------------------------------------------------------------------
std::string FileLocation::relativePath() const
{
path url(this->m_filePath);
if (!this->m_referencePath.empty() && url.is_absolute())
{
boost::system::error_code err;
path tryme = relative(url, this->m_referencePath, err);
if (err == boost::system::errc::success)
{
url = tryme;
}
}
return url.is_absolute() ? url.relative_path().string() : url.string();
}
//----------------------------------------------------------------------------
std::string FileLocation::referencePath() const
{
return this->m_referencePath;
}
} // namespace common
} // namespace smtk
//=========================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
//
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//=========================================================================
// .NAME smtkFileLocation.h - A class for SMTK file locations
// .SECTION Description
// This class will allow user specify the path of a file and a reference
// path that a relative path w.r.t the reference path can be constructed.
// This is useful when we try to export a json file (.smtk file) that will
// include files for the native models and meshes, which should be relative
// to the json (.smtk) file location, so that all the files can be shared
// easily with other users.
// .SECTION See Also
#ifndef __smtk_common_FileLocation_h
#define __smtk_common_FileLocation_h
#include "smtk/CoreExports.h"
#include <string>
namespace smtk
{
namespace common
{
class SMTKCORE_EXPORT FileLocation
{
public:
FileLocation()
{
m_filePath = std::string();
m_referencePath = std::string();
}
FileLocation(const std::string& filePath,
const std::string& refPath = std::string());
FileLocation(const FileLocation& other);
virtual ~FileLocation() { }
std::string absolutePath() const;
std::string relativePath() const;
std::string referencePath() const;
bool empty() const
{
return this->m_filePath.empty();
}
void clear()
{
m_filePath.clear();
m_referencePath.clear();
}
FileLocation &operator=(const FileLocation &from)
{
m_filePath = from.m_filePath;
m_referencePath = from.m_referencePath;
return *this;
}
bool operator==(const FileLocation &from) const;
bool operator==(const std::string &from) const
{
return *this == FileLocation(from);
}
protected:
std::string m_filePath;
std::string m_referencePath;
};
}
}
#endif /* __smtk_common_FileLocation_h */
......@@ -189,7 +189,7 @@ OperatorResult MeshOperator::operateInternal()
smtk::common::UUID collectionUUID = i->first;
if( existingCollections.find(collectionUUID) == existingCollections.end())
{ //found a new collection
std::string location = collection->readLocation();
std::string location = collection->readLocation().absolutePath();
if(!location.empty())
{ //delete the file if it exists
::boost::filesystem::path cpath( location );
......
......@@ -1062,7 +1062,13 @@ int ExportJSON::forSingleCollection(cJSON* mdesc,
//if it should use the type, or fall back to the json interface
if(!collection->writeLocation().empty())
{
const std::string& fileWriteLocation = collection->writeLocation();
// if there is a reference path, write out the relative path to it;
// otherwise, write out the absolute path
const std::string& fileWriteLocation =
collection->writeLocation().referencePath().empty() ?
collection->writeLocation().absolutePath() :
collection->writeLocation().relativePath();
cJSON_AddStringToObject(jsonCollection, "location", fileWriteLocation.c_str() );
smtk::io::WriteMesh::entireCollection(collection);
}
......
......@@ -32,6 +32,9 @@
#include "smtk/io/Logger.h"
#include "smtk/io/ImportMesh.h"
#include "boost/filesystem.hpp"
#include "boost/system/error_code.hpp"
#include "cJSON.h"
#include <stdio.h>
......@@ -44,6 +47,7 @@
using namespace smtk::io;
using namespace smtk::common;
using namespace smtk::model;
using namespace boost::filesystem;
// Some cJSON helpers
namespace {
......@@ -1059,8 +1063,8 @@ int ImportJSON::ofLog(cJSON* logrecordarray, smtk::io::Logger& log)
*
*/
int ImportJSON::ofMeshesOfModel(cJSON* node,
smtk::model::ManagerPtr modelMgr)
smtk::model::ManagerPtr modelMgr,
const std::string& refPath)
{
int status = 1;
if (!node || !modelMgr)
......@@ -1117,7 +1121,16 @@ int ImportJSON::ofMeshesOfModel(cJSON* node,
//get the file_path from json
std::string file_path;
cJSON_GetStringValue(fLocationNode, file_path);
importedCollection = smtk::io::ImportMesh::entireFile(file_path, meshMgr);
path absPath(file_path);
if (!refPath.empty() && !absPath.is_absolute())
{
path tryme = refPath / absPath;
if (exists(tryme))
{
absPath = canonical(tryme, refPath);
}
}
importedCollection = smtk::io::ImportMesh::entireFile(absPath.string(), meshMgr);
}
//wasnt moab, or failed to load as moab
......@@ -1142,7 +1155,6 @@ int ImportJSON::ofMeshesOfModel(cJSON* node,
collection = meshMgr->makeCollection(uid, importedCollection->interface());
}
//remove the old collection, as its interface is now owned by the new
//collection
meshMgr->removeCollection(importedCollection);
......
......@@ -63,7 +63,8 @@ public:
static int ofLog(cJSON* logrecordarray, smtk::io::Logger& log);
//write all mesh collections that have associations to a model
static int ofMeshesOfModel(cJSON* node, smtk::model::ManagerPtr modelMgr);
static int ofMeshesOfModel(cJSON* node, smtk::model::ManagerPtr modelMgr,
const std::string& refPath = std::string());
//write all mesh properties for the collection
static int ofMeshProperties(cJSON* node, smtk::mesh::CollectionPtr collection);
// Mid-level helpers:
......
......@@ -23,7 +23,7 @@ bool WriteMesh::entireCollection(smtk::mesh::CollectionPtr collection)
{ //require a file location to write too
return false;
}
return smtk::mesh::moab::write(collection->writeLocation(), collection);
return smtk::mesh::moab::write(collection->writeLocation().absolutePath(), collection);
}
bool WriteMesh::onlyDomain(smtk::mesh::CollectionPtr collection)
......@@ -32,7 +32,7 @@ bool WriteMesh::onlyDomain(smtk::mesh::CollectionPtr collection)
{ //require a file location to write too
return false;
}
return smtk::mesh::moab::write_domain(collection->writeLocation(), collection);
return smtk::mesh::moab::write_domain(collection->writeLocation().absolutePath(), collection);
}
bool WriteMesh::onlyNeumann(smtk::mesh::CollectionPtr collection)
......@@ -41,7 +41,7 @@ bool WriteMesh::onlyNeumann(smtk::mesh::CollectionPtr collection)
{ //require a file location to write too
return false;
}
return smtk::mesh::moab::write_neumann(collection->writeLocation(), collection);
return smtk::mesh::moab::write_neumann(collection->writeLocation().absolutePath(), collection);
}
bool WriteMesh::onlyDirichlet(smtk::mesh::CollectionPtr collection)
......@@ -50,7 +50,7 @@ bool WriteMesh::onlyDirichlet(smtk::mesh::CollectionPtr collection)
{ //require a file location to write too
return false;
}
return smtk::mesh::moab::write_dirichlet(collection->writeLocation(), collection);
return smtk::mesh::moab::write_dirichlet(collection->writeLocation().absolutePath(), collection);
}
bool WriteMesh::entireCollection(const std::string& filePath,
......
......@@ -171,13 +171,13 @@ bool Collection::assignUniqueNameIfNotAlready()
}
//----------------------------------------------------------------------------
const std::string& Collection::readLocation() const
const smtk::common::FileLocation& Collection::readLocation() const
{
return this->m_readLocation;
}
//----------------------------------------------------------------------------
void Collection::readLocation(const std::string& n)
void Collection::readLocation(const smtk::common::FileLocation& n)
{
this->m_readLocation = n;
//if the write location hasn't been set, update it to be the read location
......@@ -188,13 +188,13 @@ void Collection::readLocation(const std::string& n)
}
//----------------------------------------------------------------------------
const std::string& Collection::writeLocation() const
const smtk::common::FileLocation& Collection::writeLocation() const
{
return this->m_writeLocation;
}
//----------------------------------------------------------------------------
void Collection::writeLocation(const std::string& n)
void Collection::writeLocation(const smtk::common::FileLocation& n)
{
this->m_writeLocation = n;
}
......@@ -206,7 +206,6 @@ void Collection::clearReadWriteLocations()
this->m_writeLocation.clear();
}
//----------------------------------------------------------------------------
std::string Collection::interfaceName() const
{
......
......@@ -16,6 +16,7 @@
#include "smtk/PublicPointerDefs.h"
#include "smtk/common/UUID.h"
#include "smtk/common/FileLocation.h"
#include "smtk/mesh/CellSet.h"
#include "smtk/mesh/PointConnectivity.h"
......@@ -82,13 +83,15 @@ public:
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;
//will return an empty FileLocation if this collection wasn't read from file
const smtk::common::FileLocation& readLocation() const;
//set the file that this collection should be saved to.
//By default this is set to be the same as the readLocation()
void writeLocation(const std::string& path);
const std::string& writeLocation() const;
void writeLocation(const smtk::common::FileLocation& path);
void writeLocation(const std::string& path)
{ this->writeLocation(smtk::common::FileLocation(path)); }
const smtk::common::FileLocation& writeLocation() const;
//clear both the read and write locations for the collection. This
//is generally done when de-serializing a collection and the read and write
......@@ -278,7 +281,9 @@ private:
Collection& operator=( const Collection& other ); //blank since we are used by shared_ptr
//Sets the location that this collection was loaded from
void readLocation(const std::string& path);
void readLocation(const std::string& path)
{ this->readLocation(smtk::common::FileLocation(path)); }
void readLocation(const smtk::common::FileLocation& path);
//Swap the internal interfaces between this Collection and another Collection
//this is how we can easily update a collection that has already been
......@@ -295,8 +300,8 @@ private:
smtk::common::UUID m_entity;
std::string m_name;
std::string m_readLocation;
std::string m_writeLocation;
smtk::common::FileLocation m_readLocation;
smtk::common::FileLocation m_writeLocation;
smtk::model::WeakManagerPtr m_modelManager;
smtk::shared_ptr<MeshFloatData> m_floatData;
......
......@@ -99,8 +99,14 @@ int SessionIOJSON::importJSON(ManagerPtr modelMgr,
if(!nativemodelfile.empty())
{
// failed to load native model is still ok
this->loadNativeModel(modelMgr, session, nativemodelfile);
// failed to load native model is still ok;
// If the model is loaded successfully, we need to cache the loadedURL so that we
// can recover it because loadModelsRecord may set the "url" to something else
std::string loadedURL;
if(this->loadNativeModel(modelMgr, session, nativemodelfile, loadedURL))
{
existingURLs[modelid] = loadedURL;
}
}
}
}
......@@ -176,7 +182,8 @@ int SessionIOJSON::loadMeshesRecord(ManagerPtr modelMgr,
smtkInfoMacro(modelMgr->log(), "Expecting a \"mesh_collections\" entry!");
return 1;
}
return smtk::io::ImportJSON::ofMeshesOfModel(sessionRec, modelMgr);
return smtk::io::ImportJSON::ofMeshesOfModel(sessionRec, modelMgr,
this->referencePath());
}
/**\brief Encode information into \a sessionRec for the given \a modelMgr.
......@@ -318,7 +325,8 @@ std::string SessionIOJSON::getOutputFileNameForNativeModel(
*/
int SessionIOJSON::loadNativeModel(smtk::model::ManagerPtr modelMgr,
const smtk::model::SessionPtr& sess,
const std::string& inNativeFile)
const std::string& inNativeFile,
std::string& loadedURL)
{
// if this is not a valid session, return;
if(!sess)
......@@ -342,7 +350,7 @@ int SessionIOJSON::loadNativeModel(smtk::model::ManagerPtr modelMgr,
path tryme = this->referencePath() / actualFilename;
if (exists(tryme))
{
actualFilename = tryme;
actualFilename = canonical(tryme, this->referencePath());
}
}
readOp->specification()->findFile("filename")->setValue(actualFilename.string());
......@@ -353,6 +361,7 @@ int SessionIOJSON::loadNativeModel(smtk::model::ManagerPtr modelMgr,
smtkInfoMacro(modelMgr->log(), "Failed to read the model for native kernel!");
return 0;
}
loadedURL = actualFilename.string();
return 1;
}
......
......@@ -45,7 +45,8 @@ protected:
std::string& outNativeFile);
virtual int loadNativeModel(smtk::model::ManagerPtr modelMgr,
const smtk::model::SessionPtr& sess,
const std::string& inNativeFile);
const std::string& inNativeFile,
std::string& loadedURL);
virtual std::string getOutputFileNameForNativeModel(
smtk::model::ManagerPtr modelMgr,
const smtk::model::SessionPtr& sess,
......
......@@ -64,10 +64,10 @@ smtk::model::OperatorResult ExportSMTKModel::operateInternal()
// Add the output smtk model name to the model "smtk_url", so that the individual session can
// use that name to construct a filename for saving native models of the session.
smtk::model::Models::const_iterator modit;
smtk::model::Models::iterator modit;
for(modit = models.begin(); modit != models.end(); ++modit)
{
this->manager()->setStringProperty(modit->entity(), "smtk_url", filename);
modit->setStringProperty("smtk_url", filename);
// we also want to write out the meshes to new "write_locations"
std::vector<smtk::mesh::CollectionPtr> collections =
......@@ -78,7 +78,8 @@ smtk::model::OperatorResult ExportSMTKModel::operateInternal()
std::ostringstream outmeshname;
outmeshname << smtkfilename << "_" << (*cit)->name() << ".h5m";
std::string write_path = (path(smtkfilepath) / path(outmeshname.str())).string();
(*cit)->writeLocation(write_path);
smtk::common::FileLocation wfLocation(write_path, smtkfilepath);
(*cit)->writeLocation(wfLocation);
}
}
......@@ -93,6 +94,27 @@ smtk::model::OperatorResult ExportSMTKModel::operateInternal()
cJSON_Delete(top);
jsonFile.close();
// Now we need to do some work to reset the url property of models since
// during export, the property may be changed to be relative path, and we want
// to set it back to be absolute path to display
if(!smtkfilepath.empty())
{
for(modit = models.begin(); modit != models.end(); ++modit)
{
if(modit->hasStringProperty("url"))
{
path url(modit->stringProperty("url")[0]);
if (!url.string().empty() && !url.is_absolute())
{
url = smtkfilepath / url;
url = canonical(url, smtkfilepath);
// set the url property to be consistent with "modelFiles" record when written out
modit->setStringProperty("url", url.string());
}
}
}
}
return this->createResult(smtk::model::OPERATION_SUCCEEDED);
}
......
......@@ -14,12 +14,9 @@
Export models in SMTK's native JSON format.
</DetailedDescription>
<ItemDefinitions>
<File Name="filename" Label="SMTK Model File Name" NumberOfRequiredValues="1">
<File Name="filename" Label="SMTK Model File Name " FileFilters="SMTK Model (*.smtk);;All files (*.*)" NumberOfRequiredValues="1">
<BriefDescription>The destination file for the JSON.</BriefDescription>
</File>
<File Name="nativemodelfilename" Label="Native Model File Name" NumberOfRequiredValues="1">
<BriefDescription>The destination file for the native model.</BriefDescription>
</File>
</ItemDefinitions>
</AttDef>
<!-- Result -->
......
......@@ -337,8 +337,6 @@
<suppress-warning text="skipping function 'smtk::model::MeshListPhrase::shared_from_this', unmatched return type 'smtk::shared_ptr&lt;smtk::model::MeshListPhrase::SelfType&gt;'"/>
<suppress-warning text="skipping function 'smtk::model::MeshListPhrase::shared_from_this', unmatched return type 'smtk::shared_ptr&lt;const smtk::model::MeshListPhrase::SelfType&gt;'"/>
<suppress-warning text="skipping field 'DescriptivePhrase::m_delegate' with unmatched type 'smtk::shared_ptr&lt;SubphraseGenerator&gt;'"/>
<suppress-warning text="skipping function 'smtk::attribute::ValueItemTemplate::setValue', unmatched parameter type 'size_t'"/>
<suppress-warning text="skipping function 'smtk::attribute::ValueItemTemplate::concreteDefinition', unmatched return type 'shared_ptr&lt;const smtk::attribute::ValueItemTemplate&lt;DataT&gt;::DefType&gt;"/>
......@@ -392,7 +390,10 @@
<suppress-warning text="skipping function 'smtk::io::MeshExport3DM::write', unmatched parameter type 'std::ostream&amp;'"/>
<suppress-warning text="template baseclass 'std::bitset&lt;CellType_MAX&gt;' of 'CellTypes' is not known"/>
<suppress-warning text="skipping function 'smtk::mesh::Collection::interface', unmatched return type 'smtk::mesh::InterfacePtr const&amp;'"/>
<suppress-warning text="skipping function 'smtk::mesh::Collection::readLocation', unmatched return type 'smtk::common::FileLocation const&amp;'"/>
<suppress-warning text="skipping function 'smtk::mesh::Collection::readLocation', unmatched parameter type 'smtk::common::FileLocation const&amp;'"/>
<suppress-warning text="skipping function 'smtk::mesh::Collection::writeLocation', unmatched parameter type 'smtk::common::FileLocation const&amp;'"/>
<suppress-warning text="skipping function 'smtk::mesh::Collection::writeLocation', unmatched return type 'smtk::common::FileLocation const&amp;'"/>
<suppress-warning text="skipping field 'Manager::m_conditionTriggers' with unmatched type 'std::set&lt;ConditionTrigger&gt;'"/>
<suppress-warning text="skipping field 'Manager::m_oneToOneTriggers' with unmatched type 'std::set&lt;OneToOneTrigger&gt;'"/>
......
Markdown is supported
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