Skip to content

Commit

Permalink
Add ResourceRetriever::getFilePath() (#972)
Browse files Browse the repository at this point in the history
  • Loading branch information
jslee02 authored Feb 12, 2018
1 parent 88e5186 commit a4208af
Show file tree
Hide file tree
Showing 16 changed files with 417 additions and 59 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

### DART 6.4.0 (201X-XX-XX)

* Common

* Added ResourceRetriever::getFilePath(): [#972](https://github.com/dartsim/dart/pull/972)

* Kinematics/Dynamics

* Added lazy evaluation for shape's volume and bounding-box computation: [#959](https://github.com/dartsim/dart/pull/959)
Expand Down
27 changes: 19 additions & 8 deletions dart/common/LocalResourceRetriever.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,7 @@ namespace common {
//==============================================================================
bool LocalResourceRetriever::exists(const Uri& _uri)
{
// Open and close the file to check if it exists. It would be more efficient
// to stat() it, but that is not portable.
if(_uri.mScheme.get_value_or("file") != "file")
return false;
else if (!_uri.mPath)
return false;

return std::ifstream(_uri.getFilesystemPath(), std::ios::binary).good();
return !getFilePath(_uri).empty();
}

//==============================================================================
Expand All @@ -70,5 +63,23 @@ common::ResourcePtr LocalResourceRetriever::retrieve(const Uri& _uri)
return nullptr;
}

//==============================================================================
std::string LocalResourceRetriever::getFilePath(const Uri& uri)
{
// Open and close the file to check if it exists. It would be more efficient
// to stat() it, but that is not portable.
if(uri.mScheme.get_value_or("file") != "file")
return "";
else if (!uri.mPath)
return "";

const auto path = uri.getFilesystemPath();

if (std::ifstream(path, std::ios::binary).good())
return path;
else
return "";
}

} // namespace common
} // namespace dart
3 changes: 3 additions & 0 deletions dart/common/LocalResourceRetriever.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ class LocalResourceRetriever : public virtual ResourceRetriever

// Documentation inherited.
ResourcePtr retrieve(const Uri& _uri) override;

// Documentation inherited.
std::string getFilePath(const Uri& uri) override;
};

using LocalResourceRetrieverPtr = std::shared_ptr<LocalResourceRetriever>;
Expand Down
6 changes: 6 additions & 0 deletions dart/common/ResourceRetriever.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,5 +53,11 @@ std::string ResourceRetriever::readAll(const Uri& uri)
return resource->readAll();
}

//==============================================================================
std::string ResourceRetriever::getFilePath(const Uri& /*uri*/)
{
return "";
}

} // namespace common
} // namespace dart
19 changes: 12 additions & 7 deletions dart/common/ResourceRetriever.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,10 @@ class ResourceRetriever
public:
virtual ~ResourceRetriever() = default;

/// \brief Return whether the resource specified by a URI exists.
/// Returns whether the resource specified by a URI exists.
virtual bool exists(const Uri& _uri) = 0;

/// \brief Return the resource specified by a URI or nullptr on failure.
/// Returns the resource specified by a URI or nullptr on failure.
virtual ResourcePtr retrieve(const Uri& _uri) = 0;

/// Reads all data from the resource of uri, and returns it as a string.
Expand All @@ -61,11 +61,16 @@ class ResourceRetriever
/// \throw std::runtime_error when failed to read sucessfully.
virtual std::string readAll(const Uri& uri);

// We don't const-qualify for exists, retrieve, and readAll here. Derived
// classes of ResourceRetriever will be interacting with external resources
// that you don't necessarily have control over so we cannot guarantee that
// you get the same result every time with the same input Uri. Indeed,
// const-qualification for those functions is pointless.
/// Returns absolute file path to \c uri; an empty string if unavailable.
///
/// This base class returns an empty string by default.
virtual std::string getFilePath(const Uri& uri);

// We don't const-qualify for exists, retrieve, readAll, and getFilePath here.
// Derived classes of ResourceRetriever will be interacting with external
// resources that you don't necessarily have control over so we cannot
// guarantee that you get the same result every time with the same input Uri.
// Indeed, const-qualification for those functions is pointless.
};

using ResourceRetrieverPtr = std::shared_ptr<ResourceRetriever>;
Expand Down
13 changes: 13 additions & 0 deletions dart/utils/CompositeResourceRetriever.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,19 @@ common::ResourcePtr CompositeResourceRetriever::retrieve(
return nullptr;
}

//==============================================================================
std::string CompositeResourceRetriever::getFilePath(const common::Uri& uri)
{
for (const auto& resourceRetriever : getRetrievers(uri))
{
const auto path = resourceRetriever->getFilePath(uri);
if (!path.empty())
return path;
}

return "";
}

