<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!-- set JSON date format to ISO-8601 e.g. 1970-01-01T00:00:00Z -->
    <bean id="sourceObjectMapper" class="com.fasterxml.jackson.databind.ObjectMapper"/>

    <!-- NOTE: When configuring 'sourceObjectMapper' make sure the static methods in ObjectConverter class are also updated -->
    <bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
        <property name="targetObject" ref="sourceObjectMapper"/>
        <property name="targetMethod" value="disable"/>
        <property name="arguments" value="WRITE_DATES_AS_TIMESTAMPS"/>
    </bean>
    <bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
        <property name="targetObject" ref="sourceObjectMapper"/>
        <property name="targetMethod" value="disable"/>
        <property name="arguments" value="FAIL_ON_UNKNOWN_PROPERTIES"/>
    </bean>

    <bean id="dateTimeSerializerFormatter" class="java.time.format.DateTimeFormatter" factory-method="ofPattern">
        <constructor-arg value="yyyy-MM-dd'T'HH:mm:ss.SSS'Z'" />
    </bean>

    <bean id="localDateTimeSerializer" class="com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer">
        <constructor-arg ref="dateTimeSerializerFormatter" />
    </bean>

    <bean id="dateSerializerFormatter" class="java.text.SimpleDateFormat">
        <constructor-arg value="yyyy-MM-dd'T'HH:mm:ss.SSS'Z'" />
    </bean>

    <bean id="dateSerializer" class="com.fasterxml.jackson.databind.ser.std.DateSerializer">
        <constructor-arg value="false" />
        <constructor-arg ref="dateSerializerFormatter" />
    </bean>

    <bean id="objectConverterFactory" class="com.armedia.acm.objectonverter.ObjectConverter"/>
    <bean id="dateTimeDeserializerFormatter" class="java.time.format.DateTimeFormatter" factory-bean="objectConverterFactory" factory-method="getISODateTimeFormatter" />

    <bean id="localDateTimeDeserializer" class="com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer">
        <constructor-arg ref="dateTimeDeserializerFormatter" />
    </bean>

    <bean id="javaTimeModule" class="com.fasterxml.jackson.datatype.jsr310.JavaTimeModule"/>

    <bean id="localDateTimeClass" class="java.lang.Class" factory-method="forName">
        <constructor-arg value="java.time.LocalDateTime"/>
    </bean>

    <bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
        <property name="targetObject" ref="javaTimeModule"/>
        <property name="targetMethod" value="addSerializer"/>
        <property name="arguments">
            <list>
                <ref bean="localDateTimeClass"/>
                <ref bean="localDateTimeSerializer"/>
            </list>
        </property>
    </bean>

    <bean id="dateClass" class="java.lang.Class" factory-method="forName">
        <constructor-arg value="java.util.Date"/>
    </bean>

    <bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
        <property name="targetObject" ref="javaTimeModule"/>
        <property name="targetMethod" value="addSerializer"/>
        <property name="arguments">
            <list>
                <ref bean="dateClass"/>
                <ref bean="dateSerializer"/>
            </list>
        </property>
    </bean>

    <bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
        <property name="targetObject" ref="javaTimeModule"/>
        <property name="targetMethod" value="addDeserializer"/>
        <property name="arguments">
            <list>
                <ref bean="localDateTimeClass"/>
                <ref bean="localDateTimeDeserializer"/>
            </list>
        </property>
    </bean>

    <bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
        <property name="targetObject" ref="sourceObjectMapper"/>
        <property name="targetMethod" value="registerModule"/>
        <property name="arguments" ref="javaTimeModule"/>
    </bean>

    <bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
        <property name="targetObject" ref="sourceObjectMapper"/>
        <property name="targetMethod" value="findAndRegisterModules"/>
    </bean>

    <bean id="jsonMarshaller" class="com.armedia.acm.objectonverter.json.JSONMarshaller">
        <property name="mapper" ref="sourceObjectMapper"/>
    </bean>

    <bean id="jsonUnmarshaller" class="com.armedia.acm.objectonverter.json.JSONUnmarshaller">
        <property name="mapper" ref="sourceObjectMapper"/>
    </bean>

    <bean id="xmlMarshaller" class="com.armedia.acm.objectonverter.xml.XMLMarshaller"/>

    <bean id="xmlUnmarshaller" class="com.armedia.acm.objectonverter.xml.XMLUnmarshaller"/>

    <bean id="objectConverter" class="com.armedia.acm.objectonverter.ObjectConverter">
        <property name="jsonMarshaller" ref="jsonMarshaller"/>
        <property name="jsonUnmarshaller" ref="jsonUnmarshaller"/>
        <property name="xmlMarshaller" ref="xmlMarshaller"/>
        <property name="xmlUnmarshaller" ref="xmlUnmarshaller"/>
    </bean>

</beans>