Data types in MMBase


Table of Contents

1. MMBase Data Types
2. Description of the Data-type XML
2.1. Description, class, default value, and properties
2.2. Restrictions
2.2.1. Enforcement and fixation
2.2.2. Error messages
2.2.3. Unique
2.2.4. Required
2.2.5. Minimal and maximal values
2.2.6. Minimal, maximal and fixed lengths
2.2.7. Patterns
2.3. Other properties & enumerations
2.3.1. Password
2.3.2. Enumerations
Enumeration from a Resource bundle
sorterclass attribute
Enumerations based on MMBase queries
2.4. Processors
2.4.1. Set-processors and Get-processors
2.4.2. Commit-processors
3. How to associate a data type with a field
4. Datatypes and the MMBase bridge
5. Datatypes and the MMBase Taglib
5.1. Forms & validation
6. Datatypes and JavaScript
7. Summary of default datatypes

MMBase datatypes are defined in the resource <MMBase configuration>/datatypes.xml. See the Xml Schema Definition, for a formal description of this XML format. This resource can exist multiple times, but there is at least one in mmbase.jar. The contents of that one are described in Section 7, “Summary of default datatypes”

Other jars (e.g. of MMBase components) can also provide such a datatypes.xml, which will also be read in, and added to the repository of available datatypes.

Of course you can also place your own datatypes.xml, e.g. just in WEB-INF/config.

On a running MMBase you can see which datatypes are available in /mmbase/validation/. See e.g. at /mmbase/validation at the mmbase.org site.

A datatypes.xml basically contains a list of 'datatype' entries. E.g.

<?xml version="1.0" ?>
<datatypes
    xmlns="http://www.mmbase.org/xmlns/datatypes"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.mmbase.org/xmlns/datatypes http://www.mmbase.org/xmlns/datatypes.xsd">


  <datatype id="integer">
    <description xml:lang="en">
      Not so very big integer numbers. Common base for all kind of enumerations.
    </description>
    <class name="org.mmbase.datatypes.IntegerDataType" />
  </datatype>
  ...

        
      
There are only a limited number of data types which can be defined like 'integer' in this example. Namely only the database types of MMBase (string, integer, binary, float, double, long, xml, node, datetime and boolean). All other datatypes are based on one of those. This can be done in two ways. As a sub element 'specialization':
<datatype id="float">
  <specialization id="scale1-10">
    <description xml:lang="en">A scale from 1 to 10.</description>
    <minInclusive value="1.0"  />
    <maxInclusive value="10.0"  />
  </specialization>
</datatype>
or as a 'datatype' element with a 'base' attribute.
<datatype base="float" id="scale1-10">
  <description xml:lang="en">A scale from 1 to 10.</description>
  <minInclusive value="1.0"  />
  <maxInclusive value="10.0"  />
</datatype>

It is also possible to replace a data type, by extending from the data type with the same id. This is only feasible in WEB-INF/config/datatypes because that one is parsed last.

<!-- In this site, email addresses are required -->
<datatype base="emailaddress" id="emailaddress">
  <required value="true">
    <description xml:lang="nl">Je moet een emailadres intypen</description>
    <description xml:lang="fr">Un address courriel est requis</description>
    <description xml:lang="en">An email address is required</description>
  </required>
</datatype>

In the following subsections we will elaborate a bit on the possible sub-elements of a datatype (or 'specialization') element.

You can start with descriptions (one for each language). These descriptions are used in automated overview pages (as e.g. in /mmbase/validation). If you define a data type for inclusion in mmbase.jar or in some component, it is advised to at least provide a description in English.

There can be one or no 'class' element then, which defines the actual implementation of the org.mmbase.datatypes.DataType interface which backs the data type. The class can often be inherited from the base data type. If not, the class must at least extend from the class from the base data type.

With every data type a default value is associated. E.g.

<datatype id="integer">
    <specialization id="colors">
      <description xml:lang="en">
        colors as can be used in css
      </description>
      <default value="white" />
      <enumeration>
        <entry basename="org.mmbase.datatypes.resources.string.colors" />
      </enumeration>
    </specialization>
The value is implicitly cast to the correct type. In this case 'white' can be converted to an integer, because there is a mapping present in the defined enumeration.

If the class of the data type supports properties which are not recognized by the data type XSD (as described in this document) then arbitrary properties can be set using 'property' sub elements.

<specialization id="confirmpassword">
  <description xml:lang="en">
    This is a field datatype that of which the value is only valid, if it is equal to the value
    of another field in this node. The other field's name is default 'password' but it can be
    changed by overriding the property 'field'.
  </description>
  <class name="org.mmbase.datatypes.ConfirmPasswordDataType" />
  <property name="field" value="password" />
</specialization>
In this case, the 'ConfirmPasswordDataType' class has a 'setField' method which is called when this data type is instantiated.

Several 'restrictions' can then be applied to further define the 'data type'. The following sub sections describe the possibilities.

It is also possible to restrict the values to the entries of a certain set. There are several ways to provided those certain values. The most basic one, is simply stating every value:

<specialization id="spells">
<!-- example to test -->
  <enumeration>
    <entry value="1" xml:lang="nl" display="hokus pokus" />
    <entry value="2" xml:lang="nl" display="simsalabim" />
    <entry value="3" xml:lang="nl" display="pilatus pas" />
    <entry value="4" xml:lang="nl" display="abcracadabra" />
    <entry value="2" xml:lang="en" display="simsalabim" />
    <entry value="3" xml:lang="en" display="pilatus pas" />
    <entry value="1" xml:lang="en" display="hocus pocus" />
  </enumeration>
</specialization>
You can see that you can enter the same value more than once, for different languages. The default value to display is the value itself, so it is not needed to specify localized display values.

Enumerations are most often used on data types with 'base="integer"', but can also work on string data types, and node data type (using 'query').

An enumeration is a restriction, but or course it is mainly a powerfull hint to produce a user interface using e.g. a dropdown list or so.

The data type also provides hooks to plug in functionality on several events like 'getting a value' 'setting a value' and 'committing the object which contains this data type'. This is at the moment only sensible for fields. MMBase provides several general purpose processors, which you can also use in your own datatypes. But of course you can also implement new ones (if you want to do that, we refer to the javadoc of the org.mmbase.datatype.processors package)

Lets take an example:

<specialization id="created">
  <description xml:lang="en">
    Read-only date-time field that contains the time of creation of the node.
  </description>
  <default value="now" />
  <setprocessor>
     <class name="org.mmbase.datatypes.processors.Readonly" />
  </setprocessor>
  <getprocessor type="*">
    <class name="org.mmbase.datatypes.processors.CreationTimeGuesser" />
  </getprocessor>
  <getprocessor type="string">
    <class name="org.mmbase.datatypes.processors.CreationTimeGuesser" />
    <class name="org.mmbase.datatypes.processors.FormatDateTime" />
  </getprocessor>
</specialization>
Using the 'type' attribute one of the MMBase database type can be associated with get- and setprocessors. Those database types also correspond to methods in the MMBase bridge 'Node' interface. In this case we see that when getting a value as a string ('getStringValue'), something else happens then when it is gotten otherwise ('getDateValue'). In this case the creation time is nicely formatted when the value is requested as a string.

The CreationTimeGuesser processor arranges that if the value is empty, it guesses an actual value using the MMBase 'day markers'.

In this example, there is also hooked in a class on the set-processor. Namely the processor which simply refuses the action, effectively leading to a read-only field. (The CreationTimeGuesser itself can use 'setObjectValue' to bypass all set-processors, if it wants to store its guessed value for efficiency).

Note

You can specify more than one class for a certain processor. They will be 'chained' in such a case.

Note

The class may also implemented org.mmbase.util.transformers.CharTransformer (or factory), in which case an instance of that class is simply wrapped into a Processor, which only transforms the value.

Note

The instances of the processors can be configured with 'param' subtags.

A data type specialization needs to be added to a field in a builder configuration file just before the 'db' section. By the way, since the datatypes can provide the necessary information, the db section can be omitted all together. The following example creates a lastmodified field for a node that is automatically adjusted every time a node is saved.

<field>
  <datatype xmlns="http://www.mmbase.org/xmlns/datatypes" base="lastmodified" />
  <db>
    <name>updated</name>
    <type key="false" notnull="false" state="system">DATETIME</type>
  </db>
</field>

which can also be noted like this.

<field name="updated" state="system">
  <datatype xmlns="http://www.mmbase.org/xmlns/datatypes" base="lastmodified">
    <required value="false" /> <!-- this is btw also the default -->
  </datatype>
</field>

As you can see, this is simply a part of the same XML as also used in datatypes.xml's. So, you can also 'anonymously' define or refine a data type just for one field.

When you use the bridge, you can get the data type associated with a certain field use the 'getDataType' method on 'Field'. Then you can use the interfaces of 'org.mmbase.datatypes' to explore the possible values.

If the mm:fieldinfo tag is used to create form-entries, then the data type of the field is explored to do that. If it e.g. detects that new-lines are permissible, then a textarea is created.

Since MMBase 1.8.5, the meta information provided by MMBase Data Types can also be accessed using JavaScript. For that you include the javascript file /mmbase/validation/validation.js.jsp, plus some other utilities (see /mmbase/valiation/test.jspx), and instatiate an "MMBaseValidator".

<html  xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <title>Test</title>
    <jsp:directive.include file="/mmbase/validation/javascript.jspxf" />
  </head>
  <body>
    <script type="text/javascript">new MMBaseValidator(window);</script>
    ... the rest of your page..

This javascript library searches (on load) all form elements with the class "mm_validate". 'onkeyup' events are added to all those elements.

The data type is determined by inspecting the css class names. If one starts with "mm_dt_" then the remaining is interpreted as the MMBase Data Type id. There can also be two class names, one starting with mm_f_ and mm_nm_ which can together identify the datatype of a certain field of a nodemanager.

The mm:fieldinfo tag of the MMBase Taglib will set up the correct CSS class for form elements that it creates.

As soon a data type meta information is needed, then this is requested (using 'ajax') with a call to /mmbase/validation/datatype.jspx. The resulting XML's are cached in MMBaseValidator.

This is a summary of all MMBase datatypes and their specializations found in the 'datatypes.xml' in mmbase.jar and as such are per default available. The basic data types (the 'database types') are xml, string, datetime, long, boolean, integer, long, float, double, binary and node, below their respective titles you will find their specializations.


This is part of the MMBase documentation.

For questions and remarks about this documentation mail to: [email protected]