//==============================================================================
std::vector<common::ResourceRetrieverPtr>
CompositeResourceRetriever::getRetrievers(const common::Uri& _uri) const
Expand Down
3 changes: 3 additions & 0 deletions dart/utils/CompositeResourceRetriever.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@ class CompositeResourceRetriever : public virtual common::ResourceRetriever
// Documentation inherited.
common::ResourcePtr retrieve(const common::Uri& _uri) override;

// Documentation inherited.
std::string getFilePath(const common::Uri& uri) override;

private:
std::vector<common::ResourceRetrieverPtr> getRetrievers(
const common::Uri& _uri) const;
Expand Down
33 changes: 33 additions & 0 deletions dart/utils/DartResourceRetriever.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,39 @@ common::ResourcePtr DartResourceRetriever::retrieve(const common::Uri& uri)
return nullptr;
}

//==============================================================================
std::string DartResourceRetriever::getFilePath(const common::Uri& uri)
{
std::string relativePath;
if (!resolveDataUri(uri, relativePath))
return "";

if (uri.mAuthority.get() == "sample")
{
for (const auto& dataPath : mDataDirectories)
{
common::Uri fileUri;
fileUri.fromPath(dataPath + relativePath);

const auto path = mLocalRetriever->getFilePath(fileUri);

// path is empty if the file specified by fileUri doesn't exist.
if (!path.empty())
return path;
}
}
else
{
const auto path = mLocalRetriever->getFilePath(uri);

// path is empty if the file specified by fileUri doesn't exist.
if (!path.empty())
return path;
}

return "";
}

//==============================================================================
void DartResourceRetriever::addDataDirectory(
const std::string& dataDirectory)
Expand Down
3 changes: 3 additions & 0 deletions dart/utils/DartResourceRetriever.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,9 @@ class DartResourceRetriever : public common::ResourceRetriever
// Documentation inherited.
common::ResourcePtr retrieve(const common::Uri& uri) override;

// Documentation inherited.
std::string getFilePath(const common::Uri& uri) override;

private:

void addDataDirectory(const std::string& packageDirectory);
Expand Down
25 changes: 24 additions & 1 deletion dart/utils/PackageResourceRetriever.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,14 +73,15 @@ bool PackageResourceRetriever::exists(const common::Uri& _uri)
if (!resolvePackageUri(_uri, packageName, relativePath))
return false;

for(const std::string& packagePath : getPackagePaths(packageName))
for (const std::string& packagePath : getPackagePaths(packageName))
{
common::Uri fileUri;
fileUri.fromPath(packagePath + relativePath);

if (mLocalRetriever->exists(fileUri))
return true;
}

return false;
}

Expand All @@ -102,6 +103,28 @@ common::ResourcePtr PackageResourceRetriever::retrieve(const common::Uri& _uri)
return nullptr;
}

//==============================================================================
std::string PackageResourceRetriever::getFilePath(const common::Uri& uri)
{
std::string packageName, relativePath;
if (!resolvePackageUri(uri, packageName, relativePath))
return "";

for(const std::string& packagePath : getPackagePaths(packageName))
{
common::Uri fileUri;
fileUri.fromPath(packagePath + relativePath);

const auto path = mLocalRetriever->getFilePath(fileUri);

// path is empty if the file specified by fileUri doesn't exist.
if (!path.empty())
return path;
}

return "";
}

//==============================================================================
const std::vector<std::string>& PackageResourceRetriever::getPackagePaths(
const std::string& _packageName) const
Expand Down
3 changes: 3 additions & 0 deletions dart/utils/PackageResourceRetriever.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,9 @@ class PackageResourceRetriever : public virtual common::ResourceRetriever
// Documentation inherited.
common::ResourcePtr retrieve(const common::Uri& _uri) override;

// Documentation inherited.
std::string getFilePath(const common::Uri& uri) override;

private:
common::ResourceRetrieverPtr mLocalRetriever;
std::unordered_map<std::string, std::vector<std::string> > mPackageMap;
Expand Down
14 changes: 14 additions & 0 deletions unittests/TestHelpers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -505,13 +505,20 @@ struct PresentResourceRetriever : public dart::common::ResourceRetriever
return true;
}

std::string getFilePath(const dart::common::Uri& _uri) override
{
mGetFilePath.push_back(_uri.toString());
return _uri.toString();
}

dart::common::ResourcePtr retrieve(const dart::common::Uri& _uri) override
{
mRetrieve.push_back(_uri.toString());
return std::make_shared<TestResource>();
}

std::vector<std::string> mExists;
std::vector<std::string> mGetFilePath;
std::vector<std::string> mRetrieve;
};

Expand All @@ -524,13 +531,20 @@ struct AbsentResourceRetriever : public dart::common::ResourceRetriever
return false;
}

std::string getFilePath(const dart::common::Uri& _uri) override
{
mGetFilePath.push_back(_uri.toString());
return "";
}

dart::common::ResourcePtr retrieve(const dart::common::Uri& _uri) override
{
mRetrieve.push_back(_uri.toString());
return nullptr;
}

