diff --git a/livesupport/modules/core/src/AudioClip.cxx b/livesupport/modules/core/src/AudioClip.cxx index 9f46f4ae2..2fa65266e 100644 --- a/livesupport/modules/core/src/AudioClip.cxx +++ b/livesupport/modules/core/src/AudioClip.cxx @@ -22,7 +22,7 @@ Author : $Author: fgerlits $ - Version : $Revision: 1.17 $ + Version : $Revision: 1.18 $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/core/src/AudioClip.cxx,v $ ------------------------------------------------------------------------------*/ @@ -240,13 +240,17 @@ AudioClip :: configure(const xmlpp::Element & element) if (!playlength && (attribute = element.get_attribute(playlengthAttrName))) { - playlength.reset(new time_duration( - duration_from_string(attribute->get_value()))); + playlength.reset(new time_duration(duration_from_string( + attribute->get_value() ))); + Ptr::Ref playlengthString(new const Glib::ustring( + attribute->get_value() )); + setMetadata(playlengthString, extentElementName, extentElementPrefix); } if (!title && (attribute = element.get_attribute(titleAttrName))) { title.reset(new const Glib::ustring(attribute->get_value())); + setMetadata(title, titleElementName, titleElementPrefix); } if (!uri @@ -326,10 +330,6 @@ AudioClip :: configure(const xmlpp::Element & element) throw std::invalid_argument(eMsg); } - Ptr::Ref playlengthString(new const Glib::ustring( - to_simple_string(*playlength) )); - setMetadata(playlengthString, extentElementName, extentElementPrefix); - if (!title) { std::string eMsg = "missing attribute "; eMsg += titleAttrName; @@ -337,8 +337,6 @@ AudioClip :: configure(const xmlpp::Element & element) eMsg += titleElementPrefix + ":" + titleElementName; throw std::invalid_argument(eMsg); } - - setMetadata(title, titleElementName, titleElementPrefix); } diff --git a/livesupport/modules/core/src/Playlist.cxx b/livesupport/modules/core/src/Playlist.cxx index 8331455d2..35c9dc014 100644 --- a/livesupport/modules/core/src/Playlist.cxx +++ b/livesupport/modules/core/src/Playlist.cxx @@ -22,7 +22,7 @@ Author : $Author: fgerlits $ - Version : $Revision: 1.26 $ + Version : $Revision: 1.27 $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/core/src/Playlist.cxx,v $ ------------------------------------------------------------------------------*/ @@ -106,12 +106,16 @@ Playlist :: configure(const xmlpp::Element & element) } playlength.reset(new time_duration( duration_from_string(attribute->get_value()))); - + Ptr::Ref playlengthString(new Glib::ustring( + attribute->get_value() )); + metadata["dcterms:extent"] = playlengthString; + if ((attribute = element.get_attribute(titleAttrName))) { title.reset(new const Glib::ustring(attribute->get_value())); } else { title.reset(new const Glib::ustring("")); } + metadata["dc:title"] = title; xmlpp::Node::NodeList childNodes = element.get_children(elementListAttrName); diff --git a/livesupport/modules/storage/etc/testStorage.xml b/livesupport/modules/storage/etc/testStorage.xml index a48f82c11..f8d9a9da2 100644 --- a/livesupport/modules/storage/etc/testStorage.xml +++ b/livesupport/modules/storage/etc/testStorage.xml @@ -7,6 +7,7 @@ + @@ -24,9 +25,10 @@ ]> - + - @@ -41,30 +43,31 @@ + playlength="00:00:11.000000" title="Playlist Two"> - + - - - diff --git a/livesupport/modules/storage/include/LiveSupport/Storage/SearchCriteria.h b/livesupport/modules/storage/include/LiveSupport/Storage/SearchCriteria.h index 30b42324b..02b946c2d 100644 --- a/livesupport/modules/storage/include/LiveSupport/Storage/SearchCriteria.h +++ b/livesupport/modules/storage/include/LiveSupport/Storage/SearchCriteria.h @@ -22,7 +22,7 @@ Author : $Author: fgerlits $ - Version : $Revision: 1.1 $ + Version : $Revision: 1.2 $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/storage/include/LiveSupport/Storage/Attic/SearchCriteria.h,v $ ------------------------------------------------------------------------------*/ @@ -47,6 +47,8 @@ namespace LiveSupport { namespace Storage { +class TestStorageClient; // forward declaration of friend class + /* ================================================================ constants */ @@ -143,6 +145,12 @@ class SearchCriteria return returnValue; } + /** + * Give access of private members to the TestStorageClient. + */ + friend class Storage::TestStorageClient; + + public: /** @@ -158,7 +166,7 @@ class SearchCriteria : limit(0), offset(0) { setType(type); - setOperator(logicalOperator); + setLogicalOperator(logicalOperator); } /** @@ -202,7 +210,7 @@ class SearchCriteria * @param logicalOperator either "and" or "or" */ void - setOperator(const std::string & logicalOperator) + setLogicalOperator(const std::string & logicalOperator) throw(std::invalid_argument) { std::string lowerCaseOp = lowerCase(logicalOperator); diff --git a/livesupport/modules/storage/include/LiveSupport/Storage/StorageClientInterface.h b/livesupport/modules/storage/include/LiveSupport/Storage/StorageClientInterface.h index 1e24c2e71..6b192e5dd 100644 --- a/livesupport/modules/storage/include/LiveSupport/Storage/StorageClientInterface.h +++ b/livesupport/modules/storage/include/LiveSupport/Storage/StorageClientInterface.h @@ -22,7 +22,7 @@ Author : $Author: fgerlits $ - Version : $Revision: 1.6 $ + Version : $Revision: 1.7 $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/storage/include/LiveSupport/Storage/StorageClientInterface.h,v $ ------------------------------------------------------------------------------*/ @@ -47,6 +47,8 @@ #include "LiveSupport/Core/SessionId.h" #include "LiveSupport/Core/XmlRpcException.h" +#include "LiveSupport/Storage/SearchCriteria.h" + namespace LiveSupport { namespace Storage { @@ -65,7 +67,7 @@ using namespace Core; * An interface for storage clients. * * @author $Author: fgerlits $ - * @version $Revision: 1.6 $ + * @version $Revision: 1.7 $ */ class StorageClientInterface { @@ -363,6 +365,45 @@ class StorageClientInterface getAllAudioClips(Ptr::Ref sessionId) const throw (XmlRpcException) = 0; + + /** + * Search for audio clips or playlists. The results can be read + * using getAudioClipIds() and getPlaylistIds(). + * + * @param sessionId the session ID from the authentication client + * @param searchCriteria an object containing the search criteria + * @return the number of items found. + * @exception XmlRpcException if there is a problem with the XML-RPC + * call. + */ + virtual int + search(Ptr::Ref sessionId, + Ptr::Ref searchCriteria) + throw (XmlRpcException) + = 0; + + /** + * Return the list of audio clip IDs found by the search method. + * + * (Or the list of audio clip IDs returned by the reset() method + * in WebStorageClient -- used for testing.) + * + * @return a vector of UniqueId objects. + */ + virtual Ptr::Ref> >::Ref + getAudioClipIds(void) throw () = 0; + + + /** + * Return the list of playlist IDs found by the search method. + * + * (Or the list of playlist IDs returned by the reset() method + * in WebStorageClient -- used for testing.) + * + * @return a vector of UniqueId objects. + */ + virtual Ptr::Ref> >::Ref + getPlaylistIds(void) throw () = 0; }; diff --git a/livesupport/modules/storage/src/TestStorageClient.cxx b/livesupport/modules/storage/src/TestStorageClient.cxx index 01ea2e158..cce9cc83e 100644 --- a/livesupport/modules/storage/src/TestStorageClient.cxx +++ b/livesupport/modules/storage/src/TestStorageClient.cxx @@ -22,7 +22,7 @@ Author : $Author: fgerlits $ - Version : $Revision: 1.31 $ + Version : $Revision: 1.32 $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/storage/src/TestStorageClient.cxx,v $ ------------------------------------------------------------------------------*/ @@ -199,8 +199,12 @@ TestStorageClient :: configure(const xmlpp::Element & element) *----------------------------------------------------------------------------*/ Ptr::Ref TestStorageClient :: createPlaylist(Ptr::Ref sessionId) - throw () + throw (XmlRpcException) { + if (!sessionId) { + throw XmlRpcException("missing session ID argument"); + } + // generate a new UniqueId -- TODO: fix UniqueId to make sure // this is really unique; not checked here! Ptr::Ref playlistId = @@ -224,8 +228,12 @@ TestStorageClient :: createPlaylist(Ptr::Ref sessionId) const bool TestStorageClient :: existsPlaylist(Ptr::Ref sessionId, Ptr::Ref id) const - throw () + throw (XmlRpcException) { + if (!sessionId) { + throw XmlRpcException("missing session ID argument"); + } + return playlistMap.count(id->getId()) == 1 ? true : false; } @@ -238,6 +246,10 @@ TestStorageClient :: getPlaylist(Ptr::Ref sessionId, Ptr::Ref id) const throw (XmlRpcException) { + if (!sessionId) { + throw XmlRpcException("missing session ID argument"); + } + Ptr::Ref playlist; EditedPlaylistsType::const_iterator @@ -266,6 +278,10 @@ TestStorageClient :: editPlaylist(Ptr::Ref sessionId, Ptr::Ref id) throw (XmlRpcException) { + if (!sessionId) { + throw XmlRpcException("missing session ID argument"); + } + if (editedPlaylists.find(id->getId()) != editedPlaylists.end()) { throw XmlRpcException("playlist is already being edited"); } @@ -287,6 +303,10 @@ TestStorageClient :: savePlaylist(Ptr::Ref sessionId, Ptr::Ref playlist) throw (XmlRpcException) { + if (!sessionId) { + throw XmlRpcException("missing session ID argument"); + } + if (! playlist->getToken()) { throw XmlRpcException("savePlaylist() called without editPlaylist()"); } @@ -327,6 +347,10 @@ TestStorageClient :: acquirePlaylist(Ptr::Ref sessionId, Ptr::Ref id) const throw (XmlRpcException) { + if (!sessionId) { + throw XmlRpcException("missing session ID argument"); + } + PlaylistMapType::const_iterator playlistMapIt = playlistMap.find(id->getId()); @@ -416,6 +440,10 @@ TestStorageClient :: releasePlaylist(Ptr::Ref sessionId, Ptr::Ref playlist) const throw (XmlRpcException) { + if (!sessionId) { + throw XmlRpcException("missing session ID argument"); + } + if (! playlist->getUri()) { throw XmlRpcInvalidArgumentException("playlist URI not found"); } @@ -474,6 +502,10 @@ TestStorageClient :: deletePlaylist(Ptr::Ref sessionId, Ptr::Ref id) throw (XmlRpcException) { + if (!sessionId) { + throw XmlRpcException("missing session ID argument"); + } + if (editedPlaylists.find(id->getId()) != editedPlaylists.end()) { throw XmlRpcException("playlist is being edited"); } @@ -491,8 +523,12 @@ TestStorageClient :: deletePlaylist(Ptr::Ref sessionId, Ptr::Ref> >::Ref TestStorageClient :: getAllPlaylists(Ptr::Ref sessionId) const - throw () + throw (XmlRpcException) { + if (!sessionId) { + throw XmlRpcException("missing session ID argument"); + } + PlaylistMapType::const_iterator it = playlistMap.begin(); Ptr::Ref> >::Ref playlistVector (new std::vector::Ref>); @@ -512,8 +548,12 @@ TestStorageClient :: getAllPlaylists(Ptr::Ref sessionId) const bool TestStorageClient :: existsAudioClip(Ptr::Ref sessionId, Ptr::Ref id) const - throw () + throw (XmlRpcException) { + if (!sessionId) { + throw XmlRpcException("missing session ID argument"); + } + return audioClipMap.count(id->getId()) == 1 ? true : false; } @@ -526,6 +566,10 @@ TestStorageClient :: getAudioClip(Ptr::Ref sessionId, Ptr::Ref id) const throw (XmlRpcException) { + if (!sessionId) { + throw XmlRpcException("missing session ID argument"); + } + AudioClipMapType::const_iterator it = audioClipMap.find(id->getId()); if (it == audioClipMap.end()) { @@ -545,6 +589,10 @@ TestStorageClient :: storeAudioClip(Ptr::Ref sessionId, Ptr::Ref audioClip) throw (XmlRpcException) { + if (!sessionId) { + throw XmlRpcException("missing session ID argument"); + } + if (!audioClip->getUri()) { throw XmlRpcException("audio clip has no URI field"); } @@ -572,6 +620,10 @@ TestStorageClient :: acquireAudioClip(Ptr::Ref sessionId, Ptr::Ref id) const throw (XmlRpcException) { + if (!sessionId) { + throw XmlRpcException("missing session ID argument"); + } + AudioClipUrisType::const_iterator it = audioClipUris.find(id->getId()); if (it == audioClipUris.end()) { @@ -606,6 +658,10 @@ TestStorageClient :: releaseAudioClip(Ptr::Ref sessionId, Ptr::Ref audioClip) const throw (XmlRpcException) { + if (!sessionId) { + throw XmlRpcException("missing session ID argument"); + } + if (!audioClip->getUri()) { throw XmlRpcException("audio clip does not have a URI field"); } @@ -623,6 +679,10 @@ TestStorageClient :: deleteAudioClip(Ptr::Ref sessionId, Ptr::Ref id) throw (XmlRpcException) { + if (!sessionId) { + throw XmlRpcException("missing session ID argument"); + } + // erase() returns the number of entries found & erased if (!audioClipMap.erase(id->getId())) { throw XmlRpcException("no such audio clip"); @@ -636,8 +696,12 @@ TestStorageClient :: deleteAudioClip(Ptr::Ref sessionId, Ptr::Ref> >::Ref TestStorageClient :: getAllAudioClips(Ptr::Ref sessionId) const - throw () + throw (XmlRpcException) { + if (!sessionId) { + throw XmlRpcException("missing session ID argument"); + } + AudioClipMapType::const_iterator it = audioClipMap.begin(); Ptr::Ref> >::Ref audioClipVector (new std::vector::Ref>); @@ -650,3 +714,164 @@ TestStorageClient :: getAllAudioClips(Ptr::Ref sessionId) return audioClipVector; } + +/*------------------------------------------------------------------------------ + * Search for audio clips or playlists. + *----------------------------------------------------------------------------*/ +int +TestStorageClient :: search(Ptr::Ref sessionId, + Ptr::Ref searchCriteria) + throw (XmlRpcException) +{ + if (!sessionId) { + throw XmlRpcException("missing session ID argument"); + } + + int counter = 0; + int first = searchCriteria->offset; + int last; + if (searchCriteria->limit) { + last = searchCriteria->offset + searchCriteria->limit; + } else { + last = 0; + } + + audioClipIds.reset(new std::vector::Ref>); + playlistIds.reset(new std::vector::Ref>); + + if (searchCriteria->type == "audioclip" || searchCriteria->type == "all") { + AudioClipMapType::const_iterator it = audioClipMap.begin(); + while (it != audioClipMap.end()) { + if (matchesCriteria(it->second, searchCriteria)) { + if (counter >= first) { + audioClipIds->push_back(it->second->getId()); + } + ++counter; + if (last && counter >= last) { + return (counter - first); + } + } + ++it; + } + } + + if (searchCriteria->type == "playlist" || searchCriteria->type == "all") { + PlaylistMapType::const_iterator it = playlistMap.begin(); + while (it != playlistMap.end()) { + if (matchesCriteria(it->second, searchCriteria)) { + if (counter >= first) { + playlistIds->push_back(it->second->getId()); + } + ++counter; + if (last && counter >= last) { + return (counter - first); + } + } + ++it; + } + } + + return (counter - first); +} + + +/*------------------------------------------------------------------------------ + * See if the Playable instance satisfies the search criteria + *----------------------------------------------------------------------------*/ +bool +TestStorageClient :: matchesCriteria(Ptr::Ref playable, + Ptr::Ref criteria) + throw (XmlRpcException) +{ + bool vetoValue; + if (criteria->logicalOperator == "and") { + vetoValue = false; + } else if (criteria->logicalOperator == "or") { + vetoValue = true; + } else { + std::string eMsg = "unknown logical operator: "; + eMsg += criteria->type; + throw XmlRpcException(eMsg); + } + + bool foundAVetoValue = false; + + SearchCriteria::SearchConditionListType::const_iterator + it = criteria->searchConditions.begin(); + while (it != criteria->searchConditions.end()) { + if (satisfiesCondition(playable, *it) == vetoValue) { + foundAVetoValue = true; + break; + } + ++it; + } + + if (foundAVetoValue) { + return vetoValue; + } else { + return !vetoValue; + } +} + + +/*------------------------------------------------------------------------------ + * See if the Playable instance satisfies a single condition + *----------------------------------------------------------------------------*/ +bool +TestStorageClient :: satisfiesCondition( + Ptr::Ref playable, + const SearchCriteria::SearchConditionType & condition) + throw (XmlRpcException) +{ + std::string name, nameSpace; + separateNameAndNameSpace(condition.key, name, nameSpace); + + Ptr::Ref value = playable->getMetadata(name, nameSpace); + if (!value) { + return false; + } + + std::string op = condition.comparisonOperator; + + if (op == "=") { + return (*value == condition.value); + } else if (op == "partial") { + return (value->find(condition.value) != std::string::npos); + } else if (op == "prefix") { + return (value->find(condition.value) == 0); + } else if (op == "<") { + return (*value < condition.value); + } else if (op == "<=") { + return (*value <= condition.value); + } else if (op == ">") { + return (*value > condition.value); + } else if (op == ">=") { + return (*value >= condition.value); + } else { + std::string eMsg = "unknown comparison operator: "; + eMsg += op; + throw XmlRpcException(eMsg); + } +} + + +/*------------------------------------------------------------------------------ + * Separate a key into the metadata name and its namespace + *----------------------------------------------------------------------------*/ +void +LiveSupport::Storage :: separateNameAndNameSpace(const std::string & key, + std::string & name, + std::string & nameSpace) + throw () +{ + unsigned int colonPosition = key.find(':'); + + if (colonPosition != std::string::npos) { // there is a colon + nameSpace = key.substr(0, colonPosition); + name = key.substr(colonPosition+1); + } else { // no colon found + nameSpace = ""; + name = key; + } +} + diff --git a/livesupport/modules/storage/src/TestStorageClient.h b/livesupport/modules/storage/src/TestStorageClient.h index 4fe511fec..b5317fabd 100644 --- a/livesupport/modules/storage/src/TestStorageClient.h +++ b/livesupport/modules/storage/src/TestStorageClient.h @@ -22,7 +22,7 @@ Author : $Author: fgerlits $ - Version : $Revision: 1.25 $ + Version : $Revision: 1.26 $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/storage/src/TestStorageClient.h,v $ ------------------------------------------------------------------------------*/ @@ -42,11 +42,7 @@ #include -#include "LiveSupport/Core/Ptr.h" -#include "LiveSupport/Core/UniqueId.h" -#include "LiveSupport/Core/Playlist.h" #include "LiveSupport/Core/Configurable.h" -#include "LiveSupport/Core/SessionId.h" #include "LiveSupport/Storage/StorageClientInterface.h" @@ -90,7 +86,7 @@ using namespace LiveSupport::Core; * * * @author $Author: fgerlits $ - * @version $Revision: 1.25 $ + * @version $Revision: 1.26 $ */ class TestStorageClient : virtual public Configurable, @@ -151,6 +147,34 @@ class TestStorageClient : */ std::string localTempStorage; + /** + * A vector containing the unique IDs of the audio clips returned + * by search(). + */ + Ptr::Ref> >::Ref audioClipIds; + + /** + * A vector containing the unique IDs of the playlists returned + * by search(). + */ + Ptr::Ref> >::Ref playlistIds; + + /** + * Auxilliary method used by search(). + */ + bool + matchesCriteria(Ptr::Ref playable, + Ptr::Ref criteria) + throw (XmlRpcException); + + /** + * Auxilliary method used by matchesCriteria(). + */ + bool + satisfiesCondition( + Ptr::Ref playable, + const SearchCriteria::SearchConditionType & condition) + throw (XmlRpcException); public: /** @@ -195,7 +219,7 @@ class TestStorageClient : */ virtual Ptr::Ref createPlaylist(Ptr::Ref sessionId) - throw (); + throw (XmlRpcException); /** @@ -209,7 +233,7 @@ class TestStorageClient : virtual const bool existsPlaylist(Ptr::Ref sessionId, Ptr::Ref id) const - throw (); + throw (XmlRpcException); /** @@ -344,7 +368,7 @@ class TestStorageClient : */ virtual Ptr::Ref> >::Ref getAllPlaylists(Ptr::Ref sessionId) const - throw (); + throw (XmlRpcException); /** @@ -358,7 +382,7 @@ class TestStorageClient : virtual const bool existsAudioClip(Ptr::Ref sessionId, Ptr::Ref id) const - throw (); + throw (XmlRpcException); /** * Return an audio clip with the specified id to be displayed. @@ -465,7 +489,57 @@ class TestStorageClient : */ virtual Ptr::Ref> >::Ref getAllAudioClips(Ptr::Ref sessionId) const - throw (); + throw (XmlRpcException); + + + /** + * Search for audio clips or playlists. The results can be read + * using getAudioClipIds() and getPlaylistIds(). + * + * If an audio clip or playlist does not have a metadata field X, + * it does not match any condition about field X. In particular, + * a search for ("X", "partial", "") returns all records + * which contain a metadata field X. + * + * @param sessionId the session ID from the authentication client + * @param searchCriteria an object containing the search criteria + * @return the number of items found. + * @exception XmlRpcException if there is a problem with the XML-RPC + * call. + */ + virtual int + search(Ptr::Ref sessionId, + Ptr::Ref searchCriteria) + throw (XmlRpcException); + + /** + * Return the list of audio clip IDs found by the search method. + * + * (Or the list of audio clip IDs returned by the reset() method + * -- used for testing.) + * + * @return a vector of UniqueId objects. + */ + virtual Ptr::Ref> >::Ref + getAudioClipIds(void) throw () + { + return audioClipIds; + } + + + /** + * Return the list of playlist IDs found by the search method. + * + * (Or the list of playlist IDs returned by the reset() method + * -- used for testing.) + * + * @return a vector of UniqueId objects. + */ + virtual Ptr::Ref> >::Ref + getPlaylistIds(void) throw () + { + return playlistIds; + } }; @@ -474,8 +548,16 @@ class TestStorageClient : /* ====================================================== function prototypes */ + /** + * Auxilliary method used by satisfiesCondition(). + */ + void + separateNameAndNameSpace(const std::string & key, + std::string & name, + std::string & nameSpace) + throw (); -} // namespace Core +} // namespace Storage } // namespace LiveSupport #endif // TestStorageClient_h diff --git a/livesupport/modules/storage/src/TestStorageClientTest.cxx b/livesupport/modules/storage/src/TestStorageClientTest.cxx index 84e1f69b5..769b338e2 100644 --- a/livesupport/modules/storage/src/TestStorageClientTest.cxx +++ b/livesupport/modules/storage/src/TestStorageClientTest.cxx @@ -22,7 +22,7 @@ Author : $Author: fgerlits $ - Version : $Revision: 1.22 $ + Version : $Revision: 1.23 $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/storage/src/TestStorageClientTest.cxx,v $ ------------------------------------------------------------------------------*/ @@ -132,6 +132,7 @@ TestStorageClientTest :: firstTest(void) } catch (XmlRpcException &e) { CPPUNIT_FAIL(e.what()); } + CPPUNIT_ASSERT(playlist->getId()); CPPUNIT_ASSERT(playlist->getId()->getId() == id1->getId()); } @@ -238,7 +239,7 @@ TestStorageClientTest :: audioClipTest(void) } CPPUNIT_ASSERT(audioClip->getId()->getId() == id02->getId()); CPPUNIT_ASSERT(audioClip->getPlaylength()->total_seconds() - == 30*60); + == 12); Ptr::Ref> >::Ref audioClipVector; try { @@ -378,3 +379,68 @@ TestStorageClientTest :: acquirePlaylistTest(void) } catch (XmlRpcException &e) { } } + + +/*------------------------------------------------------------------------------ + * Search test. + *----------------------------------------------------------------------------*/ +void +TestStorageClientTest :: searchTest(void) + throw (CPPUNIT_NS::Exception) +{ + try { + Ptr::Ref criteria(new SearchCriteria( + "audioClip", + "dcterms:extent", "=", "00:00:11.000000")); + + int numberFound = tsc->search(dummySessionId, criteria); + CPPUNIT_ASSERT(numberFound == 2); + CPPUNIT_ASSERT(tsc->getAudioClipIds()->size() == 2); + CPPUNIT_ASSERT(tsc->getAudioClipIds()->at(0)->getId() == 0x10001); + CPPUNIT_ASSERT(tsc->getAudioClipIds()->at(1)->getId() == 0x10003); + CPPUNIT_ASSERT(tsc->getPlaylistIds()->size() == 0); + + } catch (std::invalid_argument &e) { + CPPUNIT_FAIL(e.what()); + } catch (Core::XmlRpcException &e) { + CPPUNIT_FAIL(e.what()); + } + + try { + Ptr::Ref criteria(new SearchCriteria("all", "or")); + criteria->addCondition("dcterms:extent", ">", "00:00:11.000000"); + criteria->addCondition("dc:title", "prefix", "Playlist"); + int numberFound = tsc->search(dummySessionId, criteria); + CPPUNIT_ASSERT(numberFound == 3); + CPPUNIT_ASSERT(tsc->getAudioClipIds()->size() == 1); + CPPUNIT_ASSERT(tsc->getAudioClipIds()->at(0)->getId() == 0x10002); + CPPUNIT_ASSERT(tsc->getPlaylistIds()->size() == 2); + CPPUNIT_ASSERT(tsc->getPlaylistIds()->at(0)->getId() == 1); + CPPUNIT_ASSERT(tsc->getPlaylistIds()->at(1)->getId() == 2); + + } catch (std::invalid_argument &e) { + CPPUNIT_FAIL(e.what()); + } catch (Core::XmlRpcException &e) { + CPPUNIT_FAIL(e.what()); + } + + try { + Ptr::Ref criteria(new SearchCriteria); + criteria->setType("all"); + criteria->addCondition("dc:title", "partial", "t"); + criteria->setLimit(2); + criteria->setOffset(1); + int numberFound = tsc->search(dummySessionId, criteria); + CPPUNIT_ASSERT(numberFound == 2); + CPPUNIT_ASSERT(tsc->getAudioClipIds()->size() == 1); + CPPUNIT_ASSERT(tsc->getAudioClipIds()->at(0)->getId() == 0x10003); + CPPUNIT_ASSERT(tsc->getPlaylistIds()->size() == 1); + CPPUNIT_ASSERT(tsc->getPlaylistIds()->at(0)->getId() == 1); + + } catch (std::invalid_argument &e) { + CPPUNIT_FAIL(e.what()); + } catch (Core::XmlRpcException &e) { + CPPUNIT_FAIL(e.what()); + } +} + diff --git a/livesupport/modules/storage/src/TestStorageClientTest.h b/livesupport/modules/storage/src/TestStorageClientTest.h index 930358a48..3a3c08b0b 100644 --- a/livesupport/modules/storage/src/TestStorageClientTest.h +++ b/livesupport/modules/storage/src/TestStorageClientTest.h @@ -22,7 +22,7 @@ Author : $Author: fgerlits $ - Version : $Revision: 1.8 $ + Version : $Revision: 1.9 $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/storage/src/TestStorageClientTest.h,v $ ------------------------------------------------------------------------------*/ @@ -58,7 +58,7 @@ namespace Storage { * Unit test for the UploadPlaylistMetohd class. * * @author $Author: fgerlits $ - * @version $Revision: 1.8 $ + * @version $Revision: 1.9 $ * @see TestStorageClient */ class TestStorageClientTest : public CPPUNIT_NS::TestFixture @@ -71,6 +71,7 @@ class TestStorageClientTest : public CPPUNIT_NS::TestFixture CPPUNIT_TEST(audioClipTest); CPPUNIT_TEST(acquireAudioClipTest); CPPUNIT_TEST(acquirePlaylistTest); + CPPUNIT_TEST(searchTest); CPPUNIT_TEST_SUITE_END(); private: @@ -142,6 +143,14 @@ class TestStorageClientTest : public CPPUNIT_NS::TestFixture void acquirePlaylistTest(void) throw (CPPUNIT_NS::Exception); + /** + * Testing the search operations. + * + * @exception CPPUNIT_NS::Exception on test failures. + */ + void + searchTest(void) throw (CPPUNIT_NS::Exception); + public: diff --git a/livesupport/modules/storage/src/WebStorageClient.cxx b/livesupport/modules/storage/src/WebStorageClient.cxx index 6f56dd4b5..c8e2c4cf6 100644 --- a/livesupport/modules/storage/src/WebStorageClient.cxx +++ b/livesupport/modules/storage/src/WebStorageClient.cxx @@ -22,7 +22,7 @@ Author : $Author: fgerlits $ - Version : $Revision: 1.29 $ + Version : $Revision: 1.30 $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/storage/src/WebStorageClient.cxx,v $ ------------------------------------------------------------------------------*/ @@ -197,6 +197,35 @@ static const std::string resetStorageAudioClipResultParamName = "audioclips"; static const std::string resetStoragePlaylistResultParamName = "playlists"; +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ storage server constants: search */ + +/*------------------------------------------------------------------------------ + * The name of the search method on the storage server + *----------------------------------------------------------------------------*/ +static const std::string searchMethodName + = "locstor.searchMetadata"; + +/*------------------------------------------------------------------------------ + * The name of the session ID parameter in the input structure + *----------------------------------------------------------------------------*/ +static const std::string searchSessionIdParamName = "sessid"; + +/*------------------------------------------------------------------------------ + * The name of the search criteria parameter in the input structure + *----------------------------------------------------------------------------*/ +static const std::string searchCriteriaParamName = "criteria"; + +/*------------------------------------------------------------------------------ + * The name of the audio clips result parameter returned by the method + *----------------------------------------------------------------------------*/ +static const std::string searchAudioClipResultParamName = "audioClipResults"; + +/*------------------------------------------------------------------------------ + * The name of the playlists result parameter returned by the method + *----------------------------------------------------------------------------*/ +static const std::string searchPlaylistResultParamName = "playlistResults"; + + /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ playlist methods */ /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ storage server constants: createPlaylist */ @@ -1864,7 +1893,7 @@ WebStorageClient :: reset(void) } XmlRpcValue audioClipArray = result[resetStorageAudioClipResultParamName]; - testAudioClipIds.reset(new std::vector::Ref>); + audioClipIds.reset(new std::vector::Ref>); for (int i=0; i < audioClipArray.size(); i++) { if (audioClipArray[i].getType() != XmlRpcValue::TypeString) { @@ -1877,11 +1906,11 @@ WebStorageClient :: reset(void) } Ptr::Ref uniqueId(new UniqueId(std::string( audioClipArray[i]))); - testAudioClipIds->push_back(uniqueId); + audioClipIds->push_back(uniqueId); } XmlRpcValue playlistArray = result[resetStoragePlaylistResultParamName]; - testPlaylistIds.reset(new std::vector::Ref>); + playlistIds.reset(new std::vector::Ref>); for (int i=0; i < playlistArray.size(); i++) { if (playlistArray[i].getType() != XmlRpcValue::TypeString) { @@ -1894,7 +1923,101 @@ WebStorageClient :: reset(void) } Ptr::Ref uniqueId(new UniqueId(std::string( playlistArray[i]))); - testPlaylistIds->push_back(uniqueId); + playlistIds->push_back(uniqueId); } } + +/*------------------------------------------------------------------------------ + * Search for audio clips or playlists. + *----------------------------------------------------------------------------*/ +int +WebStorageClient :: search(Ptr::Ref sessionId, + Ptr::Ref searchCriteria) + throw (XmlRpcException) +{ + XmlRpcValue parameters; + XmlRpcValue result; + + XmlRpcClient xmlRpcClient(storageServerName.c_str(), storageServerPort, + storageServerPath.c_str(), false); + + parameters.clear(); + parameters[searchSessionIdParamName] + = sessionId->getId(); + parameters[searchCriteriaParamName] + = *searchCriteria; +// std::cerr << "\nparams: " << parameters.toXml() << "\n"; + + result.clear(); + if (!xmlRpcClient.execute(searchMethodName.c_str(), + parameters, result)) { + xmlRpcClient.close(); + std::string eMsg = "cannot execute XML-RPC method '"; + eMsg += searchMethodName; + eMsg += "'"; + throw XmlRpcCommunicationException(eMsg); + } + xmlRpcClient.close(); + +// std::cerr << "result: " << result.toXml() << "\n"; + if (xmlRpcClient.isFault()) { + std::stringstream eMsg; + eMsg << "XML-RPC method '" + << searchMethodName + << "' returned error message:\n" + << result; + throw XmlRpcMethodFaultException(eMsg.str()); + } + + if (! result.hasMember(searchAudioClipResultParamName) + || result[searchAudioClipResultParamName].getType() + != XmlRpcValue::TypeArray + || ! result.hasMember(searchPlaylistResultParamName) + || result[searchPlaylistResultParamName].getType() + != XmlRpcValue::TypeArray) { + std::stringstream eMsg; + eMsg << "XML-RPC method '" + << searchMethodName + << "' returned unexpected value:\n" + << result; + throw XmlRpcMethodResponseException(eMsg.str()); + } + + XmlRpcValue audioClipArray = result[searchAudioClipResultParamName]; + audioClipIds.reset(new std::vector::Ref>); + + for (int i=0; i < audioClipArray.size(); i++) { + if (audioClipArray[i].getType() != XmlRpcValue::TypeString) { + std::stringstream eMsg; + eMsg << "Non-string audio clip gunid returned by XML-RPC method '" + << searchMethodName + << "':\n" + << result; + throw XmlRpcMethodResponseException(eMsg.str()); + } + Ptr::Ref uniqueId(new UniqueId(std::string( + audioClipArray[i]))); + audioClipIds->push_back(uniqueId); + } + + XmlRpcValue playlistArray = result[searchPlaylistResultParamName]; + playlistIds.reset(new std::vector::Ref>); + + for (int i=0; i < playlistArray.size(); i++) { + if (playlistArray[i].getType() != XmlRpcValue::TypeString) { + std::stringstream eMsg; + eMsg << "Non-string playlist gunid returned by XML-RPC method '" + << searchMethodName + << "':\n" + << result; + throw XmlRpcMethodResponseException(eMsg.str()); + } + Ptr::Ref uniqueId(new UniqueId(std::string( + playlistArray[i]))); + playlistIds->push_back(uniqueId); + } + + return audioClipIds->size() + playlistIds->size(); +} + diff --git a/livesupport/modules/storage/src/WebStorageClient.h b/livesupport/modules/storage/src/WebStorageClient.h index 7825c6965..6f3ed90dc 100644 --- a/livesupport/modules/storage/src/WebStorageClient.h +++ b/livesupport/modules/storage/src/WebStorageClient.h @@ -22,7 +22,7 @@ Author : $Author: fgerlits $ - Version : $Revision: 1.20 $ + Version : $Revision: 1.21 $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/storage/src/WebStorageClient.h,v $ ------------------------------------------------------------------------------*/ @@ -42,11 +42,8 @@ #include -#include "LiveSupport/Core/Ptr.h" -#include "LiveSupport/Core/UniqueId.h" #include "LiveSupport/Core/Playlist.h" #include "LiveSupport/Core/Configurable.h" -#include "LiveSupport/Core/SessionId.h" #include "LiveSupport/Storage/StorageClientInterface.h" @@ -99,7 +96,7 @@ using namespace LiveSupport::Core; * * * @author $Author: fgerlits $ - * @version $Revision: 1.20 $ + * @version $Revision: 1.21 $ */ class WebStorageClient : virtual public Configurable, @@ -162,6 +159,19 @@ class WebStorageClient : Ptr::Ref& token) throw (XmlRpcException); + /** + * A vector containing the unique IDs of the audio clips returned + * by reset() (for testing) or by search(). + */ + Ptr::Ref> >::Ref audioClipIds; + + /** + * A vector containing the unique IDs of the playlists returned + * by reset() (for testing) or by search(). + */ + Ptr::Ref> >::Ref playlistIds; + + public: /** * A virtual destructor, as this class has virtual functions. @@ -505,18 +515,6 @@ class WebStorageClient : throw (XmlRpcException); - /** - * A vector containing the unique IDs of the audio clips in the - * storage. Set by reset(). Used for testing. - */ - Ptr::Ref> >::Ref testAudioClipIds; - - /** - * A vector containing the unique IDs of the playlists in the - * storage. Set by reset(). Used for testing. - */ - Ptr::Ref> >::Ref testPlaylistIds; - /** * Reset the storage to its initial state. * Calls locstor.resetStorage, and puts the unique IDs returned @@ -527,6 +525,51 @@ class WebStorageClient : void reset(void) throw (XmlRpcException); + + + /** + * Search for audio clips or playlists. The results can be read + * using getAudioClipIds() and getPlaylistIds(). + * + * @param sessionId the session ID from the authentication client + * @param searchCriteria an object containing the search criteria + * @return the number of items found. + * @exception XmlRpcException if there is a problem with the XML-RPC + * call. + */ + virtual int + search(Ptr::Ref sessionId, + Ptr::Ref searchCriteria) + throw (XmlRpcException); + + /** + * Return the list of audio clip IDs found by the search method. + * + * (Or the list of audio clip IDs returned by the reset() method + * -- used for testing.) + * + * @return a vector of UniqueId objects. + */ + virtual Ptr::Ref> >::Ref + getAudioClipIds(void) throw () + { + return audioClipIds; + } + + + /** + * Return the list of playlist IDs found by the search method. + * + * (Or the list of playlist IDs returned by the reset() method + * -- used for testing.) + * + * @return a vector of UniqueId objects. + */ + virtual Ptr::Ref> >::Ref + getPlaylistIds(void) throw () + { + return playlistIds; + } }; diff --git a/livesupport/modules/storage/src/WebStorageClientTest.cxx b/livesupport/modules/storage/src/WebStorageClientTest.cxx index 0ff30f5cc..79b2abdea 100644 --- a/livesupport/modules/storage/src/WebStorageClientTest.cxx +++ b/livesupport/modules/storage/src/WebStorageClientTest.cxx @@ -22,7 +22,7 @@ Author : $Author: fgerlits $ - Version : $Revision: 1.30 $ + Version : $Revision: 1.31 $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/storage/src/WebStorageClientTest.cxx,v $ ------------------------------------------------------------------------------*/ @@ -186,8 +186,8 @@ WebStorageClientTest :: playlistTest(void) } catch (XmlRpcException &e) { CPPUNIT_FAIL(e.what()); } - CPPUNIT_ASSERT(wsc->testAudioClipIds->size() >= 3); - Ptr::Ref audioClipId = wsc->testAudioClipIds->at(0); + CPPUNIT_ASSERT(wsc->getAudioClipIds()->size() >= 3); + Ptr::Ref audioClipId = wsc->getAudioClipIds()->at(0); Ptr::Ref sessionId; try { @@ -365,12 +365,12 @@ WebStorageClientTest :: audioClipTest(void) } catch (XmlRpcException &e) { CPPUNIT_FAIL(e.what()); } - CPPUNIT_ASSERT(wsc->testAudioClipIds->size() >= 2); - Ptr::Ref id01 = wsc->testAudioClipIds->at(1); + CPPUNIT_ASSERT(wsc->getAudioClipIds()->size() >= 2); + Ptr::Ref id01 = wsc->getAudioClipIds()->at(1); // std::cout << "\nReset storage result:\n"; -// for (unsigned i=0; i < wsc->testAudioClipIds->size(); i++) { -// std::cout << std::hex << std::string(*wsc->testAudioClipIds->at(i)) +// for (unsigned i=0; i < wsc->getAudioClipIds()->size(); i++) { +// std::cout << std::hex << std::string(*wsc->getAudioClipIds()->at(i)) // << std::endl; // } @@ -504,8 +504,8 @@ WebStorageClientTest :: simplePlaylistTest(void) } catch (XmlRpcException &e) { CPPUNIT_FAIL(e.what()); } - CPPUNIT_ASSERT(wsc->testAudioClipIds->size() >= 3); - Ptr::Ref audioClipId = wsc->testAudioClipIds->at(0); + CPPUNIT_ASSERT(wsc->getAudioClipIds()->size() >= 3); + Ptr::Ref audioClipId = wsc->getAudioClipIds()->at(0); Ptr::Ref sessionId; try { @@ -575,6 +575,74 @@ WebStorageClientTest :: simplePlaylistTest(void) } CPPUNIT_ASSERT(!newPlaylist->getUri()); */ + + try{ + authentication->logout(sessionId); + } catch (XmlRpcException &e) { + CPPUNIT_FAIL(e.what()); + } } +/*------------------------------------------------------------------------------ + * Search test. + *----------------------------------------------------------------------------*/ +void +WebStorageClientTest :: searchTest(void) + throw (CPPUNIT_NS::Exception) +{ +/* + try { + wsc->reset(); + } catch (XmlRpcException &e) { + CPPUNIT_FAIL(e.what()); + } + CPPUNIT_ASSERT(wsc->getAudioClipIds()->size() >= 3); + Ptr::Ref audioClip0 = wsc->getAudioClipIds()->at(0); + Ptr::Ref audioClip1 = wsc->getAudioClipIds()->at(1); + Ptr::Ref audioClip2 = wsc->getAudioClipIds()->at(2); + CPPUNIT_ASSERT(wsc->getPlaylistIds()->size() >= 1); + Ptr::Ref playlist0 = wsc->getPlaylistIds()->at(0); + + Ptr::Ref sessionId; + try { + sessionId = authentication->login("root", "q"); + } catch (XmlRpcException &e) { + CPPUNIT_FAIL(e.what()); + } + CPPUNIT_ASSERT(sessionId); + + try { + Ptr::Ref criteria(new SearchCriteria( + "audioClip", + "dc:title", "prefix", "File")); + int results = wsc->search(sessionId, criteria); + CPPUNIT_ASSERT(results == 2); + } catch (XmlRpcException &e) { + CPPUNIT_FAIL(e.what()); + } + CPPUNIT_ASSERT(wsc->getAudioClipIds()->size() == 2); + CPPUNIT_ASSERT(*wsc->getAudioClipIds()->at(0) == *audioClip0); + CPPUNIT_ASSERT(*wsc->getAudioClipIds()->at(1) == *audioClip1); + + try { + Ptr::Ref criteria(new SearchCriteria( + "playlist", "or")); + criteria->addCondition("dcterms:extent", ">=", "0"); + criteria->setLimit(10); + int results = wsc->search(sessionId, criteria); + CPPUNIT_ASSERT(results == 1); + } catch (XmlRpcException &e) { + CPPUNIT_FAIL(e.what()); + } + CPPUNIT_ASSERT(wsc->getPlaylistIds()->size() == 1); + CPPUNIT_ASSERT(*wsc->getPlaylistIds()->at(0) == *playlist0); + + try{ + authentication->logout(sessionId); + } catch (XmlRpcException &e) { + CPPUNIT_FAIL(e.what()); + } +*/ +} + diff --git a/livesupport/modules/storage/src/WebStorageClientTest.h b/livesupport/modules/storage/src/WebStorageClientTest.h index 1bf8f591d..e82eaab6a 100644 --- a/livesupport/modules/storage/src/WebStorageClientTest.h +++ b/livesupport/modules/storage/src/WebStorageClientTest.h @@ -21,8 +21,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - Author : $Author: maroy $ - Version : $Revision: 1.6 $ + Author : $Author: fgerlits $ + Version : $Revision: 1.7 $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/storage/src/WebStorageClientTest.h,v $ ------------------------------------------------------------------------------*/ @@ -62,8 +62,8 @@ using namespace LiveSupport::Authentication; /** * Unit test for the UploadPlaylistMetohd class. * - * @author $Author: maroy $ - * @version $Revision: 1.6 $ + * @author $Author: fgerlits $ + * @version $Revision: 1.7 $ * @see WebStorageClient */ class WebStorageClientTest : public CPPUNIT_NS::TestFixture @@ -73,6 +73,7 @@ class WebStorageClientTest : public CPPUNIT_NS::TestFixture CPPUNIT_TEST(simplePlaylistTest); CPPUNIT_TEST(playlistTest); CPPUNIT_TEST(audioClipTest); + CPPUNIT_TEST(searchTest); CPPUNIT_TEST_SUITE_END(); private: @@ -120,6 +121,14 @@ class WebStorageClientTest : public CPPUNIT_NS::TestFixture void playlistTest(void) throw (CPPUNIT_NS::Exception); + /** + * Testing the search operations. + * + * @exception CPPUNIT_NS::Exception on test failures. + */ + void + searchTest(void) throw (CPPUNIT_NS::Exception); + public: diff --git a/livesupport/modules/storageServer/var/tests/plist1.xml b/livesupport/modules/storageServer/var/tests/plist1.xml index 7f979019d..05f7aac39 100644 --- a/livesupport/modules/storageServer/var/tests/plist1.xml +++ b/livesupport/modules/storageServer/var/tests/plist1.xml @@ -1,9 +1,23 @@ - - - - - - + + + + + + + + + My First Playlist + Me, myself and I + 00:00:23.000000 + +