/*
 *  Licensed to the Apache Software Foundation (ASF) under one
 *  or more contributor license agreements.  See the NOTICE file
 *  distributed with this work for additional information
 *  regarding copyright ownership.  The ASF licenses this file
 *  to you 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
 *
 *    https://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.
 */
package gorm

import grails.gorm.transactions.Transactional

/**
 * Service for testing where queries with local variable names that
 * match domain property names inside @Transactional methods.
 *
 * This exercises the fix for https://github.com/apache/grails-core/issues/11464
 * where VariableScopeVisitor rewrites delegate method calls generated by
 * DetachedCriteriaTransformer when implicitThis is true and a local variable
 * with the same name exists in scope.
 */
@Transactional
class WhereQueryVariableScopeService {

    /**
     * Where query using a local variable named 'author' which matches
     * the Book.author association property.
     */
    List<Book> findBooksByAuthor(Author author) {
        Book.where {
            author == author
        }.list()
    }

    /**
     * Where query using a local variable named 'title' which matches
     * the Book.title property.
     */
    List<Book> findBooksByTitle(String title) {
        Book.where {
            title == title
        }.list()
    }

    /**
     * Where query using association property traversal where the
     * association variable name 'author' matches a local variable.
     */
    List<Book> findBooksByAuthorName(String name) {
        def author = Author.findByName(name)
        Book.where {
            author.name == name
        }.list()
    }

    /**
     * Where query with multiple variable name collisions.
     */
    List<Book> findBooksWithMultipleCollisions(String title, Boolean inStock) {
        Book.where {
            title == title && inStock == inStock
        }.list()
    }

    /**
     * Read-only transactional variant - verifies the fix also works with
     * @Transactional(readOnly = true) where VariableScopeVisitor is
     * similarly re-run by the transactional transform.
     */
    @Transactional(readOnly = true)
    List<Book> findBooksByTitleReadOnly(String title) {
        Book.where {
            title == title
        }.list()
    }
}