std::vector<std::string> mExists;
std::vector<std::string> mGetFilePath;
std::vector<std::string> mRetrieve;
};

Expand Down
82 changes: 82 additions & 0 deletions unittests/unit/test_CompositeResourceRetriever.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,88 @@ TEST(CompositeResourceRetriever, exists_DefaultResourceRetrieverSucceeds_Returns
EXPECT_TRUE(retriever3->mRetrieve.empty());
}

TEST(CompositeResourceRetriever, getFilePath_NothingRegistered_ReturnsEmptyString)
{
CompositeResourceRetriever retriever;
EXPECT_EQ(retriever.getFilePath(Uri::createFromString("package://test/foo")), "");
}

TEST(CompositeResourceRetriever, getFilePath_AllRetrieversFail_ReturnsFalse)
{
auto retriever1 = std::make_shared<AbsentResourceRetriever>();
auto retriever2 = std::make_shared<AbsentResourceRetriever>();
CompositeResourceRetriever retriever;

EXPECT_TRUE(retriever.addSchemaRetriever("package", retriever1));
retriever.addDefaultRetriever(retriever2);

EXPECT_EQ(retriever.getFilePath(Uri::createFromString("package://test/foo")), "");

EXPECT_TRUE(retriever1->mExists.empty());
ASSERT_EQ(1u, retriever1->mGetFilePath.size());
EXPECT_EQ("package://test/foo", retriever1->mGetFilePath.front());
EXPECT_TRUE(retriever1->mRetrieve.empty());

EXPECT_TRUE(retriever2->mExists.empty());
ASSERT_EQ(1u, retriever2->mGetFilePath.size());
EXPECT_EQ("package://test/foo", retriever2->mGetFilePath.front());
EXPECT_TRUE(retriever2->mRetrieve.empty());
}

TEST(CompositeResourceRetriever, getFilePath_CompositeResourceRetrieverSucceeds_ReturnsFilePath)
{
auto retriever1 = std::make_shared<PresentResourceRetriever>();
auto retriever2 = std::make_shared<AbsentResourceRetriever>();
auto retriever3 = std::make_shared<AbsentResourceRetriever>();
CompositeResourceRetriever retriever;

EXPECT_TRUE(retriever.addSchemaRetriever("package", retriever1));
EXPECT_TRUE(retriever.addSchemaRetriever("package", retriever2));
retriever.addDefaultRetriever(retriever3);

EXPECT_EQ(retriever.getFilePath(Uri::createFromString("package://test/foo")), "package://test/foo");

EXPECT_TRUE(retriever2->mExists.empty());
ASSERT_EQ(1u, retriever1->mGetFilePath.size());
EXPECT_EQ("package://test/foo", retriever1->mGetFilePath.front());
EXPECT_TRUE(retriever1->mRetrieve.empty());

EXPECT_TRUE(retriever2->mExists.empty());
EXPECT_TRUE(retriever2->mGetFilePath.empty());
EXPECT_TRUE(retriever2->mRetrieve.empty());
EXPECT_TRUE(retriever3->mExists.empty());
EXPECT_TRUE(retriever3->mGetFilePath.empty());
EXPECT_TRUE(retriever3->mRetrieve.empty());
}

TEST(CompositeResourceRetriever, getFilePath_DefaultResourceRetrieverSucceeds_ReturnsFilePath)
{
auto retriever1 = std::make_shared<AbsentResourceRetriever>();
auto retriever2 = std::make_shared<PresentResourceRetriever>();
auto retriever3 = std::make_shared<AbsentResourceRetriever>();
CompositeResourceRetriever retriever;

EXPECT_TRUE(retriever.addSchemaRetriever("package", retriever1));
retriever.addDefaultRetriever(retriever2);
retriever.addDefaultRetriever(retriever3);

EXPECT_EQ(retriever.getFilePath(Uri::createFromString("package://test/foo")), "package://test/foo");

EXPECT_TRUE(retriever1->mExists.empty());
ASSERT_EQ(1u, retriever1->mGetFilePath.size());
EXPECT_EQ("package://test/foo", retriever1->mGetFilePath.front());
EXPECT_TRUE(retriever1->mRetrieve.empty());

EXPECT_TRUE(retriever2->mExists.empty());
ASSERT_EQ(1u, retriever2->mGetFilePath.size());
EXPECT_EQ("package://test/foo", retriever2->mGetFilePath.front());
EXPECT_TRUE(retriever2->mRetrieve.empty());

EXPECT_TRUE(retriever3->mExists.empty());
EXPECT_TRUE(retriever3->mGetFilePath.empty());
EXPECT_TRUE(retriever3->mRetrieve.empty());
}

TEST(CompositeResourceRetriever, retrieve_NothingRegistered_ReturnsNull)
{
CompositeResourceRetriever retriever;
Expand Down
Loading

0 comments on commit a4208af

Please sign in to comment.