added a SearchCriteria constructor from an XmlRpcValue;
this closes #1679
This commit is contained in:
parent
68a85e5946
commit
047ef2d923
4 changed files with 202 additions and 8 deletions
|
@ -180,6 +180,16 @@ class SearchCriteria
|
||||||
*/
|
*/
|
||||||
friend class LiveSupport::StorageClient::TestStorageClient;
|
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:
|
public:
|
||||||
|
|
||||||
|
@ -189,6 +199,7 @@ class SearchCriteria
|
||||||
*
|
*
|
||||||
* @param type one of "audioClip" (default), "playlist" or "all"
|
* @param type one of "audioClip" (default), "playlist" or "all"
|
||||||
* @param logicalOperator either "and" (default) or "or"
|
* @param logicalOperator either "and" (default) or "or"
|
||||||
|
* @exception std::invalid_argument on syntax errors.
|
||||||
*/
|
*/
|
||||||
SearchCriteria(const std::string & type = "all",
|
SearchCriteria(const std::string & type = "all",
|
||||||
const std::string & logicalOperator = "and")
|
const std::string & logicalOperator = "and")
|
||||||
|
@ -207,6 +218,7 @@ class SearchCriteria
|
||||||
* @param comparisonOperator one of "=", "partial", "prefix",
|
* @param comparisonOperator one of "=", "partial", "prefix",
|
||||||
* "<", "<=", ">" or ">="
|
* "<", "<=", ">" or ">="
|
||||||
* @param value the value to compare to
|
* @param value the value to compare to
|
||||||
|
* @exception std::invalid_argument on syntax errors.
|
||||||
*/
|
*/
|
||||||
SearchCriteria(const std::string & type,
|
SearchCriteria(const std::string & type,
|
||||||
const std::string & key,
|
const std::string & key,
|
||||||
|
@ -214,10 +226,21 @@ class SearchCriteria
|
||||||
const std::string & value)
|
const std::string & value)
|
||||||
throw(std::invalid_argument);
|
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.
|
* Set the type field.
|
||||||
*
|
*
|
||||||
* @param type one of "audioClip", "playlist" or "all"
|
* @param type one of "audioClip", "playlist" or "all"
|
||||||
|
* @exception std::invalid_argument on syntax errors.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
setType(const std::string & type)
|
setType(const std::string & type)
|
||||||
|
@ -238,6 +261,7 @@ class SearchCriteria
|
||||||
* Set the logical operator field.
|
* Set the logical operator field.
|
||||||
*
|
*
|
||||||
* @param logicalOperator either "and" or "or"
|
* @param logicalOperator either "and" or "or"
|
||||||
|
* @exception std::invalid_argument on syntax errors.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
setLogicalOperator(const std::string & logicalOperator)
|
setLogicalOperator(const std::string & logicalOperator)
|
||||||
|
@ -258,6 +282,7 @@ class SearchCriteria
|
||||||
* @param comparisonOperator one of "=", "partial", "prefix",
|
* @param comparisonOperator one of "=", "partial", "prefix",
|
||||||
* "<", "<=", ">" or ">="
|
* "<", "<=", ">" or ">="
|
||||||
* @param value the value to compare to
|
* @param value the value to compare to
|
||||||
|
* @exception std::invalid_argument on syntax errors.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
addCondition(const std::string & key,
|
addCondition(const std::string & key,
|
||||||
|
@ -271,6 +296,7 @@ class SearchCriteria
|
||||||
* @param comparisonOperator one of "=", "partial", "prefix",
|
* @param comparisonOperator one of "=", "partial", "prefix",
|
||||||
* "<", "<=", ">" or ">="
|
* "<", "<=", ">" or ">="
|
||||||
* @param value the value of the mtime to compare to
|
* @param value the value of the mtime to compare to
|
||||||
|
* @exception std::invalid_argument on syntax errors.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
addMtimeCondition(const std::string & comparisonOperator,
|
addMtimeCondition(const std::string & comparisonOperator,
|
||||||
|
@ -281,6 +307,7 @@ class SearchCriteria
|
||||||
* Add a search condition.
|
* Add a search condition.
|
||||||
*
|
*
|
||||||
* @param condition the search condition to add
|
* @param condition the search condition to add
|
||||||
|
* @exception std::invalid_argument on syntax errors.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
addCondition(const Ptr<SearchConditionType>::Ref condition)
|
addCondition(const Ptr<SearchConditionType>::Ref condition)
|
||||||
|
@ -295,6 +322,7 @@ class SearchCriteria
|
||||||
* Set the limit field.
|
* Set the limit field.
|
||||||
*
|
*
|
||||||
* @param limit the maximum number of search results to be returned
|
* @param limit the maximum number of search results to be returned
|
||||||
|
* @exception std::invalid_argument on syntax errors.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
setLimit(const int limit)
|
setLimit(const int limit)
|
||||||
|
@ -312,6 +340,7 @@ class SearchCriteria
|
||||||
*
|
*
|
||||||
* @param offset the index of the first matching condition
|
* @param offset the index of the first matching condition
|
||||||
* to be returned (first = 0)
|
* to be returned (first = 0)
|
||||||
|
* @exception std::invalid_argument on syntax errors.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
setOffset(const int offset)
|
setOffset(const int offset)
|
||||||
|
@ -327,7 +356,13 @@ class SearchCriteria
|
||||||
/**
|
/**
|
||||||
* Convert to an XmlRpc::XmlRpcValue.
|
* 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();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,7 @@
|
||||||
|
|
||||||
using namespace LiveSupport::Core;
|
using namespace LiveSupport::Core;
|
||||||
using namespace boost::posix_time;
|
using namespace boost::posix_time;
|
||||||
|
using namespace XmlRpc;
|
||||||
|
|
||||||
/* =================================================== local data structures */
|
/* =================================================== 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.
|
* 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).
|
* 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()
|
throw()
|
||||||
{
|
{
|
||||||
XmlRpc::XmlRpcValue returnValue;
|
XmlRpcValue returnValue;
|
||||||
|
|
||||||
returnValue["filetype"] = type;
|
returnValue["filetype"] = type;
|
||||||
if (searchConditions.size() != 1) {
|
if (searchConditions.size() != 1) {
|
||||||
returnValue["operator"] = logicalOperator;
|
returnValue["operator"] = logicalOperator;
|
||||||
}
|
}
|
||||||
|
|
||||||
XmlRpc::XmlRpcValue conditionList;
|
XmlRpcValue conditionList;
|
||||||
conditionList.setSize(searchConditions.size());
|
conditionList.setSize(searchConditions.size());
|
||||||
SearchConditionListType::const_iterator it, end;
|
SearchConditionListType::const_iterator it, end;
|
||||||
it = searchConditions.begin();
|
it = searchConditions.begin();
|
||||||
end = searchConditions.end();
|
end = searchConditions.end();
|
||||||
for (int i = 0; it != end; ++i, ++it) {
|
for (int i = 0; it != end; ++i, ++it) {
|
||||||
XmlRpc::XmlRpcValue condition;
|
XmlRpcValue condition;
|
||||||
condition["cat"] = it->key;
|
condition["cat"] = it->key;
|
||||||
condition["op"] = it->comparisonOperator;
|
condition["op"] = it->comparisonOperator;
|
||||||
condition["val"] = it->value;
|
condition["val"] = it->value;
|
||||||
|
@ -141,10 +219,10 @@ SearchCriteria :: operator XmlRpc::XmlRpcValue() const
|
||||||
struct tm mtimeStructTm;
|
struct tm mtimeStructTm;
|
||||||
TimeConversion::ptimeToTm(mtimeValue, mtimeStructTm);
|
TimeConversion::ptimeToTm(mtimeValue, mtimeStructTm);
|
||||||
|
|
||||||
XmlRpc::XmlRpcValue condition;
|
XmlRpcValue condition;
|
||||||
condition["cat"] = "ls:mtime";
|
condition["cat"] = "ls:mtime";
|
||||||
condition["op"] = mtimeComparisonOperator;
|
condition["op"] = mtimeComparisonOperator;
|
||||||
condition["val"] = XmlRpc::XmlRpcValue(&mtimeStructTm);
|
condition["val"] = XmlRpcValue(&mtimeStructTm);
|
||||||
conditionList[i] = condition;
|
conditionList[i] = condition;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,3 +239,38 @@ SearchCriteria :: operator XmlRpc::XmlRpcValue() const
|
||||||
return returnValue;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -156,3 +156,40 @@ SearchCriteriaTest :: firstTest(void)
|
||||||
CPPUNIT_ASSERT(condition0["val"] == "X");
|
CPPUNIT_ASSERT(condition0["val"] == "X");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------
|
||||||
|
* Test the conversion to/from an XmlRpcValue.
|
||||||
|
*----------------------------------------------------------------------------*/
|
||||||
|
void
|
||||||
|
SearchCriteriaTest :: marshalingTest(void)
|
||||||
|
throw (CPPUNIT_NS::Exception)
|
||||||
|
{
|
||||||
|
Ptr<SearchCriteria>::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<SearchCriteria>::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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -65,6 +65,7 @@ class SearchCriteriaTest : public CPPUNIT_NS::TestFixture
|
||||||
{
|
{
|
||||||
CPPUNIT_TEST_SUITE(SearchCriteriaTest);
|
CPPUNIT_TEST_SUITE(SearchCriteriaTest);
|
||||||
CPPUNIT_TEST(firstTest);
|
CPPUNIT_TEST(firstTest);
|
||||||
|
CPPUNIT_TEST(marshalingTest);
|
||||||
CPPUNIT_TEST_SUITE_END();
|
CPPUNIT_TEST_SUITE_END();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -77,6 +78,14 @@ class SearchCriteriaTest : public CPPUNIT_NS::TestFixture
|
||||||
void
|
void
|
||||||
firstTest(void) throw (CPPUNIT_NS::Exception);
|
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:
|
public:
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue