/*
Copyright (c) 2025 WuJingrun(吴京润)
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.
*/
package f_orm
import std.collection.ArrayList
import f_orm.exception.ORMException
public class ChooseCondition {
private static let emptyPartial: () -> (String, Any) = {=> ('', '')}
private let conditions = ArrayList<(() -> Bool, () -> (String, Any))>()
private var _otherwise: () -> (String, Any) = emptyPartial
private var pair = true
private var _argInSql: Bool = false
public ChooseCondition(private let executor: SqlExecutor) {}
public prop argInSql: ChooseCondition {
get() {
_argInSql = true
this
}
}
public func condition(condition: () -> Bool): ChooseCondition {
if (pair) {
pair = false
conditions.add((condition, emptyPartial))
this
} else {
throw ORMException('condition and sql partial generation function arg not paring')
}
}
public func partial(partial: () -> (String, Any)): ChooseCondition {
if (pair) {
throw ORMException('condition and sql partial generation function arg not paring')
} else {
pair = true
let idx = conditions.size - 1
let (c, _) = conditions[idx]
conditions[idx] = (c, partial)
this
}
}
private func callee(partial: () -> Any): () -> (String, Any) {
{=> ('', partial())}
}
private func callee(partial: () -> String): () -> (String, Any){
{=> (partial(), ())}
}
public func partial(partial: () -> Any): ChooseCondition {
this.partial(callee(partial))
}
public func partial(partial: () -> String): ChooseCondition {
this.partial(callee(partial))
}
public func otherwise(partial: () -> (String, Any)): ChooseCondition {
_otherwise = partial
this
}
public func otherwise(partial: () -> String): ChooseCondition {
otherwise(callee(partial))
}
public func otherwise(partial: () -> Any): ChooseCondition {
otherwise(callee(partial))
}
public func done(): String {
if (!pair) {
throw ORMException('condition and sql partial generation function arg not paring')
}
func gen(partial: () -> (String, Any)) {
let (frag, arg) = partial()
if (frag.size > 0) {
if (_argInSql) {
match (arg) {
case _: Unit => ' ${frag} ${Condition.delimiter} '
case x: ToString => ' ${frag} ${x} ${Condition.delimiter} '
case x =>
executor.add(arg)
' ${frag} ? ${Condition.delimiter} '
}
} else {
executor.add(arg)
' ${frag} ? ${Condition.delimiter} '
}
} else if (_argInSql) {
match (arg) {
case x: ToString => ' ${x} ${Condition.delimiter} '
case x =>
executor.add(arg)
' ? ${Condition.delimiter} '
}
} else {
executor.add(arg)
' ? ${Condition.delimiter} '
}
}
func gen(){
for ((cond, partial) in conditions where cond()) {
return gen(partial)
}
gen(_otherwise)
}
let sql = gen()
executor.partials.append(sql)
sql
}
}