4.2.2.3.3. Example of a Custom Datatype

Let us consider the implementation of a custom GeoCoordinateDatatype, intended for the attributes storing geographical coordinates.

First, create the following class in the global module:

package com.company.sample;

import com.haulmont.chile.core.datatypes.Datatypes;
import com.haulmont.chile.core.datatypes.FormatStrings;
import com.haulmont.chile.core.datatypes.impl.DoubleDatatype;
import org.apache.commons.lang.StringUtils;
import org.dom4j.Element;

import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.Locale;

public class GeoCoordinateDatatype extends DoubleDatatype {

    // This field is required for Studio even if you don't use it in code
    public static final String NAME = "geocoordinate";

    // The format is the same for all locales but may differ in decimal points
    public static final String FORMAT = "#0.000000";

    public GeoCoordinateDatatype(Element element) {
        super(element);
    }

    @Override
    public String getName() {
        return NAME;
    }

    @Override
    public String format(Object value, Locale locale) {
        if (value == null)
            return "";
        FormatStrings formatStrings = Datatypes.getFormatStrings(locale);
        if (formatStrings == null)
            return format(value);

        NumberFormat format = new DecimalFormat(FORMAT, formatStrings.getFormatSymbols());
        return format.format(value);
    }

    @Override
    public Double parse(String value, Locale locale) throws ParseException {
        if (StringUtils.isBlank(value))
            return null;
        FormatStrings formatStrings = Datatypes.getFormatStrings(locale);
        if (formatStrings == null)
            return parse(value);

        NumberFormat format = new DecimalFormat(FORMAT, formatStrings.getFormatSymbols());
        return parse(value, format).doubleValue();
    }
}

Next, create the datatypes.xml file in the root of the global module src directory in the application project and copy contents from the /com/haulmont/chile/core/datatypes/datatypes.xml file located in global module of the CUBA application component. Then add registration of the new type to it:

<datatypes>

    <datatype class="com.company.sample.GeoCoordinateDatatype"
              format="#0.000000" decimalSeparator="." groupingSeparator=""
              javaType="java.lang.Double"/>

    <!-- copied from /com/haulmont/chile/core/datatypes/datatypes.xml -->

    <datatype class="com.haulmont.chile.core.datatypes.impl.BooleanDatatype"/>
    <datatype class="com.haulmont.chile.core.datatypes.impl.IntegerDatatype"
              format="0" groupingSeparator=""/>
    <datatype class="com.haulmont.chile.core.datatypes.impl.LongDatatype"
              format="0" groupingSeparator=""/>
    <datatype class="com.haulmont.chile.core.datatypes.impl.DoubleDatatype"
              format="0.###" decimalSeparator="." groupingSeparator=""/>
    <datatype class="com.haulmont.chile.core.datatypes.impl.BigDecimalDatatype"
              format="0.####" decimalSeparator="." groupingSeparator=""/>
    <datatype class="com.haulmont.chile.core.datatypes.impl.StringDatatype"/>
    <datatype class="com.haulmont.chile.core.datatypes.impl.DateTimeDatatype"
              format="yyyy-MM-dd HH:mm:ss.SSS"/>
    <datatype class="com.haulmont.chile.core.datatypes.impl.DateDatatype"
              format="yyyy-MM-dd"/>
    <datatype class="com.haulmont.chile.core.datatypes.impl.TimeDatatype"
              format="HH:mm:ss"/>
    <datatype class="com.haulmont.chile.core.datatypes.impl.UUIDDatatype"/>
    <datatype class="com.haulmont.chile.core.datatypes.impl.ByteArrayDatatype"/>

</datatypes>

In the datatype element, you can also specify the sqlType attribute containing an SQL type of your database suitable for storing values of the new type. This SQL type will be used by CUBA Studio when it generates database scripts. Studio can automatically determine an SQL type for the following Java types:

  • java.lang.Boolean

  • java.lang.Integer

  • java.lang.Long

  • java.math.BigDecimal

  • java.lang.Double

  • java.lang.String

  • java.util.Date

  • java.util.UUID

  • byte[]

If you have specified one of the listed Java types in the javaType attribute, the sqlType attribute can be omitted.

Finally, specify the new datatype for the required attributes (the new data type will also be available in the Studio entity attribute editor):

@MetaProperty(datatype = GeoCoordinateDatatype.NAME)
@Column(name = "LATITUDE")
private Double latitude;

After the above listed operations are completed, the latitude attribute will be displayed in the desired format throughout the application.