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
+