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

    <bean id="acmDataSource" class="org.apache.tomcat.jdbc.pool.DataSource" destroy-method="close">
        <property name="driverClassName" value="#{dataSourceConfig.driverClassName}"/>
        <property name="url" value="#{dataSourceConfig.url}"/>
        <property name="username" value="#{dataSourceConfig.username}"/>
        <property name="password" value="#{dataSourceConfig.password}"/>
        <property name="initialSize" value="#{dataSourceConfig.initialSize}"/>
        <property name="maxActive" value="#{dataSourceConfig.maxActive}"/>
        <property name="maxIdle" value="#{dataSourceConfig.maxActive}"/>
        <property name="minIdle" value="#{dataSourceConfig.minIdle}"/>
        <property name="maxWait" value="#{dataSourceConfig.maxWait}"/>
        <property name="maxAge" value="5000"/>
        <property name="testOnBorrow" value="#{dataSourceConfig.testOnBorrow}"/>
        <property name="testOnReturn" value="#{dataSourceConfig.testOnReturn}"/>
        <!--<property name="test" value="${acm.idleConnectionTestPeriodInSeconds}"/>-->
        <property name="validationQuery" value="#{dataSourceConfig.validationQuery}"/>
        <property name="loginTimeout" value="#{dataSourceConfig.maxWait}"/>
        <property name="defaultAutoCommit" value="#{dataSourceConfig.autoCommit}"/>
        <property name="logAbandoned" value="true"/>
        <property name="minEvictableIdleTimeMillis" value="1000"/>
        <property name="removeAbandoned" value="true"/>
        <property name="removeAbandonedTimeout" value="#{dataSourceConfig.abandonedTimeoutInSeconds}"/>
        <property name="timeBetweenEvictionRunsMillis" value="3000"/>
        <property name="testOnConnect" value="true"/>
        <property name="jdbcInterceptors" value="#{dataSourceConfig.jdbcInterceptors}"/>
    </bean>

    <bean id="converterScanPostProcessor" class="com.armedia.acm.data.converter.ConverterScanPostProcessor">
        <property name="packagesToScan" value="#{dataSourceConfig.jpaModelPackages}"/>
    </bean>

    <bean id="acmPersistenceUnitManager" class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager">
        <property name="defaultDataSource" ref="acmDataSource"/>
        <property name="packagesToScan" value="#{dataSourceConfig.jpaModelPackages}"/>
        <property name="persistenceUnitPostProcessors">
            <list>
                <ref bean="converterScanPostProcessor"/>
            </list>
        </property>
    </bean>

    <bean id="acmEntityManager" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <!--<property name="dataSource" ref="acmDataSource"/>-->
        <property name="jpaDialect" ref="eclipseLinkDialect"/>
        <property name="persistenceProviderClass" value="org.eclipse.persistence.jpa.PersistenceProvider"/>
        <property name="jpaPropertyMap">
            <props>
                <prop key="eclipselink.weaving">false</prop>
                <prop key="eclipselink.logging.level">#{dataSourceConfig.eclipseLinkLoggingLevel}</prop>
                <prop key="eclipselink.logging.logger">#{dataSourceConfig.eclipseLinkLoggingLogger}</prop>
                <!-- The EclipseLink core cache causes unusual things to happen unless every single database
           update is through EclipseLink.  For ACM this mostly will not be true; most customers will have
           batch feeds and other processes that modify the share database without using the application
           code.  May have to find another way around this if performance testing turns into an issue.
           But for now we'll err on the side of correctness (i.e. accurate database info) -->
                <prop key="eclipselink.cache.shared.default">false</prop>
                <prop key="eclipselink.persistence-context.close-on-commit">true</prop>
                <prop key="eclipselink.validate-existence">true</prop>
                <prop key="eclipselink.jdbc.sequence-connection-pool">true</prop>
                <!--<prop key="eclipselink.connection-pool.initial">5</prop>-->
                <!--<prop key="eclipselink.connection-pool.min">5</prop>-->
                <!--<prop key="eclipselink.connection-pool.max">10</prop>-->
                <!--<prop key="eclipselink.connection-pool.wait">500</prop>-->
                <!--<prop key="eclipselink.connection-pool.url">${acm.url}</prop>-->
                <!--<prop key="eclipselink.connection-pool.user">${acm.username}</prop>-->
                <!--<prop key="eclipselink.connection-pool.password">${acm.password}</prop>-->
                <!--<prop key="eclipselink.connection-pool.shared">false</prop>-->
                <!--<prop key="eclipselink.connection-pool.jtaDataSource">jdbc/acmDataSource</prop>-->
                <!--<prop key="eclipselink.connection-pool.nonJtaDataSource">jdbc/acmDataSource</prop>-->

            </props>
        </property>
        <property name="jpaVendorAdapter" ref="jpaVendorAdapter"/>
        <property name="persistenceUnitManager" ref="acmPersistenceUnitManager"/>
    </bean>

    <bean id="objectChangesBySessionAccumulator" class="com.armedia.acm.data.ObjectChangesBySessionAccumulator"/>

    <bean id="sessionCommitListener" class="com.armedia.acm.data.SessionAccumulatingSessionListener">
        <property name="descriptorListener" ref="objectChangesBySessionAccumulator"/>
    </bean>

    <bean id="acmObjectChangeNotifier" class="com.armedia.acm.data.AcmObjectChangedNotifier">
        <property name="objectEventChannel" ref="objectEventChannel"/>
    </bean>
    <bean id="acmObjectChangedLogger" class="com.armedia.acm.data.AcmObjectChangedLogger"/>

    <int:service-activator ref="acmObjectChangedLogger" input-channel="objectEventChannel" method="logObject"/>

    <bean id="acmProgressNotifier" class="com.armedia.acm.data.AcmProgressNotifier">
        <property name="genericMessagesChannel" ref="genericMessagesChannel"/>
    </bean>

    <bean id="acmServiceLdapSyncNotifier" class="com.armedia.acm.data.AcmServiceLdapSyncNotifier">
        <property name="genericMessagesChannel" ref="genericMessagesChannel"/>
    </bean>

    <bean id="acmProgressNotifierInitializer" class="com.armedia.acm.data.AcmProgressNotifierInitializer">
        <property name="progressNotifier" ref="acmProgressNotifier"/>
    </bean>

    <bean id="auditPropertyEntityAdapter" class="com.armedia.acm.data.AuditPropertyEntityAdapter"/>

    <bean id="springEntityListenerConfigurer" class="com.armedia.acm.data.SpringEntityListenerConfigurer">
        <property name="springContextHolder" ref="acmContextHolder"/>
        <property name="entityManagerFactory" ref="acmEntityManager"/>
        <property name="sessionListener" ref="sessionCommitListener"/>
        <property name="defaultListeners">
            <list>
                <ref bean="objectChangesBySessionAccumulator"/>
                <ref bean="auditPropertyEntityAdapter"/>
            </list>
        </property>
    </bean>

    <bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
        <property name="staticMethod" value="com.armedia.acm.data.converter.StringEncryptionConverter.setAcmDecryptionProperties"/>
        <property name="arguments">
            <list>
                <value type="java.lang.Boolean">#{dataSourceConfig.encryptionEnabled}</value>
                <ref bean="acmCryptoUtils"/>
                <value type="java.lang.String">#{dataSourceConfig.encryptionPassphrase}</value>
                <value type="java.lang.Boolean">#{dataSourceConfig.encryptionSupported}</value>

            </list>
        </property>
    </bean>

    <bean id="eclipseLinkDialect" class="org.springframework.orm.jpa.vendor.EclipseLinkJpaDialect">
        <property name="lazyDatabaseTransaction" value="false"/>
    </bean>

    <bean id="jpaVendorAdapter" class="org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter">
        <property name="databasePlatform" value="#{dataSourceConfig.databasePlatform}"/>
        <property name="generateDdl" value="false"/>
        <property name="showSql" value="#{dataSourceConfig.showSql}"/>
    </bean>

    <!-- JPA transaction manager (use JtaTransactionManager for
         global tx) -->
    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="dataSource" ref="acmDataSource"/>
    </bean>

    <!-- enable transaction demarcation with annotations -->
    <tx:annotation-driven transaction-manager="transactionManager"/>

    <!-- bean post-processor for JPA annotations -->
    <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>

    <!-- jdbc template for non-JPA resources e.g. lists of values -->
    <bean id="acmJdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <constructor-arg index="0" ref="acmDataSource"/>
    </bean>

    <!-- generate the database structures -->
    <bean id="liquibase" class="liquibase.integration.spring.SpringLiquibase">
        <property name="dataSource" ref="acmDataSource"/>
        <property name="changeLog" value="classpath:/ddl/acm-database-changelog.xml"/>
        <property name="shouldRun" value="#{dataSourceConfig.autoUpdate}"/>
        <!--<property name="dropFirst" value="true"/>-->

        <!--
        contexts specifies the runtime contexts to use.
        -->
        <!--<property name="contexts" value="test, production" />-->
    </bean>

    <bean id="dataSourceConfig" class="com.armedia.acm.data.AcmDataSourceConfig" scope="refresh" depends-on="configSource">
        <aop:scoped-proxy/>
    </bean>
</beans>