diff --git a/livesupport/src/modules/core/etc/Makefile.in b/livesupport/src/modules/core/etc/Makefile.in index eb33b9b63..ee45c8875 100644 --- a/livesupport/src/modules/core/etc/Makefile.in +++ b/livesupport/src/modules/core/etc/Makefile.in @@ -141,7 +141,9 @@ CORE_LIB_OBJS = ${TMP_DIR}/UniqueId.o \ ${TMP_DIR}/MetadataTypeContainer.o \ ${TMP_DIR}/OptionsContainer.o \ ${TMP_DIR}/FileTools.o \ - ${TMP_DIR}/AsyncState.o + ${TMP_DIR}/AsyncState.o \ + ${TMP_DIR}/MetadataConstraint.o \ + ${TMP_DIR}/NumericConstraint.o TEST_RUNNER_OBJS = ${TMP_DIR}/TestRunner.o \ ${TMP_DIR}/FileToolsTest.o \ @@ -160,8 +162,8 @@ TEST_RUNNER_OBJS = ${TMP_DIR}/TestRunner.o \ ${TMP_DIR}/Md5Test.o \ ${TMP_DIR}/XmlRpcToolsTest.o \ ${TMP_DIR}/SearchCriteriaTest.o \ - ${TMP_DIR}/MetadataTypeContainerTest.o \ - ${TMP_DIR}/AsyncStateTest.o + ${TMP_DIR}/MetadataTypeContainerTest.o \ + ${TMP_DIR}/AsyncStateTest.o TEST_RUNNER_RES = ${TMP_DIR}/${PACKAGE_NAME}_root.res \ ${TMP_DIR}/${PACKAGE_NAME}_en.res \ diff --git a/livesupport/src/modules/core/etc/metadataTypeContainer.xml b/livesupport/src/modules/core/etc/metadataTypeContainer.xml index 7ebdf1f30..555446ff8 100644 --- a/livesupport/src/modules/core/etc/metadataTypeContainer.xml +++ b/livesupport/src/modules/core/etc/metadataTypeContainer.xml @@ -1,13 +1,18 @@ <?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE metadataTypeContainer [ -<!ELEMENT metadataType EMPTY > +<!ELEMENT metadataTypeContainer (metadataType+) > + +<!ELEMENT metadataType (constraint?) > <!ATTLIST metadataType dcName NMTOKEN #REQUIRED > <!ATTLIST metadataType id3Tag CDATA #IMPLIED > <!ATTLIST metadataType localizationKey CDATA #REQUIRED > <!ATTLIST metadataType tab NMTOKEN #IMPLIED > -<!ELEMENT metadataTypeContainer (metadataType+) > +<!ELEMENT constraint (value*) > +<!ATTLIST constraint type NMTOKEN #REQUIRED > + +<!ELEMENT value (CDATA) > ]> @@ -27,8 +32,9 @@ /> <metadataType dcName = "ls:year" id3Tag = "TYER" - localizationKey = "year" - /> + localizationKey = "year" > + <constraint type = "numeric" /> + </metadataType> <metadataType dcName = "dc:type" id3Tag = "TCON" localizationKey = "genre" @@ -42,8 +48,9 @@ /> <metadataType dcName = "ls:bpm" id3Tag = "TBPM" - localizationKey = "bpm" - /> + localizationKey = "bpm" > + <constraint type = "numeric" /> + </metadataType> <metadataType dcName = "ls:rating" id3Tag = "POPM" localizationKey = "rating" @@ -57,12 +64,14 @@ /> <metadataType dcName = "ls:track_num" id3Tag = "TRCK" - localizationKey = "track_number" - /> + localizationKey = "track_number" > + <constraint type = "numeric" /> + </metadataType> <metadataType dcName = "ls:disc_num" id3Tag = "TPOS" - localizationKey = "disc_number" - /> + localizationKey = "disc_number" > + <constraint type = "numeric" /> + </metadataType> <metadataType dcName = "ls:mood" id3Tag = "TMOO" localizationKey = "mood" @@ -79,11 +88,13 @@ localizationKey = "bitrate" /> <metadataType dcName = "ls:channels" - localizationKey = "channels" - /> + localizationKey = "channels" > + <constraint type = "numeric" /> + </metadataType> <metadataType dcName = "ls:samplerate" - localizationKey = "sample_rate" - /> + localizationKey = "sample_rate" > + <constraint type = "numeric" /> + </metadataType> <metadataType dcName = "ls:encoder" id3Tag = "TSSE" localizationKey = "encoding_software" diff --git a/livesupport/src/modules/core/include/LiveSupport/Core/MetadataConstraint.h b/livesupport/src/modules/core/include/LiveSupport/Core/MetadataConstraint.h new file mode 100644 index 000000000..83aadd3c4 --- /dev/null +++ b/livesupport/src/modules/core/include/LiveSupport/Core/MetadataConstraint.h @@ -0,0 +1,181 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2004 Media Development Loan Fund + + This file is part of the LiveSupport project. + http://livesupport.campware.org/ + To report bugs, send an e-mail to bugs@campware.org + + LiveSupport is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + LiveSupport is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with LiveSupport; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + + Author : $Author$ + Version : $Revision$ + Location : $URL$ + +------------------------------------------------------------------------------*/ +#ifndef LiveSupport_Core_MetadataConstraint_h +#define LiveSupport_Core_MetadataConstraint_h + +#ifndef __cplusplus +#error This is a C++ include file +#endif + + +/* ============================================================ include files */ + +#include "LiveSupport/Core/Ptr.h" +#include "LiveSupport/Core/Configurable.h" + + +namespace LiveSupport { +namespace Core { + + +/* ================================================================ constants */ + + +/* =================================================================== macros */ + + +/* =============================================================== data types */ + +/** + * A class for representing a constraint on the values of a metadata type. + * + * This is an abstract-cum-factory class for constructing the concrete + * constraint subclasses. You construct and configure this class, which + * will transparently construct the concrete subclass desired, and delegate + * the actual value checking to it. + * + * This object has to be configured with an XML configuration element + * called constraint. This may look like the following: + * + * <pre><code> + * <constraint type = "numericRange"> + * <value>1</value> + * <value>12</value> + * </constraint> + * </code></pre> + * + * The type attribute identifies this MetadataConstraint object as belonging + * to the subclass NumericRangeConstraint. Other subclasses are + * NumericConstraint, EnumerationConstraint etc. + * + * Each MetadataType object may contain an optional MetadataConstraint member + * object, which restricts the acceptable values for this metadata type. + * + * The DTD for the expected XML element looks like the following: + * + * <pre><code> + * <!ELEMENT constraint (value*) > + * <!ATTLIST constraint type NMTOKEN #REQUIRED > + * <!ELEMENT value (CDATA) > + * </code></pre> + * + * @author $Author$ + * @version $Revision$ + * @see MetadataConstraintContainer + */ +class MetadataConstraint : public Configurable +{ + private: + /** + * The name of the configuration XML element used by MetadataConstraint. + */ + static const std::string configElementNameStr; + + /** + * A reference to a concrete subclass. + */ + Ptr<MetadataConstraint>::Ref concreteConstraint; + + + protected: + /** + * The name of the type attribute. + */ + static const std::string typeAttributeName; + + /** + * The name of the configuration element for the constraint values. + */ + static const std::string valueElementName; + + + public: + /** + * Constructor. + */ + MetadataConstraint() throw () + { + } + + /** + * A virtual destructor, as this class has virtual functions. + */ + virtual + ~MetadataConstraint(void) throw () + { + } + + /** + * Return the name of the XML element this object expects + * to be sent to a call to configure(). + * + * @return the name of the expected XML configuration element. + */ + static const std::string + getConfigElementName(void) throw () + { + return configElementNameStr; + } + + /** + * Configure the metadata object based on an XML configuration element. + * + * @param elemen the XML configuration element. + * @exception std::invalid_argument of the supplied XML element + * contains bad configuration information + */ + virtual void + configure(const xmlpp::Element & element) + throw (std::invalid_argument); + + /** + * Check that the given value satisfies the constraint. + * + * @param value the value to be checked against the constraint. + * @return true if the value satisfies the constraint. + * @exception std::logic_error if the object has not been + * configured yet. + */ + virtual bool + check(Ptr<const Glib::ustring>::Ref value) const + throw (std::logic_error); +}; + + +/* ================================================= external data structures */ + + +/* ====================================================== function prototypes */ + + +} // namespace Core +} // namespace LiveSupport + +#endif // LiveSupport_Core_MetadataConstraint_h + diff --git a/livesupport/src/modules/core/include/LiveSupport/Core/MetadataType.h b/livesupport/src/modules/core/include/LiveSupport/Core/MetadataType.h index 2f1f733fe..8c7d39790 100644 --- a/livesupport/src/modules/core/include/LiveSupport/Core/MetadataType.h +++ b/livesupport/src/modules/core/include/LiveSupport/Core/MetadataType.h @@ -44,6 +44,7 @@ #include "LiveSupport/Core/Ptr.h" #include "LiveSupport/Core/Configurable.h" +#include "LiveSupport/Core/MetadataConstraint.h" namespace LiveSupport { @@ -71,8 +72,12 @@ class MetadataTypeContainer; * <metadataType dcName = "dc:creator" * id3Tag = "TPE2" * localizationKey = "dc_creator" - * tab = "main" - * /> + * tab = "main" > + * <constraint type = "numericRange" > + * <value>1</value> + * <value>12</value> + * </constraint> + * </metadataType> * </code></pre> * * The tab attribute (if present) must be one of "main", "music" or "voice" @@ -81,10 +86,14 @@ class MetadataTypeContainer; * the Main, Music, or Voice tab. If the attribute is omitted, the metadata * field will appear in none of the tabs. * + * The optional constraint sub-element can give restrictions on the acceptable + * values for this type of metadata. See the MetadataConstraint class for + * more information, including the DTD of the "constraint" element. + * * The DTD for the expected XML element looks like the following: * * <pre><code> - * <!ELEMENT metadataType EMPTY > + * <!ELEMENT metadataType (constraint?) > * <!ATTLIST metadataType dcName NMTOKEN #REQUIRED > * <!ATTLIST metadataType id3Tag NMTOKEN #IMPLIED > * <!ATTLIST metadataType localizationKey NMTOKEN #REQUIRED > @@ -141,6 +150,11 @@ class MetadataType : public Configurable */ TabType tab; + /** + * The constraint object, if any. + */ + Ptr<MetadataConstraint>::Ref constraint; + protected: /** @@ -255,6 +269,17 @@ class MetadataType : public Configurable { return tab; } + + /** + * Check that the given value satisfies the constraint. + * If the metadata type has no constraints, it returns true. + * If the constraint throws an exception, it returns false. + * + * @param value the value to be checked against the constraint. + * @return true if the value satisfies the constraint. + */ + bool + check(Ptr<const Glib::ustring>::Ref value) const throw (); }; diff --git a/livesupport/src/modules/core/include/LiveSupport/Core/MetadataTypeContainer.h b/livesupport/src/modules/core/include/LiveSupport/Core/MetadataTypeContainer.h index 7863a2aa5..bd0a39088 100644 --- a/livesupport/src/modules/core/include/LiveSupport/Core/MetadataTypeContainer.h +++ b/livesupport/src/modules/core/include/LiveSupport/Core/MetadataTypeContainer.h @@ -241,6 +241,23 @@ class MetadataTypeContainer : public Configurable, Ptr<const MetadataType>::Ref getById3Tag(const Glib::ustring id3Tag) throw (std::invalid_argument); + + /** + * Check that the given value satisfies the constraint of a metadata + * type. + * If the metadata type has no constraints, it returns true. + * If the constraint throws an exception, it returns false. + * + * @param dcName the metadata type, by its Dublin Core name. + * @param value the value to be checked against the constraint. + * @return true if the value satisfies the constraint. + * @exception std::invalid_argument if no metadata type exists + * with the suplied name. + */ + bool + check(const Glib::ustring & dcName, + Ptr<const Glib::ustring>::Ref value) + throw (std::invalid_argument); }; diff --git a/livesupport/src/modules/core/src/AudioClipTest.cxx b/livesupport/src/modules/core/src/AudioClipTest.cxx index 62b4a468f..e081decd4 100644 --- a/livesupport/src/modules/core/src/AudioClipTest.cxx +++ b/livesupport/src/modules/core/src/AudioClipTest.cxx @@ -84,7 +84,7 @@ static const std::string metadataConfigFileName * Set up the test environment *----------------------------------------------------------------------------*/ void -AudioClipTest :: setUp(void) throw () +AudioClipTest :: setUp(void) throw (CPPUNIT_NS::Exception) { try { Ptr<xmlpp::DomParser>::Ref parser( diff --git a/livesupport/src/modules/core/src/AudioClipTest.h b/livesupport/src/modules/core/src/AudioClipTest.h index 13a1e45bd..0fda6dbf7 100644 --- a/livesupport/src/modules/core/src/AudioClipTest.h +++ b/livesupport/src/modules/core/src/AudioClipTest.h @@ -123,7 +123,7 @@ class AudioClipTest : public CPPUNIT_NS::TestFixture * Set up the environment for the test case. */ void - setUp(void) throw (); + setUp(void) throw (CPPUNIT_NS::Exception); /** * Clean up the environment after the test case. diff --git a/livesupport/src/modules/core/src/MetadataConstraint.cxx b/livesupport/src/modules/core/src/MetadataConstraint.cxx new file mode 100644 index 000000000..08305f7c3 --- /dev/null +++ b/livesupport/src/modules/core/src/MetadataConstraint.cxx @@ -0,0 +1,105 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2004 Media Development Loan Fund + + This file is part of the LiveSupport project. + http://livesupport.campware.org/ + To report bugs, send an e-mail to bugs@campware.org + + LiveSupport is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + LiveSupport is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with LiveSupport; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + + Author : $Author$ + Version : $Revision$ + Location : $URL$ + +------------------------------------------------------------------------------*/ + +/* ============================================================ include files */ + +#include "LiveSupport/Core/MetadataConstraint.h" +#include "NumericConstraint.h" + + +using namespace LiveSupport::Core; + +/* =================================================== local data structures */ + + +/* ================================================ local constants & macros */ + +/*------------------------------------------------------------------------------ + * The name of the config element for this class + *----------------------------------------------------------------------------*/ +const std::string MetadataConstraint::configElementNameStr = "constraint"; + +/*------------------------------------------------------------------------------ + * The name of the type attribute. + *----------------------------------------------------------------------------*/ +const std::string MetadataConstraint::typeAttributeName = "type"; + +/*------------------------------------------------------------------------------ + * The name of the configuration element for the constraint values. + *----------------------------------------------------------------------------*/ +const std::string MetadataConstraint::valueElementName = "value"; + + +/* =============================================== local function prototypes */ + + +/* ============================================================= module code */ + +/*------------------------------------------------------------------------------ + * Create a constraint element object based on an XML element. + *----------------------------------------------------------------------------*/ +void +MetadataConstraint :: configure(const xmlpp::Element & element) + throw (std::invalid_argument) +{ + if (element.get_name() != configElementNameStr) { + throw std::invalid_argument("bad configuration element " + + element.get_name()); + } + + const xmlpp::Attribute* typeAttribute; + if (!(typeAttribute = element.get_attribute(typeAttributeName))) { + throw std::invalid_argument("missing attribute " + typeAttributeName); + } + std::string type = typeAttribute->get_value(); + + if (type == "numeric") { + concreteConstraint.reset(new NumericConstraint()); + concreteConstraint->configure(element); + + } else { + throw std::invalid_argument("unknown metadata constraint" + type); + } +} + + +/*------------------------------------------------------------------------------ + * Check that the given value satisfies the constraint. + *----------------------------------------------------------------------------*/ +inline bool +MetadataConstraint :: check(Ptr<const Glib::ustring>::Ref value) const + throw (std::logic_error) +{ + if (concreteConstraint) { + return concreteConstraint->check(value); + } else { + throw std::logic_error("MetadataConstraint not configured yet"); + } +} + diff --git a/livesupport/src/modules/core/src/MetadataType.cxx b/livesupport/src/modules/core/src/MetadataType.cxx index f3ce503f2..530fa710a 100644 --- a/livesupport/src/modules/core/src/MetadataType.cxx +++ b/livesupport/src/modules/core/src/MetadataType.cxx @@ -113,7 +113,7 @@ MetadataType :: configure(const xmlpp::Element & element) throw (std::invalid_argument) { if (element.get_name() != configElementNameStr) { - throw std::invalid_argument("bad coniguration element " + throw std::invalid_argument("bad configuration element " + element.get_name()); } @@ -149,6 +149,20 @@ MetadataType :: configure(const xmlpp::Element & element) tab = voiceTab; } } + + // get the constraint, optional + xmlpp::Node::NodeList childNodes = element.get_children( + MetadataConstraint::getConfigElementName()); + xmlpp::Node::NodeList::iterator it = childNodes.begin(); + + if (it != childNodes.end()) { + const xmlpp::Element * constraintElement + = dynamic_cast<const xmlpp::Element*> (*it); + if (constraintElement) { + constraint.reset(new MetadataConstraint()); + constraint->configure(*constraintElement); + } + } } @@ -162,3 +176,26 @@ MetadataType :: getLocalizedName(void) const return container->getResourceUstring(*localizationKey); } + +/*------------------------------------------------------------------------------ + * Check that the given value satisfies the constraint. + *----------------------------------------------------------------------------*/ +bool +MetadataType :: check(Ptr<const Glib::ustring>::Ref value) const + throw () +{ + if (!value) { + return false; + } + + if (constraint) { + try { + return constraint->check(value); + } catch (std::logic_error &e) { + return false; + } + } else { + return true; + } +} + diff --git a/livesupport/src/modules/core/src/MetadataTypeContainer.cxx b/livesupport/src/modules/core/src/MetadataTypeContainer.cxx index b1503eaa5..24132a363 100644 --- a/livesupport/src/modules/core/src/MetadataTypeContainer.cxx +++ b/livesupport/src/modules/core/src/MetadataTypeContainer.cxx @@ -63,7 +63,7 @@ MetadataTypeContainer :: configure(const xmlpp::Element & element) throw (std::invalid_argument) { if (element.get_name() != configElementNameStr) { - throw std::invalid_argument("bad coniguration element " + throw std::invalid_argument("bad configuration element " + element.get_name()); } @@ -156,3 +156,16 @@ MetadataTypeContainer :: getById3Tag(const Glib::ustring id3Tag) return id3TagMap[id3Tag]; } + +/*------------------------------------------------------------------------------ + * Check that the given value satisfies the constraint of a metadata type. + *----------------------------------------------------------------------------*/ +bool +MetadataTypeContainer :: check(const Glib::ustring & dcName, + Ptr<const Glib::ustring>::Ref value) + throw (std::invalid_argument) +{ + Ptr<const MetadataType>::Ref metadataType = getByDcName(dcName); + return metadataType->check(value); +} + diff --git a/livesupport/src/modules/core/src/MetadataTypeContainerTest.cxx b/livesupport/src/modules/core/src/MetadataTypeContainerTest.cxx index 95e91fb1e..d02a96383 100644 --- a/livesupport/src/modules/core/src/MetadataTypeContainerTest.cxx +++ b/livesupport/src/modules/core/src/MetadataTypeContainerTest.cxx @@ -81,7 +81,7 @@ static const std::string configFileName = "etc/metadataTypeContainer.xml"; * Set up the test environment *----------------------------------------------------------------------------*/ void -MetadataTypeContainerTest :: setUp(void) throw () +MetadataTypeContainerTest :: setUp(void) throw (CPPUNIT_NS::Exception) { Ptr<ResourceBundle>::Ref rootBundle; try { @@ -304,3 +304,26 @@ MetadataTypeContainerTest :: localizedTest(void) CPPUNIT_ASSERT((*ustr)[5] == 0x30fc); // katakana '-' } + +/*------------------------------------------------------------------------------ + * Test to see if the constraints work. + *----------------------------------------------------------------------------*/ +void +MetadataTypeContainerTest :: constraintTest(void) + throw (CPPUNIT_NS::Exception) +{ + // test the case of no constraint; everything is OK + Ptr<Glib::ustring>::Ref title; + CPPUNIT_ASSERT(!container->check("dc:title", title)); // except a 0 pointer + title.reset(new Glib::ustring("Some title")); + CPPUNIT_ASSERT(container->check("dc:title", title)); + + // test the numeric constraint; [0-9]+ required + Ptr<Glib::ustring>::Ref year(new Glib::ustring ("1000")); + CPPUNIT_ASSERT(container->check("ls:bpm", year)); + year->assign("2000 or more"); + CPPUNIT_ASSERT(!container->check("ls:bpm", year)); + year->assign(""); + CPPUNIT_ASSERT(!container->check("ls:bpm", year)); +} + diff --git a/livesupport/src/modules/core/src/MetadataTypeContainerTest.h b/livesupport/src/modules/core/src/MetadataTypeContainerTest.h index d8e7cfd5b..c86eb090e 100644 --- a/livesupport/src/modules/core/src/MetadataTypeContainerTest.h +++ b/livesupport/src/modules/core/src/MetadataTypeContainerTest.h @@ -67,6 +67,7 @@ class MetadataTypeContainerTest : public CPPUNIT_NS::TestFixture CPPUNIT_TEST(firstTest); CPPUNIT_TEST(iteratorTest); CPPUNIT_TEST(localizedTest); + CPPUNIT_TEST(constraintTest); CPPUNIT_TEST_SUITE_END(); protected: @@ -105,6 +106,14 @@ class MetadataTypeContainerTest : public CPPUNIT_NS::TestFixture void localizedTest(void) throw (CPPUNIT_NS::Exception); + /** + * Test to see if the constraints work. + * + * @exception CPPUNIT_NS::Exception on test failures. + */ + void + constraintTest(void) throw (CPPUNIT_NS::Exception); + public: @@ -112,7 +121,7 @@ class MetadataTypeContainerTest : public CPPUNIT_NS::TestFixture * Set up the environment for the test case. */ void - setUp(void) throw (); + setUp(void) throw (CPPUNIT_NS::Exception); /** * Clean up the environment after the test case. diff --git a/livesupport/src/modules/core/src/NumericConstraint.cxx b/livesupport/src/modules/core/src/NumericConstraint.cxx new file mode 100644 index 000000000..fc9b7d328 --- /dev/null +++ b/livesupport/src/modules/core/src/NumericConstraint.cxx @@ -0,0 +1,108 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2004 Media Development Loan Fund + + This file is part of the LiveSupport project. + http://livesupport.campware.org/ + To report bugs, send an e-mail to bugs@campware.org + + LiveSupport is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + LiveSupport is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with LiveSupport; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + + Author : $Author$ + Version : $Revision$ + Location : $URL$ + +------------------------------------------------------------------------------*/ + +/* ============================================================ include files */ + +#include "NumericConstraint.h" + + +using namespace LiveSupport::Core; + +/* =================================================== local data structures */ + + +/* ================================================ local constants & macros */ + +namespace { + +/*------------------------------------------------------------------------------ + * The value of the type attribute for this class + *----------------------------------------------------------------------------*/ +const std::string typeAttributeValue = "numeric"; + +} + + +/* =============================================== local function prototypes */ + + +/* ============================================================= module code */ + +/*------------------------------------------------------------------------------ + * Create a constraint element object based on an XML element. + *----------------------------------------------------------------------------*/ +void +NumericConstraint :: configure(const xmlpp::Element & element) + throw (std::invalid_argument) +{ + if (element.get_name() != MetadataConstraint::getConfigElementName()) { + throw std::invalid_argument("bad configuration element " + + element.get_name()); + } + + const xmlpp::Attribute* typeAttribute; + if (!(typeAttribute = element.get_attribute(typeAttributeName))) { + throw std::invalid_argument("missing attribute " + typeAttributeName); + } + std::string type = typeAttribute->get_value(); + + if (type != typeAttributeValue) { + throw std::invalid_argument("numeric constraint configured with a " + "constraint element of type " + type); + } +} + + +/*------------------------------------------------------------------------------ + * Check that the given value satisfies the constraint. + *----------------------------------------------------------------------------*/ +bool +NumericConstraint :: check(Ptr<const Glib::ustring>::Ref value) const + throw (std::logic_error) +{ + if (!value) { + throw std::logic_error("NumericConstraint::check() called with " + "a 0 pointer value"); + } + + Glib::ustring::const_iterator it = value->begin(); + + if (it == value->end()) { // the empty string is not a number + return false; + } + + for (; it != value->end(); ++it) { + if (*it < '0' || *it > '9') { + return false; + } + } + + return true; +} + diff --git a/livesupport/src/modules/core/src/NumericConstraint.h b/livesupport/src/modules/core/src/NumericConstraint.h new file mode 100644 index 000000000..e98ae4673 --- /dev/null +++ b/livesupport/src/modules/core/src/NumericConstraint.h @@ -0,0 +1,153 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2004 Media Development Loan Fund + + This file is part of the LiveSupport project. + http://livesupport.campware.org/ + To report bugs, send an e-mail to bugs@campware.org + + LiveSupport is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + LiveSupport is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with LiveSupport; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + + Author : $Author$ + Version : $Revision$ + Location : $URL$ + +------------------------------------------------------------------------------*/ +#ifndef LiveSupport_Core_NumericConstraint_h +#define LiveSupport_Core_NumericConstraint_h + +#ifndef __cplusplus +#error This is a C++ include file +#endif + + +/* ============================================================ include files */ + +#include "LiveSupport/Core/MetadataConstraint.h" + + +namespace LiveSupport { +namespace Core { + + +/* ================================================================ constants */ + + +/* =================================================================== macros */ + + +/* =============================================================== data types */ + +/** + * A class for representing a numeric metadata constraint. + * + * This is a concrete subclass of NumericConstraint. Do not explicitly + * instantiate this class; create a NumericConstraint object instead, and + * configure it with an XML element with the appropriate type attribute. + * + * This object has to be configured with an XML configuration element + * called constraint. This may look like the following: + * + * <pre><code> + * <constraint type = "numeric"/> + * </code></pre> + * + * A metadata type with this kind of constraint can only accept (decimal, + * non-negative) integer values, i.e., [0-9]+. + * + * The DTD for the expected XML element looks like the following: + * + * <pre><code> + * <!ELEMENT constraint EMPTY > + * <!ATTLIST constraint type "numeric" #FIXED > + * </code></pre> + * + * @author $Author$ + * @version $Revision$ + * @see NumericConstraintContainer + */ +class NumericConstraint : public MetadataConstraint +{ + private: + /** + * The name of the configuration XML element used by NumericConstraint. + */ + static const std::string configElementNameStr; + + + public: + /** + * Constructor. + */ + NumericConstraint() throw () + { + } + + /** + * A virtual destructor, as this class has virtual functions. + */ + virtual + ~NumericConstraint(void) throw () + { + } + + /** + * Return the name of the XML element this object expects + * to be sent to a call to configure(). + * + * @return the name of the expected XML configuration element. + */ + static const std::string + getConfigElementName(void) throw () + { + return configElementNameStr; + } + + /** + * Configure the metadata object based on an XML configuration element. + * + * @param elemen the XML configuration element. + * @exception std::invalid_argument of the supplied XML element + * contains bad configuration information + */ + virtual void + configure(const xmlpp::Element &element) + throw (std::invalid_argument); + + /** + * Check that the given value satisfies the constraint. + * + * @param value the value to be checked against the constraint. + * @return true if the value satisfies the constraint. + * @exception std::logic_error if the parameter is a 0 pointer. + */ + virtual bool + check(Ptr<const Glib::ustring>::Ref value) const + throw (std::logic_error); +}; + + +/* ================================================= external data structures */ + + +/* ====================================================== function prototypes */ + + +} // namespace Core +} // namespace LiveSupport + +#endif // LiveSupport_Core_NumericConstraint_h +