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 @@
+
+
+
-
+
+
+
+
]>
@@ -27,8 +32,9 @@
/>
+ *
+ *
+ * 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:
+ *
+ *
+ *
+ * @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
+ *
+ *
+ *
+ *
- *
+ *
*
*
*
@@ -141,6 +150,11 @@ class MetadataType : public Configurable
*/
TabType tab;
+ /**
+ * The constraint object, if any.
+ */
+ Ptr::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::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::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::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::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::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 (*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::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::Ref value)
+ throw (std::invalid_argument)
+{
+ Ptr::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::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::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::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::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:
+ *
+ *
+ *
+ *
+ *
+ * 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:
+ *
+ *
+ *
+ *
+ *
+ *
+ * @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::Ref value) const
+ throw (std::logic_error);
+};
+
+
+/* ================================================= external data structures */
+
+
+/* ====================================================== function prototypes */
+
+
+} // namespace Core
+} // namespace LiveSupport
+
+#endif // LiveSupport_Core_NumericConstraint_h
+