<?xml version="1.0" encoding="UTF-8" ?>

<!DOCTYPE sqlMap      
    PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"      
    "http://ibatis.apache.org/dtd/sql-map-2.dtd">

<sqlMap namespace="alfresco.audit">

    <!--                -->
    <!-- Type Defs      -->
    <!--                -->
    
    <typeAlias alias="AuditModel" type="org.alfresco.repo.domain.audit.AuditModelEntity"/>
    <typeAlias alias="AuditApplication" type="org.alfresco.repo.domain.audit.AuditApplicationEntity"/>
    <typeAlias alias="AuditEntry" type="org.alfresco.repo.domain.audit.AuditEntryEntity"/>
    <typeAlias alias="AuditDeleteParameters" type="org.alfresco.repo.domain.audit.AuditDeleteParameters"/>
    <typeAlias alias="AuditQueryParameters" type="org.alfresco.repo.domain.audit.AuditQueryParameters"/>
    <typeAlias alias="AuditQueryResult" type="org.alfresco.repo.domain.audit.AuditQueryResult"/>

    <!--                -->
    <!-- Result Maps    -->
    <!--                -->

    <resultMap id="result_AuditModel" class="AuditModel">
        <result property="id" column="id" jdbcType="BIGINT" javaType="java.lang.Long"/>
        <result property="contentDataId" column="content_data_id" jdbcType="BIGINT" javaType="java.lang.Long"/>
        <result property="contentCrc" column="content_crc" jdbcType="BIGINT" javaType="long"/>
    </resultMap>
    <resultMap id="result_AuditApplication" class="AuditApplication">
        <result property="id" column="id" jdbcType="BIGINT" javaType="java.lang.Long"/>
        <result property="version" column="version" jdbcType="TINYINT" javaType="java.lang.Short"/>
        <result property="applicationNameId" column="app_name_id" jdbcType="BIGINT" javaType="java.lang.Long"/>
        <result property="auditModelId" column="audit_model_id" jdbcType="BIGINT" javaType="java.lang.Long"/>
        <result property="disabledPathsId" column="disabled_paths_id" jdbcType="BIGINT" javaType="java.lang.Long"/>
    </resultMap>
    <resultMap id="result_AuditEntry" class="AuditEntry">
        <result property="id" column="id" jdbcType="BIGINT" javaType="java.lang.Long"/>
        <result property="auditApplicationId" column="audit_app_id" jdbcType="BIGINT" javaType="java.lang.Long"/>
        <result property="auditUserId" column="audit_user_id" jdbcType="BIGINT" javaType="java.lang.Long"/>
        <result property="auditTime" column="audit_time" jdbcType="BIGINT" javaType="long"/>
        <result property="auditValuesId" column="audit_values_id" jdbcType="BIGINT" javaType="long"/>
    </resultMap>
    <resultMap id="result_AuditQueryNoValues" class="AuditQueryResult">
        <result property="auditAppNameId" column="audit_app_name_id" jdbcType="BIGINT" javaType="long"/>
        <result property="auditEntryId" column="audit_entry_id" jdbcType="BIGINT" javaType="long"/>
        <result property="auditUserId" column="audit_user_id" jdbcType="BIGINT" javaType="long"/>
        <result property="auditTime" column="audit_time" jdbcType="BIGINT" javaType="long"/>
        <result property="auditValuesId" column="audit_values_id" jdbcType="BIGINT" javaType="long"/>
    </resultMap>
    <resultMap id="result_AuditQueryAllValues"
               extends="alfresco.audit.result_AuditQueryNoValues"
               class="AuditQueryResult">
        <result property="auditValueRows" resultMap="alfresco.propval.result_PropertyIdSearchRow"/>
    </resultMap>
  
    <!--                -->
    <!-- Parameter Maps -->
    <!--                -->

    <parameterMap id="parameter_IdMap" class="map">
        <parameter property="id" jdbcType="BIGINT" javaType="java.lang.Long"/>
    </parameterMap>
  
    <!--                -->
    <!-- SQL Snippets   -->
    <!--                -->
    
    <sql id="insert_AuditModel_AutoIncrement">
        insert into alf_audit_model (content_data_id, content_crc) 
        values (#contentDataId#, #contentCrc#)
    </sql>
    
    <sql id="insert_AuditApplication_AutoIncrement">
        insert into alf_audit_app (version, app_name_id, audit_model_id, disabled_paths_id) 
        values (#version#, #applicationNameId#, #auditModelId#, #disabledPathsId#)
    </sql>
    
    <sql id="insert_AuditEntry_AutoIncrement">
        insert into alf_audit_entry (audit_app_id, audit_user_id, audit_time, audit_values_id) 
        values (#auditApplicationId#, #auditUserId#, #auditTime#, #auditValuesId#)
    </sql>
    
    <!--                -->
    <!-- Statements     -->
    <!--                -->
    
    <!-- Get the audit model by the CRC value -->
    <select id="select_AuditModelByCrc" parameterClass="AuditModel" resultMap="result_AuditModel">
        select
            *
        from
            alf_audit_model
        where
            content_crc = #contentCrc#
    </select>

    <!-- Get the audit application by ID -->
    <select id="select_AuditApplicationById" parameterMap="parameter_IdMap" resultMap="result_AuditApplication">
        select
            *
        from
            alf_audit_app
        where
            id = ?
    </select>

    <!-- Get the audit application by name ID -->
    <select id="select_AuditApplicationByNameId" parameterMap="parameter_IdMap" resultMap="result_AuditApplication">
        select
            *
        from
            alf_audit_app
        where
            app_name_id = ?
    </select>

    <!-- Optimistic update of the audit application -->
    <update id="update_AuditApplication" parameterClass="AuditApplication">
        update
            alf_audit_app
        set
            version = #version#,
            app_name_id = #applicationNameId#,
            audit_model_id = #auditModelId#,
            disabled_paths_id = #disabledPathsId#
        where
            id = #id#
        <isGreaterThan property="version" compareValue="1">
            and version = ((#version#-1))
        </isGreaterThan>
    </update>
    
    <!-- TODO: This has to be replaced with two deletes; one for the property links and another for the entries -->
    <delete id="delete_AuditEntries" parameterClass="AuditDeleteParameters">
       delete
       from
           alf_audit_entry
       where
           audit_app_id = #auditApplicationId#
       <isNotNull property="auditFromTime">
           <![CDATA[and audit_time >= #auditFromTime#]]>
       </isNotNull>
       <isNotNull property="auditFromTime">
           <![CDATA[and audit_time < #auditToTime#]]>
       </isNotNull>
    </delete>
    
    <!-- Get audit entries -->
    <select id="select_AuditEntriesWithValues" parameterClass="AuditQueryParameters" resultMap="result_AuditQueryAllValues">
        select
            app.app_name_id             as audit_app_name_id,
            entry.id                    as audit_entry_id,
            entry.audit_user_id         as audit_user_id,
            entry.audit_time            as audit_time,
            entry.audit_values_id       as audit_values_id,

            pl.root_prop_id             as link_root_prop_id,
            pl.prop_index               as link_prop_index,
            pl.contained_in             as link_contained_in,
            pl.key_prop_id              as link_key_prop_id,
            pl.value_prop_id            as link_value_prop_id,
            pv.actual_type_id           as prop_actual_type_id,
            pv.persisted_type           as prop_persisted_type,
            pv.long_value               as prop_long_value,
            dv.double_value             as prop_double_value,
            sv.string_value             as prop_string_value,
            serv.serializable_value     as prop_serializable_value
        from
            alf_audit_app app
            join alf_audit_entry entry on (entry.audit_app_id = app.id)
            
        <isNotNull property="searchKeyId">
            join alf_prop_link sp_kpl on (sp_kpl.root_prop_id = entry.audit_values_id)
        </isNotNull>
        <isNotNull property="searchValueId">
            join alf_prop_link sp_mpl on (sp_mpl.root_prop_id = entry.audit_values_id)
        </isNotNull>
        
            join alf_prop_link pl on (pl.root_prop_id = entry.audit_values_id)
            join alf_prop_value pv on (pl.value_prop_id = pv.id)
            left join alf_prop_double_value dv on (dv.id = pv.long_value and pv.persisted_type = 2)
            left join alf_prop_string_value sv on (sv.id = pv.long_value and (pv.persisted_type = 3 OR pv.persisted_type = 5))
            left join alf_prop_serializable_value serv on (serv.id = pv.long_value and pv.persisted_type = 4)
        <dynamic prepend="where">
            <isNotNull prepend="and" property="auditAppNameId">
                app.app_name_id = #auditAppNameId#
            </isNotNull>
            <isNotNull prepend="and" property="auditUserId">
                entry.audit_user_id = #auditUserId#
            </isNotNull>
            <isNotNull prepend="and" property="auditFromId">
                <![CDATA[entry.id >= #auditFromId#]]>
            </isNotNull>
            <isNotNull prepend="and" property="auditToId">
                <![CDATA[entry.id < #auditToId#]]>
            </isNotNull>
            <isNotNull prepend="and" property="auditFromTime">
                <![CDATA[entry.audit_time >= #auditFromTime#]]>
            </isNotNull>
            <isNotNull prepend="and" property="auditToTime">
                <![CDATA[entry.audit_time < #auditToTime#]]>
            </isNotNull>
            <isNotNull prepend="and" property="searchKeyId">
                sp_kpl.key_prop_id = #searchKeyId#
            </isNotNull>
            <isNotNull prepend="and" property="searchValueId">
                sp_mpl.value_prop_id = #searchValueId#
            </isNotNull>
        </dynamic>
        <isEqual property="forward" compareProperty="forwardTrue">
        order by
            entry.id asc
        </isEqual>
        <isNotEqual property="forward" compareProperty="forwardTrue">
        order by
            entry.id desc
        </isNotEqual>
    </select>

    <!-- Get audit entries -->
    <select id="select_AuditEntriesWithoutValues" parameterClass="AuditQueryParameters" resultMap="result_AuditQueryNoValues">
        select
            app.app_name_id             as audit_app_name_id,
            entry.id                    as audit_entry_id,
            entry.audit_user_id         as audit_user_id,
            entry.audit_time            as audit_time,
            entry.audit_values_id       as audit_values_id
        from
            alf_audit_app app
            join alf_audit_entry entry on (entry.audit_app_id = app.id)
            
        <isNotNull property="searchKeyId">
            join alf_prop_link sp_kpl on (sp_kpl.root_prop_id = entry.audit_values_id)
        </isNotNull>
        <isNotNull property="searchValueId">
            join alf_prop_link sp_mpl on (sp_mpl.root_prop_id = entry.audit_values_id)
        </isNotNull>
        
        <dynamic prepend="where">
            <isNotNull prepend="and" property="auditAppNameId">
                app.app_name_id = #auditAppNameId#
            </isNotNull>
            <isNotNull prepend="and" property="auditUserId">
                entry.audit_user_id = #auditUserId#
            </isNotNull>
            <isNotNull prepend="and" property="auditFromId">
                <![CDATA[entry.id >= #auditFromId#]]>
            </isNotNull>
            <isNotNull prepend="and" property="auditToId">
                <![CDATA[entry.id < #auditToId#]]>
            </isNotNull>
            <isNotNull prepend="and" property="auditFromTime">
                <![CDATA[entry.audit_time >= #auditFromTime#]]>
            </isNotNull>
            <isNotNull prepend="and" property="auditToTime">
                <![CDATA[entry.audit_time < #auditToTime#]]>
            </isNotNull>
            <isNotNull prepend="and" property="searchKeyId">
                sp_kpl.key_prop_id = #searchKeyId#
            </isNotNull>
            <isNotNull prepend="and" property="searchValueId">
                sp_mpl.value_prop_id = #searchValueId#
            </isNotNull>
        </dynamic>
        <isEqual property="forward" compareProperty="forwardTrue">
        order by
            entry.id asc
        </isEqual>
        <isNotEqual property="forward" compareProperty="forwardTrue">
        order by
            entry.id desc
        </isNotEqual>
    </select>

</sqlMap>