From 047ef2d92318148bd6eb62191447c4ac9055a864 Mon Sep 17 00:00:00 2001 From: fgerlits Date: Wed, 17 May 2006 14:57:38 +0000 Subject: [PATCH] added a SearchCriteria constructor from an XmlRpcValue; this closes #1679 --- .../include/LiveSupport/Core/SearchCriteria.h | 37 ++++- .../src/modules/core/src/SearchCriteria.cxx | 127 +++++++++++++++++- .../modules/core/src/SearchCriteriaTest.cxx | 37 +++++ .../src/modules/core/src/SearchCriteriaTest.h | 9 ++ 4 files changed, 202 insertions(+), 8 deletions(-) diff --git a/livesupport/src/modules/core/include/LiveSupport/Core/SearchCriteria.h b/livesupport/src/modules/core/include/LiveSupport/Core/SearchCriteria.h index 854809473..4621a8371 100644 --- a/livesupport/src/modules/core/include/LiveSupport/Core/SearchCriteria.h +++ b/livesupport/src/modules/core/include/LiveSupport/Core/SearchCriteria.h @@ -180,6 +180,16 @@ class SearchCriteria */ friend class LiveSupport::StorageClient::TestStorageClient; + /** + * Add a search condition. + * + * @param xmlRpcValue the condition to add. + * @exception std::invalid_argument on syntax errors. + */ + void + addCondition(const XmlRpc::XmlRpcValue & xmlRpcValue) + throw(std::invalid_argument); + public: @@ -189,6 +199,7 @@ class SearchCriteria * * @param type one of "audioClip" (default), "playlist" or "all" * @param logicalOperator either "and" (default) or "or" + * @exception std::invalid_argument on syntax errors. */ SearchCriteria(const std::string & type = "all", const std::string & logicalOperator = "and") @@ -207,6 +218,7 @@ class SearchCriteria * @param comparisonOperator one of "=", "partial", "prefix", * "<", "<=", ">" or ">=" * @param value the value to compare to + * @exception std::invalid_argument on syntax errors. */ SearchCriteria(const std::string & type, const std::string & key, @@ -214,10 +226,21 @@ class SearchCriteria const std::string & value) throw(std::invalid_argument); + /** + * Construct a SearchCriteria object from an XmlRpcValue. + * + * @param xmlRpcValue an XmlRpcValue struct, containing + * the search criteria. + * @exception std::invalid_argument on syntax errors. + */ + SearchCriteria(const XmlRpc::XmlRpcValue & xmlRpcValue) + throw(std::invalid_argument); + /** * Set the type field. * * @param type one of "audioClip", "playlist" or "all" + * @exception std::invalid_argument on syntax errors. */ void setType(const std::string & type) @@ -238,6 +261,7 @@ class SearchCriteria * Set the logical operator field. * * @param logicalOperator either "and" or "or" + * @exception std::invalid_argument on syntax errors. */ void setLogicalOperator(const std::string & logicalOperator) @@ -258,6 +282,7 @@ class SearchCriteria * @param comparisonOperator one of "=", "partial", "prefix", * "<", "<=", ">" or ">=" * @param value the value to compare to + * @exception std::invalid_argument on syntax errors. */ void addCondition(const std::string & key, @@ -271,6 +296,7 @@ class SearchCriteria * @param comparisonOperator one of "=", "partial", "prefix", * "<", "<=", ">" or ">=" * @param value the value of the mtime to compare to + * @exception std::invalid_argument on syntax errors. */ void addMtimeCondition(const std::string & comparisonOperator, @@ -281,6 +307,7 @@ class SearchCriteria * Add a search condition. * * @param condition the search condition to add + * @exception std::invalid_argument on syntax errors. */ void addCondition(const Ptr::Ref condition) @@ -295,6 +322,7 @@ class SearchCriteria * Set the limit field. * * @param limit the maximum number of search results to be returned + * @exception std::invalid_argument on syntax errors. */ void setLimit(const int limit) @@ -312,6 +340,7 @@ class SearchCriteria * * @param offset the index of the first matching condition * to be returned (first = 0) + * @exception std::invalid_argument on syntax errors. */ void setOffset(const int offset) @@ -327,7 +356,13 @@ class SearchCriteria /** * Convert to an XmlRpc::XmlRpcValue. */ - operator XmlRpc::XmlRpcValue() const throw(); + operator XmlRpc::XmlRpcValue() const throw(); + + /** + * Check two SearchCriteria objects for equality. + */ + bool + operator ==(const SearchCriteria & other) const throw(); }; diff --git a/livesupport/src/modules/core/src/SearchCriteria.cxx b/livesupport/src/modules/core/src/SearchCriteria.cxx index bfeb56291..2e95bac5d 100644 --- a/livesupport/src/modules/core/src/SearchCriteria.cxx +++ b/livesupport/src/modules/core/src/SearchCriteria.cxx @@ -38,6 +38,7 @@ using namespace LiveSupport::Core; using namespace boost::posix_time; +using namespace XmlRpc; /* =================================================== local data structures */ @@ -65,6 +66,51 @@ SearchCriteria :: SearchCriteria(const std::string & type, } +/*------------------------------------------------------------------------------ + * Construct a SearchCriteria object from an XmlRpcValue. + *----------------------------------------------------------------------------*/ +SearchCriteria :: SearchCriteria(const XmlRpcValue & xmlRpcValue) + throw(std::invalid_argument) +{ + // make a non-const copy, because XmlRpcValue::operator[](const char *) + // does not work on const objects + XmlRpcValue value(xmlRpcValue); + + if (value.hasMember("filetype") + && value["filetype"].getType() == XmlRpcValue::TypeString) { + type = std::string(value["filetype"]); + } else { + throw std::invalid_argument("missing file type in search criteria"); + } + + if (value.hasMember("operator") + && value["operator"].getType() == XmlRpcValue::TypeString) { + logicalOperator = std::string(value["operator"]); + } else { + logicalOperator = std::string("and"); + } + + if (value.hasMember("limit") + && value["limit"].getType() == XmlRpcValue::TypeInt) { + limit = value["limit"]; + } + + if (value.hasMember("offset") + && value["offset"].getType() == XmlRpcValue::TypeInt) { + offset = value["offset"]; + } + + if (!value.hasMember("conditions") + || value["conditions"].getType() != XmlRpcValue::TypeArray) { + throw std::invalid_argument("missing conditions in search criteria"); + } + + for (int i = 0; i < value["conditions"].size(); ++i) { + addCondition(value["conditions"][i]); + } +} + + /*------------------------------------------------------------------------------ * Add a search condition. *----------------------------------------------------------------------------*/ @@ -88,6 +134,38 @@ SearchCriteria :: addCondition(const std::string & key, } +/*------------------------------------------------------------------------------ + * Add a search condition. + *----------------------------------------------------------------------------*/ +void +SearchCriteria :: addCondition(const XmlRpcValue & xmlRpcValue) + throw(std::invalid_argument) +{ + // make a non-const copy, because XmlRpcValue::operator[](const char *) + // does not work on const objects + XmlRpcValue value(xmlRpcValue); + + if (!value.hasMember("cat") + || value["cat"].getType() != XmlRpcValue::TypeString) { + throw std::invalid_argument("missing metadata name in search criteria"); + } + + if (!value.hasMember("op") + || value["op"].getType() != XmlRpcValue::TypeString) { + throw std::invalid_argument("missing operator name in search criteria"); + } + + if (!value.hasMember("val") + || value["val"].getType() != XmlRpcValue::TypeString) { + throw std::invalid_argument("missing value in search criteria"); + } + + addCondition(std::string(value["cat"]), + std::string(value["op"]), + std::string(value["val"])); +} + + /*------------------------------------------------------------------------------ * Add a search condition specifying the mtime (modified-at time). *----------------------------------------------------------------------------*/ @@ -111,25 +189,25 @@ SearchCriteria :: addMtimeCondition(const std::string & comparisonOperator, /*------------------------------------------------------------------------------ - * Convert to an XmlRpc::XmlRpcValue. + * Convert to an XmlRpcValue. *----------------------------------------------------------------------------*/ -SearchCriteria :: operator XmlRpc::XmlRpcValue() const +SearchCriteria :: operator XmlRpcValue() const throw() { - XmlRpc::XmlRpcValue returnValue; + XmlRpcValue returnValue; returnValue["filetype"] = type; if (searchConditions.size() != 1) { returnValue["operator"] = logicalOperator; } - XmlRpc::XmlRpcValue conditionList; + XmlRpcValue conditionList; conditionList.setSize(searchConditions.size()); SearchConditionListType::const_iterator it, end; it = searchConditions.begin(); end = searchConditions.end(); for (int i = 0; it != end; ++i, ++it) { - XmlRpc::XmlRpcValue condition; + XmlRpcValue condition; condition["cat"] = it->key; condition["op"] = it->comparisonOperator; condition["val"] = it->value; @@ -141,10 +219,10 @@ SearchCriteria :: operator XmlRpc::XmlRpcValue() const struct tm mtimeStructTm; TimeConversion::ptimeToTm(mtimeValue, mtimeStructTm); - XmlRpc::XmlRpcValue condition; + XmlRpcValue condition; condition["cat"] = "ls:mtime"; condition["op"] = mtimeComparisonOperator; - condition["val"] = XmlRpc::XmlRpcValue(&mtimeStructTm); + condition["val"] = XmlRpcValue(&mtimeStructTm); conditionList[i] = condition; } @@ -161,3 +239,38 @@ SearchCriteria :: operator XmlRpc::XmlRpcValue() const return returnValue; } + +/*------------------------------------------------------------------------------ + * Check two SearchCriteria objects for equality. + *----------------------------------------------------------------------------*/ +bool +SearchCriteria :: operator ==(const SearchCriteria & other) const + throw() +{ + if (type != other.type + || limit != other.limit + || offset != other.offset + || searchConditions.size() != other.searchConditions.size()) { + return false; + } + + if (searchConditions.size() != 1 + && logicalOperator != other.logicalOperator) { + return false; + } + + SearchConditionListType::const_iterator it, otherIt; + it = searchConditions.begin(); + otherIt = other.searchConditions.begin(); + + for ( ; it != searchConditions.end(); ++it, ++otherIt) { + if (it->key != otherIt->key + || it->comparisonOperator != otherIt->comparisonOperator + || it->value != otherIt->value) { + return false; + } + } + + return true; +} + diff --git a/livesupport/src/modules/core/src/SearchCriteriaTest.cxx b/livesupport/src/modules/core/src/SearchCriteriaTest.cxx index e70bbbcd9..a667041de 100644 --- a/livesupport/src/modules/core/src/SearchCriteriaTest.cxx +++ b/livesupport/src/modules/core/src/SearchCriteriaTest.cxx @@ -156,3 +156,40 @@ SearchCriteriaTest :: firstTest(void) CPPUNIT_ASSERT(condition0["val"] == "X"); } + +/*------------------------------------------------------------------------------ + * Test the conversion to/from an XmlRpcValue. + *----------------------------------------------------------------------------*/ +void +SearchCriteriaTest :: marshalingTest(void) + throw (CPPUNIT_NS::Exception) +{ + Ptr::Ref criteria; + CPPUNIT_ASSERT_NO_THROW( + criteria.reset(new SearchCriteria("playlist", "Or")); + criteria->setLimit(50); + criteria->setOffset(100); + criteria->addCondition("dc:title", "PREFIX", "My "); + criteria->addCondition("DcTerms:Extent", "<", "180"); + ); + + XmlRpc::XmlRpcValue xmlRpcValue; + CPPUNIT_ASSERT_NO_THROW( + xmlRpcValue = *criteria; + ); + + Ptr::Ref copyCriteria; + CPPUNIT_ASSERT_NO_THROW( + copyCriteria.reset(new SearchCriteria(xmlRpcValue)); + ); + + CPPUNIT_ASSERT(*criteria == *copyCriteria); + + XmlRpc::XmlRpcValue copyXmlRpcValue; + CPPUNIT_ASSERT_NO_THROW( + copyXmlRpcValue = *copyCriteria; + ); + + CPPUNIT_ASSERT(xmlRpcValue == copyXmlRpcValue); +} + diff --git a/livesupport/src/modules/core/src/SearchCriteriaTest.h b/livesupport/src/modules/core/src/SearchCriteriaTest.h index 1bb46fb32..21e1c5dc0 100644 --- a/livesupport/src/modules/core/src/SearchCriteriaTest.h +++ b/livesupport/src/modules/core/src/SearchCriteriaTest.h @@ -65,6 +65,7 @@ class SearchCriteriaTest : public CPPUNIT_NS::TestFixture { CPPUNIT_TEST_SUITE(SearchCriteriaTest); CPPUNIT_TEST(firstTest); + CPPUNIT_TEST(marshalingTest); CPPUNIT_TEST_SUITE_END(); protected: @@ -77,6 +78,14 @@ class SearchCriteriaTest : public CPPUNIT_NS::TestFixture void firstTest(void) throw (CPPUNIT_NS::Exception); + /** + * Test the conversion to/from an XmlRpcValue. + * + * @exception CPPUNIT_NS::Exception on test failures. + */ + void + marshalingTest(void) throw (CPPUNIT_NS::Exception); + public: