/* Copyright 2010 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import org.apache.commons.logging.LogFactory

/**
 * Unit tests for HqlBuilder class.
 * GroovyTestCase is used so that class does not depend on Grails as it may be useful outside of Grails.
 *
 * @author Gavin Kromhout
 * @version DraftA
 *
 */
public class HqlBuilderTests extends GroovyTestCase {

    def n = '\n'
    def savedMetaClass

    protected void setUp() {
        super.setUp()
        savedMetaClass = HqlBuilder.metaClass
        def emc = new ExpandoMetaClass(HqlBuilder, true, true)
        //emc.log = LogFactory.getLog(getClass())
        emc.initialize()
        GroovySystem.metaClassRegistry.setMetaClass(HqlBuilder, emc)
    }

    protected void tearDown() {
        GroovySystem.metaClassRegistry.removeMetaClass(HqlBuilder)
        GroovySystem.metaClassRegistry.setMetaClass(HqlBuilder, savedMetaClass)
        super.tearDown()
    }

    void testSelectBasic() {

        def q = new HqlBuilder().query {
            select 'count(distinct book)'
            from 'Book as book'
            where 'book.id > 100'
        }

        assert q.query == 'select count(distinct book) from Book as book where book.id > 100'

        q.select = 'distinct book'
        assert q.query == 'select distinct book from Book as book where book.id > 100'
        assert q.printFormattedQuery == 'select distinct book \nfrom Book as book \nwhere book.id > 100'

    } // testSelectBasic()

    void testSelectAdditional() {

        def q = new HqlBuilder().query {
            select 'distinct book'
            from 'Book as book'
            left 'join book.group as group',
                    'left join group.type as type'
            where 'book.id > 100',
                        'and group = :group'
        }

        assert q.query == 'select distinct book from Book as book left join book.group as group left join group.type as type where book.id > 100 and group = :group'

    } // testSelectAdditional()

    void testSelectAlternate() {

        def q = new HqlBuilder()

        q {
            select 'distinct book'
            from 'Book as book'
            where(/book.name like '%Ned%'/) // Slashy string literals have to be protected when calling a function.
            where 'and book.description like "Head"'
        }

        assert q.query == /select distinct book from Book as book where book.name like '%Ned%' and book.description like "Head"/
        assert q.printFormattedQuery == /select distinct book ${n}from Book as book ${n}where book.name like '%Ned%' ${n}and book.description like "Head"/

    } // testSelectAlternate()

    void testSelectWithPlaceHolder() {

        def q = new HqlBuilder().query {
            select 'distinct book'
            from 'Book as book'
            where '' // Place holder.
            order 'by book.name asc'
        }

        // Insert to place holder which is in the middle of query string.
        q.where = /book.name like '%Ned%'/  // Slashy string literals don't need protecting when assigning.

        assert q.query == /select distinct book from Book as book where book.name like '%Ned%' order by book.name asc/

    } // testSelectWithPlaceHolder()

    void testSelectWithClauseRemoval() {

        def q = new HqlBuilder().query {
            select 'count(distinct book)'
            from 'Book as book'
            where = /book.name like '%Ned%'/  // Slashy string literals don't need protecting when assigning.
            order 'by book.name asc'
        }

        q.order = null // Remove clause, since order by makes no sense when selecting a count ;-)
        assert q.query == /select count(distinct book) from Book as book where book.name like '%Ned%'/

    } // testSelectWithClauseRemoval()

} // end class